From 5ec970fab4d29a2229d468c886ca4dcd594af42c Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 16 Mar 2022 11:25:42 +0800 Subject: [PATCH 01/23] =?UTF-8?q?fix:=20=E5=85=A8=E5=B1=80=E7=BB=84?= =?UTF-8?q?=E7=BB=87=E5=8F=97=E6=9D=83=E9=99=90=E4=BD=8D=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/users/models/user.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/users/models/user.py b/apps/users/models/user.py index 5ff82b803..3ccf02fc9 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -783,9 +783,11 @@ 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 class Meta: From 995c9a6c1941829397b9846844e581db712b1960 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 16 Mar 2022 12:01:51 +0800 Subject: [PATCH 02/23] =?UTF-8?q?perf:=20=E4=BF=AE=E5=A4=8D=E4=B8=80?= =?UTF-8?q?=E4=BA=9Bbug=EF=BC=8C=20rolebingding=20=E6=89=BE=E5=88=B0?= =?UTF-8?q?=E5=90=88=E9=80=82=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jumpserver/views/celery_flower.py | 2 +- apps/locale/zh/LC_MESSAGES/django.po | 6 +++--- apps/rbac/const.py | 3 ++- apps/rbac/models/rolebinding.py | 6 ++---- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/apps/jumpserver/views/celery_flower.py b/apps/jumpserver/views/celery_flower.py index 0ec4a0fe1..abc288bf2 100644 --- a/apps/jumpserver/views/celery_flower.py +++ b/apps/jumpserver/views/celery_flower.py @@ -14,7 +14,7 @@ __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) try: diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index a0c2964c4..fe7b2de2d 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -3111,15 +3111,15 @@ 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 msgid "{} at least one system role" diff --git a/apps/rbac/const.py b/apps/rbac/const.py index d7f58e841..99e03123d 100644 --- a/apps/rbac/const.py +++ b/apps/rbac/const.py @@ -102,7 +102,8 @@ only_system_permissions = ( ('terminal', 'replaystorage', '*', '*'), ('terminal', 'status', '*', '*'), ('terminal', 'task', '*', '*'), - ('tickets', 'ticketflow', '*', '*'), + ('tickets', '*', '*', '*'), + ('authentication', '*', '*', '*'), ) only_org_permissions = ( diff --git a/apps/rbac/models/rolebinding.py b/apps/rbac/models/rolebinding.py index 55061e230..3aa04955d 100644 --- a/apps/rbac/models/rolebinding.py +++ b/apps/rbac/models/rolebinding.py @@ -15,11 +15,9 @@ __all__ = ['RoleBinding', 'SystemRoleBinding', 'OrgRoleBinding'] class RoleBindingManager(models.Manager): def get_queryset(self): queryset = super(RoleBindingManager, self).get_queryset() - + q = Q(scope=Scope.system) 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 From c065f82d300250e4adb7e7bf84ce3b597b3c0505 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 16 Mar 2022 11:01:11 +0800 Subject: [PATCH 03/23] =?UTF-8?q?fix:=20=E6=8E=92=E9=99=A4=E6=94=B6?= =?UTF-8?q?=E9=9B=86=E7=94=A8=E6=88=B7=E6=89=A7=E8=A1=8C=E7=9A=84=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E3=80=81=E5=88=A0=E9=99=A4=E6=9D=83=E9=99=90=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/rbac/const.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/rbac/const.py b/apps/rbac/const.py index 99e03123d..a3b69c33a 100644 --- a/apps/rbac/const.py +++ b/apps/rbac/const.py @@ -74,6 +74,7 @@ exclude_permissions = ( ('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'), From 8a1cd7e2a9ab9189a105da310ed328d3728bdee3 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 15 Mar 2022 20:54:34 +0800 Subject: [PATCH 04/23] perf: fix some bug --- apps/rbac/tree.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/rbac/tree.py b/apps/rbac/tree.py index ee742d865..8b8b23c4f 100644 --- a/apps/rbac/tree.py +++ b/apps/rbac/tree.py @@ -116,7 +116,8 @@ 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' ] From 572c5b6925201ba2ad24ef216d3d18940d000856 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 16 Mar 2022 14:43:20 +0800 Subject: [PATCH 05/23] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E5=B7=A5?= =?UTF-8?q?=E5=8D=95=E7=AE=A1=E7=90=86=E6=9D=83=E9=99=90=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/rbac/const.py | 6 +++--- apps/rbac/permissions.py | 8 +++++--- apps/rbac/tree.py | 8 +++++++- apps/tickets/api/comment.py | 3 +++ apps/tickets/api/relation.py | 3 +++ apps/tickets/api/ticket.py | 8 ++++++-- 6 files changed, 27 insertions(+), 9 deletions(-) diff --git a/apps/rbac/const.py b/apps/rbac/const.py index a3b69c33a..ff2534e72 100644 --- a/apps/rbac/const.py +++ b/apps/rbac/const.py @@ -62,12 +62,12 @@ 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'), diff --git a/apps/rbac/permissions.py b/apps/rbac/permissions.py index dc1260d67..877cf06b2 100644 --- a/apps/rbac/permissions.py +++ b/apps/rbac/permissions.py @@ -69,13 +69,16 @@ class RBACPermission(permissions.DjangoModelPermissions): 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 +99,6 @@ class RBACPermission(permissions.DjangoModelPermissions): :param view: :return: """ - model_cls = self.get_model_cls(view) action = getattr(view, 'action', None) if not action: diff --git a/apps/rbac/tree.py b/apps/rbac/tree.py index 8b8b23c4f..ff7027db0 100644 --- a/apps/rbac/tree.py +++ b/apps/rbac/tree.py @@ -104,11 +104,13 @@ 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"), } @@ -279,13 +281,17 @@ 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: action_name = self.action_mapper[action] name = action_name + content_types_name_mapper[app_model] else: name = gettext(p.name) - icon = self.action_icon.get(action, 'file') name = name.replace('Can ', '').replace('可以', '') return name, icon diff --git a/apps/tickets/api/comment.py b/apps/tickets/api/comment.py index 3bdf55079..ab0584eed 100644 --- a/apps/tickets/api/comment.py +++ b/apps/tickets/api/comment.py @@ -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): diff --git a/apps/tickets/api/relation.py b/apps/tickets/api/relation.py index cbb661259..2dfa33146 100644 --- a/apps/tickets/api/relation.py +++ b/apps/tickets/api/relation.py @@ -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(): diff --git a/apps/tickets/api/ticket.py b/apps/tickets/api/ticket.py index f112dae0c..a7e4fa485 100644 --- a/apps/tickets/api/ticket.py +++ b/apps/tickets/api/ticket.py @@ -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) From efb26132f6b3ba9647a5aca4751893204983a887 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 16 Mar 2022 17:03:16 +0800 Subject: [PATCH 06/23] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dsso=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E7=99=BB=E5=BD=95=E5=A4=B1=E8=B4=A5=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/api/sso.py | 2 +- apps/authentication/backends/sso.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/authentication/api/sso.py b/apps/authentication/api/sso.py index 11f76d633..88d9707db 100644 --- a/apps/authentication/api/sso.py +++ b/apps/authentication/api/sso.py @@ -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) diff --git a/apps/authentication/backends/sso.py b/apps/authentication/backends/sso.py index 86d8f76e1..7bee484dc 100644 --- a/apps/authentication/backends/sso.py +++ b/apps/authentication/backends/sso.py @@ -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): """ 什么也不做呀😺 """ From 7eed7b32cca390960278c35183ab755fafac2b42 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 16 Mar 2022 15:59:52 +0800 Subject: [PATCH 07/23] =?UTF-8?q?perf:=20=E4=BF=AE=E5=A4=8D=20org=20role?= =?UTF-8?q?=20binding=20=E5=9C=A8root=E7=BB=84=E7=BB=87=E4=B8=8B=E7=9C=8B?= =?UTF-8?q?=E5=88=B0=E7=9A=84=E5=8F=AF=E8=83=BD=E4=B8=8D=E5=AF=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/rbac/api/rolebinding.py | 18 +++++++++++++---- apps/rbac/const.py | 1 - apps/rbac/models/rolebinding.py | 29 ++++++++++++++++++++-------- apps/rbac/serializers/rolebinding.py | 4 ++-- 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/apps/rbac/api/rolebinding.py b/apps/rbac/api/rolebinding.py index 677ef30bf..0dd431220 100644 --- a/apps/rbac/api/rolebinding.py +++ b/apps/rbac/api/rolebinding.py @@ -22,9 +22,10 @@ class RoleBindingViewSet(OrgBulkModelViewSet): 'user__name', 'user__username', 'role__name' ] - def get_queryset(self): - queryset = super().get_queryset() \ - .prefetch_related('user', 'role') \ + @staticmethod + def annotate_queryset(queryset): + queryset = queryset \ + .prefetch_related('user', 'role', 'org') \ .annotate( user_display=Concat( F('user__name'), Value('('), @@ -34,6 +35,11 @@ class RoleBindingViewSet(OrgBulkModelViewSet): ) return queryset + def get_queryset(self): + queryset = super().get_queryset() + queryset = self.annotate_queryset(queryset) + return queryset + class SystemRoleBindingViewSet(RoleBindingViewSet): model = SystemRoleBinding @@ -49,9 +55,13 @@ class SystemRoleBindingViewSet(RoleBindingViewSet): class OrgRoleBindingViewSet(RoleBindingViewSet): - model = OrgRoleBinding serializer_class = serializers.OrgRoleBindingSerializer + def get_queryset(self): + queryset = OrgRoleBinding.objects.root_all() + queryset = self.annotate_queryset(queryset) + return queryset + def perform_bulk_create(self, serializer): validated_data = serializer.validated_data bindings = [ diff --git a/apps/rbac/const.py b/apps/rbac/const.py index ff2534e72..2bac12c5d 100644 --- a/apps/rbac/const.py +++ b/apps/rbac/const.py @@ -103,7 +103,6 @@ only_system_permissions = ( ('terminal', 'replaystorage', '*', '*'), ('terminal', 'status', '*', '*'), ('terminal', 'task', '*', '*'), - ('tickets', '*', '*', '*'), ('authentication', '*', '*', '*'), ) diff --git a/apps/rbac/models/rolebinding.py b/apps/rbac/models/rolebinding.py index 3aa04955d..f7ee3881a 100644 --- a/apps/rbac/models/rolebinding.py +++ b/apps/rbac/models/rolebinding.py @@ -15,12 +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) + q = Q(scope=Scope.system, org__isnull=True) if not current_org.is_root(): 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 @@ -53,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) @@ -65,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) @@ -84,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 @@ -118,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 diff --git a/apps/rbac/serializers/rolebinding.py b/apps/rbac/serializers/rolebinding.py index 75f0ed903..cfbf248b8 100644 --- a/apps/rbac/serializers/rolebinding.py +++ b/apps/rbac/serializers/rolebinding.py @@ -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")} } From f41e6db007a0595b4c9000c95d00df815148cb9d Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 16 Mar 2022 16:26:59 +0800 Subject: [PATCH 08/23] =?UTF-8?q?perf:=20sso=20token=20=E5=8F=AA=E8=83=BD?= =?UTF-8?q?=E8=B6=85=E7=BA=A7=E7=AE=A1=E7=90=86=E5=91=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/rbac/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/rbac/const.py b/apps/rbac/const.py index 2bac12c5d..1ba3d1802 100644 --- a/apps/rbac/const.py +++ b/apps/rbac/const.py @@ -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', '*', '*'), From ee757e261dae0b0619ccbdfdd876a9e804c8aec8 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 16 Mar 2022 16:31:06 +0800 Subject: [PATCH 09/23] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E5=86=99?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/rbac/api/rolebinding.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/apps/rbac/api/rolebinding.py b/apps/rbac/api/rolebinding.py index 0dd431220..f7ad47351 100644 --- a/apps/rbac/api/rolebinding.py +++ b/apps/rbac/api/rolebinding.py @@ -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): @@ -22,9 +25,8 @@ class RoleBindingViewSet(OrgBulkModelViewSet): 'user__name', 'user__username', 'role__name' ] - @staticmethod - def annotate_queryset(queryset): - queryset = queryset \ + def get_queryset(self): + queryset = self._get_queryset()\ .prefetch_related('user', 'role', 'org') \ .annotate( user_display=Concat( @@ -35,10 +37,8 @@ class RoleBindingViewSet(OrgBulkModelViewSet): ) return queryset - def get_queryset(self): - queryset = super().get_queryset() - queryset = self.annotate_queryset(queryset) - return queryset + def _get_queryset(self): + return super().get_queryset() class SystemRoleBindingViewSet(RoleBindingViewSet): @@ -57,10 +57,8 @@ class SystemRoleBindingViewSet(RoleBindingViewSet): class OrgRoleBindingViewSet(RoleBindingViewSet): serializer_class = serializers.OrgRoleBindingSerializer - def get_queryset(self): - queryset = OrgRoleBinding.objects.root_all() - queryset = self.annotate_queryset(queryset) - return queryset + def _get_queryset(self): + return OrgRoleBinding.objects.root_all() def perform_bulk_create(self, serializer): validated_data = serializer.validated_data From 3a26b9d10284699af577f9d6fd621536d1b9ad00 Mon Sep 17 00:00:00 2001 From: feng626 <1304903146@qq.com> Date: Wed, 16 Mar 2022 16:21:00 +0800 Subject: [PATCH 10/23] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=B7=A5?= =?UTF-8?q?=E5=8D=95=E7=9B=B8=E5=BA=94bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/applications/api/application.py | 2 +- apps/common/drf/metadata.py | 1 + apps/rbac/permissions.py | 9 ++++++--- apps/tickets/api/ticket.py | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/applications/api/application.py b/apps/applications/api/application.py index 6d98123bc..435ccccad 100644 --- a/apps/applications/api/application.py +++ b/apps/applications/api/application.py @@ -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') diff --git a/apps/common/drf/metadata.py b/apps/common/drf/metadata.py index 3f721bbea..59561e978 100644 --- a/apps/common/drf/metadata.py +++ b/apps/common/drf/metadata.py @@ -32,6 +32,7 @@ class SimpleMetadataWithFilters(SimpleMetadata): the fields that are accepted for 'PUT' and 'POST' methods. """ actions = {} + view.raw_action = view.action for method in self.methods & set(view.allowed_methods): if hasattr(view, 'action_map'): view.action = view.action_map.get(method.lower(), view.action) diff --git a/apps/rbac/permissions.py b/apps/rbac/permissions.py index 877cf06b2..7611698b6 100644 --- a/apps/rbac/permissions.py +++ b/apps/rbac/permissions.py @@ -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,9 +63,11 @@ 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): @@ -116,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) diff --git a/apps/tickets/api/ticket.py b/apps/tickets/api/ticket.py index a7e4fa485..8e7923e8e 100644 --- a/apps/tickets/api/ticket.py +++ b/apps/tickets/api/ticket.py @@ -35,7 +35,7 @@ class TicketViewSet(CommonApiMixin, viewsets.ModelViewSet): ) ordering = ('-date_created',) rbac_perms = { - 'open': 'tickets.view_ticket' + 'open': 'tickets.view_ticket', } def create(self, request, *args, **kwargs): From bbdeba365972d01e751b323b9f891a64d7d84b80 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 16 Mar 2022 17:22:30 +0800 Subject: [PATCH 11/23] =?UTF-8?q?perf:=20=E4=BF=AE=E5=A4=8D=20org=20admin?= =?UTF-8?q?=20all?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/zh/LC_MESSAGES/django.mo | 4 ++-- apps/locale/zh/LC_MESSAGES/django.po | 2 +- apps/orgs/models.py | 33 ++++++++++++---------------- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 72474d430..29f57f55b 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:a8c1155ea28b70a0eb06aa39ab6ae04619cd30d02f59698fadaa6068d91a7900 -size 104348 +oid sha256:f529bbca004aeba7532d9faf50f6f8ab5532b19bf0afd650f8360f418c03c15c +size 104629 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index fe7b2de2d..8ae493524 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -2804,7 +2804,7 @@ msgstr "汇总" #: ops/models/adhoc.py:339 msgid "AdHoc execution" -msgstr "任务执行历史" +msgstr "任务执行" #: ops/models/command.py:32 msgid "Date finished" diff --git a/apps/orgs/models.py b/apps/orgs/models.py index 2daa2bd3f..0b4795aa7 100644 --- a/apps/orgs/models.py +++ b/apps/orgs/models.py @@ -112,7 +112,8 @@ class Organization(models.Model): role_id = role.id with tmp_to_org(self): defaults = { - 'user': user, 'role_id': role_id, 'org_id': self.id, 'scope': 'org' + 'user': user, 'role_id': role_id, + 'org_id': self.id, 'scope': 'org' } self.members.through.objects.update_or_create(**defaults, defaults=defaults) @@ -162,25 +163,19 @@ class Organization(models.Model): self.delete_related_models() return super().delete(*args, **kwargs) + @property + def admin(self): + from rbac.models import OrgRoleBinding + from users.models import User + from rbac.builtin import BuiltinRole + from .utils import tmp_to_org -# 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") + role_org_admin = BuiltinRole.org_admin.get_role() + with tmp_to_org(self): + org_admins = OrgRoleBinding.get_role_users(role_org_admin) + if not org_admins: + org_admins = User.objects.filter(username='admin') + return org_admins class OrganizationMember(models.Model): From 1ce2706f20e1527e4b41fc102a239413f88ca48b Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 16 Mar 2022 17:38:20 +0800 Subject: [PATCH 12/23] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E7=BF=BB?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/zh/LC_MESSAGES/django.po | 94 +++++++++++++++------------- apps/orgs/models.py | 2 +- apps/rbac/tree.py | 1 + 3 files changed, 51 insertions(+), 46 deletions(-) diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 8ae493524..7bc35a968 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-15 19:46+0800\n" +"POT-Creation-Date: 2022-03-16 17:35+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -22,7 +22,7 @@ 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 @@ -56,7 +56,7 @@ 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 @@ -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:191 perms/models/base.py:84 +#: rbac/builtin.py:97 rbac/models/rolebinding.py:33 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:14 orgs/models.py:194 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:195 msgid "Date updated" msgstr "更新日期" @@ -627,7 +627,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:13 -#: orgs/models.py:201 perms/models/base.py:91 users/models/user.py:619 +#: orgs/models.py:196 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 "系统" @@ -1383,7 +1383,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:161 users/templates/users/user_asset_permission.html:128 #: users/templates/users/user_database_app_permission.html:111 msgid "Delete" msgstr "删除" @@ -1437,11 +1437,11 @@ msgstr "文件管理" #: audits/models.py:55 #: authentication/templates/authentication/_access_key_modal.html:22 -#: rbac/tree.py:155 +#: rbac/tree.py:158 msgid "Create" msgstr "创建" -#: audits/models.py:56 rbac/tree.py:157 templates/_csv_import_export.html:18 +#: audits/models.py:56 rbac/tree.py:160 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 @@ -2883,7 +2883,7 @@ 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/models.py:188 rbac/const.py:7 rbac/models/rolebinding.py:40 #: rbac/serializers/rolebinding.py:40 tickets/serializers/ticket/ticket.py:77 msgid "Organization" msgstr "组织" @@ -2896,7 +2896,7 @@ msgstr "全局组织" msgid "Can view root org" msgstr "可以查看全局组织" -#: orgs/models.py:198 rbac/models/role.py:46 rbac/models/rolebinding.py:38 +#: orgs/models.py:193 rbac/models/role.py:46 rbac/models/rolebinding.py:36 #: users/models/user.py:584 users/templates/users/_select_user_modal.html:15 msgid "Role" msgstr "角色" @@ -3181,7 +3181,7 @@ msgstr "文件管理" msgid "Permission" msgstr "授权" -#: rbac/models/role.py:31 rbac/models/rolebinding.py:32 +#: rbac/models/role.py:31 rbac/models/rolebinding.py:30 msgid "Scope" msgstr "范围" @@ -3201,21 +3201,21 @@ msgstr "系统角色" msgid "Organization role" msgstr "组织角色" -#: rbac/models/rolebinding.py:47 +#: rbac/models/rolebinding.py:45 msgid "Role binding" msgstr "角色绑定" -#: rbac/models/rolebinding.py:113 +#: rbac/models/rolebinding.py:111 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:118 msgid "Organization role binding" msgstr "组织角色绑定" -#: rbac/models/rolebinding.py:134 +#: rbac/models/rolebinding.py:132 msgid "System role binding" msgstr "系统角色绑定" @@ -3307,11 +3307,19 @@ msgstr "我的应用" msgid "Ticket comment" msgstr "工单评论" -#: rbac/tree.py:113 +#: rbac/tree.py:113 tickets/models/ticket.py:163 +msgid "Ticket" +msgstr "工单管理" + +#: rbac/tree.py:114 msgid "Common setting" msgstr "一般设置" -#: rbac/tree.py:156 +#: rbac/tree.py:115 +msgid "Execute batch command" +msgstr "执行批量命令" + +#: rbac/tree.py:159 msgid "View" msgstr "查看" @@ -5363,10 +5371,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 +5678,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 "用户密码历史" @@ -6807,11 +6811,11 @@ msgstr "退出页面logo" msgid "Interface setting" msgstr "界面设置" -#: xpack/plugins/license/api.py:43 +#: xpack/plugins/license/api.py:41 msgid "License import successfully" msgstr "许可证导入成功" -#: xpack/plugins/license/api.py:44 +#: xpack/plugins/license/api.py:42 msgid "License is invalid" msgstr "无效的许可证" diff --git a/apps/orgs/models.py b/apps/orgs/models.py index 0b4795aa7..a7ae90e9f 100644 --- a/apps/orgs/models.py +++ b/apps/orgs/models.py @@ -164,7 +164,7 @@ class Organization(models.Model): return super().delete(*args, **kwargs) @property - def admin(self): + def admins(self): from rbac.models import OrgRoleBinding from users.models import User from rbac.builtin import BuiltinRole diff --git a/apps/rbac/tree.py b/apps/rbac/tree.py index ff7027db0..75c70026c 100644 --- a/apps/rbac/tree.py +++ b/apps/rbac/tree.py @@ -112,6 +112,7 @@ verbose_name_mapper = { 'tickets.comment': _("Ticket comment"), 'tickets.view_ticket': _("Ticket"), 'settings.setting': _("Common setting"), + 'ops.add_commandexecution': _('Execute batch command') } xpack_nodes = [ From da9136f7af8237611f23f5164c2a149ecc5000c1 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 16 Mar 2022 17:50:07 +0800 Subject: [PATCH 13/23] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20org=20role?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/orgs/models.py | 84 ++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/apps/orgs/models.py b/apps/orgs/models.py index a7ae90e9f..057c73ecf 100644 --- a/apps/orgs/models.py +++ b/apps/orgs/models.py @@ -7,7 +7,59 @@ 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 + } + role = role_mapper.get(role_name) + 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,22 +153,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,20 +199,6 @@ class Organization(models.Model): self.delete_related_models() return super().delete(*args, **kwargs) - @property - def admins(self): - from rbac.models import OrgRoleBinding - from users.models import User - from rbac.builtin import BuiltinRole - from .utils import tmp_to_org - - role_org_admin = BuiltinRole.org_admin.get_role() - with tmp_to_org(self): - org_admins = OrgRoleBinding.get_role_users(role_org_admin) - if not org_admins: - org_admins = User.objects.filter(username='admin') - return org_admins - class OrganizationMember(models.Model): """ From 580d2cd80b059ec2074b740f0e578edf8570e67d Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 16 Mar 2022 17:53:06 +0800 Subject: [PATCH 14/23] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20org=20admin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/orgs/models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/orgs/models.py b/apps/orgs/models.py index 057c73ecf..def83f509 100644 --- a/apps/orgs/models.py +++ b/apps/orgs/models.py @@ -37,7 +37,8 @@ class OrgRoleMixin: 'auditor': BuiltinRole.org_auditor, 'admin': BuiltinRole.org_admin } - role = role_mapper.get(role_name) + 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 From 04b35ba520de9699a06a1f13f06b018dc103103c Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 16 Mar 2022 18:27:05 +0800 Subject: [PATCH 15/23] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E5=91=BD=E4=BB=A4=E6=9D=83=E9=99=90=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/audits/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/audits/api.py b/apps/audits/api.py index d57682ee3..8b30451a6 100644 --- a/apps/audits/api.py +++ b/apps/audits/api.py @@ -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): From aa9ae14e465a3b06dca2862fab8eef4d3ec7c423 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 16 Mar 2022 18:32:34 +0800 Subject: [PATCH 16/23] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dview=20action?= =?UTF-8?q?=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/drf/metadata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/common/drf/metadata.py b/apps/common/drf/metadata.py index 59561e978..569854722 100644 --- a/apps/common/drf/metadata.py +++ b/apps/common/drf/metadata.py @@ -32,7 +32,7 @@ class SimpleMetadataWithFilters(SimpleMetadata): the fields that are accepted for 'PUT' and 'POST' methods. """ actions = {} - view.raw_action = view.action + 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) From 0fbc548c0221b712430d258136dc5808c776b063 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 16 Mar 2022 18:52:22 +0800 Subject: [PATCH 17/23] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=20flower=20=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jumpserver/views/celery_flower.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/jumpserver/views/celery_flower.py b/apps/jumpserver/views/celery_flower.py index abc288bf2..3d98d3bef 100644 --- a/apps/jumpserver/views/celery_flower.py +++ b/apps/jumpserver/views/celery_flower.py @@ -16,7 +16,7 @@ __all__ = ['celery_flower_view'] def celery_flower_view(request, path): 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: From 8233c690380da3428d422b00e1a23bf047bd194f Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 16 Mar 2022 19:25:06 +0800 Subject: [PATCH 18/23] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dadhoc=E6=9D=83?= =?UTF-8?q?=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/api/adhoc.py | 3 +++ apps/rbac/const.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/ops/api/adhoc.py b/apps/ops/api/adhoc.py index 3bb1acb53..0cc7b6d55 100644 --- a/apps/ops/api/adhoc.py +++ b/apps/ops/api/adhoc.py @@ -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() diff --git a/apps/rbac/const.py b/apps/rbac/const.py index 1ba3d1802..ea54c2474 100644 --- a/apps/rbac/const.py +++ b/apps/rbac/const.py @@ -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'), From 3b507dc7953285792db8ad81f7cea314d9309bba Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 16 Mar 2022 20:27:38 +0800 Subject: [PATCH 19/23] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E8=8B=B1?= =?UTF-8?q?=E6=96=87=E4=B8=8B=E6=A0=91=E7=9A=84=E6=98=BE=E7=A4=BA=20(#7883?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * perf: 优化英文下树的显示 * perf: 修改翻译 * perf: 修改翻译 Co-authored-by: ibuler --- apps/locale/zh/LC_MESSAGES/django.po | 122 +++++++++++++++------------ apps/rbac/builtin.py | 1 + apps/rbac/tree.py | 24 ++++-- 3 files changed, 85 insertions(+), 62 deletions(-) diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 7bc35a968..6e26ba466 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 17:35+0800\n" +"POT-Creation-Date: 2022-03-16 19:59+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -26,7 +26,7 @@ msgstr "访问控制" #: 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 @@ -62,7 +62,7 @@ msgstr "激活中" #: 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,8 +89,8 @@ 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:191 perms/models/base.py:84 -#: rbac/builtin.py:97 rbac/models/rolebinding.py:33 templates/index.html:78 +#: authentication/models.py:50 orgs/models.py:214 perms/models/base.py:84 +#: rbac/builtin.py:98 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 @@ -375,7 +375,7 @@ 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:194 perms/models/base.py:92 +#: 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" @@ -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:195 +#: 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:196 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 @@ -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:161 users/templates/users/user_asset_permission.html:128 +#: rbac/tree.py:160 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:158 +#: rbac/tree.py:157 msgid "Create" msgstr "创建" -#: audits/models.py:56 rbac/tree.py:160 templates/_csv_import_export.html:18 +#: audits/models.py:56 rbac/tree.py:159 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 "用户名称" @@ -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:188 rbac/const.py:7 rbac/models/rolebinding.py:40 +#: 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:193 rbac/models/role.py:46 rbac/models/rolebinding.py:36 +#: 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 "角色" @@ -3121,7 +3122,7 @@ msgstr "角色已绑定用户,不能删除" msgid "Internal role, can't be update" 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 "组织用户" @@ -3181,7 +3182,7 @@ msgstr "文件管理" msgid "Permission" msgstr "授权" -#: rbac/models/role.py:31 rbac/models/rolebinding.py:30 +#: 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:45 +#: rbac/models/rolebinding.py:51 msgid "Role binding" msgstr "角色绑定" -#: rbac/models/rolebinding.py:111 +#: 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:118 +#: rbac/models/rolebinding.py:130 msgid "Organization role binding" msgstr "组织角色绑定" -#: rbac/models/rolebinding.py:132 +#: 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,87 +3240,87 @@ 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:113 tickets/models/ticket.py:163 +#: rbac/tree.py:112 tickets/models/ticket.py:163 msgid "Ticket" msgstr "工单管理" -#: rbac/tree.py:114 +#: rbac/tree.py:113 msgid "Common setting" msgstr "一般设置" -#: rbac/tree.py:115 +#: rbac/tree.py:114 msgid "Execute batch command" msgstr "执行批量命令" -#: rbac/tree.py:159 +#: rbac/tree.py:158 msgid "View" msgstr "查看" @@ -6839,6 +6840,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 "可以连接我的资产" diff --git a/apps/rbac/builtin.py b/apps/rbac/builtin.py index 0fe12195e..1ed528a78 100644 --- a/apps/rbac/builtin.py +++ b/apps/rbac/builtin.py @@ -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 + ( diff --git a/apps/rbac/tree.py b/apps/rbac/tree.py index 75c70026c..d81551168 100644 --- a/apps/rbac/tree.py +++ b/apps/rbac/tree.py @@ -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 @@ -155,10 +154,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', @@ -178,6 +177,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): @@ -288,12 +288,18 @@ class PermissionTreeUtil: 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) - name = name.replace('Can ', '').replace('可以', '') + name = name.replace('Can ', '').replace('可以', '').capitalize() return name, icon def _create_perms_nodes(self): From 433d829c292841c5836d1548a2b43d56fc1b72a0 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 16 Mar 2022 20:36:12 +0800 Subject: [PATCH 20/23] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0profile=20myorgs?= =?UTF-8?q?=20(#7887)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/users/models/user.py | 4 ++++ apps/users/serializers/profile.py | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/users/models/user.py b/apps/users/models/user.py index 3ccf02fc9..67efa8b3c 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -790,6 +790,10 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser): orgs = [Organization.root()] + orgs return orgs + @property + def my_orgs(self): + return list(self.orgs.all().distinct()) + class Meta: ordering = ['username'] verbose_name = _("User") diff --git a/apps/users/serializers/profile.py b/apps/users/serializers/profile.py index 3434260e6..55083c23d 100644 --- a/apps/users/serializers/profile.py +++ b/apps/users/serializers/profile.py @@ -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', From aa022a02c151b03bc45ee1ee85c79e442ae667b5 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 16 Mar 2022 20:41:54 +0800 Subject: [PATCH 21/23] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E8=AE=A4=E8=AF=81=E5=A4=B1=E8=B4=A5=E7=9A=84=E8=AF=A6?= =?UTF-8?q?=E7=BB=86=E4=BF=A1=E6=81=AF=E6=98=BE=E7=A4=BA=20(#7886)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 修复用户认证失败的详细信息显示 * fix: 更新授权树翻译 Co-authored-by: Jiangjie.Bai Co-authored-by: Jiangjie.Bai <32935519+BaiJiangJie@users.noreply.github.com> --- .../migrations/0020_auto_20220316_2028.py | 18 ++++++++++++ apps/authentication/backends/base.py | 6 ++-- apps/locale/zh/LC_MESSAGES/django.po | 29 ++++++++++--------- .../migrations/0028_auto_20220316_2028.py | 18 ++++++++++++ apps/rbac/tree.py | 1 + 5 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 apps/applications/migrations/0020_auto_20220316_2028.py create mode 100644 apps/perms/migrations/0028_auto_20220316_2028.py diff --git a/apps/applications/migrations/0020_auto_20220316_2028.py b/apps/applications/migrations/0020_auto_20220316_2028.py new file mode 100644 index 000000000..3eeedf2d6 --- /dev/null +++ b/apps/applications/migrations/0020_auto_20220316_2028.py @@ -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'), + ), + ] diff --git a/apps/authentication/backends/base.py b/apps/authentication/backends/base.py index 12b978250..64faf3334 100644 --- a/apps/authentication/backends/base.py +++ b/apps/authentication/backends/base.py @@ -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): diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 6e26ba466..7922f9a31 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 19:59+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 \n" "Language-Team: JumpServer team\n" @@ -90,7 +90,7 @@ 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:98 rbac/models/rolebinding.py:39 templates/index.html:78 +#: 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 @@ -1384,7 +1384,7 @@ msgstr "日志审计" #: audits/models.py:27 audits/models.py:57 #: authentication/templates/authentication/_access_key_modal.html:65 -#: rbac/tree.py:160 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 "删除" @@ -1438,11 +1438,11 @@ msgstr "文件管理" #: audits/models.py:55 #: authentication/templates/authentication/_access_key_modal.html:22 -#: rbac/tree.py:157 +#: rbac/tree.py:159 msgid "Create" msgstr "创建" -#: audits/models.py:56 rbac/tree.py:159 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 @@ -3180,7 +3180,7 @@ msgstr "文件管理" #: rbac/models/permission.py:26 msgid "Permission" -msgstr "授权" +msgstr "权限" #: rbac/models/role.py:31 rbac/models/rolebinding.py:36 msgid "Scope" @@ -3316,11 +3316,15 @@ msgstr "工单管理" msgid "Common setting" msgstr "一般设置" -#: rbac/tree.py:114 +#: rbac/tree.py:115 +msgid "View permission tree" +msgstr "查看授权树" + +#: rbac/tree.py:116 msgid "Execute batch command" msgstr "执行批量命令" -#: rbac/tree.py:158 +#: rbac/tree.py:160 msgid "View" msgstr "查看" @@ -6182,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' 必须是 [{}]" @@ -6812,11 +6816,11 @@ msgstr "退出页面logo" msgid "Interface setting" msgstr "界面设置" -#: xpack/plugins/license/api.py:41 +#: xpack/plugins/license/api.py:43 msgid "License import successfully" msgstr "许可证导入成功" -#: xpack/plugins/license/api.py:42 +#: xpack/plugins/license/api.py:44 msgid "License is invalid" msgstr "无效的许可证" @@ -7032,9 +7036,6 @@ msgstr "社区版" #~ msgid "Overview" #~ msgstr "概览" -#~ msgid "View permission user" -#~ msgstr "查看授权用户" - #~ msgid "Add user to role" #~ msgstr "添加用户到角色" diff --git a/apps/perms/migrations/0028_auto_20220316_2028.py b/apps/perms/migrations/0028_auto_20220316_2028.py new file mode 100644 index 000000000..a1a71e5f2 --- /dev/null +++ b/apps/perms/migrations/0028_auto_20220316_2028.py @@ -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'), + ), + ] diff --git a/apps/rbac/tree.py b/apps/rbac/tree.py index d81551168..b8bd2407e 100644 --- a/apps/rbac/tree.py +++ b/apps/rbac/tree.py @@ -111,6 +111,7 @@ verbose_name_mapper = { 'tickets.comment': _("Ticket comment"), 'tickets.view_ticket': _("Ticket"), 'settings.setting': _("Common setting"), + 'rbac.view_permission': _('View permission tree'), 'ops.add_commandexecution': _('Execute batch command') } From 30556023d10050213de06b6a3d5c89078eb834c6 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 16 Mar 2022 19:56:11 +0800 Subject: [PATCH 22/23] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=BC=9A?= =?UTF-8?q?=E8=AF=9D=E5=BD=95=E5=83=8F=E6=92=AD=E6=94=BE=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/api/session.py | 2 +- utils/clean_db_content_types.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/apps/terminal/api/session.py b/apps/terminal/api/session.py index 949ac8d09..c78d48383 100644 --- a/apps/terminal/api/session.py +++ b/apps/terminal/api/session.py @@ -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 diff --git a/utils/clean_db_content_types.py b/utils/clean_db_content_types.py index f0ce20cd3..d8c05db22 100644 --- a/utils/clean_db_content_types.py +++ b/utils/clean_db_content_types.py @@ -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'), From 1a05a942c2c2e42f5594800862c6c8ad42bef992 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Wed, 16 Mar 2022 20:48:26 +0800 Subject: [PATCH 23/23] =?UTF-8?q?fix:=20=E6=9B=B4=E6=96=B0=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=E8=AF=A6=E6=83=85=E6=8E=88=E6=9D=83=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/asset.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/assets/api/asset.py b/apps/assets/api/asset.py index bec662c63..79e5a451d 100644 --- a/apps/assets/api/asset.py +++ b/apps/assets/api/asset.py @@ -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()