65 lines
3.3 KiB
SQL
65 lines
3.3 KiB
SQL
-- Migration 0017: persoenliche Gruppen als rechteerhaltende Migration weg
|
|
-- von Direktvergaben (user_hostgroup_roles) -- Teil D.6 Schritt 3, D.4
|
|
-- (Umsetzungsauftrag_Sonnet5.md). Empfohlener Ansatz dort: "automatisch
|
|
-- erzeugte persoenliche Gruppe je betroffenem Benutzer, danach manuelle
|
|
-- Konsolidierung" -- niemand verliert oder gewinnt beim Umstieg etwas.
|
|
--
|
|
-- user_hostgroup_roles bleibt nach dieser Migration bestehen (Projekt-
|
|
-- konvention: Altes bleibt lesbar erhalten statt geloescht, siehe 0010/0012)
|
|
-- und wird auch weiterhin von app/rbac.py ausgewertet -- das Leeren/
|
|
-- Umbenennen dieser Tabelle ist D.6 Schritt 5 (Schreibpfade abschalten),
|
|
-- NICHT dieser Schritt. Diese Migration fuegt nur die Gruppen-Spiegelung
|
|
-- HINZU, sie nimmt niemandem etwas weg.
|
|
|
|
-- D.7-Risiko "Rechteausweitung ueber persoenliche Gruppen": Kennzeichen
|
|
-- "persoenlich" (fuer UI/Reports in Schritt 6) plus Trigger-Sperre "max. 1
|
|
-- Mitglied" weiter unten. ADD COLUMN mit konstantem Default ist in SQLite
|
|
-- ohne Tabellen-Rebuild moeglich.
|
|
ALTER TABLE user_groups ADD COLUMN is_personal INTEGER NOT NULL DEFAULT 0;
|
|
|
|
CREATE TRIGGER IF NOT EXISTS enforce_personal_group_single_member
|
|
BEFORE INSERT ON user_group_members
|
|
FOR EACH ROW
|
|
WHEN (SELECT is_personal FROM user_groups WHERE id = NEW.user_group_id) = 1
|
|
AND (SELECT COUNT(*) FROM user_group_members WHERE user_group_id = NEW.user_group_id) >= 1
|
|
BEGIN
|
|
SELECT RAISE(ABORT, 'Persoenliche Gruppe darf nur ein Mitglied haben');
|
|
END;
|
|
|
|
-- Eine persoenliche Gruppe je Benutzer mit mindestens einer Direktvergabe.
|
|
-- Name enthaelt bewusst die User-ID (nicht nur den Benutzernamen), um jede
|
|
-- Kollision mit einer bereits existierenden, gleichnamigen Gruppe
|
|
-- auszuschliessen (user_groups.name ist UNIQUE NOT NULL) -- ein Fehlschlag
|
|
-- hier wuerde die gesamte Migration abbrechen. Explizite Transaktion fuer
|
|
-- Atomaritaet (alle drei INSERTs oder keiner) -- anders als 0014 wird hier
|
|
-- nichts umgebaut/gedroppt, PRAGMA foreign_keys = OFF ist daher nicht noetig
|
|
-- (keine der drei INSERT-Anweisungen kann eine gueltige Fremdschluessel-
|
|
-- Referenz verletzen).
|
|
BEGIN IMMEDIATE;
|
|
|
|
INSERT INTO user_groups (name, description, is_personal)
|
|
SELECT 'Persoenlich: ' || u.username || ' (#' || u.id || ')',
|
|
'Automatisch erzeugt bei der Migration auf ausschliesslich '
|
|
|| 'gruppenbasierte Berechtigungen (Teil D.6 Schritt 3, Migration '
|
|
|| '0017) -- Spiegel der vormaligen Direktvergaben dieses Benutzers '
|
|
|| 'aus user_hostgroup_roles. Kann spaeter bewusst in eine echte '
|
|
|| 'Team-Gruppe ueberfuehrt werden (D.6 Schritt 6).',
|
|
1
|
|
FROM users u
|
|
WHERE u.id IN (SELECT DISTINCT user_id FROM user_hostgroup_roles)
|
|
AND u.deleted_at IS NULL;
|
|
|
|
INSERT INTO user_group_members (user_group_id, user_id, added_by, added_at)
|
|
SELECT ug.id, u.id, NULL, strftime('%Y-%m-%dT%H:%M:%fZ','now')
|
|
FROM user_groups ug
|
|
JOIN users u ON ug.name = 'Persoenlich: ' || u.username || ' (#' || u.id || ')'
|
|
WHERE ug.is_personal = 1;
|
|
|
|
INSERT INTO group_hostgroup_roles (user_group_id, host_group_id, role_id, granted_by, granted_at, expires_at)
|
|
SELECT ug.id, uhr.host_group_id, uhr.role_id, uhr.granted_by, uhr.granted_at, uhr.expires_at
|
|
FROM user_hostgroup_roles uhr
|
|
JOIN users u ON u.id = uhr.user_id
|
|
JOIN user_groups ug ON ug.name = 'Persoenlich: ' || u.username || ' (#' || u.id || ')' AND ug.is_personal = 1;
|
|
|
|
COMMIT;
|