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 } })