修正管理员权限判断
This commit is contained in:
@@ -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. 返回成功数据(管理员无 KefuProfile,nicheng 用 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,
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user