feat: add admin media upgrade decisions

This commit is contained in:
ik
2026-09-16 20:28:45 +07:00
parent 53e7b0e4ae
commit 85d81aa996
5 changed files with 75 additions and 4 deletions
+2
View File
@@ -81,9 +81,11 @@ def review_assets(entity_type: str | None = None, status: str | None = None) ->
"height": item.get("height"),
"content_type": item.get("content_type"),
"image_url": f"/api/v1/admin/media/assets/{digest}",
"asset_url": item.get("asset_url", ""),
"source_system": source,
"source_url": source_page,
"duplicate_of": item.get("duplicate_of"),
"supersedes": item.get("supersedes"),
"derivatives": [{
"role": variant.get("role"), "format": variant.get("format"),
"width": variant.get("width"), "height": variant.get("height"),
+30 -2
View File
@@ -15,10 +15,12 @@ from ..community_review import ExternalReviewError, map_observation, publish_obs
from ..config import settings
from ..dependencies import Db
from ..importer import ImportAlreadyRunning, ImportSourceError, import_records
from ..media_catalog import review_assets, review_file
from rf4_research.media_assets import publish_quality_upgrades, rollback_quality_upgrade
from ..media_catalog import MEDIA_ROOT, review_assets, review_file
from ..models import CatchReport, CommunityImportRun, DataSource, ExternalObservation, Fish, ModerationEvent, ModerationStatus, OfficialRecordImport, SourceType, Waterbody
from ..public_cache import public_cache
from ..schemas import AdminCatchReportOut, AdminMediaReviewOut, AdminModerationHistoryOut, AdminSourceStatusOut, CatchReportCreated, ExternalAliasSuggestionOut, ExternalObservationAction, ExternalObservationDecision, ExternalObservationMapping, ExternalObservationOut, ExternalObservationPublished, ImportRunOut, ModerationUpdate
from ..schemas import AdminCatchReportOut, AdminMediaDecision, AdminMediaReviewOut, AdminMediaRollback, AdminModerationHistoryOut, AdminSourceStatusOut, CatchReportCreated, ExternalAliasSuggestionOut, ExternalObservationAction, ExternalObservationDecision, ExternalObservationMapping, ExternalObservationOut, ExternalObservationPublished, ImportRunOut, ModerationUpdate
from ..storage import delete_screenshot, signed_screenshot_url
from ..time_utils import aware
@@ -50,6 +52,32 @@ def admin_media_asset(digest: str, _: Annotated[str, Depends(_admin)]) -> FileRe
return FileResponse(path, media_type=media_type, headers={"Cache-Control": "private, no-store"})
@router.post("/api/v1/admin/media/upgrades/publish")
def admin_publish_media_upgrades(
payload: AdminMediaDecision,
_: Annotated[str, Depends(_admin)],
) -> dict[str, int]:
"""Atomically publish all stored quality upgrades after an explicit decision."""
try:
return publish_quality_upgrades(MEDIA_ROOT / "manifest.json", note=payload.note)
except ValueError as exc:
raise HTTPException(status_code=409, detail=str(exc)) from exc
@router.post("/api/v1/admin/media/upgrades/rollback")
def admin_rollback_media_upgrade(
payload: AdminMediaRollback,
_: Annotated[str, Depends(_admin)],
) -> dict[str, str]:
"""Restore one superseded fallback while retaining the reviewed candidate."""
try:
return rollback_quality_upgrade(
MEDIA_ROOT / "manifest.json", asset_url=payload.asset_url, note=payload.note,
)
except ValueError as exc:
raise HTTPException(status_code=409, detail=str(exc)) from exc
@router.get("/api/v1/admin/diagnostics")
def admin_diagnostics(db: Db, _: Annotated[str, Depends(_admin)]) -> JSONResponse:
report_counts = {status.value: count for status, count in db.execute(
+10
View File
@@ -318,7 +318,17 @@ class AdminMediaReviewOut(BaseModel):
height: int | None
content_type: str | None
image_url: str
asset_url: str
source_system: str
source_url: str
duplicate_of: str | None
supersedes: str | None
derivatives: list[AdminMediaDerivativeOut]
class AdminMediaDecision(BaseModel):
note: str = Field(min_length=1, max_length=1000)
class AdminMediaRollback(AdminMediaDecision):
asset_url: str = Field(min_length=1, max_length=2000)