#!/usr/bin/env python3 """Initialisiert die SQLite-Datenbank für den PoE Manager.""" 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")) conn = sqlite3.connect(DB_PATH) c = conn.cursor() # Zugangsdaten (wiederverwendbare SSH-Logins, mehrere Switche können sich # dieselben teilen; Passwort wird verschlüsselt gespeichert) c.execute(""" CREATE TABLE IF NOT EXISTS credentials ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL, username TEXT NOT NULL, password TEXT NOT NULL ); """) # Switches (Aruba-Switche) — referenzieren ihre Zugangsdaten statt sie # direkt zu speichern c.execute(""" CREATE TABLE IF NOT EXISTS switches ( hostname TEXT PRIMARY KEY, ip TEXT NOT NULL, ssh_port INTEGER, credential_id INTEGER, last_modified_by TEXT, last_modified_at TEXT, FOREIGN KEY (credential_id) REFERENCES credentials(id) ); """) # Devices c.execute(""" CREATE TABLE IF NOT EXISTS devices ( mac TEXT PRIMARY KEY, rpi_ip TEXT NOT NULL, switch_hostname TEXT, port TEXT, name TEXT NOT NULL, is_active INTEGER DEFAULT 1, last_modified_by TEXT, last_modified_at TEXT, FOREIGN KEY (switch_hostname) REFERENCES switches(hostname) ); """) # Benutzer c.execute(""" CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password TEXT NOT NULL, is_admin INTEGER DEFAULT 0, first_name TEXT, last_name TEXT, avatar_filename TEXT ); """) # Gruppen (Rechtesystem) — Admins besitzen ohnehin alle Rechte; Gruppen # dienen dazu, normalen Benutzern gezielt einzelne Verwaltungsrechte für # Devices/Switches zu geben, ohne sie zu Admins zu machen. c.execute(""" 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 ); """) # Welche Berechtigungen eine Gruppe gewährt (siehe app.py: PERMISSIONS) c.execute(""" CREATE TABLE IF NOT EXISTS group_permissions ( group_id INTEGER NOT NULL, permission TEXT NOT NULL, PRIMARY KEY (group_id, permission), FOREIGN KEY (group_id) REFERENCES groups(id) ); """) # Gruppenmitgliedschaft (ein Benutzer kann in mehreren Gruppen sein; # effektive Rechte = Vereinigung aller Gruppen) c.execute(""" CREATE TABLE IF NOT EXISTS user_groups ( user_id INTEGER NOT NULL, group_id INTEGER NOT NULL, PRIMARY KEY (user_id, group_id), FOREIGN KEY (user_id) REFERENCES users(id), FOREIGN KEY (group_id) REFERENCES groups(id) ); """) # Settings (z.B. Prüfintervall) c.execute(""" CREATE TABLE IF NOT EXISTS settings ( key TEXT PRIMARY KEY, value TEXT NOT NULL ); """) # DHCP: eigene Options-Definitionen (analog "Vordefinierte Optionen und # Werte" bei einem Windows-DHCP-Server) — Code/Name/Typ/Beschreibung. 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 ); """) # DHCP: Werte je Option — device_mac='' bedeutet global (gilt für den # ganzen Scope), ein gesetzter device_mac überschreibt den globalen Wert # für genau dieses Gerät. Bewusst '' statt NULL für den globalen Fall, # da SQLite NULL in UNIQUE-Constraints nicht als gleich behandelt (zwei # NULL-Zeilen wären sonst kein Konflikt) — mit '' funktioniert ON CONFLICT # zuverlässig für den Upsert des globalen Werts. c.execute(""" CREATE TABLE IF NOT EXISTS dhcp_option_values ( id INTEGER PRIMARY KEY AUTOINCREMENT, option_def_id INTEGER NOT NULL, device_mac TEXT NOT NULL DEFAULT '', value TEXT NOT NULL, FOREIGN KEY (option_def_id) REFERENCES dhcp_option_defs(id), UNIQUE (option_def_id, device_mac) ); """) # Änderungslog (Audit-Log) — wer hat wann was geändert. Bewusst OHNE # PoE-Neustarts (die stehen im Live-Log von poe.sh). c.execute(""" CREATE TABLE IF NOT EXISTS audit_log ( id INTEGER PRIMARY KEY AUTOINCREMENT, ts TEXT NOT NULL, username TEXT NOT NULL, action TEXT NOT NULL, target TEXT, details TEXT ); """) # Standard-Setting: Prüfintervall 5 Minuten (interval = Minuten, check_interval = Sekunden) c.execute("INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)", ("interval", "5")) c.execute("INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)", ("check_interval", "300")) # Standardgruppe 'Benutzer' — Systemgruppe (is_system), Name und Rechte # sind über die UI fest und nicht änderbar. Jeder neu angelegte (nicht-admin) # Benutzer landet automatisch darin (siehe app.py: users()). Der genaue # Rechtesatz muss mit DEFAULT_GROUP_PERMISSIONS in app.py übereinstimmen. cur = c.execute("INSERT OR IGNORE INTO groups (name, is_default, is_system) VALUES (?, 1, 1)", ("Benutzer",)) if cur.rowcount > 0: default_group_id = cur.lastrowid c.executemany( "INSERT OR IGNORE INTO group_permissions (group_id, permission) VALUES (?, ?)", [ (default_group_id, "devices_group.view"), (default_group_id, "devices.view"), (default_group_id, "switches.view"), (default_group_id, "logs_group.view"), (default_group_id, "logs_live.view"), ], ) conn.commit() conn.close() print(f"Datenbank '{DB_PATH}' wurde initialisiert inklusive Settings.")