186 lines
5.4 KiB
Python
186 lines
5.4 KiB
Python
# services/auth/app/schemas/auth.py - UPDATED WITH UNIFIED TOKEN RESPONSE
|
|
"""
|
|
Authentication schemas - Updated with unified token response format
|
|
Following industry best practices from Firebase, Cognito, etc.
|
|
"""
|
|
|
|
from pydantic import BaseModel, EmailStr, Field
|
|
from typing import Optional, Dict, Any
|
|
from datetime import datetime
|
|
|
|
# ================================================================
|
|
# REQUEST SCHEMAS
|
|
# ================================================================
|
|
|
|
class UserRegistration(BaseModel):
|
|
"""User registration request"""
|
|
email: EmailStr
|
|
password: str = Field(..., min_length=8, max_length=128)
|
|
full_name: str = Field(..., min_length=1, max_length=255)
|
|
tenant_name: Optional[str] = Field(None, max_length=255)
|
|
|
|
class UserLogin(BaseModel):
|
|
"""User login request"""
|
|
email: EmailStr
|
|
password: str
|
|
|
|
class RefreshTokenRequest(BaseModel):
|
|
"""Refresh token request"""
|
|
refresh_token: str
|
|
|
|
class PasswordChange(BaseModel):
|
|
"""Password change request"""
|
|
current_password: str
|
|
new_password: str = Field(..., min_length=8, max_length=128)
|
|
|
|
class PasswordReset(BaseModel):
|
|
"""Password reset request"""
|
|
email: EmailStr
|
|
|
|
class PasswordResetConfirm(BaseModel):
|
|
"""Password reset confirmation"""
|
|
token: str
|
|
new_password: str = Field(..., min_length=8, max_length=128)
|
|
|
|
# ================================================================
|
|
# RESPONSE SCHEMAS
|
|
# ================================================================
|
|
|
|
class UserData(BaseModel):
|
|
"""User data embedded in token responses"""
|
|
id: str
|
|
email: str
|
|
full_name: str
|
|
is_active: bool
|
|
is_verified: bool
|
|
created_at: str # ISO format datetime string
|
|
tenant_id: Optional[str] = None
|
|
role: Optional[str] = "user"
|
|
|
|
class TokenResponse(BaseModel):
|
|
"""
|
|
Unified token response for both registration and login
|
|
Follows industry standards (Firebase, AWS Cognito, etc.)
|
|
"""
|
|
access_token: str
|
|
refresh_token: Optional[str] = None
|
|
token_type: str = "bearer"
|
|
expires_in: int = 3600 # seconds
|
|
user: Optional[UserData] = None
|
|
|
|
class Config:
|
|
schema_extra = {
|
|
"example": {
|
|
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
"refresh_token": "def502004b8b7f8f...",
|
|
"token_type": "bearer",
|
|
"expires_in": 3600,
|
|
"user": {
|
|
"id": "123e4567-e89b-12d3-a456-426614174000",
|
|
"email": "user@example.com",
|
|
"full_name": "John Doe",
|
|
"is_active": True,
|
|
"is_verified": False,
|
|
"created_at": "2025-07-22T10:00:00Z",
|
|
"role": "user"
|
|
}
|
|
}
|
|
}
|
|
|
|
class UserResponse(BaseModel):
|
|
"""User response for user management endpoints"""
|
|
id: str
|
|
email: str
|
|
full_name: str
|
|
is_active: bool
|
|
is_verified: bool
|
|
created_at: str
|
|
tenant_id: Optional[str] = None
|
|
role: Optional[str] = "user"
|
|
|
|
class TokenVerification(BaseModel):
|
|
"""Token verification response"""
|
|
valid: bool
|
|
user_id: Optional[str] = None
|
|
email: Optional[str] = None
|
|
exp: Optional[int] = None
|
|
message: Optional[str] = None
|
|
|
|
class PasswordResetResponse(BaseModel):
|
|
"""Password reset response"""
|
|
message: str
|
|
reset_token: Optional[str] = None
|
|
|
|
class LogoutResponse(BaseModel):
|
|
"""Logout response"""
|
|
message: str
|
|
success: bool = True
|
|
|
|
# ================================================================
|
|
# ERROR SCHEMAS
|
|
# ================================================================
|
|
|
|
class ErrorDetail(BaseModel):
|
|
"""Error detail for API responses"""
|
|
message: str
|
|
code: Optional[str] = None
|
|
field: Optional[str] = None
|
|
|
|
class ErrorResponse(BaseModel):
|
|
"""Standardized error response"""
|
|
success: bool = False
|
|
error: ErrorDetail
|
|
timestamp: str
|
|
|
|
class Config:
|
|
schema_extra = {
|
|
"example": {
|
|
"success": False,
|
|
"error": {
|
|
"message": "Invalid credentials",
|
|
"code": "AUTH_001"
|
|
},
|
|
"timestamp": "2025-07-22T10:00:00Z"
|
|
}
|
|
}
|
|
|
|
# ================================================================
|
|
# VALIDATION SCHEMAS
|
|
# ================================================================
|
|
|
|
class EmailVerificationRequest(BaseModel):
|
|
"""Email verification request"""
|
|
email: EmailStr
|
|
|
|
class EmailVerificationConfirm(BaseModel):
|
|
"""Email verification confirmation"""
|
|
token: str
|
|
|
|
class ProfileUpdate(BaseModel):
|
|
"""Profile update request"""
|
|
full_name: Optional[str] = Field(None, min_length=1, max_length=255)
|
|
email: Optional[EmailStr] = None
|
|
|
|
# ================================================================
|
|
# INTERNAL SCHEMAS (for service communication)
|
|
# ================================================================
|
|
|
|
class UserContext(BaseModel):
|
|
"""User context for internal service communication"""
|
|
user_id: str
|
|
email: str
|
|
tenant_id: Optional[str] = None
|
|
roles: list[str] = ["user"]
|
|
is_verified: bool = False
|
|
|
|
class TokenClaims(BaseModel):
|
|
"""JWT token claims structure"""
|
|
sub: str # subject (user_id)
|
|
email: str
|
|
full_name: str
|
|
user_id: str
|
|
is_verified: bool
|
|
tenant_id: Optional[str] = None
|
|
iat: int # issued at
|
|
exp: int # expires at
|
|
iss: str = "bakery-auth" # issuer |