修改了鉴权模型,使用 GVSDSDK 来修正

This commit is contained in:
2026-06-18 23:51:33 +08:00
parent 38fcfd730c
commit d3903c913b
2 changed files with 114 additions and 99 deletions

View File

@@ -5,8 +5,9 @@ from functools import lru_cache
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q
from rest_framework.response import Response
from .models import AbnormalUserLog, UserRole, RolePermission, Permission, PlayerDailyStats, MerchantDailyStats, \
from .models import AbnormalUserLog, PlayerDailyStats, MerchantDailyStats, \
ManagerRenewalDailyStats, ManagerDailyStats, LeaderDailyStats, WithdrawalDailyStats
from gvsdsdk.models import UserRole as SdkUserRole, RolePermission as SdkRolePermission, Permission as SdkPermission
from django.db import transaction
from django.db.models import F
@@ -97,44 +98,30 @@ def verify_kefu_permission(request, username_from_frontend=None):
}, status=403)
# ---------- 4. 获取用户的所有权限 ----------
# 优先从 RBAC 表获取,若 RBAC 表不存在/无数据则回退到旧 account_permission 表
# 使用 gvsdsdk RBAC 表UserRole → RolePermission → Permission
try:
user_roles = UserRole.query.filter(account_id=current_user.phone).select_related('role')
role_ids = [ur.role_id for ur in user_roles]
if role_ids:
perm_ids = RolePermission.query.filter(role_id__in=role_ids).values_list('permission_id', flat=True)
permissions = list(Permission.query.filter(
perm_id__in=perm_ids
).values_list('perm_code', flat=True).distinct())
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 = []
except Exception:
permissions = []
# RBAC 无数据时,回退到旧 account_permission 表
if not permissions:
try:
from config.models import AccountPermission
old_perms = AccountPermission.query.filter(
account_id=current_user.phone,
is_enabled=True
).values_list('permission_code', flat=True)
# 旧权限码映射到新权限编码
perm_code_map = {
1: '001', # 超级管理员
2: '002ab', # 平台订单管理
3: '002ac', # 处罚管理
4: '002ad', # 退款管理
5: '002ae', # 店铺管理
6: '002af', # 商品审核
7: '002ag', # 提现审核
8: '002ah', # 用户管理
9: '002ai', # 数据统计
10: '002aj', # 系统配置
}
permissions = [perm_code_map.get(code, str(code)) for code in old_perms if code in perm_code_map]
except Exception:
permissions = []
# 超级用户自动拥有所有权限
if current_user.IsSuperuser and '000001' not in permissions:
permissions.insert(0, '000001')
if not permissions:
logger.warning(f"用户 {current_user.phone} 没有任何权限,请检查角色分配")

View File

