Task 004: add demo auth and role checks
This commit is contained in:
@@ -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)
|
||||
Reference in New Issue
Block a user