From a77bf48b41c45b7715c340e853b857b1a5f8ceca Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Thu, 16 Jul 2026 01:53:43 -0600 Subject: [PATCH] fix: 500 error when updating user visibility (#38480) ## How to reproduce this bug 1. Create a user with `visibility=public` 2. Update `ALLOWED_USER_VISIBILITY_MODES` setting to `limited, private` 3. Modify any field other than "User visibility" (e.g. "Full Name") 4. UI shows 500 error ## Fix Only update the visibility field when it actually changes. --- services/user/update.go | 3 ++- services/user/update_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/services/user/update.go b/services/user/update.go index fe1693e1dfc..441e0217749 100644 --- a/services/user/update.go +++ b/services/user/update.go @@ -145,7 +145,8 @@ func UpdateUser(ctx context.Context, u *user_model.User, opts *UpdateOptions) er } } - if opts.Visibility.Has() { + // only validate and persist the visibility when it actually changes + if opts.Visibility.Has() && opts.Visibility.Value() != u.Visibility { if !u.IsOrganization() && !setting.Service.AllowedUserVisibilityModesSlice.IsAllowedVisibility(opts.Visibility.Value()) { return fmt.Errorf("visibility mode not allowed: %s", opts.Visibility.Value().String()) } diff --git a/services/user/update_test.go b/services/user/update_test.go index 9d829ad7fd7..8ef59a99c02 100644 --- a/services/user/update_test.go +++ b/services/user/update_test.go @@ -10,7 +10,9 @@ import ( user_model "gitea.dev/models/user" password_module "gitea.dev/modules/auth/password" "gitea.dev/modules/optional" + "gitea.dev/modules/setting" "gitea.dev/modules/structs" + "gitea.dev/modules/test" "github.com/stretchr/testify/assert" ) @@ -121,3 +123,33 @@ func TestUpdateAuth(t *testing.T) { Password: optional.Some("aaaa"), }), password_module.ErrMinLength) } + +func TestUpdateUserVisibility(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + // user28's current visibility is public, e.g. an account created before public was disallowed + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 28}) + assert.Equal(t, structs.VisibleTypePublic, user.Visibility) + + // public is no longer an allowed visibility mode, e.g. ALLOWED_USER_VISIBILITY_MODES = limited, private + defer test.MockVariableValue(&setting.Service.AllowedUserVisibilityModesSlice, setting.AllowedVisibility{false, true, true})() + + // re-submitting the unchanged (now-disallowed) visibility must not fail the whole update + assert.NoError(t, UpdateUser(t.Context(), user, &UpdateOptions{ + FullName: optional.Some("Changed Name"), + Visibility: optional.Some(structs.VisibleTypePublic), + })) + assert.Equal(t, "Changed Name", user.FullName) + assert.Equal(t, structs.VisibleTypePublic, user.Visibility) + + // changing to an allowed visibility still works + assert.NoError(t, UpdateUser(t.Context(), user, &UpdateOptions{ + Visibility: optional.Some(structs.VisibleTypePrivate), + })) + assert.Equal(t, structs.VisibleTypePrivate, user.Visibility) + + // genuinely changing to a disallowed visibility is still rejected + assert.Error(t, UpdateUser(t.Context(), user, &UpdateOptions{ + Visibility: optional.Some(structs.VisibleTypePublic), + })) +}