-- --------------------------------------------------------------------------- -- HANDGESCHRIEBEN. Prisma erzeugt hier zusaetzlich Loeschbefehle fuer die -- zusammengesetzten Fremdschluessel (Mandantengrenze), die Trigramm-Indizes -- (Archivsuche), die partiellen eindeutigen Indizes und alle Trigger: es kennt -- sie nicht, weil sie sich im Schema nicht ausdruecken lassen. Diese -- Loeschbefehle sind bewusst gestrichen. -- -- tests/datenbankregeln.test.ts prueft, dass alle diese Objekte vorhanden sind – -- ein versehentlich stehengelassener Loeschbefehl faellt dort sofort auf. -- --------------------------------------------------------------------------- -- Quellenarten und Microsoft-Graph-Quelle (#028). CREATE TYPE "QuellenArt" AS ENUM ('LDAP', 'GRAPH', 'SCIM'); /* * **Die Reihenfolge der drei Schritte ist nicht beliebig.** * * Erst die Spalte mit Vorgabe `LDAP` anlegen, dann die bisherigen * Pflichtfelder lockern, und erst danach den CHECK setzen. Umgekehrt waere der * CHECK fuer die Dauer einer Anweisung gegen Zeilen gerichtet, die ihn noch * nicht erfuellen koennen. * * Die Vorgabe `LDAP` ist zugleich die Nachfuehrung fuer alle bestehenden Zeilen: * vor #028 war jede Quelle implizit LDAP, und `ADD COLUMN ... DEFAULT` schreibt * den Wert in jede vorhandene Zeile. Ein eigenes `UPDATE` braucht es deshalb * nicht — aber die Pruefung unten steht trotzdem da. */ ALTER TABLE "Verzeichnisquelle" ADD COLUMN "art" "QuellenArt" NOT NULL DEFAULT 'LDAP'; -- Die LDAP-Felder gelten nur noch fuer LDAP-Quellen. ALTER TABLE "Verzeichnisquelle" ALTER COLUMN "url" DROP NOT NULL, ALTER COLUMN "bindDn" DROP NOT NULL, ALTER COLUMN "bindPasswortVerschluesselt" DROP NOT NULL, ALTER COLUMN "basisDn" DROP NOT NULL, ALTER COLUMN "filter" DROP NOT NULL; -- Und die Felder einer Graph-Quelle. ALTER TABLE "Verzeichnisquelle" ADD COLUMN "tenantId" TEXT, ADD COLUMN "clientId" TEXT, ADD COLUMN "clientSecretVerschluesselt" TEXT; /* * **Welche Felder eine Art braucht, haelt die Datenbank fest.** * * Ohne das waere eine Graph-Quelle mit `basisDn` moeglich — eine Zeile, die zwei * Dinge gleichzeitig behauptet, und bei der niemand mehr sagen kann, was gilt. * Der Dienst prueft dasselbe noch einmal, nur mit besserer Meldung. * * `SCIM` fehlt hier mit Absicht: die Art steht im Enum, weil #029 dieselbe * Weiche braucht, hat aber noch keine Felder. Eine Bedingung auf Felder, die es * nicht gibt, waere eine Zeile, die beim naechsten Meilenstein umgeschrieben * werden muss — und der Dienst weist `SCIM` bis dahin ohnehin ab. */ ALTER TABLE "Verzeichnisquelle" ADD CONSTRAINT "Verzeichnisquelle_felder_je_art" CHECK ( ("art" = 'LDAP' AND "url" IS NOT NULL AND "bindDn" IS NOT NULL AND "bindPasswortVerschluesselt" IS NOT NULL AND "basisDn" IS NOT NULL AND "filter" IS NOT NULL AND "tenantId" IS NULL AND "clientId" IS NULL AND "clientSecretVerschluesselt" IS NULL) OR ("art" = 'GRAPH' AND "tenantId" IS NOT NULL AND "clientId" IS NOT NULL AND "clientSecretVerschluesselt" IS NOT NULL AND "url" IS NULL AND "bindDn" IS NULL AND "bindPasswortVerschluesselt" IS NULL AND "basisDn" IS NULL AND "filter" IS NULL) OR ("art" = 'SCIM') ); -- Das Client-Secret verschluesselt, dieselbe Pruefung wie beim Bind-Passwort. ALTER TABLE "Verzeichnisquelle" ADD CONSTRAINT "Verzeichnisquelle_clientsecret_verschluesselt" CHECK ("clientSecretVerschluesselt" ~ '^v[0-9]+\.'); -- Der Zeitplan fragt nach faelligen **aktiven** Quellen; die Art kommt jetzt in -- dieselbe Abfrage, weil das Holen der Eintraege je Art ein anderes ist. CREATE INDEX "Verzeichnisquelle_art_idx" ON "Verzeichnisquelle"("art"); /* * Gegenprobe zur Nachfuehrung: nach dem `ADD COLUMN ... DEFAULT` darf keine * Zeile ohne Art dastehen. `art` ist NOT NULL, das kann also nicht schiefgehen — * aber eine Migration, die ihre eigene Nachfuehrung behauptet, ohne sie zu * pruefen, ist genau die Art Zusage, die dieses Projekt teuer bezahlt hat. */ DO $$ DECLARE ohne_art INTEGER; BEGIN SELECT count(*) INTO ohne_art FROM "Verzeichnisquelle" WHERE "art" IS NULL; IF ohne_art > 0 THEN RAISE EXCEPTION 'Nachfuehrung fehlgeschlagen: % Quellen ohne Art.', ohne_art; END IF; END $$;