Fix empty password save behaviour on settings.

The earlier logic for copying existing passwords from the DB to
SMTP and messenger settings when the frontend sent an empty
password was based on array positions (and flawed). This commit
introduces an internal UUID field to SMTP and Messenger settings
to keep track of password changes in the settings UI.
This commit is contained in:
Kailash Nadh 2020-10-10 21:25:59 +05:30
parent 6cf43ea674
commit f667935a82
1 changed files with 30 additions and 18 deletions

View File

@ -9,6 +9,7 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/gofrs/uuid"
"github.com/jmoiron/sqlx/types" "github.com/jmoiron/sqlx/types"
"github.com/labstack/echo" "github.com/labstack/echo"
) )
@ -43,6 +44,7 @@ type settings struct {
UploadS3Expiry string `json:"upload.s3.expiry"` UploadS3Expiry string `json:"upload.s3.expiry"`
SMTP []struct { SMTP []struct {
UUID string `json:"uuid"`
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
Host string `json:"host"` Host string `json:"host"`
HelloHostname string `json:"hello_hostname"` HelloHostname string `json:"hello_hostname"`
@ -60,6 +62,7 @@ type settings struct {
} `json:"smtp"` } `json:"smtp"`
Messengers []struct { Messengers []struct {
UUID string `json:"uuid"`
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
Name string `json:"name"` Name string `json:"name"`
RootURL string `json:"root_url"` RootURL string `json:"root_url"`
@ -121,15 +124,21 @@ func handleUpdateSettings(c echo.Context) error {
has = true has = true
} }
// If there's no password coming in from the frontend, attempt to get the // Assign a UUID. The frontend only sends a password when the user explictly
// last saved password for the SMTP block at the same position. // changes the password. In other cases, the existing password in the DB
if set.SMTP[i].Password == "" { // is copied while updating the settings and the UUID is used to match
if len(cur.SMTP) > i && // the incoming array of SMTP blocks with the array in the DB.
set.SMTP[i].Host == cur.SMTP[i].Host && if s.UUID == "" {
set.SMTP[i].Username == cur.SMTP[i].Username { set.SMTP[i].UUID = uuid.Must(uuid.NewV4()).String()
// Copy the existing password as password's needn't be }
// sent from the frontend for updating entries.
set.SMTP[i].Password = cur.SMTP[i].Password // If there's no password coming in from the frontend, copy the existing
// password by matching the UUID.
if s.Password == "" {
for _, c := range cur.SMTP {
if s.UUID == c.UUID {
set.SMTP[i].Password = c.Password
}
} }
} }
} }
@ -142,18 +151,21 @@ func handleUpdateSettings(c echo.Context) error {
// and "email" is a reserved name. // and "email" is a reserved name.
names := map[string]bool{emailMsgr: true} names := map[string]bool{emailMsgr: true}
for i := range set.Messengers { for i, m := range set.Messengers {
if set.Messengers[i].Password == "" { // UUID to keep track of password changes similar to the SMTP logic above.
if len(cur.Messengers) > i && if m.UUID == "" {
set.Messengers[i].RootURL == cur.Messengers[i].RootURL && set.Messengers[i].UUID = uuid.Must(uuid.NewV4()).String()
set.Messengers[i].Username == cur.Messengers[i].Username { }
// Copy the existing password as password's needn't be
// sent from the frontend for updating entries. if m.Password == "" {
set.Messengers[i].Password = cur.Messengers[i].Password for _, c := range cur.Messengers {
if m.UUID == c.UUID {
set.Messengers[i].Password = c.Password
}
} }
} }
name := reAlphaNum.ReplaceAllString(strings.ToLower(set.Messengers[i].Name), "") name := reAlphaNum.ReplaceAllString(strings.ToLower(m.Name), "")
if _, ok := names[name]; ok { if _, ok := names[name]; ok {
return echo.NewHTTPError(http.StatusBadRequest, return echo.NewHTTPError(http.StatusBadRequest,
fmt.Sprintf("Duplicate messenger name `%s`.", name)) fmt.Sprintf("Duplicate messenger name `%s`.", name))