From 361fece3788fff577d2759bcf414b0d64c320789 Mon Sep 17 00:00:00 2001 From: Abhinav Raut Date: Tue, 20 Jan 2026 00:03:01 +0530 Subject: [PATCH] fix: trim whitespace from inbox and settings fields Fixes #223 --- cmd/inboxes.go | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ cmd/settings.go | 19 ++++++++++++++--- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/cmd/inboxes.go b/cmd/inboxes.go index 8a0f52cd..036d4205 100644 --- a/cmd/inboxes.go +++ b/cmd/inboxes.go @@ -4,6 +4,7 @@ import ( "encoding/json" "net/mail" "strconv" + "strings" "github.com/abhinavxd/libredesk/internal/envelope" "github.com/abhinavxd/libredesk/internal/inbox" @@ -56,6 +57,11 @@ func handleCreateInbox(r *fastglue.Request) error { return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.Ts("globals.messages.errorParsing", "name", "{globals.terms.request}"), err.Error(), envelope.InputError) } + // Trim whitespace from inbox fields and config. + if err := trimInboxFields(&inbox); err != nil { + return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.Ts("globals.messages.errorParsing", "name", "config"), err.Error(), envelope.InputError) + } + createdInbox, err := app.inbox.Create(inbox) if err != nil { return sendErrorEnvelope(r, err) @@ -94,6 +100,11 @@ func handleUpdateInbox(r *fastglue.Request) error { return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.Ts("globals.messages.errorParsing", "name", "{globals.terms.request}"), err.Error(), envelope.InputError) } + // Trim whitespace from inbox fields and config. + if err := trimInboxFields(&inbox); err != nil { + return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.Ts("globals.messages.errorParsing", "name", "config"), err.Error(), envelope.InputError) + } + if err := validateInbox(app, inbox); err != nil { return sendErrorEnvelope(r, err) } @@ -248,3 +259,49 @@ func validateEmailConfig(app *App, configJSON json.RawMessage) error { return nil } + +// trimInboxFields trims whitespace from inbox fields and its email config if applicable. +func trimInboxFields(inb *imodels.Inbox) error { + inb.Name = strings.TrimSpace(inb.Name) + inb.From = strings.TrimSpace(inb.From) + + // Trim email config fields if this is an email channel. + if inb.Channel == inbox.ChannelEmail && len(inb.Config) > 0 { + var cfg imodels.Config + if err := json.Unmarshal(inb.Config, &cfg); err != nil { + return err + } + trimEmailConfig(&cfg) + trimmedConfig, err := json.Marshal(cfg) + if err != nil { + return err + } + inb.Config = trimmedConfig + } + return nil +} + +// trimEmailConfig trims whitespace from email configuration fields. +// Passwords and secrets are intentionally NOT trimmed. +func trimEmailConfig(cfg *imodels.Config) { + // Trim IMAP configs. + for i := range cfg.IMAP { + cfg.IMAP[i].Host = strings.TrimSpace(cfg.IMAP[i].Host) + cfg.IMAP[i].Username = strings.TrimSpace(cfg.IMAP[i].Username) + cfg.IMAP[i].Mailbox = strings.TrimSpace(cfg.IMAP[i].Mailbox) + } + + // Trim SMTP configs. + for i := range cfg.SMTP { + cfg.SMTP[i].Host = strings.TrimSpace(cfg.SMTP[i].Host) + cfg.SMTP[i].Username = strings.TrimSpace(cfg.SMTP[i].Username) + cfg.SMTP[i].HelloHostname = strings.TrimSpace(cfg.SMTP[i].HelloHostname) + } + + // Trim OAuth config. + if cfg.OAuth != nil { + cfg.OAuth.Provider = strings.TrimSpace(cfg.OAuth.Provider) + cfg.OAuth.ClientID = strings.TrimSpace(cfg.OAuth.ClientID) + cfg.OAuth.TenantID = strings.TrimSpace(cfg.OAuth.TenantID) + } +} diff --git a/cmd/settings.go b/cmd/settings.go index 264c4997..4182a082 100644 --- a/cmd/settings.go +++ b/cmd/settings.go @@ -47,14 +47,19 @@ func handleUpdateGeneralSettings(r *fastglue.Request) error { return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.T("globals.messages.badRequest"), nil, envelope.InputError) } + // Trim whitespace from string fields. + req.SiteName = strings.TrimSpace(req.SiteName) + req.FaviconURL = strings.TrimSpace(req.FaviconURL) + req.LogoURL = strings.TrimSpace(req.LogoURL) + req.Timezone = strings.TrimSpace(req.Timezone) + // Trim whitespace and trailing slash from root URL. + req.RootURL = strings.TrimRight(strings.TrimSpace(req.RootURL), "/") + // Get current language before update. app.Lock() oldLang := ko.String("app.lang") app.Unlock() - // Remove any trailing slash `/` from the root url. - req.RootURL = strings.TrimRight(req.RootURL, "/") - if err := app.setting.Update(req); err != nil { return sendErrorEnvelope(r, err) } @@ -113,6 +118,14 @@ func handleUpdateEmailNotificationSettings(r *fastglue.Request) error { return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.T("globals.messages.badRequest"), nil, envelope.InputError) } + // Trim whitespace from string fields (Password intentionally NOT trimmed). + req.Host = strings.TrimSpace(req.Host) + req.Username = strings.TrimSpace(req.Username) + req.EmailAddress = strings.TrimSpace(req.EmailAddress) + req.HelloHostname = strings.TrimSpace(req.HelloHostname) + req.IdleTimeout = strings.TrimSpace(req.IdleTimeout) + req.WaitTimeout = strings.TrimSpace(req.WaitTimeout) + out, err := app.setting.GetByPrefix("notification.email") if err != nil { return sendErrorEnvelope(r, err)