- Rename Go module switchboard-core → armature (155+ files) - Rename Docker image → gobha/armature - Rename K8s resources, secrets, deployments - Rename Prometheus metrics switchboard_* → armature_* - Rename env vars SWITCHBOARD_ADMIN_* → ARMATURE_ADMIN_* - Rename DB names switchboard_core* → armature* - Update all frontend branding, notification templates, docs - Update CI scripts, e2e tests, Keycloak realm, nginx conf - Rename scripts/switchboard-ca.sh → scripts/armature-ca.sh - Rename k8s/switchboard.yaml → k8s/armature.yaml - Rename chart alerting/dashboard files - Fix: DockerHub push uses env: binding for secret injection - Helm chart updated (name, labels, template functions, dashboard, alerting) - Replace favicon/icon assets with Armature brand No functional changes. Pure mechanical rename + CI fix. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
97 lines
2.9 KiB
Go
97 lines
2.9 KiB
Go
package postgres
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/json"
|
|
|
|
"armature/models"
|
|
)
|
|
|
|
type GlobalConfigStore struct{}
|
|
|
|
func NewGlobalConfigStore() *GlobalConfigStore { return &GlobalConfigStore{} }
|
|
|
|
func (s *GlobalConfigStore) Get(ctx context.Context, key string) (models.JSONMap, error) {
|
|
var valueJSON []byte
|
|
err := DB.QueryRowContext(ctx,
|
|
"SELECT value FROM global_settings WHERE key = $1", key).Scan(&valueJSON)
|
|
if err == sql.ErrNoRows {
|
|
return nil, nil
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var result models.JSONMap
|
|
json.Unmarshal(valueJSON, &result)
|
|
return result, nil
|
|
}
|
|
|
|
func (s *GlobalConfigStore) Set(ctx context.Context, key string, value models.JSONMap, updatedBy string) error {
|
|
valueJSON := ToJSON(value)
|
|
_, err := DB.ExecContext(ctx, `
|
|
INSERT INTO global_settings (key, value, updated_by, updated_at)
|
|
VALUES ($1, $2, $3, NOW())
|
|
ON CONFLICT (key) DO UPDATE SET value = $2, updated_by = $3, updated_at = NOW()`,
|
|
key, valueJSON, updatedBy)
|
|
return err
|
|
}
|
|
|
|
func (s *GlobalConfigStore) GetAll(ctx context.Context) (map[string]models.JSONMap, error) {
|
|
rows, err := DB.QueryContext(ctx, "SELECT key, value FROM global_settings")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
result := make(map[string]models.JSONMap)
|
|
for rows.Next() {
|
|
var key string
|
|
var valueJSON []byte
|
|
if err := rows.Scan(&key, &valueJSON); err != nil {
|
|
continue
|
|
}
|
|
var m models.JSONMap
|
|
json.Unmarshal(valueJSON, &m)
|
|
result[key] = m
|
|
}
|
|
return result, rows.Err()
|
|
}
|
|
|
|
// ── OIDC state ────────────────────────────────────────────
|
|
|
|
func (s *GlobalConfigStore) SaveOIDCState(ctx context.Context, state, nonce, redirectTo string) error {
|
|
_, err := DB.ExecContext(ctx, `
|
|
INSERT INTO oidc_auth_state (state, nonce, redirect_to) VALUES ($1, $2, $3)
|
|
`, state, nonce, redirectTo)
|
|
return err
|
|
}
|
|
|
|
func (s *GlobalConfigStore) ConsumeOIDCState(ctx context.Context, state string) (string, string, error) {
|
|
var nonce, redirectTo string
|
|
err := DB.QueryRowContext(ctx, `
|
|
SELECT nonce, COALESCE(redirect_to, '') FROM oidc_auth_state WHERE state = $1
|
|
`, state).Scan(&nonce, &redirectTo)
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
// Delete (one-time use)
|
|
_, _ = DB.ExecContext(ctx, `DELETE FROM oidc_auth_state WHERE state = $1`, state)
|
|
return nonce, redirectTo, nil
|
|
}
|
|
|
|
func (s *GlobalConfigStore) CleanupOIDCState(ctx context.Context) error {
|
|
_, err := DB.ExecContext(ctx,
|
|
`DELETE FROM oidc_auth_state WHERE created_at < NOW() - INTERVAL '10 minutes'`)
|
|
return err
|
|
}
|
|
|
|
// ── CS6 additions ─────────────────────────────────────────────
|
|
|
|
func (s *GlobalConfigStore) GetString(ctx context.Context, key string) (string, error) {
|
|
var val string
|
|
err := DB.QueryRowContext(ctx,
|
|
"SELECT value FROM global_settings WHERE key = $1", key).Scan(&val)
|
|
return val, err
|
|
}
|