diff --git a/srv/tesm/create_admin.py b/srv/tesm/create_admin.py index 387aadc..c1338af 100644 --- a/srv/tesm/create_admin.py +++ b/srv/tesm/create_admin.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 -"""Legt einen Admin-Benutzer im PoE Manager an.""" +"""Legt einen Admin-Benutzer in TESM an.""" import os import sqlite3 from getpass import getpass from flask_bcrypt import Bcrypt BASE_DIR = os.path.dirname(os.path.abspath(__file__)) -DB_PATH = os.environ.get("POE_DB_PATH", os.path.join(BASE_DIR, "sqlite.db")) +DB_PATH = os.environ.get("TESM_DB_PATH", os.path.join(BASE_DIR, "sqlite.db")) bcrypt = Bcrypt() diff --git a/srv/tesm/create_db.py b/srv/tesm/create_db.py index e96670f..9d870cb 100644 --- a/srv/tesm/create_db.py +++ b/srv/tesm/create_db.py @@ -4,7 +4,7 @@ import os import sqlite3 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) -DB_PATH = os.environ.get("POE_DB_PATH", os.path.join(BASE_DIR, "sqlite.db")) +DB_PATH = os.environ.get("TESM_DB_PATH", os.path.join(BASE_DIR, "sqlite.db")) conn = sqlite3.connect(DB_PATH) c = conn.cursor() @@ -16,7 +16,9 @@ CREATE TABLE IF NOT EXISTS credentials ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL, username TEXT NOT NULL, - password TEXT NOT NULL + password TEXT NOT NULL, + category TEXT NOT NULL DEFAULT 'switch', + deleted_at TEXT ); """) @@ -30,6 +32,7 @@ CREATE TABLE IF NOT EXISTS switches ( credential_id INTEGER, last_modified_by TEXT, last_modified_at TEXT, + deleted_at TEXT, FOREIGN KEY (credential_id) REFERENCES credentials(id) ); """) @@ -45,6 +48,9 @@ CREATE TABLE IF NOT EXISTS devices ( is_active INTEGER DEFAULT 1, last_modified_by TEXT, last_modified_at TEXT, + credential_id INTEGER, + ssh_port INTEGER, + deleted_at TEXT, FOREIGN KEY (switch_hostname) REFERENCES switches(hostname) ); """) @@ -61,7 +67,8 @@ CREATE TABLE IF NOT EXISTS users ( avatar_filename TEXT, auth_source TEXT NOT NULL DEFAULT 'local', email TEXT, - is_locked INTEGER NOT NULL DEFAULT 0 + is_locked INTEGER NOT NULL DEFAULT 0, + deleted_at TEXT ); """) @@ -73,7 +80,8 @@ CREATE TABLE IF NOT EXISTS groups ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL, is_default INTEGER DEFAULT 0, - is_system INTEGER DEFAULT 0 + is_system INTEGER DEFAULT 0, + deleted_at TEXT ); """) @@ -109,13 +117,17 @@ CREATE TABLE IF NOT EXISTS settings ( # DHCP: eigene Options-Definitionen (analog "Vordefinierte Optionen und # Werte" bei einem Windows-DHCP-Server) — Code/Name/Typ/Beschreibung. +# is_standard markiert die vorbefüllten Standard-Optionen (Router/DNS/…) -- +# die können vom Admin nicht gelöscht werden, nur ihr Wert geleert (die +# tatsächliche Vorbefüllung übernimmt app.py: _ensure_schema()). c.execute(""" CREATE TABLE IF NOT EXISTS dhcp_option_defs ( id INTEGER PRIMARY KEY AUTOINCREMENT, code INTEGER NOT NULL UNIQUE, name TEXT NOT NULL UNIQUE, type TEXT NOT NULL, - description TEXT + description TEXT, + is_standard INTEGER NOT NULL DEFAULT 0 ); """) @@ -136,6 +148,63 @@ CREATE TABLE IF NOT EXISTS dhcp_option_values ( ); """) +# DHCP: konfigurierte Subnetze (Interface + Range + optionales Gateway/DNS) +# -- ein Host kann mehrere Subnetze gleichzeitig bedienen, je eines pro +# Interface/Netz. sort_order steuert die Anzeige-/Verarbeitungsreihenfolge, +# enabled erlaubt ein Subnetz vorübergehend aus der geschriebenen +# Konfiguration auszuschließen, ohne es zu löschen. +c.execute(""" +CREATE TABLE IF NOT EXISTS dhcp_subnets ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + interface TEXT NOT NULL, + range_start TEXT NOT NULL, + range_end TEXT NOT NULL, + gateway TEXT, + dns TEXT, + sort_order INTEGER NOT NULL DEFAULT 0, + enabled INTEGER NOT NULL DEFAULT 1 +); +""") + +# DHCP: manuelle Reservierungen für Geräte OHNE eigenen Client-Datensatz +# (Geräte mit MAC+IP in der devices-Tabelle bekommen ihre Reservierung +# automatisch, siehe _dhcp_reservation_candidates in app.py). +c.execute(""" +CREATE TABLE IF NOT EXISTS dhcp_manual_reservations ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + mac TEXT NOT NULL UNIQUE, + ip TEXT NOT NULL, + name TEXT NOT NULL +); +""") + +# Service-Accounts (aktuell nur das LDAP-Bind-Konto) -- bewusst NICHT in der +# users-Tabelle (kein echter, einloggbarer App-Benutzer) und NICHT in der +# credentials-Tabelle (die ist für Switch-/Geräte-Zugangsdaten, ein anderer +# Anwendungsfall) -- eine eigene, kleine Tabelle. "purpose" ist UNIQUE, ein +# neu gespeichertes Konto für denselben Zweck ersetzt das alte. +c.execute(""" +CREATE TABLE IF NOT EXISTS service_accounts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + purpose TEXT UNIQUE NOT NULL, + username TEXT NOT NULL, + password TEXT NOT NULL +); +""") + +# AD-Gruppe -> App-Rechtegruppe: mehrere AD-Gruppen können jeweils einer +# App-Gruppe zugeordnet werden (additiv, siehe _ldap_resolve_app_groups in +# app.py) -- passt keine dieser Gruppen, greift die Standardgruppe. +c.execute(""" +CREATE TABLE IF NOT EXISTS ldap_group_mappings ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + ad_group_dn TEXT UNIQUE NOT NULL, + ad_group_name TEXT NOT NULL, + app_group_id INTEGER NOT NULL, + FOREIGN KEY (app_group_id) REFERENCES groups(id) +); +""") + # Änderungslog (Audit-Log) — wer hat wann was geändert. Bewusst OHNE # PoE-Neustarts (die stehen im Live-Log von poe.sh). c.execute("""