mirror of
https://github.com/anand34577/ferrum.git
synced 2026-09-16 15:45:09 +00:00
61ee806af6
- Default all queries to a 20s poll + refetch-on-focus (main.tsx) instead of a per-page opt-in, so every page/widget stays live without manual tuning. - New internal/notify package: Gotify and SMTP (stdlib net/smtp, STARTTLS and implicit-TLS-on-465) notifications, each independently optional. Fires from the alert evaluator on new alert triggers; admin-configurable from Settings with a send-test-notification action per channel. - OIDC/SSO moved from config.yaml-only to a DB-backed, admin-editable Settings card — swaps the live client with no restart. config.yaml is used to seed the database once on first boot after upgrading. - New Security settings: session TTL, login lockout policy, and a real "require 2FA for admins" enforcement (requireTOTPEnrolled middleware) that blocks non-enrolled admins from everything but /profile and logout. - New org-wide default preferences (theme/accent/look/landing page) for brand-new accounts, plus a personal landing-page picker and an email-me-alerts opt-in on Profile. - Storage page: separate Local vs Shared/External storage tables and capacity donuts, fixing shared-storage totals that were being summed once per node that mounts them (e.g. a 2TB NFS share on 4 nodes read as 8TB). - RankedBarChart: stop the longest bar's value label wrapping onto two lines (recharts auto-wraps LabelList when space is tight).
58 lines
1.6 KiB
Go
58 lines
1.6 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
|
|
"ferrum/internal/auth"
|
|
)
|
|
|
|
// BootstrapSettings loads OIDC and notification settings from the database
|
|
// and applies them (live OIDC client, live Notifier) at startup.
|
|
//
|
|
// seedOIDC is the config.yaml/env OIDC config (internal/config.OIDCConfig,
|
|
// converted by the caller) — config.yaml was the only way to set this up
|
|
// before the Settings UI existed. The very first boot after upgrading copies
|
|
// it into the database once; every boot after that (and every save from the
|
|
// UI) uses the database exclusively, so config.yaml stops being read for
|
|
// OIDC at all once a row exists.
|
|
func (s *Server) BootstrapSettings(ctx context.Context, seedEnabled bool, seedOIDC auth.OIDCConfig) error {
|
|
var exists int
|
|
err := s.db.QueryRowContext(ctx, `SELECT 1 FROM oidc_settings WHERE id = 1`).Scan(&exists)
|
|
if err == sql.ErrNoRows {
|
|
enc, encErr := s.secrets.Encrypt(seedOIDC.ClientSecret)
|
|
if encErr != nil {
|
|
return encErr
|
|
}
|
|
if err := s.saveOIDCRow(ctx, oidcRow{
|
|
enabled: seedEnabled, displayName: seedOIDC.DisplayName, issuerURL: seedOIDC.IssuerURL,
|
|
clientID: seedOIDC.ClientID, clientSecretEnc: enc, redirectURL: seedOIDC.RedirectURL,
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
|
|
row, err := s.loadOIDCRow(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
s.applyOIDCRow(row)
|
|
|
|
notifRow, err := s.loadNotificationRow(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := s.applyNotificationRow(notifRow); err != nil {
|
|
return err
|
|
}
|
|
|
|
secRow, err := s.loadSecurityRow(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
s.applySecurityRow(secRow)
|
|
return nil
|
|
}
|