This commit is contained in:
2025-11-28 21:20:40 +08:00
commit f940b95b67
73 changed files with 15721 additions and 0 deletions

276
routes/auth.py Normal file
View File

@@ -0,0 +1,276 @@
from flask import Blueprint, request, jsonify, session
from flask_login import login_user, logout_user, login_required, current_user
from models import User, EmailVerification
from models import db
from utils.security import hash_password, verify_password, generate_verification_code, get_client_ip
from utils.email import EmailService
from datetime import datetime, timedelta
import re
auth_bp = Blueprint('auth', __name__)
def validate_email(email):
"""验证邮箱格式"""
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return re.match(pattern, email) is not None
@auth_bp.route('/send-code', methods=['POST'])
def send_verification_code():
"""发送验证码"""
data = request.get_json()
email = data.get('email')
purpose = data.get('purpose', 'register')
if not email or not validate_email(email):
return jsonify({'success': False, 'message': '邮箱格式不正确'}), 400
# 检查用户是否已存在
if purpose == 'register':
if User.query.filter_by(email=email).first():
return jsonify({'success': False, 'message': '该邮箱已被注册'}), 400
elif purpose in ['reset_password', 'forgot_password']:
if not User.query.filter_by(email=email).first():
return jsonify({'success': False, 'message': '该邮箱未注册'}), 400
# 生成验证码
code = generate_verification_code(6)
expires_at = datetime.utcnow() + timedelta(minutes=10)
# 保存验证码
verification = EmailVerification(
email=email,
code=code,
purpose=purpose,
expires_at=expires_at
)
db.session.add(verification)
db.session.commit()
# 发送邮件
try:
EmailService.send_verification_code(email, code, purpose)
return jsonify({'success': True, 'message': '验证码已发送'})
except Exception as e:
return jsonify({'success': False, 'message': str(e)}), 500
@auth_bp.route('/register', methods=['GET', 'POST'])
def register():
"""用户注册"""
if request.method == 'GET':
from flask import render_template
return render_template('register.html')
data = request.get_json()
username = data.get('username')
email = data.get('email')
password = data.get('password')
code = data.get('code')
# 验证输入
if not all([username, email, password, code]):
return jsonify({'success': False, 'message': '请填写完整信息'}), 400
if not validate_email(email):
return jsonify({'success': False, 'message': '邮箱格式不正确'}), 400
if len(password) < 6:
return jsonify({'success': False, 'message': '密码长度至少6位'}), 400
# 检查用户名和邮箱是否已存在
if User.query.filter_by(username=username).first():
return jsonify({'success': False, 'message': '用户名已存在'}), 400
if User.query.filter_by(email=email).first():
return jsonify({'success': False, 'message': '邮箱已被注册'}), 400
# 验证验证码
verification = EmailVerification.query.filter_by(
email=email,
code=code,
purpose='register',
is_used=False
).filter(EmailVerification.expires_at > datetime.utcnow()).first()
if not verification:
return jsonify({'success': False, 'message': '验证码无效或已过期'}), 400
# 创建用户
user = User(
username=username,
email=email,
password=hash_password(password),
register_ip=get_client_ip(request),
group_id=2 # 默认普通用户
)
db.session.add(user)
# 标记验证码已使用
verification.is_used = True
db.session.commit()
return jsonify({'success': True, 'message': '注册成功'})
@auth_bp.route('/login', methods=['GET', 'POST'])
def login():
"""用户登录"""
if request.method == 'GET':
from flask import render_template
return render_template('login.html')
data = request.get_json()
email = data.get('email')
password = data.get('password')
if not all([email, password]):
return jsonify({'success': False, 'message': '请填写完整信息'}), 400
user = User.query.filter_by(email=email).first()
if not user or not verify_password(password, user.password):
return jsonify({'success': False, 'message': '邮箱或密码错误'}), 401
if not user.is_active:
return jsonify({'success': False, 'message': '账号已被禁用'}), 403
# 更新登录信息
user.last_login_ip = get_client_ip(request)
db.session.commit()
# 登录用户
login_user(user)
return jsonify({
'success': True,
'message': '登录成功',
'user': {
'id': user.id,
'username': user.username,
'email': user.email
}
})
@auth_bp.route('/logout', methods=['POST'])
@login_required
def logout():
"""用户登出"""
logout_user()
return jsonify({'success': True, 'message': '已退出登录'})
@auth_bp.route('/reset-password', methods=['POST'])
def reset_password():
"""重置密码"""
data = request.get_json()
email = data.get('email')
code = data.get('code')
new_password = data.get('new_password')
if not all([email, code, new_password]):
return jsonify({'success': False, 'message': '请填写完整信息'}), 400
if len(new_password) < 6:
return jsonify({'success': False, 'message': '密码长度至少6位'}), 400
# 验证验证码
verification = EmailVerification.query.filter_by(
email=email,
code=code,
is_used=False
).filter(
EmailVerification.purpose.in_(['reset_password', 'forgot_password'])
).filter(EmailVerification.expires_at > datetime.utcnow()).first()
if not verification:
return jsonify({'success': False, 'message': '验证码无效或已过期'}), 400
# 更新密码
user = User.query.filter_by(email=email).first()
if not user:
return jsonify({'success': False, 'message': '用户不存在'}), 404
user.password = hash_password(new_password)
verification.is_used = True
db.session.commit()
return jsonify({'success': True, 'message': '密码重置成功'})
@auth_bp.route('/user-info', methods=['GET'])
@login_required
def user_info():
"""获取当前用户信息"""
return jsonify({
'success': True,
'user': {
'id': current_user.id,
'username': current_user.username,
'email': current_user.email,
'group_id': current_user.group_id,
'total_parse_count': current_user.total_parse_count
}
})
@auth_bp.route('/profile', methods=['GET'])
@login_required
def profile():
"""用户个人中心页面"""
from flask import render_template
return render_template('profile.html')
@auth_bp.route('/api/profile', methods=['GET'])
@login_required
def get_profile():
"""获取用户个人中心数据"""
from models import UserGroup, DailyParseStat, ParseLog
from datetime import date
# 获取用户组信息
user_group = UserGroup.query.get(current_user.group_id)
daily_limit = user_group.daily_limit if user_group else 10
group_name = user_group.name if user_group else '普通用户'
# 获取今日使用次数
today = date.today()
today_stat = DailyParseStat.query.filter_by(
user_id=current_user.id,
date=today
).first()
today_used = today_stat.parse_count if today_stat else 0
today_remaining = max(0, daily_limit - today_used)
# 获取解析记录最近20条
parse_logs = ParseLog.query.filter_by(
user_id=current_user.id
).order_by(ParseLog.created_at.desc()).limit(20).all()
logs_data = [{
'id': log.id,
'platform': log.platform,
'video_url': log.video_url[:50] + '...' if len(log.video_url) > 50 else log.video_url,
'status': log.status,
'response_time': log.response_time,
'created_at': log.created_at.strftime('%Y-%m-%d %H:%M:%S') if log.created_at else ''
} for log in parse_logs]
return jsonify({
'success': True,
'data': {
'user': {
'id': current_user.id,
'username': current_user.username,
'email': current_user.email,
'created_at': current_user.created_at.strftime('%Y-%m-%d') if current_user.created_at else ''
},
'group': {
'id': current_user.group_id,
'name': group_name,
'daily_limit': daily_limit
},
'usage': {
'daily_limit': daily_limit,
'today_used': today_used,
'today_remaining': today_remaining,
'total_parse_count': current_user.total_parse_count or 0
},
'parse_logs': logs_data
}
})