diff --git a/apps/applications/api/application.py b/apps/applications/api/application.py index 435ccccad..9d1b130ce 100644 --- a/apps/applications/api/application.py +++ b/apps/applications/api/application.py @@ -17,7 +17,7 @@ class ApplicationViewSet(SuggestionMixin, OrgBulkModelViewSet): model = Application filterset_fields = { 'name': ['exact'], - 'category': ['exact'], + 'category': ['exact', 'in'], 'type': ['exact', 'in'], } search_fields = ('name', 'type', 'category') diff --git a/apps/assets/api/accounts.py b/apps/assets/api/accounts.py index b4e75122b..9989599b8 100644 --- a/apps/assets/api/accounts.py +++ b/apps/assets/api/accounts.py @@ -65,7 +65,7 @@ class AccountViewSet(OrgBulkModelViewSet): } rbac_perms = { 'verify_account': 'assets.test_authbook', - 'PATCH': 'assets.change_assetaccountsecret' + 'partial_update': 'assets.change_assetaccountsecret', } def get_queryset(self): diff --git a/apps/assets/api/domain.py b/apps/assets/api/domain.py index b022f4dec..1e500c29a 100644 --- a/apps/assets/api/domain.py +++ b/apps/assets/api/domain.py @@ -40,7 +40,7 @@ class GatewayTestConnectionApi(SingleObjectMixin, APIView): queryset = Gateway.objects.all() object = None rbac_perms = { - 'POST': 'assets.change_gateway' + 'POST': 'assets.test_gateway' } def post(self, request, *args, **kwargs): diff --git a/apps/assets/migrations/0089_auto_20220310_0616.py b/apps/assets/migrations/0089_auto_20220310_0616.py index 342c3d887..1aa70d616 100644 --- a/apps/assets/migrations/0089_auto_20220310_0616.py +++ b/apps/assets/migrations/0089_auto_20220310_0616.py @@ -16,7 +16,7 @@ class Migration(migrations.Migration): ), migrations.AlterModelOptions( name='systemuser', - options={'ordering': ['name'], 'permissions': [('view_systemuserasset', 'Can view system user asset'), ('add_systemuserasset', 'Can add asset to system user'), ('remove_systemuserasset', 'Can remove system user asset'), ('match_systemuser', 'Can match system user')], 'verbose_name': 'System user'}, + options={'ordering': ['name'], 'permissions': [('match_systemuser', 'Can match system user')], 'verbose_name': 'System user'}, ), migrations.AlterModelOptions( name='asset', diff --git a/apps/assets/models/user.py b/apps/assets/models/user.py index 6ae0fa825..678e5f8cf 100644 --- a/apps/assets/models/user.py +++ b/apps/assets/models/user.py @@ -324,9 +324,6 @@ class SystemUser(ProtocolMixin, AuthMixin, BaseUser): unique_together = [('name', 'org_id')] verbose_name = _("System user") permissions = [ - ('view_systemuserasset', _('Can view system user asset')), - ('add_systemuserasset', _('Can add asset to system user')), - ('remove_systemuserasset', _('Can remove system user asset')), ('match_systemuser', _('Can match system user')), ] diff --git a/apps/assets/serializers/cmd_filter.py b/apps/assets/serializers/cmd_filter.py index 1d798d7eb..a57fab72a 100644 --- a/apps/assets/serializers/cmd_filter.py +++ b/apps/assets/serializers/cmd_filter.py @@ -12,13 +12,11 @@ from terminal.models import Session class CommandFilterSerializer(BulkOrgResourceModelSerializer): - class Meta: model = CommandFilter fields_mini = ['id', 'name'] fields_small = fields_mini + [ - 'org_id', 'org_name', - 'is_active', + 'org_id', 'org_name', 'is_active', 'date_created', 'date_updated', 'comment', 'created_by', ] @@ -26,7 +24,9 @@ class CommandFilterSerializer(BulkOrgResourceModelSerializer): fields_m2m = ['users', 'user_groups', 'system_users', 'assets', 'applications'] fields = fields_small + fields_fk + fields_m2m extra_kwargs = { - 'rules': {'read_only': True} + 'rules': {'read_only': True}, + 'date_created': {'label': _("Date created")}, + 'date_updated': {'label': _("Date updated")}, } @@ -45,6 +45,11 @@ class CommandFilterRuleSerializer(BulkOrgResourceModelSerializer): ] fields_fk = ['filter'] fields = fields_small + fields_fk + extra_kwargs = { + 'date_created': {'label': _("Date created")}, + 'date_updated': {'label': _("Date updated")}, + 'action_display': {'label': _("Action display")} + } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/apps/audits/api.py b/apps/audits/api.py index 8b30451a6..fb1efe989 100644 --- a/apps/audits/api.py +++ b/apps/audits/api.py @@ -132,7 +132,8 @@ class CommandExecutionHostRelationViewSet(OrgRelationMixin, OrgBulkModelViewSet) search_fields = ('asset__hostname', ) http_method_names = ['options', 'get'] rbac_perms = { - 'GET': 'ops.view_commandexecution' + 'GET': 'ops.view_commandexecution', + 'list': 'ops.view_commandexecution', } def get_queryset(self): diff --git a/apps/authentication/signal_handlers.py b/apps/authentication/signal_handlers.py index 5c5aa1abd..0d2a617f9 100644 --- a/apps/authentication/signal_handlers.py +++ b/apps/authentication/signal_handlers.py @@ -18,7 +18,7 @@ from .signals import post_auth_success, post_auth_failed @receiver(user_logged_in) def on_user_auth_login_success(sender, user, request, **kwargs): # 失效 perms 缓存 - user.expire_perms_cache() + user.expire_rbac_perms_cache() # 开启了 MFA,且没有校验过, 可以全局校验, middleware 中可以全局管理 oidc 等第三方认证的 MFA if settings.SECURITY_MFA_AUTH_ENABLED_FOR_THIRD_PARTY \ diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 29f57f55b..a3e26b6ec 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f529bbca004aeba7532d9faf50f6f8ab5532b19bf0afd650f8360f418c03c15c -size 104629 +oid sha256:43b38f824f3e62af12575cc853ec0ad7f9b0ac935e1d99116ebe3ddb6c93485c +size 104599 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 7922f9a31..6d166475b 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-03-16 20:38+0800\n" +"POT-Creation-Date: 2022-03-17 15:19+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -30,7 +30,7 @@ msgstr "访问控制" #: settings/models.py:29 settings/serializers/sms.py:6 #: terminal/models/storage.py:23 terminal/models/task.py:16 #: terminal/models/terminal.py:100 users/forms/profile.py:32 -#: users/models/group.py:15 users/models/user.py:574 +#: users/models/group.py:15 users/models/user.py:584 #: users/templates/users/_select_user_modal.html:13 #: users/templates/users/user_asset_permission.html:37 #: users/templates/users/user_asset_permission.html:154 @@ -66,7 +66,7 @@ msgstr "激活中" #: perms/models/base.py:93 rbac/models/role.py:37 settings/models.py:34 #: terminal/models/storage.py:26 terminal/models/terminal.py:114 #: tickets/models/comment.py:24 tickets/models/ticket.py:154 -#: users/models/group.py:16 users/models/user.py:611 +#: users/models/group.py:16 users/models/user.py:621 #: xpack/plugins/change_auth_plan/models/base.py:44 #: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:116 #: xpack/plugins/gathered_user/models.py:26 @@ -90,12 +90,12 @@ msgstr "登录复核" #: assets/models/cmd_filter.py:30 assets/models/label.py:15 audits/models.py:37 #: audits/models.py:60 audits/models.py:85 audits/serializers.py:100 #: authentication/models.py:50 orgs/models.py:214 perms/models/base.py:84 -#: rbac/builtin.py:97 rbac/models/rolebinding.py:39 templates/index.html:78 +#: rbac/builtin.py:101 rbac/models/rolebinding.py:39 templates/index.html:78 #: terminal/backends/command/models.py:19 #: terminal/backends/command/serializers.py:12 terminal/models/session.py:42 -#: terminal/notifications.py:88 terminal/notifications.py:136 -#: tickets/models/comment.py:17 users/const.py:14 users/models/user.py:795 -#: users/models/user.py:826 users/serializers/group.py:19 +#: terminal/notifications.py:91 terminal/notifications.py:139 +#: tickets/models/comment.py:17 users/const.py:14 users/models/user.py:809 +#: users/models/user.py:840 users/serializers/group.py:19 #: users/templates/users/user_asset_permission.html:38 #: users/templates/users/user_asset_permission.html:64 #: users/templates/users/user_database_app_permission.html:37 @@ -141,7 +141,7 @@ msgstr "系统用户" #: audits/models.py:39 perms/models/asset_permission.py:23 #: templates/index.html:82 terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 -#: terminal/notifications.py:87 +#: terminal/notifications.py:90 #: users/templates/users/user_asset_permission.html:40 #: users/templates/users/user_asset_permission.html:70 #: xpack/plugins/change_auth_plan/models/asset.py:199 @@ -168,7 +168,7 @@ msgstr "格式为逗号分隔的字符串, * 表示匹配所有. " #: authentication/forms.py:15 authentication/forms.py:17 #: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9 -#: ops/models/adhoc.py:159 users/forms/profile.py:31 users/models/user.py:572 +#: ops/models/adhoc.py:159 users/forms/profile.py:31 users/models/user.py:582 #: users/templates/users/_msg_user_created.html:12 #: users/templates/users/_select_user_modal.html:14 #: xpack/plugins/change_auth_plan/models/asset.py:34 @@ -341,6 +341,7 @@ msgid "Domain" msgstr "网域" #: applications/models/application.py:220 xpack/plugins/cloud/models.py:33 +#: xpack/plugins/cloud/serializers/account.py:57 msgid "Attrs" msgstr "属性" @@ -373,16 +374,18 @@ msgstr "类型名称" #: assets/models/base.py:181 assets/models/cluster.py:26 #: assets/models/domain.py:26 assets/models/gathered_user.py:19 #: assets/models/group.py:22 assets/models/label.py:25 -#: assets/serializers/account.py:18 common/db/models.py:113 +#: assets/serializers/account.py:18 assets/serializers/cmd_filter.py:28 +#: assets/serializers/cmd_filter.py:49 common/db/models.py:113 #: common/mixins/models.py:50 ops/models/adhoc.py:39 ops/models/command.py:30 #: orgs/models.py:67 orgs/models.py:217 perms/models/base.py:92 -#: users/models/group.py:18 users/models/user.py:827 +#: users/models/group.py:18 users/models/user.py:841 #: xpack/plugins/cloud/models.py:125 msgid "Date created" msgstr "创建日期" #: applications/serializers/application.py:104 assets/models/base.py:182 #: assets/models/gathered_user.py:20 assets/serializers/account.py:21 +#: assets/serializers/cmd_filter.py:29 assets/serializers/cmd_filter.py:50 #: common/db/models.py:114 common/mixins/models.py:51 ops/models/adhoc.py:40 #: orgs/models.py:218 msgid "Date updated" @@ -607,7 +610,7 @@ msgid "Is active" msgstr "激活" #: assets/models/asset.py:222 assets/models/cluster.py:19 -#: assets/models/user.py:222 assets/models/user.py:380 +#: assets/models/user.py:222 assets/models/user.py:377 msgid "Admin user" msgstr "特权用户" @@ -627,7 +630,7 @@ msgstr "标签管理" #: assets/models/cluster.py:28 assets/models/cmd_filter.py:52 #: assets/models/cmd_filter.py:99 assets/models/group.py:21 #: common/db/models.py:111 common/mixins/models.py:49 orgs/models.py:66 -#: orgs/models.py:219 perms/models/base.py:91 users/models/user.py:619 +#: orgs/models.py:219 perms/models/base.py:91 users/models/user.py:629 #: users/serializers/group.py:33 #: xpack/plugins/change_auth_plan/models/base.py:48 #: xpack/plugins/cloud/models.py:122 xpack/plugins/gathered_user/models.py:30 @@ -808,7 +811,7 @@ msgstr "带宽" msgid "Contact" msgstr "联系人" -#: assets/models/cluster.py:22 users/models/user.py:594 +#: assets/models/cluster.py:22 users/models/user.py:604 msgid "Phone" msgstr "手机" @@ -834,7 +837,7 @@ msgid "Default" msgstr "默认" #: assets/models/cluster.py:36 assets/models/label.py:14 rbac/const.py:6 -#: users/models/user.py:812 +#: users/models/user.py:826 msgid "System" msgstr "系统" @@ -843,7 +846,7 @@ msgid "Default Cluster" msgstr "默认Cluster" #: assets/models/cmd_filter.py:34 perms/models/base.py:86 -#: users/models/group.py:31 users/models/user.py:580 +#: users/models/group.py:31 users/models/user.py:590 #: users/templates/users/_select_user_modal.html:16 #: users/templates/users/user_asset_permission.html:39 #: users/templates/users/user_asset_permission.html:67 @@ -1060,18 +1063,6 @@ msgid "Switch from" msgstr "切换自" #: assets/models/user.py:327 -msgid "Can view system user asset" -msgstr "可以查看系统用户资产列表" - -#: assets/models/user.py:328 -msgid "Can add asset to system user" -msgstr "可以添加资产到系统用户" - -#: assets/models/user.py:329 -msgid "Can remove system user asset" -msgstr "可以移除系统用户资产" - -#: assets/models/user.py:330 msgid "Can match system user" msgstr "可以匹配系统用户" @@ -1162,6 +1153,12 @@ msgstr "密钥密码" msgid "private key invalid or passphrase error" msgstr "密钥不合法或密钥密码错误" +#: assets/serializers/cmd_filter.py:51 +#, fuzzy +#| msgid "Application display" +msgid "Action display" +msgstr "应用名称" + #: assets/serializers/domain.py:13 assets/serializers/label.py:12 #: assets/serializers/system_user.py:59 #: perms/serializers/asset/permission.py:49 @@ -1384,7 +1381,7 @@ msgstr "日志审计" #: audits/models.py:27 audits/models.py:57 #: authentication/templates/authentication/_access_key_modal.html:65 -#: rbac/tree.py:162 users/templates/users/user_asset_permission.html:128 +#: rbac/tree.py:167 users/templates/users/user_asset_permission.html:128 #: users/templates/users/user_database_app_permission.html:111 msgid "Delete" msgstr "删除" @@ -1438,11 +1435,11 @@ msgstr "文件管理" #: audits/models.py:55 #: authentication/templates/authentication/_access_key_modal.html:22 -#: rbac/tree.py:159 +#: rbac/tree.py:164 msgid "Create" msgstr "创建" -#: audits/models.py:56 rbac/tree.py:161 templates/_csv_import_export.html:18 +#: audits/models.py:56 rbac/tree.py:166 templates/_csv_import_export.html:18 #: templates/_csv_update_modal.html:6 #: users/templates/users/user_asset_permission.html:127 #: users/templates/users/user_database_app_permission.html:110 @@ -1506,7 +1503,7 @@ msgstr "用户代理" #: audits/models.py:124 #: authentication/templates/authentication/_mfa_confirm_modal.html:14 -#: users/forms/profile.py:64 users/models/user.py:597 +#: users/forms/profile.py:64 users/models/user.py:607 #: users/serializers/profile.py:121 msgid "MFA" msgstr "MFA" @@ -1584,13 +1581,13 @@ msgstr "认证令牌" #: audits/signal_handlers.py:71 authentication/notifications.py:73 #: authentication/views/login.py:164 authentication/views/wecom.py:158 -#: notifications/backends/__init__.py:11 users/models/user.py:633 +#: notifications/backends/__init__.py:11 users/models/user.py:643 msgid "WeCom" msgstr "企业微信" #: audits/signal_handlers.py:72 authentication/views/dingtalk.py:160 #: authentication/views/login.py:170 notifications/backends/__init__.py:12 -#: users/models/user.py:634 +#: users/models/user.py:644 msgid "DingTalk" msgstr "钉钉" @@ -2111,7 +2108,7 @@ msgid "Secret" msgstr "密钥" #: authentication/templates/authentication/_access_key_modal.html:33 -#: terminal/notifications.py:90 terminal/notifications.py:138 +#: terminal/notifications.py:93 terminal/notifications.py:141 msgid "Date" msgstr "日期" @@ -2121,14 +2118,14 @@ msgid "Show" msgstr "显示" #: authentication/templates/authentication/_access_key_modal.html:66 -#: settings/serializers/security.py:39 users/models/user.py:469 +#: settings/serializers/security.py:39 users/models/user.py:479 #: users/serializers/profile.py:111 users/templates/users/mfa_setting.html:61 #: users/templates/users/user_verify_mfa.html:36 msgid "Disable" msgstr "禁用" #: authentication/templates/authentication/_access_key_modal.html:67 -#: users/models/user.py:470 users/serializers/profile.py:112 +#: users/models/user.py:480 users/serializers/profile.py:112 #: users/templates/users/mfa_setting.html:26 #: users/templates/users/mfa_setting.html:68 msgid "Enable" @@ -2377,7 +2374,7 @@ msgid "The FeiShu is already bound to another user" msgstr "该飞书已经绑定其他用户" #: authentication/views/feishu.py:148 authentication/views/login.py:176 -#: notifications/backends/__init__.py:14 users/models/user.py:635 +#: notifications/backends/__init__.py:14 users/models/user.py:645 msgid "FeiShu" msgstr "飞书" @@ -2672,7 +2669,7 @@ msgid "Notifications" msgstr "通知" #: notifications/backends/__init__.py:10 users/forms/profile.py:101 -#: users/models/user.py:576 +#: users/models/user.py:586 msgid "Email" msgstr "邮件" @@ -2879,7 +2876,7 @@ msgstr "当前组织 ({}) 不能被删除" msgid "The organization have resource ({}) cannot be deleted" msgstr "组织存在资源 ({}) 不能被删除" -#: orgs/apps.py:7 rbac/tree.py:110 +#: orgs/apps.py:7 rbac/tree.py:113 msgid "App organizations" msgstr "组织管理" @@ -2898,7 +2895,7 @@ msgid "Can view root org" msgstr "可以查看全局组织" #: orgs/models.py:216 rbac/models/role.py:46 rbac/models/rolebinding.py:42 -#: users/models/user.py:584 users/templates/users/_select_user_modal.html:15 +#: users/models/user.py:594 users/templates/users/_select_user_modal.html:15 msgid "Role" msgstr "角色" @@ -2997,7 +2994,7 @@ msgstr "剪贴板复制粘贴" #: perms/models/base.py:90 #: tickets/serializers/ticket/meta/ticket_type/apply_application.py:58 #: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:60 -#: users/models/user.py:616 +#: users/models/user.py:626 msgid "Date expired" msgstr "失效日期" @@ -3040,15 +3037,15 @@ msgstr "组织 ({}) 的应用授权" #: perms/serializers/application/permission.py:20 #: perms/serializers/application/permission.py:41 #: perms/serializers/asset/permission.py:19 -#: perms/serializers/asset/permission.py:45 users/serializers/user.py:139 +#: perms/serializers/asset/permission.py:45 users/serializers/user.py:137 msgid "Is valid" msgstr "账号是否有效" #: perms/serializers/application/permission.py:21 #: perms/serializers/application/permission.py:40 #: perms/serializers/asset/permission.py:20 -#: perms/serializers/asset/permission.py:44 users/serializers/user.py:85 -#: users/serializers/user.py:141 +#: perms/serializers/asset/permission.py:44 users/serializers/user.py:83 +#: users/serializers/user.py:139 msgid "Is expired" msgstr "已过期" @@ -3130,27 +3127,27 @@ msgstr "{} 至少有一个系统角色" msgid "RBAC" msgstr "RBAC" -#: rbac/builtin.py:89 +#: rbac/builtin.py:92 msgid "SystemAdmin" msgstr "系统管理员" -#: rbac/builtin.py:92 +#: rbac/builtin.py:95 msgid "SystemAuditor" msgstr "系统审计员" -#: rbac/builtin.py:95 +#: rbac/builtin.py:98 msgid "SystemComponent" msgstr "系统组件" -#: rbac/builtin.py:101 +#: rbac/builtin.py:104 msgid "OrgAdmin" msgstr "组织管理员" -#: rbac/builtin.py:104 +#: rbac/builtin.py:107 msgid "OrgAuditor" msgstr "组织审计员" -#: rbac/builtin.py:107 +#: rbac/builtin.py:110 msgid "OrgUser" msgstr "组织用户" @@ -3220,7 +3217,7 @@ msgstr "组织角色绑定" msgid "System role binding" msgstr "系统角色绑定" -#: rbac/serializers/permission.py:26 users/serializers/profile.py:125 +#: rbac/serializers/permission.py:26 users/serializers/profile.py:126 msgid "Perms" msgstr "权限" @@ -3240,91 +3237,91 @@ msgstr "角色显示" msgid "Has bound this role" msgstr "已经绑定" -#: rbac/tree.py:16 rbac/tree.py:17 +#: rbac/tree.py:19 rbac/tree.py:20 msgid "All permissions" msgstr "所有权限" -#: rbac/tree.py:23 +#: rbac/tree.py:26 msgid "Console view" msgstr "控制台" -#: rbac/tree.py:24 +#: rbac/tree.py:27 msgid "Workspace view" msgstr "工作台" -#: rbac/tree.py:25 +#: rbac/tree.py:28 msgid "Audit view" msgstr "审计台" -#: rbac/tree.py:26 settings/models.py:140 +#: rbac/tree.py:29 settings/models.py:140 msgid "System setting" msgstr "系统设置" -#: rbac/tree.py:27 +#: rbac/tree.py:30 msgid "Other" msgstr "其它" -#: rbac/tree.py:35 +#: rbac/tree.py:38 msgid "Accounts" msgstr "账号管理" -#: rbac/tree.py:39 +#: rbac/tree.py:42 msgid "Session audits" msgstr "会话审计" -#: rbac/tree.py:49 +#: rbac/tree.py:52 msgid "Cloud import" msgstr "云同步" -#: rbac/tree.py:50 +#: rbac/tree.py:53 msgid "Backup account" msgstr "备份账号" -#: rbac/tree.py:51 +#: rbac/tree.py:54 msgid "Gather account" msgstr "收集账号" -#: rbac/tree.py:52 +#: rbac/tree.py:55 msgid "App change auth" msgstr "应用改密" -#: rbac/tree.py:53 +#: rbac/tree.py:56 msgid "Asset change auth" msgstr "资产改密" -#: rbac/tree.py:54 +#: rbac/tree.py:57 msgid "Terminal setting" msgstr "终端设置" -#: rbac/tree.py:55 +#: rbac/tree.py:58 msgid "My assets" msgstr "我的资产" -#: rbac/tree.py:56 +#: rbac/tree.py:59 msgid "My apps" msgstr "我的应用" -#: rbac/tree.py:111 +#: rbac/tree.py:114 msgid "Ticket comment" msgstr "工单评论" -#: rbac/tree.py:112 tickets/models/ticket.py:163 +#: rbac/tree.py:115 tickets/models/ticket.py:163 msgid "Ticket" msgstr "工单管理" -#: rbac/tree.py:113 +#: rbac/tree.py:116 msgid "Common setting" msgstr "一般设置" -#: rbac/tree.py:115 +#: rbac/tree.py:117 msgid "View permission tree" msgstr "查看授权树" -#: rbac/tree.py:116 +#: rbac/tree.py:118 msgid "Execute batch command" msgstr "执行批量命令" -#: rbac/tree.py:160 +#: rbac/tree.py:165 msgid "View" msgstr "查看" @@ -4991,11 +4988,11 @@ msgstr "会话管理" msgid "Danger command alert" msgstr "危险命令告警" -#: terminal/notifications.py:89 terminal/notifications.py:137 +#: terminal/notifications.py:92 terminal/notifications.py:140 msgid "Level" msgstr "级别" -#: terminal/notifications.py:107 +#: terminal/notifications.py:110 msgid "Batch danger command alert" msgstr "批量危险命令告警" @@ -5039,7 +5036,7 @@ msgstr "端点无效: 移除路径 `{}`" msgid "Bucket" msgstr "桶名称" -#: terminal/serializers/storage.py:34 users/models/user.py:608 +#: terminal/serializers/storage.py:34 users/models/user.py:618 msgid "Secret key" msgstr "密钥" @@ -5384,19 +5381,19 @@ msgstr "请再次尝试" msgid "Super ticket" msgstr "超级工单" -#: tickets/notifications.py:57 +#: tickets/notifications.py:63 msgid "Your has a new ticket, applicant - {}" msgstr "你有一个新的工单, 申请人 - {}" -#: tickets/notifications.py:63 +#: tickets/notifications.py:69 msgid "New Ticket - {} ({})" msgstr "新工单 - {} ({})" -#: tickets/notifications.py:85 +#: tickets/notifications.py:91 msgid "Your ticket has been processed, processor - {}" msgstr "你的工单已被处理, 处理人 - {}" -#: tickets/notifications.py:89 +#: tickets/notifications.py:95 msgid "Ticket has processed - {} ({})" msgstr "你的工单已被处理, 处理人 - {} ({})" @@ -5535,7 +5532,7 @@ msgstr "当前组织已存在该类型" msgid "Click here to review" msgstr "点击查看" -#: users/api/user.py:175 +#: users/api/user.py:180 msgid "Could not reset self otp, use profile reset instead" msgstr "不能在该页面重置 MFA 多因子认证, 请去个人信息页面重置" @@ -5638,72 +5635,72 @@ msgid "Public key should not be the same as your old one." msgstr "不能和原来的密钥相同" #: users/forms/profile.py:149 users/serializers/profile.py:95 -#: users/serializers/profile.py:175 users/serializers/profile.py:202 +#: users/serializers/profile.py:176 users/serializers/profile.py:203 msgid "Not a valid ssh public key" msgstr "SSH密钥不合法" -#: users/forms/profile.py:160 users/models/user.py:605 +#: users/forms/profile.py:160 users/models/user.py:615 #: users/templates/users/user_password_update.html:48 msgid "Public key" msgstr "SSH公钥" -#: users/models/user.py:471 +#: users/models/user.py:481 msgid "Force enable" msgstr "强制启用" -#: users/models/user.py:538 +#: users/models/user.py:548 msgid "Local" msgstr "数据库" -#: users/models/user.py:586 users/serializers/user.py:140 +#: users/models/user.py:596 users/serializers/user.py:138 msgid "Is service account" msgstr "服务账号" -#: users/models/user.py:588 +#: users/models/user.py:598 msgid "Avatar" msgstr "头像" -#: users/models/user.py:591 +#: users/models/user.py:601 msgid "Wechat" msgstr "微信" -#: users/models/user.py:602 +#: users/models/user.py:612 msgid "Private key" msgstr "ssh私钥" -#: users/models/user.py:624 +#: users/models/user.py:634 msgid "Source" msgstr "来源" -#: users/models/user.py:628 +#: users/models/user.py:638 msgid "Date password last updated" msgstr "最后更新密码日期" -#: users/models/user.py:631 +#: users/models/user.py:641 msgid "Need update password" msgstr "需要更新密码" -#: users/models/user.py:797 +#: users/models/user.py:811 msgid "Can invite user" msgstr "可以邀请用户" -#: users/models/user.py:798 +#: users/models/user.py:812 msgid "Can remove user" msgstr "可以移除用户" -#: users/models/user.py:799 +#: users/models/user.py:813 msgid "Can match user" msgstr "可以匹配用户" -#: users/models/user.py:808 +#: users/models/user.py:822 msgid "Administrator" msgstr "管理员" -#: users/models/user.py:811 +#: users/models/user.py:825 msgid "Administrator is the super user of system" msgstr "Administrator是初始的超级管理员" -#: users/models/user.py:836 +#: users/models/user.py:850 msgid "User password history" msgstr "用户密码历史" @@ -5742,7 +5739,7 @@ msgstr "重置 MFA" msgid "The old password is incorrect" msgstr "旧密码错误" -#: users/serializers/profile.py:36 users/serializers/profile.py:189 +#: users/serializers/profile.py:36 users/serializers/profile.py:190 msgid "Password does not match security rules" msgstr "密码不满足安全规则" @@ -5754,97 +5751,97 @@ msgstr "新密码不能是最近 {} 次的密码" msgid "The newly set password is inconsistent" msgstr "两次密码不一致" -#: users/serializers/profile.py:141 users/serializers/user.py:138 +#: users/serializers/profile.py:142 users/serializers/user.py:136 msgid "Is first login" msgstr "首次登录" -#: users/serializers/user.py:26 users/serializers/user.py:33 +#: users/serializers/user.py:24 users/serializers/user.py:31 msgid "System roles" msgstr "系统角色" -#: users/serializers/user.py:31 users/serializers/user.py:34 +#: users/serializers/user.py:29 users/serializers/user.py:32 msgid "Org roles" msgstr "组织角色" -#: users/serializers/user.py:77 +#: users/serializers/user.py:75 #: xpack/plugins/change_auth_plan/models/base.py:35 #: xpack/plugins/change_auth_plan/serializers/base.py:22 msgid "Password strategy" msgstr "密码策略" -#: users/serializers/user.py:79 +#: users/serializers/user.py:77 msgid "MFA enabled" msgstr "MFA" -#: users/serializers/user.py:80 +#: users/serializers/user.py:78 msgid "MFA force enabled" msgstr "强制 MFA" -#: users/serializers/user.py:82 +#: users/serializers/user.py:80 msgid "MFA level display" msgstr "MFA 等级名称" -#: users/serializers/user.py:84 +#: users/serializers/user.py:82 msgid "Login blocked" msgstr "登录被阻塞" -#: users/serializers/user.py:87 +#: users/serializers/user.py:85 msgid "Can public key authentication" msgstr "能否公钥认证" -#: users/serializers/user.py:142 +#: users/serializers/user.py:140 msgid "Avatar url" msgstr "头像路径" -#: users/serializers/user.py:144 +#: users/serializers/user.py:142 msgid "Groups name" msgstr "用户组名" -#: users/serializers/user.py:145 +#: users/serializers/user.py:143 msgid "Source name" msgstr "用户来源名" -#: users/serializers/user.py:146 +#: users/serializers/user.py:144 msgid "Organization role name" msgstr "组织角色名称" -#: users/serializers/user.py:147 +#: users/serializers/user.py:145 msgid "Super role name" msgstr "超级角色名称" -#: users/serializers/user.py:148 +#: users/serializers/user.py:146 msgid "Total role name" msgstr "汇总角色名称" -#: users/serializers/user.py:150 +#: users/serializers/user.py:148 msgid "Is wecom bound" msgstr "是否绑定了企业微信" -#: users/serializers/user.py:151 +#: users/serializers/user.py:149 msgid "Is dingtalk bound" msgstr "是否绑定了钉钉" -#: users/serializers/user.py:152 +#: users/serializers/user.py:150 msgid "Is feishu bound" msgstr "是否绑定了飞书" -#: users/serializers/user.py:153 +#: users/serializers/user.py:151 msgid "Is OTP bound" msgstr "是否绑定了虚拟 MFA" -#: users/serializers/user.py:155 +#: users/serializers/user.py:153 msgid "System role name" msgstr "系统角色名称" -#: users/serializers/user.py:247 +#: users/serializers/user.py:245 msgid "Select users" msgstr "选择用户" -#: users/serializers/user.py:248 +#: users/serializers/user.py:246 msgid "For security, only list several users" msgstr "为了安全,仅列出几个用户" -#: users/serializers/user.py:281 +#: users/serializers/user.py:279 msgid "name not unique" msgstr "名称重复" @@ -6685,6 +6682,14 @@ msgstr "华北-乌兰察布一" msgid "CN South-Guangzhou-InvitationOnly" msgstr "华南-广州-友好用户环境" +#: xpack/plugins/cloud/serializers/account.py:58 +msgid "Validity display" +msgstr "有效显示" + +#: xpack/plugins/cloud/serializers/account.py:59 +msgid "Provider display" +msgstr "服务商名称" + #: xpack/plugins/cloud/serializers/account_attrs.py:13 msgid "AccessKey ID" msgstr "" @@ -6844,6 +6849,25 @@ msgstr "旗舰版" msgid "Community edition" msgstr "社区版" +#, fuzzy +#~| msgid "Date created" +#~ msgid "date created" +#~ msgstr "创建日期" + +#, fuzzy +#~| msgid "Date updated" +#~ msgid "date updated" +#~ msgstr "更新日期" + +#~ msgid "Can view system user asset" +#~ msgstr "可以查看系统用户资产列表" + +#~ msgid "Can add asset to system user" +#~ msgstr "可以添加资产到系统用户" + +#~ msgid "Can remove system user asset" +#~ msgstr "可以移除系统用户资产" + #, fuzzy #~| msgid "Create" #~ msgid "create" diff --git a/apps/ops/models/command.py b/apps/ops/models/command.py index 66bd8ed28..b5a1f2292 100644 --- a/apps/ops/models/command.py +++ b/apps/ops/models/command.py @@ -55,6 +55,10 @@ class CommandExecution(OrgModelMixin): def user_display(self): return str(self.user) + @lazyproperty + def hosts_display(self): + return ','.join(self.hosts.all().values_list('hostname', flat=True)) + @property def result(self): if self._result: diff --git a/apps/ops/serializers/adhoc.py b/apps/ops/serializers/adhoc.py index 80619c34a..094abf958 100644 --- a/apps/ops/serializers/adhoc.py +++ b/apps/ops/serializers/adhoc.py @@ -136,8 +136,7 @@ class CommandExecutionSerializer(serializers.ModelSerializer): fields_mini = ['id'] fields_small = fields_mini + [ 'command', 'result', 'log_url', - 'is_finished', - 'date_created', 'date_finished' + 'is_finished', 'date_created', 'date_finished' ] fields_fk = ['run_as'] fields_m2m = ['hosts'] diff --git a/apps/perms/migrations/0027_auto_20220310_1802.py b/apps/perms/migrations/0027_auto_20220310_1802.py index 542785345..48d9ffceb 100644 --- a/apps/perms/migrations/0027_auto_20220310_1802.py +++ b/apps/perms/migrations/0027_auto_20220310_1802.py @@ -27,10 +27,10 @@ class Migration(migrations.Migration): ), migrations.AlterModelOptions( name='applicationpermission', - options={'ordering': ('name',), 'permissions': [('view_permuserapplication', 'Can view application of permission to user')], 'verbose_name': 'Application permission'}, + options={'ordering': ('name',), 'permissions': [], 'verbose_name': 'Application permission'}, ), migrations.AlterModelOptions( name='assetpermission', - options={'ordering': ('name',), 'permissions': [('view_permuserasset', 'Can view asset of permission to user'), ('view_permusergroupasset', 'Can view asset of permission to user group')], 'verbose_name': 'Asset permission'}, + options={'ordering': ('name',), 'permissions': [], 'verbose_name': 'Asset permission'}, ), ] diff --git a/apps/perms/models/application_permission.py b/apps/perms/models/application_permission.py index 7cefec448..6bea6e47f 100644 --- a/apps/perms/models/application_permission.py +++ b/apps/perms/models/application_permission.py @@ -37,7 +37,6 @@ class ApplicationPermission(BasePermission): unique_together = [('org_id', 'name')] verbose_name = _('Application permission') permissions = [ - ('view_permuserapplication', _('Can view application of permission to user')) ] ordering = ('name',) diff --git a/apps/perms/models/asset_permission.py b/apps/perms/models/asset_permission.py index b8e4eddb5..ea795d889 100644 --- a/apps/perms/models/asset_permission.py +++ b/apps/perms/models/asset_permission.py @@ -29,8 +29,6 @@ class AssetPermission(BasePermission): verbose_name = _("Asset permission") ordering = ('name',) permissions = [ - ('view_permuserasset', _('Can view asset of permission to user')), - ('view_permusergroupasset', _('Can view asset of permission to user group')) ] @lazyproperty diff --git a/apps/rbac/api/permission.py b/apps/rbac/api/permission.py index 75025ba8a..722deb556 100644 --- a/apps/rbac/api/permission.py +++ b/apps/rbac/api/permission.py @@ -41,13 +41,3 @@ class PermissionViewSet(JMSModelViewSet): queryset = Permission.get_permissions(self.scope) queryset = queryset.prefetch_related('content_type') return queryset - - -# class UserPermsApi(ListAPIView): -# serializer_class = UserPermsSerializer -# permission_classes = (IsValidUser,) -# -# def list(self, request, *args, **kwargs): -# perms = RoleBinding.get_user_perms(request.user) -# serializer = super().get_serializer(data={'perms': perms}) -# return Res diff --git a/apps/rbac/builtin.py b/apps/rbac/builtin.py index 1ed528a78..a47139132 100644 --- a/apps/rbac/builtin.py +++ b/apps/rbac/builtin.py @@ -2,6 +2,8 @@ from django.utils.translation import ugettext_noop from .const import Scope, system_exclude_permissions, org_exclude_permissions +# Todo: 获取应该区分 系统用户,和组织用户的权限 +# 工作台也区分组织后再考虑 user_perms = ( ('rbac', 'menupermission', 'view', 'workspace'), ('rbac', 'menupermission', 'view', 'webterminal'), @@ -11,13 +13,14 @@ user_perms = ( ('assets', 'asset', 'match', 'asset'), ('assets', 'systemuser', 'match', 'systemuser'), ('assets', 'node', 'match', 'node'), + ('applications', 'application', 'match', 'application'), ('ops', 'commandexecution', 'add', 'commandexecution'), ('authentication', 'connectiontoken', 'add', 'connectiontoken'), + ('tickets', 'ticket', 'view', 'ticket'), ) auditor_perms = user_perms + ( ('rbac', 'menupermission', 'view', 'audit'), - ('rbac', 'menupermission', 'view', 'dashboard'), ('audits', '*', '*', '*'), ('terminal', 'commandstorage', 'view', 'commandstorage'), ('terminal', 'sessionreplay', 'view,download', 'sessionreplay'), @@ -95,7 +98,7 @@ class BuiltinRole: '4', ugettext_noop('SystemComponent'), Scope.system, app_exclude_perms, 'exclude' ) system_user = PredefineRole( - '3', ugettext_noop('User'), Scope.system, [] + '3', ugettext_noop('User'), Scope.system, user_perms ) org_admin = PredefineRole( '5', ugettext_noop('OrgAdmin'), Scope.org, [] diff --git a/apps/rbac/const.py b/apps/rbac/const.py index ea54c2474..250a30a0e 100644 --- a/apps/rbac/const.py +++ b/apps/rbac/const.py @@ -29,7 +29,8 @@ exclude_permissions = ( ('users', 'userpasswordhistory', '*', '*'), ('applications', 'applicationuser', '*', '*'), ('applications', 'historicalaccount', '*', '*'), - ('applications', 'account', 'add,change', 'account'), + ('applications', 'account', 'add,change,delete', 'account'), + ('applications', 'account', 'change', 'appplicationaccountsecret'), ('assets', 'adminuser', '*', '*'), ('assets', 'assetgroup', '*', '*'), ('assets', 'cluster', '*', '*'), @@ -78,6 +79,7 @@ exclude_permissions = ( ('common', 'permission', 'add,delete,view,change', 'permission'), ('terminal', 'command', 'delete,change', 'command'), ('terminal', 'status', 'delete,change', 'status'), + ('terminal', 'task', 'add,delete', 'task'), ('terminal', 'sessionjoinrecord', 'delete', 'sessionjoinrecord'), ('terminal', 'sessionreplay', 'add,change,delete', 'sessionreplay'), ('terminal', 'sessionsharing', 'view,add,change,delete', 'sessionsharing'), diff --git a/apps/rbac/permissions.py b/apps/rbac/permissions.py index 7611698b6..bfcb71cc7 100644 --- a/apps/rbac/permissions.py +++ b/apps/rbac/permissions.py @@ -66,8 +66,10 @@ class RBACPermission(permissions.DjangoModelPermissions): perms = {} if hasattr(view, 'rbac_perms'): perms.update(dict(view.rbac_perms)) + default_perms = self.get_default_action_perms(model_cls) if '*' not in perms: - perms.update(self.get_default_action_perms(model_cls)) + for k, v in default_perms.items(): + perms.setdefault(k, v) return perms def _get_action_perms(self, action, model_cls, view): diff --git a/apps/rbac/signal_handlers.py b/apps/rbac/signal_handlers.py index 316c38211..86eefb180 100644 --- a/apps/rbac/signal_handlers.py +++ b/apps/rbac/signal_handlers.py @@ -1,7 +1,8 @@ from django.dispatch import receiver -from django.db.models.signals import post_migrate +from django.db.models.signals import post_migrate, post_save from django.apps import apps +from .models import SystemRole, OrgRole from .builtin import BuiltinRole @@ -12,3 +13,15 @@ def after_migrate_update_builtin_role_permissions(sender, app_config, **kwargs): if app_config.name == last_app.name: print("After migration, update builtin role permissions") BuiltinRole.sync_to_db() + + +@receiver(post_save, sender=SystemRole) +def on_system_role_update(sender, instance, created, **kwargs): + from users.models import User + User.expire_users_rbac_perms_cache() + + +@receiver(post_save, sender=OrgRole) +def on_org_role_update(sender, instance, created, **kwargs): + from users.models import User + User.expire_users_rbac_perms_cache() diff --git a/apps/rbac/tree.py b/apps/rbac/tree.py index b8bd2407e..083e64c96 100644 --- a/apps/rbac/tree.py +++ b/apps/rbac/tree.py @@ -1,6 +1,7 @@ #!/usr/bin/python from collections import defaultdict from typing import Callable +import os from django.utils.translation import gettext_lazy as _, gettext, get_language from django.conf import settings @@ -10,6 +11,8 @@ from django.db.models import F, Count from common.tree import TreeNode from .models import Permission, ContentType +DEBUG_DB = os.environ.get('DEBUG_DB', '0') == '1' + # 根节点 root_node_data = { 'id': '$ROOT$', @@ -116,11 +119,14 @@ verbose_name_mapper = { } xpack_nodes = [ - 'xpack', 'tickets', 'applications.remoteapp', - "assets.accountbackupplan", "assets.accountbackupplanexecution", + 'xpack', 'tickets', 'gather_account_node', + 'applications.remoteapp', "assets.accountbackupplan", + "assets.accountbackupplanexecution", "rbac.orgrole", "rbac.orgrolebinding", - "settings.change_interface", 'assets.gathereduser', - 'gather_account_node' + 'assets.gathereduser', + + 'settings.change_interface', 'settings.change_sms', + 'users.invite_user', 'users.remove_user', ] @@ -313,12 +319,15 @@ class PermissionTreeUtil: model_id = f'{p.app}.{p.model}' if not self._check_model_xpack(model_id): continue + title = p.app_label_codename + if not settings.XPACK_ENABLED and title in xpack_nodes: + continue + # name 要特殊处理,解决 i18n 问题 name, icon = self._get_permission_name_icon(p, content_types_name_mapper) - if settings.DEBUG: + if DEBUG_DB: name += '[{}]'.format(p.app_label_codename) - title = p.app_label_codename pid = model_id # perm node 的特殊设置用的是 title,因为 id 是数字,不一致 if title in special_pid_mapper: @@ -366,9 +375,9 @@ class PermissionTreeUtil: } node_data['title'] = node_data['id'] node = TreeNode(**node_data) - if settings.DEBUG: + if DEBUG_DB: node.name += ('[' + node.id + ']') - if settings.DEBUG: + if DEBUG_DB: node.name += ('-' + node.id) node.name += f'({checked_count}/{total_count})' return node diff --git a/apps/terminal/api/command.py b/apps/terminal/api/command.py index 9fa401421..09ed27e30 100644 --- a/apps/terminal/api/command.py +++ b/apps/terminal/api/command.py @@ -105,6 +105,7 @@ class CommandViewSet(JMSBulkModelViewSet): command_store = get_command_storage() serializer_class = SessionCommandSerializer filterset_class = CommandFilter + search_fields = ('input',) model = Command ordering_fields = ('timestamp', ) diff --git a/apps/terminal/notifications.py b/apps/terminal/notifications.py index e43a782e7..62bc50592 100644 --- a/apps/terminal/notifications.py +++ b/apps/terminal/notifications.py @@ -82,6 +82,9 @@ class CommandAlertMessage(CommandAlertMixin, SystemMessage): 'api-terminal:session-detail', kwargs={'pk': command['session']}, external=True, api_to_ui=True ) + '?oid={}'.format(self.command['org_id']) + session_detail_url = session_detail_url.replace( + '/terminal/sessions/', '/audit/sessions/sessions/' + ) level = Command.get_risk_level_str(command['risk_level']) items = { _("Asset"): command['asset'], diff --git a/apps/tickets/const.py b/apps/tickets/const.py index 1d76ae487..9bfaf795e 100644 --- a/apps/tickets/const.py +++ b/apps/tickets/const.py @@ -1,7 +1,7 @@ from django.db.models import TextChoices, IntegerChoices from django.utils.translation import ugettext_lazy as _ -TICKET_DETAIL_URL = '/ui/#/tickets/tickets/{id}' +TICKET_DETAIL_URL = '/ui/#/tickets/tickets/{id}?type={type}' class TicketType(TextChoices): diff --git a/apps/tickets/notifications.py b/apps/tickets/notifications.py index a70e6d497..ffca227be 100644 --- a/apps/tickets/notifications.py +++ b/apps/tickets/notifications.py @@ -20,7 +20,13 @@ class BaseTicketMessage(UserMessage): @property def ticket_detail_url(self): tp = self.ticket.type - return urljoin(settings.SITE_URL, const.TICKET_DETAIL_URL.format(id=str(self.ticket.id))) + return urljoin( + settings.SITE_URL, + const.TICKET_DETAIL_URL.format( + id=str(self.ticket.id), + type=tp + ) + ) @property def content_title(self): diff --git a/apps/users/api/user.py b/apps/users/api/user.py index 092aef223..6d203a548 100644 --- a/apps/users/api/user.py +++ b/apps/users/api/user.py @@ -10,7 +10,7 @@ from rest_framework_bulk import BulkModelViewSet from common.mixins import CommonApiMixin from common.utils import get_logger from common.mixins.api import SuggestionMixin -from orgs.utils import current_org +from orgs.utils import current_org, tmp_to_root_org from rbac.models import Role, RoleBinding from users.utils import LoginBlockUtil, MFABlockUtils from .mixins import UserQuerysetMixin @@ -61,6 +61,11 @@ class UserViewSet(CommonApiMixin, UserQuerysetMixin, SuggestionMixin, BulkModelV self.set_users_roles_for_cache(queryset) return page + @action(methods=['get'], detail=False, url_path='suggestions') + def match(self, request, *args, **kwargs): + with tmp_to_root_org(): + return super().match(request, *args, **kwargs) + @staticmethod def set_users_roles_for_cache(queryset): # Todo: 未来有机会用 SQL 实现 diff --git a/apps/users/models/user.py b/apps/users/models/user.py index 67efa8b3c..e7834a088 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -279,10 +279,15 @@ class RoleMixin: cache.set(key, perms, 3600) return perms - def expire_perms_cache(self): + def expire_rbac_perms_cache(self): key = self.PERM_CACHE_KEY.format(self.id, '*') cache.delete_pattern(key) + @classmethod + def expire_users_rbac_perms_cache(cls): + key = cls.PERM_CACHE_KEY.format('*', '*') + cache.delete_pattern(key) + @lazyproperty def is_superuser(self): """ @@ -377,6 +382,11 @@ class RoleMixin: perms = RoleBinding.get_user_perms(self) return perms + def set_default_system_role(self): + from rbac.builtin import BuiltinRole + role_user = BuiltinRole.system_user.get_role() + self.system_roles.add(role_user) + class TokenMixin: CACHE_KEY_USER_RESET_PASSWORD_PREFIX = "_KEY_USER_RESET_PASSWORD_{}" diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py index 21d67961b..7421c9cc1 100644 --- a/apps/users/serializers/user.py +++ b/apps/users/serializers/user.py @@ -6,13 +6,11 @@ from rest_framework import serializers from common.mixins import CommonBulkSerializerMixin from common.validators import PhoneValidator -from rbac.models import Role from rbac.builtin import BuiltinRole from rbac.permissions import RBACPermission -from rbac.models import OrgRoleBinding, SystemRoleBinding +from rbac.models import OrgRoleBinding, SystemRoleBinding, Role from ..models import User from ..const import PasswordStrategy -from rbac.models import Role __all__ = [ 'UserSerializer', 'MiniUserSerializer', diff --git a/apps/users/signal_handlers.py b/apps/users/signal_handlers.py index c4d84e561..8f2065ca3 100644 --- a/apps/users/signal_handlers.py +++ b/apps/users/signal_handlers.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # - from django.dispatch import receiver from django_auth_ldap.backend import populate_user from django.conf import settings @@ -9,9 +8,9 @@ from django_cas_ng.signals import cas_user_authenticated from django.db.models.signals import post_save from authentication.backends.oidc.signals import openid_create_or_update_user - from authentication.backends.saml2.signals import saml2_create_or_update_user from common.utils import get_logger +from common.decorator import on_transaction_commit from .signals import post_user_create from .models import User, UserPasswordHistory @@ -26,7 +25,8 @@ def user_authenticated_handle(user, created, source, attrs=None, **kwargs): if created: user.source = source user.save() - elif not created and settings.AUTH_SAML2_ALWAYS_UPDATE_USER: + + if not created and settings.AUTH_SAML2_ALWAYS_UPDATE_USER: attr_whitelist = ('user', 'username', 'email', 'phone', 'comment') logger.debug( "Receive saml2 user updated signal: {}, " @@ -34,16 +34,18 @@ def user_authenticated_handle(user, created, source, attrs=None, **kwargs): "(Update only properties in the whitelist. [{}])" "".format(user, str(attrs), ','.join(attr_whitelist)) ) - if attrs is not None: - for key, value in attrs.items(): - if key in attr_whitelist and value: - setattr(user, key, value) - user.save() + if not attrs: + return + for key, value in attrs.items(): + if key in attr_whitelist and value: + setattr(user, key, value) + user.save() @receiver(post_save, sender=User) def save_passwd_change(sender, instance: User, **kwargs): - passwords = UserPasswordHistory.objects.filter(user=instance) \ + passwords = UserPasswordHistory.objects\ + .filter(user=instance) \ .order_by('-date_created')\ .values_list('password', flat=True) passwords = passwords[:int(settings.OLD_PASSWORD_HISTORY_LIMIT_COUNT)] @@ -58,6 +60,17 @@ def save_passwd_change(sender, instance: User, **kwargs): ) +@receiver(post_save, sender=User) +@on_transaction_commit +def on_user_create_set_default_system_role(sender, instance, created, **kwargs): + if not created: + return + has_system_role = instance.system_roles.all().exists() + if not has_system_role: + logger.debug("Receive user create signal, set default role") + instance.set_default_system_role() + + @receiver(post_user_create) def on_user_create(sender, user=None, **kwargs): logger.debug("Receive user `{}` create signal".format(user.name)) diff --git a/utils/clean_db_content_types.py b/utils/clean_db_content_types.py index d8c05db22..9ca387be2 100644 --- a/utils/clean_db_content_types.py +++ b/utils/clean_db_content_types.py @@ -55,6 +55,9 @@ def clean_db_content_types(): ('perms', 'permedkubernetesapp', 'view_mykubernetesapp'), ('perms', 'permedremoteapp', 'connect_myremoteapp'), ('perms', 'permedremoteapp', 'view_myremoteapp'), + ('perms', 'applicationpermission', 'view_permuserapplication'), + ('perms', 'assetpermission', 'view_permuserasset'), + ('perms', 'assetpermission', 'view_permusergroupasset'), ('applications', 'databaseapp', 'add_databaseapp'), ('applications', 'databaseapp', 'change_databaseapp'), @@ -79,6 +82,9 @@ def clean_db_content_types(): ('rbac', 'menupermission', 'view_userview'), ('rbac', 'menupermission', 'view_adminview'), ('rbac', 'menupermission', 'view_auditview'), + ('assets', 'systemuser', 'view_systemuserasset'), + ('assets', 'systemuser', 'add_systemuserasset'), + ('assets', 'systemuser', 'remove_systemuserasset'), ] for app, model, codename in permissions_delete_required: print('delete {}.{} ({})'.format(app, codename, model))