hxf/backend/th_agenter/api/endpoints/users.py

241 lines
7.4 KiB
Python

"""User management endpoints."""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.orm import Session
from ...db.database import get_db
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()
@router.get("/profile", response_model=UserResponse)
async def get_user_profile(
current_user = Depends(AuthService.get_current_user)
):
"""Get current user profile."""
return UserResponse.from_orm(current_user)
@router.put("/profile", response_model=UserResponse)
async def update_user_profile(
user_update: UserUpdate,
current_user = Depends(AuthService.get_current_user),
db: Session = Depends(get_db)
):
"""Update current user profile."""
user_service = UserService(db)
# Check if email is being changed and is already taken
if user_update.email and user_update.email != current_user.email:
existing_user = user_service.get_user_by_email(user_update.email)
if existing_user:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Email already registered"
)
# Update user
updated_user = user_service.update_user(current_user.id, user_update)
return UserResponse.from_orm(updated_user)
@router.delete("/profile")
async def delete_user_account(
current_user = Depends(AuthService.get_current_user),
db: Session = Depends(get_db)
):
"""Delete current user account."""
user_service = UserService(db)
user_service.delete_user(current_user.id)
return {"message": "Account deleted successfully"}
# Admin endpoints
@router.post("/", response_model=UserResponse)
async def create_user(
user_create: UserCreate,
# current_user = Depends(require_superuser),
db: Session = Depends(get_db)
):
"""Create a new user (admin only)."""
user_service = UserService(db)
# Check if username already exists
existing_user = user_service.get_user_by_username(user_create.username)
if existing_user:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Username already registered"
)
# Check if email already exists
existing_user = user_service.get_user_by_email(user_create.email)
if existing_user:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Email already registered"
)
# Create user
new_user = user_service.create_user(user_create)
return UserResponse.from_orm(new_user)
@router.get("/")
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),
# current_user = Depends(require_superuser),
db: Session = Depends(get_db)
):
"""List all users with pagination and filters (admin only)."""
user_service = UserService(db)
skip = (page - 1) * size
users, total = user_service.get_users_with_filters(
skip=skip,
limit=size,
search=search,
role_id=role_id,
is_active=is_active
)
result = {
"users": [UserResponse.from_orm(user) for user in users],
"total": total,
"page": page,
"page_size": size
}
return result
@router.get("/{user_id}", response_model=UserResponse)
async def get_user(
user_id: int,
current_user = Depends(AuthService.get_current_active_user),
db: Session = Depends(get_db)
):
"""Get user by ID (admin only)."""
user_service = UserService(db)
user = user_service.get_user(user_id)
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found"
)
return UserResponse.from_orm(user)
@router.put("/change-password")
async def change_password(
request: ChangePasswordRequest,
current_user = Depends(AuthService.get_current_active_user),
db: Session = Depends(get_db)
):
"""Change current user's password."""
user_service = UserService(db)
try:
user_service.change_password(
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"
)
@router.put("/{user_id}/reset-password")
async def reset_user_password(
user_id: int,
request: ResetPasswordRequest,
current_user = Depends(require_super_admin),
db: Session = Depends(get_db)
):
"""Reset user password (admin only)."""
user_service = UserService(db)
try:
user_service.reset_password(
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"
)
@router.put("/{user_id}", response_model=UserResponse)
async def update_user(
user_id: int,
user_update: UserUpdate,
current_user = Depends(AuthService.get_current_active_user),
db: Session = Depends(get_db)
):
"""Update user by ID (admin only)."""
user_service = UserService(db)
user = user_service.get_user(user_id)
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found"
)
updated_user = user_service.update_user(user_id, user_update)
return UserResponse.from_orm(updated_user)
@router.delete("/{user_id}")
async def delete_user(
user_id: int,
current_user = Depends(AuthService.get_current_active_user),
db: Session = Depends(get_db)
):
"""Delete user by ID (admin only)."""
user_service = UserService(db)
user = user_service.get_user(user_id)
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found"
)
user_service.delete_user(user_id)
return {"message": "User deleted successfully"}