"""User signup endpoint.""" from typing import Optional from fastapi import APIRouter, Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer from sqlalchemy.ext.asyncio import AsyncSession from passlib.context import CryptContext from pydantic import BaseModel, EmailStr from ..dao.database import get_db from ..dao.user_dao import UserDAO from ..users import User router = APIRouter(prefix="/users", tags=["users"]) pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") class UserCreate(BaseModel): username: str email: Optional[EmailStr] = None full_name: Optional[str] = None password: str class UserResponse(BaseModel): id: int username: str email: Optional[str] = None full_name: Optional[str] = None disabled: bool class Config: from_attributes = True def hash_password(password: str) -> str: """Hash a password using bcrypt.""" return pwd_context.hash(password) @router.post("/signup", response_model=UserResponse, status_code=status.HTTP_201_CREATED) async def signup( user_data: UserCreate, db: AsyncSession = Depends(get_db) ): """Create a new user account.""" # Check if username already exists existing_user = await UserDAO.get_user_by_username(db, user_data.username) if existing_user: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Username already registered" ) # Check if email already exists (if provided) if user_data.email: existing_email = await UserDAO.get_user_by_email(db, user_data.email) if existing_email: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Email already registered" ) # Hash the password hashed_password = hash_password(user_data.password) # Create the user user = await UserDAO.create_user( db=db, username=user_data.username, email=user_data.email, full_name=user_data.full_name, hashed_password=hashed_password ) return UserResponse.from_orm(user)