add admin stuff

This commit is contained in:
2026-08-20 10:43:19 +02:00
parent 7108d446d8
commit 91758a2701
19 changed files with 2514 additions and 85 deletions

View File

@ -0,0 +1,35 @@
-- Benutzergruppen (Teams): Rollen koennen einer ganzen Gruppe auf einer
-- Hostgruppe gewaehrt werden ("Verbindungen mit einer Gruppe teilen"),
-- statt jedes Mitglied einzeln ueber user_hostgroup_roles pflegen zu
-- muessen. Volle Rollen-Vererbung: jedes aktuelle und zukuenftige
-- Mitglied der Gruppe erhaelt automatisch alle der Gruppe gewaehrten
-- Rollen (Durchsetzung in app/rbac.py: user_has_role() vereinigt direkte
-- User-Grants mit Grants ueber Gruppenmitgliedschaft).
CREATE TABLE IF NOT EXISTS user_groups (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
description TEXT,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
);
CREATE TABLE IF NOT EXISTS user_group_members (
user_group_id INTEGER NOT NULL REFERENCES user_groups(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
added_by INTEGER REFERENCES users(id),
added_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
PRIMARY KEY (user_group_id, user_id)
);
CREATE INDEX IF NOT EXISTS idx_ugm_user ON user_group_members(user_id);
CREATE TABLE IF NOT EXISTS group_hostgroup_roles (
user_group_id INTEGER NOT NULL REFERENCES user_groups(id) ON DELETE CASCADE,
host_group_id INTEGER NOT NULL REFERENCES host_groups(id) ON DELETE CASCADE,
role_id INTEGER NOT NULL REFERENCES roles(id),
granted_by INTEGER REFERENCES users(id),
granted_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
expires_at TEXT,
PRIMARY KEY (user_group_id, host_group_id, role_id)
);
CREATE INDEX IF NOT EXISTS idx_ghr_group ON group_hostgroup_roles(user_group_id);
CREATE INDEX IF NOT EXISTS idx_ghr_hostgroup ON group_hostgroup_roles(host_group_id);

View File

@ -0,0 +1,26 @@
-- API-Tokens mit granularem Scope (ro/rw je Ressourcengruppe) fuer
-- programmatischen Zugriff auf die Admin-/Verwaltungs-API, unabhaengig von
-- der Browser-Session. Bewusst NICHT nutzbar fuer SSH/RDP/SFTP-Sitzungen
-- selbst (Terminal-/RDP-WebSocket und Dateitransfer bleiben ausschliesslich
-- an eine eingeloggte, TOTP-verifizierte Session gebunden -- siehe
-- app/auth/deps.py) und NICHT nutzbar, um weitere Tokens zu verwalten
-- (Privilege-Escalation-Schutz: Token-Verwaltung selbst bleibt reine
-- Session-Admin-Aktion).
--
-- Nur der Hash des Tokens wird gespeichert (siehe app/security/api_tokens.py,
-- analog zu Recovery-Codes); das Klartext-Token wird nur einmalig bei der
-- Erzeugung angezeigt und ist danach nicht mehr rekonstruierbar.
CREATE TABLE IF NOT EXISTS api_tokens (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
label TEXT NOT NULL,
token_hash TEXT NOT NULL UNIQUE,
token_prefix TEXT NOT NULL,
scopes_json TEXT NOT NULL,
created_by INTEGER REFERENCES users(id),
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
expires_at TEXT,
last_used_at TEXT,
revoked_at TEXT
);
CREATE INDEX IF NOT EXISTS idx_api_tokens_user ON api_tokens(user_id);