mirror of
https://github.com/bitwarden/server.git
synced 2024-12-01 13:43:23 +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:
parent
88323f4fde
commit
f30f247c64
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user