Files
wecom_it_smart_desk/backend/app/api/admin_users.py
T

368 lines
11 KiB
Python
Raw Normal View History

# =============================================================================
# 企微IT智能服务台 — 管理员用户管理 API
# =============================================================================
# 说明:管理员用户的 CRUD API
# 端点:
# GET /api/admin/users — 获取管理员列表
# POST /api/admin/users — 创建管理员
# GET /api/admin/users/{id} — 获取管理员详情
# PUT /api/admin/users/{id} — 更新管理员
# DELETE /api/admin/users/{id} — 删除管理员
# POST /api/admin/users/{id}/reset-password — 重置密码
# =============================================================================
import logging
from typing import Optional
from fastapi import APIRouter, Depends, Query
from sqlalchemy.ext.asyncio import AsyncSession
from app.database import get_db
from app.dependencies import UserInfo, get_current_user, require_role
from app.schemas.admin_user import (
AdminUserCreateRequest,
AdminUserListResponse,
AdminUserResetPasswordRequest,
AdminUserResponse,
AdminUserUpdateRequest,
)
from app.services.admin_user_service import AdminUserService
from app.utils.response import AppException, success_response
from app.utils.error_codes import ErrorCode
logger = logging.getLogger(__name__)
# 创建路由器
router = APIRouter(prefix="/admin/users", tags=["管理员用户管理"])
# =============================================================================
# 0. GET /api/admin/users/me — 获取当前登录用户信息
# =============================================================================
@router.get("/me", response_model=None)
async def get_current_admin_user(
current_user: UserInfo = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
"""获取当前登录的管理员用户信息。
无需额外权限,任何已登录用户都可以访问。
Args:
current_user: 当前用户
db: 数据库会话
Returns:
当前用户信息
"""
service = AdminUserService(db)
agent = await service.get_user_by_user_id(current_user.employee_id)
if not agent:
raise AppException(ErrorCode.NOT_FOUND, "用户不存在")
return success_response(data=AdminUserResponse(
id=agent.id,
user_id=agent.user_id,
name=agent.name,
role=agent.role,
is_active=agent.status == "online",
mfa_enabled=agent.mfa_enabled,
mfa_bound_at=agent.mfa_bound_at,
created_at=agent.created_at,
updated_at=agent.updated_at,
).model_dump())
# =============================================================================
# 1. GET /api/admin/users — 获取管理员列表
# =============================================================================
@router.get("", response_model=None)
async def list_admin_users(
page: int = Query(1, ge=1, description="页码"),
page_size: int = Query(20, ge=1, le=100, description="每页数量"),
is_active: Optional[bool] = Query(None, description="是否激活(true=在线,false=离线)"),
current_user: UserInfo = Depends(require_role("admin")),
db: AsyncSession = Depends(get_db),
):
"""获取管理员用户列表。
需要 admin 或 super_admin 角色。
Args:
page: 页码
page_size: 每页数量
is_active: 按激活状态过滤
current_user: 当前用户
db: 数据库会话
Returns:
管理员列表
"""
service = AdminUserService(db)
items, total = await service.list_admin_users(
page=page,
page_size=page_size,
is_active=is_active,
)
# 转换为响应格式
user_responses = []
for agent in items:
user_responses.append(AdminUserResponse(
id=agent.id,
user_id=agent.user_id,
name=agent.name,
role=agent.role,
is_active=agent.status == "online",
mfa_enabled=agent.mfa_enabled,
mfa_bound_at=agent.mfa_bound_at,
created_at=agent.created_at,
updated_at=agent.updated_at,
))
return success_response(data=AdminUserListResponse(
items=user_responses,
total=total,
).model_dump())
# =============================================================================
# 2. POST /api/admin/users — 创建管理员
# =============================================================================
@router.post("", response_model=None)
async def create_admin_user(
body: AdminUserCreateRequest,
current_user: UserInfo = Depends(require_role("super_admin")),
db: AsyncSession = Depends(get_db),
):
"""创建管理员用户。
需要 super_admin 角色。
Args:
body: 创建请求
current_user: 当前用户
db: 数据库会话
Returns:
创建的用户信息
"""
service = AdminUserService(db)
try:
agent = await service.create_admin_user(
user_id=body.user_id,
name=body.name,
role=body.role,
password=body.password,
)
await db.commit()
return success_response(data=AdminUserResponse(
id=agent.id,
user_id=agent.user_id,
name=agent.name,
role=agent.role,
is_active=agent.status == "online",
mfa_enabled=agent.mfa_enabled,
mfa_bound_at=agent.mfa_bound_at,
created_at=agent.created_at,
updated_at=agent.updated_at,
).model_dump())
except AppException:
await db.rollback()
raise
except Exception as e:
await db.rollback()
logger.error(f"创建管理员失败: {e}")
raise AppException(ErrorCode.INTERNAL_ERROR, "创建管理员失败")
# =============================================================================
# 3. GET /api/admin/users/{id} — 获取管理员详情
# =============================================================================
@router.get("/{id}", response_model=None)
async def get_admin_user(
id: str,
current_user: UserInfo = Depends(require_role("admin")),
db: AsyncSession = Depends(get_db),
):
"""获取管理员用户详情。
需要 admin 或 super_admin 角色。
Args:
id: 用户ID
current_user: 当前用户
db: 数据库会话
Returns:
用户详情
"""
service = AdminUserService(db)
agent = await service.get_user_by_id(id)
if not agent:
raise AppException(ErrorCode.NOT_FOUND, "用户不存在")
return success_response(data=AdminUserResponse(
id=agent.id,
user_id=agent.user_id,
name=agent.name,
role=agent.role,
is_active=agent.status == "online",
mfa_enabled=agent.mfa_enabled,
mfa_bound_at=agent.mfa_bound_at,
created_at=agent.created_at,
updated_at=agent.updated_at,
).model_dump())
# =============================================================================
# 4. PUT /api/admin/users/{id} — 更新管理员
# =============================================================================
@router.put("/{id}", response_model=None)
async def update_admin_user(
id: str,
body: AdminUserUpdateRequest,
current_user: UserInfo = Depends(require_role("admin")),
db: AsyncSession = Depends(get_db),
):
"""更新管理员用户。
需要 admin 或 super_admin 角色。
- admin 角色只能更新普通 admin
- super_admin 角色可以更新所有用户
Args:
id: 用户ID
body: 更新请求
current_user: 当前用户
db: 数据库会话
Returns:
更新后的用户信息
"""
# 权限检查:非 super_admin 不能修改 super_admin
if "super_admin" not in current_user.roles:
target = await AdminUserService(db).get_user_by_id(id)
if target and target.role == "super_admin":
raise AppException(ErrorCode.FORBIDDEN, "无法修改超级管理员")
service = AdminUserService(db)
try:
agent = await service.update_admin_user(
id=id,
name=body.name,
role=body.role,
is_active=body.is_active,
)
await db.commit()
return success_response(data=AdminUserResponse(
id=agent.id,
user_id=agent.user_id,
name=agent.name,
role=agent.role,
is_active=agent.status == "online",
mfa_enabled=agent.mfa_enabled,
mfa_bound_at=agent.mfa_bound_at,
created_at=agent.created_at,
updated_at=agent.updated_at,
).model_dump())
except AppException:
await db.rollback()
raise
except Exception as e:
await db.rollback()
logger.error(f"更新管理员失败: {e}")
raise AppException(ErrorCode.INTERNAL_ERROR, "更新管理员失败")
# =============================================================================
# 5. DELETE /api/admin/users/{id} — 删除管理员
# =============================================================================
@router.delete("/{id}", response_model=None)
async def delete_admin_user(
id: str,
current_user: UserInfo = Depends(require_role("super_admin")),
db: AsyncSession = Depends(get_db),
):
"""删除管理员用户。
需要 super_admin 角色。
Args:
id: 用户ID
current_user: 当前用户
db: 数据库会话
Returns:
删除结果
"""
service = AdminUserService(db)
try:
await service.delete_admin_user(id)
await db.commit()
return success_response(data={"message": "删除成功"})
except AppException:
await db.rollback()
raise
except Exception as e:
await db.rollback()
logger.error(f"删除管理员失败: {e}")
raise AppException(ErrorCode.INTERNAL_ERROR, "删除管理员失败")
# =============================================================================
# 6. POST /api/admin/users/{id}/reset-password — 重置密码
# =============================================================================
@router.post("/{id}/reset-password", response_model=None)
async def reset_password(
id: str,
body: AdminUserResetPasswordRequest,
current_user: UserInfo = Depends(require_role("admin")),
db: AsyncSession = Depends(get_db),
):
"""重置管理员密码。
需要 admin 或 super_admin 角色。
Args:
id: 用户ID
body: 重置请求
current_user: 当前用户
db: 数据库会话
Returns:
重置结果
"""
# 权限检查:非 super_admin 不能重置 super_admin 的密码
if "super_admin" not in current_user.roles:
target = await AdminUserService(db).get_user_by_id(id)
if target and target.role == "super_admin":
raise AppException(ErrorCode.FORBIDDEN, "无法重置超级管理员密码")
service = AdminUserService(db)
try:
await service.reset_password(id, body.new_password)
await db.commit()
return success_response(data={"message": "密码重置成功"})
except AppException:
await db.rollback()
raise
except Exception as e:
await db.rollback()
logger.error(f"重置密码失败: {e}")
raise AppException(ErrorCode.INTERNAL_ERROR, "重置密码失败")