Coverage for api/auth/schema.py: 100.00%
48 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-09-03 15:30 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-09-03 15:30 +0000
1from datetime import datetime
2from typing import TypedDict
4from pydantic import BaseModel, EmailStr, Field
6from core.config import settings
9class UserResponse(BaseModel):
10 id: str = Field(..., description="User ID")
11 first_name: str = Field(..., description="First name")
12 last_name: str = Field(..., description="Last name")
13 email: str = Field(..., description="User email address")
14 phone: str = Field(..., description="Phone number")
17class LoginResult(TypedDict):
18 user: UserResponse
19 session_id: str
20 access_token: str
21 csrf_token: str
24class SessionResult(TypedDict):
25 session_id: str
26 access_token: str
27 csrf_token: str
30class UserRegister(BaseModel):
31 first_name: str = Field(..., min_length=1, max_length=50, description="First name")
32 last_name: str = Field(..., min_length=1, max_length=50, description="Last name")
33 email: EmailStr = Field(..., description="User email address")
34 phone: str = Field(..., min_length=1, max_length=20, description="Phone number")
35 password: str = Field(
36 ..., min_length=settings.PASSWORD_MIN_LENGTH, max_length=50, description="Password"
37 )
40class UserLogin(BaseModel):
41 email: EmailStr = Field(..., description="User email address")
42 password: str = Field(..., min_length=1, description="Password")
45class UserLoginResponse(BaseModel):
46 access_token: str = Field(..., description="JWT access token")
47 expires_at: datetime = Field(..., description="Token expiration time")
48 user: UserResponse = Field(..., description="User information")
51class TokenResponse(BaseModel):
52 access_token: str = Field(..., description="JWT access token")
53 expires_at: datetime = Field(..., description="Token expiration time")
56class CsrfTokenResponse(BaseModel):
57 csrf_token: str = Field(..., description="CSRF token")
58 expires_at: datetime = Field(..., description="CSRF token expiration time")
61class ActionRequiredResponse(BaseModel):
62 action_type: str = Field(
63 ...,
64 description="Action type for frontend routing: 'password_reset' or 'email_verification'",
65 )
66 token: str | None = Field(default=None, description="Token for the password reset")
67 expires_at: str | None = Field(default=None, description="Token expiration time (ISO format)")
70class LogoutRequest(BaseModel):
71 logout_all: bool = Field(False, description="Whether to logout from all devices")
74class ResetPasswordRequest(BaseModel):
75 new_password: str = Field(
76 ..., min_length=settings.PASSWORD_MIN_LENGTH, max_length=50, description="New password"
77 )
80class TokenValidationResponse(BaseModel):
81 is_valid: bool = Field(..., description="Whether the token is valid")
84class ForgotPasswordRequest(BaseModel):
85 email: EmailStr = Field(..., description="User email address")
88class PasswordResetCooldownResponse(BaseModel):
89 cooldown_seconds: int = Field(..., description="Remaining cooldown time in seconds")
92class ResendVerificationRequest(BaseModel):
93 email: EmailStr = Field(..., description="Email address to resend verification")
96action_required_response_examples = {
97 "passwordReset": {
98 "summary": "Password reset required",
99 "value": {
100 "code": 202,
101 "message": "Password reset required",
102 "data": {
103 "action_type": "password_reset",
104 "token": "password_reset_token",
105 "expires_at": "2024-01-01T12:00:00+00:00",
106 },
107 },
108 },
109 "emailVerification": {
110 "summary": "Email verification required",
111 "value": {
112 "code": 202,
113 "message": "Email verification required",
114 "data": {
115 "action_type": "email_verification",
116 "token": None,
117 "expires_at": "2024-01-01T12:00:00+00:00",
118 },
119 },
120 },
121}