fix: 修复换打手权限、后台用户重复创建及角色绑定

This commit is contained in:
XingQue
2026-07-02 02:20:29 +08:00
parent c21168ad2d
commit 5d20d1a25e
2 changed files with 69 additions and 42 deletions

View File

@@ -77,6 +77,13 @@ class _AllPermissions(list):
return True
def has_merchant_order_permission(permissions):
"""商家/链接订单处理权限002ac 商家订单、002ab 平台订单、003aa 跨平台。"""
if isinstance(permissions, _AllPermissions):
return True
return any(p in permissions for p in ('002ac', '002ab', '003aa'))
def _legacy_backend_role_permissions(phone):
"""
读取旧权限表backend.models

View File

@@ -53,6 +53,7 @@ from .utils import (
PERMISSION_TO_SHENFEN,
SHENFEN_PROFILE_MAP,
has_fadan_view_permission,
has_merchant_order_permission,
check_fadan_permission,
pick_order_id,
pick_penalty_create_params,
@@ -646,13 +647,18 @@ class ModifyAdminUserView(APIView):
if not role:
missing.append(rc)
continue
UserRole.objects.get_or_create(
UserRoleUUID=uuid.uuid4().bytes,
_, created = UserRole.objects.get_or_create(
UserUUID=target_user.UserUUID,
RoleUUID=role.RoleUUID,
CompanyUUID=uuid.UUID('b0000000-0000-0000-0000-000000000001').bytes,
defaults={
'UserRoleUUID': uuid.uuid4().bytes,
'CompanyUUID': uuid.UUID('b0000000-0000-0000-0000-000000000001').bytes,
},
)
added.append(role.RoleName)
if created:
added.append(role.RoleName)
elif role.RoleName not in added:
added.append(role.RoleName)
if not added:
return Response({
'code': 400,
@@ -710,33 +716,46 @@ class AddAdminUserView(APIView):
if len(password) < 6 or len(erjimima) < 6:
return Response({'code': 400, 'msg': '密码和二级密码至少6位'})
# 校验手机号是否已被客服占用
if User.query.filter(Phone=phone, KefuProfile__isnull=False).exists():
from jituan.services.club_context import resolve_club_id_from_request
from jituan.services.club_rbac import resolve_role_by_name
target_club_id = resolve_club_id_from_request(request)
# 校验手机号是否已被后台客服占用(同俱乐部优先)
existing_kefu = User.query.filter(
Phone=phone, KefuProfile__isnull=False
).order_by('-UserCreateTime').first()
if existing_kefu:
return Response({'code': 400, 'msg': '该账号已存在'})
# 生成唯一的 yonghuid7位数字
while True:
yonghuid = str(random.randint(1000000, 9999999))
if not User.query.filter(UserUID=yonghuid).exists():
break
with transaction.atomic():
# 事务内二次校验,防止并发重复创建
if User.query.filter(Phone=phone, KefuProfile__isnull=False).exists():
return Response({'code': 400, 'msg': '该账号已存在'})
# 生成唯一的 openid格式admin_{时间戳}_{随机6位}
timestamp = str(int(time.time() * 1000))
random_suffix = ''.join(random.choices(string.ascii_lowercase + string.digits, k=6))
openid = f"admin_{timestamp}_{random_suffix}"
while User.query.filter(OpenID=openid).exists():
# 生成唯一的 yonghuid7位数字
while True:
yonghuid = str(random.randint(1000000, 9999999))
if not User.query.filter(UserUID=yonghuid).exists():
break
# 生成唯一的 openid格式admin_{时间戳}_{随机6位}
timestamp = str(int(time.time() * 1000))
random_suffix = ''.join(random.choices(string.ascii_lowercase + string.digits, k=6))
openid = f"admin_{timestamp}_{random_suffix}"
while User.query.filter(OpenID=openid).exists():
random_suffix = ''.join(random.choices(string.ascii_lowercase + string.digits, k=6))
openid = f"admin_{timestamp}_{random_suffix}"
with transaction.atomic():
user_main = User.query.create(
UserUID=yonghuid,
UserName=openid,
OpenID=openid,
Phone=phone,
ClubID=target_club_id,
)
user_main.SetPassword(password)
user_main.save(update_fields=['UserPassword'])
user_main.save(update_fields=['UserPassword', 'ClubID'])
# 创建客服扩展表(后台用户扩展)
import bcrypt as _bcrypt
erjimima_hashed = _bcrypt.hashpw(erjimima.encode('utf-8'), _bcrypt.gensalt(rounds=12)).decode('utf-8')
@@ -746,27 +765,28 @@ class AddAdminUserView(APIView):
erjimima=erjimima_hashed,
zhuangtai=1
)
# 分配客服角色
kefu_role = Role.objects.filter(RoleName='客服').first()
if kefu_role:
UserRole.objects.create(
UserRoleUUID=uuid.uuid4().bytes,
# 分配角色(默认客服 + 所选角色,按俱乐部解析,去重)
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(
UserUUID=user_main.UserUUID,
RoleUUID=kefu_role.RoleUUID,
CompanyUUID=uuid.UUID('b0000000-0000-0000-0000-000000000001').bytes,
RoleUUID=role.RoleUUID,
defaults={
'UserRoleUUID': uuid.uuid4().bytes,
'CompanyUUID': uuid.UUID('b0000000-0000-0000-0000-000000000001').bytes,
},
)
# 分配额外角色
for rc in role_codes:
try:
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
return Response({'code': 0, 'msg': '添加成功'})
@@ -8536,7 +8556,7 @@ class ZxkfghdsView(APIView):
4. 生成新的派单链接,并标记为已使用
5. 新链接记录上一个链接ID和上一个订单ID
6. 【关键】不操作商家余额、退款次数、每日统计,因新订单是替换而非新增扣款
权限:需要'003aa'(跨平台管理)权限,与退款接口一致
权限:002ac商家订单管理/ 002ab平台订单管理/ 003aa跨平台管理
"""
permission_classes = [IsAuthenticated]
@@ -8544,17 +8564,17 @@ class ZxkfghdsView(APIView):
def post(self, request):
# ========== 1. 参数提取 ==========
username = request.data.get('username', '').strip()
username = request.data.get('username', '').strip() or request.data.get('phone', '').strip()
OrderID = pick_order_id(request.data)
if not username or not OrderID:
logger.warning("更换打手参数不完整")
return Response({'code': 400, 'msg': '参数不完整'})
# ========== 2. 权限校验(与跨平台退款相同 ==========
# ========== 2. 权限校验(商家链接页客服需 002ac非仅跨平台 003aa ==========
kefu, permissions = verify_kefu_permission(request, username)
if kefu is None:
return permissions # 返回错误响应
if '003aa' not in permissions:
return permissions # 返回 error response
if not has_merchant_order_permission(permissions):
return Response({'code': 403, 'msg': '您无权处理订单'})
current_user = request.user