@@ -51,8 +51,10 @@ from .utils import (
)
# models 集中导入
## gvsdsdk RBAC 模型(使用 PascalCase 字段名,匹配实际数据库表结构)
from gvsdsdk.models import Role, Permission, RolePermission, UserRole
## backend
from backend.models import Role, Permission, RolePermission, UserRole, WithdrawalDailyStats
from backend.models import WithdrawalDailyStats
## users
from users.models import (
@@ -119,29 +121,26 @@ class GetRolePermissionView(APIView):
return Response({'code': 403, 'msg': '您无权访问此页面'})
# 3. 获取所有权限
all_perms = Permission.query.all().values('perm_code', 'perm_name', 'description')
all_perms = Permission.objects.filter(PermStatus=1).values('PermCode', 'PermName', 'PermDesc')
permissions_list = list(all_perms)
# 4. 获取所有角色,并统计每个角色下的用户数和关联的权限
roles = Role.query.all()
roles = Role.objects.filter(RoleStatus=1)
roles_data = []
for role in roles:
# 统计该角色下的用户数
user_count = UserRole.query.filter(role=role).count()
user_count = UserRole.objects.filter(RoleUUID=role.RoleUUID).count()
# 获取该角色绑定的权限
role_perms = RolePermission.query.filter(role=role).select_related('permission')
perms_of_role = [
{
'perm_code': rp.permission.perm_code,
'perm_name': rp.permission.perm_name,
'description': rp.permission.description
}
for rp in role_perms
]
role_perm_uuids = RolePermission.objects.filter(
RoleUUID=role.RoleUUID
).values_list('PermUUID', flat=True)
perms_of_role = list(Permission.objects.filter(
PermUUID__in=list(role_perm_uuids)
).values('PermCode', 'PermName', 'PermDesc'))
roles_data.append({
'role_code': role.role_code,
'role_name': role.role_name,
'description': role.description,
'role_code': role.RoleName,
'role_name': role.RoleName,
'description': role.RoleDesc,
'user_count': user_count,
'permissions': perms_of_role
})
@@ -175,28 +174,27 @@ class ModifyRolePermissionView(APIView):
if '000001' not in permissions:
return Response({'code': 403, 'msg': '您无权进行此操作'})
# 获取角色(需要角色编码
# 获取角色(需要角色名称
role_code = request.data.get('role_code')
if not role_code:
return Response({'code': 400, 'msg': '缺少角色编码'})
try:
role = Role.query.get(role_code=role_code)
role = Role.objects.get(RoleName=role_code)
except Role.DoesNotExist:
return Response({'code': 404, 'msg': '角色不存在'})
# 超级管理员角色role_code='000001'的特殊限制
if role.role_code == '000001':
# 超级管理员角色的特殊限制
if role.RoleName == '管理员':
if action in ['delete_role']:
return Response({'code': 403, 'msg': '超级管理员角色不能删除'})
# 修改名称/描述(本接口不涉及名称描述修改,但若后续扩展需限制)
# 根据 action 处理
if action == 'delete_role':
# 删除角色:同时删除角色权限关联、用户角色关联
with transaction.atomic():
RolePermission.query.filter(role=role).delete()
UserRole.query.filter(role=role).delete()
RolePermission.objects.filter(RoleUUID=role.RoleUUID).delete()
UserRole.objects.filter(RoleUUID=role.RoleUUID).delete()
role.delete()
return Response({'code': 0, 'msg': '角色删除成功'})
@@ -204,32 +202,35 @@ class ModifyRolePermissionView(APIView):
perm_code = request.data.get('perm_code')
if not perm_code:
return Response({'code': 400, 'msg': '缺少权限编码'})
# 超级管理员角色不能添加 000001 权限(但实际它已拥有,这里防御)
if role.role_code == '000001' and perm_code == '000001':
if role.RoleName == '管理员' and perm_code == '000001':
return Response({'code': 403, 'msg': '此权限已存在,不能重复添加'})
try:
perm = Permission.query.get(perm_code=perm_code)
perm = Permission.objects.get(PermCode=perm_code)
except Permission.DoesNotExist:
return Response({'code': 404, 'msg': '权限不存在'})
# 检查是否已存在
if RolePermission.query.filter(role=role, permission=perm).exists():
if RolePermission.objects.filter(RoleUUID=role.RoleUUID, PermUUID=perm.PermUUID).exists():
return Response({'code': 400, 'msg': '该角色已拥有此权限'})
RolePermission.query.create(role=role, permission=perm)
RolePermission.objects.create(
RolePermUUID=uuid.uuid4().bytes,
RoleUUID=role.RoleUUID,
PermUUID=perm.PermUUID,
CreateTime=timezone.now(),
)
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': '缺少权限编码'})
# 超级管理员角色不能删除 000001 权限
if role.role_code == '000001' and perm_code == '000001':
if role.RoleName == '管理员' and perm_code == '000001':
return Response({'code': 403, 'msg': '不能移除超级管理员的此权限'})
try:
perm = Permission.query.get(perm_code=perm_code)
perm = Permission.objects.get(PermCode=perm_code)
except Permission.DoesNotExist:
return Response({'code': 404, 'msg': '权限不存在'})
deleted = RolePermission.query.filter(role=role, permission=perm).delete()
if deleted[0] == 0:
deleted, _ = RolePermission.objects.filter(RoleUUID=role.RoleUUID, PermUUID=perm.PermUUID).delete()
if deleted == 0:
return Response({'code': 400, 'msg': '该角色未拥有此权限'})
return Response({'code': 0, 'msg': '权限移除成功'})
@@ -260,23 +261,23 @@ class AddRoleView(APIView):
return Response({'code': 403, 'msg': '您无权进行此操作'})
# 检查角色名称是否已存在
if Role.query.filter(role_name=role_name).exists():
if Role.objects.filter(RoleName=role_name).exists():
return Response({'code': 400, 'msg': '角色名称已存在'})
# 生成唯一角色编码格式ROLE_ + 8位随机字母数字
while True:
random_str = ''.join(random.choices(string.ascii_uppercase + string.digits, k=8))
role_code = f"ROLE_{random_str}"
if not Role.query.filter(role_code=role_code).exists():
break
role_code = f"ROLE_{''.join(random.choices(string.ascii_uppercase + string.digits, k=8))}"
# 创建角色
with transaction.atomic():
role = Role.query.create(
role_code=role_code,
role_name=role_name,
description=description,
role = Role.objects.create(
RoleUUID=uuid.uuid4().bytes,
TenantUUID=b'\x00' * 16,
RoleName=role_name,
RoleType=2,
RoleStatus=1,
AssignScope=0,
RoleDesc=description,
CreateTime=timezone.now(),
)
# 绑定权限(过滤掉不存在的权限编码)
for pc in perm_codes:
@@ -284,12 +285,15 @@ class AddRoleView(APIView):
if pc == '000001':
continue
try:
perm = Permission.query.get(perm_code=pc)
RolePermission.query.create(role=role, permission=perm)
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:
# 忽略不存在的权限,或记录日志
logger.warning(f"添加角色时忽略不存在的权限编码: {pc}")
pass
return Response({'code': 0, 'msg': '角色添加成功', 'data': {'role_code': role_code}})
@@ -328,11 +332,21 @@ class GetAdminUserListView(APIView):
# 关键修正:先求值为列表,再传入 phone__in
if role_code:
user_ids_with_role = list(
UserRole.query.filter(role__role_code=role_code)
.values_list('account_id', flat=True)
)
users = users.filter(phone__in=user_ids_with_role)
# 通过 gvsdsdk UserRole 查询拥有该角色的用户
target_role = Role.objects.filter(RoleName=role_code).first()
if target_role:
user_uuids = list(
UserRole.objects.filter(RoleUUID=target_role.RoleUUID)
.values_list('UserUUID', flat=True)
)
# 将 UserUUID 转为 phone 列表
user_phones = list(
User.objects.filter(UserUUID__in=user_uuids)
.values_list('Phone', flat=True)
)
users = users.filter(phone__in=user_phones)
else:
users = users.none()
users = users.order_by('-create_time')
paginator = Paginator(users, page_size)
@@ -340,10 +354,15 @@ class GetAdminUserListView(APIView):
data_list = []
for user in page_obj:
user_roles = UserRole.query.filter(account_id=user.phone).select_related('role')
# 通过 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)
roles_data = [
{'role_code': ur.role.role_code, 'role_name': ur.role.role_name}
for ur in user_roles
{'role_code': r.RoleName, 'role_name': r.RoleName}
for r in user_roles
]
data_list.append({
'phone': user.phone,
@@ -385,11 +404,11 @@ class GetAdminRolesView(APIView):
if '000001' not in permissions:
return Response({'code': 403, 'msg': '您无权访问此页面'})
roles = Role.query.all().values('role_code', 'role_name')
roles = Role.objects.filter(RoleStatus=1).values('RoleName')
return Response({
'code': 0,
'data': {
'roles': list(roles)
'roles': [{'role_code': r['RoleName'], 'role_name': r['RoleName']} for r in roles]
}
})
@@ -525,10 +544,15 @@ class ModifyAdminUserView(APIView):
return Response({'code': 400, 'msg': '请选择角色'})
for rc in role_codes:
try:
role = Role.query.get(role_code=rc)
role = Role.objects.get(RoleName=rc)
except Role.DoesNotExist:
continue
UserRole.query.get_or_create(account_id=target_phone, role=role)
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,
)
return Response({'code': 0, 'msg': '角色添加成功'})
elif action == 'remove_user_role':
@@ -536,10 +560,10 @@ class ModifyAdminUserView(APIView):
if not role_code:
return Response({'code': 400, 'msg': '缺少角色编码'})
try:
role = Role.query.get(role_code=role_code)
role = Role.objects.get(RoleName=role_code)
except Role.DoesNotExist:
return Response({'code': 404, 'msg': '角色不存在'})
UserRole.query.filter(account_id=target_phone, role=role).delete()
UserRole.objects.filter(UserUUID=target_user.UserUUID, RoleUUID=role.RoleUUID).delete()
return Response({'code': 0, 'msg': '角色移除成功'})
else:
@@ -612,7 +636,6 @@ class AddAdminUserView(APIView):
zhuangtai=1
)
# 分配客服角色
from gvsdsdk.models import UserRole, Role
kefu_role = Role.objects.filter(RoleName='客服').first()
if kefu_role:
UserRole.objects.create(
@@ -621,11 +644,16 @@ class AddAdminUserView(APIView):
RoleUUID=kefu_role.RoleUUID,
CompanyUUID=uuid.UUID('b0000000-0000-0000-0000-000000000001').bytes,
)
# 分配角色
# 分配额外角色
for rc in role_codes:
try:
role = Role.query.get(role_code=rc)
UserRole.query.create(account_id=phone, role=role)
role = Role.objects.get(RoleName=rc)
UserRole.objects.create(
UserRoleUUID=uuid.uuid4().bytes,
UserUUID=user_main.UserUUID,
RoleUUID=role.RoleUUID,
CompanyUUID=uuid.UUID('b0000000-0000-0000-0000-000000000001').bytes,
)
except Role.DoesNotExist:
pass