user.py
 1  """User-related schemas."""
 2  from datetime import datetime
 3  from typing import Optional
 4  
 5  from pydantic import BaseModel, EmailStr, Field, validator
 6  
 7  
 8  # Shared properties
 9  class UserBase(BaseModel):
10      """Base user schema with common fields."""
11      email: Optional[EmailStr] = None
12      is_active: Optional[bool] = True
13      full_name: Optional[str] = None
14      is_superuser: bool = False
15  
16  
17  # Properties to receive via API on creation
18  class UserCreate(UserBase):
19      """Schema for creating a new user."""
20      email: EmailStr
21      password: str = Field(..., min_length=8, max_length=100)
22      full_name: str = Field(..., min_length=2, max_length=100)
23  
24      @validator('password')
25      def password_strength(cls, v):
26          """Validate password strength."""
27          if len(v) < 8:
28              raise ValueError('Password must be at least 8 characters long')
29          if not any(c.isupper() for c in v):
30              raise ValueError('Password must contain at least one uppercase letter')
31          if not any(c.islower() for c in v):
32              raise ValueError('Password must contain at least one lowercase letter')
33          if not any(c.isdigit() for c in v):
34              raise ValueError('Password must contain at least one number')
35          return v
36  
37  
38  # Properties to receive via API on update
39  class UserUpdate(UserBase):
40      """Schema for updating a user."""
41      password: Optional[str] = Field(None, min_length=8, max_length=100)
42      email: Optional[EmailStr] = None
43  
44  
45  class UserInDBBase(UserBase):
46      """Base schema for user stored in DB."""
47      id: Optional[int] = None
48      created_at: Optional[datetime] = None
49      updated_at: Optional[datetime] = None
50  
51      class Config:
52          """Pydantic config."""
53          orm_mode = True
54  
55  
56  # Additional properties to return via API
57  class User(UserInDBBase):
58      """User schema for API responses."""
59      pass
60  
61  
62  # Additional properties stored in DB
63  class UserInDB(UserInDBBase):
64      """User schema for data stored in the database."""
65      hashed_password: str
66  
67  
68  class UserLogin(BaseModel):
69      """Schema for user login."""
70      email: EmailStr
71      password: str = Field(..., min_length=8)
72  
73  
74  class UserRegister(UserCreate):
75      """Schema for user registration."""
76      password_confirm: str
77  
78      @validator('password_confirm')
79      def passwords_match(cls, v, values, **kwargs):
80          """Validate that passwords match."""
81          if 'password' in values and v != values['password']:
82              raise ValueError('passwords do not match')
83          return v