package database import ( "database/sql" "fmt" _ "modernc.org/sqlite" ) // DB wraps the sqlite connection used by the whole application. type DB struct { *sql.DB } const schema = ` CREATE TABLE IF NOT EXISTS servers ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, interface_name TEXT NOT NULL UNIQUE, listen_port INTEGER NOT NULL, private_key TEXT NOT NULL, public_key TEXT NOT NULL, address_range TEXT NOT NULL, dns TEXT DEFAULT '', mtu INTEGER DEFAULT 1420, enabled INTEGER NOT NULL DEFAULT 1, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS peers ( id INTEGER PRIMARY KEY AUTOINCREMENT, server_id INTEGER NOT NULL REFERENCES servers(id) ON DELETE CASCADE, name TEXT NOT NULL, email TEXT DEFAULT '', public_key TEXT NOT NULL, private_key TEXT DEFAULT '', preshared_key TEXT DEFAULT '', allowed_ips TEXT NOT NULL, endpoint TEXT DEFAULT '', persistent_keepalive INTEGER DEFAULT 25, enabled INTEGER NOT NULL DEFAULT 1, expires_at DATETIME, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS audit_log ( id INTEGER PRIMARY KEY AUTOINCREMENT, actor TEXT NOT NULL, action TEXT NOT NULL, target TEXT NOT NULL, detail TEXT DEFAULT '', created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL UNIQUE, password_hash TEXT NOT NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_peers_server_id ON peers(server_id); ` // Open opens (creating if needed) the sqlite database at path and applies schema. func Open(path string) (*DB, error) { sqlDB, err := sql.Open("sqlite", path+"?_pragma=foreign_keys(1)") if err != nil { return nil, fmt.Errorf("open sqlite: %w", err) } if _, err := sqlDB.Exec(schema); err != nil { sqlDB.Close() return nil, fmt.Errorf("apply schema: %w", err) } return &DB{sqlDB}, nil } // LogAudit records an entry in the audit log. func (db *DB) LogAudit(actor, action, target, detail string) error { _, err := db.Exec(`INSERT INTO audit_log (actor, action, target, detail) VALUES (?, ?, ?, ?)`, actor, action, target, detail) return err }