package main import ( "database/sql" "embed" "fmt" "log/slog" "os" "path/filepath" "github.com/pressly/goose/v3" _ "modernc.org/sqlite" ) //go:embed migrations/*.sql var embedMigrations embed.FS // Create new sqlite database // If filepath parameter is empty func NewDatabaseConnection(dataDir string, dbName string) (*sql.DB, error) { var dbFilePath string if dbName == "" { dbFilePath = filepath.Join(dataDir, "app.db") } else { dbFilePath = filepath.Join(dataDir, filepath.Base(dbName)) } db, err := sql.Open("sqlite", dbFilePath) if err != nil { return nil, fmt.Errorf("database open error: %w", err) } if err := db.Ping(); err != nil { return nil, fmt.Errorf("database connection error: %w", err) } return db, nil } func MigrateDatabase(db *sql.DB) { dialect := "sqlite3" goose.SetBaseFS(embedMigrations) if err := goose.SetDialect(dialect); err != nil { slog.Error("Database dialect error", "dialect", dialect, "error", err) os.Exit(1) } if err := goose.Up(db, "migrations"); err != nil { slog.Error("Database migration error", "error", err) os.Exit(1) } migratedVersion, err := goose.GetDBVersion(db) if err != nil { slog.Error("Datatabase migration version check error", "error", err) os.Exit(1) } slog.Info("Database up to date", "version", migratedVersion) } func SeedDatabase(db *sql.DB, superadminPassword string) error { seededValue := "false" row := db.QueryRow("SELECT value FROM settings WHERE key='seeded';") _ = row.Scan(&seededValue) if seededValue == "true" { slog.Info("Database already seeded with default data, skipping") return nil } slog.Info("Database empty, seeding with default values") row = db.QueryRow("SELECT COUNT(*) FROM menu_items") var count int _ = row.Scan(&count) if count == 0 { slog.Info("Seeding default menu_items") defaults := []struct { category string name string }{ {"soup", "Erőleves"}, {"soup", "Dörgicsei Csibeleves"}, {"soup", "Újházi Tyúkhúsleves"}, {"soup", "Jókai Bableves"}, {"soup", "Tárkonyos Raguleves"}, {"soup", "Frankfurti Leves"}, {"soup", "Tavaszi Zöldségleves"}, {"soup", "Fokhagyma Krémleves"}, {"main", "Babragus Csülök"}, {"main", "Rántott Csirkemell"}, {"main", "Rántott Gomba és Rántott Camembert"}, {"main", "Cordon Bleu"}, {"main", "Cigánypecsenye Kakastaréjjal"}, {"main", "Mozzarellás-Paradicsomos Csirkemell Roston"}, {"main", "Kemencés Fokhagymás Csülökszeletek"}, {"main", "Holstein Szelet"}, {"main", "Jalapeños Sajtgolyók"}, {"main", "Cornflakes Bundában Sült Csirkemell"}, {"main", "Baconköntösben Pirított Csirkemáj"}, {"side", "Friss Saláta Kapros Joghurtos Öntettel"}, {"side", "Párolt Rizs"}, {"side", "Fűszeres Steakburgonya"}, {"side", "Grill Zöldség"}, {"side", "Lilahagymás Kukoricasaláta"}, } for _, d := range defaults { _, err := db.Exec("INSERT INTO menu_items (category, name) VALUES (?, ?)", d.category, d.name) if err != nil { return fmt.Errorf("Error seeding menu_items table: %w", err) } } } else { slog.Info("Table menu_items already seeded, skipping") } _, err := db.Exec(`INSERT OR REPLACE INTO settings (key, value) VALUES ('seeded', 'true')`) if err != nil { return fmt.Errorf("Error saving setting table: %w", err) } updateSuperadminPassword(db, superadminPassword) return nil } func updateSuperadminPassword(db *sql.DB, superadminPassword string) { _, err := db.Exec(`INSERT OR REPLACE INTO users (id, username, password, role) VALUES ( 1, 'superadmin', ?, COALESCE((SELECT role FROM users WHERE id = 1), '0') )`, superadminPassword) if err != nil { slog.Error("Error setting superadmin password", "error", err) } slog.Debug("Superadmin password", "password", superadminPassword) }