修正管理员权限判断

This commit is contained in:
2026-06-19 13:08:12 +08:00
parent ce0fb79b39
commit 4963b06e21
2 changed files with 55 additions and 34 deletions

View File

@@ -140,14 +140,6 @@ def verify_kefu_permission(request, username_from_frontend=None):
if '000001' in permissions:
permissions = _AllPermissions(permissions)
# 临时调试日志 — 诊断管理员权限问题
logger.warning(
f"[权限调试] Phone={current_user.Phone} UserType={current_user.UserType} "
f"IsSuperuser={current_user.IsSuperuser} is_admin={is_admin} "
f"perms_type={type(permissions).__name__} perms_len={len(permissions)} "
f"has_000001={'000001' in permissions} is_AllPerm={isinstance(permissions, _AllPermissions)}"
)
if not permissions:
logger.warning(f"用户 {current_user.Phone} 没有任何权限,请检查角色分配")

View File

@@ -6706,13 +6706,15 @@ class ShangjiaChufaJiluHuoquView(APIView):
class KefuLoginView(APIView):
"""
客服登录接口(支持手机号重复)
客服/管理员登录接口(支持手机号重复)
请求POST /yonghu/kefujinru
请求体:{"phone": "13800138000", "password": "xxx", "erjimima": "yyy"}
返回:
code=0 成功data包含token,nicheng,yonghuid
code=4 账号被封禁(提示“账号已被封禁”
其他错误统一 code=1 msg="登录失败"
code=1 失败msg区分用户不存在/密码错误/二级密码错误
code=4 账号被封禁
管理员IsSuperuser 或 UserType='admin')无需 erjimima 和 KefuProfile。
"""
throttle_classes = [AnonRateThrottle] # 限制匿名请求频率
permission_classes = [AllowAny] # 任何人都可访问
@@ -6723,41 +6725,61 @@ class KefuLoginView(APIView):
password = request.data.get('password', '')
erjimima = request.data.get('erjimima', '')
if not phone or not password or not erjimima:
if not phone or not password:
return Response({
'code': 1,
'msg': '登录失败', # 统一提示,不暴露具体原因
'msg': '请填写手机号和密码',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
# 2. 获取客户端真实IP
client_ip = self.get_client_ip(request)
# 3. 查询该手机号下所有客服账号(User 字段为 Phone与 backend 创建客服校验写法一致
user_mains = User.query.filter(
Phone=phone,
KefuProfile__isnull=False,
).select_related('KefuProfile')
# 3. 查询该手机号下所有账号(客服 + 管理员
# 先查客服(有 KefuProfile再查管理员IsSuperuser 或 UserType='admin'
user_mains = list(
User.query.filter(
Phone=phone,
KefuProfile__isnull=False,
).select_related('KefuProfile')
)
if not user_mains.exists():
logger.warning(f"登录失败,手机号不存在或非客服: {phone}, IP: {client_ip}")
# 如果没有客服账号,尝试查找管理员账号
if not user_mains:
admin_candidates = User.query.filter(Phone=phone)
for admin_user in admin_candidates:
if admin_user.IsSuperuser or admin_user.UserType == 'admin':
user_mains = [admin_user]
break
if not user_mains:
logger.warning(f"登录失败,用户不存在: {phone}, IP: {client_ip}")
return Response({
'code': 1,
'msg': '登录失败',
'msg': '用户不存在',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
# 4. 遍历所有匹配的客服账号,验证密码和二级密码
# 4. 遍历所有匹配的账号,验证密码和二级密码
target_user = None
target_kefu = None
password_matched = False
for user in user_mains:
kefu = user.KefuProfile
# 验证主密码bcrypt 哈希验证)
if not user.CheckPassword(password):
continue
password_matched = True
# 验证二级密码(兼容 bcrypt 哈希和明文)
# 管理员:跳过二级密码和客服扩展表检查
is_admin = user.IsSuperuser or user.UserType == 'admin'
if is_admin:
target_user = user
target_kefu = None
break
# 客服:验证二级密码
kefu = user.KefuProfile
stored_erji = kefu.erjimima or ''
if stored_erji.startswith(('$2b$', '$2a$')) and len(stored_erji) == 60:
import bcrypt as _bcrypt
@@ -6766,11 +6788,9 @@ class KefuLoginView(APIView):
elif stored_erji != erjimima:
continue
# 如果账号被禁用,记录但继续查找(可能还有其他正常账号?)
# 如果账号被禁用,记录但继续查找
if kefu.zhuangtai != 1:
# 如果找到被禁用的,记录下来,但继续查找是否有正常账号
if target_user is None:
# 暂时记录这个禁用账号,但继续遍历
target_user = user
target_kefu = kefu
continue
@@ -6780,7 +6800,7 @@ class KefuLoginView(APIView):
target_kefu = kefu
break
else:
# 循环结束未找到正常账号,但可能找到了禁用账号
# 循环结束未找到正常账号
if target_user and target_kefu:
# 只有被禁用的账号匹配,返回封禁提示
logger.warning(f"登录失败,客服账号已禁用: {phone}, IP: {client_ip}")
@@ -6789,12 +6809,20 @@ class KefuLoginView(APIView):
'msg': '账号已被封禁',
'data': None
}, status=status.HTTP_403_FORBIDDEN)
else:
# 没有任何账号匹配(密码/二级密码错误
logger.warning(f"登录失败,密码或二级密码错误: {phone}, IP: {client_ip}")
elif password_matched:
# 密码正确但二级密码错误
logger.warning(f"登录失败,二级密码错误: {phone}, IP: {client_ip}")
return Response({
'code': 1,
'msg': '登录失败',
'msg': '二级密码错误',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
else:
# 密码错误
logger.warning(f"登录失败,密码错误: {phone}, IP: {client_ip}")
return Response({
'code': 1,
'msg': '密码错误',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
@@ -6807,13 +6835,14 @@ class KefuLoginView(APIView):
refresh = RefreshToken.for_user(target_user)
token = str(refresh.access_token)
# 7. 返回成功数据
# 7. 返回成功数据(管理员无 KefuProfilenicheng 用 UserName 或 Phone 兜底)
nicheng = target_kefu.nicheng if target_kefu else (target_user.UserName or target_user.Phone)
return Response({
'code': 0,
'msg': '登录成功',
'data': {
'token': token,
'nicheng': target_kefu.nicheng,
'nicheng': nicheng,
'yonghuid': target_user.UserUID,
}
})