Files
mailcow-birthday-daemon/cmd/mcbdd/persist.go
Patrick Asmus (scriptos) c000664165
All checks were successful
Build Test Docker Image / docker-test (pull_request) Successful in 2m1s
Run Tests / test (pull_request) Successful in 5m2s
feat: Hairpin-NAT-Lösung, CA-Zertifikate und konfigurierbarer Kalendername
2026-03-28 15:03:49 +01:00

107 lines
2.8 KiB
Go

package main
import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"log/slog"
"os"
)
func (d *Daemon) loadState() error {
stateVer := struct {
Version int `json:"version"`
}{}
if err := d.loadFromDisk(&stateVer); err != nil {
return fmt.Errorf("cant detect state version: %w", err)
}
var storedCalendarName string
switch stateVer.Version {
case 0:
slog.Warn("loading old state version", "stateVer", stateVer.Version)
if err := d.loadFromDisk(&d.userTokens); err != nil {
return fmt.Errorf("cant load state v%d: %w", stateVer.Version, err)
}
d.stateUnsaved = true
case 1:
state := struct {
Version int `json:"version"`
UserTokens map[string]string `json:"userTokens"`
}{}
if err := d.loadFromDisk(&state); err != nil {
return fmt.Errorf("cant load state v%d: %w", stateVer.Version, err)
}
for k, v := range state.UserTokens {
dec, err := base64.StdEncoding.DecodeString(v)
if err != nil {
return fmt.Errorf("cant decode pass from %s: %w", k, err)
}
d.userTokens[k] = string(dec)
}
d.stateUnsaved = true
case 2:
state := struct {
Version int `json:"version"`
UserTokens map[string]string `json:"userTokens"`
CalendarName string `json:"calendarName"`
}{}
if err := d.loadFromDisk(&state); err != nil {
return fmt.Errorf("cant load state v%d: %w", stateVer.Version, err)
}
for k, v := range state.UserTokens {
dec, err := base64.StdEncoding.DecodeString(v)
if err != nil {
return fmt.Errorf("cant decode pass from %s: %w", k, err)
}
d.userTokens[k] = string(dec)
}
storedCalendarName = state.CalendarName
}
if storedCalendarName != "" && storedCalendarName != d.calendarName {
slog.Info("calendar name changed, old calendars will be cleaned up",
"old", storedCalendarName, "new", d.calendarName)
d.oldCalendarName = storedCalendarName
d.stateUnsaved = true
}
return nil
}
func (d *Daemon) saveState() error {
encTokens := make(map[string]string, len(d.userTokens))
for k, v := range d.userTokens {
encTokens[k] = base64.StdEncoding.EncodeToString([]byte(v))
}
state := struct {
Version int `json:"version"`
UserTokens map[string]string `json:"userTokens"`
CalendarName string `json:"calendarName"`
}{
Version: 2,
UserTokens: encTokens,
CalendarName: d.calendarName,
}
return d.saveToDisk(state)
}
func (d *Daemon) loadFromDisk(state any) error {
f, err := os.OpenFile(d.stateFilepath, os.O_RDONLY, 0o660)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return nil
}
return err
}
defer f.Close()
return json.NewDecoder(f).Decode(state)
}
func (d *Daemon) saveToDisk(state any) error {
f, err := os.OpenFile(d.stateFilepath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o660)
if err != nil {
return err
}
defer f.Close()
return json.NewEncoder(f).Encode(state)
}