add admin data mutations and load check
Some checks failed
ci / test (pull_request) Has been cancelled
Some checks failed
ci / test (pull_request) Has been cancelled
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user