fix: 单俱乐部视图下角色/用户/会员严格隔离,禁止泄露其他俱乐部
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -223,9 +223,15 @@ class ModifyRolePermissionView(APIView):
|
||||
if not role_code:
|
||||
return Response({'code': 400, 'msg': '缺少角色编码'})
|
||||
|
||||
from jituan.services.admin_context import can_manage_admin_assignments, can_manage_roles_for_club
|
||||
from jituan.services.club_rbac import resolve_role_by_name, resolve_role_club_id
|
||||
explicit_club = (request.data.get('target_club_id') or request.data.get('club_id') or '').strip() or None
|
||||
bind_club_id = resolve_role_club_id(request, explicit_club)
|
||||
if bind_club_id:
|
||||
if not can_manage_roles_for_club(request.user, permissions, bind_club_id):
|
||||
return Response({'code': 403, 'msg': '您无权管理该俱乐部的角色'})
|
||||
elif not can_manage_admin_assignments(request.user, permissions):
|
||||
return Response({'code': 403, 'msg': '您无权管理全局角色'})
|
||||
role = resolve_role_by_name(role_code, bind_club_id)
|
||||
if not role:
|
||||
return Response({'code': 404, 'msg': '角色不存在或与当前俱乐部不匹配'})
|
||||
@@ -354,11 +360,17 @@ class AddRoleView(APIView):
|
||||
if '000001' not in permissions:
|
||||
return Response({'code': 403, 'msg': '您无权进行此操作'})
|
||||
|
||||
# 检查角色名称是否已存在(同俱乐部内唯一)
|
||||
# 检查角色名称是否已存在(同俱乐部内唯一);单俱乐部视图强制写入当前顶栏俱乐部
|
||||
from jituan.services.admin_context import can_manage_admin_assignments, can_manage_roles_for_club
|
||||
from jituan.services.club_rbac import resolve_role_club_id, role_name_exists
|
||||
target_club_id = resolve_role_club_id(
|
||||
request, (request.data.get('target_club_id') or '').strip() or None,
|
||||
)
|
||||
if target_club_id:
|
||||
if not can_manage_roles_for_club(request.user, permissions, target_club_id):
|
||||
return Response({'code': 403, 'msg': '您无权在该俱乐部下创建角色'})
|
||||
elif not can_manage_admin_assignments(request.user, permissions):
|
||||
return Response({'code': 403, 'msg': '仅集团权限可创建全局角色'})
|
||||
if role_name_exists(role_name, target_club_id):
|
||||
return Response({'code': 400, 'msg': '该俱乐部下角色名称已存在'})
|
||||
|
||||
@@ -494,16 +506,45 @@ class GetAdminUserListView(APIView):
|
||||
'is_primary': a.is_primary,
|
||||
})
|
||||
|
||||
from jituan.constants import DATA_SCOPE_ALL
|
||||
from jituan.services.club_context import resolve_club_id_from_request, resolve_club_scope
|
||||
from jituan.services.club_rbac import filter_roles_for_request
|
||||
|
||||
scope = resolve_club_scope(request)
|
||||
curr_club = (resolve_club_id_from_request(request) or '').strip()
|
||||
# 单俱乐部视图:角色下拉/展示只允许「本俱乐部角色」;若本店无角色则仅全局
|
||||
allowed_role_club_ids = None
|
||||
if scope != DATA_SCOPE_ALL:
|
||||
scoped_roles = list(filter_roles_for_request(request).values_list('ClubID', flat=True))
|
||||
allowed_role_club_ids = {(c or '').strip() for c in scoped_roles}
|
||||
|
||||
def _roles_in_view(roles_data):
|
||||
if scope == DATA_SCOPE_ALL or allowed_role_club_ids is None:
|
||||
return roles_data
|
||||
return [
|
||||
r for r in roles_data
|
||||
if (r.get('club_id') or '').strip() in allowed_role_club_ids
|
||||
]
|
||||
|
||||
def _assignments_in_view(assignments):
|
||||
if scope == DATA_SCOPE_ALL:
|
||||
return assignments
|
||||
# 本俱乐部任职 + 集团级(club_id 空);绝不展示其他子公司任职
|
||||
return [
|
||||
a for a in assignments
|
||||
if not a.get('club_id') or a.get('club_id') == curr_club
|
||||
]
|
||||
|
||||
data_list = []
|
||||
for user in _page_users:
|
||||
roles_data = _roles_by_user.get(user.UserUUID, [])
|
||||
roles_data = _roles_in_view(_roles_by_user.get(user.UserUUID, []))
|
||||
data_list.append({
|
||||
'phone': user.Phone or '',
|
||||
'yonghuid': user.UserUID or '',
|
||||
'nicheng': user.KefuProfile.nicheng,
|
||||
'club_id': getattr(user, 'ClubID', '') or '',
|
||||
'roles': roles_data,
|
||||
'assignments': _assignments_by_user.get(user.UserUID, []),
|
||||
'assignments': _assignments_in_view(_assignments_by_user.get(user.UserUID, [])),
|
||||
'status': user.KefuProfile.zhuangtai,
|
||||
'create_time': user.UserCreateTime.strftime('%Y-%m-%d %H:%M:%S') if getattr(user, 'UserCreateTime', None) else '',
|
||||
'update_time': user.KefuProfile.UpdateTime.strftime('%Y-%m-%d %H:%M:%S') if getattr(user.KefuProfile, 'UpdateTime', None) else '',
|
||||
@@ -512,6 +553,10 @@ class GetAdminUserListView(APIView):
|
||||
})
|
||||
|
||||
from jituan.services.admin_context import can_manage_admin_assignments, get_manageable_club_ids
|
||||
manageable = sorted(get_manageable_club_ids(request.user, permissions))
|
||||
if scope != DATA_SCOPE_ALL:
|
||||
# 顶栏在具体俱乐部时,可管理集合收敛到当前店(含超级管理 000001)
|
||||
manageable = [c for c in manageable if c == curr_club]
|
||||
return Response({
|
||||
'code': 0,
|
||||
'data': {
|
||||
@@ -520,7 +565,9 @@ 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)),
|
||||
'manageable_club_ids': manageable,
|
||||
'current_club_id': curr_club,
|
||||
'scope': scope,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -546,19 +593,23 @@ class GetAdminRolesView(APIView):
|
||||
if not can_access_admin_user_management(request.user, permissions):
|
||||
return Response({'code': 403, 'msg': '您无权访问此页面'})
|
||||
|
||||
from jituan.services.admin_context import can_manage_admin_assignments, get_manageable_club_ids
|
||||
from jituan.constants import DATA_SCOPE_ALL
|
||||
from jituan.services.admin_context import can_manage_admin_assignments
|
||||
from jituan.services.club_context import resolve_club_scope
|
||||
from jituan.services.club_rbac import filter_roles_for_request
|
||||
|
||||
scope = resolve_club_scope(request)
|
||||
all_clubs = request.data.get('all_clubs') in (True, 1, '1', 'true', 'yes')
|
||||
if all_clubs and can_manage_admin_assignments(request.user, permissions):
|
||||
# 仅集团汇总视图 + 集团任职管理权 才可拉全量子公司角色;
|
||||
# 顶栏在具体俱乐部时(含集团账号切到某店),绝不容许其他俱乐部角色泄露。
|
||||
if (
|
||||
scope == DATA_SCOPE_ALL
|
||||
and all_clubs
|
||||
and can_manage_admin_assignments(request.user, permissions)
|
||||
):
|
||||
roles = Role.objects.filter(RoleStatus=1).order_by('ClubID', 'RoleName').values('RoleName', 'ClubID')
|
||||
else:
|
||||
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')
|
||||
roles = filter_roles_for_request(request).order_by('ClubID', 'RoleName').values('RoleName', 'ClubID')
|
||||
return Response({
|
||||
'code': 0,
|
||||
'data': {
|
||||
@@ -721,11 +772,12 @@ class ModifyAdminUserView(APIView):
|
||||
role_codes = request.data.get('role_codes', [])
|
||||
if not role_codes:
|
||||
return Response({'code': 400, 'msg': '请选择角色'})
|
||||
from jituan.services.club_rbac import resolve_role_by_name
|
||||
from jituan.services.club_context import resolve_club_id_from_request
|
||||
bind_club_id = (request.data.get('target_club_id') or '').strip()
|
||||
from jituan.services.club_rbac import resolve_role_by_name, resolve_role_club_id
|
||||
bind_club_id = resolve_role_club_id(
|
||||
request, (request.data.get('target_club_id') or '').strip() or None,
|
||||
)
|
||||
if not bind_club_id:
|
||||
bind_club_id = resolve_club_id_from_request(request)
|
||||
return Response({'code': 400, 'msg': '请先切换到具体俱乐部再分配角色'})
|
||||
if not can_manage_roles_for_club(request.user, permissions, bind_club_id):
|
||||
return Response({'code': 403, 'msg': '您无权管理该俱乐部的角色分配'})
|
||||
added, missing = [], []
|
||||
@@ -766,11 +818,12 @@ class ModifyAdminUserView(APIView):
|
||||
role_code = request.data.get('role_code')
|
||||
if not role_code:
|
||||
return Response({'code': 400, 'msg': '缺少角色编码'})
|
||||
from jituan.services.club_rbac import resolve_role_by_name
|
||||
from jituan.services.club_context import resolve_club_id_from_request
|
||||
bind_club_id = (request.data.get('target_club_id') or '').strip()
|
||||
from jituan.services.club_rbac import resolve_role_by_name, resolve_role_club_id
|
||||
bind_club_id = resolve_role_club_id(
|
||||
request, (request.data.get('target_club_id') or '').strip() or None,
|
||||
)
|
||||
if not bind_club_id:
|
||||
bind_club_id = resolve_club_id_from_request(request)
|
||||
return Response({'code': 400, 'msg': '请先切换到具体俱乐部再操作角色'})
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user