336 lines
11 KiB
Python
336 lines
11 KiB
Python
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
|
|
|