feat: harden shared platform contracts
This commit is contained in:
@@ -132,6 +132,24 @@ class ApiSmokeTests(unittest.TestCase):
|
||||
self.assertEqual(response.status_code, 201, response.text)
|
||||
return str(response.json()["id"])
|
||||
|
||||
def _campaign_version_precondition(
|
||||
self,
|
||||
headers: dict[str, str],
|
||||
campaign_id: str,
|
||||
version_id: str,
|
||||
) -> tuple[dict[str, str], int]:
|
||||
response = self.client.get(
|
||||
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}",
|
||||
headers=headers,
|
||||
)
|
||||
self.assertEqual(response.status_code, 200, response.text)
|
||||
etag = response.headers.get("etag")
|
||||
self.assertIsNotNone(etag)
|
||||
return (
|
||||
{**headers, "If-Match": str(etag)},
|
||||
int(response.json()["edit_revision"]),
|
||||
)
|
||||
|
||||
def test_recipient_import_mapping_profiles_are_db_backed(self) -> None:
|
||||
headers, _ = self._login()
|
||||
payload = {
|
||||
@@ -950,6 +968,33 @@ class ApiSmokeTests(unittest.TestCase):
|
||||
user_always = {item["id"]: item for item in user_docs_payload["layers"]["always"]["documentation"]}
|
||||
self.assertEqual(user_always["docs.configured-system-documentation"]["translation_locale"], "de")
|
||||
|
||||
sources = self.client.get("/api/v1/docs/sources", headers=headers)
|
||||
self.assertEqual(sources.status_code, 200, sources.text)
|
||||
source_payload = sources.json()
|
||||
self.assertEqual(source_payload["total"], len(source_payload["items"]))
|
||||
manifest_source = next(
|
||||
item
|
||||
for item in source_payload["items"]
|
||||
if item["id"] == "docs.manifest"
|
||||
)
|
||||
self.assertEqual(manifest_source["kind"], "manifest")
|
||||
self.assertNotIn("inspection", manifest_source)
|
||||
|
||||
inspected_source = self.client.get(
|
||||
manifest_source["inspection_url"],
|
||||
headers=headers,
|
||||
)
|
||||
self.assertEqual(inspected_source.status_code, 200, inspected_source.text)
|
||||
self.assertEqual(
|
||||
inspected_source.json()["inspection"]["module_id"],
|
||||
"docs",
|
||||
)
|
||||
unknown_source = self.client.get(
|
||||
"/api/v1/docs/sources/docs.unknown",
|
||||
headers=headers,
|
||||
)
|
||||
self.assertEqual(unknown_source.status_code, 404, unknown_source.text)
|
||||
|
||||
platform_status = self.client.get("/api/v1/platform/status", headers=headers)
|
||||
self.assertEqual(platform_status.status_code, 200, platform_status.text)
|
||||
i18n_status = platform_status.json()["i18n"]
|
||||
@@ -2747,7 +2792,10 @@ class ApiSmokeTests(unittest.TestCase):
|
||||
archive.writestr("reports/february.txt", "February report")
|
||||
payload.seek(0)
|
||||
|
||||
with patch("govoplan_files.backend.router._read_limited_upload", side_effect=AssertionError("ZIP upload should not be fully buffered")):
|
||||
with patch(
|
||||
"govoplan_files.backend.routes.uploads._read_limited_upload",
|
||||
side_effect=AssertionError("ZIP upload should not be fully buffered"),
|
||||
):
|
||||
response = self.client.post(
|
||||
"/api/v1/files/upload-zip",
|
||||
headers=headers,
|
||||
@@ -2890,10 +2938,18 @@ class ApiSmokeTests(unittest.TestCase):
|
||||
self.assertTrue(full_payload["full"])
|
||||
self.assertEqual(full_payload["current_version"]["id"], version_id)
|
||||
|
||||
mutation_headers, base_revision = self._campaign_version_precondition(
|
||||
headers,
|
||||
campaign_id,
|
||||
version_id,
|
||||
)
|
||||
autosaved = self.client.post(
|
||||
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}/autosave",
|
||||
headers=headers,
|
||||
json={"current_step": "fields"},
|
||||
headers=mutation_headers,
|
||||
json={
|
||||
"current_step": "fields",
|
||||
"base_revision": base_revision,
|
||||
},
|
||||
)
|
||||
self.assertEqual(autosaved.status_code, 200, autosaved.text)
|
||||
self.assertEqual(autosaved.json()["current_step"], "fields")
|
||||
@@ -3038,10 +3094,18 @@ class ApiSmokeTests(unittest.TestCase):
|
||||
self.assertEqual(temporary.json()["user_lock_state"], "temporary")
|
||||
self.assertTrue(temporary.json()["user_locked_at"])
|
||||
|
||||
mutation_headers, base_revision = self._campaign_version_precondition(
|
||||
headers,
|
||||
campaign_id,
|
||||
version_id,
|
||||
)
|
||||
blocked_update = self.client.put(
|
||||
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}",
|
||||
headers=headers,
|
||||
json={"current_step": "fields"},
|
||||
headers=mutation_headers,
|
||||
json={
|
||||
"current_step": "fields",
|
||||
"base_revision": base_revision,
|
||||
},
|
||||
)
|
||||
self.assertEqual(blocked_update.status_code, 409, blocked_update.text)
|
||||
|
||||
@@ -3052,10 +3116,18 @@ class ApiSmokeTests(unittest.TestCase):
|
||||
self.assertEqual(unlocked.status_code, 200, unlocked.text)
|
||||
self.assertIsNone(unlocked.json()["user_lock_state"])
|
||||
|
||||
mutation_headers, base_revision = self._campaign_version_precondition(
|
||||
headers,
|
||||
campaign_id,
|
||||
version_id,
|
||||
)
|
||||
updated = self.client.put(
|
||||
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}",
|
||||
headers=headers,
|
||||
json={"current_step": "fields"},
|
||||
headers=mutation_headers,
|
||||
json={
|
||||
"current_step": "fields",
|
||||
"base_revision": base_revision,
|
||||
},
|
||||
)
|
||||
self.assertEqual(updated.status_code, 200, updated.text)
|
||||
self.assertEqual(updated.json()["current_step"], "fields")
|
||||
@@ -3116,18 +3188,34 @@ class ApiSmokeTests(unittest.TestCase):
|
||||
self.assertNotEqual(second_version_id, first_version_id)
|
||||
self.assertEqual(copied.json()["campaign"]["current_version_id"], second_version_id)
|
||||
|
||||
mutation_headers, base_revision = self._campaign_version_precondition(
|
||||
headers,
|
||||
campaign_id,
|
||||
first_version_id,
|
||||
)
|
||||
historical_update = self.client.put(
|
||||
f"/api/v1/campaigns/{campaign_id}/versions/{first_version_id}",
|
||||
headers=headers,
|
||||
json={"current_step": "fields"},
|
||||
headers=mutation_headers,
|
||||
json={
|
||||
"current_step": "fields",
|
||||
"base_revision": base_revision,
|
||||
},
|
||||
)
|
||||
self.assertEqual(historical_update.status_code, 409, historical_update.text)
|
||||
self.assertIn("Historical campaign versions are read-only", historical_update.text)
|
||||
|
||||
mutation_headers, base_revision = self._campaign_version_precondition(
|
||||
headers,
|
||||
campaign_id,
|
||||
second_version_id,
|
||||
)
|
||||
second_update = self.client.put(
|
||||
f"/api/v1/campaigns/{campaign_id}/versions/{second_version_id}",
|
||||
headers=headers,
|
||||
json={"current_step": "fields"},
|
||||
headers=mutation_headers,
|
||||
json={
|
||||
"current_step": "fields",
|
||||
"base_revision": base_revision,
|
||||
},
|
||||
)
|
||||
self.assertEqual(second_update.status_code, 200, second_update.text)
|
||||
|
||||
@@ -4613,8 +4701,14 @@ class ApiSmokeTests(unittest.TestCase):
|
||||
)
|
||||
updated = self.client.put(
|
||||
f"/api/v1/campaigns/{campaign_id}/versions/{second_version_id}",
|
||||
headers=headers,
|
||||
json={"campaign_json": campaign_json},
|
||||
headers={
|
||||
**headers,
|
||||
"If-Match": str(version_response.headers["etag"]),
|
||||
},
|
||||
json={
|
||||
"campaign_json": campaign_json,
|
||||
"base_revision": version_response.json()["edit_revision"],
|
||||
},
|
||||
)
|
||||
self.assertEqual(updated.status_code, 200, updated.text)
|
||||
validated = self.client.post(
|
||||
@@ -5883,10 +5977,18 @@ class ApiSmokeTests(unittest.TestCase):
|
||||
self.assertEqual(allowed_write.status_code, 200, allowed_write.text)
|
||||
changed_config = version_detail.json()["raw_json"]
|
||||
changed_config["entries"]["inline"][0]["to"][0]["email"] = "changed@example.org"
|
||||
mutation_headers, base_revision = self._campaign_version_precondition(
|
||||
reader_headers,
|
||||
campaign_id,
|
||||
version_id,
|
||||
)
|
||||
denied_recipient_edit = self.client.put(
|
||||
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}",
|
||||
headers=reader_headers,
|
||||
json={"campaign_json": changed_config},
|
||||
headers=mutation_headers,
|
||||
json={
|
||||
"campaign_json": changed_config,
|
||||
"base_revision": base_revision,
|
||||
},
|
||||
)
|
||||
self.assertEqual(denied_recipient_edit.status_code, 403, denied_recipient_edit.text)
|
||||
self.assertEqual(self.client.get(f"/api/v1/campaigns/{campaign_id}", headers=other_headers).status_code, 403)
|
||||
@@ -6030,18 +6132,29 @@ class ApiSmokeTests(unittest.TestCase):
|
||||
}
|
||||
blocked_inline = self.client.put(
|
||||
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}",
|
||||
headers=headers,
|
||||
json={"campaign_json": inline_json},
|
||||
headers={**headers, "If-Match": str(detail.headers["etag"])},
|
||||
json={
|
||||
"campaign_json": inline_json,
|
||||
"base_revision": detail.json()["edit_revision"],
|
||||
},
|
||||
)
|
||||
self.assertEqual(blocked_inline.status_code, 422, blocked_inline.text)
|
||||
self.assertIn("may only reference", blocked_inline.json()["detail"])
|
||||
|
||||
reusable_json = detail.json()["raw_json"]
|
||||
reusable_json["server"] = {"mail_profile_id": tenant_profile_id}
|
||||
mutation_headers, base_revision = self._campaign_version_precondition(
|
||||
headers,
|
||||
campaign_id,
|
||||
version_id,
|
||||
)
|
||||
allowed_reusable = self.client.put(
|
||||
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}",
|
||||
headers=headers,
|
||||
json={"campaign_json": reusable_json},
|
||||
headers=mutation_headers,
|
||||
json={
|
||||
"campaign_json": reusable_json,
|
||||
"base_revision": base_revision,
|
||||
},
|
||||
)
|
||||
self.assertEqual(allowed_reusable.status_code, 200, allowed_reusable.text)
|
||||
|
||||
@@ -6080,8 +6193,11 @@ class ApiSmokeTests(unittest.TestCase):
|
||||
raw_json["server"] = {"mail_profile_id": profile_id}
|
||||
denied_update = self.client.put(
|
||||
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}",
|
||||
headers=headers,
|
||||
json={"campaign_json": raw_json},
|
||||
headers={**headers, "If-Match": str(detail.headers["etag"])},
|
||||
json={
|
||||
"campaign_json": raw_json,
|
||||
"base_revision": detail.json()["edit_revision"],
|
||||
},
|
||||
)
|
||||
self.assertEqual(denied_update.status_code, 422, denied_update.text)
|
||||
|
||||
@@ -6091,10 +6207,18 @@ class ApiSmokeTests(unittest.TestCase):
|
||||
json={"policy": {"allowed_profile_ids": [profile_id]}},
|
||||
)
|
||||
self.assertEqual(allowed_policy.status_code, 200, allowed_policy.text)
|
||||
mutation_headers, base_revision = self._campaign_version_precondition(
|
||||
headers,
|
||||
campaign_id,
|
||||
version_id,
|
||||
)
|
||||
allowed_update = self.client.put(
|
||||
f"/api/v1/campaigns/{campaign_id}/versions/{version_id}",
|
||||
headers=headers,
|
||||
json={"campaign_json": raw_json},
|
||||
headers=mutation_headers,
|
||||
json={
|
||||
"campaign_json": raw_json,
|
||||
"base_revision": base_revision,
|
||||
},
|
||||
)
|
||||
self.assertEqual(allowed_update.status_code, 200, allowed_update.text)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user