Add the experience service with sites through analytics/AI hooks, migrations through 0011, and phase docs/manifests marking the track complete. Co-authored-by: Cursor <cursoragent@cursor.com>
62 lines
2.2 KiB
Python
62 lines
2.2 KiB
Python
"""Localization & media-ref domain policies — Phase 11.5."""
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from app.models.types import LocalizationStatus, MediaRefStatus
|
|
from app.validators.localization import (
|
|
ensure_localization_status_transition,
|
|
ensure_media_ref_status_transition,
|
|
ensure_no_binary_media_payload,
|
|
validate_storage_file_ref,
|
|
)
|
|
from shared.exceptions import AppError
|
|
|
|
|
|
class SiteLocaleBindingPolicy:
|
|
def assert_profile_usable(self, profile: Any) -> None:
|
|
if profile is None:
|
|
raise AppError(
|
|
"پروفایل locale یافت نشد",
|
|
error_code="locale_profile_not_found",
|
|
status_code=404,
|
|
)
|
|
if getattr(profile, "is_deleted", False):
|
|
raise AppError(
|
|
"پروفایل locale حذفشده قابل اتصال نیست",
|
|
error_code="locale_profile_deleted",
|
|
status_code=409,
|
|
)
|
|
status = getattr(profile, "status", None)
|
|
status_value = getattr(status, "value", status)
|
|
if status_value in {"archived", "suspended", "inactive"}:
|
|
raise AppError(
|
|
"پروفایل locale غیرفعال قابل اتصال نیست",
|
|
error_code="locale_profile_inactive",
|
|
status_code=409,
|
|
details={"status": status_value},
|
|
)
|
|
|
|
|
|
class LocalizationPolicy:
|
|
def assert_status_change(
|
|
self, *, current: LocalizationStatus, target: LocalizationStatus
|
|
) -> LocalizationStatus:
|
|
ensure_localization_status_transition(current, target)
|
|
return target
|
|
|
|
|
|
class MediaRefPolicy:
|
|
def assert_storage_ref_only(
|
|
self, *, storage_file_ref: str, metadata_json: dict | None = None
|
|
) -> str:
|
|
cleaned = validate_storage_file_ref(storage_file_ref)
|
|
ensure_no_binary_media_payload(metadata_json)
|
|
return cleaned
|
|
|
|
def assert_status_change(
|
|
self, *, current: MediaRefStatus, target: MediaRefStatus
|
|
) -> MediaRefStatus:
|
|
ensure_media_ref_status_transition(current, target)
|
|
return target
|