fix: 切换俱乐部仅算本俱乐部角色权限,统一权限解析
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -170,11 +170,10 @@ def verify_kefu_permission(request, username_from_frontend=None):
|
||||
'msg': '身份错误,无权操作其他账号,相关操作已记录'
|
||||
}, status=403)
|
||||
|
||||
# ---------- 4. 获取用户的所有权限 ----------
|
||||
# 使用 gvsdsdk RBAC 表(UserRole → RolePermission → Permission)
|
||||
# ---------- 4. 获取用户的所有权限(与菜单 menu-access 同一套算法) ----------
|
||||
from jituan.constants import CLUB_ID_DEFAULT, DATA_SCOPE_SINGLE
|
||||
from jituan.services.admin_context import resolve_admin_effective_club, get_allowed_club_ids, is_system_super_admin
|
||||
from jituan.services.club_rbac import filter_role_uuids_for_club_scope
|
||||
from jituan.services.club_rbac import resolve_effective_permission_codes
|
||||
|
||||
eff_club = getattr(request, 'club_id', None) or CLUB_ID_DEFAULT
|
||||
eff_scope = getattr(request, 'club_scope', None) or DATA_SCOPE_SINGLE
|
||||
@@ -188,27 +187,27 @@ def verify_kefu_permission(request, username_from_frontend=None):
|
||||
allowed_club_ids = list(get_allowed_club_ids(current_user))
|
||||
|
||||
try:
|
||||
user_uuid = current_user.UserUUID
|
||||
role_uuids = list(SdkUserRole.objects.filter(
|
||||
UserUUID=user_uuid
|
||||
).values_list('RoleUUID', flat=True))
|
||||
|
||||
if role_uuids and not is_system_super_admin(current_user):
|
||||
role_uuids = filter_role_uuids_for_club_scope(
|
||||
role_uuids, eff_club, eff_scope, allowed_club_ids,
|
||||
)
|
||||
|
||||
if role_uuids:
|
||||
perm_uuids = list(SdkRolePermission.objects.filter(
|
||||
RoleUUID__in=role_uuids
|
||||
).values_list('PermUUID', flat=True))
|
||||
|
||||
permissions = list(SdkPermission.objects.filter(
|
||||
PermUUID__in=perm_uuids,
|
||||
PermStatus=1
|
||||
).values_list('PermCode', flat=True).distinct())
|
||||
if is_system_super_admin(current_user):
|
||||
user_uuid = current_user.UserUUID
|
||||
role_uuids = list(SdkUserRole.objects.filter(
|
||||
UserUUID=user_uuid
|
||||
).values_list('RoleUUID', flat=True))
|
||||
if role_uuids:
|
||||
perm_uuids = list(SdkRolePermission.objects.filter(
|
||||
RoleUUID__in=role_uuids
|
||||
).values_list('PermUUID', flat=True))
|
||||
permissions = list(SdkPermission.objects.filter(
|
||||
PermUUID__in=perm_uuids, PermStatus=1
|
||||
).values_list('PermCode', flat=True).distinct())
|
||||
else:
|
||||
permissions = []
|
||||
legacy_codes, _ = _legacy_backend_role_permissions(current_user.Phone)
|
||||
if legacy_codes:
|
||||
permissions = list(set(list(permissions) + legacy_codes))
|
||||
else:
|
||||
permissions = []
|
||||
permissions = resolve_effective_permission_codes(
|
||||
current_user, eff_club, eff_scope, allowed_club_ids,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
'verify_kefu_permission failed: UserUUID=%s Phone=%s err=%s',
|
||||
@@ -219,11 +218,6 @@ def verify_kefu_permission(request, username_from_frontend=None):
|
||||
)
|
||||
permissions = []
|
||||
|
||||
# 旧权限表(user_role 按手机号):仅在没有 gvsdsdk 角色绑定时兜底,避免污染多俱乐部权限
|
||||
legacy_codes, _ = _legacy_backend_role_permissions(current_user.Phone)
|
||||
if legacy_codes and not role_uuids:
|
||||
permissions = list(set(list(permissions) + legacy_codes))
|
||||
|
||||
# 仅系统级超管自动拥有全部功能权限;俱乐部 000001 只解锁超管页,不展开全部菜单
|
||||
if is_system_super_admin(current_user):
|
||||
if '000001' not in permissions:
|
||||
|
||||
@@ -135,34 +135,44 @@ def resolve_roles_for_binding(role_names, club_id=None):
|
||||
def filter_role_uuids_for_club_scope(role_uuids, club_id, scope, allowed_club_ids=None):
|
||||
"""
|
||||
按当前俱乐部上下文过滤 UserRole 绑定的 RoleUUID。
|
||||
SINGLE_CLUB:本俱乐部角色 + 全局角色(ClubID 为空)。
|
||||
ALL_CLUBS:全局角色 + 各已授权俱乐部的角色(并集)。
|
||||
SINGLE_CLUB:仅本俱乐部角色(Role.ClubID=当前俱乐部),不含其他俱乐部/全局。
|
||||
ALL_CLUBS:已授权各俱乐部角色 + 全局角色(club_id 为空)。
|
||||
"""
|
||||
if not role_uuids:
|
||||
return []
|
||||
qs = Role.objects.filter(RoleUUID__in=role_uuids, RoleStatus=1)
|
||||
wanted = {role_uuid_bytes(u) for u in role_uuids}
|
||||
|
||||
if scope == DATA_SCOPE_ALL:
|
||||
club_ids = [c for c in (allowed_club_ids or []) if c]
|
||||
if club_ids:
|
||||
return list(
|
||||
qs.filter(Q(ClubID='') | Q(ClubID__in=club_ids)).values_list('RoleUUID', flat=True)
|
||||
)
|
||||
return list(qs.filter(ClubID='').values_list('RoleUUID', flat=True))
|
||||
club_ids = {c for c in (allowed_club_ids or []) if c}
|
||||
matched = []
|
||||
for role in Role.objects.filter(RoleStatus=1):
|
||||
key = role_uuid_bytes(role.RoleUUID)
|
||||
if key not in wanted:
|
||||
continue
|
||||
rcid = (getattr(role, 'ClubID', None) or '').strip()
|
||||
if rcid == '' or rcid in club_ids:
|
||||
matched.append(role.RoleUUID)
|
||||
return matched
|
||||
|
||||
cid = (club_id or CLUB_ID_DEFAULT).strip()
|
||||
# 本俱乐部专属角色 + 全局角色(权限取并集;002ac 等常在全局角色上)
|
||||
return list(qs.filter(Q(ClubID=cid) | Q(ClubID='')).values_list('RoleUUID', flat=True))
|
||||
matched = []
|
||||
for role in Role.objects.filter(RoleStatus=1, ClubID=cid):
|
||||
if role_uuid_bytes(role.RoleUUID) in wanted:
|
||||
matched.append(role.RoleUUID)
|
||||
return matched
|
||||
|
||||
|
||||
def resolve_permission_codes_for_club(user, club_id, allowed_club_ids=None):
|
||||
"""指定俱乐部 SINGLE 视图下用户的 gvsdsdk 权限码。"""
|
||||
def resolve_permission_codes_for_club(user, club_id, allowed_club_ids=None, scope=None):
|
||||
"""当前俱乐部上下文下的 gvsdsdk 权限码(与 verify_kefu_permission / 菜单共用)。"""
|
||||
from jituan.constants import DATA_SCOPE_SINGLE
|
||||
from gvsdsdk.models import Permission as SdkPermission, RolePermission as SdkRolePermission, UserRole as SdkUserRole
|
||||
|
||||
eff_scope = scope or DATA_SCOPE_SINGLE
|
||||
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,
|
||||
role_uuids, club_id, eff_scope, allowed_club_ids,
|
||||
)
|
||||
if not role_uuids:
|
||||
return []
|
||||
@@ -176,6 +186,13 @@ def resolve_permission_codes_for_club(user, club_id, allowed_club_ids=None):
|
||||
)
|
||||
|
||||
|
||||
def resolve_effective_permission_codes(user, club_id, scope, allowed_club_ids=None):
|
||||
"""菜单与各业务接口统一权限码:仅当前俱乐部 gvsdsdk 角色,不串其他俱乐部。"""
|
||||
return resolve_permission_codes_for_club(
|
||||
user, club_id, allowed_club_ids, scope=scope,
|
||||
)
|
||||
|
||||
|
||||
def user_bound_role_names(user, club_id=None, scope=None, allowed_club_ids=None):
|
||||
from backend.utils import _legacy_backend_role_permissions
|
||||
|
||||
|
||||
@@ -132,8 +132,8 @@ def build_menu_access_payload(request, username=None):
|
||||
visible_ids.append(page.page_id)
|
||||
|
||||
club_ctx = build_admin_club_context(request.user)
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
scope = resolve_club_scope(request)
|
||||
club_id = getattr(request, 'club_id', None) or resolve_club_id_from_request(request)
|
||||
scope = getattr(request, 'club_scope', None) or resolve_club_scope(request)
|
||||
allowed = list(get_allowed_club_ids(request.user))
|
||||
path_by_id = {p.page_id: p.path for p in pages if p.path}
|
||||
visible_paths = [path_by_id[pid] for pid in visible_ids if pid in path_by_id]
|
||||
|
||||
@@ -56,7 +56,7 @@ from orders.utils import (
|
||||
from backend.utils import (
|
||||
update_dashou_daily_by_action, update_guanshi_daily_by_action,
|
||||
update_shangjia_daily, update_zuzhang_daily_by_action,
|
||||
verify_kefu_permission, has_perm_code,
|
||||
verify_kefu_permission, has_merchant_order_permission, has_perm_code,
|
||||
)
|
||||
from rank.utils import get_tag_fee, create_shenhe_jilu, validate_shenheguan
|
||||
|
||||
@@ -304,15 +304,7 @@ class KefuGetShangjiaOrderListView(APIView):
|
||||
if kefu is None:
|
||||
return permissions
|
||||
|
||||
from jituan.constants import CLUB_ID_DEFAULT
|
||||
from jituan.services.admin_context import get_allowed_club_ids
|
||||
from jituan.services.club_rbac import resolve_permission_codes_for_club
|
||||
|
||||
club_id = getattr(request, 'club_id', None) or CLUB_ID_DEFAULT
|
||||
eff_codes = resolve_permission_codes_for_club(
|
||||
request.user, club_id, list(get_allowed_club_ids(request.user)),
|
||||
)
|
||||
if not has_perm_code(permissions, '002ac') and '002ac' not in eff_codes:
|
||||
if not has_merchant_order_permission(permissions):
|
||||
return Response({'code': 403, 'msg': '您无权查看商家订单列表'})
|
||||
|
||||
# 4. 获取分页和筛选参数
|
||||
|
||||
Reference in New Issue
Block a user