feat: continue roadmap acceptance work
This commit is contained in:
@@ -124,7 +124,7 @@ def _validate_waterbody_detail(detail: dict[str, Any]) -> dict[str, Any]:
|
||||
external_id = _required(payload, "source_external_id", 200)
|
||||
source_url = _required(payload, "source_url", 2000)
|
||||
parsed_url = urlparse(source_url)
|
||||
if parsed_url.scheme != "https" or parsed_url.hostname not in {"rf4db.com", "www.rf4db.com"}:
|
||||
if parsed_url.scheme != "https" or parsed_url.hostname not in {"rf4db.com", "www.rf4db.com", "download.rf4db.com"}:
|
||||
raise CommunityImportError("waterbody detail source_url does not match rf4db")
|
||||
_required(payload, "name", 200)
|
||||
_optional(payload, "description", 20_000)
|
||||
|
||||
@@ -49,12 +49,26 @@ def published_file(digest: str) -> tuple[Path, str] | None:
|
||||
return None
|
||||
manifest = json.loads((MEDIA_ROOT / "manifest.json").read_text(encoding="utf-8"))
|
||||
item = next((row for row in manifest.get("assets", []) if row.get("status") == "approved" and row.get("sha256") == digest), None)
|
||||
if not item:
|
||||
media_type = None
|
||||
local_path = None
|
||||
if item:
|
||||
media_type = item.get("content_type")
|
||||
local_path = item.get("local_path")
|
||||
else:
|
||||
for row in manifest.get("assets", []):
|
||||
if row.get("status") != "approved":
|
||||
continue
|
||||
variant = next((candidate for candidate in row.get("derivatives", []) if candidate.get("sha256") == digest), None)
|
||||
if variant:
|
||||
media_type = variant.get("content_type")
|
||||
local_path = variant.get("local_path")
|
||||
break
|
||||
if not local_path:
|
||||
return None
|
||||
target = (MEDIA_ROOT / item["local_path"]).resolve()
|
||||
target = (MEDIA_ROOT / local_path).resolve()
|
||||
if not target.is_relative_to(MEDIA_ROOT.resolve()) or not target.is_file():
|
||||
return None
|
||||
return target, str(item["content_type"])
|
||||
return target, str(media_type or "application/octet-stream")
|
||||
|
||||
|
||||
def review_assets(entity_type: str | None = None, status: str | None = None) -> list[dict]:
|
||||
|
||||
@@ -217,6 +217,21 @@
|
||||
"title": "AdminCatchReportOut",
|
||||
"type": "object"
|
||||
},
|
||||
"AdminMediaDecision": {
|
||||
"properties": {
|
||||
"note": {
|
||||
"maxLength": 1000,
|
||||
"minLength": 1,
|
||||
"title": "Note",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"note"
|
||||
],
|
||||
"title": "AdminMediaDecision",
|
||||
"type": "object"
|
||||
},
|
||||
"AdminMediaDerivativeOut": {
|
||||
"properties": {
|
||||
"format": {
|
||||
@@ -275,6 +290,10 @@
|
||||
},
|
||||
"AdminMediaReviewOut": {
|
||||
"properties": {
|
||||
"asset_url": {
|
||||
"title": "Asset Url",
|
||||
"type": "string"
|
||||
},
|
||||
"content_type": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -368,6 +387,17 @@
|
||||
"title": "Status",
|
||||
"type": "string"
|
||||
},
|
||||
"supersedes": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Supersedes"
|
||||
},
|
||||
"width": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -390,14 +420,38 @@
|
||||
"height",
|
||||
"content_type",
|
||||
"image_url",
|
||||
"asset_url",
|
||||
"source_system",
|
||||
"source_url",
|
||||
"duplicate_of",
|
||||
"supersedes",
|
||||
"derivatives"
|
||||
],
|
||||
"title": "AdminMediaReviewOut",
|
||||
"type": "object"
|
||||
},
|
||||
"AdminMediaRollback": {
|
||||
"properties": {
|
||||
"asset_url": {
|
||||
"maxLength": 2000,
|
||||
"minLength": 1,
|
||||
"title": "Asset Url",
|
||||
"type": "string"
|
||||
},
|
||||
"note": {
|
||||
"maxLength": 1000,
|
||||
"minLength": 1,
|
||||
"title": "Note",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"note",
|
||||
"asset_url"
|
||||
],
|
||||
"title": "AdminMediaRollback",
|
||||
"type": "object"
|
||||
},
|
||||
"AdminModerationHistoryOut": {
|
||||
"properties": {
|
||||
"action": {
|
||||
@@ -3223,6 +3277,128 @@
|
||||
"summary": "Admin Media Catalog"
|
||||
}
|
||||
},
|
||||
"/api/v1/admin/media/upgrades/publish": {
|
||||
"post": {
|
||||
"description": "Atomically publish all stored quality upgrades after an explicit decision.",
|
||||
"operationId": "admin_publish_media_upgrades_api_v1_admin_media_upgrades_publish_post",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "header",
|
||||
"name": "authorization",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Authorization"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/AdminMediaDecision"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"additionalProperties": {
|
||||
"type": "integer"
|
||||
},
|
||||
"title": "Response Admin Publish Media Upgrades Api V1 Admin Media Upgrades Publish Post",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Successful Response"
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Validation Error"
|
||||
}
|
||||
},
|
||||
"summary": "Admin Publish Media Upgrades"
|
||||
}
|
||||
},
|
||||
"/api/v1/admin/media/upgrades/rollback": {
|
||||
"post": {
|
||||
"description": "Restore one superseded fallback while retaining the reviewed candidate.",
|
||||
"operationId": "admin_rollback_media_upgrade_api_v1_admin_media_upgrades_rollback_post",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "header",
|
||||
"name": "authorization",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Authorization"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/AdminMediaRollback"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": "Response Admin Rollback Media Upgrade Api V1 Admin Media Upgrades Rollback Post",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Successful Response"
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Validation Error"
|
||||
}
|
||||
},
|
||||
"summary": "Admin Rollback Media Upgrade"
|
||||
}
|
||||
},
|
||||
"/api/v1/admin/moderation-history": {
|
||||
"get": {
|
||||
"operationId": "admin_moderation_history_api_v1_admin_moderation_history_get",
|
||||
|
||||
@@ -82,6 +82,9 @@ def test_published_media_catalog_and_content_addressed_file() -> None:
|
||||
assert image.status_code == 200
|
||||
assert image.headers["content-type"].startswith("image/")
|
||||
assert image.headers["cache-control"] == "public, max-age=31536000, immutable"
|
||||
variant = client.get(item["variants"][0]["url"])
|
||||
assert variant.status_code == 200
|
||||
assert variant.headers["content-type"].startswith("image/")
|
||||
assert client.get("/api/v1/media/assets/not-a-hash").status_code == 404
|
||||
|
||||
|
||||
|
||||
@@ -124,6 +124,21 @@ def test_waterbody_detail_updates_only_imported_identity_without_media_roles(db:
|
||||
assert item.source_image_urls == ["https://oss.rf4db.com/map.webp"]
|
||||
|
||||
|
||||
def test_waterbody_detail_accepts_authorized_download_subdomain(db: Session) -> None:
|
||||
upsert_waterbody_catalog(db, [waterbody_row()])
|
||||
assert update_waterbody_detail(db, {
|
||||
"source_system": "rf4db",
|
||||
"source_external_id": "level_001_mosquito",
|
||||
"source_url": "https://download.rf4db.com/ru/maps/level_001_mosquito",
|
||||
"name": "оз. Комариное",
|
||||
"description": None,
|
||||
"aliases": [],
|
||||
"fish_species": ["Щука"],
|
||||
"image_urls": [],
|
||||
"point_urls": [],
|
||||
}) is True
|
||||
|
||||
|
||||
def test_waterbody_detail_batch_validates_before_writing(db: Session) -> None:
|
||||
upsert_waterbody_catalog(db, [waterbody_row()])
|
||||
valid = {
|
||||
|
||||
Reference in New Issue
Block a user