Prevents the removal of all user groups from a user (#19995)

* Prevents the removal of all user groups from a user.

* Add additional user group when removing

---------

Co-authored-by: mole <nikolajlauridsen@protonmail.ch>
This commit is contained in:
Andy Butland
2025-08-27 13:38:28 +02:00
committed by GitHub
parent a2b2ecb221
commit cbb1eaec28
4 changed files with 24 additions and 3 deletions

View File

@@ -25,7 +25,7 @@ public abstract class UserOrCurrentUserControllerBase : ManagementApiControllerB
.Build()),
UserOperationStatus.NoUserGroup => BadRequest(problemDetailsBuilder
.WithTitle("No User Group Specified")
.WithDetail("A user group must be specified to create a user")
.WithDetail("A user must be assigned to at least one group")
.Build()),
UserOperationStatus.UserNameIsNotEmail => BadRequest(problemDetailsBuilder
.WithTitle("Invalid Username")

View File

@@ -883,7 +883,7 @@ internal partial class UserService : RepositoryService, IUserService
return UserOperationStatus.DuplicateUserName;
}
if(model.UserGroupKeys.Count == 0)
if (model.UserGroupKeys.Count == 0)
{
return UserOperationStatus.NoUserGroup;
}
@@ -912,6 +912,13 @@ internal partial class UserService : RepositoryService, IUserService
return Attempt.FailWithStatus<IUser?, UserOperationStatus>(UserOperationStatus.MissingUser, existingUser);
}
// A user must remain assigned to at least one group.
if (model.UserGroupKeys.Count == 0)
{
scope.Complete();
return Attempt.FailWithStatus<IUser?, UserOperationStatus>(UserOperationStatus.NoUserGroup, existingUser);
}
// User names can only contain the configured allowed characters. This is validated by ASP.NET Identity on create
// as the setting is applied to the BackOfficeIdentityOptions, but we need to check ourselves for updates.
var allowedUserNameCharacters = _securitySettings.AllowedUserNameCharacters;

View File

@@ -642,4 +642,4 @@ test.skip('cannot remove all user group from a user', {tag: '@release'}, async (
// Assert
await umbracoUi.user.isErrorNotificationVisible();
});
});

View File

@@ -151,7 +151,21 @@ internal sealed partial class UserServiceCrudTests
Assert.AreEqual(email, updatedUser.Email);
Assert.AreEqual(name, updatedUser.Name);
});
}
[Test]
public async Task Cannot_Update_User_To_Have_No_Groups()
{
var userService = CreateUserService(securitySettings: new SecuritySettings { UsernameIsEmail = false });
var (updateModel, createdUser) = await CreateUserForUpdate(userService);
updateModel.UserGroupKeys.Clear();
var updateAttempt = await userService.UpdateAsync(Constants.Security.SuperUserKey, updateModel);
Assert.IsFalse(updateAttempt.Success);
Assert.AreEqual(UserOperationStatus.NoUserGroup, updateAttempt.Status);
}
[Test]