add admin data mutations and load check
Some checks failed
ci / test (pull_request) Has been cancelled

This commit is contained in:
VPN SaaS Dev
2026-05-18 18:37:19 +09:00
parent 59bc6ebd4f
commit 8982299e71
9 changed files with 650 additions and 44 deletions

View File

@@ -222,6 +222,129 @@ async def test_data_query_creates_audit_log(client, admin_auth_headers, internal
assert any(item["action"] == "admin.data.query" for item in audit.json())
@pytest.mark.asyncio
async def test_admin_data_update_requires_reason_and_audits(
client, admin_auth_headers, internal_headers
) -> None:
await ensure_admin(client, internal_headers)
user = (
await client.post(
"/api/users",
headers=internal_headers,
json={"telegram_id": 456789, "first_name": "Before"},
)
).json()
missing_reason = await client.patch(
f"/api/admin/data/users/{user['id']}",
headers=admin_auth_headers,
json={"values": {"first_name": "After"}, "reason": ""},
)
updated = await client.patch(
f"/api/admin/data/users/{user['id']}",
headers=admin_auth_headers,
json={"values": {"first_name": "After"}, "reason": "support correction"},
)
audit = await client.get("/api/admin/audit-log?action=admin.data.update", headers=admin_auth_headers)
assert missing_reason.status_code == 400
assert updated.status_code == 200
assert updated.json()["row"]["first_name"] == "After"
assert any(item["action"] == "admin.data.update" for item in audit.json())
@pytest.mark.asyncio
async def test_admin_data_update_rejects_forbidden_field(
client, admin_auth_headers, internal_headers
) -> None:
await ensure_admin(client, internal_headers)
user = (
await client.post(
"/api/users",
headers=internal_headers,
json={"telegram_id": 556677, "first_name": "Nope"},
)
).json()
response = await client.patch(
f"/api/admin/data/users/{user['id']}",
headers=admin_auth_headers,
json={"values": {"telegram_id": 1}, "reason": "support correction"},
)
assert response.status_code == 400
assert "Forbidden fields" in response.text
@pytest.mark.asyncio
async def test_admin_data_delete_soft_blocks_user(
client, admin_auth_headers, internal_headers
) -> None:
await ensure_admin(client, internal_headers)
user = (
await client.post(
"/api/users",
headers=internal_headers,
json={"telegram_id": 667788, "first_name": "Blocked soon"},
)
).json()
deleted = await client.request(
"DELETE",
f"/api/admin/data/users/{user['id']}",
headers=admin_auth_headers,
json={"reason": "support requested block"},
)
query = await client.post(
"/api/admin/data/query",
headers=admin_auth_headers,
json={"source": "users", "user_id": user["id"], "limit": 25},
)
audit = await client.get("/api/admin/audit-log?action=admin.data.delete", headers=admin_auth_headers)
assert deleted.status_code == 200
assert deleted.json()["mode"] == "soft"
assert query.json()["rows"][0]["platform_role"] == "blocked"
assert any(item["action"] == "admin.data.delete" for item in audit.json())
@pytest.mark.asyncio
async def test_admin_data_delete_hard_deletes_fuel_entry(
client, auth_headers, admin_auth_headers, internal_headers
) -> None:
await ensure_admin(client, internal_headers)
car = (await client.post("/api/cars", headers=auth_headers, json={"name": "Admin delete fuel"})).json()
fuel = (
await client.post(
"/api/fuel",
headers=auth_headers,
json={
"car_id": car["id"],
"entry_date": "2026-05-18",
"odometer": 1200,
"liters": 35,
"price_per_liter": 2,
},
)
).json()
deleted = await client.request(
"DELETE",
f"/api/admin/data/fuel_entries/{fuel['id']}",
headers=admin_auth_headers,
json={"reason": "duplicate record cleanup"},
)
query = await client.post(
"/api/admin/data/query",
headers=admin_auth_headers,
json={"source": "fuel_entries", "vehicle_id": car["id"], "limit": 25},
)
assert deleted.status_code == 200
assert deleted.json()["mode"] == "hard"
assert query.json()["rows"] == []
@pytest.mark.asyncio
async def test_pending_sto_queue_and_approve_audit(
client, auth_headers, admin_auth_headers, internal_headers