Yassine Mhirsi
feat: Implement user management service with Supabase integration, including user registration, retrieval, and name update endpoints.
6e8d513
raw
history blame
3.93 kB
"""User management endpoints"""
from fastapi import APIRouter, HTTPException, Header
from typing import Optional
import logging
from services.user_service import user_service
from models.user import (
UserRegisterRequest,
UserResponse,
UserUpdateNameRequest,
UserGetRequest,
)
router = APIRouter()
logger = logging.getLogger(__name__)
@router.post("/register", response_model=UserResponse, tags=["Users"])
async def register_user(request: UserRegisterRequest):
"""
Register a new user or get existing user by unique_id
- **unique_id**: Browser-generated unique identifier (from localStorage)
- **name**: Optional display name (will generate random if not provided)
Returns user data including the user_id to store in localStorage
"""
try:
user = user_service.register_or_get_user(
unique_id=request.unique_id,
name=request.name
)
logger.info(f"User registered/retrieved: {user.get('id')}")
return UserResponse(**user)
except ValueError as e:
logger.error(f"Validation error: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"Registration error: {str(e)}")
raise HTTPException(status_code=500, detail=f"Registration failed: {str(e)}")
@router.get("/me", response_model=UserResponse, tags=["Users"])
async def get_current_user(x_user_id: Optional[str] = Header(None, alias="X-User-ID")):
"""
Get current user by user_id from header
- **X-User-ID**: User UUID (sent in request header)
Returns user data
"""
if not x_user_id:
raise HTTPException(status_code=400, detail="X-User-ID header is required")
try:
user = user_service.get_user_by_id(x_user_id)
if not user:
raise HTTPException(status_code=404, detail="User not found")
return UserResponse(**user)
except HTTPException:
raise
except Exception as e:
logger.error(f"Error getting user: {str(e)}")
raise HTTPException(status_code=500, detail=f"Failed to get user: {str(e)}")
@router.get("/by-unique-id", response_model=UserResponse, tags=["Users"])
async def get_user_by_unique_id(unique_id: str):
"""
Get user by unique_id (query parameter)
- **unique_id**: Browser-generated unique identifier
Returns user data
"""
try:
user = user_service.get_user_by_unique_id(unique_id)
if not user:
raise HTTPException(status_code=404, detail="User not found")
return UserResponse(**user)
except HTTPException:
raise
except Exception as e:
logger.error(f"Error getting user: {str(e)}")
raise HTTPException(status_code=500, detail=f"Failed to get user: {str(e)}")
@router.patch("/me/name", response_model=UserResponse, tags=["Users"])
async def update_user_name(
request: UserUpdateNameRequest,
x_user_id: Optional[str] = Header(None, alias="X-User-ID")
):
"""
Update user's display name
- **X-User-ID**: User UUID (sent in request header)
- **name**: New display name
Returns updated user data
"""
if not x_user_id:
raise HTTPException(status_code=400, detail="X-User-ID header is required")
try:
user = user_service.update_user_name(
user_id=x_user_id,
name=request.name
)
logger.info(f"Updated user name: {x_user_id}")
return UserResponse(**user)
except ValueError as e:
logger.error(f"Validation error: {str(e)}")
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"Update error: {str(e)}")
raise HTTPException(status_code=500, detail=f"Update failed: {str(e)}")