mirror of
https://github.com/bitwarden/server.git
synced 2025-12-10 17:45:21 -06:00
[PM-20010] Fix purge logic to skip claimed user check for organization vault (#6107)
* Implement unit tests for PostPurge method in CiphersController to handle various scenarios * Refactor PostPurge method in CiphersController to use Guid for organizationId parameter and update related unit tests * Refactor PostPurge method in CiphersController to skip checking if user is claimed if its purging the org vault
This commit is contained in:
parent
47237fa88f
commit
43372b7168
@ -1113,7 +1113,7 @@ public class CiphersController : Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("purge")]
|
[HttpPost("purge")]
|
||||||
public async Task PostPurge([FromBody] SecretVerificationRequestModel model, string organizationId = null)
|
public async Task PostPurge([FromBody] SecretVerificationRequestModel model, Guid? organizationId = null)
|
||||||
{
|
{
|
||||||
var user = await _userService.GetUserByPrincipalAsync(User);
|
var user = await _userService.GetUserByPrincipalAsync(User);
|
||||||
if (user == null)
|
if (user == null)
|
||||||
@ -1128,24 +1128,22 @@ public class CiphersController : Controller
|
|||||||
throw new BadRequestException(ModelState);
|
throw new BadRequestException(ModelState);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the user is claimed by any organization.
|
if (organizationId == null)
|
||||||
if (await _userService.IsClaimedByAnyOrganizationAsync(user.Id))
|
|
||||||
{
|
|
||||||
throw new BadRequestException("Cannot purge accounts owned by an organization. Contact your organization administrator for additional details.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(organizationId))
|
|
||||||
{
|
{
|
||||||
|
// Check if the user is claimed by any organization.
|
||||||
|
if (await _userService.IsClaimedByAnyOrganizationAsync(user.Id))
|
||||||
|
{
|
||||||
|
throw new BadRequestException("Cannot purge accounts owned by an organization. Contact your organization administrator for additional details.");
|
||||||
|
}
|
||||||
await _cipherRepository.DeleteByUserIdAsync(user.Id);
|
await _cipherRepository.DeleteByUserIdAsync(user.Id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var orgId = new Guid(organizationId);
|
if (!await _currentContext.EditAnyCollection(organizationId!.Value))
|
||||||
if (!await _currentContext.EditAnyCollection(orgId))
|
|
||||||
{
|
{
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
await _cipherService.PurgeAsync(orgId);
|
await _cipherService.PurgeAsync(organizationId!.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using Bit.Api.Auth.Models.Request.Accounts;
|
||||||
using Bit.Api.Vault.Controllers;
|
using Bit.Api.Vault.Controllers;
|
||||||
using Bit.Api.Vault.Models;
|
using Bit.Api.Vault.Models;
|
||||||
using Bit.Api.Vault.Models.Request;
|
using Bit.Api.Vault.Models.Request;
|
||||||
@ -1789,5 +1790,123 @@ public class CiphersControllerTests
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
[Theory, BitAutoData]
|
||||||
|
public async Task PostPurge_WhenUserNotFound_ThrowsUnauthorizedAccessException(
|
||||||
|
SecretVerificationRequestModel model,
|
||||||
|
SutProvider<CiphersController> sutProvider)
|
||||||
|
{
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>())
|
||||||
|
.Returns((User)null);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<UnauthorizedAccessException>(() => sutProvider.Sut.PostPurge(model));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task PostPurge_WhenUserVerificationFails_ThrowsBadRequestException(
|
||||||
|
User user,
|
||||||
|
SecretVerificationRequestModel model,
|
||||||
|
SutProvider<CiphersController> sutProvider)
|
||||||
|
{
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>())
|
||||||
|
.Returns(user);
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.VerifySecretAsync(user, model.Secret)
|
||||||
|
.Returns(false);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.PostPurge(model));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task PostPurge_UserPurge_WithClaimedUser_ThrowsBadRequestException(
|
||||||
|
User user,
|
||||||
|
SecretVerificationRequestModel model,
|
||||||
|
SutProvider<CiphersController> sutProvider)
|
||||||
|
{
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>())
|
||||||
|
.Returns(user);
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.VerifySecretAsync(user, model.Secret)
|
||||||
|
.Returns(true);
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.IsClaimedByAnyOrganizationAsync(user.Id)
|
||||||
|
.Returns(true);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.PostPurge(model));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task PostPurge_UserPurge_WithUnclaimedUser_Successful(
|
||||||
|
User user,
|
||||||
|
SecretVerificationRequestModel model,
|
||||||
|
SutProvider<CiphersController> sutProvider)
|
||||||
|
{
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>())
|
||||||
|
.Returns(user);
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.VerifySecretAsync(user, model.Secret)
|
||||||
|
.Returns(true);
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.IsClaimedByAnyOrganizationAsync(user.Id)
|
||||||
|
.Returns(false);
|
||||||
|
|
||||||
|
await sutProvider.Sut.PostPurge(model);
|
||||||
|
|
||||||
|
await sutProvider.GetDependency<ICipherRepository>()
|
||||||
|
.Received(1)
|
||||||
|
.DeleteByUserIdAsync(user.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task PostPurge_OrganizationPurge_WithEditAnyCollectionPermission_Successful(
|
||||||
|
User user,
|
||||||
|
SecretVerificationRequestModel model,
|
||||||
|
Guid organizationId,
|
||||||
|
SutProvider<CiphersController> sutProvider)
|
||||||
|
{
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>())
|
||||||
|
.Returns(user);
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.VerifySecretAsync(user, model.Secret)
|
||||||
|
.Returns(true);
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.IsClaimedByAnyOrganizationAsync(user.Id)
|
||||||
|
.Returns(true);
|
||||||
|
sutProvider.GetDependency<ICurrentContext>()
|
||||||
|
.EditAnyCollection(organizationId)
|
||||||
|
.Returns(true);
|
||||||
|
|
||||||
|
await sutProvider.Sut.PostPurge(model, organizationId);
|
||||||
|
|
||||||
|
await sutProvider.GetDependency<ICipherService>()
|
||||||
|
.Received(1)
|
||||||
|
.PurgeAsync(organizationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task PostPurge_OrganizationPurge_WithInsufficientPermissions_ThrowsNotFoundException(
|
||||||
|
User user,
|
||||||
|
Guid organizationId,
|
||||||
|
SecretVerificationRequestModel model,
|
||||||
|
SutProvider<CiphersController> sutProvider)
|
||||||
|
{
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>())
|
||||||
|
.Returns(user);
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.VerifySecretAsync(user, model.Secret)
|
||||||
|
.Returns(true);
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.IsClaimedByAnyOrganizationAsync(user.Id)
|
||||||
|
.Returns(false);
|
||||||
|
sutProvider.GetDependency<ICurrentContext>()
|
||||||
|
.EditAnyCollection(organizationId)
|
||||||
|
.Returns(false);
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.PostPurge(model, organizationId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user