diff --git a/server/channels/api4/user.go b/server/channels/api4/user.go index 31cc111c4c..84e3ddbc53 100644 --- a/server/channels/api4/user.go +++ b/server/channels/api4/user.go @@ -3127,6 +3127,7 @@ func verifyUserEmailWithoutToken(c *Context, w http.ResponseWriter, r *http.Requ auditRec.Success() c.LogAudit("user verified") + c.App.SanitizeProfile(user, true) if err := json.NewEncoder(w).Encode(user); err != nil { c.Logger.Warn("Error while writing response", mlog.Err(err)) } diff --git a/server/channels/api4/user_test.go b/server/channels/api4/user_test.go index 7d4375facf..1907e8f20d 100644 --- a/server/channels/api4/user_test.go +++ b/server/channels/api4/user_test.go @@ -6602,6 +6602,51 @@ func TestVerifyUserEmailWithoutToken(t *testing.T) { require.Equal(t, ruser.Id, vuser.Id) }, "Should verify a new user") + th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { + // Enable MFA for this test + th.App.Srv().SetLicense(model.NewTestLicense("mfa")) + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableMultifactorAuthentication = true }) + + email := th.GenerateTestEmail() + user := model.User{Email: email, Nickname: "Test User", Password: "password123", Username: GenerateTestUsername(), Roles: model.SystemUserRoleId} + ruser, _, _ := th.Client.CreateUser(context.Background(), &user) + + // Set some NotifyProps to ensure we have data to verify is preserved + ruser.NotifyProps = map[string]string{ + "email": "true", + "push": "mention", + "desktop": "mention", + "channel": "true", + } + _, appErr := th.App.UpdateUser(th.Context, ruser, false) + require.Nil(t, appErr) + + // Set up MFA secret for the user + secret, appErr := th.App.GenerateMfaSecret(ruser.Id) + require.Nil(t, appErr) + err := th.Server.Store().User().UpdateMfaSecret(ruser.Id, secret.Secret) + require.NoError(t, err) + + // Verify the user has a password hash and MFA secret in the database + dbUser, appErr := th.App.GetUser(ruser.Id) + require.Nil(t, appErr) + require.NotEmpty(t, dbUser.Password, "User should have a password hash in database") + require.NotEmpty(t, dbUser.MfaSecret, "User should have MFA secret in database") + + // Call the API endpoint + vuser, _, err := client.VerifyUserEmailWithoutToken(context.Background(), ruser.Id) + require.NoError(t, err) + require.Equal(t, ruser.Id, vuser.Id) + + // Verify sensitive fields are sanitized in the response + require.Empty(t, vuser.Password, "Password hash should be sanitized from response") + require.Empty(t, vuser.MfaSecret, "MFA secret should be sanitized from response") + + // Verify admin-level fields like NotifyProps are preserved for system admin + require.NotEmpty(t, vuser.NotifyProps, "NotifyProps should be preserved for system admin") + require.Equal(t, "true", vuser.NotifyProps["email"], "NotifyProps data should be preserved for system admin") + }, "Should sanitize password hash and MFA secret from response") + th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) { vuser, _, err := client.VerifyUserEmailWithoutToken(context.Background(), "randomId") require.Error(t, err)