From a2376d3afd9f441f4ed00d971cb7f15f0931cf9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AB=E5=8D=83=E6=B5=81?= <40739051+jym503558564@users.noreply.github.com> Date: Thu, 12 Sep 2019 18:56:26 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B6=85=E7=BA=A7=E7=AE=A1=E7=90=86=E5=91=98?= =?UTF-8?q?=E5=8F=AF=E5=88=9B=E5=BB=BA=E8=B6=85=E7=BA=A7=E5=AE=A1=E8=AE=A1?= =?UTF-8?q?=E5=91=98=E5=B9=B6=E5=8F=AF=E8=AE=BE=E7=BD=AE=E5=AE=A1=E8=AE=A1?= =?UTF-8?q?=E5=91=98=E4=B8=BA=E7=BB=84=E7=BB=87=E5=AE=A1=E8=AE=A1=E5=91=98?= =?UTF-8?q?=20(#3141)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Update] 超级管理员可创建超级审计员并可设置审计员为组织审计员 * [Update] 修改小问题 * [Update] 修改普通用户角色可以是组织审计员 * [Update] 更改组织审计员切换组织问题 * [Update] 修改小问题 * [Update] 普通用户是组织审计员的页面左侧栏显示 * [Update] 修改删除权限问题和组织显示问题 * [Update] 优化逻辑 * [Update] 优化类名 * [Update] 修改小问题 * [Update] 优化逻辑 * [Update] 优化切换到某一个组织逻辑 * [Update] 修改用户详情页的 删除/更新 按钮是否可点击 * [Update] 优化代码 * [Update] 组织管理列表增加审计员显示 * [Update] 优化代码细节 * [Update] 优化权限类逻辑 * [Update] 优化导航菜单控制 * [Update] 优化页面控制逻辑 * [Update] 修改变量名错误问题 * [Update] 修改页面上的小问题 * [Update] 审计员或组织审计员能够更新个人部分信息 * [Update] 用户名为admin的用户不能被删除 * [Update] 不同用户在不同组织下扮演不同角色的权限不同,为了避免切换组织时出现403,重定向到index * [Update] 一个用户在同一个组织既是管理员又是审计员,隐藏个人信息模块,仅当是审计员,在当前组织显示个人信息模块 * [Update] 修改方法命名 * [Update] 优化代码细节 * [Update] 修改命令执行列表方法 * [Update] 优化用户之间操作的权限逻辑;添加 UserModel 的 property 属性;修改 Organization 的 related name 名称; * [Update] 修改OrgProcessor Anonymous问题 * [Update] 修改用户序列类校验组织和转换raw密码的逻辑 --- apps/audits/api.py | 4 +- apps/audits/views.py | 35 +-- apps/common/permissions.py | 120 +++++---- apps/jumpserver/views.py | 12 +- apps/ops/views/celery.py | 4 +- apps/ops/views/command.py | 4 +- apps/orgs/api.py | 2 +- apps/orgs/context_processor.py | 6 +- apps/orgs/middleware.py | 13 +- apps/orgs/models.py | 75 +++++- apps/orgs/serializers.py | 1 + apps/orgs/views.py | 26 +- apps/perms/forms/asset_permission.py | 2 +- apps/perms/forms/remote_app_permission.py | 2 +- apps/perms/views/asset_permission.py | 13 +- apps/perms/views/remote_app_permission.py | 12 +- apps/templates/_header_bar.html | 22 +- apps/templates/_left_side_bar.html | 8 +- apps/templates/_nav.html | 285 +++++++++++--------- apps/templates/_nav_audits.html | 31 --- apps/templates/_user_profile.html | 66 ++--- apps/terminal/api/command.py | 4 +- apps/terminal/api/session.py | 6 +- apps/terminal/views/command.py | 4 +- apps/terminal/views/session.py | 6 +- apps/users/api/user.py | 36 +-- apps/users/forms.py | 2 +- apps/users/models/user.py | 75 ++++-- apps/users/serializers/v1.py | 55 +++- apps/users/templates/users/_user.html | 16 +- apps/users/templates/users/user_detail.html | 80 +++--- apps/users/templates/users/user_list.html | 4 +- apps/users/views/group.py | 3 +- apps/users/views/user.py | 11 +- 34 files changed, 611 insertions(+), 434 deletions(-) delete mode 100644 apps/templates/_nav_audits.html diff --git a/apps/audits/api.py b/apps/audits/api.py index daf111ed8..626749b29 100644 --- a/apps/audits/api.py +++ b/apps/audits/api.py @@ -3,7 +3,7 @@ from rest_framework import viewsets -from common.permissions import IsOrgAdminOrAppUser, IsAuditor +from common.permissions import IsOrgAdminOrAppUser, IsOrgAuditor from .models import FTPLog from .serializers import FTPLogSerializer @@ -11,4 +11,4 @@ from .serializers import FTPLogSerializer class FTPLogViewSet(viewsets.ModelViewSet): queryset = FTPLog.objects.all() serializer_class = FTPLogSerializer - permission_classes = (IsOrgAdminOrAppUser | IsAuditor,) + permission_classes = (IsOrgAdminOrAppUser | IsOrgAuditor,) diff --git a/apps/audits/views.py b/apps/audits/views.py index 8c9b6467d..13b0031d0 100644 --- a/apps/audits/views.py +++ b/apps/audits/views.py @@ -18,8 +18,9 @@ from django.db.models import Q from audits.utils import get_excel_response, write_content_to_excel from common.mixins import DatetimeSearchMixin -from common.permissions import PermissionsMixin, IsOrgAdmin, IsAuditor, IsValidUser - +from common.permissions import ( + PermissionsMixin, IsOrgAdmin, IsValidUser, IsOrgAuditor +) from orgs.utils import current_org from ops.views import CommandExecutionListView as UserCommandExecutionListView from .models import FTPLog, OperateLog, PasswordChangeLog, UserLoginLog @@ -47,7 +48,7 @@ class FTPLogListView(PermissionsMixin, DatetimeSearchMixin, ListView): paginate_by = settings.DISPLAY_PER_PAGE user = asset = system_user = filename = '' date_from = date_to = None - permission_classes = [IsOrgAdmin | IsAuditor] + permission_classes = [IsOrgAdmin | IsOrgAuditor] def get_queryset(self): self.queryset = super().get_queryset() @@ -96,7 +97,7 @@ class OperateLogListView(PermissionsMixin, DatetimeSearchMixin, ListView): user = action = resource_type = '' date_from = date_to = None actions_dict = dict(OperateLog.ACTION_CHOICES) - permission_classes = [IsOrgAdmin | IsAuditor] + permission_classes = [IsOrgAdmin | IsOrgAuditor] def get_queryset(self): self.queryset = super().get_queryset() @@ -119,7 +120,7 @@ class OperateLogListView(PermissionsMixin, DatetimeSearchMixin, ListView): def get_context_data(self, **kwargs): context = { - 'user_list': current_org.get_org_users(), + 'user_list': current_org.get_org_members(), 'actions': self.actions_dict, 'resource_type_list': get_resource_type_list(), 'date_from': self.date_from, @@ -139,10 +140,10 @@ class PasswordChangeLogList(PermissionsMixin, DatetimeSearchMixin, ListView): paginate_by = settings.DISPLAY_PER_PAGE user = '' date_from = date_to = None - permission_classes = [IsOrgAdmin | IsAuditor] + permission_classes = [IsOrgAdmin | IsOrgAuditor] def get_queryset(self): - users = current_org.get_org_users() + users = current_org.get_org_members() self.queryset = super().get_queryset().filter( user__in=[user.__str__() for user in users] ) @@ -159,7 +160,7 @@ class PasswordChangeLogList(PermissionsMixin, DatetimeSearchMixin, ListView): def get_context_data(self, **kwargs): context = { - 'user_list': current_org.get_org_users(), + 'user_list': current_org.get_org_members(), 'date_from': self.date_from, 'date_to': self.date_to, 'user': self.user, @@ -176,18 +177,18 @@ class LoginLogListView(PermissionsMixin, DatetimeSearchMixin, ListView): paginate_by = settings.DISPLAY_PER_PAGE user = keyword = "" date_to = date_from = None - permission_classes = [IsOrgAdmin | IsAuditor] + permission_classes = [IsOrgAdmin | IsOrgAuditor] @staticmethod - def get_org_users(): - users = current_org.get_org_users().values_list('username', flat=True) + def get_org_members(): + users = current_org.get_org_members().values_list('username', flat=True) return users def get_queryset(self): if current_org.is_default(): queryset = super().get_queryset() else: - users = self.get_org_users() + users = self.get_org_members() queryset = super().get_queryset().filter(username__in=users) self.user = self.request.GET.get('user', '') @@ -214,7 +215,7 @@ class LoginLogListView(PermissionsMixin, DatetimeSearchMixin, ListView): 'date_to': self.date_to, 'user': self.user, 'keyword': self.keyword, - 'user_list': self.get_org_users(), + 'user_list': self.get_org_members(), } kwargs.update(context) return super().get_context_data(**kwargs) @@ -223,6 +224,10 @@ class LoginLogListView(PermissionsMixin, DatetimeSearchMixin, ListView): class CommandExecutionListView(UserCommandExecutionListView): user_id = None + def get_user_list(self): + users = current_org.get_org_members(exclude=('Auditor',)) + return users + def get_queryset(self): queryset = self._get_queryset() self.user_id = self.request.GET.get('user') @@ -233,10 +238,6 @@ class CommandExecutionListView(UserCommandExecutionListView): queryset = queryset.filter(user__in=org_users) return queryset - def get_user_list(self): - users = current_org.get_org_users() - return users - def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context.update({ diff --git a/apps/common/permissions.py b/apps/common/permissions.py index 648689165..08350d89b 100644 --- a/apps/common/permissions.py +++ b/apps/common/permissions.py @@ -4,8 +4,6 @@ import time from rest_framework import permissions from django.contrib.auth.mixins import UserPassesTestMixin -from django.shortcuts import redirect -from django.http.response import HttpResponseForbidden from django.conf import settings from orgs.utils import current_org @@ -27,12 +25,6 @@ class IsAppUser(IsValidUser): and request.user.is_app -class IsAuditor(IsValidUser): - def has_permission(self, request, view): - return super(IsAuditor, self).has_permission(request, view) \ - and request.user.is_auditor - - class IsSuperUser(IsValidUser): def has_permission(self, request, view): return super(IsSuperUser, self).has_permission(request, view) \ @@ -45,6 +37,20 @@ class IsSuperUserOrAppUser(IsSuperUser): or request.user.is_app +class IsSuperAuditor(IsValidUser): + def has_permission(self, request, view): + return super(IsSuperAuditor, self).has_permission(request, view) \ + and request.user.is_super_auditor + + +class IsOrgAuditor(IsValidUser): + def has_permission(self, request, view): + if not current_org: + return False + return super(IsOrgAuditor, self).has_permission(request, view) \ + and current_org.can_audit_by(request.user) + + class IsOrgAdmin(IsValidUser): """Allows access only to superuser""" @@ -81,43 +87,6 @@ class IsCurrentUserOrReadOnly(permissions.BasePermission): return obj == request.user -class LoginRequiredMixin(UserPassesTestMixin): - def test_func(self): - if self.request.user.is_authenticated: - return True - else: - return False - - -class AdminUserRequiredMixin(UserPassesTestMixin): - def test_func(self): - if not self.request.user.is_authenticated: - return False - elif not current_org.can_admin_by(self.request.user): - self.raise_exception = True - return False - return True - - def dispatch(self, request, *args, **kwargs): - if not request.user.is_authenticated: - return super().dispatch(request, *args, **kwargs) - - if not current_org: - return redirect('orgs:switch-a-org') - - if not current_org.can_admin_by(request.user): - if request.user.is_org_admin: - return redirect('orgs:switch-a-org') - return HttpResponseForbidden() - return super().dispatch(request, *args, **kwargs) - - -class SuperUserRequiredMixin(UserPassesTestMixin): - def test_func(self): - if self.request.user.is_authenticated and self.request.user.is_superuser: - return True - - class WithBootstrapToken(permissions.BasePermission): def has_permission(self, request, view): authorization = request.META.get('HTTP_AUTHORIZATION', '') @@ -159,14 +128,61 @@ class NeedMFAVerify(permissions.BasePermission): return False -class CanUpdateDeleteSuperUser(permissions.BasePermission): - def has_object_permission(self, request, view, obj): - if request.method in ['GET', 'OPTIONS']: - return True - elif request.method == 'DELETE' and str(request.user.id) == str(obj.id): +class CanUpdateDeleteUser(permissions.BasePermission): + + @staticmethod + def has_delete_object_permission(request, view, obj): + if not request.user.can_admin_current_org: return False - elif request.user.is_superuser: + # 超级管理员 / 组织管理员 + if str(request.user.id) == str(obj.id): + return False + # 超级管理员 + if request.user.is_superuser: + if obj.is_superuser and obj.username in ['admin']: + return False return True - if hasattr(obj, 'is_superuser') and obj.is_superuser: + # 组织管理员 + if obj.is_superuser: + return False + if obj.is_super_auditor: + return False + if obj.is_org_admin: + return False + if len(obj.audit_orgs) > 1: + return False + if len(obj.user_orgs) > 1: return False return True + + @staticmethod + def has_update_object_permission(request, view, obj): + if not request.user.can_admin_current_org: + return False + # 超级管理员 / 组织管理员 + if str(request.user.id) == str(obj.id): + return True + # 超级管理员 + if request.user.is_superuser: + return True + # 组织管理员 + if obj.is_superuser: + return False + if obj.is_super_auditor: + return False + if obj.is_org_admin: + return False + if len(obj.audit_orgs) > 1: + return False + if len(obj.user_orgs) > 1: + return False + return True + + def has_object_permission(self, request, view, obj): + if not request.user.can_admin_current_org: + return False + if request.method in ['DELETE']: + return self.has_delete_object_permission(request, view, obj) + if request.method in ['PUT', 'PATCH']: + return self.has_update_object_permission(request, view, obj) + return True diff --git a/apps/jumpserver/views.py b/apps/jumpserver/views.py index 2afd4d420..e9c064b66 100644 --- a/apps/jumpserver/views.py +++ b/apps/jumpserver/views.py @@ -34,17 +34,13 @@ class IndexView(PermissionsMixin, TemplateView): def dispatch(self, request, *args, **kwargs): if not request.user.is_authenticated: return self.handle_no_permission() - if request.user.is_auditor: - return super(IndexView, self).dispatch(request, *args, **kwargs) - if not request.user.is_org_admin: + if request.user.is_common_user: return redirect('assets:user-asset-list') - if not current_org or not current_org.can_admin_by(request.user): - return redirect('orgs:switch-a-org') return super(IndexView, self).dispatch(request, *args, **kwargs) @staticmethod def get_user_count(): - return current_org.get_org_users().count() + return current_org.get_org_members().count() @staticmethod def get_asset_count(): @@ -99,7 +95,7 @@ class IndexView(PermissionsMixin, TemplateView): return self.session_month.values('user').distinct().count() def get_month_inactive_user_total(self): - count = current_org.get_org_users().count() - self.get_month_active_user_total() + count = current_org.get_org_members().count() - self.get_month_active_user_total() if count < 0: count = 0 return count @@ -115,7 +111,7 @@ class IndexView(PermissionsMixin, TemplateView): @staticmethod def get_user_disabled_total(): - return current_org.get_org_users().filter(is_active=False).count() + return current_org.get_org_members().filter(is_active=False).count() @staticmethod def get_asset_disabled_total(): diff --git a/apps/ops/views/celery.py b/apps/ops/views/celery.py index f2f0124bd..98ceada92 100644 --- a/apps/ops/views/celery.py +++ b/apps/ops/views/celery.py @@ -2,7 +2,7 @@ # from django.views.generic import TemplateView -from common.permissions import PermissionsMixin, IsOrgAdmin, IsAuditor +from common.permissions import PermissionsMixin, IsOrgAdmin, IsOrgAuditor __all__ = ['CeleryTaskLogView'] @@ -10,7 +10,7 @@ __all__ = ['CeleryTaskLogView'] class CeleryTaskLogView(PermissionsMixin, TemplateView): template_name = 'ops/celery_task_log.html' - permission_classes = [IsOrgAdmin | IsAuditor] + permission_classes = [IsOrgAdmin | IsOrgAuditor] def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) diff --git a/apps/ops/views/command.py b/apps/ops/views/command.py index 9c8df2086..1d5420c9f 100644 --- a/apps/ops/views/command.py +++ b/apps/ops/views/command.py @@ -6,7 +6,7 @@ from django.conf import settings from django.views.generic import ListView, TemplateView from common.permissions import ( - PermissionsMixin, IsOrgAdmin, IsAuditor, IsValidUser + PermissionsMixin, IsOrgAdmin, IsValidUser, IsOrgAuditor ) from common.mixins import DatetimeSearchMixin from ..models import CommandExecution @@ -25,7 +25,7 @@ class CommandExecutionListView(PermissionsMixin, DatetimeSearchMixin, ListView): ordering = ('-date_created',) context_object_name = 'task_list' keyword = '' - permission_classes = [IsOrgAdmin | IsAuditor] + permission_classes = [IsOrgAdmin | IsOrgAuditor] def _get_queryset(self): self.keyword = self.request.GET.get('keyword', '') diff --git a/apps/orgs/api.py b/apps/orgs/api.py index ab1310219..ea4a48955 100644 --- a/apps/orgs/api.py +++ b/apps/orgs/api.py @@ -33,7 +33,7 @@ class OrgViewSet(BulkModelViewSet): def get_data_from_model(self, model): if model == User: - data = model.objects.filter(orgs__id=self.org.id) + data = model.objects.filter(related_user_orgs__id=self.org.id) else: data = model.objects.filter(org_id=self.org.id) return data diff --git a/apps/orgs/context_processor.py b/apps/orgs/context_processor.py index 493031bc0..c78ed834a 100644 --- a/apps/orgs/context_processor.py +++ b/apps/orgs/context_processor.py @@ -7,9 +7,11 @@ from .models import Organization def org_processor(request): context = { - 'ADMIN_ORGS': Organization.get_user_admin_orgs(request.user), + # 'ADMIN_ORGS': request.user.admin_orgs, + # 'AUDIT_ORGS': request.user.audit_orgs, + 'ADMIN_OR_AUDIT_ORGS': Organization.get_user_admin_or_audit_orgs(request.user), 'CURRENT_ORG': get_org_from_request(request), - 'HAS_ORG_PERM': current_org.can_admin_by(request.user), + # 'HAS_ORG_PERM': current_org.can_admin_by(request.user), } return context diff --git a/apps/orgs/middleware.py b/apps/orgs/middleware.py index 24a2b99fe..3e491d3d2 100644 --- a/apps/orgs/middleware.py +++ b/apps/orgs/middleware.py @@ -13,14 +13,23 @@ class OrgMiddleware: def set_permed_org_if_need(request): if request.path.startswith('/api'): return - if not (request.user.is_authenticated and request.user.is_org_admin): + if not request.user.is_authenticated: + return + if request.user.is_common_user: return org = get_org_from_request(request) if org.can_admin_by(request.user): return - admin_orgs = Organization.get_user_admin_orgs(request.user) + if org.can_audit_by(request.user): + return + admin_orgs = request.user.admin_orgs if admin_orgs: request.session['oid'] = str(admin_orgs[0].id) + return + audit_orgs = request.user.audit_orgs + if audit_orgs: + request.session['oid'] = str(audit_orgs[0].id) + return def __call__(self, request): self.set_permed_org_if_need(request) diff --git a/apps/orgs/models.py b/apps/orgs/models.py index 03b46e9bc..59e28b1d1 100644 --- a/apps/orgs/models.py +++ b/apps/orgs/models.py @@ -9,8 +9,9 @@ from common.utils import is_uuid class Organization(models.Model): id = models.UUIDField(default=uuid.uuid4, primary_key=True) name = models.CharField(max_length=128, unique=True, verbose_name=_("Name")) - users = models.ManyToManyField('users.User', related_name='orgs', blank=True) - admins = models.ManyToManyField('users.User', related_name='admin_orgs', blank=True) + users = models.ManyToManyField('users.User', related_name='related_user_orgs', blank=True) + admins = models.ManyToManyField('users.User', related_name='related_admin_orgs', blank=True) + auditors = models.ManyToManyField('users.User', related_name='related_audit_orgs', blank=True) created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by')) date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True, verbose_name=_('Date created')) comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment')) @@ -70,25 +71,46 @@ class Organization(models.Model): org = cls.default() if default else None return org - def get_org_users(self, include_app=False): + def get_org_users(self): from users.models import User if self.is_real(): - users = self.users.all() - else: - users = User.objects.all() - if not include_app: - users = users.exclude(role=User.ROLE_APP) - return users + return self.users.all() + return User.objects.filter(role=User.ROLE_USER) def get_org_admins(self): + from users.models import User if self.is_real(): return self.admins.all() - return [] + return User.objects.filter(role=User.ROLE_ADMIN) + + def get_org_auditors(self): + from users.models import User + if self.is_real(): + return self.auditors.all() + return User.objects.filter(role=User.ROLE_AUDITOR) + + def get_org_members(self, exclude=()): + from users.models import User + members = User.objects.none() + if 'Admin' not in exclude: + members |= self.get_org_admins() + if 'User' not in exclude: + members |= self.get_org_users() + if 'Auditor' not in exclude: + members |= self.get_org_auditors() + return members.exclude(role=User.ROLE_APP).distinct() def can_admin_by(self, user): if user.is_superuser: return True - if user in list(self.get_org_admins()): + if self.get_org_admins().filter(id=user.id): + return True + return False + + def can_audit_by(self, user): + if user.is_super_auditor: + return True + if self.get_org_auditors().filter(id=user.id): return True return False @@ -100,13 +122,40 @@ class Organization(models.Model): admin_orgs = [] if user.is_anonymous: return admin_orgs - elif user.is_superuser or user.is_auditor: + elif user.is_superuser: admin_orgs = list(cls.objects.all()) admin_orgs.append(cls.default()) elif user.is_org_admin: - admin_orgs = user.admin_orgs.all() + admin_orgs = user.related_admin_orgs.all() return admin_orgs + @classmethod + def get_user_user_orgs(self, user): + user_orgs = [] + if user.is_anonymous: + return user_orgs + user_orgs = user.related_user_orgs.all() + return user_orgs + + @classmethod + def get_user_audit_orgs(cls, user): + audit_orgs = [] + if user.is_anonymous: + return audit_orgs + elif user.is_super_auditor: + audit_orgs = list(cls.objects.all()) + audit_orgs.append(cls.default()) + elif user.is_org_auditor: + audit_orgs = user.related_audit_orgs.all() + return audit_orgs + + @classmethod + def get_user_admin_or_audit_orgs(self, user): + admin_orgs = self.get_user_admin_orgs(user) + audit_orgs = self.get_user_audit_orgs(user) + orgs = set(admin_orgs) | set(audit_orgs) + return orgs + @classmethod def default(cls): return cls(id=cls.DEFAULT_ID, name=cls.DEFAULT_NAME) diff --git a/apps/orgs/serializers.py b/apps/orgs/serializers.py index 7f9b7c106..222598c88 100644 --- a/apps/orgs/serializers.py +++ b/apps/orgs/serializers.py @@ -21,6 +21,7 @@ class OrgSerializer(ModelSerializer): class OrgReadSerializer(ModelSerializer): admins = serializers.SlugRelatedField(slug_field='name', many=True, read_only=True) + auditors = serializers.SlugRelatedField(slug_field='name', many=True, read_only=True) users = serializers.SlugRelatedField(slug_field='name', many=True, read_only=True) user_groups = serializers.SerializerMethodField() assets = serializers.SerializerMethodField() diff --git a/apps/orgs/views.py b/apps/orgs/views.py index 757129a7f..c4b215fe2 100644 --- a/apps/orgs/views.py +++ b/apps/orgs/views.py @@ -5,6 +5,7 @@ from django.views.generic import DetailView, View from .models import Organization from common.utils import UUID_PATTERN +from orgs.utils import current_org class SwitchOrgView(DetailView): @@ -22,17 +23,28 @@ class SwitchOrgView(DetailView): return redirect(reverse('index')) if UUID_PATTERN.search(referer): return redirect(reverse('index')) + # 组织管理员切换到组织审计员时(403) + if not self.object.get_org_admins().filter(id=request.user.id): + return redirect(reverse('index')) return redirect(referer) class SwitchToAOrgView(View): def get(self, request, *args, **kwargs): - admin_orgs = Organization.get_user_admin_orgs(request.user) - if not admin_orgs: + if request.user.is_common_user: return HttpResponseForbidden() + admin_orgs = request.user.admin_orgs + audit_orgs = request.user.audit_orgs default_org = Organization.default() - if default_org in admin_orgs: - redirect_org = default_org - else: - redirect_org = admin_orgs[0] - return redirect(reverse('orgs:org-switch', kwargs={'pk': redirect_org.id})) + if admin_orgs: + if default_org in admin_orgs: + redirect_org = default_org + else: + redirect_org = admin_orgs[0] + return redirect(reverse('orgs:org-switch', kwargs={'pk': redirect_org.id})) + if audit_orgs: + if default_org in audit_orgs: + redirect_org = default_org + else: + redirect_org = audit_orgs[0] + return redirect(reverse('orgs:org-switch', kwargs={'pk': redirect_org.id})) diff --git a/apps/perms/forms/asset_permission.py b/apps/perms/forms/asset_permission.py index 6fdaee30b..b11269b85 100644 --- a/apps/perms/forms/asset_permission.py +++ b/apps/perms/forms/asset_permission.py @@ -39,7 +39,7 @@ class AssetPermissionForm(OrgModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) users_field = self.fields.get('users') - users_field.queryset = current_org.get_org_users() + users_field.queryset = current_org.get_org_members(exclude=('Auditor',)) if self.data: return diff --git a/apps/perms/forms/remote_app_permission.py b/apps/perms/forms/remote_app_permission.py index d08066ba4..5d38b283c 100644 --- a/apps/perms/forms/remote_app_permission.py +++ b/apps/perms/forms/remote_app_permission.py @@ -19,7 +19,7 @@ class RemoteAppPermissionCreateUpdateForm(OrgModelForm): super().__init__(*args, **kwargs) users_field = self.fields.get('users') if hasattr(users_field, 'queryset'): - users_field.queryset = current_org.get_org_users() + users_field.queryset = current_org.get_org_members(exclude=('Auditor',)) class Meta: model = RemoteAppPermission diff --git a/apps/perms/views/asset_permission.py b/apps/perms/views/asset_permission.py index 94c7c8c62..6130ad2e3 100644 --- a/apps/perms/views/asset_permission.py +++ b/apps/perms/views/asset_permission.py @@ -131,16 +131,15 @@ class AssetPermissionUserView(PermissionsMixin, return queryset def get_context_data(self, **kwargs): - + user_remain = current_org.get_org_members(exclude=('Auditor',)).exclude( + assetpermission=self.object) + user_groups_remain = UserGroup.objects.exclude( + assetpermission=self.object) context = { 'app': _('Perms'), 'action': _('Asset permission user list'), - 'users_remain': current_org.get_org_users().exclude( - assetpermission=self.object - ), - 'user_groups_remain': UserGroup.objects.exclude( - assetpermission=self.object - ) + 'users_remain': user_remain, + 'user_groups_remain': user_groups_remain, } kwargs.update(context) return super().get_context_data(**kwargs) diff --git a/apps/perms/views/remote_app_permission.py b/apps/perms/views/remote_app_permission.py index 1e8b30c6d..742a5fd85 100644 --- a/apps/perms/views/remote_app_permission.py +++ b/apps/perms/views/remote_app_permission.py @@ -107,15 +107,15 @@ class RemoteAppPermissionUserView(PermissionsMixin, return queryset def get_context_data(self, **kwargs): + user_remain = current_org.get_org_members(exclude=('Auditor',)).exclude( + remoteapppermission=self.object) + user_groups_remain = UserGroup.objects.exclude( + remoteapppermission=self.object) context = { 'app': _('Perms'), 'action': _('RemoteApp permission user list'), - 'users_remain': current_org.get_org_users().exclude( - remoteapppermission=self.object - ), - 'user_groups_remain': UserGroup.objects.exclude( - remoteapppermission=self.object - ) + 'users_remain': user_remain, + 'user_groups_remain': user_groups_remain, } kwargs.update(context) return super().get_context_data(**kwargs) diff --git a/apps/templates/_header_bar.html b/apps/templates/_header_bar.html index d6a0da1c3..63ee1bbfc 100644 --- a/apps/templates/_header_bar.html +++ b/apps/templates/_header_bar.html @@ -68,7 +68,7 @@