ai_admin/WebAdmin/user.py
2024-09-20 04:29:09 +00:00

447 lines
18 KiB
Python
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import re
from allauth.account.views import logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth.hashers import make_password
from django.contrib.auth import login as auth_login
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
import time
from django.db import connections
from .models import User, UserSource
import json
import logging
import requests
from django.http import JsonResponse, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from .mail import send_verification_email, verify_code
from .aliyun_sms import send_verification_sms, verify_sms_code
# 定义积分奖励值
REWARD_POINTS = 50 # 例如奖励50积分
def check_and_reward_points(user, openid):
"""
根据 openid 查询原系统会员状态,为原系统的用户增加一天会员时长(不论是否为会员)。
同时在新系统中奖励积分,并做好记录防止重复赠送或刷量。
:param user: 当前新系统中的用户
:param openid: 用户的 openid
:return: JSON 响应,包含奖励结果
"""
try:
# 检查当前用户是否已经使用过 openid 获得奖励,防止重复赠送
if user.openid_used:
return JsonResponse({'code': 400, 'message': '该用户已经通过 openid 获得过奖励', 'data': {}})
# 检查 openid 是否已被其他用户使用过,防止刷量
if User.objects.filter(openid_used=openid).exists():
return JsonResponse({'code': 400, 'message': '该 openid 已经被使用过', 'data': {}})
# 查询原系统数据库中的会员信息
with connections['external_db'].cursor() as cursor:
# 查询用户的 id、is_member 和 member_end_time
query = """
SELECT id, is_member, member_end_time
FROM user
WHERE openid = %s
"""
cursor.execute(query, [openid])
result = cursor.fetchone()
if not result:
return JsonResponse({'code': 404, 'message': '未找到此用户', 'data': {}})
user_id, is_member, member_end_time = result
# 保存用户原始的会员状态,用于后续判断
original_is_member = is_member
# 获取当前时间戳
current_timestamp = int(time.time())
one_day_seconds = 86400 # 一天的秒数
# 不管用户是否是会员,都在原系统中增加一天会员时长
# 如果用户不是会员,需要将 is_member 设置为 1
if is_member == 0:
is_member = 1 # 设置为会员
# 计算新的会员结束时间
if member_end_time and member_end_time > current_timestamp:
# 会员未过期,延长一天
new_member_end_time = member_end_time + one_day_seconds
else:
# 会员已过期或从未开通过会员,从当前时间开始加一天
new_member_end_time = current_timestamp + one_day_seconds
# 更新原系统用户的会员状态和结束时间
update_query = """
UPDATE user
SET is_member = %s,
member_end_time = %s
WHERE id = %s
"""
cursor.execute(update_query, [is_member, new_member_end_time, user_id])
# 提交事务
connections['external_db'].commit()
# 如果用户在原系统中原本是会员,额外奖励积分
if original_is_member == 1:
user.points += REWARD_POINTS
user.source = 'old_website_member' # 来源于旧网站会员
else:
user.source = 'old_website' # 来源于旧网站非会员
# 标记新系统用户的 openid 已使用
user.openid_used = openid
user.save()
return JsonResponse({
'code': 200,
'message': '成功奖励积分,并为原系统用户增加一天会员时长',
'data': {
'points': user.points
}
})
except Exception as e:
return JsonResponse({'code': 500, 'message': f'系统错误: {str(e)}', 'data': {}})
#登录后获取用户信息
@csrf_exempt
def user_profile(request):
# 验证用户是否已登录
if not request.user.is_authenticated:
return JsonResponse({'code': 401, 'message': '用户未登录'})
try:
user = request.user
openid = request.COOKIES.get('openid', None)
if openid:
# 调用检查会员状态并奖励积分的函数
reward_response = check_and_reward_points(user, openid)
print(f'用户注册登录:{reward_response}')
user_data = {
'id': user.id,
'username': user.username,
'email': user.email,
'phone': user.phone,
'is_member': user.is_member,
'points': user.points,
'referral_code': user.referral_code,
'commission_rate': user.commission_rate,
'login_count': user.login_count,
'last_login_ip': user.last_login_ip,
'membership_start': user.membership_start,
'membership_end': user.membership_end
}
return JsonResponse({'code': 200, 'message': '获取成功', 'data': user_data})
except:
return JsonResponse({'code': 400, 'message': '非法参数'})
#邮箱号码发送和核验部分:
@csrf_exempt
def send_verification_email_view(request):
if request.method == 'POST':
try:
body = json.loads(request.body)
email = body.get('phone_number')
if not email:
return JsonResponse({'code': 400, 'message': '邮箱地址是必须的'})
response = send_verification_email(email)
return JsonResponse(response)
except json.JSONDecodeError:
return JsonResponse({'code': 400, 'message': '无效的请求数据'})
except Exception as e:
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
else:
return JsonResponse({'code': 405, 'message': '方法不允许'})
@csrf_exempt
def verify_code_view(request):
if request.method == 'POST':
try:
body = json.loads(request.body)
email = body.get('phone_number')
code = body.get('code')
if not email or not code:
return JsonResponse({'code': 400, 'message': '邮箱和验证码是必须的'})
response = verify_code(email, code)
return JsonResponse(response)
except json.JSONDecodeError:
return JsonResponse({'code': 400, 'message': '无效的请求数据'})
except Exception as e:
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
else:
return JsonResponse({'code': 405, 'message': '方法不允许'})
@csrf_exempt
def send_verification_sms_view(request):
if request.method == 'POST':
try:
body = json.loads(request.body)
phone_number = body.get('phone_number')
if not phone_number:
return JsonResponse({'code': 400, 'message': '手机号码是必须的'})
sign_name = "福铭科技" # 替换为实际的签名名称
template_code = "SMS_299200388" # 替换为实际的短信模板代码
response = send_verification_sms(phone_number, sign_name, template_code)
return JsonResponse(response)
except json.JSONDecodeError:
return JsonResponse({'code': 400, 'message': '无效的请求数据'})
except Exception as e:
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
else:
return JsonResponse({'code': 405, 'message': '方法不允许'})
@csrf_exempt
def verify_sms_code_view(request):
if request.method == 'POST':
try:
body = json.loads(request.body)
phone_number = body.get('phone_number')
code = body.get('code')
if not phone_number or not code:
return JsonResponse({'code': 400, 'message': '手机号码和验证码是必须的'})
response = verify_sms_code(phone_number, code)
return JsonResponse(response)
except json.JSONDecodeError:
return JsonResponse({'code': 400, 'message': '无效的请求数据'})
except Exception as e:
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
else:
return JsonResponse({'code': 405, 'message': '方法不允许'})
#邮箱号码发送和核验部分END
#用户注册部分
@csrf_exempt
def register_view(request):
if request.method == 'POST':
try:
body = json.loads(request.body)
username = body.get('username')
password = body.get('password')
confirm_password = body.get('confirm_password')
email = body.get('email')
phone = body.get('phone')
code = body.get('code')
register_method = body.get('registerMethod')
if not username or not password or not confirm_password:
return JsonResponse({'code': 400, 'message': '用户名和密码是必须的'})
if password != confirm_password:
return JsonResponse({'code': 400, 'message': '两次密码输入不一致'})
if not validate_password_strength(password):
return JsonResponse({'code': 400, 'message': '密码强度不够'})
if User.objects.filter(phone=phone).exists():
return JsonResponse({'code': 400, 'message': '手机号已存在'})
if User.objects.filter(email=email).exists():
return JsonResponse({'code': 400, 'message': '此邮箱已存在'})
if User.objects.filter(username=username).exists():
return JsonResponse({'code': 400, 'message': '用户名已存在'})
if register_method == 'email':
if not email or not code:
return JsonResponse({'code': 400, 'message': '邮箱和验证码是必须的'})
try:
validate_email(email)
except ValidationError:
return JsonResponse({'code': 400, 'message': '无效的邮箱地址'})
email_verification_result = verify_code(email, code)
if email_verification_result['code'] != 200:
return JsonResponse(email_verification_result)
user = User.objects.create(username=username, email=email, password=make_password(password))
else:
if not phone or not code:
return JsonResponse({'code': 400, 'message': '手机号和验证码是必须的'})
sms_verification_result = verify_sms_code(phone, code)
if sms_verification_result['code'] != 200:
return JsonResponse(sms_verification_result)
user = User.objects.create(username=username, password=make_password(password))
user.phone = phone
user.save()
user.backend = 'allauth.account.auth_backends.AuthenticationBackend'
auth_login(request, user)
return JsonResponse({'code': 200, 'message': '注册成功'})
except json.JSONDecodeError:
return JsonResponse({'code': 400, 'message': '无效的请求数据'})
except Exception as e:
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
else:
return JsonResponse({'code': 405, 'message': '方法不允许'})
def validate_password_strength(password):
if len(password) < 6:
return False
if not re.search(r"[A-Za-z]", password) or not re.search(r"[0-9]", password):
return False
return True
#注册部分结束
#登录部分开始
@csrf_exempt
def login_view(request):
if request.method == 'POST':
try:
body = json.loads(request.body)
login_type = body.get('login_type')
if login_type == 'password':
username = body.get('username')
password = body.get('password')
if not username or not password:
return JsonResponse({'code': 400, 'message': '用户名和密码是必须的'})
# 验证用户名可以是邮箱或手机号
user = None
if re.match(r'^\S+@\S+\.\S+$', username): # 判断是否为邮箱
user = User.objects.filter(email=username).first()
elif re.match(r'^\d{11}$', username): # 判断是否为手机号
user = User.objects.filter(phone=username).first()
if user and user.check_password(password):
user.backend = 'allauth.account.auth_backends.AuthenticationBackend'
auth_login(request, user)
return JsonResponse({'code': 200, 'message': '登录成功'})
else:
return JsonResponse({'code': 400, 'message': '用户名或密码错误'})
elif login_type == 'code':
phone = body.get('phone')
code = body.get('code')
if not phone or not code:
return JsonResponse({'code': 400, 'message': '手机号和验证码是必须的'})
# 调用验证码核验接口
sms_verification_result = verify_sms_code(phone, code)
if sms_verification_result['code'] != 200:
return JsonResponse(sms_verification_result)
try:
user = User.objects.get(phone=phone)
if user:
user.backend = 'allauth.account.auth_backends.AuthenticationBackend'
auth_login(request, user)
return JsonResponse({'code': 200, 'message': '登录成功'})
else:
return JsonResponse({'code': 400, 'message': '用户不存在'})
except User.DoesNotExist:
return JsonResponse({'code': 400, 'message': '用户不存在'})
except Exception as e:
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
else:
return JsonResponse({'code': 400, 'message': '无效的登录类型'})
except json.JSONDecodeError:
return JsonResponse({'code': 400, 'message': '无效的请求数据'})
except Exception as e:
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
else:
return JsonResponse({'code': 405, 'message': '方法不允许'})
#找回密码开始
@csrf_exempt
def send_verification_code_view(request):
if request.method == 'POST':
try:
body = json.loads(request.body)
identifier = body.get('identifier')
if not identifier:
return JsonResponse({'code': 400, 'message': '手机号或邮箱是必须的'})
if '@' in identifier:
response = send_verification_email(identifier)
else:
response = send_verification_sms(identifier, "福铭科技", "SMS_299200388")
return JsonResponse(response)
except json.JSONDecodeError:
return JsonResponse({'code': 400, 'message': '无效的请求数据'})
except Exception as e:
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
else:
return JsonResponse({'code': 405, 'message': '方法不允许'})
@csrf_exempt
def reset_password_view(request):
if request.method == 'POST':
try:
body = json.loads(request.body)
identifier = body.get('identifier')
code = body.get('code')
new_password = body.get('new_password')
if not identifier or not code or not new_password:
return JsonResponse({'code': 400, 'message': '所有字段都是必须的'})
if '@' in identifier:
verification_result = verify_code(identifier, code)
else:
verification_result = verify_sms_code(identifier, code)
if verification_result['code'] != 200:
return JsonResponse(verification_result)
if not validate_password_strength(new_password):
return JsonResponse({'code': 400, 'message': '密码强度不够'})
if '@' in identifier:
user = User.objects.get(email=identifier)
else:
user = User.objects.get(phone=identifier)
user.password = make_password(new_password)
user.save()
return JsonResponse({'code': 200, 'message': '密码重置成功'})
except User.DoesNotExist:
return JsonResponse({'code': 400, 'message': '用户不存在'})
except json.JSONDecodeError:
return JsonResponse({'code': 400, 'message': '无效的请求数据'})
except Exception as e:
return JsonResponse({'code': 500, 'message': f'服务器内部错误: {str(e)}'})
else:
return JsonResponse({'code': 405, 'message': '方法不允许'})
#找回密码结束
#退出登录开始
@csrf_exempt
def logout_view(request):
"""
用户退出登录接口
"""
if request.method == 'POST':
# 执行 Django 的内置 logout 函数,清除用户的 session
logout(request)
return JsonResponse({'code': 200, 'message': 'ok','data': {}})
return JsonResponse({'code': 405, 'message': 'no','data': {}})
#退出登录结束