Files
MABEA/backend/tests/test_benutzer_admin.py
patrickandClaude Sonnet 5 7f5bbb65d5
CI / backend-tests (push) Failing after 1m19s
CI / frontend-build (push) Successful in 23s
Rollen-differenzierte Verwaltungs-UI (Material-/Leitungsverantwortliche)
Bug: Frontend prüfte nur istAdmin, Materialverantwortliche und Leitungs-
verantwortliche sahen exakt dieselbe UI wie Mitarbeiter - obwohl das Backend
längst granular unterscheidet (require_roles je Endpunkt).

- AuthContext gibt volle Rollenliste + istVerantwortlich/istMaterial-
  verantwortlich/istLeitungsverantwortlich weiter.
- /admin-Route für alle drei Rollen offen, AdminPage filtert Tabs nach
  Rolle (Material/Leitung: Objekte-Pflege, Kontrollverantwortung,
  Änderungslog; nur Administration: Stammdaten/Benutzer/Eskalation/
  Zuständigkeit).
- ObjektSection blendet Anlegen/Duplizieren/Kopplung für Nicht-Admins aus
  (waren admin-only im Backend, hätten 403 geworfen).
- Promise.allSettled statt Promise.all beim Laden, damit ein admin-only
  Endpunkt (z.B. /benutzer) nicht die ganze Seite für niedrigere Rollen
  blockiert.
- Backend: GET /benutzer jetzt auch für Material-/Leitungsverantwortliche
  lesbar (für Kontrollverantwortung-Auswahl im Frontend nötig), Schreiben
  bleibt admin-only.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-04 22:25:32 +02:00

94 lines
3.3 KiB
Python

import pytest
from tests.conftest import auth_header, login
@pytest.mark.asyncio
async def test_admin_can_create_benutzer_with_rollen(client, admin_user):
token = await login(client, "admin1")
response = await client.post(
"/api/v1/benutzer",
json={
"name": "Neue Kollegin",
"login": "neu1",
"passwort": "sicheres-passwort",
"rollen": ["mitarbeiter", "materialverantwortlicher"],
},
headers=auth_header(token),
)
assert response.status_code == 201
body = response.json()
assert body["login"] == "neu1"
assert set(body["rollen"]) == {"mitarbeiter", "materialverantwortlicher"}
@pytest.mark.asyncio
async def test_duplicate_login_conflict(client, admin_user):
token = await login(client, "admin1")
payload = {
"name": "Doppelt",
"login": "doppelt1",
"passwort": "sicheres-passwort",
"rollen": [],
}
first = await client.post("/api/v1/benutzer", json=payload, headers=auth_header(token))
assert first.status_code == 201
second = await client.post("/api/v1/benutzer", json=payload, headers=auth_header(token))
assert second.status_code == 409
@pytest.mark.asyncio
async def test_mitarbeiter_cannot_manage_benutzer(client, mitarbeiter_user):
token = await login(client, "mitarbeiter1")
response = await client.get("/api/v1/benutzer", headers=auth_header(token))
assert response.status_code == 403
@pytest.mark.asyncio
async def test_admin_can_update_rollen(client, admin_user, mitarbeiter_user):
token = await login(client, "admin1")
response = await client.patch(
f"/api/v1/benutzer/{mitarbeiter_user.id}",
json={"rollen": ["leitungsverantwortlicher"]},
headers=auth_header(token),
)
assert response.status_code == 200
assert response.json()["rollen"] == ["leitungsverantwortlicher"]
@pytest.mark.asyncio
async def test_materialverantwortlicher_darf_benutzer_lesen_nicht_anlegen(
client, materialverantwortlicher_user
):
"""Rollen-Vorgabe: Material-/Leitungsverantwortliche brauchen die Liste
lesend (z.B. Kontrollverantwortung-Auswahl im Frontend), aber kein
Schreibrecht - anders als Administration."""
token = await login(client, "materialverantwortlicher1")
gelesen = await client.get("/api/v1/benutzer", headers=auth_header(token))
assert gelesen.status_code == 200
angelegt = await client.post(
"/api/v1/benutzer",
json={"name": "X", "login": "x1", "passwort": "sicheres-passwort", "rollen": ["mitarbeiter"]},
headers=auth_header(token),
)
assert angelegt.status_code == 403
@pytest.mark.asyncio
async def test_leitungsverantwortlicher_darf_benutzer_lesen(client, db_session):
from app.core.security import hash_password
from app.models.auth import Benutzer, BenutzerRolle, RolleTyp
benutzer = Benutzer(
name="Test Leitung", login="leitung1", passwort_hash=hash_password("test-passwort-123"), aktiv=True
)
db_session.add(benutzer)
await db_session.flush()
db_session.add(BenutzerRolle(benutzer_id=benutzer.id, rolle=RolleTyp.leitungsverantwortlicher))
await db_session.flush()
token = await login(client, "leitung1")
response = await client.get("/api/v1/benutzer", headers=auth_header(token))
assert response.status_code == 200