2025-12-04 14:48:38 +08:00
|
|
|
"""User management endpoints."""
|
|
|
|
|
|
|
|
|
|
from typing import List, Optional
|
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, status, Query
|
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
|
|
2025-12-16 13:55:16 +08:00
|
|
|
from ...db.database import get_session
|
2025-12-04 14:48:38 +08:00
|
|
|
from ...core.simple_permissions import require_super_admin
|
|
|
|
|
from ...services.auth import AuthService
|
|
|
|
|
from ...services.user import UserService
|
|
|
|
|
from ...schemas.user import UserResponse, UserUpdate, UserCreate, ChangePasswordRequest, ResetPasswordRequest
|
|
|
|
|
|
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
2025-12-16 13:55:16 +08:00
|
|
|
@router.get("/profile", response_model=UserResponse, summary="获取当前用户的个人信息")
|
2025-12-04 14:48:38 +08:00
|
|
|
async def get_user_profile(
|
|
|
|
|
current_user = Depends(AuthService.get_current_user)
|
|
|
|
|
):
|
2025-12-16 13:55:16 +08:00
|
|
|
"""获取当前用户的个人信息."""
|
|
|
|
|
return UserResponse.model_validate(current_user)
|
2025-12-04 14:48:38 +08:00
|
|
|
|
2025-12-16 13:55:16 +08:00
|
|
|
@router.put("/profile", response_model=UserResponse, summary="更新当前用户的个人信息")
|
2025-12-04 14:48:38 +08:00
|
|
|
async def update_user_profile(
|
|
|
|
|
user_update: UserUpdate,
|
|
|
|
|
current_user = Depends(AuthService.get_current_user),
|
2025-12-16 13:55:16 +08:00
|
|
|
session: Session = Depends(get_session)
|
2025-12-04 14:48:38 +08:00
|
|
|
):
|
2025-12-16 13:55:16 +08:00
|
|
|
"""更新当前用户的个人信息."""
|
|
|
|
|
user_service = UserService(session)
|
2025-12-04 14:48:38 +08:00
|
|
|
|
|
|
|
|
# Check if email is being changed and is already taken
|
|
|
|
|
if user_update.email and user_update.email != current_user.email:
|
2025-12-16 13:55:16 +08:00
|
|
|
existing_user = await user_service.get_user_by_email(user_update.email)
|
2025-12-04 14:48:38 +08:00
|
|
|
if existing_user:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
|
|
|
detail="Email already registered"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Update user
|
2025-12-16 13:55:16 +08:00
|
|
|
updated_user = await user_service.update_user(current_user.id, user_update)
|
|
|
|
|
return UserResponse.model_validate(updated_user)
|
2025-12-04 14:48:38 +08:00
|
|
|
|
2025-12-16 13:55:16 +08:00
|
|
|
@router.delete("/profile", summary="删除当前用户的账户")
|
2025-12-04 14:48:38 +08:00
|
|
|
async def delete_user_account(
|
|
|
|
|
current_user = Depends(AuthService.get_current_user),
|
2025-12-16 13:55:16 +08:00
|
|
|
session: Session = Depends(get_session)
|
2025-12-04 14:48:38 +08:00
|
|
|
):
|
2025-12-16 13:55:16 +08:00
|
|
|
"""删除当前用户的账户."""
|
|
|
|
|
username = current_user.username
|
|
|
|
|
user_service = UserService(session)
|
|
|
|
|
await user_service.delete_user(current_user.id)
|
|
|
|
|
session.desc = f"删除用户 [{username}] 成功"
|
|
|
|
|
return {"message": f"删除用户 {username} 成功"}
|
2025-12-04 14:48:38 +08:00
|
|
|
|
|
|
|
|
# Admin endpoints
|
2025-12-16 13:55:16 +08:00
|
|
|
@router.post("/", response_model=UserResponse, summary="创建新用户 (需要有管理员权限)")
|
|
|
|
|
async def create_user(
|
2025-12-04 14:48:38 +08:00
|
|
|
user_create: UserCreate,
|
2025-12-16 13:55:16 +08:00
|
|
|
current_user = Depends(require_super_admin),
|
|
|
|
|
session: Session = Depends(get_session)
|
2025-12-04 14:48:38 +08:00
|
|
|
):
|
2025-12-16 13:55:16 +08:00
|
|
|
"""创建一个新用户 (需要有管理员权限)."""
|
|
|
|
|
user_service = UserService(session)
|
2025-12-04 14:48:38 +08:00
|
|
|
|
|
|
|
|
# Check if username already exists
|
2025-12-16 13:55:16 +08:00
|
|
|
existing_user = await user_service.get_user_by_username(user_create.username)
|
2025-12-04 14:48:38 +08:00
|
|
|
if existing_user:
|
2025-12-16 13:55:16 +08:00
|
|
|
session.desc = f"创建用户 [{user_create.username}] 失败 - 用户名已存在"
|
2025-12-04 14:48:38 +08:00
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
|
|
|
detail="Username already registered"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Check if email already exists
|
2025-12-16 13:55:16 +08:00
|
|
|
existing_user = await user_service.get_user_by_email(user_create.email)
|
2025-12-04 14:48:38 +08:00
|
|
|
if existing_user:
|
2025-12-16 13:55:16 +08:00
|
|
|
session.desc = f"创建用户 [{user_create.username}] 失败 - 邮箱已存在"
|
2025-12-04 14:48:38 +08:00
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
|
|
|
detail="Email already registered"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Create user
|
2025-12-16 13:55:16 +08:00
|
|
|
new_user = await user_service.create_user(user_create)
|
|
|
|
|
return UserResponse.model_validate(new_user)
|
2025-12-04 14:48:38 +08:00
|
|
|
|
2025-12-16 13:55:16 +08:00
|
|
|
@router.get("/", summary="列出所有用户,支持分页和筛选 (仅管理员权限)")
|
2025-12-04 14:48:38 +08:00
|
|
|
async def list_users(
|
|
|
|
|
page: int = Query(1, ge=1),
|
|
|
|
|
size: int = Query(20, ge=1, le=100),
|
|
|
|
|
search: Optional[str] = Query(None),
|
|
|
|
|
role_id: Optional[int] = Query(None),
|
|
|
|
|
is_active: Optional[bool] = Query(None),
|
2025-12-16 13:55:16 +08:00
|
|
|
session: Session = Depends(get_session)
|
2025-12-04 14:48:38 +08:00
|
|
|
):
|
2025-12-16 13:55:16 +08:00
|
|
|
"""列出所有用户,支持分页和筛选 (仅管理员权限)."""
|
|
|
|
|
session.desc = f"START: 列出所有用户,分页={page}, 每页大小={size}, 搜索={search}, 角色ID={role_id}, 激活状态={is_active}"
|
|
|
|
|
user_service = UserService(session)
|
2025-12-04 14:48:38 +08:00
|
|
|
skip = (page - 1) * size
|
2025-12-16 13:55:16 +08:00
|
|
|
users, total = await user_service.get_users_with_filters(
|
2025-12-04 14:48:38 +08:00
|
|
|
skip=skip,
|
|
|
|
|
limit=size,
|
|
|
|
|
search=search,
|
|
|
|
|
role_id=role_id,
|
|
|
|
|
is_active=is_active
|
|
|
|
|
)
|
|
|
|
|
result = {
|
2025-12-16 13:55:16 +08:00
|
|
|
"users": [UserResponse.model_validate(user) for user in users],
|
2025-12-04 14:48:38 +08:00
|
|
|
"total": total,
|
|
|
|
|
"page": page,
|
|
|
|
|
"page_size": size
|
|
|
|
|
}
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
2025-12-16 13:55:16 +08:00
|
|
|
@router.get("/{user_id}", response_model=UserResponse, summary="通过ID获取用户信息 (仅管理员权限)")
|
2025-12-04 14:48:38 +08:00
|
|
|
async def get_user(
|
|
|
|
|
user_id: int,
|
|
|
|
|
current_user = Depends(AuthService.get_current_active_user),
|
2025-12-16 13:55:16 +08:00
|
|
|
session: Session = Depends(get_session)
|
2025-12-04 14:48:38 +08:00
|
|
|
):
|
2025-12-16 13:55:16 +08:00
|
|
|
"""通过ID获取用户信息 (仅管理员权限)."""
|
|
|
|
|
user_service = UserService(session)
|
|
|
|
|
user = await user_service.get_user_by_id(user_id)
|
2025-12-04 14:48:38 +08:00
|
|
|
if not user:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
|
|
|
detail="User not found"
|
|
|
|
|
)
|
2025-12-16 13:55:16 +08:00
|
|
|
return UserResponse.model_validate(user)
|
2025-12-04 14:48:38 +08:00
|
|
|
|
2025-12-16 13:55:16 +08:00
|
|
|
@router.put("/change-password", summary="修改当前用户的密码")
|
2025-12-04 14:48:38 +08:00
|
|
|
async def change_password(
|
|
|
|
|
request: ChangePasswordRequest,
|
|
|
|
|
current_user = Depends(AuthService.get_current_active_user),
|
2025-12-16 13:55:16 +08:00
|
|
|
session: Session = Depends(get_session)
|
2025-12-04 14:48:38 +08:00
|
|
|
):
|
2025-12-16 13:55:16 +08:00
|
|
|
"""修改当前用户的密码."""
|
|
|
|
|
user_service = UserService(session)
|
2025-12-04 14:48:38 +08:00
|
|
|
|
|
|
|
|
try:
|
2025-12-16 13:55:16 +08:00
|
|
|
await user_service.change_password(
|
2025-12-04 14:48:38 +08:00
|
|
|
user_id=current_user.id,
|
|
|
|
|
current_password=request.current_password,
|
|
|
|
|
new_password=request.new_password
|
|
|
|
|
)
|
|
|
|
|
return {"message": "Password changed successfully"}
|
|
|
|
|
except Exception as e:
|
|
|
|
|
if "Current password is incorrect" in str(e):
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
|
|
|
detail="Current password is incorrect"
|
|
|
|
|
)
|
|
|
|
|
elif "must be at least 6 characters" in str(e):
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
|
|
|
detail="New password must be at least 6 characters long"
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
|
|
|
detail="Failed to change password"
|
|
|
|
|
)
|
|
|
|
|
|
2025-12-16 13:55:16 +08:00
|
|
|
@router.put("/{user_id}/reset-password", summary="重置用户密码 (仅管理员权限)")
|
2025-12-04 14:48:38 +08:00
|
|
|
async def reset_user_password(
|
|
|
|
|
user_id: int,
|
|
|
|
|
request: ResetPasswordRequest,
|
|
|
|
|
current_user = Depends(require_super_admin),
|
2025-12-16 13:55:16 +08:00
|
|
|
session: Session = Depends(get_session)
|
2025-12-04 14:48:38 +08:00
|
|
|
):
|
2025-12-16 13:55:16 +08:00
|
|
|
"""重置用户密码 (仅管理员权限)."""
|
|
|
|
|
user_service = UserService(session)
|
2025-12-04 14:48:38 +08:00
|
|
|
|
|
|
|
|
try:
|
2025-12-16 13:55:16 +08:00
|
|
|
await user_service.reset_password(
|
2025-12-04 14:48:38 +08:00
|
|
|
user_id=user_id,
|
|
|
|
|
new_password=request.new_password
|
|
|
|
|
)
|
|
|
|
|
return {"message": "Password reset successfully"}
|
|
|
|
|
except Exception as e:
|
|
|
|
|
if "User not found" in str(e):
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
|
|
|
detail="User not found"
|
|
|
|
|
)
|
|
|
|
|
elif "must be at least 6 characters" in str(e):
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
|
|
|
detail="New password must be at least 6 characters long"
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
|
|
|
detail="Failed to reset password"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2025-12-16 13:55:16 +08:00
|
|
|
@router.put("/{user_id}", response_model=UserResponse, summary="更新用户信息 (仅管理员权限)")
|
2025-12-04 14:48:38 +08:00
|
|
|
async def update_user(
|
|
|
|
|
user_id: int,
|
|
|
|
|
user_update: UserUpdate,
|
|
|
|
|
current_user = Depends(AuthService.get_current_active_user),
|
2025-12-16 13:55:16 +08:00
|
|
|
session: Session = Depends(get_session)
|
2025-12-04 14:48:38 +08:00
|
|
|
):
|
2025-12-16 13:55:16 +08:00
|
|
|
"""更新用户信息 (仅管理员权限)."""
|
|
|
|
|
user_service = UserService(session)
|
2025-12-04 14:48:38 +08:00
|
|
|
|
2025-12-16 13:55:16 +08:00
|
|
|
user = await user_service.get_user_by_id(user_id)
|
2025-12-04 14:48:38 +08:00
|
|
|
if not user:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
|
|
|
detail="User not found"
|
|
|
|
|
)
|
|
|
|
|
|
2025-12-16 13:55:16 +08:00
|
|
|
updated_user = await user_service.update_user(user_id, user_update)
|
|
|
|
|
return UserResponse.model_validate(updated_user)
|
2025-12-04 14:48:38 +08:00
|
|
|
|
2025-12-16 13:55:16 +08:00
|
|
|
@router.delete("/{user_id}", summary="删除用户 (仅管理员权限)")
|
2025-12-04 14:48:38 +08:00
|
|
|
async def delete_user(
|
|
|
|
|
user_id: int,
|
|
|
|
|
current_user = Depends(AuthService.get_current_active_user),
|
2025-12-16 13:55:16 +08:00
|
|
|
session: Session = Depends(get_session)
|
2025-12-04 14:48:38 +08:00
|
|
|
):
|
2025-12-16 13:55:16 +08:00
|
|
|
"""删除用户 (仅管理员权限)."""
|
|
|
|
|
user_service = UserService(session)
|
2025-12-04 14:48:38 +08:00
|
|
|
|
2025-12-16 13:55:16 +08:00
|
|
|
user = await user_service.get_user_by_id(user_id)
|
2025-12-04 14:48:38 +08:00
|
|
|
if not user:
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
|
|
|
detail="User not found"
|
|
|
|
|
)
|
|
|
|
|
|
2025-12-16 13:55:16 +08:00
|
|
|
await user_service.delete_user(user_id)
|
2025-12-04 14:48:38 +08:00
|
|
|
return {"message": "User deleted successfully"}
|