Files
Aether/backend/db/migrations/000011_acl_entries.up.sql
HoneyandClaude Opus 5 31a027c93a feat(aether): initial commit – self-hosted Cloud, Phasen 1–7
Go-Backend (chi, pgx, golang-migrate) + React/TS-Frontend als PWA.
Enthalten: Auth inkl. OIDC, Dateien mit Versionen und Papierkorb,
Freigaben (Links + intern), WebDAV, Gruppenordner, Admin/Theming,
Volltextsuche mit OCR, eigener PDF-Betrachter und WOPI-Office
(Collabora/OnlyOffice).

Nicht im Repo: deploy/.env (Sitzungsschlüssel, DB- und Admin-Passwort)
sowie alle Daten- und Build-Verzeichnisse – siehe .gitignore.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 09:25:36 +02:00

52 lines
3.1 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- Interne Freigaben: Ordner oder Datei an einen anderen Nutzer oder eine Gruppe
-- geben, ohne dass die Bytes umziehen. Der Empfänger sieht sie virtuell unter
-- „Geteilt mit mir"; auf der Platte bleibt alles beim Eigentümer.
--
-- Abweichung vom Projektplan: dort war eine polymorphe Tabelle skizziert
-- (subject_type + subject_id als Text/UUID ohne Fremdschlüssel). Hier stattdessen
-- vier nullbare Fremdschlüssel mit CHECK-Bedingung. Grund: polymorph kann die
-- Datenbank nichts erzwingen – ein gelöschter Nutzer oder Ordner hinterließe
-- Einträge, die auf nichts mehr zeigen, und aus so einer Leiche später eine
-- Freigabe für einen neu vergebenen Namen zu machen wäre ein Sicherheitsloch.
-- Mit echten Fremdschlüsseln räumt ON DELETE CASCADE das von selbst auf.
CREATE TABLE acl_entries (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Empfänger: genau eines von beiden.
subject_user_id UUID REFERENCES users(id) ON DELETE CASCADE,
subject_group_id UUID REFERENCES groups(id) ON DELETE CASCADE,
-- Freigegebene Ressource: genau eines von beiden.
resource_folder_id UUID REFERENCES folders(id) ON DELETE CASCADE,
resource_file_id UUID REFERENCES files(id) ON DELETE CASCADE,
permission TEXT NOT NULL CHECK (permission IN ('read', 'write')),
-- Wer die Freigabe erteilt hat. SET NULL statt CASCADE: die Freigabe soll
-- nicht verschwinden, nur weil das Konto des Erteilers gelöscht wurde.
granted_by UUID REFERENCES users(id) ON DELETE SET NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT acl_one_subject CHECK (num_nonnulls(subject_user_id, subject_group_id) = 1),
CONSTRAINT acl_one_resource CHECK (num_nonnulls(resource_folder_id, resource_file_id) = 1)
);
-- Zwei Freigaben derselben Ressource an denselben Empfänger wären mehrdeutig:
-- welches Recht gilt dann? Partielle Unique-Indizes, weil NULL in einem
-- gewöhnlichen UNIQUE nicht mit sich selbst kollidiert.
CREATE UNIQUE INDEX idx_acl_user_folder ON acl_entries (subject_user_id, resource_folder_id)
WHERE subject_user_id IS NOT NULL AND resource_folder_id IS NOT NULL;
CREATE UNIQUE INDEX idx_acl_user_file ON acl_entries (subject_user_id, resource_file_id)
WHERE subject_user_id IS NOT NULL AND resource_file_id IS NOT NULL;
CREATE UNIQUE INDEX idx_acl_group_folder ON acl_entries (subject_group_id, resource_folder_id)
WHERE subject_group_id IS NOT NULL AND resource_folder_id IS NOT NULL;
CREATE UNIQUE INDEX idx_acl_group_file ON acl_entries (subject_group_id, resource_file_id)
WHERE subject_group_id IS NOT NULL AND resource_file_id IS NOT NULL;
-- Die Zugriffsprüfung läuft bei jedem Request; sie fragt nach Ressource.
CREATE INDEX idx_acl_folder ON acl_entries (resource_folder_id) WHERE resource_folder_id IS NOT NULL;
CREATE INDEX idx_acl_file ON acl_entries (resource_file_id) WHERE resource_file_id IS NOT NULL;
-- „Geteilt mit mir" fragt nach Empfänger.
CREATE INDEX idx_acl_subject_user ON acl_entries (subject_user_id) WHERE subject_user_id IS NOT NULL;
CREATE INDEX idx_acl_subject_group ON acl_entries (subject_group_id) WHERE subject_group_id IS NOT NULL;