From 1c6607fa6ea4d5cbe96b970649899dedd3bda2f6 Mon Sep 17 00:00:00 2001 From: XingQue Date: Mon, 6 Jul 2026 18:23:29 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=A7=92=E8=89=B2=E5=88=86=E9=85=8D?= =?UTF-8?q?=E6=8C=89=E4=BF=B1=E4=B9=90=E9=83=A8=E8=B6=85=E7=AE=A1=E6=9D=83?= =?UTF-8?q?=E9=99=90=E9=9A=94=E7=A6=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- backend/views/roles.py | 25 ++++++++++++++++++++----- jituan/services/admin_context.py | 25 +++++++++++++++++++++++++ jituan/services/club_rbac.py | 23 +++++++++++++++++++++++ 3 files changed, 68 insertions(+), 5 deletions(-) diff --git a/backend/views/roles.py b/backend/views/roles.py index e76873c..9c7392d 100644 --- a/backend/views/roles.py +++ b/backend/views/roles.py @@ -510,7 +510,7 @@ class GetAdminUserListView(APIView): 'UpdateTime': user.KefuProfile.UpdateTime.strftime('%Y-%m-%d %H:%M:%S') if getattr(user.KefuProfile, 'UpdateTime', None) else '', }) - from jituan.services.admin_context import can_manage_admin_assignments + from jituan.services.admin_context import can_manage_admin_assignments, get_manageable_club_ids return Response({ 'code': 0, 'data': { @@ -519,6 +519,7 @@ class GetAdminUserListView(APIView): 'page': page, 'pageSize': page_size, 'can_manage_club_assignments': can_manage_admin_assignments(request.user, permissions), + 'manageable_club_ids': sorted(get_manageable_club_ids(request.user, permissions)), } }) @@ -543,12 +544,19 @@ class GetAdminRolesView(APIView): if '000001' not in permissions: return Response({'code': 403, 'msg': '您无权访问此页面'}) + from jituan.services.admin_context import can_manage_admin_assignments, get_manageable_club_ids from jituan.services.club_rbac import filter_roles_for_request all_clubs = request.data.get('all_clubs') in (True, 1, '1', 'true', 'yes') - if all_clubs: + if all_clubs and can_manage_admin_assignments(request.user, permissions): roles = Role.objects.filter(RoleStatus=1).order_by('ClubID', 'RoleName').values('RoleName', 'ClubID') else: - roles = filter_roles_for_request(request).values('RoleName', 'ClubID') + manageable = get_manageable_club_ids(request.user, permissions) + if manageable: + roles = Role.objects.filter( + RoleStatus=1, ClubID__in=manageable, + ).order_by('ClubID', 'RoleName').values('RoleName', 'ClubID') + else: + roles = filter_roles_for_request(request).values('RoleName', 'ClubID') return Response({ 'code': 0, 'data': { @@ -651,12 +659,15 @@ class ModifyAdminUserView(APIView): if kefu is None: return permissions - from jituan.services.admin_context import can_manage_admin_assignments + from jituan.services.admin_context import can_manage_admin_assignments, can_manage_roles_for_club club_assign_actions = {'add_club_assignment', 'remove_club_assignment'} + role_manage_actions = {'add_user_roles', 'remove_user_role'} if action in club_assign_actions: if not can_manage_admin_assignments(request.user, permissions): - return Response({'code': 403, 'msg': '仅集团高层(集团总负责人/集团超管)可分配俱乐部任职'}) + return Response({'code': 403, 'msg': '无权分配俱乐部任职'}) + elif action in role_manage_actions: + pass elif '000001' not in permissions: return Response({'code': 403, 'msg': '您无权进行此操作'}) @@ -707,6 +718,8 @@ class ModifyAdminUserView(APIView): bind_club_id = (request.data.get('target_club_id') or '').strip() if not bind_club_id: bind_club_id = resolve_club_id_from_request(request) + if not can_manage_roles_for_club(request.user, permissions, bind_club_id): + return Response({'code': 403, 'msg': '您无权管理该俱乐部的角色分配'}) added, missing = [], [] for rc in role_codes: role = resolve_role_by_name(rc, bind_club_id) @@ -746,6 +759,8 @@ class ModifyAdminUserView(APIView): bind_club_id = (request.data.get('target_club_id') or '').strip() if not bind_club_id: bind_club_id = resolve_club_id_from_request(request) + if not can_manage_roles_for_club(request.user, permissions, bind_club_id): + return Response({'code': 403, 'msg': '您无权管理该俱乐部的角色分配'}) role = resolve_role_by_name(role_code, bind_club_id) if not role: return Response({'code': 404, 'msg': '角色不存在或与所选俱乐部不匹配'}) diff --git a/jituan/services/admin_context.py b/jituan/services/admin_context.py index 3d3bd01..077be20 100644 --- a/jituan/services/admin_context.py +++ b/jituan/services/admin_context.py @@ -171,6 +171,31 @@ def can_manage_admin_assignments(user, permissions=None): ) +def can_manage_roles_for_club(user, permissions, club_id): + """ + 是否可为指定俱乐部分配/移除功能角色。 + 集团高层:全部俱乐部;否则须在该俱乐部拥有 000001 超级管理权限。 + """ + if can_manage_admin_assignments(user, permissions): + return True + cid = (club_id or '').strip() + if not cid: + return False + from jituan.services.club_rbac import resolve_permission_codes_for_club + codes = resolve_permission_codes_for_club(user, cid) + return '000001' in codes + + +def get_manageable_club_ids(user, permissions=None): + """当前操作者可管理角色分配的俱乐部集合。""" + if can_manage_admin_assignments(user, permissions): + return {c.club_id for c in Club.query.filter(status=1)} + return { + c.club_id for c in Club.query.filter(status=1) + if can_manage_roles_for_club(user, permissions, c.club_id) + } + + def _pack(scope, club_id, is_group_admin, assignments, clubs, can_switch_club, role_code, role_name): allowed_club_ids = sorted({ diff --git a/jituan/services/club_rbac.py b/jituan/services/club_rbac.py index fe5bf12..744a525 100644 --- a/jituan/services/club_rbac.py +++ b/jituan/services/club_rbac.py @@ -152,6 +152,29 @@ def filter_role_uuids_for_club_scope(role_uuids, club_id, scope, allowed_club_id return list(qs.filter(Q(ClubID=cid) | Q(ClubID='')).values_list('RoleUUID', flat=True)) +def resolve_permission_codes_for_club(user, club_id, allowed_club_ids=None): + """指定俱乐部 SINGLE 视图下用户的 gvsdsdk 权限码。""" + from jituan.constants import DATA_SCOPE_SINGLE + from gvsdsdk.models import Permission as SdkPermission, RolePermission as SdkRolePermission, UserRole as SdkUserRole + + role_uuids = list(SdkUserRole.objects.filter( + UserUUID=user.UserUUID, + ).values_list('RoleUUID', flat=True)) + role_uuids = filter_role_uuids_for_club_scope( + role_uuids, club_id, DATA_SCOPE_SINGLE, allowed_club_ids, + ) + if not role_uuids: + return [] + perm_uuids = SdkRolePermission.objects.filter( + RoleUUID__in=role_uuids, + ).values_list('PermUUID', flat=True) + return list( + SdkPermission.objects.filter( + PermUUID__in=perm_uuids, PermStatus=1, + ).values_list('PermCode', flat=True).distinct() + ) + + def user_bound_role_names(user, club_id=None, scope=None, allowed_club_ids=None): from backend.utils import _legacy_backend_role_permissions