142 lines
4.8 KiB
Python
142 lines
4.8 KiB
Python
from flask import Blueprint, render_template, request, redirect, url_for, flash, session, jsonify
|
||
from app.forms import LoginForm, RegisterForm
|
||
from app.models.user import User
|
||
from app.models.verification import EmailVerification
|
||
from app.utils.email_service import send_verification_email
|
||
from config.database import db
|
||
|
||
auth_bp = Blueprint('auth', __name__, url_prefix='/auth')
|
||
|
||
|
||
@auth_bp.route('/login', methods=['GET', 'POST'])
|
||
def login():
|
||
"""用户登录"""
|
||
if 'user_id' in session:
|
||
return redirect(url_for('main.index'))
|
||
|
||
form = LoginForm()
|
||
if form.validate_on_submit():
|
||
username = form.username.data
|
||
password = form.password.data
|
||
|
||
# 支持用户名、手机号、邮箱登录
|
||
user = User.query.filter(
|
||
(User.username == username) |
|
||
(User.phone == username) |
|
||
(User.email == username)
|
||
).first()
|
||
|
||
if user and user.check_password(password):
|
||
if user.status == 0:
|
||
flash('账户已被禁用,请联系管理员', 'error')
|
||
return render_template('user/login.html', form=form)
|
||
|
||
# 登录成功,设置session
|
||
session['user_id'] = user.id
|
||
session['username'] = user.username
|
||
session['nickname'] = user.nickname or user.username
|
||
session.permanent = form.remember_me.data
|
||
|
||
flash(f'欢迎回来,{user.nickname or user.username}!', 'success')
|
||
|
||
# 获取登录前的页面
|
||
next_page = request.args.get('next')
|
||
if next_page:
|
||
return redirect(next_page)
|
||
return redirect(url_for('main.index'))
|
||
else:
|
||
flash('用户名或密码错误', 'error')
|
||
|
||
return render_template('user/login.html', form=form)
|
||
|
||
|
||
@auth_bp.route('/send_email_code', methods=['POST'])
|
||
def send_email_code():
|
||
"""发送邮箱验证码"""
|
||
try:
|
||
data = request.get_json()
|
||
email = data.get('email')
|
||
code_type = data.get('type', 1) # 默认为注册类型
|
||
|
||
if not email:
|
||
return jsonify({'success': False, 'message': '邮箱地址不能为空'})
|
||
|
||
# 检查邮箱格式
|
||
import re
|
||
email_pattern = r'^[^\s@]+@[^\s@]+\.[^\s@]+$'
|
||
if not re.match(email_pattern, email):
|
||
return jsonify({'success': False, 'message': '邮箱格式不正确'})
|
||
|
||
# 如果是注册,检查邮箱是否已被注册
|
||
if code_type == 1:
|
||
existing_user = User.query.filter_by(email=email).first()
|
||
if existing_user:
|
||
return jsonify({'success': False, 'message': '该邮箱已被注册'})
|
||
|
||
# 检查是否频繁发送(1分钟内只能发送一次)
|
||
from datetime import datetime, timedelta
|
||
recent_code = EmailVerification.query.filter_by(
|
||
email=email,
|
||
type=code_type
|
||
).filter(
|
||
EmailVerification.created_at > datetime.utcnow() - timedelta(minutes=1)
|
||
).first()
|
||
|
||
if recent_code:
|
||
return jsonify({'success': False, 'message': '发送过于频繁,请稍后再试'})
|
||
|
||
# 创建验证码
|
||
verification = EmailVerification.create_verification(email, code_type)
|
||
|
||
# 发送邮件
|
||
send_verification_email(email, verification.code, code_type)
|
||
|
||
return jsonify({'success': True, 'message': '验证码已发送'})
|
||
|
||
except Exception as e:
|
||
print(f"发送邮箱验证码错误: {e}")
|
||
return jsonify({'success': False, 'message': '发送失败,请重试'})
|
||
|
||
|
||
@auth_bp.route('/register', methods=['GET', 'POST'])
|
||
def register():
|
||
"""用户注册"""
|
||
if 'user_id' in session:
|
||
return redirect(url_for('main.index'))
|
||
|
||
form = RegisterForm()
|
||
if form.validate_on_submit():
|
||
try:
|
||
# 验证邮箱验证码
|
||
if not EmailVerification.verify_code(form.email.data, form.email_code.data, 1):
|
||
flash('邮箱验证码错误或已过期', 'error')
|
||
return render_template('user/register.html', form=form)
|
||
|
||
user = User(
|
||
username=form.username.data,
|
||
email=form.email.data,
|
||
phone=form.phone.data,
|
||
nickname=form.username.data
|
||
)
|
||
user.set_password(form.password.data)
|
||
|
||
db.session.add(user)
|
||
db.session.commit()
|
||
|
||
flash('注册成功!请登录', 'success')
|
||
return redirect(url_for('auth.login'))
|
||
except Exception as e:
|
||
db.session.rollback()
|
||
flash('注册失败,请重试', 'error')
|
||
print(f"注册错误: {e}")
|
||
|
||
return render_template('user/register.html', form=form)
|
||
|
||
|
||
@auth_bp.route('/logout')
|
||
def logout():
|
||
"""用户登出"""
|
||
session.clear()
|
||
flash('您已成功登出', 'info')
|
||
return redirect(url_for('main.index'))
|