Provides CRUD operations on the module_state and settings_overrides tables (created in migration 016). - GetModuleStates / SetModuleState — upsert module enabled/disabled - GetOverrides / SetOverride / DeleteOverride — JSONB config overrides Part of #99
106 lines
3.1 KiB
Go
106 lines
3.1 KiB
Go
package db
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
)
|
|
|
|
// SettingsRepository provides access to module_state and settings_overrides tables.
|
|
type SettingsRepository struct {
|
|
db *DB
|
|
}
|
|
|
|
// NewSettingsRepository creates a new SettingsRepository.
|
|
func NewSettingsRepository(db *DB) *SettingsRepository {
|
|
return &SettingsRepository{db: db}
|
|
}
|
|
|
|
// GetModuleStates returns all module enabled/disabled states from the database.
|
|
func (r *SettingsRepository) GetModuleStates(ctx context.Context) (map[string]bool, error) {
|
|
rows, err := r.db.pool.Query(ctx,
|
|
`SELECT module_id, enabled FROM module_state`)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("querying module states: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
states := make(map[string]bool)
|
|
for rows.Next() {
|
|
var id string
|
|
var enabled bool
|
|
if err := rows.Scan(&id, &enabled); err != nil {
|
|
return nil, fmt.Errorf("scanning module state: %w", err)
|
|
}
|
|
states[id] = enabled
|
|
}
|
|
return states, rows.Err()
|
|
}
|
|
|
|
// SetModuleState persists a module's enabled state. Uses upsert semantics.
|
|
func (r *SettingsRepository) SetModuleState(ctx context.Context, moduleID string, enabled bool, updatedBy string) error {
|
|
_, err := r.db.pool.Exec(ctx,
|
|
`INSERT INTO module_state (module_id, enabled, updated_by, updated_at)
|
|
VALUES ($1, $2, $3, now())
|
|
ON CONFLICT (module_id) DO UPDATE
|
|
SET enabled = EXCLUDED.enabled,
|
|
updated_by = EXCLUDED.updated_by,
|
|
updated_at = now()`,
|
|
moduleID, enabled, updatedBy)
|
|
if err != nil {
|
|
return fmt.Errorf("setting module state: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetOverrides returns all settings overrides from the database.
|
|
func (r *SettingsRepository) GetOverrides(ctx context.Context) (map[string]json.RawMessage, error) {
|
|
rows, err := r.db.pool.Query(ctx,
|
|
`SELECT key, value FROM settings_overrides`)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("querying settings overrides: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
overrides := make(map[string]json.RawMessage)
|
|
for rows.Next() {
|
|
var key string
|
|
var value json.RawMessage
|
|
if err := rows.Scan(&key, &value); err != nil {
|
|
return nil, fmt.Errorf("scanning settings override: %w", err)
|
|
}
|
|
overrides[key] = value
|
|
}
|
|
return overrides, rows.Err()
|
|
}
|
|
|
|
// SetOverride persists a settings override. Uses upsert semantics.
|
|
func (r *SettingsRepository) SetOverride(ctx context.Context, key string, value any, updatedBy string) error {
|
|
jsonVal, err := json.Marshal(value)
|
|
if err != nil {
|
|
return fmt.Errorf("marshaling override value: %w", err)
|
|
}
|
|
_, err = r.db.pool.Exec(ctx,
|
|
`INSERT INTO settings_overrides (key, value, updated_by, updated_at)
|
|
VALUES ($1, $2, $3, now())
|
|
ON CONFLICT (key) DO UPDATE
|
|
SET value = EXCLUDED.value,
|
|
updated_by = EXCLUDED.updated_by,
|
|
updated_at = now()`,
|
|
key, jsonVal, updatedBy)
|
|
if err != nil {
|
|
return fmt.Errorf("setting override: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// DeleteOverride removes a settings override.
|
|
func (r *SettingsRepository) DeleteOverride(ctx context.Context, key string) error {
|
|
_, err := r.db.pool.Exec(ctx,
|
|
`DELETE FROM settings_overrides WHERE key = $1`, key)
|
|
if err != nil {
|
|
return fmt.Errorf("deleting override: %w", err)
|
|
}
|
|
return nil
|
|
}
|