feat(store): open encrypted SQLite, schema v1, settings
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
// Package store owns the encrypted SQLite config and read state.
|
||||
package store
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
// Store wraps the database and the field-encryption key.
|
||||
type Store struct {
|
||||
db *sql.DB
|
||||
key []byte
|
||||
}
|
||||
|
||||
// Open opens (creating if needed) the DB at path and applies the schema.
|
||||
func Open(path string, key []byte) (*Store, error) {
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
|
||||
return nil, fmt.Errorf("create db dir: %w", err)
|
||||
}
|
||||
db, err := sql.Open("sqlite", path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := db.Exec("PRAGMA foreign_keys = ON;"); err != nil {
|
||||
db.Close()
|
||||
return nil, err
|
||||
}
|
||||
if _, err := db.Exec(schemaSQL); err != nil {
|
||||
db.Close()
|
||||
return nil, fmt.Errorf("apply schema: %w", err)
|
||||
}
|
||||
s := &Store{db: db, key: key}
|
||||
if _, err := s.GetSetting("schema_version"); err != nil {
|
||||
if err := s.SetSetting("schema_version", strconv.Itoa(schemaVersion)); err != nil {
|
||||
db.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *Store) Close() error { return s.db.Close() }
|
||||
|
||||
// DefaultDBPath resolves EMCLI_DB or the per-OS default location.
|
||||
func DefaultDBPath() (string, error) {
|
||||
if p := os.Getenv("EMCLI_DB"); p != "" {
|
||||
return p, nil
|
||||
}
|
||||
if runtime.GOOS == "windows" {
|
||||
if dir := os.Getenv("AppData"); dir != "" {
|
||||
return filepath.Join(dir, "emcli", "emcli.db"), nil
|
||||
}
|
||||
}
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(home, ".config", "emcli", "emcli.db"), nil
|
||||
}
|
||||
Reference in New Issue
Block a user