1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-21 12:05:42 +01:00

[PM-11409] prevent managed user from leaving managing organization (#4995)

* prevent managed user from leaving managing organization

* fix org check to be specific to single org

* simplify logic
This commit is contained in:
Brandon Treston 2024-11-07 14:10:00 -05:00 committed by GitHub
parent 4adcecb80a
commit 15bc5060c6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 40 additions and 2 deletions

View File

@ -252,6 +252,12 @@ public class OrganizationsController : Controller
throw new BadRequestException("Your organization's Single Sign-On settings prevent you from leaving."); throw new BadRequestException("Your organization's Single Sign-On settings prevent you from leaving.");
} }
if (_featureService.IsEnabled(FeatureFlagKeys.AccountDeprovisioning)
&& (await _userService.GetOrganizationsManagingUserAsync(user.Id)).Any(x => x.Id == id))
{
throw new BadRequestException("Managed user account cannot leave managing organization. Contact your organization administrator for additional details.");
}
await _removeOrganizationUserCommand.RemoveUserAsync(id, user.Id); await _removeOrganizationUserCommand.RemoveUserAsync(id, user.Id);
} }

View File

@ -51,7 +51,6 @@ public class OrganizationsControllerTests : IDisposable
private readonly IProviderBillingService _providerBillingService; private readonly IProviderBillingService _providerBillingService;
private readonly IDataProtectorTokenFactory<OrgDeleteTokenable> _orgDeleteTokenDataFactory; private readonly IDataProtectorTokenFactory<OrgDeleteTokenable> _orgDeleteTokenDataFactory;
private readonly IRemoveOrganizationUserCommand _removeOrganizationUserCommand; private readonly IRemoveOrganizationUserCommand _removeOrganizationUserCommand;
private readonly OrganizationsController _sut; private readonly OrganizationsController _sut;
public OrganizationsControllerTests() public OrganizationsControllerTests()
@ -123,7 +122,8 @@ public class OrganizationsControllerTests : IDisposable
_currentContext.OrganizationUser(orgId).Returns(true); _currentContext.OrganizationUser(orgId).Returns(true);
_ssoConfigRepository.GetByOrganizationIdAsync(orgId).Returns(ssoConfig); _ssoConfigRepository.GetByOrganizationIdAsync(orgId).Returns(ssoConfig);
_userService.GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>()).Returns(user); _userService.GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>()).Returns(user);
_featureService.IsEnabled(FeatureFlagKeys.AccountDeprovisioning).Returns(true);
_userService.GetOrganizationsManagingUserAsync(user.Id).Returns(new List<Organization> { null });
var exception = await Assert.ThrowsAsync<BadRequestException>(() => _sut.Leave(orgId)); var exception = await Assert.ThrowsAsync<BadRequestException>(() => _sut.Leave(orgId));
Assert.Contains("Your organization's Single Sign-On settings prevent you from leaving.", Assert.Contains("Your organization's Single Sign-On settings prevent you from leaving.",
@ -132,6 +132,36 @@ public class OrganizationsControllerTests : IDisposable
await _removeOrganizationUserCommand.DidNotReceiveWithAnyArgs().RemoveUserAsync(default, default); await _removeOrganizationUserCommand.DidNotReceiveWithAnyArgs().RemoveUserAsync(default, default);
} }
[Theory, AutoData]
public async Task OrganizationsController_UserCannotLeaveOrganizationThatManagesUser(
Guid orgId, User user)
{
var ssoConfig = new SsoConfig
{
Id = default,
Data = new SsoConfigurationData
{
MemberDecryptionType = MemberDecryptionType.KeyConnector
}.Serialize(),
Enabled = true,
OrganizationId = orgId,
};
var foundOrg = new Organization();
foundOrg.Id = orgId;
_currentContext.OrganizationUser(orgId).Returns(true);
_ssoConfigRepository.GetByOrganizationIdAsync(orgId).Returns(ssoConfig);
_userService.GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>()).Returns(user);
_featureService.IsEnabled(FeatureFlagKeys.AccountDeprovisioning).Returns(true);
_userService.GetOrganizationsManagingUserAsync(user.Id).Returns(new List<Organization> { { foundOrg } });
var exception = await Assert.ThrowsAsync<BadRequestException>(() => _sut.Leave(orgId));
Assert.Contains("Managed user account cannot leave managing organization. Contact your organization administrator for additional details.",
exception.Message);
await _removeOrganizationUserCommand.DidNotReceiveWithAnyArgs().RemoveUserAsync(default, default);
}
[Theory] [Theory]
[InlineAutoData(true, false)] [InlineAutoData(true, false)]
[InlineAutoData(false, true)] [InlineAutoData(false, true)]
@ -157,6 +187,8 @@ public class OrganizationsControllerTests : IDisposable
_currentContext.OrganizationUser(orgId).Returns(true); _currentContext.OrganizationUser(orgId).Returns(true);
_ssoConfigRepository.GetByOrganizationIdAsync(orgId).Returns(ssoConfig); _ssoConfigRepository.GetByOrganizationIdAsync(orgId).Returns(ssoConfig);
_userService.GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>()).Returns(user); _userService.GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>()).Returns(user);
_featureService.IsEnabled(FeatureFlagKeys.AccountDeprovisioning).Returns(true);
_userService.GetOrganizationsManagingUserAsync(user.Id).Returns(new List<Organization>());
await _sut.Leave(orgId); await _sut.Leave(orgId);