v0.7.0: Phase 1 — Authentication, Persistence & Settings Page
- New settings.json persistence layer (internal/settings/settings.go) - Atomic write (tmp + rename), thread-safe with sync.RWMutex - Stores password hash overrides and DB validation cache - Auto-creates on first save, graceful handling if missing - Auth improvements - Password resolution priority: settings.json > controller.yaml > none - Session duration extended to 7 days (was 24h) - ?next= redirect after session expiry (returns to original page) - Flash messages on login page (used after password change) - Conditional logout link (hidden when auth disabled) - Session invalidation on password change - New Settings page (/settings) - Read-only system config display (customer, domain, git, backup, monitoring) - Password change form with validation (min 8 chars, match check) - Sidebar "Beállítások" item pinned to bottom above version - DB validation persistence - Validation results saved to settings.json after each dump - Cached data survives container restarts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,14 +11,16 @@ import (
|
||||
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/config"
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/monitor"
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/settings"
|
||||
)
|
||||
|
||||
// Manager orchestrates database dumps and restic backups.
|
||||
type Manager struct {
|
||||
cfg *config.Config
|
||||
restic *ResticManager
|
||||
logger *log.Logger
|
||||
pinger *monitor.Pinger
|
||||
cfg *config.Config
|
||||
restic *ResticManager
|
||||
logger *log.Logger
|
||||
pinger *monitor.Pinger
|
||||
settings *settings.Settings
|
||||
|
||||
mu sync.Mutex
|
||||
lastDBDump *DBDumpStatus
|
||||
@@ -100,12 +102,13 @@ type BackupStatus struct {
|
||||
}
|
||||
|
||||
// NewManager creates a new backup manager.
|
||||
func NewManager(cfg *config.Config, pinger *monitor.Pinger, logger *log.Logger) *Manager {
|
||||
func NewManager(cfg *config.Config, pinger *monitor.Pinger, sett *settings.Settings, logger *log.Logger) *Manager {
|
||||
return &Manager{
|
||||
cfg: cfg,
|
||||
restic: NewResticManager(cfg, logger),
|
||||
logger: logger,
|
||||
pinger: pinger,
|
||||
cfg: cfg,
|
||||
restic: NewResticManager(cfg, logger),
|
||||
logger: logger,
|
||||
pinger: pinger,
|
||||
settings: sett,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +139,7 @@ func (m *Manager) RunDBDumps(ctx context.Context) error {
|
||||
|
||||
results := DumpAll(ctx, dbs, m.cfg.Paths.DBDumpDir, m.logger)
|
||||
|
||||
// Check results
|
||||
// Check results and persist validations
|
||||
allOK := true
|
||||
var summary []string
|
||||
var totalSize int64
|
||||
@@ -148,6 +151,22 @@ func (m *Manager) RunDBDumps(ctx context.Context) error {
|
||||
} else {
|
||||
totalSize += r.Size
|
||||
summary = append(summary, fmt.Sprintf("OK %s (%s)", r.DB.ContainerName, formatBytes(r.Size)))
|
||||
|
||||
// Persist validation result to settings.json
|
||||
if m.settings != nil && r.FilePath != "" {
|
||||
filename := filepath.Base(r.FilePath)
|
||||
cache := settings.DBValidationCache{
|
||||
ValidatedAt: time.Now().Format(time.RFC3339),
|
||||
TableCount: r.Validation.TableCount,
|
||||
HasHeader: r.Validation.Valid,
|
||||
}
|
||||
if !r.Validation.Valid {
|
||||
cache.Error = r.Validation.Error
|
||||
}
|
||||
if err := m.settings.SetDBValidation(filename, cache); err != nil {
|
||||
m.logger.Printf("[WARN] Failed to cache validation for %s: %v", filename, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user