From feb17792e4fd23da114d12688ed78b8364512519 Mon Sep 17 00:00:00 2001 From: Dominik Pschenitschni <6173598+dpschen@users.noreply.github.com> Date: Mon, 4 Aug 2025 16:07:00 +0200 Subject: [PATCH] fix(user): persist status on email updates (#1084) --- pkg/user/test.go | 2 + pkg/user/update_email.go | 14 ++++--- pkg/user/update_email_test.go | 72 ++++++++++++++++++++++++++++++++++ pkg/user/user.go | 2 +- pkg/user/user_create.go | 2 +- pkg/user/user_email_confirm.go | 2 +- 6 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 pkg/user/update_email_test.go diff --git a/pkg/user/test.go b/pkg/user/test.go index 85080bac9..6ec443c4d 100644 --- a/pkg/user/test.go +++ b/pkg/user/test.go @@ -21,6 +21,7 @@ import ( "code.vikunja.io/api/pkg/db" "code.vikunja.io/api/pkg/events" "code.vikunja.io/api/pkg/log" + "code.vikunja.io/api/pkg/mail" "code.vikunja.io/api/pkg/modules/keyvalue" ) @@ -42,6 +43,7 @@ func InitTests() { } events.Fake() + mail.Fake() keyvalue.InitStorage() diff --git a/pkg/user/update_email.go b/pkg/user/update_email.go index 3c5201586..b0ec0bec4 100644 --- a/pkg/user/update_email.go +++ b/pkg/user/update_email.go @@ -55,22 +55,24 @@ func UpdateEmail(s *xorm.Session, update *EmailUpdate) (err error) { // Send the confirmation mail if !config.MailerEnabled.GetBool() { + update.User.Status = StatusActive _, err = s. Where("id = ?", update.User.ID). - Cols("email"). + Cols("email", "status"). Update(update.User) return } update.User.Status = StatusEmailConfirmationRequired - token, err := generateToken(s, update.User, TokenEmailConfirm) + _, err = s. + Where("id = ?", update.User.ID). + Cols("email", "status"). + Update(update.User) if err != nil { return } - _, err = s. - Where("id = ?", update.User.ID). - Cols("email", "is_active"). // TODO: Status change - Update(update.User) + + token, err := generateToken(s, update.User, TokenEmailConfirm) if err != nil { return } diff --git a/pkg/user/update_email_test.go b/pkg/user/update_email_test.go new file mode 100644 index 000000000..fa7ece15a --- /dev/null +++ b/pkg/user/update_email_test.go @@ -0,0 +1,72 @@ +// Vikunja is a to-do list application to facilitate your life. +// Copyright 2018-present Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package user + +import ( + "testing" + + "code.vikunja.io/api/pkg/config" + "code.vikunja.io/api/pkg/db" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestUpdateEmailStatusPersistence(t *testing.T) { + t.Run("mailer enabled", func(t *testing.T) { + db.LoadAndAssertFixtures(t) + s := db.NewSession() + defer s.Close() + + config.MailerEnabled.Set(true) + defer config.MailerEnabled.Set(false) + + err := UpdateEmail(s, &EmailUpdate{User: &User{ID: 1}, NewEmail: "new1@example.com"}) + require.NoError(t, err) + + err = s.Commit() + require.NoError(t, err) + + s2 := db.NewSession() + defer s2.Close() + updated, err := GetUserWithEmail(s2, &User{ID: 1}) + require.NoError(t, err) + assert.Equal(t, StatusEmailConfirmationRequired, updated.Status) + assert.Equal(t, "new1@example.com", updated.Email) + }) + + t.Run("mailer disabled", func(t *testing.T) { + db.LoadAndAssertFixtures(t) + s := db.NewSession() + defer s.Close() + + config.MailerEnabled.Set(false) + + err := UpdateEmail(s, &EmailUpdate{User: &User{ID: 2}, NewEmail: "new2@example.com"}) + require.NoError(t, err) + + err = s.Commit() + require.NoError(t, err) + + s2 := db.NewSession() + defer s2.Close() + updated, err := GetUserWithEmail(s2, &User{ID: 2}) + require.NoError(t, err) + assert.Equal(t, StatusActive, updated.Status) + assert.Equal(t, "new2@example.com", updated.Email) + }) +} diff --git a/pkg/user/user.go b/pkg/user/user.go index 6f6d44662..f0252e634 100644 --- a/pkg/user/user.go +++ b/pkg/user/user.go @@ -596,7 +596,7 @@ func UpdateUser(s *xorm.Session, user *User, forceOverride bool) (updatedUser *U "email", "avatar_provider", "avatar_file_id", - "is_active", + "status", "name", "email_reminders_enabled", "discoverable_by_name", diff --git a/pkg/user/user_create.go b/pkg/user/user_create.go index d25e0e975..79c790b9e 100644 --- a/pkg/user/user_create.go +++ b/pkg/user/user_create.go @@ -108,7 +108,7 @@ func CreateUser(s *xorm.Session, user *User) (newUser *User, err error) { _, err = s. Where("id = ?", user.ID). - Cols("email", "is_active"). + Cols("email", "status"). Update(user) if err != nil { return diff --git a/pkg/user/user_email_confirm.go b/pkg/user/user_email_confirm.go index 498146d16..6e7c72346 100644 --- a/pkg/user/user_email_confirm.go +++ b/pkg/user/user_email_confirm.go @@ -54,7 +54,7 @@ func ConfirmEmail(s *xorm.Session, c *EmailConfirm) (err error) { } _, err = s. Where("id = ?", user.ID). - Cols("is_active"). + Cols("status"). Update(user) return }