0bc9160d97
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
58 lines
1.3 KiB
Go
58 lines
1.3 KiB
Go
package db
|
|
|
|
import (
|
|
"database/sql"
|
|
_ "embed"
|
|
"fmt"
|
|
|
|
_ "modernc.org/sqlite"
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
|
"qbank/internal/config"
|
|
)
|
|
|
|
//go:embed schema.sql
|
|
var schema string
|
|
|
|
func Open(path string) (*sql.DB, error) {
|
|
db, err := sql.Open("sqlite", path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("open sqlite: %w", err)
|
|
}
|
|
db.SetMaxOpenConns(1)
|
|
for _, stmt := range []string{
|
|
"PRAGMA journal_mode=WAL",
|
|
"PRAGMA foreign_keys=ON",
|
|
} {
|
|
if _, err := db.Exec(stmt); err != nil {
|
|
db.Close()
|
|
return nil, fmt.Errorf("pragma %q: %w", stmt, err)
|
|
}
|
|
}
|
|
if _, err := db.Exec(schema); err != nil {
|
|
db.Close()
|
|
return nil, fmt.Errorf("apply schema: %w", err)
|
|
}
|
|
return db, nil
|
|
}
|
|
|
|
func Seed(db *sql.DB, users []config.AdminUser) error {
|
|
var count int
|
|
if err := db.QueryRow("SELECT COUNT(*) FROM users").Scan(&count); err != nil {
|
|
return fmt.Errorf("count users: %w", err)
|
|
}
|
|
if count > 0 {
|
|
return nil
|
|
}
|
|
for _, u := range users {
|
|
hash, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
return fmt.Errorf("hash password for %q: %w", u.Name, err)
|
|
}
|
|
if _, err := db.Exec("INSERT INTO users (name, password_hash) VALUES (?, ?)", u.Name, string(hash)); err != nil {
|
|
return fmt.Errorf("insert user %q: %w", u.Name, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|