Add configurable email notification digests
This commit is contained in:
64
store.go
64
store.go
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
@@ -59,6 +60,20 @@ type HistoryPoint struct {
|
||||
|
||||
type Store struct{ db *sql.DB }
|
||||
|
||||
type EmailSettings struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password,omitempty"`
|
||||
HasPassword bool `json:"hasPassword"`
|
||||
From string `json:"from"`
|
||||
To string `json:"to"`
|
||||
IntervalMinutes int `json:"intervalMinutes"`
|
||||
Severities []string `json:"severities"`
|
||||
Sources []string `json:"sources"`
|
||||
}
|
||||
|
||||
func openStore(path string) (*Store, error) {
|
||||
if path != ":memory:" {
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o750); err != nil {
|
||||
@@ -114,6 +129,55 @@ func (s *Store) SaveThresholds(value AlertThresholds) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func defaultEmailSettings() EmailSettings {
|
||||
return EmailSettings{Port: 587, IntervalMinutes: 60, Severities: []string{"critical", "warning"}, Sources: []string{"CPU", "Память", "Storage", "Диски", "ZFS", "UPS", "VM/LXC", "Dashboard"}}
|
||||
}
|
||||
|
||||
func (s *Store) EmailSettings(includePassword bool) EmailSettings {
|
||||
settings := defaultEmailSettings()
|
||||
var value string
|
||||
if s.db.QueryRow(`SELECT value FROM settings WHERE key='email_notifications'`).Scan(&value) == nil {
|
||||
_ = json.Unmarshal([]byte(value), &settings)
|
||||
}
|
||||
settings.HasPassword = settings.Password != ""
|
||||
if !includePassword {
|
||||
settings.Password = ""
|
||||
}
|
||||
return settings
|
||||
}
|
||||
|
||||
func (s *Store) SaveEmailSettings(settings EmailSettings) error {
|
||||
if settings.Port < 1 || settings.Port > 65535 || settings.IntervalMinutes < 5 || settings.IntervalMinutes > 10080 {
|
||||
return fmt.Errorf("проверьте порт и интервал (от 5 минут до 7 дней)")
|
||||
}
|
||||
if settings.Enabled && (settings.Host == "" || settings.From == "" || settings.To == "") {
|
||||
return fmt.Errorf("для отправки нужны SMTP-сервер, отправитель и получатель")
|
||||
}
|
||||
if strings.ContainsAny(settings.Host+settings.From+settings.To+settings.Username, "\r\n") {
|
||||
return fmt.Errorf("поля почты содержат недопустимые символы")
|
||||
}
|
||||
if settings.Password == "" {
|
||||
settings.Password = s.EmailSettings(true).Password
|
||||
}
|
||||
settings.HasPassword = settings.Password != ""
|
||||
data, _ := json.Marshal(settings)
|
||||
_, err := s.db.Exec(`INSERT INTO settings(key,value) VALUES('email_notifications',?) ON CONFLICT(key) DO UPDATE SET value=excluded.value`, string(data))
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Store) LastEmailAt() time.Time {
|
||||
var value string
|
||||
if s.db.QueryRow(`SELECT value FROM settings WHERE key='email_last_sent'`).Scan(&value) != nil {
|
||||
return time.Time{}
|
||||
}
|
||||
result, _ := time.Parse(time.RFC3339, value)
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *Store) SetLastEmailAt(value time.Time) {
|
||||
_, _ = s.db.Exec(`INSERT INTO settings(key,value) VALUES('email_last_sent',?) ON CONFLICT(key) DO UPDATE SET value=excluded.value`, value.Format(time.RFC3339))
|
||||
}
|
||||
|
||||
func validateThresholds(t AlertThresholds) error {
|
||||
percentages := []float64{t.CPUWarning, t.CPUCritical, t.MemoryWarning, t.MemoryCritical, t.SwapWarning, t.StorageWarning, t.StorageCritical, t.ZFSWarning, t.ZFSCritical, t.UPSChargeCritical}
|
||||
for _, value := range percentages {
|
||||
|
||||
Reference in New Issue
Block a user