"""Verwaltung von Teams und Nutzern durch den Plattform-Admin.""" import re import pytest from fastapi.testclient import TestClient from sqlalchemy import select from app.identity.models import Team, User from helpers import PASSWORD, create_workspace @pytest.fixture def admin(browser, people, db): with db.session() as session: session.get(User, people["anna"]).is_admin = True return browser("anna") def team_id(db, slug: str) -> int: with db.session() as session: return session.scalar(select(Team.id).where(Team.slug == slug)) def test_nur_plattform_admin(browser, people): ben = browser("ben") for url in ("/admin/teams", "/admin/users", f"/admin/teams/{people['team_demo']}"): assert ben.get(url).status_code == 403 assert ben.post("/admin/teams", {"slug": "x1", "name": "X"}).status_code == 403 assert ben.post("/admin/users", {"username": "eve"}).status_code == 403 assert ben.post(f"/admin/users/{people['ben']}", {"is_admin": "1", "active": "1"}).status_code == 403 def test_nutzer_und_team_anlegen_dann_workspace(admin, db, app): created = admin.post("/admin/users", {"username": "Erik", "display_name": "Erik E."}) assert created.status_code == 200 secret = re.search(r'([^<]+)', created.text).group(1) response = admin.post("/admin/teams", {"slug": "plattform", "name": "Plattform"}) assert response.status_code == 303 new_team = team_id(db, "plattform") admin.post(f"/admin/teams/{new_team}/members", {"username": "erik"}) assert "Erik E." in admin.get(f"/admin/teams/{new_team}").text # Erik kann sich anmelden und für sein neues Team einen Workspace anlegen from helpers import Browser with TestClient(app) as client: client.post("/login", data={"username": "erik", "password": secret}) token = re.search(r'name="_csrf" value="([^"]+)"', client.get("/password").text).group(1) client.post("/password", data={"_csrf": token, "current": secret, "new": "Blauer Himmel ueber Bonn 9", "repeat": "Blauer Himmel ueber Bonn 9"}) erik = Browser(client) erik.csrf = token create_workspace(erik, new_team, "Eriks Workspace") @pytest.mark.parametrize("data", [{"slug": "A B", "name": "X"}, {"slug": "demo", "name": "Doppelt"}, {"slug": "ok-slug", "name": " "}]) def test_ungueltige_teams(admin, data): assert admin.post("/admin/teams", data).status_code == 400 def test_doppelter_nutzername(admin): assert admin.post("/admin/users", {"username": "ben"}).status_code == 400 assert admin.post("/admin/users", {"username": "x"}).status_code == 400 def test_aus_team_entfernen_beendet_workspace_zugriff(admin, people, browser): workspace_id = create_workspace(admin, people["team_demo"]) admin.post(f"/workspaces/{workspace_id}/members", {"username": "ben", "role": "member"}) ben = browser("ben") assert ben.get(f"/workspaces/{workspace_id}").status_code == 200 response = admin.post(f"/admin/teams/{people['team_demo']}/members/{people['ben']}/remove") assert response.status_code == 200 assert ben.get(f"/workspaces/{workspace_id}").status_code == 404 assert "ben" not in admin.get(f"/workspaces/{workspace_id}/settings?tab=members").text.split("", 1)[1].split("
")[0] def test_teamzugehoerigkeit_wird_zusaetzlich_geprueft(admin, people, browser, db): """Auch wenn eine Workspace-Mitgliedschaft übrig bliebe, reicht sie ohne Team nicht.""" from app.identity.models import TeamMembership workspace_id = create_workspace(admin, people["team_demo"]) admin.post(f"/workspaces/{workspace_id}/members", {"username": "ben", "role": "member"}) with db.session() as session: session.delete(session.get(TeamMembership, (people["team_demo"], people["ben"]))) assert browser("ben").get(f"/workspaces/{workspace_id}").status_code == 404 def test_letzter_workspace_admin_bleibt_im_team(admin, people): create_workspace(admin, people["team_demo"], "Annas Workspace") response = admin.post(f"/admin/teams/{people['team_demo']}/members/{people['anna']}/remove") assert response.status_code == 400 and "Annas Workspace" in response.text def test_deaktivieren_beendet_sitzung(admin, people, browser): ben = browser("ben") assert ben.get("/workspaces").status_code == 200 admin.post(f"/admin/users/{people['ben']}", {"display_name": "Ben", "active": ""}) assert ben.get("/workspaces", follow_redirects=False).status_code == 303 response = ben.client.post("/login", data={"username": "ben", "password": PASSWORD}) assert response.status_code == 401 def test_letzter_plattform_admin_bleibt(admin, people): response = admin.post(f"/admin/users/{people['anna']}", {"display_name": "Anna", "active": "1"}) assert response.status_code == 400 and "letzte Plattform-Admin" in response.text response = admin.post(f"/admin/users/{people['anna']}", {"display_name": "Anna", "is_admin": "1"}) assert response.status_code == 400 def test_workspace_mitglied_entfernen(admin, people, browser): workspace_id = create_workspace(admin, people["team_demo"]) admin.post(f"/workspaces/{workspace_id}/members", {"username": "ben", "role": "member"}) assert admin.post(f"/workspaces/{workspace_id}/members/{people['ben']}/remove").status_code == 303 assert browser("ben").get(f"/workspaces/{workspace_id}").status_code == 404 assert admin.post(f"/workspaces/{workspace_id}/members/{people['anna']}/remove").status_code == 400