"""Owner-only project delete: files+meta gone; other owners and auth users untouched.""" from __future__ import annotations from pathlib import Path from fastapi.testclient import TestClient from backend.services import projects as proj_svc from backend.services.storage import LocalStorageBackend def _client(tmp_path: Path) -> TestClient: from backend.main import app app.state.storage = LocalStorageBackend(tmp_path) return TestClient(app) def test_owner_delete_removes_project_files_not_auth(tmp_path: Path): client = _client(tmp_path) auth_users = tmp_path / "auth" / "users.json" auth_users.parent.mkdir(parents=True) auth_users.write_text('{"users":[{"email":"keep@example.com"}]}\n') meta = client.post("/api/projects", json={"name": "mine"}).json() pid = meta["id"] prefix = f"users/local/projects/{pid}" storage = client.app.state.storage storage.write_json(f"{prefix}/report.json", {"findings": []}) storage.write_text(f"{prefix}/uploads/netlist.asc", "*PADS-PCB*\n") resp = client.delete(f"/api/projects/{pid}") assert resp.status_code == 200, resp.text assert resp.json()["ok"] is True assert not storage.exists(f"{prefix}/project.json") assert not storage.exists(f"{prefix}/report.json") assert auth_users.is_file() assert "keep@example.com" in auth_users.read_text() listed = client.get("/api/projects").json() assert all(p["id"] != pid for p in listed) def test_delete_another_owners_project_is_404(tmp_path: Path): client = _client(tmp_path) storage = client.app.state.storage other = proj_svc.create_project(storage, "alice", "secret-board") key = f"users/alice/projects/{other.id}/project.json" report = f"users/alice/projects/{other.id}/report.json" storage.write_json(report, {"findings": [{"id": 1}]}) alice_users = tmp_path / "users" / "alice" / "profile.json" alice_users.parent.mkdir(parents=True, exist_ok=True) alice_users.write_text('{"user_id":"alice"}\n') resp = client.delete(f"/api/projects/{other.id}") assert resp.status_code == 404 assert storage.exists(key) assert storage.exists(report) assert alice_users.is_file() def test_collaborator_cannot_delete_owner_project(tmp_path: Path): client = _client(tmp_path) storage = client.app.state.storage other = proj_svc.create_project(storage, "alice", "shared") proj_svc.add_collaborator(storage, "alice", other.id, "local") key = f"users/alice/projects/{other.id}/project.json" resp = client.delete(f"/api/projects/{other.id}") assert resp.status_code == 403, resp.text assert storage.exists(key) meta = proj_svc.get_project(storage, "alice", other.id) assert meta is not None assert "local" in meta.collaborators