feat(auth): 新增 IsCompanyAdminUser 权限类并修复待审列表跨租户泄漏
- permissions.py 新增 IsCompanyAdminUser(admin:company / admin:tenant / admin:super) - ListPendingApplications 移除被静默忽略的 TenantUUID 形参,改为显式 AllowedCompanyUUIDs - 过滤在 SQL 侧用子查询完成,规避 UUIDObj 与 bytes 混比恒为 False 的坑
This commit is contained in:
1 parent
4b074e565a
commit
94cb71e82a
2 files changed
+45
-3
No files matched your search
+23
-3
@@ -3257,12 +3257,32 @@ class AppManager:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def ListPendingApplications(TenantUUID):
|
def ListPendingApplications(AllowedCompanyUUIDs=None):
|
||||||
"""待审批的个人授权申请(ApplyStatus=1,按申请时间倒序)
|
"""待审批的个人授权申请(ApplyStatus=1,按申请时间倒序)
|
||||||
|
|
||||||
说明:UserApp 表无租户列,租户隔离由上层承担(保持既有行为)。
|
数据范围:UserApp 表无租户/公司列,作用域按「申请人所属公司」反查
|
||||||
|
(UserRole.CompanyUUID)。由调用方按管理员级别显式传参:
|
||||||
|
- ``AllowedCompanyUUIDs=None`` → 不限制(平台管理员 admin:super)
|
||||||
|
- ``AllowedCompanyUUIDs=[]`` → 无任何可管辖公司,返回空
|
||||||
|
- ``AllowedCompanyUUIDs=[...]`` → 仅申请人的公司命中该集合的申请
|
||||||
|
|
||||||
|
注意:此前签名是 ``(TenantUUID)`` 但**传入值被完全忽略**,导致任何租户
|
||||||
|
管理员都能看到全平台待审申请(跨租户泄漏)。现改为显式范围参数,不再
|
||||||
|
接受会被静默忽略的租户参数。
|
||||||
"""
|
"""
|
||||||
return list(UserApp.objects.filter(ApplyStatus=1).order_by('-ApplyTime'))
|
qs = UserApp.objects.filter(ApplyStatus=1).order_by('-ApplyTime')
|
||||||
|
if AllowedCompanyUUIDs is not None:
|
||||||
|
allowed = [c for c in AllowedCompanyUUIDs if c]
|
||||||
|
if not allowed:
|
||||||
|
return []
|
||||||
|
# 用子查询在 SQL 侧完成「申请人属于可管辖公司」过滤,避免 Python 侧
|
||||||
|
# UUIDObj/bytes 混比(两者 hash 不同,曾因此导致判定恒为 False)
|
||||||
|
qs = qs.filter(
|
||||||
|
UserUUID__in=UserRole.objects.filter(
|
||||||
|
CompanyUUID__in=allowed,
|
||||||
|
).values('UserUUID')
|
||||||
|
)
|
||||||
|
return list(qs)
|
||||||
|
|
||||||
# ==================== 应用配置(AppConfig 键值表) ====================
|
# ==================== 应用配置(AppConfig 键值表) ====================
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,28 @@ class IsAdminUser(BasePermission):
|
|||||||
return IsAdmin(request)
|
return IsAdmin(request)
|
||||||
|
|
||||||
|
|
||||||
|
class IsCompanyAdminUser(BasePermission):
|
||||||
|
"""仅允许公司管理员及以上访问(admin:company / admin:tenant / admin:super)
|
||||||
|
|
||||||
|
三级管理员体系(由窄到宽):
|
||||||
|
- ``admin:company``:公司管理员,按 RolePermission.CompanyUUID 绑定到具体公司后生效
|
||||||
|
- ``admin:tenant`` :租户内管理员,自动继承公司管理员能力
|
||||||
|
- ``admin:super`` :跨租户管理员,天然具备
|
||||||
|
|
||||||
|
判定委托给 ``gvsdsdk.auth.admin_service.IsCompanyAdmin``。本类只负责"能不能进",
|
||||||
|
数据范围收窄(本公司/本租户/全部)由视图按 IsSuperAdmin/IsTenantAdmin 另行计算。
|
||||||
|
"""
|
||||||
|
|
||||||
|
def has_permission(self, request, view):
|
||||||
|
user = request.user
|
||||||
|
if not user or not user.is_authenticated:
|
||||||
|
return False
|
||||||
|
if not isinstance(user, _GetUserModel()):
|
||||||
|
return False
|
||||||
|
from gvsdsdk.auth.admin_service import IsCompanyAdmin
|
||||||
|
return IsCompanyAdmin(request)
|
||||||
|
|
||||||
|
|
||||||
class IsCompanyMember(BasePermission):
|
class IsCompanyMember(BasePermission):
|
||||||
"""验证用户当前角色属于目标数据所在公司
|
"""验证用户当前角色属于目标数据所在公司
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user