Pradeep Rajan
Initial deployment of Zyon Traders Backend7
5c7dec2
"""
Pydantic models for authentication
"""
from pydantic import BaseModel, EmailStr, Field, validator
from typing import Optional
from datetime import datetime
class UserSignup(BaseModel):
email: EmailStr = Field(..., description="User email address")
password: str = Field(..., min_length=8, description="User password (minimum 8 characters)")
first_name: str = Field(..., min_length=1, max_length=50, description="First name")
last_name: str = Field(..., min_length=1, max_length=50, description="Last name")
@validator('password')
def validate_password(cls, v):
if len(v) < 8:
raise ValueError('Password must be at least 8 characters long')
if not any(c.isupper() for c in v):
raise ValueError('Password must contain at least one uppercase letter')
if not any(c.islower() for c in v):
raise ValueError('Password must contain at least one lowercase letter')
if not any(c.isdigit() for c in v):
raise ValueError('Password must contain at least one digit')
return v
class UserLogin(BaseModel):
email: EmailStr = Field(..., description="User email address")
password: str = Field(..., description="User password")
class UserResponse(BaseModel):
id: str
email: str
first_name: str
last_name: str
role: str
message: Optional[str] = None
created_at: Optional[datetime] = None
updated_at: Optional[datetime] = None
class TokenResponse(BaseModel):
access_token: str
token_type: str = "bearer"
expires_in: int
user: Optional[UserResponse] = None
class PasswordReset(BaseModel):
token: str = Field(..., description="Password reset token")
new_password: str = Field(..., min_length=8, description="New password")
@validator('new_password')
def validate_password(cls, v):
if len(v) < 8:
raise ValueError('Password must be at least 8 characters long')
if not any(c.isupper() for c in v):
raise ValueError('Password must contain at least one uppercase letter')
if not any(c.islower() for c in v):
raise ValueError('Password must contain at least one lowercase letter')
if not any(c.isdigit() for c in v):
raise ValueError('Password must contain at least one digit')
return v
class TokenPayload(BaseModel):
sub: str # Subject (user ID)
email: str
role: str
exp: datetime
iat: datetime
class GoogleAuthRequest(BaseModel):
id_token: str = Field(..., description="Google ID token")
class RefreshTokenRequest(BaseModel):
refresh_token: str = Field(..., description="Refresh token")
class ChangePasswordRequest(BaseModel):
current_password: str = Field(..., description="Current password")
new_password: str = Field(..., min_length=8, description="New password")
@validator('new_password')
def validate_password(cls, v):
if len(v) < 8:
raise ValueError('Password must be at least 8 characters long')
if not any(c.isupper() for c in v):
raise ValueError('Password must contain at least one uppercase letter')
if not any(c.islower() for c in v):
raise ValueError('Password must contain at least one lowercase letter')
if not any(c.isdigit() for c in v):
raise ValueError('Password must contain at least one digit')
return v
class UpdateProfileRequest(BaseModel):
first_name: Optional[str] = Field(None, min_length=1, max_length=50)
last_name: Optional[str] = Field(None, min_length=1, max_length=50)
phone: Optional[str] = Field(None, regex=r'^\+?[1-9]\d{1,14}$')
preferences: Optional[dict] = None
class UserPreferences(BaseModel):
theme: Optional[str] = Field("light", regex=r'^(light|dark|auto)$')
notifications: Optional[bool] = True
email_alerts: Optional[bool] = True
sms_alerts: Optional[bool] = False
trading_alerts: Optional[bool] = True
default_order_type: Optional[str] = Field("MARKET", regex=r'^(MARKET|LIMIT)$')
default_product_type: Optional[str] = Field("CNC", regex=r'^(CNC|MIS|NRML)$')
risk_tolerance: Optional[str] = Field("MEDIUM", regex=r'^(LOW|MEDIUM|HIGH)$')
investment_experience: Optional[str] = Field("INTERMEDIATE", regex=r'^(BEGINNER|INTERMEDIATE|ADVANCED)$')
class UserRole(BaseModel):
role: str = Field(..., regex=r'^(admin|instructor|trader|student)$')
permissions: Optional[list] = []
class AdminUserUpdate(BaseModel):
role: Optional[str] = Field(None, regex=r'^(admin|instructor|trader|student)$')
is_active: Optional[bool] = None
permissions: Optional[list] = None