umbau 1.0

This commit is contained in:
2026-09-02 20:30:44 +02:00
parent afe6719f51
commit 5c95b21be7
77 changed files with 10733 additions and 1914 deletions

View File

@ -0,0 +1,64 @@
-- 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;