from datetime import datetime from enum import Enum from typing import Optional, Annotated from bson import ObjectId from pydantic import BaseModel, EmailStr, Field, BeforeValidator def validate_object_id(v) -> str: """Convert ObjectId to string""" if isinstance(v, ObjectId): return str(v) if isinstance(v, str): return v raise ValueError('Invalid ObjectId') PyObjectId = Annotated[str, BeforeValidator(validate_object_id)] class UserRole(str, Enum): CLIENT = "client" REVIEWER = "reviewer" ADMIN = "admin" class AuthProvider(str, Enum): LOCAL = "local" MICROSOFT = "microsoft" class User(BaseModel): id: Optional[PyObjectId] = Field(None, alias="_id") email: EmailStr hashed_password: Optional[str] = None # Optional for Microsoft users full_name: str role: UserRole = UserRole.CLIENT auth_provider: AuthProvider = AuthProvider.LOCAL is_active: bool = True created_at: Optional[datetime] = None updated_at: Optional[datetime] = None class Config: populate_by_name = True use_enum_values = True class UserInDB(User): pass class UserCreate(BaseModel): email: EmailStr password: str full_name: str role: UserRole = UserRole.CLIENT class UserUpdate(BaseModel): email: Optional[EmailStr] = None full_name: Optional[str] = None role: Optional[UserRole] = None is_active: Optional[bool] = None