216 lines
6.7 KiB
Python
216 lines
6.7 KiB
Python
"""
|
|
用户管理 API 接口
|
|
|
|
演示权限控制的使用
|
|
"""
|
|
|
|
from typing import List
|
|
from fastapi import APIRouter, Depends, HTTPException, status, Path, Query
|
|
from app.domain.schemas.user import UserResponse, UserUpdate, UserCreate
|
|
from app.domain.models.role import UserRole
|
|
from app.domain.schemas.user import UserInDB
|
|
from app.infra.db.metadb.repositories.user_repository import UserRepository
|
|
from app.auth.dependencies import get_user_repository, get_current_active_user
|
|
from app.auth.permissions import get_current_admin, require_role, check_resource_owner
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get(
|
|
"/",
|
|
summary="列出所有用户",
|
|
description="获取用户列表(仅管理员)",
|
|
response_model=List[UserResponse],
|
|
)
|
|
async def list_users(
|
|
skip: int = Query(0, ge=0, description="跳过的用户数"),
|
|
limit: int = Query(100, ge=1, le=1000, description="返回的最大用户数"),
|
|
current_user: UserInDB = Depends(require_role(UserRole.ADMIN)),
|
|
user_repo: UserRepository = Depends(get_user_repository),
|
|
) -> List[UserResponse]:
|
|
"""
|
|
获取用户列表
|
|
|
|
获取系统中所有的用户信息(需要管理员权限)
|
|
"""
|
|
users = await user_repo.get_all_users(skip=skip, limit=limit)
|
|
return [UserResponse.model_validate(user) for user in users]
|
|
|
|
|
|
@router.get(
|
|
"/{user_id}",
|
|
summary="获取用户详情",
|
|
description="获取指定用户的详细信息",
|
|
response_model=UserResponse,
|
|
)
|
|
async def get_user(
|
|
user_id: int = Path(..., gt=0, description="用户ID"),
|
|
current_user: UserInDB = Depends(get_current_active_user),
|
|
user_repo: UserRepository = Depends(get_user_repository),
|
|
) -> UserResponse:
|
|
"""
|
|
获取用户详情
|
|
|
|
管理员可查看所有用户,普通用户只能查看自己
|
|
"""
|
|
# 检查权限
|
|
if not check_resource_owner(user_id, current_user):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="You don't have permission to view this user",
|
|
)
|
|
|
|
user = await user_repo.get_user_by_id(user_id)
|
|
if not user:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND, detail="User not found"
|
|
)
|
|
|
|
return UserResponse.model_validate(user)
|
|
|
|
|
|
@router.put(
|
|
"/{user_id}",
|
|
summary="更新用户信息",
|
|
description="更新指定用户的信息",
|
|
response_model=UserResponse,
|
|
)
|
|
async def update_user(
|
|
user_id: int = Path(..., gt=0, description="用户ID"),
|
|
user_update: UserUpdate = None,
|
|
current_user: UserInDB = Depends(get_current_active_user),
|
|
user_repo: UserRepository = Depends(get_user_repository),
|
|
) -> UserResponse:
|
|
"""
|
|
更新用户信息
|
|
|
|
管理员可更新所有用户,普通用户只能更新自己(且不能修改角色)
|
|
"""
|
|
# 检查用户是否存在
|
|
target_user = await user_repo.get_user_by_id(user_id)
|
|
if not target_user:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND, detail="User not found"
|
|
)
|
|
|
|
# 权限检查
|
|
is_owner = current_user.id == user_id
|
|
is_admin = UserRole(current_user.role).has_permission(UserRole.ADMIN)
|
|
|
|
if not is_owner and not is_admin:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="You don't have permission to update this user",
|
|
)
|
|
|
|
# 非管理员不能修改角色和激活状态
|
|
if not is_admin:
|
|
if user_update.role is not None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="Only admins can change user roles",
|
|
)
|
|
if user_update.is_active is not None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="Only admins can change user active status",
|
|
)
|
|
|
|
# 更新用户
|
|
updated_user = await user_repo.update_user(user_id, user_update)
|
|
if not updated_user:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="Failed to update user",
|
|
)
|
|
|
|
return UserResponse.model_validate(updated_user)
|
|
|
|
|
|
@router.delete("/{user_id}", summary="删除用户", description="删除指定用户(仅管理员)")
|
|
async def delete_user(
|
|
user_id: int = Path(..., gt=0, description="用户ID"),
|
|
current_user: UserInDB = Depends(get_current_admin),
|
|
user_repo: UserRepository = Depends(get_user_repository),
|
|
) -> dict:
|
|
"""
|
|
删除用户
|
|
|
|
删除指定用户(需要管理员权限,不能删除自己)
|
|
"""
|
|
# 不能删除自己
|
|
if current_user.id == user_id:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="You cannot delete your own account",
|
|
)
|
|
|
|
success = await user_repo.delete_user(user_id)
|
|
if not success:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND, detail="User not found"
|
|
)
|
|
|
|
return {"message": "User deleted successfully"}
|
|
|
|
|
|
@router.post(
|
|
"/{user_id}/activate",
|
|
summary="激活用户",
|
|
description="激活指定用户账户(仅管理员)",
|
|
response_model=UserResponse,
|
|
)
|
|
async def activate_user(
|
|
user_id: int = Path(..., gt=0, description="用户ID"),
|
|
current_user: UserInDB = Depends(get_current_admin),
|
|
user_repo: UserRepository = Depends(get_user_repository),
|
|
) -> UserResponse:
|
|
"""
|
|
激活用户
|
|
|
|
激活指定用户的账户(需要管理员权限)
|
|
"""
|
|
user_update = UserUpdate(is_active=True)
|
|
updated_user = await user_repo.update_user(user_id, user_update)
|
|
|
|
if not updated_user:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND, detail="User not found"
|
|
)
|
|
|
|
return UserResponse.model_validate(updated_user)
|
|
|
|
|
|
@router.post(
|
|
"/{user_id}/deactivate",
|
|
summary="停用用户",
|
|
description="停用指定用户账户(仅管理员)",
|
|
response_model=UserResponse,
|
|
)
|
|
async def deactivate_user(
|
|
user_id: int = Path(..., gt=0, description="用户ID"),
|
|
current_user: UserInDB = Depends(get_current_admin),
|
|
user_repo: UserRepository = Depends(get_user_repository),
|
|
) -> UserResponse:
|
|
"""
|
|
停用用户
|
|
|
|
停用指定用户的账户(需要管理员权限,不能停用自己)
|
|
"""
|
|
# 不能停用自己
|
|
if current_user.id == user_id:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="You cannot deactivate your own account",
|
|
)
|
|
|
|
user_update = UserUpdate(is_active=False)
|
|
updated_user = await user_repo.update_user(user_id, user_update)
|
|
|
|
if not updated_user:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND, detail="User not found"
|
|
)
|
|
|
|
return UserResponse.model_validate(updated_user)
|