fix(backend): keep login notification and email verification settings on upgrade

This commit is contained in:
Elias Schneider
2026-10-21 18:27:36 +02:00
parent b352c81c38
commit 6b9aba1735
3 changed files with 41 additions and 19 deletions
+1 -1
View File
@@ -41,6 +41,7 @@ require (
github.com/quic-go/quic-go v0.63.0
github.com/spf13/cobra v1.10.2
github.com/stretchr/testify v1.12.1
github.com/vmihailenco/msgpack/v5 v5.4.1
github.com/zitadel/exifremove v0.1.0
go.opentelemetry.io/contrib/bridges/otelslog v0.21.0
go.opentelemetry.io/contrib/exporters/autoexport v0.72.0
@@ -178,7 +179,6 @@ require (
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.3.2 // indirect
github.com/valyala/fastjson v1.6.10 // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.mongodb.org/mongo-driver/v2 v2.9.1 // indirect
+7 -6
View File
@@ -1,16 +1,17 @@
package appconfig
import "encoding/json"
import "github.com/vmihailenco/msgpack/v5"
// UnmarshalJSON preserves settings stored in actor state before boolean toggles were replaced by modes
func (m *AppConfigModel) UnmarshalJSON(data []byte) error {
// DecodeMsgpack preserves settings stored in actor state before boolean toggles were replaced by modes
// Francis stores actor state as MessagePack keyed by Go field name, so the legacy keys are the old field names
func (m *AppConfigModel) DecodeMsgpack(dec *msgpack.Decoder) error {
type config AppConfigModel
value := struct {
*config
LegacyNotificationEnabled AppConfigValue `json:"emailLoginNotificationEnabled"`
LegacyEmailVerificationEnabled AppConfigValue `json:"emailVerificationEnabled"`
LegacyNotificationEnabled AppConfigValue `msgpack:"EmailLoginNotificationEnabled"`
LegacyEmailVerificationEnabled AppConfigValue `msgpack:"EmailVerificationEnabled"`
}{config: (*config)(m)}
if err := json.Unmarshal(data, &value); err != nil {
if err := dec.Decode(&value); err != nil {
return err
}
if m.EmailLoginNotificationMode == "" && value.LegacyNotificationEnabled != "" {
+33 -12
View File
@@ -1,7 +1,6 @@
package appconfig
import (
"encoding/json"
"errors"
"reflect"
"strings"
@@ -9,6 +8,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/vmihailenco/msgpack/v5"
"github.com/pocket-id/pocket-id/backend/internal/dto"
)
@@ -302,26 +302,47 @@ func TestAppConfigModel_Update(t *testing.T) {
})
}
func TestAppConfigModel_UnmarshalJSON(t *testing.T) {
t.Run("maps the legacy email verification toggle to a mode", func(t *testing.T) {
tests := map[string]AppConfigValue{
"true": EmailVerificationOptional,
"false": EmailVerificationDisabled,
func TestAppConfigModel_DecodeMsgpack(t *testing.T) {
t.Run("maps the legacy toggles to modes", func(t *testing.T) {
tests := map[string]struct {
notification AppConfigValue
emailVerification AppConfigValue
}{
"true": {LoginNotificationBrowserRecognition, EmailVerificationOptional},
"false": {LoginNotificationDisabled, EmailVerificationDisabled},
}
for enabled, expected := range tests {
var m AppConfigModel
err := json.Unmarshal([]byte(`{"emailVerificationEnabled":"`+enabled+`"}`), &m)
data, err := msgpack.Marshal(map[string]string{
"AppName": "Legacy App",
"EmailLoginNotificationEnabled": enabled,
"EmailVerificationEnabled": enabled,
})
require.NoError(t, err)
assert.Equal(t, expected, m.EmailVerification)
var m AppConfigModel
err = msgpack.Unmarshal(data, &m)
require.NoError(t, err)
assert.Equal(t, AppConfigValue("Legacy App"), m.AppName)
assert.Equal(t, expected.notification, m.EmailLoginNotificationMode)
assert.Equal(t, expected.emailVerification, m.EmailVerification)
}
})
t.Run("an explicit email verification mode wins over the legacy toggle", func(t *testing.T) {
var m AppConfigModel
err := json.Unmarshal([]byte(`{"emailVerification":"required","emailVerificationEnabled":"false"}`), &m)
t.Run("stored modes win over the legacy toggles", func(t *testing.T) {
data, err := msgpack.Marshal(map[string]string{
"EmailLoginNotificationMode": LoginNotificationAlways,
"EmailLoginNotificationEnabled": "false",
"EmailVerification": EmailVerificationRequired,
"EmailVerificationEnabled": "false",
})
require.NoError(t, err)
var m AppConfigModel
err = msgpack.Unmarshal(data, &m)
require.NoError(t, err)
assert.Equal(t, AppConfigValue(LoginNotificationAlways), m.EmailLoginNotificationMode)
assert.Equal(t, AppConfigValue(EmailVerificationRequired), m.EmailVerification)
})
}