88 lines
2.1 KiB
Go
88 lines
2.1 KiB
Go
package settings
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"time"
|
|
|
|
"github.com/jmoiron/sqlx"
|
|
|
|
"github.com/kandev/kandev/internal/db"
|
|
"github.com/kandev/kandev/internal/db/dialect"
|
|
)
|
|
|
|
// Store persists install-wide Kandev settings that are not scoped to a user,
|
|
// workspace, agent profile, or integration.
|
|
type Store struct {
|
|
db *sqlx.DB
|
|
ro *sqlx.DB
|
|
}
|
|
|
|
func NewStore(pool *db.Pool) (*Store, error) {
|
|
store := &Store{db: pool.Writer(), ro: pool.Reader()}
|
|
if err := store.initSchema(); err != nil {
|
|
return nil, err
|
|
}
|
|
return store, nil
|
|
}
|
|
|
|
func (s *Store) initSchema() error {
|
|
if _, err := s.db.Exec(`
|
|
CREATE TABLE IF NOT EXISTS settings (
|
|
key TEXT PRIMARY KEY,
|
|
value TEXT NOT NULL,
|
|
updated_at TIMESTAMP NOT NULL
|
|
);
|
|
`); err != nil {
|
|
return err
|
|
}
|
|
return s.migrateLegacySystemSettings()
|
|
}
|
|
|
|
func (s *Store) migrateLegacySystemSettings() error {
|
|
if dialect.IsPostgres(s.db.DriverName()) {
|
|
return nil
|
|
}
|
|
|
|
var exists int
|
|
if err := s.db.QueryRow(`
|
|
SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name = 'system_settings'
|
|
`).Scan(&exists); err != nil {
|
|
return err
|
|
}
|
|
if exists == 0 {
|
|
return nil
|
|
}
|
|
_, err := s.db.Exec(`
|
|
INSERT OR IGNORE INTO settings (key, value, updated_at)
|
|
SELECT key, value, updated_at FROM system_settings
|
|
`)
|
|
return err
|
|
}
|
|
|
|
func (s *Store) Get(ctx context.Context, key string) ([]byte, bool, error) {
|
|
var raw string
|
|
err := s.ro.QueryRowContext(ctx, s.ro.Rebind(`SELECT value FROM settings WHERE key = ?`), key).Scan(&raw)
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, false, nil
|
|
}
|
|
return nil, false, err
|
|
}
|
|
return []byte(raw), true, nil
|
|
}
|
|
|
|
func (s *Store) Save(ctx context.Context, key string, value []byte) error {
|
|
_, err := s.db.ExecContext(ctx, s.db.Rebind(`
|
|
INSERT INTO settings (key, value, updated_at)
|
|
VALUES (?, ?, ?)
|
|
ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at
|
|
`), key, string(value), time.Now().UTC())
|
|
return err
|
|
}
|
|
|
|
func (s *Store) Delete(ctx context.Context, key string) error {
|
|
_, err := s.db.ExecContext(ctx, s.db.Rebind(`DELETE FROM settings WHERE key = ?`), key)
|
|
return err
|
|
}
|