feat: add bulk moderation decisions
This commit is contained in:
@@ -20,7 +20,7 @@ from rf4_research.media_assets import publish_quality_upgrades, rollback_quality
|
||||
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, AdminMediaDecision, AdminMediaReviewOut, AdminMediaRollback, 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, ModerationBulkResult, ModerationBulkUpdate, ModerationUpdate
|
||||
from ..storage import delete_screenshot, signed_screenshot_url
|
||||
from ..time_utils import aware
|
||||
|
||||
@@ -400,6 +400,27 @@ def moderate_report(report_id: UUID, payload: ModerationUpdate, db: Db, moderato
|
||||
return CatchReportCreated(id=report.id, moderation_status=report.moderation_status.value)
|
||||
|
||||
|
||||
@router.post("/api/v1/admin/catch-reports/bulk", response_model=ModerationBulkResult)
|
||||
def moderate_reports_bulk(payload: ModerationBulkUpdate, db: Db, moderator: Annotated[str, Depends(_admin)]) -> ModerationBulkResult:
|
||||
if payload.status == "rejected" and not (payload.reason or "").strip():
|
||||
raise HTTPException(status_code=422, detail="rejection reason required")
|
||||
ids = [item.id for item in payload.items]
|
||||
reports = list(db.scalars(select(CatchReport).where(CatchReport.id.in_(ids)).with_for_update()))
|
||||
by_id = {report.id: report for report in reports}
|
||||
if len(by_id) != len(ids) or any(report.source_type != SourceType.user or report.deleted_at is not None or report.moderation_status != ModerationStatus.pending for report in reports):
|
||||
raise HTTPException(status_code=409, detail="one or more reports are no longer pending")
|
||||
expected = {item.id: item.expected_version for item in payload.items}
|
||||
if any(report.moderation_version != expected[report.id] for report in reports):
|
||||
raise HTTPException(status_code=409, detail="one or more reports changed; reload the queue")
|
||||
for report in reports:
|
||||
previous = report.moderation_status
|
||||
report.moderation_status = ModerationStatus(payload.status)
|
||||
report.moderation_version += 1
|
||||
db.add(ModerationEvent(catch_report=report, created_at=datetime.now(timezone.utc), previous_status=previous, new_status=report.moderation_status, moderator=moderator, reason=payload.reason))
|
||||
db.commit(); public_cache.invalidate()
|
||||
return ModerationBulkResult(updated=len(reports))
|
||||
|
||||
|
||||
@router.delete("/api/v1/admin/catch-reports/{report_id}", status_code=204, response_class=Response)
|
||||
def delete_report(report_id: UUID, db: Db, moderator: Annotated[str, Depends(_admin)], expected_version: int = Query(ge=0)) -> Response:
|
||||
report = db.scalar(select(CatchReport).where(CatchReport.id == report_id).with_for_update())
|
||||
|
||||
Reference in New Issue
Block a user