Task 004: add demo auth and role checks

This commit is contained in:
2026-05-21 18:31:40 +03:00
parent 7a11d50aa7
commit 7972e9a95f
26 changed files with 2207 additions and 23 deletions
+173
View File
@@ -0,0 +1,173 @@
from __future__ import annotations
from datetime import UTC, datetime
from hashlib import sha256
from uuid import NAMESPACE_URL, UUID, uuid5
from src.domain.contracts import (
CurrentUser,
ScriptConfigVersionCreateRequest,
ScriptConfigVersionResponse,
ScriptConfigVersionStatus,
ScriptConfigVersionSummary,
TargetSiteConfigCreateRequest,
TargetSiteConfigResponse,
TargetSiteConfigUpdateRequest,
)
def create_target_site(
repository: object,
request: TargetSiteConfigCreateRequest,
) -> TargetSiteConfigResponse:
now = _now()
site = repository.target_sites.upsert(
site_id=_stable_uuid(f"target-site:{request.slug}"),
name=request.name,
slug=request.slug,
publishing_type=request.publishing_type,
default_language=request.default_language,
brand_voice=request.brand_voice,
audience=request.audience,
seo_rules=request.seo_rules,
visual_rules=request.visual_rules,
source_rules=request.source_rules,
publishing_rules=request.publishing_rules,
active_script_config_version_id=request.active_script_config_version_id,
created_at=now,
updated_at=now,
)
return TargetSiteConfigResponse(site=site)
def update_target_site(
repository: object,
site_id: UUID,
request: TargetSiteConfigUpdateRequest,
) -> TargetSiteConfigResponse:
existing = repository.target_sites.get_by_id(site_id)
changes = request.model_dump(exclude_unset=True)
publishing_rules = (
request.publishing_rules
if "publishing_rules" in changes
else existing.publishing_rules
)
now = _now()
site = repository.target_sites.update(
site_id=existing.id,
name=changes.get("name", existing.name),
slug=changes.get("slug", existing.slug),
publishing_type=changes.get("publishing_type", existing.publishing_type),
default_language=changes.get("default_language", existing.default_language),
brand_voice=changes.get("brand_voice", existing.brand_voice),
audience=changes.get("audience", existing.audience),
seo_rules=changes.get("seo_rules", existing.seo_rules),
visual_rules=changes.get("visual_rules", existing.visual_rules),
source_rules=changes.get("source_rules", existing.source_rules),
publishing_rules=publishing_rules,
active_script_config_version_id=changes.get(
"active_script_config_version_id",
existing.active_script_config_version_id,
),
updated_at=now,
)
return TargetSiteConfigResponse(site=site)
def create_script_config_version(
repository: object,
*,
site_id: UUID,
current_user: CurrentUser,
request: ScriptConfigVersionCreateRequest,
) -> ScriptConfigVersionResponse:
repository.target_sites.get_by_id(site_id)
existing_versions = repository.script_config_versions.list_for_site(site_id)
version = request.version or _next_version(existing_versions)
now = _now()
version_id = _stable_uuid(f"script-config-version:{site_id}:{version}")
status = (
ScriptConfigVersionStatus.ACTIVE
if request.activate
else ScriptConfigVersionStatus.DRAFT
)
row = repository.script_config_versions.upsert(
version_id=version_id,
target_site_id=site_id,
version=version,
status=status,
created_by=current_user.id,
created_at=now,
updated_at=now,
diff=request.diff,
rollback_target_version_id=request.rollback_target_version_id,
activated_at=now if request.activate else None,
publishing_yaml=request.publishing_yaml,
publishing_yaml_hash=_sha256(request.publishing_yaml),
transform_script=request.transform_script,
transform_script_hash=_sha256(request.transform_script),
)
if request.activate:
row = repository.script_config_versions.activate(
target_site_id=site_id,
version_id=version_id,
activated_at=now,
)
return ScriptConfigVersionResponse(version=_script_version_summary(row))
def activate_script_config_version(
repository: object,
*,
site_id: UUID,
version_id: UUID,
) -> ScriptConfigVersionResponse:
repository.target_sites.get_by_id(site_id)
row = repository.script_config_versions.activate(
target_site_id=site_id,
version_id=version_id,
activated_at=_now(),
)
return ScriptConfigVersionResponse(version=_script_version_summary(row))
def list_script_config_versions(
repository: object,
site_id: UUID,
) -> list[ScriptConfigVersionSummary]:
repository.target_sites.get_by_id(site_id)
rows = repository.script_config_versions.list_for_site(site_id)
return [_script_version_summary(row) for row in rows]
def _script_version_summary(row: dict[str, object]) -> ScriptConfigVersionSummary:
return ScriptConfigVersionSummary(
id=row["id"],
target_site_id=row["target_site_id"],
version=row["version"],
status=row["status"],
publishing_yaml_hash=row["publishing_yaml_hash"],
transform_script_hash=row["transform_script_hash"],
created_by=row["created_by"],
created_at=row["created_at"],
)
def _next_version(rows: list[dict[str, object]]) -> int:
versions = [int(row["version"]) for row in rows]
if not versions:
return 1
return max(versions) + 1
def _stable_uuid(value: str) -> UUID:
return uuid5(NAMESPACE_URL, f"ai-content-pipeline:{value}")
def _sha256(value: str) -> str:
return sha256(value.encode("utf-8")).hexdigest()
def _now() -> datetime:
return datetime.now(UTC)