This commit is contained in:
Iliyan Angelov
2025-11-16 20:05:08 +02:00
parent 98ccd5b6ff
commit 48353cde9c
118 changed files with 9488 additions and 1336 deletions

View File

@@ -0,0 +1,68 @@
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.",
)
class CookiePolicySettingsResponse(BaseModel):
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."
)
class CookieIntegrationSettingsResponse(BaseModel):
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

View File

@@ -0,0 +1,70 @@
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).",
)
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.",
)
class CookieConsentResponse(BaseModel):
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