Phase 10: Mandantenfähigkeit (#15)
This commit was merged in pull request #15.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { RolleSchluessel } from "@prisma/client";
|
||||
import {
|
||||
ALLE_RECHTE,
|
||||
KeinZugriffFehler,
|
||||
@@ -24,7 +25,10 @@ import {
|
||||
* Terminal nur das Nötigste kann.
|
||||
*/
|
||||
|
||||
function sitzung(rollen: Sitzung["rollen"], organisationId = "org-1"): Sitzung {
|
||||
function sitzung(
|
||||
rollen: Sitzung["rollen"],
|
||||
organisationId = "org-1",
|
||||
): Sitzung & { personId: string } {
|
||||
return {
|
||||
personId: "person-1",
|
||||
organisationId,
|
||||
@@ -34,6 +38,23 @@ function sitzung(rollen: Sitzung["rollen"], organisationId = "org-1"): Sitzung {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Eine Sitzung der Kreisaufsicht: kein Konto in dieser Wehr, keine Akte.
|
||||
*
|
||||
* Seit Phase 10 gibt es diesen Zustand, und er ist der einzige, in dem
|
||||
* `personId` fehlt.
|
||||
*/
|
||||
function aufsicht(organisationId = "org-2"): Sitzung {
|
||||
return {
|
||||
personId: null,
|
||||
organisationId,
|
||||
name: "Kreisbrandinspektion",
|
||||
rollen: ["AUFSICHT"],
|
||||
anmeldeArt: "LOKAL",
|
||||
nurLesend: true,
|
||||
};
|
||||
}
|
||||
|
||||
describe("Rollenkatalog", () => {
|
||||
it("hat für jede Rolle eine deutsche Bezeichnung", () => {
|
||||
for (const rolle of ROLLEN) {
|
||||
@@ -195,3 +216,72 @@ describe("alsRolle", () => {
|
||||
expect(alsRolle(null)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Kreisaufsicht", () => {
|
||||
/**
|
||||
* Der wichtigste Test dieser Datei.
|
||||
*
|
||||
* Die Kreisebene sieht Wehren, denen sie nicht angehört. Bekäme sie dort
|
||||
* versehentlich ein Schreibrecht, wäre das kein Bedienfehler, sondern ein
|
||||
* Loch in der Mandantentrennung — und zwar eines, das niemandem auffällt,
|
||||
* weil in der Oberfläche alles normal aussieht.
|
||||
*
|
||||
* Die Zusicherung ist deshalb bewusst allgemein formuliert: nicht "diese
|
||||
* zwölf Rechte", sondern "kein einziges, das nicht lesen heißt". So gilt
|
||||
* sie auch für Module, die es noch gar nicht gibt.
|
||||
*/
|
||||
it("hat ausschließlich Leserechte — auch für künftige Module", () => {
|
||||
const rechte = [...rechteVon(["AUFSICHT"])];
|
||||
|
||||
expect(rechte.length).toBeGreaterThan(0);
|
||||
expect(rechte.filter((recht) => !recht.endsWith(".lesen"))).toEqual([]);
|
||||
});
|
||||
|
||||
it("sieht die Kasse nicht", () => {
|
||||
// Sie gehört dem Verein oder der Kommune, nicht der Kreisaufsicht — und
|
||||
// wäre nur deshalb dabei, weil das Recht zufällig auf ".lesen" endet.
|
||||
expect(hatRecht(aufsicht(), "kasse.lesen")).toBe(false);
|
||||
});
|
||||
|
||||
it("sieht weder Audit-Log noch KI-Protokoll", () => {
|
||||
// Wer wann was getan hat, bleibt innerhalb der Wehr.
|
||||
expect(hatRecht(aufsicht(), "system.auditlog")).toBe(false);
|
||||
expect(hatRecht(aufsicht(), "ki.protokoll")).toBe(false);
|
||||
});
|
||||
|
||||
it("kann keine Personendaten exportieren", () => {
|
||||
// Das Auskunftsrecht nach DSGVO erfüllt die Wehr, die die Daten führt.
|
||||
expect(hatRecht(aufsicht(), "person.export")).toBe(false);
|
||||
});
|
||||
|
||||
it("sieht den Atemschutz — dafür gibt es sie", () => {
|
||||
expect(hatRecht(aufsicht(), "atemschutz.lesen")).toBe(true);
|
||||
expect(hatRecht(aufsicht(), "atemschutz.bearbeiten")).toBe(false);
|
||||
expect(hatRecht(aufsicht(), "atemschutz.ueberwachung")).toBe(false);
|
||||
});
|
||||
|
||||
it("hat in dieser Wehr keine eigene Akte", () => {
|
||||
// Daran hängt, dass sie in keiner Mitgliederliste auftaucht und als
|
||||
// Urheber keiner Änderung eingetragen werden kann.
|
||||
expect(aufsicht().personId).toBeNull();
|
||||
expect(aufsicht().nurLesend).toBe(true);
|
||||
});
|
||||
|
||||
it("sieht fremde Personen nur über person.lesen, nie über die eigene Akte", () => {
|
||||
// `darfPersonSehen` lässt jeden die eigenen Daten sehen. Ohne Akte darf
|
||||
// dieser Weg nicht versehentlich greifen: sonst entschiede ein Vergleich
|
||||
// von null mit null darüber, wer wen sieht.
|
||||
const kreis = aufsicht();
|
||||
expect(darfPersonSehen(kreis, "irgendeine-person")).toBe(true);
|
||||
expect(hatRecht(kreis, "person.lesen")).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Rollenkatalog und Mandantentrennung", () => {
|
||||
it("führt AUFSICHT nicht als vergebbare Rolle in der Datenbank", () => {
|
||||
// Sie ergibt sich aus der Mitgliedschaftsart, nicht aus einer Zuweisung.
|
||||
// Wäre sie vergebbar, könnte jemand innerhalb einer Wehr Rechte an einer
|
||||
// anderen verteilen.
|
||||
expect(RolleSchluessel).not.toHaveProperty("AUFSICHT");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user