updates
This commit is contained in:
@@ -1,68 +1,32 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class CookiePolicySettings(BaseModel):
|
||||
"""
|
||||
Admin-configurable global cookie policy.
|
||||
Controls which categories can be used in the application.
|
||||
"""
|
||||
|
||||
analytics_enabled: bool = Field(
|
||||
default=True,
|
||||
description="If false, analytics cookies/scripts should not be used at all.",
|
||||
)
|
||||
marketing_enabled: bool = Field(
|
||||
default=True,
|
||||
description="If false, marketing cookies/scripts should not be used at all.",
|
||||
)
|
||||
preferences_enabled: bool = Field(
|
||||
default=True,
|
||||
description="If false, preference cookies should not be used at all.",
|
||||
)
|
||||
|
||||
analytics_enabled: bool = Field(default=True, description='If false, analytics cookies/scripts should not be used at all.')
|
||||
marketing_enabled: bool = Field(default=True, description='If false, marketing cookies/scripts should not be used at all.')
|
||||
preferences_enabled: bool = Field(default=True, description='If false, preference cookies should not be used at all.')
|
||||
|
||||
class CookiePolicySettingsResponse(BaseModel):
|
||||
status: str = Field(default="success")
|
||||
status: str = Field(default='success')
|
||||
data: CookiePolicySettings
|
||||
updated_at: Optional[datetime] = None
|
||||
updated_by: Optional[str] = None
|
||||
|
||||
|
||||
class CookieIntegrationSettings(BaseModel):
|
||||
"""
|
||||
IDs for well-known third-party integrations, configured by admin.
|
||||
"""
|
||||
|
||||
ga_measurement_id: Optional[str] = Field(
|
||||
default=None, description="Google Analytics 4 measurement ID (e.g. G-XXXXXXX)."
|
||||
)
|
||||
fb_pixel_id: Optional[str] = Field(
|
||||
default=None, description="Meta (Facebook) Pixel ID."
|
||||
)
|
||||
|
||||
ga_measurement_id: Optional[str] = Field(default=None, description='Google Analytics 4 measurement ID (e.g. G-XXXXXXX).')
|
||||
fb_pixel_id: Optional[str] = Field(default=None, description='Meta (Facebook) Pixel ID.')
|
||||
|
||||
class CookieIntegrationSettingsResponse(BaseModel):
|
||||
status: str = Field(default="success")
|
||||
status: str = Field(default='success')
|
||||
data: CookieIntegrationSettings
|
||||
updated_at: Optional[datetime] = None
|
||||
updated_by: Optional[str] = None
|
||||
|
||||
|
||||
class PublicPrivacyConfig(BaseModel):
|
||||
"""
|
||||
Publicly consumable privacy configuration for the frontend.
|
||||
Does not expose any secrets, only IDs and flags.
|
||||
"""
|
||||
|
||||
policy: CookiePolicySettings
|
||||
integrations: CookieIntegrationSettings
|
||||
|
||||
|
||||
class PublicPrivacyConfigResponse(BaseModel):
|
||||
status: str = Field(default="success")
|
||||
data: PublicPrivacyConfig
|
||||
|
||||
|
||||
status: str = Field(default='success')
|
||||
data: PublicPrivacyConfig
|
||||
@@ -1,64 +1,58 @@
|
||||
from pydantic import BaseModel, EmailStr, Field, validator
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class RegisterRequest(BaseModel):
|
||||
name: str = Field(..., min_length=2, max_length=50)
|
||||
email: EmailStr
|
||||
password: str = Field(..., min_length=8)
|
||||
phone: Optional[str] = None
|
||||
|
||||
@validator("password")
|
||||
@validator('password')
|
||||
def validate_password(cls, v):
|
||||
if len(v) < 8:
|
||||
raise ValueError("Password must be at least 8 characters")
|
||||
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 number")
|
||||
raise ValueError('Password must be at least 8 characters')
|
||||
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 number')
|
||||
return v
|
||||
|
||||
@validator("phone")
|
||||
@validator('phone')
|
||||
def validate_phone(cls, v):
|
||||
if v and not v.isdigit() or (v and len(v) not in [10, 11]):
|
||||
raise ValueError("Phone must be 10-11 digits")
|
||||
if v and (not v.isdigit()) or (v and len(v) not in [10, 11]):
|
||||
raise ValueError('Phone must be 10-11 digits')
|
||||
return v
|
||||
|
||||
|
||||
class LoginRequest(BaseModel):
|
||||
email: EmailStr
|
||||
password: str
|
||||
rememberMe: Optional[bool] = False
|
||||
mfaToken: Optional[str] = None
|
||||
|
||||
|
||||
class RefreshTokenRequest(BaseModel):
|
||||
refreshToken: Optional[str] = None
|
||||
|
||||
|
||||
class ForgotPasswordRequest(BaseModel):
|
||||
email: EmailStr
|
||||
|
||||
|
||||
class ResetPasswordRequest(BaseModel):
|
||||
token: str
|
||||
password: str = Field(..., min_length=8)
|
||||
|
||||
@validator("password")
|
||||
@validator('password')
|
||||
def validate_password(cls, v):
|
||||
if len(v) < 8:
|
||||
raise ValueError("Password must be at least 8 characters")
|
||||
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 number")
|
||||
raise ValueError('Password must be at least 8 characters')
|
||||
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 number')
|
||||
return v
|
||||
|
||||
|
||||
class UserResponse(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
@@ -71,38 +65,30 @@ class UserResponse(BaseModel):
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class AuthResponse(BaseModel):
|
||||
user: UserResponse
|
||||
token: str
|
||||
refreshToken: Optional[str] = None
|
||||
|
||||
|
||||
class TokenResponse(BaseModel):
|
||||
token: str
|
||||
|
||||
|
||||
class MessageResponse(BaseModel):
|
||||
status: str
|
||||
message: str
|
||||
|
||||
|
||||
class MFAInitResponse(BaseModel):
|
||||
secret: str
|
||||
qr_code: str # Base64 data URL
|
||||
|
||||
qr_code: str
|
||||
|
||||
class EnableMFARequest(BaseModel):
|
||||
secret: str
|
||||
verification_token: str
|
||||
|
||||
|
||||
class VerifyMFARequest(BaseModel):
|
||||
token: str
|
||||
is_backup_code: Optional[bool] = False
|
||||
|
||||
|
||||
class MFAStatusResponse(BaseModel):
|
||||
mfa_enabled: bool
|
||||
backup_codes_count: int
|
||||
|
||||
backup_codes_count: int
|
||||
@@ -1,70 +1,24 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class CookieCategoryPreferences(BaseModel):
|
||||
"""
|
||||
Granular consent for different cookie categories.
|
||||
|
||||
- necessary: required for the site to function (always true, not revocable)
|
||||
- analytics: usage analytics, performance tracking
|
||||
- marketing: advertising, remarketing cookies
|
||||
- preferences: UI / language / personalization preferences
|
||||
"""
|
||||
|
||||
necessary: bool = Field(
|
||||
default=True,
|
||||
description="Strictly necessary cookies (always enabled as they are required for core functionality).",
|
||||
)
|
||||
analytics: bool = Field(
|
||||
default=False, description="Allow anonymous analytics and performance cookies."
|
||||
)
|
||||
marketing: bool = Field(
|
||||
default=False, description="Allow marketing and advertising cookies."
|
||||
)
|
||||
preferences: bool = Field(
|
||||
default=False,
|
||||
description="Allow preference cookies (e.g. language, layout settings).",
|
||||
)
|
||||
|
||||
necessary: bool = Field(default=True, description='Strictly necessary cookies (always enabled as they are required for core functionality).')
|
||||
analytics: bool = Field(default=False, description='Allow anonymous analytics and performance cookies.')
|
||||
marketing: bool = Field(default=False, description='Allow marketing and advertising cookies.')
|
||||
preferences: bool = Field(default=False, description='Allow preference cookies (e.g. language, layout settings).')
|
||||
|
||||
class CookieConsent(BaseModel):
|
||||
"""
|
||||
Persisted cookie consent state.
|
||||
Stored in an HttpOnly cookie and exposed via the API.
|
||||
"""
|
||||
|
||||
version: int = Field(
|
||||
default=1, description="Consent schema version for future migrations."
|
||||
)
|
||||
updated_at: datetime = Field(
|
||||
default_factory=datetime.utcnow, description="Last time consent was updated."
|
||||
)
|
||||
has_decided: bool = Field(
|
||||
default=False,
|
||||
description="Whether the user has actively made a consent choice.",
|
||||
)
|
||||
categories: CookieCategoryPreferences = Field(
|
||||
default_factory=CookieCategoryPreferences,
|
||||
description="Granular per-category consent.",
|
||||
)
|
||||
|
||||
version: int = Field(default=1, description='Consent schema version for future migrations.')
|
||||
updated_at: datetime = Field(default_factory=datetime.utcnow, description='Last time consent was updated.')
|
||||
has_decided: bool = Field(default=False, description='Whether the user has actively made a consent choice.')
|
||||
categories: CookieCategoryPreferences = Field(default_factory=CookieCategoryPreferences, description='Granular per-category consent.')
|
||||
|
||||
class CookieConsentResponse(BaseModel):
|
||||
status: str = Field(default="success")
|
||||
status: str = Field(default='success')
|
||||
data: CookieConsent
|
||||
|
||||
|
||||
class UpdateCookieConsentRequest(BaseModel):
|
||||
"""
|
||||
Request body for updating cookie consent.
|
||||
'necessary' is ignored on write and always treated as True by the server.
|
||||
"""
|
||||
|
||||
analytics: Optional[bool] = None
|
||||
marketing: Optional[bool] = None
|
||||
preferences: Optional[bool] = None
|
||||
|
||||
|
||||
preferences: Optional[bool] = None
|
||||
Reference in New Issue
Block a user