107 lines
4.0 KiB
SQL
107 lines
4.0 KiB
SQL
-- =====================================================================
|
|
-- DOGFATHER UNIVERSE — Interner Bereich: Datenbankschema
|
|
-- Setzt "Geschuetzter_Zugang_Rollen_Benutzerverwaltung.pdf" um.
|
|
-- =====================================================================
|
|
|
|
-- Rollen: frei erstellbar/umbenennbar durch den Hauptadministrator (Owner).
|
|
-- Die Owner-Rolle selbst ist NICHT in dieser Tabelle — sie ist fest an das
|
|
-- POSTFACH_CODE-Secret gebunden und kann nicht gelöscht/verändert werden.
|
|
CREATE TABLE IF NOT EXISTS roles (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
permissions TEXT NOT NULL DEFAULT '[]', -- JSON-Array erlaubter Permission-Keys
|
|
created_at TEXT NOT NULL
|
|
);
|
|
|
|
-- Zugänge/Teammitglieder. Jede Person hat einen eigenen Code.
|
|
-- code_hash: SHA-256 für schnellen Login-Vergleich (nicht umkehrbar).
|
|
-- code_enc: AES-GCM verschlüsselter Klartext-Code, NUR vom Owner nach
|
|
-- Re-Auth entschlüsselbar (siehe crypto.js). Wird niemals an
|
|
-- andere Personen oder über die API an Nicht-Owner ausgegeben.
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
username TEXT NOT NULL UNIQUE,
|
|
email TEXT,
|
|
role_id TEXT REFERENCES roles(id),
|
|
code_hash TEXT,
|
|
code_enc TEXT,
|
|
status TEXT NOT NULL DEFAULT 'pending', -- pending | active | locked
|
|
note TEXT,
|
|
expires_at TEXT, -- NULL = dauerhaft
|
|
created_at TEXT NOT NULL,
|
|
created_by TEXT NOT NULL,
|
|
last_login_at TEXT
|
|
);
|
|
|
|
-- Individuelle Berechtigungs-Ausnahmen pro Person (haben Vorrang vor der Rolle).
|
|
CREATE TABLE IF NOT EXISTS user_permission_overrides (
|
|
user_id TEXT NOT NULL REFERENCES users(id),
|
|
permission TEXT NOT NULL,
|
|
allowed INTEGER NOT NULL, -- 1 = zusätzlich erlaubt, 0 = entzogen
|
|
PRIMARY KEY (user_id, permission)
|
|
);
|
|
|
|
-- Sessions: token wird gehasht gespeichert (wie ein Passwort), nie im Klartext.
|
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
token_hash TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL, -- 'owner' oder users.id
|
|
is_owner INTEGER NOT NULL DEFAULT 0,
|
|
created_at TEXT NOT NULL,
|
|
last_active_at TEXT NOT NULL,
|
|
expires_at TEXT NOT NULL
|
|
);
|
|
|
|
-- Aktivitätsprotokoll — Codes erscheinen hier NIEMALS im Klartext.
|
|
CREATE TABLE IF NOT EXISTS audit_log (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
actor TEXT NOT NULL,
|
|
action TEXT NOT NULL,
|
|
target TEXT,
|
|
detail TEXT,
|
|
created_at TEXT NOT NULL
|
|
);
|
|
|
|
-- Login-Schutz: Fehlversuche pro Schlüssel (IP oder Benutzername) zählen,
|
|
-- nach zu vielen Versuchen vorübergehend sperren.
|
|
CREATE TABLE IF NOT EXISTS login_attempts (
|
|
key TEXT PRIMARY KEY,
|
|
count INTEGER NOT NULL DEFAULT 0,
|
|
locked_until TEXT,
|
|
updated_at TEXT NOT NULL
|
|
);
|
|
|
|
-- Bewerbungen (bisher in KV, jetzt in D1 für Status/Zuweisung/Notizen/Entwürfe).
|
|
CREATE TABLE IF NOT EXISTS applications (
|
|
id TEXT PRIMARY KEY,
|
|
type TEXT NOT NULL, -- creator | scout | kooperation
|
|
data TEXT NOT NULL, -- JSON der Formularfelder
|
|
status TEXT NOT NULL DEFAULT 'neu', -- neu | in_bearbeitung | beantwortet
|
|
assigned_to TEXT, -- users.id oder 'owner'
|
|
archived INTEGER NOT NULL DEFAULT 0,
|
|
created_at TEXT NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS application_notes (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
application_id TEXT NOT NULL REFERENCES applications(id),
|
|
author TEXT NOT NULL,
|
|
text TEXT NOT NULL,
|
|
created_at TEXT NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS application_drafts (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
application_id TEXT NOT NULL REFERENCES applications(id),
|
|
author TEXT NOT NULL,
|
|
content TEXT NOT NULL,
|
|
created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_sessions_user ON sessions(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_audit_created ON audit_log(created_at);
|
|
CREATE INDEX IF NOT EXISTS idx_applications_status ON applications(status, archived);
|
|
CREATE INDEX IF NOT EXISTS idx_notes_app ON application_notes(application_id);
|
|
CREATE INDEX IF NOT EXISTS idx_drafts_app ON application_drafts(application_id);
|