"""Privat-Modell: Kanban-Projekte nur für Mitglieder, Artikel lesen alle / bearbeiten Beteiligte, Admins dürfen alles.""" from app import db def projekt(client, name="P", members=(), links=()): res = client.post("/api/kanban/projekte", json={"name": name, "members": list(members), "links": list(links)}) assert res.status_code == 201, res.text return res.json()["id"] def artikel(client, title="Doku"): res = client.post("/api/projects", json={"title": title}) assert res.status_code == 201, res.text return res.json()["id"] def test_kanban_privat(login, befriend): anna, ben, chef = login("anna"), login("ben"), login("chef", admin=True) pid = projekt(anna) assert ben.get("/api/kanban").json()["projects"] == [] assert ben.get(f"/api/kanban/projekte/{pid}").status_code == 404 assert ben.post(f"/api/kanban/projekte/{pid}/aufgaben", json={"title": "x"}).status_code == 404 assert chef.get(f"/api/kanban/projekte/{pid}").status_code == 200 # Admin sieht alles # Mitglied nur als Freund assert anna.patch(f"/api/kanban/projekte/{pid}", json={"members": [ben.user["id"]]}).status_code == 400 befriend(anna, ben) data = anna.patch(f"/api/kanban/projekte/{pid}", json={"members": [ben.user["id"]]}).json() assert data["project"]["members"] == [ben.user["id"]] assert ben.get(f"/api/kanban/projekte/{pid}").status_code == 200 # Mitglieder verwalten nur Ersteller/Admin assert ben.patch(f"/api/kanban/projekte/{pid}", json={"members": []}).status_code == 403 def test_bearbeiter_nur_beteiligte(login, befriend): anna, ben, carl = login("anna"), login("ben"), login("carl") befriend(anna, ben) pid = projekt(anna, members=[ben.user["id"]]) data = anna.post(f"/api/kanban/projekte/{pid}/aufgaben", json={"title": "A", "assignee": ben.user["id"]}).json() task = data["tasks"][0] assert [p["name"] for p in data["people"]] == ["Anna", "Ben"] assert anna.patch(f"/api/kanban/aufgaben/{task['id']}", json={"assignee": carl.user["id"]}).status_code == 400 # Ben fliegt raus → seine Aufgaben sind niemandem mehr zugeteilt data = anna.patch(f"/api/kanban/projekte/{pid}", json={"members": []}).json() assert data["tasks"][0]["assignee"] is None def test_artikel_lesen_alle_bearbeiten_beteiligte(login, befriend): anna, ben, carl, chef = login("anna"), login("ben"), login("carl"), login("chef", admin=True) aid = artikel(anna) assert ben.get(f"/api/projects/{aid}").json()["canEdit"] is False assert ben.patch(f"/api/projects/{aid}", json={"title": "x"}).status_code == 403 # Ben arbeitet an einem verknüpften Kanban-Projekt mit → darf bearbeiten befriend(anna, ben) projekt(anna, members=[ben.user["id"]], links=[aid]) assert ben.get(f"/api/projects/{aid}").json()["canEdit"] is True assert ben.patch(f"/api/projects/{aid}", json={"title": "Neu"}).status_code == 200 assert carl.get(f"/api/projects/{aid}").status_code == 200 # lesen dürfen alle assert carl.patch(f"/api/projects/{aid}", json={"title": "x"}).status_code == 403 assert chef.patch(f"/api/projects/{aid}", json={"title": "Admin"}).status_code == 200 # Löschen bleibt Autor/Admin assert ben.delete(f"/api/projects/{aid}").status_code == 403 def test_verknuepfen_nur_bearbeitbare_artikel(login): """Sonst könnte man sich durch ein eigenes Kanban-Projekt Bearbeitungsrechte verschaffen.""" anna, carl = login("anna"), login("carl") aid = artikel(anna) res = carl.post("/api/kanban/projekte", json={"name": "Trick", "links": [aid]}) assert res.status_code == 400 assert carl.patch(f"/api/projects/{aid}", json={"title": "x"}).status_code == 403 def test_board_auf_artikelseite_nur_sichtbare(login): anna, ben = login("anna"), login("ben") aid = artikel(anna) projekt(anna, name="Intern", links=[aid]) assert [b["name"] for b in anna.get(f"/api/projects/{aid}").json()["boards"]] == ["Intern"] assert ben.get(f"/api/projects/{aid}").json()["boards"] == [] def test_umstellung_privat(conn, login): """Schritt 6: bisher gemeinsame Listen/Projekte bekommen alle Konten als Mitglieder, ohne Besitzer → erster Admin.""" anna, ben, chef = login("anna"), login("ben"), login("chef", admin=True) with conn: conn.execute("INSERT INTO shopping_lists (id, name, everyone, position, created_at, created_by) VALUES (50, 'Alt', 1, 1, 'x', ?)", (anna.user["id"],)) conn.execute("INSERT INTO shopping_lists (id, name, everyone, position, created_at) VALUES (51, 'Ohne', 1, 2, 'x')") conn.execute("INSERT INTO kanban_projects (id, name, position, created_at, created_by, updated_at) VALUES (60, 'K', 1, 'x', ?, 'x')", (anna.user["id"],)) conn.execute("PRAGMA user_version = 5") db.init() members = lambda lid: sorted(r[0] for r in conn.execute("SELECT user_id FROM shopping_list_members WHERE list_id = ?", (lid,))) assert members(50) == sorted([ben.user["id"], chef.user["id"]]) assert conn.execute("SELECT created_by FROM shopping_lists WHERE id = 51").fetchone()[0] == chef.user["id"] assert sorted(r[0] for r in conn.execute("SELECT user_id FROM kanban_project_members WHERE project_id = 60")) == sorted([ben.user["id"], chef.user["id"]]) assert conn.execute("SELECT COUNT(*) FROM shopping_lists WHERE everyone = 1").fetchone()[0] == 0 assert any(l["id"] == 50 for l in ben.get("/api/haushalt").json()["lists"])