mirror of
https://github.com/bitwarden/server
synced 2025-12-14 15:23:42 +00:00
[PM-22104] Migrate default collection when org user is removed (#6135)
* migrate default collection to a shared collection when users are removed * remove redundant logic * fix test * fix tests * fix test * clean up * add migrations * run dotnet format * clean up, refactor duplicate logic to sproc, wip integration test * fix sql * add migration for new sproc * integration test wip * integration test wip * integration test wip * integration test wip * fix integration test LINQ expression * fix using wrong Id * wip integration test for DeleteManyAsync * fix LINQ * only set DefaultUserEmail when it is null in sproc * check for null * spelling, separate create and update request models * fix test * fix child class * refactor sproc * clean up * more cleanup * fix tests * fix user email * remove unneccesary test * add DefaultUserCollectionEmail to EF query * fix test * fix EF logic to match sprocs * clean up logic * cleanup
This commit is contained in:
@@ -22,7 +22,7 @@ namespace Bit.Api.Test.Controllers;
|
||||
public class CollectionsControllerTests
|
||||
{
|
||||
[Theory, BitAutoData]
|
||||
public async Task Post_Success(Organization organization, CollectionRequestModel collectionRequest,
|
||||
public async Task Post_Success(Organization organization, CreateCollectionRequestModel collectionRequest,
|
||||
SutProvider<CollectionsController> sutProvider)
|
||||
{
|
||||
Collection ExpectedCollection() => Arg.Is<Collection>(c =>
|
||||
@@ -46,9 +46,10 @@ public class CollectionsControllerTests
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Put_Success(Collection collection, CollectionRequestModel collectionRequest,
|
||||
public async Task Put_Success(Collection collection, UpdateCollectionRequestModel collectionRequest,
|
||||
SutProvider<CollectionsController> sutProvider)
|
||||
{
|
||||
collection.DefaultUserCollectionEmail = null;
|
||||
Collection ExpectedCollection() => Arg.Is<Collection>(c => c.Id == collection.Id &&
|
||||
c.Name == collectionRequest.Name && c.ExternalId == collectionRequest.ExternalId &&
|
||||
c.OrganizationId == collection.OrganizationId);
|
||||
@@ -72,7 +73,7 @@ public class CollectionsControllerTests
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Put_WithNoCollectionPermission_ThrowsNotFound(Collection collection, CollectionRequestModel collectionRequest,
|
||||
public async Task Put_WithNoCollectionPermission_ThrowsNotFound(Collection collection, UpdateCollectionRequestModel collectionRequest,
|
||||
SutProvider<CollectionsController> sutProvider)
|
||||
{
|
||||
sutProvider.GetDependency<IAuthorizationService>()
|
||||
@@ -484,4 +485,176 @@ public class CollectionsControllerTests
|
||||
await sutProvider.GetDependency<IBulkAddCollectionAccessCommand>().DidNotReceiveWithAnyArgs()
|
||||
.AddAccessAsync(default, default, default);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Put_With_NonNullName_DoesNotPreserveExistingName(Collection existingCollection, UpdateCollectionRequestModel collectionRequest,
|
||||
SutProvider<CollectionsController> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
var newName = "new name";
|
||||
var originalName = "original name";
|
||||
|
||||
existingCollection.Name = originalName;
|
||||
existingCollection.DefaultUserCollectionEmail = null;
|
||||
|
||||
collectionRequest.Name = newName;
|
||||
|
||||
sutProvider.GetDependency<ICollectionRepository>()
|
||||
.GetByIdAsync(existingCollection.Id)
|
||||
.Returns(existingCollection);
|
||||
|
||||
sutProvider.GetDependency<IAuthorizationService>()
|
||||
.AuthorizeAsync(Arg.Any<ClaimsPrincipal>(),
|
||||
existingCollection,
|
||||
Arg.Is<IEnumerable<IAuthorizationRequirement>>(r => r.Contains(BulkCollectionOperations.Update)))
|
||||
.Returns(AuthorizationResult.Success());
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.Put(existingCollection.OrganizationId, existingCollection.Id, collectionRequest);
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IUpdateCollectionCommand>()
|
||||
.Received(1)
|
||||
.UpdateAsync(
|
||||
Arg.Is<Collection>(c => c.Id == existingCollection.Id && c.Name == newName),
|
||||
Arg.Any<IEnumerable<CollectionAccessSelection>>(),
|
||||
Arg.Any<IEnumerable<CollectionAccessSelection>>());
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Put_WithNullName_DoesPreserveExistingName(Collection existingCollection, UpdateCollectionRequestModel collectionRequest,
|
||||
SutProvider<CollectionsController> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
var originalName = "original name";
|
||||
|
||||
existingCollection.Name = originalName;
|
||||
existingCollection.DefaultUserCollectionEmail = null;
|
||||
|
||||
collectionRequest.Name = null;
|
||||
|
||||
sutProvider.GetDependency<ICollectionRepository>()
|
||||
.GetByIdAsync(existingCollection.Id)
|
||||
.Returns(existingCollection);
|
||||
|
||||
sutProvider.GetDependency<IAuthorizationService>()
|
||||
.AuthorizeAsync(Arg.Any<ClaimsPrincipal>(),
|
||||
existingCollection,
|
||||
Arg.Is<IEnumerable<IAuthorizationRequirement>>(r => r.Contains(BulkCollectionOperations.Update)))
|
||||
.Returns(AuthorizationResult.Success());
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.Put(existingCollection.OrganizationId, existingCollection.Id, collectionRequest);
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IUpdateCollectionCommand>()
|
||||
.Received(1)
|
||||
.UpdateAsync(
|
||||
Arg.Is<Collection>(c => c.Id == existingCollection.Id && c.Name == originalName),
|
||||
Arg.Any<IEnumerable<CollectionAccessSelection>>(),
|
||||
Arg.Any<IEnumerable<CollectionAccessSelection>>());
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Put_WithDefaultUserCollectionEmail_DoesPreserveExistingName(Collection existingCollection, UpdateCollectionRequestModel collectionRequest,
|
||||
SutProvider<CollectionsController> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
var originalName = "original name";
|
||||
var defaultUserCollectionEmail = "user@email.com";
|
||||
|
||||
existingCollection.Name = originalName;
|
||||
existingCollection.DefaultUserCollectionEmail = defaultUserCollectionEmail;
|
||||
|
||||
collectionRequest.Name = "new name";
|
||||
|
||||
sutProvider.GetDependency<ICollectionRepository>()
|
||||
.GetByIdAsync(existingCollection.Id)
|
||||
.Returns(existingCollection);
|
||||
|
||||
sutProvider.GetDependency<IAuthorizationService>()
|
||||
.AuthorizeAsync(Arg.Any<ClaimsPrincipal>(),
|
||||
existingCollection,
|
||||
Arg.Is<IEnumerable<IAuthorizationRequirement>>(r => r.Contains(BulkCollectionOperations.Update)))
|
||||
.Returns(AuthorizationResult.Success());
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.Put(existingCollection.OrganizationId, existingCollection.Id, collectionRequest);
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IUpdateCollectionCommand>()
|
||||
.Received(1)
|
||||
.UpdateAsync(
|
||||
Arg.Is<Collection>(c => c.Id == existingCollection.Id && c.Name == originalName && c.DefaultUserCollectionEmail == defaultUserCollectionEmail),
|
||||
Arg.Any<IEnumerable<CollectionAccessSelection>>(),
|
||||
Arg.Any<IEnumerable<CollectionAccessSelection>>());
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Put_WithEmptyName_DoesPreserveExistingName(Collection existingCollection, UpdateCollectionRequestModel collectionRequest,
|
||||
SutProvider<CollectionsController> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
var originalName = "original name";
|
||||
|
||||
existingCollection.Name = originalName;
|
||||
existingCollection.DefaultUserCollectionEmail = null;
|
||||
|
||||
collectionRequest.Name = ""; // Empty string
|
||||
|
||||
sutProvider.GetDependency<ICollectionRepository>()
|
||||
.GetByIdAsync(existingCollection.Id)
|
||||
.Returns(existingCollection);
|
||||
|
||||
sutProvider.GetDependency<IAuthorizationService>()
|
||||
.AuthorizeAsync(Arg.Any<ClaimsPrincipal>(),
|
||||
existingCollection,
|
||||
Arg.Is<IEnumerable<IAuthorizationRequirement>>(r => r.Contains(BulkCollectionOperations.Update)))
|
||||
.Returns(AuthorizationResult.Success());
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.Put(existingCollection.OrganizationId, existingCollection.Id, collectionRequest);
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IUpdateCollectionCommand>()
|
||||
.Received(1)
|
||||
.UpdateAsync(
|
||||
Arg.Is<Collection>(c => c.Id == existingCollection.Id && c.Name == originalName),
|
||||
Arg.Any<IEnumerable<CollectionAccessSelection>>(),
|
||||
Arg.Any<IEnumerable<CollectionAccessSelection>>());
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Put_WithWhitespaceOnlyName_DoesPreserveExistingName(Collection existingCollection, UpdateCollectionRequestModel collectionRequest,
|
||||
SutProvider<CollectionsController> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
var originalName = "original name";
|
||||
|
||||
existingCollection.Name = originalName;
|
||||
existingCollection.DefaultUserCollectionEmail = null;
|
||||
|
||||
collectionRequest.Name = " "; // Whitespace only
|
||||
|
||||
sutProvider.GetDependency<ICollectionRepository>()
|
||||
.GetByIdAsync(existingCollection.Id)
|
||||
.Returns(existingCollection);
|
||||
|
||||
sutProvider.GetDependency<IAuthorizationService>()
|
||||
.AuthorizeAsync(Arg.Any<ClaimsPrincipal>(),
|
||||
existingCollection,
|
||||
Arg.Is<IEnumerable<IAuthorizationRequirement>>(r => r.Contains(BulkCollectionOperations.Update)))
|
||||
.Returns(AuthorizationResult.Success());
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.Put(existingCollection.OrganizationId, existingCollection.Id, collectionRequest);
|
||||
|
||||
// Assert
|
||||
await sutProvider.GetDependency<IUpdateCollectionCommand>()
|
||||
.Received(1)
|
||||
.UpdateAsync(
|
||||
Arg.Is<Collection>(c => c.Id == existingCollection.Id && c.Name == originalName),
|
||||
Arg.Any<IEnumerable<CollectionAccessSelection>>(),
|
||||
Arg.Any<IEnumerable<CollectionAccessSelection>>());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user