fix: 修复换打手权限、后台用户重复创建及角色绑定
This commit is contained in:
@@ -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):
|
||||
|
||||
104
backend/view.py
104
backend/view.py
@@ -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': '该账号已存在'})
|
||||
|
||||
# 生成唯一的 yonghuid(7位数字)
|
||||
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():
|
||||
# 生成唯一的 yonghuid(7位数字)
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user