Skip to content

Commit cbb1eae

Browse files
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 <[email protected]>
1 parent a2b2ecb commit cbb1eae

File tree

4 files changed

+24
-3
lines changed

4 files changed

+24
-3
lines changed

src/Umbraco.Cms.Api.Management/Controllers/User/UserOrCurrentUserControllerBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ protected IActionResult UserOperationStatusResult(UserOperationStatus status, Er
2525
.Build()),
2626
UserOperationStatus.NoUserGroup => BadRequest(problemDetailsBuilder
2727
.WithTitle("No User Group Specified")
28-
.WithDetail("A user group must be specified to create a user")
28+
.WithDetail("A user must be assigned to at least one group")
2929
.Build()),
3030
UserOperationStatus.UserNameIsNotEmail => BadRequest(problemDetailsBuilder
3131
.WithTitle("Invalid Username")

src/Umbraco.Core/Services/UserService.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ private async Task<UserOperationStatus> ValidateUserCreateModel(UserCreateModel
883883
return UserOperationStatus.DuplicateUserName;
884884
}
885885

886-
if(model.UserGroupKeys.Count == 0)
886+
if (model.UserGroupKeys.Count == 0)
887887
{
888888
return UserOperationStatus.NoUserGroup;
889889
}
@@ -912,6 +912,13 @@ private async Task<UserOperationStatus> ValidateUserCreateModel(UserCreateModel
912912
return Attempt.FailWithStatus<IUser?, UserOperationStatus>(UserOperationStatus.MissingUser, existingUser);
913913
}
914914

915+
// A user must remain assigned to at least one group.
916+
if (model.UserGroupKeys.Count == 0)
917+
{
918+
scope.Complete();
919+
return Attempt.FailWithStatus<IUser?, UserOperationStatus>(UserOperationStatus.NoUserGroup, existingUser);
920+
}
921+
915922
// User names can only contain the configured allowed characters. This is validated by ASP.NET Identity on create
916923
// as the setting is applied to the BackOfficeIdentityOptions, but we need to check ourselves for updates.
917924
var allowedUserNameCharacters = _securitySettings.AllowedUserNameCharacters;

tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/User.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,4 +642,4 @@ test.skip('cannot remove all user group from a user', {tag: '@release'}, async (
642642

643643
// Assert
644644
await umbracoUi.user.isErrorNotificationVisible();
645-
});
645+
});

tests/Umbraco.Tests.Integration/Umbraco.Core/Services/UserServiceCrudTests.Update.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,21 @@ public async Task Can_Update_User_Name()
151151
Assert.AreEqual(email, updatedUser.Email);
152152
Assert.AreEqual(name, updatedUser.Name);
153153
});
154+
}
155+
156+
[Test]
157+
public async Task Cannot_Update_User_To_Have_No_Groups()
158+
{
159+
var userService = CreateUserService(securitySettings: new SecuritySettings { UsernameIsEmail = false });
154160

161+
var (updateModel, createdUser) = await CreateUserForUpdate(userService);
162+
163+
updateModel.UserGroupKeys.Clear();
164+
165+
var updateAttempt = await userService.UpdateAsync(Constants.Security.SuperUserKey, updateModel);
166+
167+
Assert.IsFalse(updateAttempt.Success);
168+
Assert.AreEqual(UserOperationStatus.NoUserGroup, updateAttempt.Status);
155169
}
156170

157171
[Test]

0 commit comments

Comments
 (0)