fix: type admin API contracts
This commit is contained in:
@@ -18,7 +18,7 @@ from ..importer import ImportAlreadyRunning, ImportSourceError, import_records
|
||||
from ..media_catalog import 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, AdminModerationHistoryOut, CatchReportCreated, ExternalAliasSuggestionOut, ExternalObservationAction, ExternalObservationDecision, ExternalObservationMapping, ExternalObservationOut, ExternalObservationPublished, ImportRunOut, ModerationUpdate
|
||||
from ..schemas import AdminCatchReportOut, AdminMediaReviewOut, AdminModerationHistoryOut, AdminSourceStatusOut, CatchReportCreated, ExternalAliasSuggestionOut, ExternalObservationAction, ExternalObservationDecision, ExternalObservationMapping, ExternalObservationOut, ExternalObservationPublished, ImportRunOut, ModerationUpdate
|
||||
from ..storage import delete_screenshot, signed_screenshot_url
|
||||
from ..time_utils import aware
|
||||
|
||||
@@ -30,14 +30,14 @@ def _admin(request: Request, db: Db, authorization: Annotated[str | None, Header
|
||||
return verify_admin(request, db, authorization, settings)
|
||||
|
||||
|
||||
@router.get("/api/v1/admin/media/catalog")
|
||||
@router.get("/api/v1/admin/media/catalog", response_model=list[AdminMediaReviewOut])
|
||||
def admin_media_catalog(
|
||||
_: Annotated[str, Depends(_admin)],
|
||||
entity_type: str | None = Query(None, pattern="^(fish|waterbody|tackle|reference)$"),
|
||||
status: str | None = Query(None, pattern="^(approved|upgrade_queued|upgrade_stored)$"),
|
||||
limit: int = Query(50, ge=1, le=100),
|
||||
offset: int = Query(0, ge=0),
|
||||
) -> list[dict]:
|
||||
) -> list[AdminMediaReviewOut]:
|
||||
return review_assets(entity_type, status)[offset:offset + limit]
|
||||
|
||||
|
||||
@@ -152,11 +152,11 @@ def admin_start_official_import(db: Db, _: Annotated[str, Depends(_admin)]) -> O
|
||||
raise HTTPException(status_code=502, detail=f"official records import failed: {exc}") from exc
|
||||
|
||||
|
||||
@router.get("/api/v1/admin/source-status")
|
||||
def admin_source_status(db: Db, _: Annotated[str, Depends(_admin)]) -> list[dict[str, object]]:
|
||||
@router.get("/api/v1/admin/source-status", response_model=list[AdminSourceStatusOut])
|
||||
def admin_source_status(db: Db, _: Annotated[str, Depends(_admin)]) -> list[AdminSourceStatusOut]:
|
||||
"""Return safe operational details needed by the owner dashboard."""
|
||||
now = datetime.now(timezone.utc)
|
||||
result: list[dict[str, object]] = []
|
||||
result: list[AdminSourceStatusOut] = []
|
||||
for source in db.scalars(select(DataSource).order_by(DataSource.name)):
|
||||
runs = list(db.scalars(
|
||||
select(CommunityImportRun)
|
||||
@@ -184,17 +184,17 @@ def admin_source_status(db: Db, _: Annotated[str, Depends(_admin)]) -> list[dict
|
||||
state = "stale"
|
||||
else:
|
||||
state = "healthy"
|
||||
result.append({
|
||||
"source_system": source.key,
|
||||
"name": source.name,
|
||||
"status": state,
|
||||
"last_started_at": latest.started_at if latest else None,
|
||||
"last_success_at": success.started_at if success else None,
|
||||
"next_allowed_at": next_allowed,
|
||||
"cooldown_seconds": cooldown_seconds,
|
||||
"recent_failures_24h": recent_failures,
|
||||
"backoff_recommended": recent_failures >= 5,
|
||||
})
|
||||
result.append(AdminSourceStatusOut(
|
||||
source_system=source.key,
|
||||
name=source.name,
|
||||
status=state,
|
||||
last_started_at=latest.started_at if latest else None,
|
||||
last_success_at=success.started_at if success else None,
|
||||
next_allowed_at=next_allowed,
|
||||
cooldown_seconds=cooldown_seconds,
|
||||
recent_failures_24h=recent_failures,
|
||||
backoff_recommended=recent_failures >= 5,
|
||||
))
|
||||
return result
|
||||
|
||||
|
||||
|
||||
@@ -287,3 +287,38 @@ class SourceStatusOut(BaseModel):
|
||||
last_started_at: datetime | None
|
||||
last_success_at: datetime | None
|
||||
observations: int
|
||||
|
||||
|
||||
class AdminSourceStatusOut(BaseModel):
|
||||
source_system: str
|
||||
name: str
|
||||
status: str
|
||||
last_started_at: datetime | None
|
||||
last_success_at: datetime | None
|
||||
next_allowed_at: datetime | None
|
||||
cooldown_seconds: int
|
||||
recent_failures_24h: int
|
||||
backoff_recommended: bool
|
||||
|
||||
|
||||
class AdminMediaDerivativeOut(BaseModel):
|
||||
role: str | None
|
||||
format: str | None
|
||||
width: int | None
|
||||
height: int | None
|
||||
|
||||
|
||||
class AdminMediaReviewOut(BaseModel):
|
||||
id: str
|
||||
status: str
|
||||
entity_type: str | None
|
||||
entity_key: str | None
|
||||
label: str | None
|
||||
width: int | None
|
||||
height: int | None
|
||||
content_type: str | None
|
||||
image_url: str
|
||||
source_system: str
|
||||
source_url: str
|
||||
duplicate_of: str | None
|
||||
derivatives: list[AdminMediaDerivativeOut]
|
||||
|
||||
Reference in New Issue
Block a user