diff --git a/config.yaml b/config.yaml index b8ff970..883eeb0 100644 --- a/config.yaml +++ b/config.yaml @@ -3,74 +3,45 @@ database: server: bind_address: 0.0.0.0:14243 default_class: CONFIDENTIAL - public_url: http://nxc.nx2.site/ - email_domain: nx2.site + public_url: http://example.com/ + email_domain: example.com redaction_text: '[-]' smtp: host: localhost port: 587 user: nxcaldav@nx2.site - password: Vastly-Wrinkle9-Corsage + password_cmd: echo "Vastly-Wrinkle9-Corsage" users: - - name: daniel - password: ll + - name: alice + password: 123 groups: - family - - name: lennart - password: ll + - name: bob + password: abc groups: - family - - name: shared - password: Oxidant-Ageless3-Dispersed calendars: - - id: preservation - owner: lennart + - id: test + owner: alice color: '#F6F5F4' - - id: effort - owner: lennart - color: '#FF0000' - - id: experience - owner: lennart - color: '#2C33FF' - - id: leisure - owner: lennart - color: '#10B400' - - id: daniel - owner: daniel - color: '#ff2222' - - access: - - group: family - mode: read-write - id: family + - id: family owner: shared color: '#999999' + access: + - group: family + mode: read-write address_books: - id: contacts - owner: lennart - - id: contacts - owner: daniel + owner: alice - id: family - owner: shared + owner: bob access: - group: family mode: read-write aggregates: -- access: - - group: family - mode: read-only - - ics: future-only - id: lennart-aggregat - owner: lennart - color: '#dd9999' - sources: - - preservation - - effort - - experience - - leisure - - family diff --git a/internal/backend/db.go b/internal/backend/db.go index bc86752..151d81f 100644 --- a/internal/backend/db.go +++ b/internal/backend/db.go @@ -8,7 +8,6 @@ import ( "log" "net/http" "net/url" - "os/exec" "path" "slices" "strings" @@ -140,16 +139,9 @@ func (b *DBBackend) initSchema(ctx context.Context) error { } func (b *DBBackend) resolvePassword(u config.User) (string, error) { - var raw string - if u.PasswordCmd != "" { - cmd := exec.Command("sh", "-c", u.PasswordCmd) - out, err := cmd.Output() - if err != nil { - return "", fmt.Errorf("failed to run password command for %s: %v", u.Name, err) - } - raw = strings.TrimSpace(string(out)) - } else { - raw = u.Password + raw, err := config.ResolvePassword(u.Password, u.PasswordCmd) + if err != nil { + return "", fmt.Errorf("failed to resolve password for %s: %v", u.Name, err) } // If it already looks like a bcrypt hash, return as is. diff --git a/internal/backend/email.go b/internal/backend/email.go index c18cf9b..f54cd3a 100644 --- a/internal/backend/email.go +++ b/internal/backend/email.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/emersion/go-ical" + "nxcaldav/internal/config" ) // sendInvitation sends an iMIP (RFC 6047) invitation email. @@ -99,8 +100,14 @@ func (b *DBBackend) sendInvitation(senderName, recipientEmail, summary, descript if err = c.StartTLS(tlsConfig); err != nil { return err } } } - if b.smtp.User != "" && b.smtp.Password != "" { - auth := smtp.PlainAuth("", b.smtp.User, b.smtp.Password, b.smtp.Host) + + smtpPassword, err := config.ResolvePassword(b.smtp.Password, b.smtp.PasswordCmd) + if err != nil { + return fmt.Errorf("failed to resolve SMTP password: %v", err) + } + + if b.smtp.User != "" && smtpPassword != "" { + auth := smtp.PlainAuth("", b.smtp.User, smtpPassword, b.smtp.Host) if err = c.Auth(auth); err != nil { return err } } diff --git a/internal/config/config.go b/internal/config/config.go index 6e28638..91bf8bc 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,8 +1,10 @@ package config import ( + "fmt" "net/url" "os" + "os/exec" "slices" "strings" @@ -64,10 +66,11 @@ func (s ServerConfig) BasePath() string { type SMTPConfig struct { - Host string `yaml:"host"` - Port int `yaml:"port"` - User string `yaml:"user"` - Password string `yaml:"password"` + Host string `yaml:"host"` + Port int `yaml:"port"` + User string `yaml:"user"` + Password string `yaml:"password"` + PasswordCmd string `yaml:"password_cmd"` } type Config struct { @@ -79,6 +82,18 @@ type Config struct { AddressBooks []AddressBook `yaml:"address_books"` Aggregates []Aggregate `yaml:"aggregates"` } + +func ResolvePassword(password, passwordCmd string) (string, error) { + if passwordCmd != "" { + cmd := exec.Command("sh", "-c", passwordCmd) + out, err := cmd.Output() + if err != nil { + return "", fmt.Errorf("failed to run password command: %v", err) + } + return strings.TrimSpace(string(out)), nil + } + return password, nil +} func (c *Config) setDefaults() { if c.Server.BindAddress == "" { c.Server.BindAddress = ":8080" } if c.Server.Redaction == "" { c.Server.Redaction = "Busy" } diff --git a/main b/main deleted file mode 100755 index 696f33a..0000000 Binary files a/main and /dev/null differ