Files
Incidents-Data-Portal/backend/app/blueprints/auth/routes.py
T

336 lines
11 KiB
Python
Raw Normal View History

2026-07-10 18:55:55 +08:00
from flask import Blueprint, current_app, request, jsonify
from sqlalchemy.exc import IntegrityError
from app.models import User, Role, UserRole # 导入模型类
from app.utils import encrypt_password # 导入密码加密工具
from app import db
from flask_jwt_extended import jwt_required, get_jwt_identity # 导入JWT相关工具
auth_bp = Blueprint("auth", __name__)
@auth_bp.route("/create-user", methods=["POST"])
# @jwt_required() # 需要有效Token才能创建用户
def create_user():
"""
{
"username": "new_user",
"password": "securePass123",
"role_ids": [1, 3] // 要分配的角色ID列表
}
"""
data = request.get_json()
# print(data)
if not data or "username" not in data or "password" not in data:
return jsonify({"error": "缺少用户名或密码"}), 400
# 1. 验证用户名唯一性
existing_user = User.query.filter_by(username=data["username"]).first()
if existing_user:
return jsonify({"error": "用户名已存在"}), 409
# 2. 获取当前操作者
# current_user_id = get_jwt_identity()
current_user_id = 1
print("current_user_id", current_user_id)
current_user = User.query.get(int(current_user_id))
current_user_id = 1
# if not current_user:
# return jsonify({"error": "无效的操作者"}), 401
# 3. 密码复杂度验证
password = data["password"]
if len(password) < 4 or not any(c.isdigit() for c in password):
return jsonify({"error": "密码需至少4位且包含数字"}), 400
# 4. 验证角色(新增部分)
role_ids = data.get("role_ids", [])
valid_roles = []
if role_ids:
valid_roles = Role.query.filter(Role.id.in_(role_ids)).all()
if len(valid_roles) != len(role_ids):
return jsonify({"error": "包含无效的角色ID"}), 400
try:
# 5. 创建新用户
new_user = User(
username=data["username"],
password=encrypt_password(data["password"]),
status=data.get("status", 1),
created_by=current_user_id,
email=data.get("email"),
avatar=data.get("avatar"),
region=data.get("region"),
phone=data.get("phone"),
brief=data.get("brief"),
third_party_account=data.get("third_party_account"),
position=data.get("position"),
department=data.get("department"),
label=data.get("label"),
)
db.session.add(new_user)
db.session.flush() # 获取新用户ID但不提交事务
# 6. 分配角色(新增核心功能)
for role in valid_roles:
user_role = UserRole(
user_id=new_user.id, role_id=role.id, created_by=current_user_id
)
db.session.add(user_role)
db.session.commit()
# 7. 构造响应数据(包含角色信息)
response_data = {
"id": new_user.id,
"username": new_user.username,
"created_at": new_user.created_at.isoformat(),
"created_by": new_user.created_by,
"roles": [
{"id": r.id, "name": r.name} for r in valid_roles
], # 新增角色信息
}
# 8. 记录操作日志(新增角色信息)
current_app.logger.info(
f"用户创建成功: {new_user.username} (ID:{new_user.id}) "
f"操作者: {current_user.username} (ID:{current_user_id}) "
f"分配角色: {[r.name for r in valid_roles]}" # 记录分配的角色
)
return jsonify(response_data), 201
except Exception as e:
db.session.rollback()
current_app.logger.error(f"用户创建失败: {str(e)}")
return jsonify({"error": "服务器内部错误"}), 500
# 2.修改用户
@auth_bp.route("/update-user", methods=["POST"])
def update_user():
"""
修改用户信息(支持更新所有字段,包括新增字段)
请求体示例:
{
"user_id":"12345",
"username": "new_username", # 可选:修改用户名
"password": "new_password", # 可选:修改密码(明文)
"status": 1, # 可选:修改状态
"updated_by": 1, # 更新人ID
// 新增可选字段(需要更新的字段才传入)
"email": "new@example.com",
"phone": "+86 13987654321",
"department": "产品部",
"position": "产品经理",
"label": "产品,管理"
}
"""
data = request.get_json()
user_id = data["user_id"]
user = User.query.get(user_id)
if not user:
return jsonify({"code": 404, "message": f"用户ID {user_id} 不存在"}), 404
try:
# 基础字段更新(原有逻辑保留)
if "username" in data and data["username"]:
user.username = data["username"]
if "password" in data and data["password"]:
user.password = encrypt_password(data["password"])
if "status" in data:
user.status = data["status"]
if "updated_by" in data:
user.updated_by = data["updated_by"]
# 新增字段更新(按需更新,仅处理传入的字段)
if "email" in data:
user.email = data["email"]
if "avatar" in data:
user.avatar = data["avatar"]
if "region" in data:
user.region = data["region"]
if "phone" in data:
user.phone = data["phone"]
if "brief" in data:
user.brief = data["brief"]
if "third_party_account" in data:
user.third_party_account = data["third_party_account"]
if "position" in data:
user.position = data["position"]
if "department" in data:
user.department = data["department"]
if "label" in data:
user.label = data["label"]
db.session.commit()
# 返回更新结果(包含核心字段和新增关键字段)
return jsonify(
{
"code": 200,
"message": "用户信息更新成功",
"data": {
"user_id": user.id,
"username": user.username,
"email": user.email,
"phone": user.phone,
"department": user.department,
"updated_at": user.updated_at.strftime("%Y-%m-%d %H:%M:%S"),
},
}
)
except IntegrityError:
db.session.rollback()
return (
jsonify({"code": 409, "message": f'用户名"{data["username"]}"已存在'}),
409,
)
except Exception as e:
db.session.rollback()
return jsonify({"code": 500, "message": f"更新失败:{str(e)}"}), 500
# 3. 创建角色
@auth_bp.route("/roles", methods=["POST"])
def create_role():
"""
创建新角色
请求体示例:
{
"name": "admin", # 角色名称(唯一)
"description": "系统管理员",
"status": 1,
"created_by": 1 # 创建人ID
}
"""
data = request.get_json()
if not data.get("name"):
return jsonify({"code": 400, "message": "角色名称不能为空"}), 400
try:
new_role = Role(
name=data["name"],
description=data.get("description"),
status=data.get("status", 1),
created_by=data.get("created_by"),
updated_by=data.get("created_by"),
)
db.session.add(new_role)
db.session.commit()
return jsonify(
{
"code": 200,
"message": "角色创建成功",
"data": {"role_id": new_role.id, "name": new_role.name},
}
)
except IntegrityError:
db.session.rollback()
return jsonify({"code": 409, "message": f'角色"{data["name"]}"已存在'}), 409
except Exception as e:
db.session.rollback()
return jsonify({"code": 500, "message": f"创建失败:{str(e)}"}), 500
# 4. 修改角色
@auth_bp.route("/roles/<int:role_id>", methods=["PUT"])
def update_role(role_id):
"""
修改角色信息
请求体示例:
{
"name": "super_admin", # 可选:修改角色名称
"description": "超级管理员", # 可选:修改描述
"status": 1, # 可选:修改状态(1-启用,0-禁用)
"updated_by": 1 # 更新人ID
}
"""
data = request.get_json()
role = Role.query.get(role_id)
if not role:
return jsonify({"code": 404, "message": f"角色ID {role_id} 不存在"}), 404
try:
if "name" in data and data["name"]:
role.name = data["name"]
if "description" in data:
role.description = data["description"]
if "status" in data:
role.status = data["status"]
if "updated_by" in data:
role.updated_by = data["updated_by"]
db.session.commit()
return jsonify(
{
"code": 200,
"message": "角色信息更新成功",
"data": {"role_id": role.id, "name": role.name},
}
)
except IntegrityError:
db.session.rollback()
return jsonify({"code": 409, "message": f'角色"{data["name"]}"已存在'}), 409
except Exception as e:
db.session.rollback()
return jsonify({"code": 500, "message": f"更新失败:{str(e)}"}), 500
# 5. 给用户分配角色(补充功能:用户-角色关联)
@auth_bp.route("/user-roles", methods=["POST"])
def assign_role_to_user():
"""
给用户分配角色(多对多关联)
请求体示例:
{
"user_id": 1,
"role_id": 2,
"created_by": 1 # 操作人ID
}
"""
data = request.get_json()
user_id = data.get("user_id")
role_id = data.get("role_id")
# 校验用户和角色是否存在
if not User.query.get(user_id):
return jsonify({"code": 404, "message": f"用户ID {user_id} 不存在"}), 404
if not Role.query.get(role_id):
return jsonify({"code": 404, "message": f"角色ID {role_id} 不存在"}), 404
try:
# 检查是否已关联
existing = UserRole.query.filter_by(user_id=user_id, role_id=role_id).first()
if existing:
return (
jsonify(
{"code": 409, "message": f"用户ID {user_id} 已拥有角色ID {role_id}"}
),
409,
)
# 创建关联
user_role = UserRole(
user_id=user_id, role_id=role_id, created_by=data.get("created_by")
)
db.session.add(user_role)
db.session.commit()
return jsonify({"code": 200, "message": "角色分配成功"})
except Exception as e:
db.session.rollback()
return jsonify({"code": 500, "message": f"分配失败:{str(e)}"}), 500