feat(webhook): add webhook client for RSVP and photo uploads

This commit is contained in:
2026-08-12 20:27:42 +02:00
parent df5d8efeb1
commit d8f70cf731
5 changed files with 136 additions and 6 deletions
+15
View File
@@ -15,6 +15,7 @@ type Config struct {
Storage StorageConfig `yaml:"storage"`
Email EmailConfig `yaml:"email"`
Upload UploadConfig `yaml:"upload"`
Webhook WebhookConfig `yaml:"webhook"`
}
type ServerConfig struct {
@@ -52,6 +53,17 @@ type UploadConfig struct {
MaxFiles int `yaml:"max_files"`
}
// WebhookConfig is entirely optional: each URL is only called if set, so a
// deployment can wire up RSVP notifications without touching photo uploads
// (or either at all).
type WebhookConfig struct {
RSVPURL string `yaml:"rsvp_url"`
PhotoURL string `yaml:"photo_url"`
Secret string `yaml:"secret"` // signs the payload via HMAC-SHA256, sent in X-Webhook-Signature
Headers map[string]string `yaml:"headers"` // extra headers sent with every webhook request, e.g. Authorization
TimeoutSeconds int `yaml:"timeout_seconds"`
}
// Path resolves the config file location: $CONFIG_PATH, or ./config.yaml.
func Path() string {
if p := os.Getenv("CONFIG_PATH"); p != "" {
@@ -83,6 +95,9 @@ func Load(path string) (*Config, error) {
if cfg.Upload.MaxFiles == 0 {
cfg.Upload.MaxFiles = 10
}
if cfg.Webhook.TimeoutSeconds == 0 {
cfg.Webhook.TimeoutSeconds = 5
}
if cfg.Wedding.Date.IsZero() {
return nil, fmt.Errorf("wedding.date is required in %s", path)
}