from gvsds.apps.core.models import User from gvsdsdk.models import UserRole, Role, RolePermission, Permission, UserABAC from rest_framework.permissions import BasePermission class IsAdminUser(BasePermission): """仅允许管理员(IsStaff 或 IsSuperuser)访问""" def has_permission(self, request, view): user = request.user if not user or not user.is_authenticated: return False if not isinstance(user, User): return False return user.IsStaff or user.IsSuperuser class IsCompanyMember(BasePermission): """验证用户当前角色属于目标数据所在公司""" def has_object_permission(self, request, view, obj): if not request.current_company_uuid: return False obj_company = getattr(obj, 'CompanyUUID_id', None) or getattr(obj, 'CompanyUUID', None) if obj_company is None: return True # 无公司归属的数据不做限制 return str(obj_company) == str(request.current_company_uuid) class CompanyScopedMixin: """ViewSet Mixin:自动按当前角色所属公司过滤 queryset""" company_field = 'CompanyUUID' # 可在 ViewSet 中覆盖 def get_queryset(self): qs = super().get_queryset() company_uuid = getattr(self.request, 'current_company_uuid', None) if company_uuid and hasattr(qs.model, self.company_field): qs = qs.filter(**{self.company_field: company_uuid}) return qs def perform_create(self, serializer): company_uuid = getattr(self.request, 'current_company_uuid', None) if company_uuid and hasattr(serializer.Meta.model, 'CompanyUUID'): serializer.save(CompanyUUID=company_uuid) else: serializer.save() def PermissionVerifier(permission, attributes, user=None, request=None): """权限验证器——混合 ABAC + RBAC 检查 RBAC 仅检查当前角色(CurrentRoleUUID Cookie 指定的角色)的权限, 通过 RolePermission → Permission 链路查询,按当前公司过滤。 超级管理员/员工直接放行。 """ if not permission: return True if user is None: return False if not isinstance(user, User): return False # 超级管理员和员工直接放行 if user.IsSuperuser or user.IsStaff: return True current_role = getattr(request, 'current_role', None) if request else None current_company = getattr(request, 'current_company_uuid', None) if request else None for attr in attributes: # ABAC 检查 abac_match = UserABAC.objects.filter( UserUUID=user.UserUUID, HierarchicalPermissionIdentifiers=attr ).first() if abac_match: continue # RBAC 检查:仅检查当前角色,按公司过滤权限 if current_role and isinstance(current_role, Role): if current_role.RoleStatus != 1: return False rp_qs = RolePermission.objects.filter( RoleUUID=current_role.RoleUUID ) if current_company: rp_qs = rp_qs.filter(CompanyUUID=current_company) perm_uuids = rp_qs.values_list('PermUUID', flat=True) rbac_result = Permission.objects.filter( PermUUID__in=perm_uuids, PermCode=attr, PermStatus=1, ).exists() else: # 无 current_role 时回退到用户所有活跃角色 user_role_uuids = UserRole.objects.filter( UserUUID=user.UserUUID ).values_list('RoleUUID', flat=True) active_role_uuids = Role.objects.filter( RoleUUID__in=user_role_uuids, RoleStatus=1, ).values_list('RoleUUID', flat=True) rp_qs = RolePermission.objects.filter( RoleUUID__in=active_role_uuids ) if current_company: rp_qs = rp_qs.filter(CompanyUUID=current_company) perm_uuids = rp_qs.values_list('PermUUID', flat=True) rbac_result = Permission.objects.filter( PermUUID__in=perm_uuids, PermCode=attr, PermStatus=1, ).exists() if rbac_result: continue return False return True