mirror of https://github.com/jumpserver/jumpserver
commit
91a34d1a88
|
@ -28,7 +28,7 @@ class ApplicationViewSet(SuggestionMixin, OrgBulkModelViewSet):
|
|||
}
|
||||
rbac_perms = {
|
||||
'get_tree': 'applications.view_application',
|
||||
'match': 'assets.match_application'
|
||||
'match': 'applications.match_application'
|
||||
}
|
||||
|
||||
@action(methods=['GET'], detail=False, url_path='tree')
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.1.14 on 2022-03-16 12:28
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('applications', '0019_auto_20220310_1853'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='application',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('mysql', 'MySQL'), ('mariadb', 'MariaDB'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'),
|
||||
),
|
||||
]
|
|
@ -205,6 +205,9 @@ class AssetGatewayListApi(generics.ListAPIView):
|
|||
|
||||
|
||||
class BaseAssetPermUserOrUserGroupListApi(ListAPIView):
|
||||
rbac_perms = {
|
||||
'GET': 'assets.view_asset'
|
||||
}
|
||||
|
||||
def get_object(self):
|
||||
asset_id = self.kwargs.get('pk')
|
||||
|
@ -222,6 +225,9 @@ class AssetPermUserListApi(BaseAssetPermUserOrUserGroupListApi):
|
|||
filterset_class = UserFilter
|
||||
search_fields = ('username', 'email', 'name', 'id', 'source', 'role')
|
||||
serializer_class = UserSerializer
|
||||
rbac_perms = {
|
||||
'GET': 'assets.view_asset'
|
||||
}
|
||||
|
||||
def get_queryset(self):
|
||||
perms = self.get_asset_related_perms()
|
||||
|
|
|
@ -132,7 +132,7 @@ class CommandExecutionHostRelationViewSet(OrgRelationMixin, OrgBulkModelViewSet)
|
|||
search_fields = ('asset__hostname', )
|
||||
http_method_names = ['options', 'get']
|
||||
rbac_perms = {
|
||||
'GET': 'audits.view_commandexecution'
|
||||
'GET': 'ops.view_commandexecution'
|
||||
}
|
||||
|
||||
def get_queryset(self):
|
||||
|
|
|
@ -83,6 +83,6 @@ class SSOViewSet(AuthMixin, JMSGenericViewSet):
|
|||
return HttpResponseRedirect(next_url)
|
||||
|
||||
user = token.user
|
||||
login(self.request, user, 'authentication.backends.api.SSOAuthentication')
|
||||
login(self.request, user, settings.AUTH_BACKEND_SSO)
|
||||
self.send_auth_signal(success=True, user=user)
|
||||
return HttpResponseRedirect(next_url)
|
||||
|
|
|
@ -22,8 +22,10 @@ class JMSBaseAuthBackend:
|
|||
Reject users with is_valid=False. Custom user models that don't have
|
||||
that attribute are allowed.
|
||||
"""
|
||||
is_valid = getattr(user, 'is_valid', None)
|
||||
return is_valid or is_valid is None
|
||||
# 在 check_user_auth 中进行了校验,可以返回对应的错误信息
|
||||
# is_valid = getattr(user, 'is_valid', None)
|
||||
# return is_valid or is_valid is None
|
||||
return True
|
||||
|
||||
# allow user to authenticate
|
||||
def username_allow_authenticate(self, username):
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
from django.conf import settings
|
||||
|
||||
from .base import JMSBaseAuthBackend
|
||||
from .base import JMSModelBackend
|
||||
|
||||
|
||||
class SSOAuthentication(JMSBaseAuthBackend):
|
||||
class SSOAuthentication(JMSModelBackend):
|
||||
"""
|
||||
什么也不做呀😺
|
||||
"""
|
||||
|
@ -16,7 +16,7 @@ class SSOAuthentication(JMSBaseAuthBackend):
|
|||
pass
|
||||
|
||||
|
||||
class WeComAuthentication(JMSBaseAuthBackend):
|
||||
class WeComAuthentication(JMSModelBackend):
|
||||
"""
|
||||
什么也不做呀😺
|
||||
"""
|
||||
|
@ -29,7 +29,7 @@ class WeComAuthentication(JMSBaseAuthBackend):
|
|||
pass
|
||||
|
||||
|
||||
class DingTalkAuthentication(JMSBaseAuthBackend):
|
||||
class DingTalkAuthentication(JMSModelBackend):
|
||||
"""
|
||||
什么也不做呀😺
|
||||
"""
|
||||
|
@ -42,7 +42,7 @@ class DingTalkAuthentication(JMSBaseAuthBackend):
|
|||
pass
|
||||
|
||||
|
||||
class FeiShuAuthentication(JMSBaseAuthBackend):
|
||||
class FeiShuAuthentication(JMSModelBackend):
|
||||
"""
|
||||
什么也不做呀😺
|
||||
"""
|
||||
|
@ -55,7 +55,7 @@ class FeiShuAuthentication(JMSBaseAuthBackend):
|
|||
pass
|
||||
|
||||
|
||||
class AuthorizationTokenAuthentication(JMSBaseAuthBackend):
|
||||
class AuthorizationTokenAuthentication(JMSModelBackend):
|
||||
"""
|
||||
什么也不做呀😺
|
||||
"""
|
||||
|
|
|
@ -32,6 +32,7 @@ class SimpleMetadataWithFilters(SimpleMetadata):
|
|||
the fields that are accepted for 'PUT' and 'POST' methods.
|
||||
"""
|
||||
actions = {}
|
||||
view.raw_action = getattr(view, 'action', None)
|
||||
for method in self.methods & set(view.allowed_methods):
|
||||
if hasattr(view, 'action_map'):
|
||||
view.action = view.action_map.get(method.lower(), view.action)
|
||||
|
|
|
@ -14,9 +14,9 @@ __all__ = ['celery_flower_view']
|
|||
|
||||
@csrf_exempt
|
||||
def celery_flower_view(request, path):
|
||||
if not request.user.is_superuser:
|
||||
if not request.user.has_perm('ops.view_taskmonitor'):
|
||||
return HttpResponse("Forbidden")
|
||||
remote_url = 'http://{}/{}'.format(flower_url, path)
|
||||
remote_url = 'http://{}/core/flower/{}'.format(flower_url, path)
|
||||
try:
|
||||
response = proxy_view(request, remote_url)
|
||||
except Exception as e:
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a8c1155ea28b70a0eb06aa39ab6ae04619cd30d02f59698fadaa6068d91a7900
|
||||
size 104348
|
||||
oid sha256:f529bbca004aeba7532d9faf50f6f8ab5532b19bf0afd650f8360f418c03c15c
|
||||
size 104629
|
||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: JumpServer 0.3.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-03-15 19:46+0800\n"
|
||||
"POT-Creation-Date: 2022-03-16 20:38+0800\n"
|
||||
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
|
||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
||||
"Language-Team: JumpServer team<ibuler@qq.com>\n"
|
||||
|
@ -22,11 +22,11 @@ msgid "Acls"
|
|||
msgstr "访问控制"
|
||||
|
||||
#: acls/models/base.py:25 acls/serializers/login_asset_acl.py:47
|
||||
#: applications/models/application.py:202 assets/models/asset.py:138
|
||||
#: applications/models/application.py:209 assets/models/asset.py:138
|
||||
#: assets/models/base.py:175 assets/models/cluster.py:18
|
||||
#: assets/models/cmd_filter.py:27 assets/models/domain.py:23
|
||||
#: assets/models/group.py:20 assets/models/label.py:18 ops/mixin.py:24
|
||||
#: orgs/models.py:12 perms/models/base.py:83 rbac/models/role.py:29
|
||||
#: orgs/models.py:65 perms/models/base.py:83 rbac/models/role.py:29
|
||||
#: 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
|
||||
|
@ -56,13 +56,13 @@ msgstr "优先级可选范围为 1-100 (数值越小越优先)"
|
|||
msgid "Active"
|
||||
msgstr "激活中"
|
||||
|
||||
#: acls/models/base.py:32 applications/models/application.py:215
|
||||
#: acls/models/base.py:32 applications/models/application.py:222
|
||||
#: assets/models/asset.py:143 assets/models/asset.py:231
|
||||
#: assets/models/backup.py:54 assets/models/base.py:180
|
||||
#: assets/models/cluster.py:29 assets/models/cmd_filter.py:48
|
||||
#: assets/models/cmd_filter.py:96 assets/models/domain.py:24
|
||||
#: assets/models/domain.py:64 assets/models/group.py:23
|
||||
#: assets/models/label.py:23 ops/models/adhoc.py:38 orgs/models.py:15
|
||||
#: assets/models/label.py:23 ops/models/adhoc.py:38 orgs/models.py:68
|
||||
#: 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
|
||||
|
@ -89,13 +89,13 @@ msgstr "登录复核"
|
|||
#: acls/models/login_acl.py:24 acls/models/login_asset_acl.py:20
|
||||
#: 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:196 perms/models/base.py:84
|
||||
#: rbac/builtin.py:97 rbac/models/rolebinding.py:35 templates/index.html:78
|
||||
#: 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
|
||||
#: 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:793
|
||||
#: users/models/user.py:824 users/serializers/group.py:19
|
||||
#: tickets/models/comment.py:17 users/const.py:14 users/models/user.py:795
|
||||
#: users/models/user.py:826 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
|
||||
|
@ -254,7 +254,7 @@ msgstr "时段"
|
|||
msgid "My applications"
|
||||
msgstr "我的应用"
|
||||
|
||||
#: applications/apps.py:9 applications/models/application.py:60
|
||||
#: applications/apps.py:9 applications/models/application.py:61
|
||||
msgid "Applications"
|
||||
msgstr "应用管理"
|
||||
|
||||
|
@ -269,11 +269,11 @@ msgstr "数据库"
|
|||
msgid "Remote app"
|
||||
msgstr "远程应用"
|
||||
|
||||
#: applications/const.py:31
|
||||
#: applications/const.py:35
|
||||
msgid "Custom"
|
||||
msgstr "自定义"
|
||||
|
||||
#: applications/models/account.py:12 applications/models/application.py:219
|
||||
#: applications/models/account.py:12 applications/models/application.py:226
|
||||
#: assets/models/backup.py:32 assets/models/cmd_filter.py:45
|
||||
#: perms/models/application_permission.py:28
|
||||
msgid "Application"
|
||||
|
@ -313,7 +313,7 @@ msgstr "可以查看应用账号密码"
|
|||
msgid "Can change application account secret"
|
||||
msgstr "可以查看应用账号密码"
|
||||
|
||||
#: applications/models/application.py:204
|
||||
#: applications/models/application.py:211
|
||||
#: applications/serializers/application.py:99 assets/models/label.py:21
|
||||
#: perms/models/application_permission.py:21
|
||||
#: perms/serializers/application/user_permission.py:33
|
||||
|
@ -322,7 +322,7 @@ msgstr "可以查看应用账号密码"
|
|||
msgid "Category"
|
||||
msgstr "类别"
|
||||
|
||||
#: applications/models/application.py:207
|
||||
#: applications/models/application.py:214
|
||||
#: applications/serializers/application.py:101 assets/models/backup.py:49
|
||||
#: assets/models/cmd_filter.py:82 assets/models/user.py:233
|
||||
#: perms/models/application_permission.py:24
|
||||
|
@ -335,20 +335,20 @@ msgstr "类别"
|
|||
msgid "Type"
|
||||
msgstr "类型"
|
||||
|
||||
#: applications/models/application.py:211 assets/models/asset.py:217
|
||||
#: applications/models/application.py:218 assets/models/asset.py:217
|
||||
#: assets/models/domain.py:29 assets/models/domain.py:63
|
||||
msgid "Domain"
|
||||
msgstr "网域"
|
||||
|
||||
#: applications/models/application.py:213 xpack/plugins/cloud/models.py:33
|
||||
#: applications/models/application.py:220 xpack/plugins/cloud/models.py:33
|
||||
msgid "Attrs"
|
||||
msgstr "属性"
|
||||
|
||||
#: applications/models/application.py:223
|
||||
#: applications/models/application.py:230
|
||||
msgid "Can match application"
|
||||
msgstr "匹配应用"
|
||||
|
||||
#: applications/models/application.py:271
|
||||
#: applications/models/application.py:278
|
||||
msgid "Application user"
|
||||
msgstr "应用用户"
|
||||
|
||||
|
@ -375,8 +375,8 @@ msgstr "类型名称"
|
|||
#: assets/models/group.py:22 assets/models/label.py:25
|
||||
#: assets/serializers/account.py:18 common/db/models.py:113
|
||||
#: common/mixins/models.py:50 ops/models/adhoc.py:39 ops/models/command.py:30
|
||||
#: orgs/models.py:14 orgs/models.py:199 perms/models/base.py:92
|
||||
#: users/models/group.py:18 users/models/user.py:825
|
||||
#: orgs/models.py:67 orgs/models.py:217 perms/models/base.py:92
|
||||
#: users/models/group.py:18 users/models/user.py:827
|
||||
#: xpack/plugins/cloud/models.py:125
|
||||
msgid "Date created"
|
||||
msgstr "创建日期"
|
||||
|
@ -384,7 +384,7 @@ msgstr "创建日期"
|
|||
#: applications/serializers/application.py:104 assets/models/base.py:182
|
||||
#: assets/models/gathered_user.py:20 assets/serializers/account.py:21
|
||||
#: common/db/models.py:114 common/mixins/models.py:51 ops/models/adhoc.py:40
|
||||
#: orgs/models.py:200
|
||||
#: orgs/models.py:218
|
||||
msgid "Date updated"
|
||||
msgstr "更新日期"
|
||||
|
||||
|
@ -626,8 +626,8 @@ msgstr "标签管理"
|
|||
#: assets/models/asset.py:229 assets/models/base.py:183
|
||||
#: 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:13
|
||||
#: orgs/models.py:201 perms/models/base.py:91 users/models/user.py:619
|
||||
#: 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
|
||||
#: 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
|
||||
|
@ -834,7 +834,7 @@ msgid "Default"
|
|||
msgstr "默认"
|
||||
|
||||
#: assets/models/cluster.py:36 assets/models/label.py:14 rbac/const.py:6
|
||||
#: users/models/user.py:810
|
||||
#: users/models/user.py:812
|
||||
msgid "System"
|
||||
msgstr "系统"
|
||||
|
||||
|
@ -1255,6 +1255,7 @@ msgid "System user name"
|
|||
msgstr "系统用户名称"
|
||||
|
||||
#: assets/serializers/system_user.py:282 orgs/mixins/serializers.py:26
|
||||
#: rbac/serializers/rolebinding.py:23
|
||||
msgid "Org name"
|
||||
msgstr "组织名称"
|
||||
|
||||
|
@ -1383,7 +1384,7 @@ msgstr "日志审计"
|
|||
|
||||
#: audits/models.py:27 audits/models.py:57
|
||||
#: authentication/templates/authentication/_access_key_modal.html:65
|
||||
#: rbac/tree.py:158 users/templates/users/user_asset_permission.html:128
|
||||
#: rbac/tree.py:162 users/templates/users/user_asset_permission.html:128
|
||||
#: users/templates/users/user_database_app_permission.html:111
|
||||
msgid "Delete"
|
||||
msgstr "删除"
|
||||
|
@ -1437,11 +1438,11 @@ msgstr "文件管理"
|
|||
|
||||
#: audits/models.py:55
|
||||
#: authentication/templates/authentication/_access_key_modal.html:22
|
||||
#: rbac/tree.py:155
|
||||
#: rbac/tree.py:159
|
||||
msgid "Create"
|
||||
msgstr "创建"
|
||||
|
||||
#: audits/models.py:56 rbac/tree.py:157 templates/_csv_import_export.html:18
|
||||
#: audits/models.py:56 rbac/tree.py:161 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
|
||||
|
@ -1565,7 +1566,7 @@ msgstr "运行用户"
|
|||
msgid "Run as display"
|
||||
msgstr "运行用户名称"
|
||||
|
||||
#: audits/serializers.py:102 rbac/serializers/rolebinding.py:22
|
||||
#: audits/serializers.py:102 rbac/serializers/rolebinding.py:21
|
||||
msgid "User display"
|
||||
msgstr "用户名称"
|
||||
|
||||
|
@ -2804,7 +2805,7 @@ msgstr "汇总"
|
|||
|
||||
#: ops/models/adhoc.py:339
|
||||
msgid "AdHoc execution"
|
||||
msgstr "任务执行历史"
|
||||
msgstr "任务执行"
|
||||
|
||||
#: ops/models/command.py:32
|
||||
msgid "Date finished"
|
||||
|
@ -2878,25 +2879,25 @@ msgstr "当前组织 ({}) 不能被删除"
|
|||
msgid "The organization have resource ({}) cannot be deleted"
|
||||
msgstr "组织存在资源 ({}) 不能被删除"
|
||||
|
||||
#: orgs/apps.py:7 rbac/tree.py:111
|
||||
#: orgs/apps.py:7 rbac/tree.py:110
|
||||
msgid "App organizations"
|
||||
msgstr "组织管理"
|
||||
|
||||
#: orgs/mixins/models.py:46 orgs/mixins/serializers.py:25 orgs/models.py:27
|
||||
#: orgs/models.py:193 rbac/const.py:7 rbac/models/rolebinding.py:42
|
||||
#: orgs/mixins/models.py:46 orgs/mixins/serializers.py:25 orgs/models.py:80
|
||||
#: orgs/models.py:211 rbac/const.py:7 rbac/models/rolebinding.py:46
|
||||
#: rbac/serializers/rolebinding.py:40 tickets/serializers/ticket/ticket.py:77
|
||||
msgid "Organization"
|
||||
msgstr "组织"
|
||||
|
||||
#: orgs/models.py:21
|
||||
#: orgs/models.py:74
|
||||
msgid "GLOBAL"
|
||||
msgstr "全局组织"
|
||||
|
||||
#: orgs/models.py:29
|
||||
#: orgs/models.py:82
|
||||
msgid "Can view root org"
|
||||
msgstr "可以查看全局组织"
|
||||
|
||||
#: orgs/models.py:198 rbac/models/role.py:46 rbac/models/rolebinding.py:38
|
||||
#: 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
|
||||
msgid "Role"
|
||||
msgstr "角色"
|
||||
|
@ -3111,17 +3112,17 @@ msgstr "如果有疑问或需求,请联系系统管理员"
|
|||
|
||||
#: rbac/api/role.py:32
|
||||
msgid "Internal role, can't be destroy"
|
||||
msgstr ""
|
||||
msgstr "内部角色,不能删除"
|
||||
|
||||
#: rbac/api/role.py:36
|
||||
msgid "The role has been bound to users, can't be destroy"
|
||||
msgstr ""
|
||||
msgstr "角色已绑定用户,不能删除"
|
||||
|
||||
#: rbac/api/role.py:43
|
||||
msgid "Internal role, can't be update"
|
||||
msgstr ""
|
||||
msgstr "内部角色,不能更新"
|
||||
|
||||
#: rbac/api/rolebinding.py:46
|
||||
#: rbac/api/rolebinding.py:52
|
||||
msgid "{} at least one system role"
|
||||
msgstr "{} 至少有一个系统角色"
|
||||
|
||||
|
@ -3129,27 +3130,27 @@ msgstr "{} 至少有一个系统角色"
|
|||
msgid "RBAC"
|
||||
msgstr "RBAC"
|
||||
|
||||
#: rbac/builtin.py:88
|
||||
#: rbac/builtin.py:89
|
||||
msgid "SystemAdmin"
|
||||
msgstr "系统管理员"
|
||||
|
||||
#: rbac/builtin.py:91
|
||||
#: rbac/builtin.py:92
|
||||
msgid "SystemAuditor"
|
||||
msgstr "系统审计员"
|
||||
|
||||
#: rbac/builtin.py:94
|
||||
#: rbac/builtin.py:95
|
||||
msgid "SystemComponent"
|
||||
msgstr "系统组件"
|
||||
|
||||
#: rbac/builtin.py:100
|
||||
#: rbac/builtin.py:101
|
||||
msgid "OrgAdmin"
|
||||
msgstr "组织管理员"
|
||||
|
||||
#: rbac/builtin.py:103
|
||||
#: rbac/builtin.py:104
|
||||
msgid "OrgAuditor"
|
||||
msgstr "组织审计员"
|
||||
|
||||
#: rbac/builtin.py:106
|
||||
#: rbac/builtin.py:107
|
||||
msgid "OrgUser"
|
||||
msgstr "组织用户"
|
||||
|
||||
|
@ -3179,9 +3180,9 @@ msgstr "文件管理"
|
|||
|
||||
#: rbac/models/permission.py:26
|
||||
msgid "Permission"
|
||||
msgstr "授权"
|
||||
msgstr "权限"
|
||||
|
||||
#: rbac/models/role.py:31 rbac/models/rolebinding.py:32
|
||||
#: rbac/models/role.py:31 rbac/models/rolebinding.py:36
|
||||
msgid "Scope"
|
||||
msgstr "范围"
|
||||
|
||||
|
@ -3201,21 +3202,21 @@ msgstr "系统角色"
|
|||
msgid "Organization role"
|
||||
msgstr "组织角色"
|
||||
|
||||
#: rbac/models/rolebinding.py:47
|
||||
#: rbac/models/rolebinding.py:51
|
||||
msgid "Role binding"
|
||||
msgstr "角色绑定"
|
||||
|
||||
#: rbac/models/rolebinding.py:113
|
||||
#: rbac/models/rolebinding.py:123
|
||||
msgid ""
|
||||
"User last role in org, can not be delete, you can remove user from org "
|
||||
"instead"
|
||||
msgstr "用户最后一个角色,不能删除,你可以将用户从组织移除"
|
||||
|
||||
#: rbac/models/rolebinding.py:120
|
||||
#: rbac/models/rolebinding.py:130
|
||||
msgid "Organization role binding"
|
||||
msgstr "组织角色绑定"
|
||||
|
||||
#: rbac/models/rolebinding.py:134
|
||||
#: rbac/models/rolebinding.py:145
|
||||
msgid "System role binding"
|
||||
msgstr "系统角色绑定"
|
||||
|
||||
|
@ -3231,7 +3232,7 @@ msgstr "范围名称"
|
|||
msgid "Display name"
|
||||
msgstr "显示名称"
|
||||
|
||||
#: rbac/serializers/rolebinding.py:23
|
||||
#: rbac/serializers/rolebinding.py:22
|
||||
msgid "Role display"
|
||||
msgstr "角色显示"
|
||||
|
||||
|
@ -3239,79 +3240,91 @@ msgstr "角色显示"
|
|||
msgid "Has bound this role"
|
||||
msgstr "已经绑定"
|
||||
|
||||
#: rbac/tree.py:17 rbac/tree.py:18
|
||||
#: rbac/tree.py:16 rbac/tree.py:17
|
||||
msgid "All permissions"
|
||||
msgstr "所有权限"
|
||||
|
||||
#: rbac/tree.py:24
|
||||
#: rbac/tree.py:23
|
||||
msgid "Console view"
|
||||
msgstr "控制台"
|
||||
|
||||
#: rbac/tree.py:25
|
||||
#: rbac/tree.py:24
|
||||
msgid "Workspace view"
|
||||
msgstr "工作台"
|
||||
|
||||
#: rbac/tree.py:26
|
||||
#: rbac/tree.py:25
|
||||
msgid "Audit view"
|
||||
msgstr "审计台"
|
||||
|
||||
#: rbac/tree.py:27 settings/models.py:140
|
||||
#: rbac/tree.py:26 settings/models.py:140
|
||||
msgid "System setting"
|
||||
msgstr "系统设置"
|
||||
|
||||
#: rbac/tree.py:28
|
||||
#: rbac/tree.py:27
|
||||
msgid "Other"
|
||||
msgstr "其它"
|
||||
|
||||
#: rbac/tree.py:36
|
||||
#: rbac/tree.py:35
|
||||
msgid "Accounts"
|
||||
msgstr "账号管理"
|
||||
|
||||
#: rbac/tree.py:40
|
||||
#: rbac/tree.py:39
|
||||
msgid "Session audits"
|
||||
msgstr "会话审计"
|
||||
|
||||
#: rbac/tree.py:50
|
||||
#: rbac/tree.py:49
|
||||
msgid "Cloud import"
|
||||
msgstr "云同步"
|
||||
|
||||
#: rbac/tree.py:51
|
||||
#: rbac/tree.py:50
|
||||
msgid "Backup account"
|
||||
msgstr "备份账号"
|
||||
|
||||
#: rbac/tree.py:52
|
||||
#: rbac/tree.py:51
|
||||
msgid "Gather account"
|
||||
msgstr "收集账号"
|
||||
|
||||
#: rbac/tree.py:53
|
||||
#: rbac/tree.py:52
|
||||
msgid "App change auth"
|
||||
msgstr "应用改密"
|
||||
|
||||
#: rbac/tree.py:54
|
||||
#: rbac/tree.py:53
|
||||
msgid "Asset change auth"
|
||||
msgstr "资产改密"
|
||||
|
||||
#: rbac/tree.py:55
|
||||
#: rbac/tree.py:54
|
||||
msgid "Terminal setting"
|
||||
msgstr "终端设置"
|
||||
|
||||
#: rbac/tree.py:56
|
||||
#: rbac/tree.py:55
|
||||
msgid "My assets"
|
||||
msgstr "我的资产"
|
||||
|
||||
#: rbac/tree.py:57
|
||||
#: rbac/tree.py:56
|
||||
msgid "My apps"
|
||||
msgstr "我的应用"
|
||||
|
||||
#: rbac/tree.py:112
|
||||
#: rbac/tree.py:111
|
||||
msgid "Ticket comment"
|
||||
msgstr "工单评论"
|
||||
|
||||
#: rbac/tree.py:112 tickets/models/ticket.py:163
|
||||
msgid "Ticket"
|
||||
msgstr "工单管理"
|
||||
|
||||
#: rbac/tree.py:113
|
||||
msgid "Common setting"
|
||||
msgstr "一般设置"
|
||||
|
||||
#: rbac/tree.py:156
|
||||
#: rbac/tree.py:115
|
||||
msgid "View permission tree"
|
||||
msgstr "查看授权树"
|
||||
|
||||
#: rbac/tree.py:116
|
||||
msgid "Execute batch command"
|
||||
msgstr "执行批量命令"
|
||||
|
||||
#: rbac/tree.py:160
|
||||
msgid "View"
|
||||
msgstr "查看"
|
||||
|
||||
|
@ -5363,10 +5376,6 @@ msgstr "流程"
|
|||
msgid "TicketFlow"
|
||||
msgstr "工单流程"
|
||||
|
||||
#: tickets/models/ticket.py:163
|
||||
msgid "Ticket"
|
||||
msgstr "工单管理"
|
||||
|
||||
#: tickets/models/ticket.py:311
|
||||
msgid "Please try again"
|
||||
msgstr "请再次尝试"
|
||||
|
@ -5674,27 +5683,27 @@ msgstr "最后更新密码日期"
|
|||
msgid "Need update password"
|
||||
msgstr "需要更新密码"
|
||||
|
||||
#: users/models/user.py:795
|
||||
#: users/models/user.py:797
|
||||
msgid "Can invite user"
|
||||
msgstr "可以邀请用户"
|
||||
|
||||
#: users/models/user.py:796
|
||||
#: users/models/user.py:798
|
||||
msgid "Can remove user"
|
||||
msgstr "可以移除用户"
|
||||
|
||||
#: users/models/user.py:797
|
||||
#: users/models/user.py:799
|
||||
msgid "Can match user"
|
||||
msgstr "可以匹配用户"
|
||||
|
||||
#: users/models/user.py:806
|
||||
#: users/models/user.py:808
|
||||
msgid "Administrator"
|
||||
msgstr "管理员"
|
||||
|
||||
#: users/models/user.py:809
|
||||
#: users/models/user.py:811
|
||||
msgid "Administrator is the super user of system"
|
||||
msgstr "Administrator是初始的超级管理员"
|
||||
|
||||
#: users/models/user.py:834
|
||||
#: users/models/user.py:836
|
||||
msgid "User password history"
|
||||
msgstr "用户密码历史"
|
||||
|
||||
|
@ -6177,7 +6186,7 @@ msgstr "重置密码成功,返回到登录页面"
|
|||
msgid "XPACK"
|
||||
msgstr ""
|
||||
|
||||
#: xpack/plugins/change_auth_plan/api/app.py:109
|
||||
#: xpack/plugins/change_auth_plan/api/app.py:112
|
||||
#: xpack/plugins/change_auth_plan/api/asset.py:95
|
||||
msgid "The parameter 'action' must be [{}]"
|
||||
msgstr "参数 'action' 必须是 [{}]"
|
||||
|
@ -6835,6 +6844,21 @@ msgstr "旗舰版"
|
|||
msgid "Community edition"
|
||||
msgstr "社区版"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Create"
|
||||
#~ msgid "create"
|
||||
#~ msgstr "创建"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Update"
|
||||
#~ msgid "update"
|
||||
#~ msgstr "更新"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Delete"
|
||||
#~ msgid "delete"
|
||||
#~ msgstr "删除"
|
||||
|
||||
#~ msgid "Can connect my assets"
|
||||
#~ msgstr "可以连接我的资产"
|
||||
|
||||
|
@ -7012,9 +7036,6 @@ msgstr "社区版"
|
|||
#~ msgid "Overview"
|
||||
#~ msgstr "概览"
|
||||
|
||||
#~ msgid "View permission user"
|
||||
#~ msgstr "查看授权用户"
|
||||
|
||||
#~ msgid "Add user to role"
|
||||
#~ msgstr "添加用户到角色"
|
||||
|
||||
|
|
|
@ -42,6 +42,9 @@ class TaskViewSet(OrgBulkModelViewSet):
|
|||
class TaskRun(generics.RetrieveAPIView):
|
||||
queryset = Task.objects.all()
|
||||
serializer_class = CeleryTaskSerializer
|
||||
rbac_perms = {
|
||||
'retrieve': 'ops.add_adhoc'
|
||||
}
|
||||
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
task = self.get_object()
|
||||
|
|
|
@ -7,7 +7,60 @@ from common.utils import lazyproperty, settings
|
|||
from common.tree import TreeNode
|
||||
|
||||
|
||||
class Organization(models.Model):
|
||||
class OrgRoleMixin:
|
||||
members: models.Manager
|
||||
|
||||
def get_members(self):
|
||||
return self.members.all().distinct()
|
||||
|
||||
def add_member(self, user, role=None):
|
||||
from rbac.builtin import BuiltinRole
|
||||
from .utils import tmp_to_org
|
||||
role_id = BuiltinRole.org_user.id
|
||||
if role:
|
||||
role_id = role.id
|
||||
with tmp_to_org(self):
|
||||
defaults = {
|
||||
'user': user, 'role_id': role_id,
|
||||
'org_id': self.id, 'scope': 'org'
|
||||
}
|
||||
self.members.through.objects.update_or_create(**defaults, defaults=defaults)
|
||||
|
||||
def get_origin_role_members(self, role_name):
|
||||
from rbac.models import OrgRoleBinding
|
||||
from users.models import User
|
||||
from rbac.builtin import BuiltinRole
|
||||
from .utils import tmp_to_org
|
||||
|
||||
role_mapper = {
|
||||
'user': BuiltinRole.org_user,
|
||||
'auditor': BuiltinRole.org_auditor,
|
||||
'admin': BuiltinRole.org_admin
|
||||
}
|
||||
assert role_name in role_mapper
|
||||
role = role_mapper.get(role_name).get_role()
|
||||
with tmp_to_org(self):
|
||||
org_admins = OrgRoleBinding.get_role_users(role)
|
||||
return org_admins
|
||||
|
||||
@property
|
||||
def admins(self):
|
||||
from users.models import User
|
||||
admins = self.get_origin_role_members('admin')
|
||||
if not admins:
|
||||
admins = User.objects.filter(username='admin')
|
||||
return admins
|
||||
|
||||
@property
|
||||
def auditors(self):
|
||||
return self.get_origin_role_members('auditor')
|
||||
|
||||
@property
|
||||
def users(self):
|
||||
return self.get_origin_role_members('user')
|
||||
|
||||
|
||||
class Organization(OrgRoleMixin, models.Model):
|
||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
name = models.CharField(max_length=128, unique=True, verbose_name=_("Name"))
|
||||
created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by'))
|
||||
|
@ -101,21 +154,6 @@ class Organization(models.Model):
|
|||
from .caches import OrgResourceStatisticsCache
|
||||
return OrgResourceStatisticsCache(self)
|
||||
|
||||
def get_members(self):
|
||||
return self.members.all().distinct()
|
||||
|
||||
def add_member(self, user, role=None):
|
||||
from rbac.builtin import BuiltinRole
|
||||
from .utils import tmp_to_org
|
||||
role_id = BuiltinRole.org_user.id
|
||||
if role:
|
||||
role_id = role.id
|
||||
with tmp_to_org(self):
|
||||
defaults = {
|
||||
'user': user, 'role_id': role_id, 'org_id': self.id, 'scope': 'org'
|
||||
}
|
||||
self.members.through.objects.update_or_create(**defaults, defaults=defaults)
|
||||
|
||||
def get_total_resources_amount(self):
|
||||
from django.apps import apps
|
||||
from orgs.mixins.models import OrgModelMixin
|
||||
|
@ -163,26 +201,6 @@ class Organization(models.Model):
|
|||
return super().delete(*args, **kwargs)
|
||||
|
||||
|
||||
# class OrgMemberManager(models.Manager):
|
||||
# def remove_users(self, org, users):
|
||||
# from users.models import User
|
||||
# pk_set = []
|
||||
# for user in users:
|
||||
# if hasattr(user, 'pk'):
|
||||
# pk_set.append(user.pk)
|
||||
# else:
|
||||
# pk_set.append(user)
|
||||
#
|
||||
# send = partial(
|
||||
# signals.m2m_changed.send, sender=self.model,
|
||||
# instance=org, reverse=False, model=User,
|
||||
# pk_set=pk_set, using=self.db
|
||||
# )
|
||||
# send(action="pre_remove")
|
||||
# self.filter(org_id=org.id, user_id__in=pk_set).delete()
|
||||
# send(action="post_remove")
|
||||
|
||||
|
||||
class OrganizationMember(models.Model):
|
||||
"""
|
||||
注意:直接调用该 `Model.delete` `Model.objects.delete` 不会触发清理该用户的信号
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.1.14 on 2022-03-16 12:28
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('perms', '0027_auto_20220310_1802'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='applicationpermission',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('mysql', 'MySQL'), ('mariadb', 'MariaDB'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'),
|
||||
),
|
||||
]
|
|
@ -8,7 +8,10 @@ from common.exceptions import JMSException
|
|||
from .. import serializers
|
||||
from ..models import RoleBinding, SystemRoleBinding, OrgRoleBinding
|
||||
|
||||
__all__ = ['RoleBindingViewSet', 'SystemRoleBindingViewSet', 'OrgRoleBindingViewSet']
|
||||
__all__ = [
|
||||
'RoleBindingViewSet', 'SystemRoleBindingViewSet',
|
||||
'OrgRoleBindingViewSet'
|
||||
]
|
||||
|
||||
|
||||
class RoleBindingViewSet(OrgBulkModelViewSet):
|
||||
|
@ -23,8 +26,8 @@ class RoleBindingViewSet(OrgBulkModelViewSet):
|
|||
]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset() \
|
||||
.prefetch_related('user', 'role') \
|
||||
queryset = self._get_queryset()\
|
||||
.prefetch_related('user', 'role', 'org') \
|
||||
.annotate(
|
||||
user_display=Concat(
|
||||
F('user__name'), Value('('),
|
||||
|
@ -34,6 +37,9 @@ class RoleBindingViewSet(OrgBulkModelViewSet):
|
|||
)
|
||||
return queryset
|
||||
|
||||
def _get_queryset(self):
|
||||
return super().get_queryset()
|
||||
|
||||
|
||||
class SystemRoleBindingViewSet(RoleBindingViewSet):
|
||||
model = SystemRoleBinding
|
||||
|
@ -49,9 +55,11 @@ class SystemRoleBindingViewSet(RoleBindingViewSet):
|
|||
|
||||
|
||||
class OrgRoleBindingViewSet(RoleBindingViewSet):
|
||||
model = OrgRoleBinding
|
||||
serializer_class = serializers.OrgRoleBindingSerializer
|
||||
|
||||
def _get_queryset(self):
|
||||
return OrgRoleBinding.objects.root_all()
|
||||
|
||||
def perform_bulk_create(self, serializer):
|
||||
validated_data = serializer.validated_data
|
||||
bindings = [
|
||||
|
|
|
@ -12,6 +12,7 @@ user_perms = (
|
|||
('assets', 'systemuser', 'match', 'systemuser'),
|
||||
('assets', 'node', 'match', 'node'),
|
||||
('ops', 'commandexecution', 'add', 'commandexecution'),
|
||||
('authentication', 'connectiontoken', 'add', 'connectiontoken'),
|
||||
)
|
||||
|
||||
auditor_perms = user_perms + (
|
||||
|
|
|
@ -24,7 +24,7 @@ exclude_permissions = (
|
|||
('authentication', 'privatetoken', '*', '*'),
|
||||
('authentication', 'accesskey', 'change,delete', 'accesskey'),
|
||||
('authentication', 'connectiontoken', 'change,delete', 'connectiontoken'),
|
||||
('authentication', 'ssotoken', 'change,delete', 'ssotoken'),
|
||||
('authentication', 'ssotoken', '*', '*'),
|
||||
('authentication', 'superconnectiontoken', 'change,delete', 'superconnectiontoken'),
|
||||
('users', 'userpasswordhistory', '*', '*'),
|
||||
('applications', 'applicationuser', '*', '*'),
|
||||
|
@ -50,7 +50,7 @@ exclude_permissions = (
|
|||
('rbac', 'rolebinding', '*', '*'),
|
||||
('rbac', 'role', '*', '*'),
|
||||
('ops', 'adhoc', 'delete,change', '*'),
|
||||
('ops', 'adhocexecution', 'delete,change', '*'),
|
||||
('ops', 'adhocexecution', 'add,delete,change', '*'),
|
||||
('ops', 'celerytask', '*', '*'),
|
||||
('ops', 'task', 'add,change', 'task'),
|
||||
('ops', 'commandexecution', 'delete,change', 'commandexecution'),
|
||||
|
@ -62,18 +62,19 @@ exclude_permissions = (
|
|||
('audits', 'ftplog', 'change,delete', 'ftplog'),
|
||||
('tickets', 'ticketassignee', '*', 'ticketassignee'),
|
||||
('tickets', 'ticketflow', 'add,delete', 'ticketflow'),
|
||||
('tickets', 'comment', 'change,delete', 'comment'),
|
||||
('tickets', 'ticket', 'delete', 'ticket'),
|
||||
('tickets', 'comment', '*', '*'),
|
||||
('tickets', 'ticket', 'add,delete,change', 'ticket'),
|
||||
('tickets', 'ticketstep', '*', '*'),
|
||||
('tickets', 'approvalrule', '*', '*'),
|
||||
('tickets', 'superticket', 'delete', 'superticket'),
|
||||
('tickets', 'ticketsession', 'delete', 'ticketsession'),
|
||||
('tickets', 'ticketsession', 'view,delete', 'ticketsession'),
|
||||
('xpack', 'interface', '*', '*'),
|
||||
('xpack', 'license', '*', '*'),
|
||||
('xpack', 'syncinstancedetail', 'add,delete,change', 'syncinstancedetail'),
|
||||
('xpack', 'syncinstancetaskexecution', 'delete,change', 'syncinstancetaskexecution'),
|
||||
('xpack', 'changeauthplanexecution', 'delete,change', 'changeauthplanexecution'),
|
||||
('xpack', 'changeauthplantask', 'add,delete', 'changeauthplantask'),
|
||||
('xpack', 'gatherusertaskexecution', 'change,delete', 'gatherusertaskexecution'),
|
||||
('common', 'permission', 'add,delete,view,change', 'permission'),
|
||||
('terminal', 'command', 'delete,change', 'command'),
|
||||
('terminal', 'status', 'delete,change', 'status'),
|
||||
|
@ -102,7 +103,7 @@ only_system_permissions = (
|
|||
('terminal', 'replaystorage', '*', '*'),
|
||||
('terminal', 'status', '*', '*'),
|
||||
('terminal', 'task', '*', '*'),
|
||||
('tickets', 'ticketflow', '*', '*'),
|
||||
('authentication', '*', '*', '*'),
|
||||
)
|
||||
|
||||
only_org_permissions = (
|
||||
|
|
|
@ -15,14 +15,18 @@ __all__ = ['RoleBinding', 'SystemRoleBinding', 'OrgRoleBinding']
|
|||
class RoleBindingManager(models.Manager):
|
||||
def get_queryset(self):
|
||||
queryset = super(RoleBindingManager, self).get_queryset()
|
||||
|
||||
q = Q(scope=Scope.system, org__isnull=True)
|
||||
if not current_org.is_root():
|
||||
q = Q(scope=Scope.system) | Q(org_id=current_org.id, scope=Scope.org)
|
||||
else:
|
||||
q = Q()
|
||||
q |= Q(org_id=current_org.id, scope=Scope.org)
|
||||
queryset = queryset.filter(q)
|
||||
return queryset
|
||||
|
||||
def root_all(self):
|
||||
queryset = super().get_queryset()
|
||||
if current_org.is_root():
|
||||
return queryset
|
||||
return self.get_queryset()
|
||||
|
||||
|
||||
class RoleBinding(JMSModel):
|
||||
Scope = Scope
|
||||
|
@ -55,6 +59,12 @@ class RoleBinding(JMSModel):
|
|||
display += ' | {org}'.format(org=self.org)
|
||||
return display
|
||||
|
||||
@property
|
||||
def org_name(self):
|
||||
if self.org:
|
||||
return self.org.name
|
||||
return ''
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.scope = self.role.scope
|
||||
return super().save(*args, **kwargs)
|
||||
|
@ -67,7 +77,7 @@ class RoleBinding(JMSModel):
|
|||
@classmethod
|
||||
def get_role_users(cls, role):
|
||||
from users.models import User
|
||||
bindings = cls.objects.filter(role=role, scope=role.scope)
|
||||
bindings = cls.objects.root_all().filter(role=role, scope=role.scope)
|
||||
user_ids = bindings.values_list('user', flat=True).distinct()
|
||||
return User.objects.filter(id__in=user_ids)
|
||||
|
||||
|
@ -86,13 +96,13 @@ class RoleBinding(JMSModel):
|
|||
return self.role.display_name
|
||||
|
||||
|
||||
class OrgRoleBindingManager(models.Manager):
|
||||
class OrgRoleBindingManager(RoleBindingManager):
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = super(RoleBindingManager, self).get_queryset()
|
||||
if current_org.is_root():
|
||||
queryset = queryset.filter(scope=Scope.org)
|
||||
queryset = queryset.none()
|
||||
else:
|
||||
queryset = queryset.filter(org=current_org.id, scope=Scope.org)
|
||||
queryset = queryset.filter(org_id=current_org.id, scope=Scope.org)
|
||||
return queryset
|
||||
|
||||
|
||||
|
@ -120,9 +130,10 @@ class OrgRoleBinding(RoleBinding):
|
|||
verbose_name = _('Organization role binding')
|
||||
|
||||
|
||||
class SystemRoleBindingManager(models.Manager):
|
||||
class SystemRoleBindingManager(RoleBindingManager):
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset().filter(scope=Scope.system)
|
||||
queryset = super(RoleBindingManager, self).get_queryset()\
|
||||
.filter(scope=Scope.system)
|
||||
return queryset
|
||||
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ class RBACPermission(permissions.DjangoModelPermissions):
|
|||
def get_default_action_perms(self, model_cls):
|
||||
if model_cls is None:
|
||||
return {}
|
||||
|
||||
perms = {}
|
||||
for action, tmpl in dict(self.default_rbac_perms_tmpl).items():
|
||||
perms[action] = self.format_perms(tmpl, model_cls)
|
||||
|
@ -62,20 +63,25 @@ class RBACPermission(permissions.DjangoModelPermissions):
|
|||
def get_rbac_perms(self, view, model_cls) -> dict:
|
||||
if hasattr(view, 'get_rbac_perms'):
|
||||
return dict(view.get_rbac_perms())
|
||||
perms = self.get_default_action_perms(model_cls)
|
||||
perms = {}
|
||||
if hasattr(view, 'rbac_perms'):
|
||||
perms.update(dict(view.rbac_perms))
|
||||
if '*' not in perms:
|
||||
perms.update(self.get_default_action_perms(model_cls))
|
||||
return perms
|
||||
|
||||
def _get_action_perms(self, action, model_cls, view):
|
||||
action_perms_map = self.get_rbac_perms(view, model_cls)
|
||||
if action not in action_perms_map:
|
||||
if action in action_perms_map:
|
||||
perms = action_perms_map[action]
|
||||
elif '*' in action_perms_map:
|
||||
perms = action_perms_map['*']
|
||||
else:
|
||||
msg = 'Action not allowed: {}, only `{}` supported'.format(
|
||||
action, ','.join(list(action_perms_map.keys()))
|
||||
)
|
||||
logger.error(msg)
|
||||
raise exceptions.PermissionDenied(msg)
|
||||
perms = action_perms_map[action]
|
||||
return perms
|
||||
|
||||
def get_model_cls(self, view):
|
||||
|
@ -96,7 +102,6 @@ class RBACPermission(permissions.DjangoModelPermissions):
|
|||
:param view:
|
||||
:return:
|
||||
"""
|
||||
|
||||
model_cls = self.get_model_cls(view)
|
||||
action = getattr(view, 'action', None)
|
||||
if not action:
|
||||
|
@ -114,8 +119,8 @@ class RBACPermission(permissions.DjangoModelPermissions):
|
|||
if request.user.is_anonymous and self.authenticated_users_only:
|
||||
return False
|
||||
|
||||
action = getattr(view, 'action', None)
|
||||
if action == 'metadata':
|
||||
raw_action = getattr(view, 'raw_action', None)
|
||||
if raw_action == 'metadata':
|
||||
return True
|
||||
|
||||
perms = self.get_require_perms(request, view)
|
||||
|
|
|
@ -2,7 +2,6 @@ from rest_framework import serializers
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orgs.serializers import CurrentOrgDefault
|
||||
from orgs.utils import current_org
|
||||
from ..models import RoleBinding, SystemRoleBinding, OrgRoleBinding
|
||||
|
||||
__all__ = [
|
||||
|
@ -15,12 +14,13 @@ class RoleBindingSerializer(serializers.ModelSerializer):
|
|||
model = RoleBinding
|
||||
fields = [
|
||||
'id', 'user', 'user_display', 'role', 'role_display',
|
||||
'scope', 'org',
|
||||
'scope', 'org', 'org_name',
|
||||
]
|
||||
read_only_fields = ['scope']
|
||||
extra_kwargs = {
|
||||
'user_display': {'label': _('User display')},
|
||||
'role_display': {'label': _('Role display')},
|
||||
'org_name': {'label': _("Org name")}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
from collections import defaultdict
|
||||
from typing import Callable
|
||||
|
||||
from django.utils.translation import gettext_lazy as _, gettext
|
||||
from django.utils.translation import gettext_lazy as _, gettext, get_language
|
||||
from django.conf import settings
|
||||
from django.apps import apps
|
||||
from django.db.models import F, Count
|
||||
from django.utils.translation import ugettext
|
||||
|
||||
from common.tree import TreeNode
|
||||
from .models import Permission, ContentType
|
||||
|
@ -104,19 +103,24 @@ special_pid_mapper = {
|
|||
"rbac.view_workspace": "view_workspace",
|
||||
"rbac.view_webterminal": "view_workspace",
|
||||
"rbac.view_filemanager": "view_workspace",
|
||||
'tickets.view_ticket': 'tickets'
|
||||
}
|
||||
|
||||
verbose_name_mapper = {
|
||||
'orgs.organization': _("App organizations"),
|
||||
'tickets.comment': _("Ticket comment"),
|
||||
'tickets.view_ticket': _("Ticket"),
|
||||
'settings.setting': _("Common setting"),
|
||||
'rbac.view_permission': _('View permission tree'),
|
||||
'ops.add_commandexecution': _('Execute batch command')
|
||||
}
|
||||
|
||||
xpack_nodes = [
|
||||
'xpack', 'tickets', 'applications.remoteapp',
|
||||
"assets.accountbackupplan", "assets.accountbackupplanexecution",
|
||||
"rbac.orgrole", "rbac.orgrolebinding",
|
||||
"settings.change_interface",
|
||||
"settings.change_interface", 'assets.gathereduser',
|
||||
'gather_account_node'
|
||||
]
|
||||
|
||||
|
||||
|
@ -151,10 +155,10 @@ def sort_nodes(node):
|
|||
class PermissionTreeUtil:
|
||||
get_permissions: Callable
|
||||
action_mapper = {
|
||||
'add': ugettext('Create'),
|
||||
'view': ugettext('View'),
|
||||
'change': ugettext('Update'),
|
||||
'delete': ugettext('Delete')
|
||||
'add': _('Create'),
|
||||
'view': _('View'),
|
||||
'change': _('Update'),
|
||||
'delete': _('Delete')
|
||||
}
|
||||
action_icon = {
|
||||
'add': 'add',
|
||||
|
@ -174,6 +178,7 @@ class PermissionTreeUtil:
|
|||
self.check_disabled = check_disabled
|
||||
self.total_counts = defaultdict(int)
|
||||
self.checked_counts = defaultdict(int)
|
||||
self.lang = get_language()
|
||||
|
||||
@staticmethod
|
||||
def prefetch_permissions(perms):
|
||||
|
@ -278,14 +283,24 @@ class PermissionTreeUtil:
|
|||
|
||||
def _get_permission_name_icon(self, p: Permission, content_types_name_mapper: dict):
|
||||
action, resource = p.codename.split('_', 1)
|
||||
icon = self.action_icon.get(action, 'file')
|
||||
name = verbose_name_mapper.get(p.app_label_codename)
|
||||
if name:
|
||||
return name, icon
|
||||
|
||||
app_model = '%s.%s' % (p.content_type.app_label, resource)
|
||||
if action in self.action_mapper and app_model in content_types_name_mapper:
|
||||
if self.lang == 'en':
|
||||
name = p.name
|
||||
# 因为默认的权限位是没有翻译的,所以我们要用 action + resource name 去拼
|
||||
elif action in self.action_mapper and app_model in content_types_name_mapper:
|
||||
action_name = self.action_mapper[action]
|
||||
name = action_name + content_types_name_mapper[app_model]
|
||||
resource_name = content_types_name_mapper[app_model]
|
||||
sep = ''
|
||||
name = '{}{}{}'.format(action_name, sep, resource_name)
|
||||
# 手动创建的 permission
|
||||
else:
|
||||
name = gettext(p.name)
|
||||
icon = self.action_icon.get(action, 'file')
|
||||
name = name.replace('Can ', '').replace('可以', '')
|
||||
name = name.replace('Can ', '').replace('可以', '').capitalize()
|
||||
return name, icon
|
||||
|
||||
def _create_perms_nodes(self):
|
||||
|
|
|
@ -64,7 +64,7 @@ class SessionViewSet(OrgBulkModelViewSet):
|
|||
]
|
||||
extra_filter_backends = [DatetimeRangeFilter]
|
||||
rbac_perms = {
|
||||
'download': ['terminal.download_sessionreplay']
|
||||
'download': ['terminal.download_sessionreplay|terminal.view_sessionreplay']
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -16,6 +16,9 @@ __all__ = ['CommentViewSet']
|
|||
class CommentViewSet(mixins.CreateModelMixin, viewsets.ReadOnlyModelViewSet):
|
||||
serializer_class = serializers.CommentSerializer
|
||||
permission_classes = (RBACPermission, IsSwagger | IsAssignee | IsApplicant)
|
||||
rbac_perms = {
|
||||
'*': 'tickets.view_ticket'
|
||||
}
|
||||
|
||||
@lazyproperty
|
||||
def ticket(self):
|
||||
|
|
|
@ -18,6 +18,9 @@ class TicketSessionRelationViewSet(CreateModelMixin, JMSGenericViewSet):
|
|||
# Todo: 放到上面的 ViewSet 中
|
||||
class TicketSessionApi(views.APIView):
|
||||
perm_model = TicketSession
|
||||
rbac_perms = {
|
||||
'*': ['tickets.view_ticket']
|
||||
}
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
with tmp_to_root_org():
|
||||
|
|
|
@ -7,9 +7,10 @@ from rest_framework.response import Response
|
|||
|
||||
from common.const.http import POST, PUT
|
||||
from common.mixins.api import CommonApiMixin
|
||||
from common.permissions import IsValidUser
|
||||
from common.drf.api import JMSBulkModelViewSet
|
||||
|
||||
from rbac.permissions import RBACPermission
|
||||
|
||||
from tickets import serializers
|
||||
from tickets.models import Ticket, TicketFlow
|
||||
from tickets.filters import TicketFilter
|
||||
|
@ -33,6 +34,9 @@ class TicketViewSet(CommonApiMixin, viewsets.ModelViewSet):
|
|||
'date_created', 'serial_num',
|
||||
)
|
||||
ordering = ('-date_created',)
|
||||
rbac_perms = {
|
||||
'open': 'tickets.view_ticket',
|
||||
}
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
raise MethodNotAllowed(self.action)
|
||||
|
@ -53,7 +57,7 @@ class TicketViewSet(CommonApiMixin, viewsets.ModelViewSet):
|
|||
instance.process_map = instance.create_process_map()
|
||||
instance.open(applicant=self.request.user)
|
||||
|
||||
@action(detail=False, methods=[POST], permission_classes=[IsValidUser, ])
|
||||
@action(detail=False, methods=[POST], permission_classes=[RBACPermission, ])
|
||||
def open(self, request, *args, **kwargs):
|
||||
return super().create(request, *args, **kwargs)
|
||||
|
||||
|
|
|
@ -783,11 +783,17 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser):
|
|||
.exclude(name=BuiltinRole.system_user.name)\
|
||||
.exists()
|
||||
if has_system_role:
|
||||
orgs = [Organization.root()] + list(Organization.objects.all())
|
||||
orgs = list(Organization.objects.all())
|
||||
else:
|
||||
orgs = list(self.orgs.all().distinct())
|
||||
if self.has_perm('orgs.view_rootorg'):
|
||||
orgs = [Organization.root()] + orgs
|
||||
return orgs
|
||||
|
||||
@property
|
||||
def my_orgs(self):
|
||||
return list(self.orgs.all().distinct())
|
||||
|
||||
class Meta:
|
||||
ordering = ['username']
|
||||
verbose_name = _("User")
|
||||
|
|
|
@ -122,12 +122,13 @@ class UserProfileSerializer(UserSerializer):
|
|||
guide_url = serializers.SerializerMethodField()
|
||||
receive_backends = serializers.ListField(child=serializers.CharField(), read_only=True)
|
||||
orgs = UserOrgSerializer(many=True, read_only=True, source='all_orgs')
|
||||
myorgs = UserOrgSerializer(many=True, read_only=True, source='my_orgs')
|
||||
perms = serializers.ListField(label=_("Perms"), read_only=True)
|
||||
|
||||
class Meta(UserSerializer.Meta):
|
||||
read_only_fields = [
|
||||
'date_joined', 'last_login', 'created_by', 'source',
|
||||
'receive_backends', 'orgs', 'perms',
|
||||
'receive_backends', 'orgs', 'myorgs', 'perms',
|
||||
]
|
||||
fields = UserSerializer.Meta.fields + [
|
||||
'public_key_comment', 'public_key_hash_md5', 'guide_url',
|
||||
|
|
|
@ -33,6 +33,20 @@ def clean_db_content_types():
|
|||
('perms', 'applicationpermission', 'connect_myapps'),
|
||||
('perms', 'applicationpermission', 'view_userapps'),
|
||||
('perms', 'applicationpermission', 'view_usergroupapps'),
|
||||
('perms', 'databaseapppermission', 'view_databaseapppermission'),
|
||||
('perms', 'databaseapppermission', 'add_databaseapppermission'),
|
||||
('perms', 'databaseapppermission', 'change_databaseapppermission'),
|
||||
('perms', 'databaseapppermission', 'delete_databaseapppermission'),
|
||||
|
||||
('perms', 'k8sapppermission', 'view_k8sapppermission'),
|
||||
('perms', 'k8sapppermission', 'add_k8sapppermission'),
|
||||
('perms', 'k8sapppermission', 'change_k8sapppermission'),
|
||||
('perms', 'k8sapppermission', 'delete_k8sapppermission'),
|
||||
|
||||
('perms', 'remoteapppermission', 'view_remoteapppermission'),
|
||||
('perms', 'remoteapppermission', 'add_remoteapppermission'),
|
||||
('perms', 'remoteapppermission', 'change_remoteapppermission'),
|
||||
('perms', 'remoteapppermission', 'delete_remoteapppermission'),
|
||||
|
||||
|
||||
('perms', 'permeddatabaseapp', 'connect_mydatabaseapp'),
|
||||
|
|
Loading…
Reference in New Issue