fix: 修复添加后台用户 RoleUUID 转换错误并严格校验角色绑定
This commit is contained in:
@@ -717,7 +717,7 @@ class AddAdminUserView(APIView):
|
|||||||
return Response({'code': 400, 'msg': '密码和二级密码至少6位'})
|
return Response({'code': 400, 'msg': '密码和二级密码至少6位'})
|
||||||
|
|
||||||
from jituan.services.club_context import resolve_club_id_from_request
|
from jituan.services.club_context import resolve_club_id_from_request
|
||||||
from jituan.services.club_rbac import resolve_role_by_name
|
from jituan.services.club_rbac import resolve_roles_for_binding
|
||||||
|
|
||||||
target_club_id = resolve_club_id_from_request(request)
|
target_club_id = resolve_club_id_from_request(request)
|
||||||
|
|
||||||
@@ -728,6 +728,27 @@ class AddAdminUserView(APIView):
|
|||||||
if existing_kefu:
|
if existing_kefu:
|
||||||
return Response({'code': 400, 'msg': '该账号已存在'})
|
return Response({'code': 400, 'msg': '该账号已存在'})
|
||||||
|
|
||||||
|
if not isinstance(role_codes, list):
|
||||||
|
return Response({'code': 400, 'msg': 'role_codes 格式错误'})
|
||||||
|
|
||||||
|
# 分配角色(默认客服 + 所选角色,去重;任一角色找不到则整单拒绝)
|
||||||
|
role_names_to_bind = []
|
||||||
|
seen_names = set()
|
||||||
|
for name in (['客服'] if '客服' not in role_codes else []) + list(role_codes):
|
||||||
|
n = (name or '').strip()
|
||||||
|
if n and n not in seen_names:
|
||||||
|
seen_names.add(n)
|
||||||
|
role_names_to_bind.append(n)
|
||||||
|
|
||||||
|
roles_to_bind, missing_roles = resolve_roles_for_binding(role_names_to_bind, target_club_id)
|
||||||
|
if missing_roles:
|
||||||
|
return Response({
|
||||||
|
'code': 400,
|
||||||
|
'msg': f'角色不存在或与当前俱乐部不匹配:{", ".join(missing_roles)}',
|
||||||
|
})
|
||||||
|
if not roles_to_bind:
|
||||||
|
return Response({'code': 400, 'msg': '请至少选择一个有效角色'})
|
||||||
|
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
# 事务内二次校验,防止并发重复创建
|
# 事务内二次校验,防止并发重复创建
|
||||||
if User.query.filter(Phone=phone, KefuProfile__isnull=False).exists():
|
if User.query.filter(Phone=phone, KefuProfile__isnull=False).exists():
|
||||||
@@ -765,20 +786,7 @@ class AddAdminUserView(APIView):
|
|||||||
erjimima=erjimima_hashed,
|
erjimima=erjimima_hashed,
|
||||||
zhuangtai=1
|
zhuangtai=1
|
||||||
)
|
)
|
||||||
# 分配角色(默认客服 + 所选角色,按俱乐部解析,去重)
|
for role in roles_to_bind:
|
||||||
role_names_to_bind = []
|
|
||||||
if '客服' not in role_codes:
|
|
||||||
role_names_to_bind.append('客服')
|
|
||||||
role_names_to_bind.extend(role_codes)
|
|
||||||
bound_role_uuids = set()
|
|
||||||
for rc in role_names_to_bind:
|
|
||||||
role = resolve_role_by_name(rc, target_club_id)
|
|
||||||
if not role:
|
|
||||||
continue
|
|
||||||
role_uuid = bytes(role.RoleUUID) if not isinstance(role.RoleUUID, bytes) else role.RoleUUID
|
|
||||||
if role_uuid in bound_role_uuids:
|
|
||||||
continue
|
|
||||||
bound_role_uuids.add(role_uuid)
|
|
||||||
UserRole.objects.get_or_create(
|
UserRole.objects.get_or_create(
|
||||||
UserUUID=user_main.UserUUID,
|
UserUUID=user_main.UserUUID,
|
||||||
RoleUUID=role.RoleUUID,
|
RoleUUID=role.RoleUUID,
|
||||||
|
|||||||
@@ -76,6 +76,38 @@ def resolve_role_by_name(role_name, club_id=None):
|
|||||||
return qs.filter(ClubID='').first() or qs.first()
|
return qs.filter(ClubID='').first() or qs.first()
|
||||||
|
|
||||||
|
|
||||||
|
def role_uuid_bytes(role_uuid):
|
||||||
|
"""RoleUUID 统一转 bytes(兼容 UUIDObj / bytes / str)。"""
|
||||||
|
from gvsdsdk.model_utils import UUIDObj
|
||||||
|
if isinstance(role_uuid, bytes):
|
||||||
|
return role_uuid
|
||||||
|
return UUIDObj(role_uuid).bytes
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_roles_for_binding(role_names, club_id=None):
|
||||||
|
"""
|
||||||
|
按角色名解析并去重;任一角色在当前俱乐部下找不到则整体失败。
|
||||||
|
返回 (roles, missing_names)。
|
||||||
|
"""
|
||||||
|
resolved = []
|
||||||
|
missing = []
|
||||||
|
seen_bytes = set()
|
||||||
|
for raw in role_names or []:
|
||||||
|
name = (raw or '').strip()
|
||||||
|
if not name:
|
||||||
|
continue
|
||||||
|
role = resolve_role_by_name(name, club_id)
|
||||||
|
if not role:
|
||||||
|
missing.append(name)
|
||||||
|
continue
|
||||||
|
key = role_uuid_bytes(role.RoleUUID)
|
||||||
|
if key in seen_bytes:
|
||||||
|
continue
|
||||||
|
seen_bytes.add(key)
|
||||||
|
resolved.append(role)
|
||||||
|
return resolved, missing
|
||||||
|
|
||||||
|
|
||||||
def user_bound_role_names(user):
|
def user_bound_role_names(user):
|
||||||
from backend.utils import _legacy_backend_role_permissions
|
from backend.utils import _legacy_backend_role_permissions
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user