Phase 2: monitoring warnings, dashboard alerts & notification system
- Monitoring page: "Távoli monitoring" section showing healthcheck ping UUID configuration status (configured/not configured) for each of the 5 pings - Alert manager: persistent dashboard banners on all pages generated from health check results, missing pings, and backup status - Notification system: controller-side notifier sends events to hub relay, with cooldown tracking and event-type filtering - Notification preferences UI: email, event checkboxes, cooldown settings on the settings page with test email functionality - Settings refactored: shared settingsData() helper, NotificationPrefs struct with getter/setter and defaults New files: - controller/internal/web/alerts.go (AlertManager) - controller/internal/notify/notifier.go (hub notification client) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -26,8 +26,19 @@ type Settings struct {
|
||||
DBValidations map[string]DBValidationCache `json:"db_validations,omitempty"`
|
||||
}
|
||||
|
||||
// NotificationPrefs is a placeholder for Phase 2 notification settings.
|
||||
type NotificationPrefs struct{}
|
||||
// NotificationPrefs holds customer notification preferences.
|
||||
type NotificationPrefs struct {
|
||||
Email string `json:"email,omitempty"`
|
||||
EnabledEvents []string `json:"enabled_events,omitempty"`
|
||||
CooldownHours int `json:"cooldown_hours,omitempty"` // default: 6
|
||||
}
|
||||
|
||||
// DefaultEnabledEvents are the events enabled by default for new customers.
|
||||
var DefaultEnabledEvents = []string{
|
||||
"disk_warning",
|
||||
"backup_failed",
|
||||
"update_available",
|
||||
}
|
||||
|
||||
// DBValidationCache holds cached DB dump validation results.
|
||||
type DBValidationCache struct {
|
||||
@@ -127,3 +138,35 @@ func (s *Settings) SetDBValidation(filename string, cache DBValidationCache) err
|
||||
s.DBValidations[filename] = cache
|
||||
return s.save()
|
||||
}
|
||||
|
||||
// GetNotificationPrefs returns a copy of the notification preferences.
|
||||
func (s *Settings) GetNotificationPrefs() *NotificationPrefs {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
if s.Notifications == nil {
|
||||
return &NotificationPrefs{
|
||||
EnabledEvents: DefaultEnabledEvents,
|
||||
CooldownHours: 6,
|
||||
}
|
||||
}
|
||||
prefs := *s.Notifications
|
||||
if prefs.CooldownHours == 0 {
|
||||
prefs.CooldownHours = 6
|
||||
}
|
||||
if prefs.EnabledEvents == nil {
|
||||
prefs.EnabledEvents = DefaultEnabledEvents
|
||||
}
|
||||
// Return a copy of the slice
|
||||
events := make([]string, len(prefs.EnabledEvents))
|
||||
copy(events, prefs.EnabledEvents)
|
||||
prefs.EnabledEvents = events
|
||||
return &prefs
|
||||
}
|
||||
|
||||
// SetNotificationPrefs updates notification preferences and saves to disk.
|
||||
func (s *Settings) SetNotificationPrefs(prefs *NotificationPrefs) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.Notifications = prefs
|
||||
return s.save()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user