758 lines
25 KiB
Python
758 lines
25 KiB
Python
from flask import Blueprint, render_template, request, redirect, url_for, flash, session, jsonify
|
||
from werkzeug.security import generate_password_hash, check_password_hash
|
||
from app.models.user import User, db
|
||
from app.models.log import Log # 导入日志模型
|
||
from app.utils.email import send_verification_email, generate_verification_code
|
||
import logging
|
||
from functools import wraps
|
||
import time
|
||
from datetime import datetime, timedelta
|
||
from app.services.user_service import UserService
|
||
from flask_login import login_user, logout_user, current_user, login_required
|
||
from app.models.user import User
|
||
|
||
# 创建蓝图
|
||
user_bp = Blueprint('user', __name__)
|
||
|
||
|
||
# 使用内存字典代替Redis存储验证码
|
||
class VerificationStore:
|
||
def __init__(self):
|
||
self.codes = {} # 存储格式: {email: {'code': code, 'expires': timestamp}}
|
||
|
||
def setex(self, email, seconds, code):
|
||
"""设置验证码并指定过期时间"""
|
||
expiry = datetime.now() + timedelta(seconds=seconds)
|
||
self.codes[email] = {'code': code, 'expires': expiry}
|
||
return True
|
||
|
||
def get(self, email):
|
||
"""获取验证码,如果过期则返回None"""
|
||
if email not in self.codes:
|
||
return None
|
||
|
||
data = self.codes[email]
|
||
if datetime.now() > data['expires']:
|
||
# 验证码已过期,删除它
|
||
self.delete(email)
|
||
return None
|
||
|
||
return data['code']
|
||
|
||
def delete(self, email):
|
||
"""删除验证码"""
|
||
if email in self.codes:
|
||
del self.codes[email]
|
||
return True
|
||
|
||
|
||
# 使用内存存储验证码
|
||
verification_codes = VerificationStore()
|
||
|
||
|
||
# 添加管理员权限检查装饰器
|
||
def admin_required(f):
|
||
@wraps(f)
|
||
def decorated_function(*args, **kwargs):
|
||
print(
|
||
f"DEBUG: admin_required检查,用户认证={current_user.is_authenticated},角色ID={current_user.role_id if current_user.is_authenticated else 'None'}")
|
||
|
||
if not current_user.is_authenticated:
|
||
print("DEBUG: 用户未登录,重定向到登录页面")
|
||
return redirect(url_for('user.login', next=request.url))
|
||
|
||
if current_user.role_id != 1:
|
||
print(f"DEBUG: 用户{current_user.username}不是管理员,角色ID={current_user.role_id}")
|
||
flash('您没有管理员权限访问此页面', 'error')
|
||
return redirect(url_for('index'))
|
||
|
||
print(f"DEBUG: 用户{current_user.username}是管理员,允许访问")
|
||
return f(*args, **kwargs)
|
||
|
||
return decorated_function
|
||
|
||
|
||
@user_bp.route('/login', methods=['GET', 'POST'])
|
||
def login():
|
||
print(f"DEBUG: 登录函数被调用,认证状态={current_user.is_authenticated}")
|
||
print(f"DEBUG: 请求方法={request.method},next参数={request.args.get('next')}")
|
||
|
||
# 获取next参数
|
||
next_page = request.args.get('next')
|
||
|
||
# 如果用户已经登录,处理重定向
|
||
if current_user.is_authenticated:
|
||
if next_page:
|
||
from urllib.parse import urlparse
|
||
parsed = urlparse(next_page)
|
||
path = parsed.path
|
||
print(f"DEBUG: 提取的路径={path}")
|
||
# 删除特殊处理,直接重定向到path
|
||
return redirect(path)
|
||
return redirect(url_for('index'))
|
||
|
||
if request.method == 'POST':
|
||
username = request.form.get('username')
|
||
password = request.form.get('password')
|
||
remember_me = request.form.get('remember_me') == 'on'
|
||
|
||
if not username or not password:
|
||
return render_template('login.html', error='用户名和密码不能为空')
|
||
|
||
# 检查用户是否存在
|
||
user = User.query.filter((User.username == username) | (User.email == username)).first()
|
||
|
||
if not user or not user.check_password(password):
|
||
# 记录登录失败日志
|
||
Log.add_log(
|
||
action="登录失败",
|
||
ip_address=request.remote_addr,
|
||
description=f"尝试使用用户名/邮箱 {username} 登录失败"
|
||
)
|
||
return render_template('login.html', error='用户名或密码错误')
|
||
|
||
if user.status == 0:
|
||
# 记录禁用账号登录尝试
|
||
Log.add_log(
|
||
action="登录失败",
|
||
user_id=user.id,
|
||
ip_address=request.remote_addr,
|
||
description=f"禁用账号 {username} 尝试登录"
|
||
)
|
||
return render_template('login.html', error='账号已被禁用,请联系管理员')
|
||
|
||
# 使用 Flask-Login 的 login_user 函数
|
||
login_user(user, remember=remember_me)
|
||
|
||
# 记录登录成功日志
|
||
Log.add_log(
|
||
action="用户登录",
|
||
user_id=user.id,
|
||
ip_address=request.remote_addr,
|
||
description=f"用户 {user.username} 登录成功"
|
||
)
|
||
|
||
# 这些session信息仍然可以保留,但不再用于认证
|
||
session['username'] = user.username
|
||
session['role_id'] = user.role_id
|
||
|
||
# 获取登录后要跳转的页面
|
||
next_page = request.args.get('next')
|
||
if not next_page or not next_page.startswith('/'):
|
||
next_page = url_for('index')
|
||
|
||
# 重定向到首页或其他请求的页面
|
||
return redirect(next_page)
|
||
|
||
return render_template('login.html')
|
||
|
||
|
||
@user_bp.route('/register', methods=['GET', 'POST'])
|
||
def register():
|
||
# 如果用户已登录,重定向到首页
|
||
if current_user.is_authenticated:
|
||
return redirect(url_for('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')
|
||
verification_code = request.form.get('verification_code')
|
||
|
||
# 验证表单数据
|
||
if not username or not email or not password or not confirm_password or not verification_code:
|
||
return render_template('register.html', error='所有字段都是必填项')
|
||
|
||
if password != confirm_password:
|
||
return render_template('register.html', error='两次输入的密码不匹配')
|
||
|
||
# 检查用户名和邮箱是否已存在
|
||
if User.query.filter_by(username=username).first():
|
||
return render_template('register.html', error='用户名已存在')
|
||
|
||
if User.query.filter_by(email=email).first():
|
||
return render_template('register.html', error='邮箱已被注册')
|
||
|
||
# 验证验证码
|
||
stored_code = verification_codes.get(email)
|
||
if not stored_code or stored_code != verification_code:
|
||
return render_template('register.html', error='验证码无效或已过期')
|
||
|
||
# 创建新用户
|
||
try:
|
||
new_user = User(
|
||
username=username,
|
||
password=password, # 密码会在模型中自动哈希
|
||
email=email,
|
||
nickname=username # 默认昵称与用户名相同
|
||
)
|
||
db.session.add(new_user)
|
||
db.session.commit()
|
||
|
||
# 记录用户注册日志
|
||
Log.add_log(
|
||
action="用户注册",
|
||
user_id=new_user.id,
|
||
ip_address=request.remote_addr,
|
||
description=f"新用户 {username} 注册成功"
|
||
)
|
||
|
||
# 清除验证码
|
||
verification_codes.delete(email)
|
||
|
||
flash('注册成功,请登录', 'success')
|
||
return redirect(url_for('user.login'))
|
||
except Exception as e:
|
||
db.session.rollback()
|
||
logging.error(f"User registration failed: {str(e)}")
|
||
return render_template('register.html', error='注册失败,请稍后重试')
|
||
|
||
return render_template('register.html')
|
||
|
||
|
||
@user_bp.route('/logout')
|
||
@login_required
|
||
def logout():
|
||
username = current_user.username
|
||
user_id = current_user.id
|
||
|
||
# 先记录日志,再登出
|
||
Log.add_log(
|
||
action="用户登出",
|
||
user_id=user_id,
|
||
ip_address=request.remote_addr,
|
||
description=f"用户 {username} 登出系统"
|
||
)
|
||
|
||
logout_user()
|
||
return redirect(url_for('user.login'))
|
||
|
||
|
||
@user_bp.route('/send_verification_code', methods=['POST'])
|
||
def send_verification_code():
|
||
data = request.get_json()
|
||
email = data.get('email')
|
||
|
||
if not email:
|
||
return jsonify({'success': False, 'message': '请提供邮箱地址'})
|
||
|
||
# 检查邮箱格式
|
||
import re
|
||
if not re.match(r"[^@]+@[^@]+\.[^@]+", email):
|
||
return jsonify({'success': False, 'message': '邮箱格式不正确'})
|
||
|
||
# 生成验证码
|
||
code = generate_verification_code()
|
||
|
||
# 存储验证码(10分钟有效)
|
||
verification_codes.setex(email, 600, code) # 10分钟过期
|
||
|
||
# 发送验证码邮件
|
||
if send_verification_email(email, code):
|
||
# 记录发送验证码日志
|
||
Log.add_log(
|
||
action="发送验证码",
|
||
ip_address=request.remote_addr,
|
||
description=f"向邮箱 {email} 发送验证码"
|
||
)
|
||
return jsonify({'success': True, 'message': '验证码已发送'})
|
||
else:
|
||
return jsonify({'success': False, 'message': '邮件发送失败,请稍后重试'})
|
||
|
||
|
||
# 用户管理列表
|
||
@user_bp.route('/manage')
|
||
@login_required
|
||
@admin_required
|
||
def user_list():
|
||
page = request.args.get('page', 1, type=int)
|
||
search = request.args.get('search', '')
|
||
status = request.args.get('status', type=int)
|
||
role_id = request.args.get('role_id', type=int)
|
||
|
||
pagination = UserService.get_users(
|
||
page=page,
|
||
per_page=10,
|
||
search_query=search,
|
||
status=status,
|
||
role_id=role_id
|
||
)
|
||
|
||
# 记录管理员访问用户列表日志
|
||
Log.add_log(
|
||
action="访问用户管理",
|
||
user_id=current_user.id,
|
||
ip_address=request.remote_addr,
|
||
description=f"管理员 {current_user.username} 访问用户管理列表"
|
||
)
|
||
|
||
roles = UserService.get_all_roles()
|
||
|
||
return render_template(
|
||
'user/list.html',
|
||
pagination=pagination,
|
||
search=search,
|
||
status=status,
|
||
role_id=role_id,
|
||
roles=roles
|
||
)
|
||
|
||
|
||
# 用户详情/编辑页面
|
||
@user_bp.route('/edit/<int:user_id>', methods=['GET', 'POST'])
|
||
@login_required
|
||
@admin_required
|
||
def user_edit(user_id):
|
||
user = UserService.get_user_by_id(user_id)
|
||
if not user:
|
||
flash('用户不存在', 'error')
|
||
return redirect(url_for('user.user_list'))
|
||
|
||
roles = UserService.get_all_roles()
|
||
|
||
if request.method == 'POST':
|
||
data = {
|
||
'email': request.form.get('email'),
|
||
'phone': request.form.get('phone'),
|
||
'nickname': request.form.get('nickname'),
|
||
'role_id': int(request.form.get('role_id')),
|
||
'status': int(request.form.get('status')),
|
||
}
|
||
|
||
password = request.form.get('password')
|
||
if password:
|
||
data['password'] = password
|
||
|
||
success, message = UserService.update_user(user_id, data)
|
||
if success:
|
||
# 记录管理员编辑用户信息日志
|
||
Log.add_log(
|
||
action="编辑用户",
|
||
user_id=current_user.id,
|
||
target_type="用户",
|
||
target_id=user_id,
|
||
ip_address=request.remote_addr,
|
||
description=f"管理员 {current_user.username} 编辑用户 {user.username} 的信息"
|
||
)
|
||
flash(message, 'success')
|
||
return redirect(url_for('user.user_list'))
|
||
else:
|
||
flash(message, 'error')
|
||
|
||
# 记录访问用户编辑页面日志
|
||
if request.method == 'GET':
|
||
Log.add_log(
|
||
action="访问用户编辑",
|
||
user_id=current_user.id,
|
||
target_type="用户",
|
||
target_id=user_id,
|
||
ip_address=request.remote_addr,
|
||
description=f"管理员 {current_user.username} 访问用户 {user.username} 的编辑页面"
|
||
)
|
||
|
||
return render_template('user/edit.html', user=user, roles=roles)
|
||
|
||
|
||
# 用户状态管理API
|
||
@user_bp.route('/status/<int:user_id>', methods=['POST'])
|
||
@login_required
|
||
@admin_required
|
||
def user_status(user_id):
|
||
data = request.get_json()
|
||
status = data.get('status')
|
||
|
||
if status is None or status not in [0, 1]:
|
||
return jsonify({'success': False, 'message': '无效的状态值'})
|
||
|
||
# 不能修改自己的状态
|
||
if user_id == current_user.id:
|
||
return jsonify({'success': False, 'message': '不能修改自己的状态'})
|
||
|
||
# 查询用户获取用户名(用于日志)
|
||
target_user = User.query.get(user_id)
|
||
if not target_user:
|
||
return jsonify({'success': False, 'message': '用户不存在'})
|
||
|
||
success, message = UserService.change_user_status(user_id, status)
|
||
|
||
if success:
|
||
# 记录修改用户状态日志
|
||
status_text = "启用" if status == 1 else "禁用"
|
||
Log.add_log(
|
||
action=f"用户{status_text}",
|
||
user_id=current_user.id,
|
||
target_type="用户",
|
||
target_id=user_id,
|
||
ip_address=request.remote_addr,
|
||
description=f"管理员 {current_user.username} {status_text}用户 {target_user.username}"
|
||
)
|
||
|
||
return jsonify({'success': success, 'message': message})
|
||
|
||
|
||
# 用户删除API
|
||
@user_bp.route('/delete/<int:user_id>', methods=['POST'])
|
||
@login_required
|
||
@admin_required
|
||
def user_delete(user_id):
|
||
# 不能删除自己
|
||
if user_id == current_user.id:
|
||
return jsonify({'success': False, 'message': '不能删除自己的账号'})
|
||
|
||
# 查询用户获取用户名(用于日志)
|
||
target_user = User.query.get(user_id)
|
||
if not target_user:
|
||
return jsonify({'success': False, 'message': '用户不存在'})
|
||
|
||
target_username = target_user.username # 保存用户名以便记录在日志中
|
||
|
||
success, message = UserService.delete_user(user_id)
|
||
|
||
if success:
|
||
# 记录删除用户日志
|
||
Log.add_log(
|
||
action="删除用户",
|
||
user_id=current_user.id,
|
||
target_type="用户",
|
||
ip_address=request.remote_addr,
|
||
description=f"管理员 {current_user.username} 删除用户 {target_username}"
|
||
)
|
||
|
||
return jsonify({'success': success, 'message': message})
|
||
|
||
|
||
# 个人中心页面
|
||
@user_bp.route('/profile', methods=['GET', 'POST'])
|
||
@login_required
|
||
def user_profile():
|
||
user = current_user
|
||
|
||
if request.method == 'POST':
|
||
data = {
|
||
'email': request.form.get('email'),
|
||
'phone': request.form.get('phone'),
|
||
'nickname': request.form.get('nickname')
|
||
}
|
||
|
||
current_password = request.form.get('current_password')
|
||
new_password = request.form.get('new_password')
|
||
confirm_password = request.form.get('confirm_password')
|
||
|
||
# 如果用户想要修改密码
|
||
if current_password and new_password:
|
||
if not user.check_password(current_password):
|
||
flash('当前密码不正确', 'error')
|
||
return render_template('user/profile.html', user=user)
|
||
|
||
if new_password != confirm_password:
|
||
flash('两次输入的新密码不匹配', 'error')
|
||
return render_template('user/profile.html', user=user)
|
||
|
||
data['password'] = new_password
|
||
password_changed = True
|
||
else:
|
||
password_changed = False
|
||
|
||
success, message = UserService.update_user(user.id, data)
|
||
if success:
|
||
# 记录用户修改个人信息日志
|
||
log_description = f"用户 {user.username} 修改了个人信息"
|
||
if password_changed:
|
||
log_description += ",包括密码修改"
|
||
|
||
Log.add_log(
|
||
action="修改个人信息",
|
||
user_id=user.id,
|
||
ip_address=request.remote_addr,
|
||
description=log_description
|
||
)
|
||
flash(message, 'success')
|
||
else:
|
||
flash(message, 'error')
|
||
|
||
return render_template('user/profile.html', user=user)
|
||
|
||
|
||
# 角色管理页面
|
||
@user_bp.route('/roles', methods=['GET'])
|
||
@login_required
|
||
@admin_required
|
||
def role_list():
|
||
roles = UserService.get_all_roles()
|
||
|
||
# 记录访问角色管理页面日志
|
||
Log.add_log(
|
||
action="访问角色管理",
|
||
user_id=current_user.id,
|
||
ip_address=request.remote_addr,
|
||
description=f"管理员 {current_user.username} 访问角色管理页面"
|
||
)
|
||
|
||
return render_template('user/roles.html', roles=roles)
|
||
|
||
|
||
# 获取所有系统权限的API
|
||
@user_bp.route('/permissions', methods=['GET'])
|
||
@login_required
|
||
@admin_required
|
||
def get_permissions():
|
||
"""获取所有可用的系统权限"""
|
||
from app.models.permission import Permission
|
||
|
||
try:
|
||
permissions = Permission.query.order_by(Permission.code).all()
|
||
|
||
# 转换为JSON格式
|
||
permissions_data = [{
|
||
'id': p.id,
|
||
'code': p.code,
|
||
'name': p.name,
|
||
'description': p.description
|
||
} for p in permissions]
|
||
|
||
return jsonify({
|
||
'success': True,
|
||
'permissions': permissions_data
|
||
})
|
||
except Exception as e:
|
||
logging.error(f"获取权限列表失败: {str(e)}")
|
||
return jsonify({
|
||
'success': False,
|
||
'message': f"获取权限列表失败: {str(e)}"
|
||
}), 500
|
||
|
||
|
||
# 获取特定角色的权限
|
||
@user_bp.route('/role/<int:role_id>/permissions', methods=['GET'])
|
||
@login_required
|
||
@admin_required
|
||
def get_role_permissions(role_id):
|
||
"""获取指定角色的权限ID列表"""
|
||
from app.models.user import Role
|
||
|
||
try:
|
||
role = Role.query.get(role_id)
|
||
if not role:
|
||
return jsonify({
|
||
'success': False,
|
||
'message': '角色不存在'
|
||
}), 404
|
||
|
||
# 获取角色的所有权限ID
|
||
permissions = [p.id for p in role.permissions]
|
||
|
||
return jsonify({
|
||
'success': True,
|
||
'permissions': permissions
|
||
})
|
||
except Exception as e:
|
||
logging.error(f"获取角色权限失败: {str(e)}")
|
||
return jsonify({
|
||
'success': False,
|
||
'message': f"获取角色权限失败: {str(e)}"
|
||
}), 500
|
||
|
||
|
||
# 修改角色保存路由,支持权限管理
|
||
@user_bp.route('/role/save', methods=['POST'])
|
||
@login_required
|
||
@admin_required
|
||
def role_save():
|
||
"""创建或更新角色,包括权限分配"""
|
||
data = request.get_json()
|
||
role_id = data.get('id')
|
||
role_name = data.get('role_name')
|
||
description = data.get('description')
|
||
permission_ids = data.get('permissions', []) # 获取权限ID列表
|
||
|
||
if not role_name:
|
||
return jsonify({'success': False, 'message': '角色名不能为空'})
|
||
|
||
# 处理系统内置角色的权限保护
|
||
if role_id and int(role_id) in [1, 2]:
|
||
permission_ids = None # 不修改内置角色的权限
|
||
|
||
if role_id: # 更新角色
|
||
success, message = UserService.update_role(role_id, role_name, description, permission_ids)
|
||
if success:
|
||
# 记录编辑角色日志
|
||
Log.add_log(
|
||
action="编辑角色",
|
||
user_id=current_user.id,
|
||
target_type="角色",
|
||
target_id=role_id,
|
||
ip_address=request.remote_addr,
|
||
description=f"管理员 {current_user.username} 编辑角色 {role_name},包含权限设置"
|
||
)
|
||
else: # 创建角色
|
||
success, message, new_role_id = UserService.create_role(role_name, description, permission_ids)
|
||
if success:
|
||
role_id = new_role_id
|
||
# 记录创建角色日志
|
||
Log.add_log(
|
||
action="创建角色",
|
||
user_id=current_user.id,
|
||
target_type="角色",
|
||
target_id=role_id,
|
||
ip_address=request.remote_addr,
|
||
description=f"管理员 {current_user.username} 创建新角色 {role_name},设置了 {len(permission_ids)} 个权限"
|
||
)
|
||
|
||
return jsonify({'success': success, 'message': message})
|
||
|
||
|
||
# 角色删除API
|
||
@user_bp.route('/role/delete/<int:role_id>', methods=['POST'])
|
||
@login_required
|
||
@admin_required
|
||
def role_delete(role_id):
|
||
"""删除角色"""
|
||
# 保护系统内置角色
|
||
if role_id in [1, 2]:
|
||
return jsonify({
|
||
'success': False,
|
||
'message': '不能删除系统内置角色'
|
||
})
|
||
|
||
from app.models.user import Role
|
||
|
||
try:
|
||
# 获取角色信息用于日志记录
|
||
role = Role.query.get(role_id)
|
||
if not role:
|
||
return jsonify({
|
||
'success': False,
|
||
'message': '角色不存在'
|
||
}), 404
|
||
|
||
role_name = role.role_name
|
||
|
||
# 检查是否有用户在使用该角色
|
||
user_count = User.query.filter_by(role_id=role_id).count()
|
||
if user_count > 0:
|
||
return jsonify({
|
||
'success': False,
|
||
'message': f'无法删除:该角色下存在 {user_count} 个用户'
|
||
})
|
||
|
||
# 删除角色
|
||
db.session.delete(role)
|
||
db.session.commit()
|
||
|
||
# 记录删除角色日志
|
||
Log.add_log(
|
||
action="删除角色",
|
||
user_id=current_user.id,
|
||
target_type="角色",
|
||
ip_address=request.remote_addr,
|
||
description=f"管理员 {current_user.username} 删除了角色 {role_name}"
|
||
)
|
||
|
||
return jsonify({
|
||
'success': True,
|
||
'message': '角色删除成功'
|
||
})
|
||
except Exception as e:
|
||
db.session.rollback()
|
||
logging.error(f"删除角色失败: {str(e)}")
|
||
return jsonify({
|
||
'success': False,
|
||
'message': f"删除角色失败: {str(e)}"
|
||
}), 500
|
||
|
||
@user_bp.route('/role/<int:role_id>/count', methods=['GET'])
|
||
@login_required
|
||
@admin_required
|
||
def get_role_user_count(role_id):
|
||
"""获取指定角色的用户数量"""
|
||
try:
|
||
count = User.query.filter_by(role_id=role_id).count()
|
||
return jsonify({
|
||
'success': True,
|
||
'count': count
|
||
})
|
||
except Exception as e:
|
||
return jsonify({
|
||
'success': False,
|
||
'message': f"查询失败: {str(e)}",
|
||
'count': 0
|
||
}), 500
|
||
|
||
|
||
@user_bp.route('/add', methods=['GET', 'POST'])
|
||
@login_required
|
||
@admin_required
|
||
def add_user():
|
||
roles = UserService.get_all_roles()
|
||
|
||
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')
|
||
verification_code = request.form.get('verification_code')
|
||
nickname = request.form.get('nickname')
|
||
phone = request.form.get('phone')
|
||
if phone == '':
|
||
phone = None
|
||
nickname = request.form.get('nickname')
|
||
role_id = request.form.get('role_id', 2, type=int) # 默认为普通用户
|
||
status = request.form.get('status', 1, type=int) # 默认为启用状态
|
||
|
||
# 验证表单数据
|
||
if not username or not email or not password or not confirm_password or not verification_code:
|
||
return render_template('user/add.html', error='所有必填字段不能为空', roles=roles)
|
||
|
||
if password != confirm_password:
|
||
return render_template('user/add.html', error='两次输入的密码不匹配', roles=roles)
|
||
|
||
# 检查用户名和邮箱是否已存在
|
||
if User.query.filter_by(username=username).first():
|
||
return render_template('user/add.html', error='用户名已存在', roles=roles)
|
||
|
||
if User.query.filter_by(email=email).first():
|
||
return render_template('user/add.html', error='邮箱已被注册', roles=roles)
|
||
|
||
# 验证验证码
|
||
stored_code = verification_codes.get(email)
|
||
if not stored_code or stored_code != verification_code:
|
||
return render_template('user/add.html', error='验证码无效或已过期', roles=roles)
|
||
|
||
# 创建新用户
|
||
try:
|
||
new_user = User(
|
||
username=username,
|
||
password=password, # 密码会在模型中自动哈希
|
||
email=email,
|
||
nickname=nickname or username, # 如果未提供昵称,使用用户名
|
||
phone=phone,
|
||
role_id=role_id,
|
||
status=status
|
||
)
|
||
db.session.add(new_user)
|
||
db.session.commit()
|
||
|
||
# 记录管理员添加用户日志
|
||
Log.add_log(
|
||
action="添加用户",
|
||
user_id=current_user.id,
|
||
target_type="用户",
|
||
target_id=new_user.id,
|
||
ip_address=request.remote_addr,
|
||
description=f"管理员 {current_user.username} 添加新用户 {username}"
|
||
)
|
||
|
||
# 清除验证码
|
||
verification_codes.delete(email)
|
||
|
||
flash('用户添加成功', 'success')
|
||
return redirect(url_for('user.user_list'))
|
||
except Exception as e:
|
||
db.session.rollback()
|
||
logging.error(f"用户添加失败: {str(e)}")
|
||
return render_template('user/add.html', error=f'添加用户失败: {str(e)}', roles=roles)
|
||
|
||
# GET请求,显示添加用户表单
|
||
return render_template('user/add.html', roles=roles)
|