You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MuseGuard/src/backend/app/controllers/auth_controller.py

155 lines
5.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""
用户认证控制器
处理注册、登录、密码修改等功能
"""
from flask import Blueprint, request, jsonify
from flask_jwt_extended import create_access_token, jwt_required, get_jwt_identity
from app import db
from app.database import User, UserConfig
from functools import wraps
import re
def int_jwt_required(f):
"""获取JWT身份并转换为整数的装饰器"""
@wraps(f)
def wrapped(*args, **kwargs):
try:
current_user_id = int(get_jwt_identity())
return f(*args, current_user_id=current_user_id, **kwargs)
except (TypeError, ValueError):
return jsonify({'error': '无效的用户身份标识'}), 401
return jwt_required()(wrapped)
auth_bp = Blueprint('auth', __name__)
@auth_bp.route('/register', methods=['POST'])
def register():
"""用户注册"""
try:
data = request.get_json()
username = data.get('username')
password = data.get('password')
email = data.get('email')
# 验证输入
if not username or not password or not email:
return jsonify({'error': '用户名、密码和邮箱不能为空'}), 400
# 验证邮箱格式
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not re.match(email_pattern, email):
return jsonify({'error': '邮箱格式不正确'}), 400
# 检查用户名是否已存在
if User.query.filter_by(username=username).first():
return jsonify({'error': '用户名已存在'}), 400
# 检查邮箱是否已注册
if User.query.filter_by(email=email).first():
return jsonify({'error': '该邮箱已被注册,同一邮箱只能注册一次'}), 400
# 创建用户
user = User(username=username, email=email)
user.set_password(password)
db.session.add(user)
db.session.commit()
# 创建用户默认配置
user_config = UserConfig(user_id=user.id)
db.session.add(user_config)
db.session.commit()
return jsonify({
'message': '注册成功',
'user': user.to_dict()
}), 201
except Exception as e:
db.session.rollback()
return jsonify({'error': f'注册失败: {str(e)}'}), 500
@auth_bp.route('/login', methods=['POST'])
def login():
"""用户登录"""
try:
data = request.get_json()
username = data.get('username')
password = data.get('password')
if not username or not password:
return jsonify({'error': '用户名和密码不能为空'}), 400
# 查找用户
user = User.query.filter_by(username=username).first()
if not user or not user.check_password(password):
return jsonify({'error': '用户名或密码错误'}), 401
if not user.is_active:
return jsonify({'error': '账户已被禁用'}), 401
# 创建访问令牌 - 确保用户ID为字符串类型
access_token = create_access_token(identity=str(user.id))
return jsonify({
'message': '登录成功',
'access_token': access_token,
'user': user.to_dict()
}), 200
except Exception as e:
return jsonify({'error': f'登录失败: {str(e)}'}), 500
@auth_bp.route('/change-password', methods=['POST'])
@int_jwt_required
def change_password(current_user_id):
"""修改密码"""
try:
user = User.query.get(current_user_id)
if not user:
return jsonify({'error': '用户不存在'}), 404
data = request.get_json()
old_password = data.get('old_password')
new_password = data.get('new_password')
if not old_password or not new_password:
return jsonify({'error': '旧密码和新密码不能为空'}), 400
# 验证旧密码
if not user.check_password(old_password):
return jsonify({'error': '旧密码错误'}), 401
# 设置新密码
user.set_password(new_password)
db.session.commit()
return jsonify({'message': '密码修改成功'}), 200
except Exception as e:
db.session.rollback()
return jsonify({'error': f'密码修改失败: {str(e)}'}), 500
@auth_bp.route('/profile', methods=['GET'])
@int_jwt_required
def get_profile(current_user_id):
"""获取用户信息"""
try:
user = User.query.get(current_user_id)
if not user:
return jsonify({'error': '用户不存在'}), 404
return jsonify({'user': user.to_dict()}), 200
except Exception as e:
return jsonify({'error': f'获取用户信息失败: {str(e)}'}), 500
@auth_bp.route('/logout', methods=['POST'])
@jwt_required()
def logout():
"""用户登出客户端删除token即可"""
return jsonify({'message': '登出成功'}), 200