more admin stuff
This commit is contained in:
65
app/db/migrations/0006_tenants.sql
Normal file
65
app/db/migrations/0006_tenants.sql
Normal file
@ -0,0 +1,65 @@
|
||||
-- Mandantenfaehigkeit (volle Isolation, siehe Konzept-Erweiterung dieser
|
||||
-- Session): jede Hostgruppe, Benutzergruppe, jeder SSH-Key und jedes
|
||||
-- API-Token gehoert genau einem Mandanten. Ein Benutzer kann Mandanten-Admin
|
||||
-- fuer einen oder mehrere Mandanten sein (tenant_admins) -- er sieht/
|
||||
-- verwaltet dann AUSSCHLIESSLICH Ressourcen seines/seiner Mandanten
|
||||
-- (Durchsetzung zentral in app/tenancy.py + app/auth/deps.py, angewendet in
|
||||
-- jedem Endpunkt in app/admin/routes.py). Das bestehende users.is_admin
|
||||
-- bleibt unveraendert bestehen und wird zum "Super-Admin": sieht/verwaltet
|
||||
-- weiterhin ALLE Mandanten uebergreifend (volle Abwaertskompatibilitaet zu
|
||||
-- allen bisherigen Admin-Workflows dieser App).
|
||||
--
|
||||
-- Rueckwirkende Kompatibilitaet: ein Standard-Mandant (id=1) wird automatisch
|
||||
-- angelegt und alle VOR dieser Migration bestehenden Hostgruppen/
|
||||
-- Benutzergruppen/SSH-Keys/API-Tokens werden ihm zugeordnet -- fuer
|
||||
-- Super-Admins aendert sich dadurch am sichtbaren Verhalten nichts.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tenants (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
|
||||
);
|
||||
INSERT OR IGNORE INTO tenants (id, name, description) VALUES
|
||||
(1, 'Standard', 'Automatisch angelegter Standard-Mandant (Daten von vor der Einfuehrung der Mandantenfaehigkeit).');
|
||||
|
||||
-- Mandanten-Admin-Zuweisung ist bewusst eine eigene Tabelle (statt eines
|
||||
-- einzelnen users.tenant_id) -- ein User kann Mandanten-Admin fuer MEHRERE
|
||||
-- Mandanten sein (z.B. externer Dienstleister fuer mehrere Kunden), ohne
|
||||
-- gleich globaler Super-Admin zu sein. Nur ein Super-Admin darf diese
|
||||
-- Zuweisung vornehmen (require_global_admin, siehe admin/routes.py).
|
||||
CREATE TABLE IF NOT EXISTS tenant_admins (
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
tenant_id INTEGER NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
granted_by INTEGER REFERENCES users(id),
|
||||
granted_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
|
||||
PRIMARY KEY (user_id, tenant_id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_tenant_admins_user ON tenant_admins(user_id);
|
||||
|
||||
ALTER TABLE host_groups ADD COLUMN tenant_id INTEGER NOT NULL DEFAULT 1 REFERENCES tenants(id);
|
||||
ALTER TABLE user_groups ADD COLUMN tenant_id INTEGER NOT NULL DEFAULT 1 REFERENCES tenants(id);
|
||||
ALTER TABLE ssh_keys ADD COLUMN tenant_id INTEGER NOT NULL DEFAULT 1 REFERENCES tenants(id);
|
||||
-- api_tokens: bewusst NICHT nullable -- jedes Token (auch von einem
|
||||
-- Super-Admin erzeugte) ist genau einem Mandanten zugeordnet. Ein Token ist
|
||||
-- (wie schon vor dieser Migration) nie is_admin=True; ohne verpflichtenden
|
||||
-- Mandantenbezug waere unklar, welche Mandanten-Ressourcen es sehen darf --
|
||||
-- lieber explizit pro Mandant ein Token ausstellen als eine mehrdeutige
|
||||
-- "gilt ueberall"-Sonderregel einzufuehren (Prinzip: fail closed).
|
||||
ALTER TABLE api_tokens ADD COLUMN tenant_id INTEGER NOT NULL DEFAULT 1 REFERENCES tenants(id);
|
||||
|
||||
-- users.home_tenant_id: rein informativ/UX -- der Mandant, "fuer" den ein
|
||||
-- Benutzer angelegt wurde (automatisch gesetzt, wenn ein Mandanten-Admin den
|
||||
-- User anlegt), damit ein frisch angelegter User sofort in der Mandanten-
|
||||
-- Admin-Sicht auftaucht, auch bevor er einer Gruppe zugeordnet oder ihm eine
|
||||
-- Rolle gewaehrt wurde. Erzwingt KEINE Zugriffsbeschraenkung selbst -- die
|
||||
-- eigentliche Sichtbarkeit/Isolation ergibt sich weiterhin aus Rollen-
|
||||
-- Vergabe auf Hostgruppen eines Mandanten (siehe app/tenancy.py).
|
||||
ALTER TABLE users ADD COLUMN home_tenant_id INTEGER REFERENCES tenants(id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_host_groups_tenant ON host_groups(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_groups_tenant ON user_groups(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_ssh_keys_tenant ON ssh_keys(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_tokens_tenant ON api_tokens(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_users_home_tenant ON users(home_tenant_id);
|
||||
14
app/db/migrations/0007_crud_extras.sql
Normal file
14
app/db/migrations/0007_crud_extras.sql
Normal file
@ -0,0 +1,14 @@
|
||||
-- Ergaenzung fuer vollstaendige Loesch-/Editierbarkeit (siehe app/admin/routes.py):
|
||||
--
|
||||
-- users.deleted_at: ein Benutzerkonto kann nicht immer per hartem SQL-DELETE
|
||||
-- entfernt werden, weil audit_log.user_id (bewusst, siehe 0001_initial.sql)
|
||||
-- OHNE ON DELETE CASCADE auf users(id) verweist -- das manipulationssichere
|
||||
-- Audit-Log darf durch das Loeschen eines Kontos nicht nachtraeglich
|
||||
-- veraendert oder seiner Zuordnung beraubt werden (jede Aenderung an
|
||||
-- audit_log-Zeilen wuerde die Hash-Chain brechen bzw. ist durch DB-Trigger
|
||||
-- ohnehin hart verboten). Ein Konto mit vorhandener Audit-Historie (praktisch
|
||||
-- jedes jemals eingeloggte Konto) wird deshalb beim "Loeschen" stattdessen
|
||||
-- deaktiviert, anonymisiert (Benutzername/Passwort/TOTP-Secret geloescht)
|
||||
-- und hier markiert; nur ein Konto OHNE jede Audit-Historie wird tatsaechlich
|
||||
-- per SQL-DELETE entfernt. Siehe delete_user() in app/admin/routes.py.
|
||||
ALTER TABLE users ADD COLUMN deleted_at TEXT;
|
||||
Reference in New Issue
Block a user