fix: kefu permissions use legacy permission table instead of gvsdsdk
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
272
backend/view.py
272
backend/view.py
@@ -148,46 +148,62 @@ class GetRolePermissionView(APIView):
|
||||
if '000001' not in permissions:
|
||||
return Response({'code': 403, 'msg': '您无权访问此页面'})
|
||||
|
||||
# 3. 获取所有权限
|
||||
all_perms = Permission.objects.filter(PermStatus=1).values('PermCode', 'PermName', 'PermDesc')
|
||||
permissions_list = [_serialize_permission_row(p) for p in all_perms]
|
||||
|
||||
from jituan.services.club_rbac import count_role_users_in_scope, filter_roles_for_request
|
||||
|
||||
kefu_user_uuids = list(
|
||||
User.objects.filter(KefuProfile__isnull=False).values_list('UserUUID', flat=True)
|
||||
from backend.models import (
|
||||
Role as BackendRole,
|
||||
Permission as BackendPermission,
|
||||
UserRole as LegacyUserRole,
|
||||
)
|
||||
roles = filter_roles_for_request(request)
|
||||
|
||||
all_perms = BackendPermission.objects.all().values('perm_code', 'perm_name', 'description')
|
||||
permissions_list = [
|
||||
{
|
||||
'perm_code': p['perm_code'],
|
||||
'perm_name': p['perm_name'],
|
||||
'perm_desc': p.get('description') or '',
|
||||
}
|
||||
for p in all_perms
|
||||
]
|
||||
|
||||
roles_data = []
|
||||
for role in roles:
|
||||
user_count = count_role_users_in_scope(role, request, kefu_user_uuids)
|
||||
role_perm_uuids = RolePermission.objects.filter(
|
||||
RoleUUID=role.RoleUUID
|
||||
).values_list('PermUUID', flat=True)
|
||||
perms_of_role = [
|
||||
_serialize_permission_row(p)
|
||||
for p in Permission.objects.filter(
|
||||
PermUUID__in=list(role_perm_uuids)
|
||||
).values('PermCode', 'PermName', 'PermDesc')
|
||||
]
|
||||
for role in BackendRole.objects.all().order_by('role_id'):
|
||||
user_count = LegacyUserRole.objects.filter(role=role).count()
|
||||
perms_of_role = BackendPermission.objects.filter(rolepermission__role=role).distinct()
|
||||
roles_data.append({
|
||||
'role_code': role.RoleName,
|
||||
'role_name': role.RoleName,
|
||||
'description': role.RoleDesc or '',
|
||||
'club_id': getattr(role, 'ClubID', '') or '',
|
||||
'role_code': role.role_name,
|
||||
'role_name': role.role_name,
|
||||
'description': role.description or '',
|
||||
'club_id': '',
|
||||
'user_count': user_count,
|
||||
'permissions': perms_of_role
|
||||
'permissions': [
|
||||
{
|
||||
'perm_code': p.perm_code,
|
||||
'perm_name': p.perm_name,
|
||||
'perm_desc': p.description or '',
|
||||
}
|
||||
for p in perms_of_role
|
||||
],
|
||||
})
|
||||
|
||||
return Response({
|
||||
'code': 0,
|
||||
'data': {
|
||||
'roles': roles_data,
|
||||
'permissions': permissions_list
|
||||
}
|
||||
'permissions': permissions_list,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
def _resolve_backend_role(role_code):
|
||||
from backend.models import Role as BackendRole
|
||||
rc = (role_code or '').strip()
|
||||
if not rc:
|
||||
return None
|
||||
return (
|
||||
BackendRole.objects.filter(role_name=rc).first()
|
||||
or BackendRole.objects.filter(role_code=rc).first()
|
||||
)
|
||||
|
||||
|
||||
class ModifyRolePermissionView(APIView):
|
||||
"""
|
||||
通用接口:支持删除角色、为角色添加权限、移除角色权限
|
||||
@@ -213,22 +229,26 @@ class ModifyRolePermissionView(APIView):
|
||||
if not role_code:
|
||||
return Response({'code': 400, 'msg': '缺少角色编码'})
|
||||
|
||||
try:
|
||||
role = Role.objects.get(RoleName=role_code)
|
||||
except Role.DoesNotExist:
|
||||
from backend.models import (
|
||||
Permission as BackendPermission,
|
||||
RolePermission as LegacyRolePermission,
|
||||
UserRole as LegacyUserRole,
|
||||
)
|
||||
|
||||
role = _resolve_backend_role(role_code)
|
||||
if not role:
|
||||
return Response({'code': 404, 'msg': '角色不存在'})
|
||||
|
||||
# 超级管理员角色的特殊限制
|
||||
if role.RoleName == '管理员':
|
||||
if role.role_name == '管理员':
|
||||
if action in ['delete_role']:
|
||||
return Response({'code': 403, 'msg': '超级管理员角色不能删除'})
|
||||
|
||||
# 根据 action 处理
|
||||
if action == 'delete_role':
|
||||
# 删除角色:同时删除角色权限关联、用户角色关联
|
||||
with transaction.atomic():
|
||||
RolePermission.objects.filter(RoleUUID=role.RoleUUID).delete()
|
||||
UserRole.objects.filter(RoleUUID=role.RoleUUID).delete()
|
||||
LegacyRolePermission.objects.filter(role=role).delete()
|
||||
LegacyUserRole.objects.filter(role=role).delete()
|
||||
role.delete()
|
||||
return Response({'code': 0, 'msg': '角色删除成功'})
|
||||
|
||||
@@ -236,34 +256,26 @@ class ModifyRolePermissionView(APIView):
|
||||
perm_code = request.data.get('perm_code')
|
||||
if not perm_code:
|
||||
return Response({'code': 400, 'msg': '缺少权限编码'})
|
||||
if role.RoleName == '管理员' and perm_code == '000001':
|
||||
if role.role_name == '管理员' and perm_code == '000001':
|
||||
return Response({'code': 403, 'msg': '此权限已存在,不能重复添加'})
|
||||
try:
|
||||
perm = Permission.objects.get(PermCode=perm_code)
|
||||
except Permission.DoesNotExist:
|
||||
perm = BackendPermission.objects.filter(perm_code=perm_code).first()
|
||||
if not perm:
|
||||
return Response({'code': 404, 'msg': '权限不存在'})
|
||||
# 检查是否已存在
|
||||
if RolePermission.objects.filter(RoleUUID=role.RoleUUID, PermUUID=perm.PermUUID).exists():
|
||||
if LegacyRolePermission.objects.filter(role=role, permission=perm).exists():
|
||||
return Response({'code': 400, 'msg': '该角色已拥有此权限'})
|
||||
RolePermission.objects.create(
|
||||
RolePermUUID=uuid.uuid4().bytes,
|
||||
RoleUUID=role.RoleUUID,
|
||||
PermUUID=perm.PermUUID,
|
||||
CreateTime=timezone.now(),
|
||||
)
|
||||
LegacyRolePermission.objects.create(role=role, permission=perm)
|
||||
return Response({'code': 0, 'msg': '权限添加成功'})
|
||||
|
||||
elif action == 'remove_permission':
|
||||
perm_code = request.data.get('perm_code')
|
||||
if not perm_code:
|
||||
return Response({'code': 400, 'msg': '缺少权限编码'})
|
||||
if role.RoleName == '管理员' and perm_code == '000001':
|
||||
if role.role_name == '管理员' and perm_code == '000001':
|
||||
return Response({'code': 403, 'msg': '不能移除超级管理员的此权限'})
|
||||
try:
|
||||
perm = Permission.objects.get(PermCode=perm_code)
|
||||
except Permission.DoesNotExist:
|
||||
perm = BackendPermission.objects.filter(perm_code=perm_code).first()
|
||||
if not perm:
|
||||
return Response({'code': 404, 'msg': '权限不存在'})
|
||||
deleted, _ = RolePermission.objects.filter(RoleUUID=role.RoleUUID, PermUUID=perm.PermUUID).delete()
|
||||
deleted, _ = LegacyRolePermission.objects.filter(role=role, permission=perm).delete()
|
||||
if deleted == 0:
|
||||
return Response({'code': 400, 'msg': '该角色未拥有此权限'})
|
||||
return Response({'code': 0, 'msg': '权限移除成功'})
|
||||
@@ -272,45 +284,32 @@ class ModifyRolePermissionView(APIView):
|
||||
role_name = (request.data.get('role_name') or '').strip()
|
||||
description = (request.data.get('description') or '').strip()
|
||||
perm_codes = request.data.get('perm_codes') or []
|
||||
if role.RoleName == '管理员':
|
||||
role_name = role.RoleName
|
||||
elif role_name and role_name != role.RoleName:
|
||||
if Role.objects.filter(RoleName=role_name).exclude(RoleUUID=role.RoleUUID).exists():
|
||||
from backend.models import Role as BackendRole
|
||||
if role.role_name == '管理员':
|
||||
role_name = role.role_name
|
||||
elif role_name and role_name != role.role_name:
|
||||
if BackendRole.objects.filter(role_name=role_name).exclude(role_id=role.role_id).exists():
|
||||
return Response({'code': 400, 'msg': '角色名称已存在'})
|
||||
with transaction.atomic():
|
||||
if role.RoleName != '管理员':
|
||||
if role.role_name != '管理员':
|
||||
if role_name:
|
||||
role.RoleName = role_name
|
||||
role.RoleDesc = description
|
||||
role.save(update_fields=['RoleName', 'RoleDesc'])
|
||||
RolePermission.objects.filter(RoleUUID=role.RoleUUID).delete()
|
||||
role.role_name = role_name
|
||||
role.description = description
|
||||
role.save(update_fields=['role_name', 'description'])
|
||||
LegacyRolePermission.objects.filter(role=role).delete()
|
||||
for pc in perm_codes:
|
||||
if pc == '000001' and role.RoleName != '管理员':
|
||||
if pc == '000001' and role.role_name != '管理员':
|
||||
continue
|
||||
try:
|
||||
perm = Permission.objects.get(PermCode=pc, PermStatus=1)
|
||||
except Permission.DoesNotExist:
|
||||
perm = BackendPermission.objects.filter(perm_code=pc).first()
|
||||
if not perm:
|
||||
continue
|
||||
RolePermission.objects.create(
|
||||
RolePermUUID=uuid.uuid4().bytes,
|
||||
RoleUUID=role.RoleUUID,
|
||||
PermUUID=perm.PermUUID,
|
||||
CreateTime=timezone.now(),
|
||||
)
|
||||
if role.RoleName == '管理员':
|
||||
try:
|
||||
super_perm = Permission.objects.get(PermCode='000001', PermStatus=1)
|
||||
if not RolePermission.objects.filter(
|
||||
RoleUUID=role.RoleUUID, PermUUID=super_perm.PermUUID,
|
||||
).exists():
|
||||
RolePermission.objects.create(
|
||||
RolePermUUID=uuid.uuid4().bytes,
|
||||
RoleUUID=role.RoleUUID,
|
||||
PermUUID=super_perm.PermUUID,
|
||||
CreateTime=timezone.now(),
|
||||
)
|
||||
except Permission.DoesNotExist:
|
||||
pass
|
||||
LegacyRolePermission.objects.create(role=role, permission=perm)
|
||||
if role.role_name == '管理员':
|
||||
super_perm = BackendPermission.objects.filter(perm_code='000001').first()
|
||||
if super_perm and not LegacyRolePermission.objects.filter(
|
||||
role=role, permission=super_perm,
|
||||
).exists():
|
||||
LegacyRolePermission.objects.create(role=role, permission=super_perm)
|
||||
return Response({'code': 0, 'msg': '角色保存成功'})
|
||||
|
||||
else:
|
||||
@@ -339,47 +338,33 @@ class AddRoleView(APIView):
|
||||
if '000001' not in permissions:
|
||||
return Response({'code': 403, 'msg': '您无权进行此操作'})
|
||||
|
||||
# 检查角色名称是否已存在(同俱乐部内唯一)
|
||||
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,
|
||||
from backend.models import (
|
||||
Role as BackendRole,
|
||||
Permission as BackendPermission,
|
||||
RolePermission as LegacyRolePermission,
|
||||
)
|
||||
if role_name_exists(role_name, target_club_id):
|
||||
return Response({'code': 400, 'msg': '该俱乐部下角色名称已存在'})
|
||||
|
||||
# 生成唯一角色编码(格式:ROLE_ + 8位随机字母数字)
|
||||
if BackendRole.objects.filter(role_name=role_name).exists():
|
||||
return Response({'code': 400, 'msg': '角色名称已存在'})
|
||||
|
||||
role_code = f"ROLE_{''.join(random.choices(string.ascii_uppercase + string.digits, k=8))}"
|
||||
|
||||
# 创建角色
|
||||
with transaction.atomic():
|
||||
role = Role.objects.create(
|
||||
RoleUUID=uuid.uuid4().bytes,
|
||||
TenantUUID=b'\x00' * 16,
|
||||
RoleName=role_name,
|
||||
RoleType=2,
|
||||
RoleStatus=1,
|
||||
AssignScope=0,
|
||||
RoleDesc=description,
|
||||
ClubID=target_club_id,
|
||||
CreateTime=timezone.now(),
|
||||
role = BackendRole.objects.create(
|
||||
role_code=role_code,
|
||||
role_name=role_name,
|
||||
description=description,
|
||||
)
|
||||
# 绑定权限(过滤掉不存在的权限编码)
|
||||
for pc in perm_codes:
|
||||
# 不允许添加 000001 权限(此权限仅供超级管理员)
|
||||
if pc == '000001':
|
||||
continue
|
||||
try:
|
||||
perm = Permission.objects.get(PermCode=pc)
|
||||
RolePermission.objects.create(
|
||||
RolePermUUID=uuid.uuid4().bytes,
|
||||
RoleUUID=role.RoleUUID,
|
||||
PermUUID=perm.PermUUID,
|
||||
CreateTime=timezone.now(),
|
||||
)
|
||||
except Permission.DoesNotExist:
|
||||
perm = BackendPermission.objects.filter(perm_code=pc).first()
|
||||
if not perm:
|
||||
logger.warning(f"添加角色时忽略不存在的权限编码: {pc}")
|
||||
continue
|
||||
LegacyRolePermission.objects.create(role=role, permission=perm)
|
||||
|
||||
return Response({'code': 0, 'msg': '角色添加成功', 'data': {'role_code': role_code}})
|
||||
return Response({'code': 0, 'msg': '角色添加成功', 'data': {'role_code': role_name}})
|
||||
|
||||
|
||||
|
||||
@@ -418,15 +403,14 @@ class GetAdminUserListView(APIView):
|
||||
if nicheng:
|
||||
users = users.filter(KefuProfile__nicheng__icontains=nicheng)
|
||||
|
||||
# 关键修正:先求值为列表,再传入 phone__in
|
||||
if role_code:
|
||||
target_role = Role.objects.filter(RoleName=role_code).first()
|
||||
from backend.models import Role as BackendRole, UserRole as LegacyUserRole
|
||||
target_role = _resolve_backend_role(role_code)
|
||||
if target_role:
|
||||
user_uuids = list(
|
||||
UserRole.objects.filter(RoleUUID=target_role.RoleUUID)
|
||||
.values_list('UserUUID', flat=True)
|
||||
account_ids = list(
|
||||
LegacyUserRole.objects.filter(role=target_role).values_list('account_id', flat=True)
|
||||
)
|
||||
users = users.filter(UserUUID__in=user_uuids)
|
||||
users = users.filter(Phone__in=account_ids)
|
||||
else:
|
||||
users = users.none()
|
||||
|
||||
@@ -435,16 +419,12 @@ class GetAdminUserListView(APIView):
|
||||
page_obj = paginator.get_page(page)
|
||||
|
||||
data_list = []
|
||||
from backend.models import UserRole as LegacyUserRole
|
||||
for user in page_obj:
|
||||
# 通过 gvsdsdk UserRole 获取用户角色
|
||||
user_role_uuids = list(
|
||||
UserRole.objects.filter(UserUUID=user.UserUUID)
|
||||
.values_list('RoleUUID', flat=True)
|
||||
)
|
||||
user_roles = Role.objects.filter(RoleUUID__in=user_role_uuids)
|
||||
user_roles = LegacyUserRole.objects.filter(account_id=user.Phone).select_related('role')
|
||||
roles_data = [
|
||||
{'role_code': r.RoleName, 'role_name': r.RoleName}
|
||||
for r in user_roles
|
||||
{'role_code': ur.role.role_name, 'role_name': ur.role.role_name}
|
||||
for ur in user_roles
|
||||
]
|
||||
data_list.append({
|
||||
'phone': user.Phone or '',
|
||||
@@ -490,16 +470,16 @@ class GetAdminRolesView(APIView):
|
||||
if '000001' not in permissions:
|
||||
return Response({'code': 403, 'msg': '您无权访问此页面'})
|
||||
|
||||
from jituan.services.club_rbac import filter_roles_for_request
|
||||
roles = filter_roles_for_request(request).values('RoleName', 'ClubID')
|
||||
from backend.models import Role as BackendRole
|
||||
roles = BackendRole.objects.all().order_by('role_id')
|
||||
return Response({
|
||||
'code': 0,
|
||||
'data': {
|
||||
'roles': [
|
||||
{
|
||||
'role_code': r['RoleName'],
|
||||
'role_name': r['RoleName'],
|
||||
'club_id': r.get('ClubID') or '',
|
||||
'role_code': r.role_name,
|
||||
'role_name': r.role_name,
|
||||
'club_id': '',
|
||||
}
|
||||
for r in roles
|
||||
]
|
||||
@@ -638,25 +618,22 @@ 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
|
||||
club_id = getattr(target_user, 'ClubID', '') or ''
|
||||
from backend.models import Role as BackendRole, UserRole as LegacyUserRole
|
||||
added, missing = [], []
|
||||
for rc in role_codes:
|
||||
role = resolve_role_by_name(rc, club_id)
|
||||
role = _resolve_backend_role(rc)
|
||||
if not role:
|
||||
missing.append(rc)
|
||||
continue
|
||||
UserRole.objects.get_or_create(
|
||||
UserRoleUUID=uuid.uuid4().bytes,
|
||||
UserUUID=target_user.UserUUID,
|
||||
RoleUUID=role.RoleUUID,
|
||||
CompanyUUID=uuid.UUID('b0000000-0000-0000-0000-000000000001').bytes,
|
||||
LegacyUserRole.objects.get_or_create(
|
||||
account_id=target_user.Phone,
|
||||
role=role,
|
||||
)
|
||||
added.append(role.RoleName)
|
||||
added.append(role.role_name)
|
||||
if not added:
|
||||
return Response({
|
||||
'code': 400,
|
||||
'msg': f'未找到可绑定的角色:{", ".join(missing or role_codes)}。请确认顶栏俱乐部与角色所属俱乐部一致',
|
||||
'msg': f'未找到可绑定的角色:{", ".join(missing or role_codes)}',
|
||||
})
|
||||
if missing:
|
||||
return Response({
|
||||
@@ -669,12 +646,11 @@ 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
|
||||
club_id = getattr(target_user, 'ClubID', '') or ''
|
||||
role = resolve_role_by_name(role_code, club_id)
|
||||
from backend.models import UserRole as LegacyUserRole
|
||||
role = _resolve_backend_role(role_code)
|
||||
if not role:
|
||||
return Response({'code': 404, 'msg': '角色不存在或与用户俱乐部不匹配'})
|
||||
UserRole.objects.filter(UserUUID=target_user.UserUUID, RoleUUID=role.RoleUUID).delete()
|
||||
return Response({'code': 404, 'msg': '角色不存在'})
|
||||
LegacyUserRole.objects.filter(account_id=target_user.Phone, role=role).delete()
|
||||
return Response({'code': 0, 'msg': '角色移除成功'})
|
||||
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user