181 lines
5.6 KiB
Python
181 lines
5.6 KiB
Python
"""
|
|
用户管理 API 接口
|
|
|
|
演示权限控制的使用
|
|
"""
|
|
from typing import List
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
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.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("/", response_model=List[UserResponse])
|
|
async def list_users(
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
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}", response_model=UserResponse)
|
|
async def get_user(
|
|
user_id: int,
|
|
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}", response_model=UserResponse)
|
|
async def update_user(
|
|
user_id: int,
|
|
user_update: UserUpdate,
|
|
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}")
|
|
async def delete_user(
|
|
user_id: int,
|
|
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")
|
|
async def activate_user(
|
|
user_id: int,
|
|
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")
|
|
async def deactivate_user(
|
|
user_id: int,
|
|
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)
|