Files
atlas/internal/db/db.go
othman.suseno 54e76d9304
Some checks failed
CI / test-build (push) Failing after 2m1s
add authentication method
2025-12-14 23:55:12 +07:00

167 lines
4.0 KiB
Go

package db
import (
"database/sql"
"fmt"
"os"
"path/filepath"
_ "modernc.org/sqlite"
)
// DB wraps a database connection
type DB struct {
*sql.DB
}
// New creates a new database connection
func New(dbPath string) (*DB, error) {
// Ensure directory exists
dir := filepath.Dir(dbPath)
if err := os.MkdirAll(dir, 0755); err != nil {
return nil, fmt.Errorf("create db directory: %w", err)
}
conn, err := sql.Open("sqlite", dbPath+"?_foreign_keys=1")
if err != nil {
return nil, fmt.Errorf("open database: %w", err)
}
db := &DB{DB: conn}
// Test connection
if err := db.Ping(); err != nil {
return nil, fmt.Errorf("ping database: %w", err)
}
// Run migrations
if err := db.migrate(); err != nil {
return nil, fmt.Errorf("migrate database: %w", err)
}
return db, nil
}
// migrate runs database migrations
func (db *DB) migrate() error {
schema := `
-- Users table
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
username TEXT UNIQUE NOT NULL,
email TEXT,
password_hash TEXT NOT NULL,
role TEXT NOT NULL,
active INTEGER NOT NULL DEFAULT 1,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
-- Audit logs table
CREATE TABLE IF NOT EXISTS audit_logs (
id TEXT PRIMARY KEY,
actor TEXT NOT NULL,
action TEXT NOT NULL,
resource TEXT NOT NULL,
result TEXT NOT NULL,
message TEXT,
ip TEXT,
user_agent TEXT,
timestamp TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_audit_actor ON audit_logs(actor);
CREATE INDEX IF NOT EXISTS idx_audit_action ON audit_logs(action);
CREATE INDEX IF NOT EXISTS idx_audit_resource ON audit_logs(resource);
CREATE INDEX IF NOT EXISTS idx_audit_timestamp ON audit_logs(timestamp);
-- SMB shares table
CREATE TABLE IF NOT EXISTS smb_shares (
id TEXT PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
path TEXT NOT NULL,
dataset TEXT NOT NULL,
description TEXT,
read_only INTEGER NOT NULL DEFAULT 0,
guest_ok INTEGER NOT NULL DEFAULT 0,
enabled INTEGER NOT NULL DEFAULT 1
);
-- SMB share valid users (many-to-many)
CREATE TABLE IF NOT EXISTS smb_share_users (
share_id TEXT NOT NULL,
username TEXT NOT NULL,
PRIMARY KEY (share_id, username),
FOREIGN KEY (share_id) REFERENCES smb_shares(id) ON DELETE CASCADE
);
-- NFS exports table
CREATE TABLE IF NOT EXISTS nfs_exports (
id TEXT PRIMARY KEY,
path TEXT UNIQUE NOT NULL,
dataset TEXT NOT NULL,
read_only INTEGER NOT NULL DEFAULT 0,
root_squash INTEGER NOT NULL DEFAULT 1,
enabled INTEGER NOT NULL DEFAULT 1
);
-- NFS export clients (many-to-many)
CREATE TABLE IF NOT EXISTS nfs_export_clients (
export_id TEXT NOT NULL,
client TEXT NOT NULL,
PRIMARY KEY (export_id, client),
FOREIGN KEY (export_id) REFERENCES nfs_exports(id) ON DELETE CASCADE
);
-- iSCSI targets table
CREATE TABLE IF NOT EXISTS iscsi_targets (
id TEXT PRIMARY KEY,
iqn TEXT UNIQUE NOT NULL,
enabled INTEGER NOT NULL DEFAULT 1
);
-- iSCSI target initiators (many-to-many)
CREATE TABLE IF NOT EXISTS iscsi_target_initiators (
target_id TEXT NOT NULL,
initiator TEXT NOT NULL,
PRIMARY KEY (target_id, initiator),
FOREIGN KEY (target_id) REFERENCES iscsi_targets(id) ON DELETE CASCADE
);
-- iSCSI LUNs table
CREATE TABLE IF NOT EXISTS iscsi_luns (
target_id TEXT NOT NULL,
lun_id INTEGER NOT NULL,
zvol TEXT NOT NULL,
size INTEGER NOT NULL,
backend TEXT NOT NULL DEFAULT 'zvol',
PRIMARY KEY (target_id, lun_id),
FOREIGN KEY (target_id) REFERENCES iscsi_targets(id) ON DELETE CASCADE
);
-- Snapshot policies table
CREATE TABLE IF NOT EXISTS snapshot_policies (
id TEXT PRIMARY KEY,
dataset TEXT NOT NULL,
schedule_type TEXT NOT NULL,
schedule_value TEXT,
retention_count INTEGER,
retention_days INTEGER,
enabled INTEGER NOT NULL DEFAULT 1,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_snapshot_policy_dataset ON snapshot_policies(dataset);
`
if _, err := db.Exec(schema); err != nil {
return fmt.Errorf("create schema: %w", err)
}
return nil
}
// Close closes the database connection
func (db *DB) Close() error {
return db.DB.Close()
}