import { describe, expect, it } from "vitest"; import { ALLE_RECHTE, KeinZugriffFehler, ROLLEN, ROLLEN_BEZEICHNUNG, ROLLEN_RECHTE, alsRolle, darfPersonSehen, gehoertZurOrganisation, hatAlleRechte, hatEinesDerRechte, hatRecht, rechteVon, verlangeRecht, type Sitzung, } from "@/lib/authz"; /** * Beispieltest für Phase 0. * * Geprüft wird das, was am teuersten schiefgeht: dass der Gerätewart nicht in * die Kasse kommt, dass der Administrator wirklich alles darf, und dass das * Terminal nur das Nötigste kann. */ function sitzung(rollen: Sitzung["rollen"], organisationId = "org-1"): Sitzung { return { personId: "person-1", organisationId, name: "Testperson", rollen, anmeldeArt: "LOKAL", }; } describe("Rollenkatalog", () => { it("hat für jede Rolle eine deutsche Bezeichnung", () => { for (const rolle of ROLLEN) { expect(ROLLEN_BEZEICHNUNG[rolle]).toBeTruthy(); } }); it("vergibt in ROLLEN_RECHTE nur Rechte, die es im Katalog gibt", () => { for (const [rolle, rechte] of Object.entries(ROLLEN_RECHTE)) { for (const recht of rechte) { expect(ALLE_RECHTE, `${rolle} verweist auf unbekanntes Recht ${recht}`).toContain( recht, ); } } }); }); describe("hatRecht", () => { it("gibt dem Administrator ausnahmslos alles", () => { const admin = sitzung(["SUPERADMIN"]); for (const recht of ALLE_RECHTE) { expect(hatRecht(admin, recht)).toBe(true); } }); it("lässt den Gerätewart Geräte bearbeiten", () => { expect(hatRecht(sitzung(["GERAETEWART"]), "geraet.bearbeiten")).toBe(true); expect(hatRecht(sitzung(["GERAETEWART"]), "pruefung.durchfuehren")).toBe(true); }); it("lässt den Gerätewart NICHT an die Kasse", () => { expect(hatRecht(sitzung(["GERAETEWART"]), "kasse.bearbeiten")).toBe(false); expect(hatRecht(sitzung(["GERAETEWART"]), "kasse.abschluss")).toBe(false); }); it("lässt den Kassier nicht an Geräte und den Atemschutz", () => { expect(hatRecht(sitzung(["KASSIER"]), "geraet.bearbeiten")).toBe(false); expect(hatRecht(sitzung(["KASSIER"]), "atemschutz.ueberwachung")).toBe(false); }); it("gibt dem einfachen Mitglied nur Lese- und eigene Rechte", () => { const mitglied = sitzung(["MITGLIED"]); expect(hatRecht(mitglied, "person.eigene")).toBe(true); expect(hatRecht(mitglied, "geraet.lesen")).toBe(true); expect(hatRecht(mitglied, "person.bearbeiten")).toBe(false); expect(hatRecht(mitglied, "geraet.bearbeiten")).toBe(false); }); it("beschränkt das Terminal auf Anmelden und Erfassen", () => { const kiosk = sitzung(["KIOSK"]); expect(hatRecht(kiosk, "kiosk.anmelden")).toBe(true); expect(hatRecht(kiosk, "kiosk.erfassen")).toBe(true); expect(hatRecht(kiosk, "person.bearbeiten")).toBe(false); expect(hatRecht(kiosk, "system.einstellungen")).toBe(false); expect(hatRecht(kiosk, "kasse.lesen")).toBe(false); }); it("verweigert ohne Sitzung alles", () => { for (const recht of ALLE_RECHTE) { expect(hatRecht(null, recht)).toBe(false); } }); it("addiert die Rechte mehrerer Rollen", () => { const doppelrolle = sitzung(["GERAETEWART", "KASSIER"]); expect(hatRecht(doppelrolle, "geraet.bearbeiten")).toBe(true); expect(hatRecht(doppelrolle, "kasse.bearbeiten")).toBe(true); }); }); describe("rechteVon", () => { it("liefert für den Administrator den vollständigen Katalog", () => { expect(rechteVon(["SUPERADMIN"]).size).toBe(ALLE_RECHTE.length); }); it("liefert für das Terminal deutlich weniger als für den Kommandanten", () => { expect(rechteVon(["KIOSK"]).size).toBeLessThan(rechteVon(["KOMMANDANT"]).size); }); }); describe("hatEinesDerRechte / hatAlleRechte", () => { const geraetewart = sitzung(["GERAETEWART"]); it("genügt ein Treffer bei hatEinesDerRechte", () => { expect(hatEinesDerRechte(geraetewart, ["kasse.bearbeiten", "geraet.bearbeiten"])).toBe( true, ); }); it("verlangt hatAlleRechte jeden einzelnen Treffer", () => { expect(hatAlleRechte(geraetewart, ["kasse.bearbeiten", "geraet.bearbeiten"])).toBe(false); expect(hatAlleRechte(geraetewart, ["geraet.lesen", "geraet.bearbeiten"])).toBe(true); }); }); describe("verlangeRecht", () => { it("lässt durch, wenn das Recht vorliegt", () => { expect(() => verlangeRecht(sitzung(["KOMMANDANT"]), "person.bearbeiten")).not.toThrow(); }); it("wirft KeinZugriffFehler, wenn das Recht fehlt", () => { expect(() => verlangeRecht(sitzung(["MITGLIED"]), "person.bearbeiten")).toThrow( KeinZugriffFehler, ); }); it("nennt im Fehler das fehlende Recht", () => { try { verlangeRecht(sitzung(["MITGLIED"]), "kasse.abschluss"); expect.unreachable("hätte werfen müssen"); } catch (fehler) { expect(fehler).toBeInstanceOf(KeinZugriffFehler); expect((fehler as Error).message).toContain("kasse.abschluss"); } }); }); describe("Mandantentrennung", () => { it("erkennt Datensätze der eigenen Wehr", () => { expect(gehoertZurOrganisation(sitzung(["MITGLIED"], "org-1"), { organisationId: "org-1" })).toBe( true, ); }); it("weist Datensätze einer fremden Wehr ab — auch dem Administrator", () => { expect( gehoertZurOrganisation(sitzung(["SUPERADMIN"], "org-1"), { organisationId: "org-2" }), ).toBe(false); }); it("weist null-Datensätze ab", () => { expect(gehoertZurOrganisation(sitzung(["KOMMANDANT"]), null)).toBe(false); }); }); describe("darfPersonSehen", () => { it("lässt jeden die eigenen Daten sehen, auch ohne person.lesen", () => { const kiosk = sitzung(["KIOSK"]); expect(hatRecht(kiosk, "person.lesen")).toBe(false); expect(darfPersonSehen(kiosk, kiosk.personId)).toBe(true); }); it("verlangt für fremde Personen das Recht person.lesen", () => { expect(darfPersonSehen(sitzung(["KIOSK"]), "andere-person")).toBe(false); expect(darfPersonSehen(sitzung(["MITGLIED"]), "andere-person")).toBe(true); }); }); describe("alsRolle", () => { it("erkennt Rollen unabhängig von Groß- und Kleinschreibung", () => { expect(alsRolle("kommandant")).toBe("KOMMANDANT"); expect(alsRolle(" GeraeteWart ")).toBe("GERAETEWART"); }); it("gibt bei Unsinn null zurück", () => { expect(alsRolle("oberbrandmeister")).toBeNull(); expect(alsRolle("")).toBeNull(); expect(alsRolle(null)).toBeNull(); }); });