fix(admin): SMTP port can be cleared and saves without 'Ungültiges JSON'

The UI sent the port as a number while the server expects text, so every
save failed; the field also jumped back to 587 when emptied. The port is
now edited as text (digits only), and the server accepts number or text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
sandrodachandClaude Opus 5.5 committed 2026-10-29 07:13:29 +01:00
1 parent eaabe469d5
commit a3a709440f
4 files changed
+56 -6

No files matched your search

+31
View File
@@ -3,6 +3,7 @@ package domain
import (
"crypto/rand"
"encoding/hex"
"encoding/json"
"fmt"
"regexp"
"strings"
@@ -289,6 +290,36 @@ type SystemSettings struct {
SMTPConfiguredViaEnv bool `json:"smtpConfiguredViaEnv,omitempty"`
}
// UnmarshalJSON accepts smtpPort as text or number: older clients sent a number, which made the whole
// settings request fail with "Ungültiges JSON".
func (s *SystemSettings) UnmarshalJSON(data []byte) error {
type plain SystemSettings
aux := struct {
*plain
SMTPPort json.RawMessage `json:"smtpPort"`
}{plain: (*plain)(s)}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
port := strings.TrimSpace(string(aux.SMTPPort))
switch {
case port == "" || port == "null":
case strings.HasPrefix(port, `"`):
var str string
if err := json.Unmarshal(aux.SMTPPort, &str); err != nil {
return err
}
s.SMTPPort = strings.TrimSpace(str)
default:
var n json.Number
if err := json.Unmarshal(aux.SMTPPort, &n); err != nil {
return err
}
s.SMTPPort = n.String()
}
return nil
}
type DocumentBlock struct {
ID string `json:"id"`
DocumentID string `json:"documentId,omitempty"`
+17
View File
@@ -1,6 +1,7 @@
package domain
import (
"encoding/json"
"reflect"
"testing"
)
@@ -32,3 +33,19 @@ func TestStaleAnchorTags(t *testing.T) {
t.Fatalf("only tags that exist solely as anchors are stale, got %v", got)
}
}
func TestSystemSettingsAcceptsPortAsNumberOrText(t *testing.T) {
for _, body := range []string{`{"smtpPort": 465, "smtpHost": "mail"}`, `{"smtpPort": "465", "smtpHost": "mail"}`} {
var s SystemSettings
if err := json.Unmarshal([]byte(body), &s); err != nil {
t.Fatalf("%s: %v", body, err)
}
if s.SMTPPort != "465" || s.SMTPHost != "mail" {
t.Errorf("%s: got port %q host %q", body, s.SMTPPort, s.SMTPHost)
}
}
var empty SystemSettings
if err := json.Unmarshal([]byte(`{"smtpPort": ""}`), &empty); err != nil || empty.SMTPPort != "" {
t.Errorf("empty port: %q (%v)", empty.SMTPPort, err)
}
}