1
0
mirror of https://github.com/bitwarden/server synced 2025-12-15 15:53:59 +00:00

[PM-23987] Fix saving to default collections by updating collection lookup (#6122)

* Refactor ICollectionRepository.GetManyByOrganizationIdAsync logic to include default user collections

* Add stored procedure Collection_ReadSharedCollectionsByOrganizationId to retrieve collections by organization ID, excluding default user collections.

* Add GetManySharedCollectionsByOrganizationIdAsync method to ICollectionRepository and its implementations to retrieve collections excluding default user collections.

* Add unit test for GetManySharedCollectionsByOrganizationIdAsync method in CollectionRepositoryTests to verify retrieval of collections excluding default user collections.

* Refactor controllers to use GetManySharedCollectionsByOrganizationIdAsync for retrieving shared collections

* Update unit tests to use GetManySharedCollectionsByOrganizationIdAsync for verifying shared collections retrieval

* Revert CiphersController.CanEditItemsInCollections to use GetManyByOrganizationIdAsync for retrieving organization collections

* Update stored procedures to retrieve only DefaultUserCollection by modifying the WHERE clause in Collection_ReadSharedCollectionsByOrganizationId.sql and its corresponding migration script.

* Update EF CollectionRepository.GetManySharedCollectionsByOrganizationIdAsync to filter collections by SharedCollection

* Update OrganizationUserRepository.GetManyDetailsByOrganizationAsync_vNext to only include Shared collections

* Update comments in stored procedure and migration script to clarify filtering for SharedCollections only
This commit is contained in:
Rui Tomé
2025-07-29 15:04:00 +01:00
committed by GitHub
parent 52ef3ef7a5
commit 6dea40c868
13 changed files with 213 additions and 19 deletions

View File

@@ -525,7 +525,7 @@ public class CollectionRepositoryTests
var collection3 = new Collection { Name = "Collection 3", OrganizationId = organization.Id, };
await collectionRepository.CreateAsync(collection3, null, null);
// Create a default user collection (should not be returned by this method)
// Create a default user collection
var defaultCollection = new Collection
{
Name = "My Items",
@@ -536,12 +536,73 @@ public class CollectionRepositoryTests
var collections = await collectionRepository.GetManyByOrganizationIdAsync(organization.Id);
Assert.NotNull(collections);
Assert.Equal(4, collections.Count);
Assert.All(collections, c => Assert.Equal(organization.Id, c.OrganizationId));
Assert.Contains(collections, c => c.Name == "Collection 1");
Assert.Contains(collections, c => c.Name == "Collection 2");
Assert.Contains(collections, c => c.Name == "Collection 3");
Assert.Contains(collections, c => c.Name == "My Items");
}
/// <summary>
/// Test to ensure organization properly retrieves shared collections
/// </summary>
[DatabaseTheory, DatabaseData]
public async Task GetManySharedCollectionsByOrganizationIdAsync_Success(
IUserRepository userRepository,
IOrganizationRepository organizationRepository,
ICollectionRepository collectionRepository,
IOrganizationUserRepository organizationUserRepository)
{
var user = await userRepository.CreateAsync(new User
{
Name = "Test User",
Email = $"test+{Guid.NewGuid()}@email.com",
ApiKey = "TEST",
SecurityStamp = "stamp",
});
var organization = await organizationRepository.CreateAsync(new Organization
{
Name = "Test Org",
PlanType = PlanType.EnterpriseAnnually,
Plan = "Test Plan",
BillingEmail = "billing@email.com"
});
var orgUser = await organizationUserRepository.CreateAsync(new OrganizationUser
{
OrganizationId = organization.Id,
UserId = user.Id,
Status = OrganizationUserStatusType.Confirmed,
});
var collection1 = new Collection { Name = "Collection 1", OrganizationId = organization.Id, };
await collectionRepository.CreateAsync(collection1, null, null);
var collection2 = new Collection { Name = "Collection 2", OrganizationId = organization.Id, };
await collectionRepository.CreateAsync(collection2, null, null);
var collection3 = new Collection { Name = "Collection 3", OrganizationId = organization.Id, };
await collectionRepository.CreateAsync(collection3, null, null);
// Create a default user collection (should not be returned by this method)
var defaultCollection = new Collection
{
Name = "My Items",
OrganizationId = organization.Id,
Type = CollectionType.DefaultUserCollection
};
await collectionRepository.CreateAsync(defaultCollection, null, null);
var collections = await collectionRepository.GetManySharedCollectionsByOrganizationIdAsync(organization.Id);
Assert.NotNull(collections);
Assert.Equal(3, collections.Count); // Should only return the 3 shared collections, excluding the default user collection
Assert.All(collections, c => Assert.Equal(organization.Id, c.OrganizationId));
Assert.All(collections, c => Assert.NotEqual(CollectionType.DefaultUserCollection, c.Type));
// Verify specific collections are returned
Assert.Contains(collections, c => c.Name == "Collection 1");
Assert.Contains(collections, c => c.Name == "Collection 2");
Assert.Contains(collections, c => c.Name == "Collection 3");

View File

@@ -911,6 +911,17 @@ public class OrganizationUserRepositoryTests
RevisionDate = requestTime
});
var defaultUserCollection = await collectionRepository.CreateAsync(new Collection
{
Id = CoreHelpers.GenerateComb(),
OrganizationId = organization.Id,
Name = "My Items",
Type = CollectionType.DefaultUserCollection,
DefaultUserCollectionEmail = user1.Email,
CreationDate = requestTime,
RevisionDate = requestTime
});
// Create organization user with both groups and collections using CreateManyAsync
var createOrgUserWithCollections = new List<CreateOrganizationUser>
{
@@ -940,6 +951,13 @@ public class OrganizationUserRepositoryTests
ReadOnly = false,
HidePasswords = true,
Manage = true
},
new CollectionAccessSelection
{
Id = defaultUserCollection.Id,
ReadOnly = false,
HidePasswords = false,
Manage = true
}
],
Groups = [group1.Id, group2.Id]
@@ -969,6 +987,7 @@ public class OrganizationUserRepositoryTests
Assert.Equal(2, user1Result.Collections.Count());
Assert.Contains(user1Result.Collections, c => c.Id == collection1.Id);
Assert.Contains(user1Result.Collections, c => c.Id == collection2.Id);
Assert.DoesNotContain(user1Result.Collections, c => c.Id == defaultUserCollection.Id);
}
[DatabaseTheory, DatabaseData]