diff --git a/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/CollectionRepository/CreateDefaultCollectionsTests.cs b/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/CollectionRepository/CreateDefaultCollectionsTests.cs
index ee97655562..a549aea80e 100644
--- a/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/CollectionRepository/CreateDefaultCollectionsTests.cs
+++ b/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/CollectionRepository/CreateDefaultCollectionsTests.cs
@@ -1,11 +1,5 @@
-using Bit.Core.AdminConsole.Entities;
-using Bit.Core.AdminConsole.Repositories;
-using Bit.Core.Billing.Enums;
-using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Repositories;
-using Bit.Infrastructure.EntityFramework.Repositories;
-using Microsoft.EntityFrameworkCore;
using Xunit;
namespace Bit.Infrastructure.IntegrationTest.AdminConsole.Repositories.CollectionRepository;
@@ -14,113 +8,87 @@ public class CreateDefaultCollectionsTests
{
///
/// Test that CreateDefaultCollectionsAsync successfully creates default collections for new users
+ /// with correct permissions
///
- [DatabaseTheory, DatabaseData]
- public async Task UpsertDefaultCollectionsAsync_CreatesDefaultCollections_Success(
+ [Theory, DatabaseData]
+ public async Task CreateDefaultCollectionsAsync_CreatesDefaultCollections_Success(
IUserRepository userRepository,
IOrganizationRepository organizationRepository,
ICollectionRepository collectionRepository,
IOrganizationUserRepository organizationUserRepository)
{
// Arrange
- var user1 = await userRepository.CreateAsync(new User
- {
- Name = "Test User 1",
- Email = $"test+{Guid.NewGuid()}@email.com",
- ApiKey = "TEST",
- SecurityStamp = "stamp",
- });
-
- var user2 = await userRepository.CreateAsync(new User
- {
- Name = "Test User 2",
- 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 orgUser1 = await organizationUserRepository.CreateAsync(new OrganizationUser
- {
- OrganizationId = organization.Id,
- UserId = user1.Id,
- Status = OrganizationUserStatusType.Confirmed,
- });
-
- var orgUser2 = await organizationUserRepository.CreateAsync(new OrganizationUser
- {
- OrganizationId = organization.Id,
- UserId = user2.Id,
- Status = OrganizationUserStatusType.Confirmed,
- });
+ var user1 = await userRepository.CreateTestUserAsync("user1");
+ var user2 = await userRepository.CreateTestUserAsync("user2");
+ var organization = await organizationRepository.CreateTestOrganizationAsync();
+ var orgUser1 = await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user1);
+ var orgUser2 = await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user2);
// Act
await collectionRepository.CreateDefaultCollectionsAsync(
organization.Id,
- new[] { orgUser1.Id, orgUser2.Id },
+ [orgUser1.Id, orgUser2.Id],
"My Items");
// Assert
- var collections = await collectionRepository.GetManyByOrganizationIdAsync(organization.Id);
- var defaultCollections = collections.Where(c => c.Type == CollectionType.DefaultUserCollection).ToList();
+ var collectionsWithAccess = await collectionRepository.GetManyByOrganizationIdWithAccessAsync(organization.Id);
+ var defaultCollections = collectionsWithAccess
+ .Where(c => c.Item1.Type == CollectionType.DefaultUserCollection)
+ .ToList();
Assert.Equal(2, defaultCollections.Count);
- Assert.All(defaultCollections, c => Assert.Equal("My Items", c.Name));
- Assert.All(defaultCollections, c => Assert.Equal(organization.Id, c.OrganizationId));
+ Assert.All(defaultCollections, c => Assert.Equal("My Items", c.Item1.Name));
+ Assert.All(defaultCollections, c => Assert.Equal(organization.Id, c.Item1.OrganizationId));
+
+ // Verify each user has exactly 1 collection with correct permissions
+ var orgUser1Collection = Assert.Single(defaultCollections,
+ c => c.Item2.Users.FirstOrDefault()?.Id == orgUser1.Id);
+
+ Assert.Empty(orgUser1Collection.Item2.Groups);
+
+ var orgUser1CollectionUser = orgUser1Collection.Item2.Users.Single();
+ Assert.False(orgUser1CollectionUser.ReadOnly);
+ Assert.False(orgUser1CollectionUser.HidePasswords);
+ Assert.True(orgUser1CollectionUser.Manage);
+
+ // Verify each user has exactly 1 collection with correct permissions
+ var orgUser2Collection = Assert.Single(defaultCollections,
+ c => c.Item2.Users.FirstOrDefault()?.Id == orgUser2.Id);
+
+ Assert.Empty(orgUser2Collection.Item2.Groups);
+
+ var orgUser2CollectionUser = orgUser2Collection.Item2.Users.Single();
+ Assert.False(orgUser2CollectionUser.ReadOnly);
+ Assert.False(orgUser2CollectionUser.HidePasswords);
+ Assert.True(orgUser2CollectionUser.Manage);
}
///
/// Test that calling CreateDefaultCollectionsAsync multiple times does NOT create duplicates
///
- [DatabaseTheory, DatabaseData]
- public async Task UpsertDefaultCollectionsAsync_CalledMultipleTimes_DoesNotCreateDuplicates(
+ [Theory, DatabaseData]
+ public async Task CreateDefaultCollectionsAsync_CalledMultipleTimes_DoesNotCreateDuplicates(
IUserRepository userRepository,
IOrganizationRepository organizationRepository,
ICollectionRepository collectionRepository,
IOrganizationUserRepository organizationUserRepository)
{
// Arrange
- 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 user = await userRepository.CreateTestUserAsync();
+ var organization = await organizationRepository.CreateTestOrganizationAsync();
+ var orgUser = await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user);
// Act - Call twice
await collectionRepository.CreateDefaultCollectionsAsync(
organization.Id,
- new[] { orgUser.Id },
+ [orgUser.Id],
"My Items");
- // Second call should not create duplicate
+ // Second call should throw and should not create duplicate
await Assert.ThrowsAnyAsync(() =>
collectionRepository.CreateDefaultCollectionsAsync(
organization.Id,
- new[] { orgUser.Id },
+ [orgUser.Id],
"My Items"));
// Assert - Only one collection should exist
@@ -128,251 +96,12 @@ public class CreateDefaultCollectionsTests
var defaultCollections = collections.Where(c => c.Type == CollectionType.DefaultUserCollection).ToList();
Assert.Single(defaultCollections);
- }
- ///
- /// Test that UpsertDefaultCollectionsBulkAsync creates semaphores before collections
- ///
- [DatabaseTheory, DatabaseData]
- public async Task UpsertDefaultCollectionsBulkAsync_CreatesSemaphoresBeforeCollections_Success(
- IUserRepository userRepository,
- IOrganizationRepository organizationRepository,
- ICollectionRepository collectionRepository,
- IOrganizationUserRepository organizationUserRepository,
- DatabaseContext databaseContext)
- {
- // Arrange
- 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,
- });
-
- // Act
- await collectionRepository.UpsertDefaultCollectionsBulkAsync(
- organization.Id,
- new[] { orgUser.Id },
- "My Items");
-
- // Assert - Verify semaphore was created
- var semaphore = await databaseContext.DefaultCollectionSemaphores
- .FirstOrDefaultAsync(s => s.OrganizationId == organization.Id && s.OrganizationUserId == orgUser.Id);
-
- Assert.NotNull(semaphore);
- Assert.Equal(organization.Id, semaphore.OrganizationId);
- Assert.Equal(orgUser.Id, semaphore.OrganizationUserId);
-
- // Verify collection was created
- var collections = await collectionRepository.GetManyByOrganizationIdAsync(organization.Id);
- var defaultCollections = collections.Where(c => c.Type == CollectionType.DefaultUserCollection).ToList();
-
- Assert.Single(defaultCollections);
- }
-
- ///
- /// Test that deleting an OrganizationUser cascades to DefaultCollectionSemaphore
- ///
- [DatabaseTheory, DatabaseData]
- public async Task DeleteOrganizationUser_CascadesToSemaphore_Success(
- IUserRepository userRepository,
- IOrganizationRepository organizationRepository,
- ICollectionRepository collectionRepository,
- IOrganizationUserRepository organizationUserRepository,
- DatabaseContext databaseContext)
- {
- // Arrange
- 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,
- });
-
- await collectionRepository.CreateDefaultCollectionsAsync(
- organization.Id,
- new[] { orgUser.Id },
- "My Items");
-
- // Verify semaphore exists
- var semaphoreBefore = await databaseContext.DefaultCollectionSemaphores
- .FirstOrDefaultAsync(s => s.OrganizationUserId == orgUser.Id);
- Assert.NotNull(semaphoreBefore);
-
- // Act - Delete organization user
- await organizationUserRepository.DeleteAsync(orgUser);
-
- // Assert - Semaphore should be cascade deleted
- var semaphoreAfter = await databaseContext.DefaultCollectionSemaphores
- .FirstOrDefaultAsync(s => s.OrganizationUserId == orgUser.Id);
- Assert.Null(semaphoreAfter);
- }
-
- ///
- /// Test that deleting an Organization cascades through OrganizationUser to DefaultCollectionSemaphore
- /// Note: Cascade path is Organization -> OrganizationUser -> DefaultCollectionSemaphore (not direct)
- ///
- [DatabaseTheory, DatabaseData]
- public async Task DeleteOrganization_CascadesThroughOrganizationUser_Success(
- IUserRepository userRepository,
- IOrganizationRepository organizationRepository,
- ICollectionRepository collectionRepository,
- IOrganizationUserRepository organizationUserRepository,
- DatabaseContext databaseContext)
- {
- // Arrange
- 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,
- });
-
- await collectionRepository.CreateDefaultCollectionsAsync(
- organization.Id,
- new[] { orgUser.Id },
- "My Items");
-
- // Verify semaphore exists
- var semaphoreBefore = await databaseContext.DefaultCollectionSemaphores
- .FirstOrDefaultAsync(s => s.OrganizationId == organization.Id);
- Assert.NotNull(semaphoreBefore);
-
- // Act - Delete organization (which cascades to OrganizationUser, which cascades to semaphore)
- await organizationRepository.DeleteAsync(organization);
-
- // Assert - Semaphore should be cascade deleted via OrganizationUser
- var semaphoreAfter = await databaseContext.DefaultCollectionSemaphores
- .FirstOrDefaultAsync(s => s.OrganizationId == organization.Id);
- Assert.Null(semaphoreAfter);
- }
-
- ///
- /// Test that CreateDefaultCollectionsAsync with empty user list does nothing
- ///
- [DatabaseTheory, DatabaseData]
- public async Task UpsertDefaultCollectionsAsync_WithEmptyList_DoesNothing(
- IOrganizationRepository organizationRepository,
- ICollectionRepository collectionRepository)
- {
- // Arrange
- var organization = await organizationRepository.CreateAsync(new Organization
- {
- Name = "Test Org",
- PlanType = PlanType.EnterpriseAnnually,
- Plan = "Test Plan",
- BillingEmail = "billing@email.com"
- });
-
- // Act
- await collectionRepository.CreateDefaultCollectionsAsync(
- organization.Id,
- Array.Empty(),
- "My Items");
-
- // Assert - No collections should be created
- var collections = await collectionRepository.GetManyByOrganizationIdAsync(organization.Id);
- Assert.Empty(collections);
- }
-
- ///
- /// Test that CreateDefaultCollectionsAsync creates CollectionUser entries with correct permissions
- ///
- [DatabaseTheory, DatabaseData]
- public async Task UpsertDefaultCollectionsAsync_CreatesCollectionUsersWithCorrectPermissions(
- IUserRepository userRepository,
- IOrganizationRepository organizationRepository,
- ICollectionRepository collectionRepository,
- IOrganizationUserRepository organizationUserRepository)
- {
- // Arrange
- 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,
- });
-
- // Act
- await collectionRepository.CreateDefaultCollectionsAsync(
- organization.Id,
- new[] { orgUser.Id },
- "My Items");
-
- // Assert
- var collections = await collectionRepository.GetManyByOrganizationIdAsync(organization.Id);
- var defaultCollection = collections.First(c => c.Type == CollectionType.DefaultUserCollection);
-
- var collectionUsers = await collectionRepository.GetManyUsersByIdAsync(defaultCollection.Id);
- var collectionUser = collectionUsers.Single();
-
- Assert.Equal(orgUser.Id, collectionUser.Id);
- Assert.False(collectionUser.ReadOnly);
- Assert.False(collectionUser.HidePasswords);
- Assert.True(collectionUser.Manage);
+ var access = await collectionRepository.GetManyUsersByIdAsync(defaultCollections.Single().Id);
+ var userAccess = Assert.Single(access);
+ Assert.Equal(orgUser.Id, userAccess.Id);
+ Assert.False(userAccess.ReadOnly);
+ Assert.False(userAccess.HidePasswords);
+ Assert.True(userAccess.Manage);
}
}