118 lines
4.3 KiB
Python
118 lines
4.3 KiB
Python
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
|