import os from flask import Blueprint, render_template, request, redirect, url_for, flash from flask_login import login_user, logout_user, current_user, login_required from werkzeug.utils import secure_filename from models import db, User from config import Config auth_bp = Blueprint('auth', __name__) def allowed_file(filename): """检查文件扩展名是否允许""" return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in Config.ALLOWED_EXTENSIONS @auth_bp.route('/register', methods=['GET', 'POST']) def register(): """用户注册""" if current_user.is_authenticated: return redirect(url_for('posts.index')) if request.method == 'POST': username = request.form.get('username') email = request.form.get('email') password = request.form.get('password') confirm_password = request.form.get('confirm_password') student_id_photo = request.files.get('student_id_photo') # 验证输入 if not all([username, email, password, confirm_password, student_id_photo]): flash('请填写所有字段并上传学生证照片', 'error') return render_template('register.html') if password != confirm_password: flash('两次输入的密码不一致', 'error') return render_template('register.html') if len(password) < 6: flash('密码长度至少为6位', 'error') return render_template('register.html') # 检查用户名和邮箱是否已存在 if User.query.filter_by(username=username).first(): flash('用户名已被注册', 'error') return render_template('register.html') if User.query.filter_by(email=email).first(): flash('邮箱已被注册', 'error') return render_template('register.html') # 保存学生证照片 if student_id_photo and allowed_file(student_id_photo.filename): filename = secure_filename(f"{username}_{student_id_photo.filename}") filepath = os.path.join(Config.UPLOAD_FOLDER, 'student_ids', filename) student_id_photo.save(filepath) # 创建用户 user = User( username=username, email=email, student_id_photo=f'student_ids/{filename}', is_approved=False ) user.set_password(password) db.session.add(user) db.session.commit() flash('注册成功!请等待管理员审核您的学生身份', 'success') return redirect(url_for('auth.login')) else: flash('请上传有效的图片文件(支持 PNG, JPG, JPEG, GIF, WEBP)', 'error') return render_template('register.html') @auth_bp.route('/login', methods=['GET', 'POST']) def login(): """用户登录""" if current_user.is_authenticated: return redirect(url_for('posts.index')) if request.method == 'POST': username = request.form.get('username') password = request.form.get('password') remember = request.form.get('remember', False) if not all([username, password]): flash('请填写用户名和密码', 'error') return render_template('login.html') user = User.query.filter_by(username=username).first() if user is None or not user.check_password(password): flash('用户名或密码错误', 'error') return render_template('login.html') if not user.is_approved: flash('您的账号正在等待管理员审核', 'warning') return render_template('login.html') login_user(user, remember=remember) # 检查管理员是否需要修改密码 if user.is_admin and not user.password_changed: flash('首次登录,请修改密码', 'warning') return redirect(url_for('auth.change_password')) flash(f'欢迎回来,{user.username}!', 'success') next_page = request.args.get('next') return redirect(next_page) if next_page else redirect(url_for('posts.index')) return render_template('login.html') @auth_bp.route('/logout') def logout(): """用户登出""" logout_user() flash('您已成功退出登录', 'info') return redirect(url_for('posts.index')) @auth_bp.route('/change-password', methods=['GET', 'POST']) @login_required def change_password(): """修改密码""" if request.method == 'POST': current_password = request.form.get('current_password') new_password = request.form.get('new_password') confirm_password = request.form.get('confirm_password') if not all([current_password, new_password, confirm_password]): flash('请填写所有字段', 'error') return render_template('change_password.html') # 验证当前密码 if not current_user.check_password(current_password): flash('当前密码错误', 'error') return render_template('change_password.html') # 验证新密码 if new_password != confirm_password: flash('两次输入的新密码不一致', 'error') return render_template('change_password.html') if len(new_password) < 6: flash('密码长度至少为6位', 'error') return render_template('change_password.html') # 更新密码 current_user.set_password(new_password) current_user.password_changed = True db.session.commit() flash('密码修改成功', 'success') return redirect(url_for('posts.index')) return render_template('change_password.html')