mirror of
https://github.com/bitwarden/server
synced 2025-12-14 23:33:41 +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:
@@ -57,8 +57,8 @@ public class OrganizationRepositoryTests
|
||||
var organization = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = $"Test Org {id}",
|
||||
BillingEmail = user1.Email, // TODO: EF does not enforce this being NOT NULl
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULl
|
||||
BillingEmail = user1.Email, // TODO: EF does not enforce this being NOT NULL
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULL
|
||||
PrivateKey = "privatekey",
|
||||
});
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ public class OrganizationUserRepositoryTests
|
||||
var organization = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = "Test Org",
|
||||
BillingEmail = user.Email, // TODO: EF does not enfore this being NOT NULL
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULl
|
||||
BillingEmail = user.Email, // TODO: EF does not enforce this being NOT NULL
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULL
|
||||
});
|
||||
|
||||
var orgUser = await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
@@ -37,6 +37,7 @@ public class OrganizationUserRepositoryTests
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Email = user.Email
|
||||
});
|
||||
|
||||
await organizationUserRepository.DeleteAsync(orgUser);
|
||||
@@ -46,6 +47,171 @@ public class OrganizationUserRepositoryTests
|
||||
Assert.NotEqual(newUser.AccountRevisionDate, user.AccountRevisionDate);
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task DeleteManyAsync_Migrates_UserDefaultCollection(IUserRepository userRepository,
|
||||
ICollectionRepository collectionRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository
|
||||
)
|
||||
{
|
||||
var user1 = await userRepository.CreateAsync(new User
|
||||
{
|
||||
Name = "Test User",
|
||||
Email = $"test+{Guid.NewGuid()}@example.com",
|
||||
ApiKey = "TEST",
|
||||
SecurityStamp = "stamp",
|
||||
});
|
||||
|
||||
var user2 = await userRepository.CreateAsync(new User
|
||||
{
|
||||
Name = "Test User",
|
||||
Email = $"test+{Guid.NewGuid()}@example.com",
|
||||
ApiKey = "TEST",
|
||||
SecurityStamp = "stamp",
|
||||
});
|
||||
|
||||
var organization = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = "Test Org",
|
||||
BillingEmail = user1.Email, // TODO: EF does not enforce this being NOT NULL
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULL
|
||||
});
|
||||
|
||||
var orgUser1 = await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user1.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Email = user1.Email
|
||||
});
|
||||
|
||||
var orgUser2 = await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user2.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Email = user2.Email
|
||||
});
|
||||
|
||||
var defaultUserCollection1 = await collectionRepository.CreateAsync(new Collection
|
||||
{
|
||||
Name = "Test Collection 1",
|
||||
Id = user1.Id,
|
||||
Type = CollectionType.DefaultUserCollection,
|
||||
OrganizationId = organization.Id
|
||||
});
|
||||
|
||||
var defaultUserCollection2 = await collectionRepository.CreateAsync(new Collection
|
||||
{
|
||||
Name = "Test Collection 2",
|
||||
Id = user2.Id,
|
||||
Type = CollectionType.DefaultUserCollection,
|
||||
OrganizationId = organization.Id
|
||||
});
|
||||
|
||||
// Create the CollectionUser entry for the defaultUserCollection
|
||||
await collectionRepository.UpdateUsersAsync(defaultUserCollection1.Id, new List<CollectionAccessSelection>()
|
||||
{
|
||||
new CollectionAccessSelection
|
||||
{
|
||||
Id = orgUser1.Id,
|
||||
HidePasswords = false,
|
||||
ReadOnly = false,
|
||||
Manage = true
|
||||
},
|
||||
});
|
||||
|
||||
await collectionRepository.UpdateUsersAsync(defaultUserCollection2.Id, new List<CollectionAccessSelection>()
|
||||
{
|
||||
new CollectionAccessSelection
|
||||
{
|
||||
Id = orgUser2.Id,
|
||||
HidePasswords = false,
|
||||
ReadOnly = false,
|
||||
Manage = true
|
||||
},
|
||||
});
|
||||
|
||||
await organizationUserRepository.DeleteManyAsync(new List<Guid> { orgUser1.Id, orgUser2.Id });
|
||||
|
||||
var newUser = await userRepository.GetByIdAsync(user1.Id);
|
||||
Assert.NotNull(newUser);
|
||||
Assert.NotEqual(newUser.AccountRevisionDate, user1.AccountRevisionDate);
|
||||
|
||||
var updatedCollection1 = await collectionRepository.GetByIdAsync(defaultUserCollection1.Id);
|
||||
Assert.NotNull(updatedCollection1);
|
||||
Assert.Equal(CollectionType.SharedCollection, updatedCollection1.Type);
|
||||
Assert.Equal(user1.Email, updatedCollection1.DefaultUserCollectionEmail);
|
||||
|
||||
var updatedCollection2 = await collectionRepository.GetByIdAsync(defaultUserCollection2.Id);
|
||||
Assert.NotNull(updatedCollection2);
|
||||
Assert.Equal(CollectionType.SharedCollection, updatedCollection2.Type);
|
||||
Assert.Equal(user2.Email, updatedCollection2.DefaultUserCollectionEmail);
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task DeleteAsync_Migrates_UserDefaultCollection(IUserRepository userRepository,
|
||||
ICollectionRepository collectionRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository
|
||||
)
|
||||
{
|
||||
var user = await userRepository.CreateAsync(new User
|
||||
{
|
||||
Name = "Test User",
|
||||
Email = $"test+{Guid.NewGuid()}@example.com",
|
||||
ApiKey = "TEST",
|
||||
SecurityStamp = "stamp",
|
||||
});
|
||||
|
||||
var organization = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = "Test Org",
|
||||
BillingEmail = user.Email, // TODO: EF does not enforce this being NOT NULL
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULL
|
||||
});
|
||||
|
||||
var orgUser = await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Email = user.Email
|
||||
});
|
||||
|
||||
var defaultUserCollection = await collectionRepository.CreateAsync(new Collection
|
||||
{
|
||||
Name = "Test Collection",
|
||||
Id = user.Id,
|
||||
Type = CollectionType.DefaultUserCollection,
|
||||
OrganizationId = organization.Id
|
||||
});
|
||||
|
||||
// Create the CollectionUser entry for the defaultUserCollection
|
||||
await collectionRepository.UpdateUsersAsync(defaultUserCollection.Id, new List<CollectionAccessSelection>()
|
||||
{
|
||||
new CollectionAccessSelection
|
||||
{
|
||||
Id = orgUser.Id,
|
||||
HidePasswords = false,
|
||||
ReadOnly = false,
|
||||
Manage = true
|
||||
},
|
||||
});
|
||||
|
||||
await organizationUserRepository.DeleteAsync(orgUser);
|
||||
|
||||
var newUser = await userRepository.GetByIdAsync(user.Id);
|
||||
Assert.NotNull(newUser);
|
||||
Assert.NotEqual(newUser.AccountRevisionDate, user.AccountRevisionDate);
|
||||
|
||||
var updatedCollection = await collectionRepository.GetByIdAsync(defaultUserCollection.Id);
|
||||
Assert.NotNull(updatedCollection);
|
||||
Assert.Equal(CollectionType.SharedCollection, updatedCollection.Type);
|
||||
Assert.Equal(user.Email, updatedCollection.DefaultUserCollectionEmail);
|
||||
}
|
||||
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task DeleteManyAsync_Works(IUserRepository userRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
@@ -70,8 +236,8 @@ public class OrganizationUserRepositoryTests
|
||||
var organization = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = "Test Org",
|
||||
BillingEmail = user1.Email, // TODO: EF does not enforce this being NOT NULl
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULl
|
||||
BillingEmail = user1.Email, // TODO: EF does not enforce this being NOT NULL
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULL
|
||||
});
|
||||
|
||||
var orgUser1 = await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
@@ -79,6 +245,7 @@ public class OrganizationUserRepositoryTests
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user1.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Email = user1.Email
|
||||
});
|
||||
|
||||
var orgUser2 = await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
@@ -86,6 +253,7 @@ public class OrganizationUserRepositoryTests
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user2.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Email = user2.Email
|
||||
});
|
||||
|
||||
await organizationUserRepository.DeleteManyAsync(new List<Guid>
|
||||
@@ -135,8 +303,8 @@ public class OrganizationUserRepositoryTests
|
||||
var organization = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = "Test Org",
|
||||
BillingEmail = user1.Email, // TODO: EF does not enforce this being NOT NULl
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULl
|
||||
BillingEmail = user1.Email, // TODO: EF does not enforce this being NOT NULL
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULL
|
||||
PrivateKey = "privatekey",
|
||||
});
|
||||
|
||||
@@ -291,8 +459,8 @@ public class OrganizationUserRepositoryTests
|
||||
var organization = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = "Test Org",
|
||||
BillingEmail = user1.Email, // TODO: EF does not enforce this being NOT NULl
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULl
|
||||
BillingEmail = user1.Email, // TODO: EF does not enforce this being NOT NULL
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULL
|
||||
PrivateKey = "privatekey",
|
||||
});
|
||||
|
||||
@@ -354,6 +522,134 @@ public class OrganizationUserRepositoryTests
|
||||
Assert.Equal(organization.UseAdminSponsoredFamilies, result.UseAdminSponsoredFamilies);
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task GetManyByOrganizationWithClaimedDomainsAsync_WithVerifiedDomain_WithOneMatchingEmailDomain_ReturnsSingle(
|
||||
IUserRepository userRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
IOrganizationDomainRepository organizationDomainRepository)
|
||||
{
|
||||
var id = Guid.NewGuid();
|
||||
var domainName = $"{id}.example.com";
|
||||
|
||||
var user1 = await userRepository.CreateAsync(new User
|
||||
{
|
||||
Name = "Test User 1",
|
||||
Email = $"test+{id}@{domainName}",
|
||||
ApiKey = "TEST",
|
||||
SecurityStamp = "stamp",
|
||||
Kdf = KdfType.PBKDF2_SHA256,
|
||||
KdfIterations = 1,
|
||||
KdfMemory = 2,
|
||||
KdfParallelism = 3
|
||||
});
|
||||
|
||||
var user2 = await userRepository.CreateAsync(new User
|
||||
{
|
||||
Name = "Test User 2",
|
||||
Email = $"test+{id}@x-{domainName}", // Different domain
|
||||
ApiKey = "TEST",
|
||||
SecurityStamp = "stamp",
|
||||
Kdf = KdfType.PBKDF2_SHA256,
|
||||
KdfIterations = 1,
|
||||
KdfMemory = 2,
|
||||
KdfParallelism = 3
|
||||
});
|
||||
|
||||
var user3 = await userRepository.CreateAsync(new User
|
||||
{
|
||||
Name = "Test User 2",
|
||||
Email = $"test+{id}@{domainName}.example.com", // Different domain
|
||||
ApiKey = "TEST",
|
||||
SecurityStamp = "stamp",
|
||||
Kdf = KdfType.PBKDF2_SHA256,
|
||||
KdfIterations = 1,
|
||||
KdfMemory = 2,
|
||||
KdfParallelism = 3
|
||||
});
|
||||
|
||||
var organization = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = $"Test Org {id}",
|
||||
BillingEmail = user1.Email, // TODO: EF does not enforce this being NOT NULL
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULL
|
||||
PrivateKey = "privatekey",
|
||||
UsePolicies = false,
|
||||
UseSso = false,
|
||||
UseKeyConnector = false,
|
||||
UseScim = false,
|
||||
UseGroups = false,
|
||||
UseDirectory = false,
|
||||
UseEvents = false,
|
||||
UseTotp = false,
|
||||
Use2fa = false,
|
||||
UseApi = false,
|
||||
UseResetPassword = false,
|
||||
UseSecretsManager = false,
|
||||
SelfHost = false,
|
||||
UsersGetPremium = false,
|
||||
UseCustomPermissions = false,
|
||||
Enabled = true,
|
||||
UsePasswordManager = false,
|
||||
LimitCollectionCreation = false,
|
||||
LimitCollectionDeletion = false,
|
||||
LimitItemDeletion = false,
|
||||
AllowAdminAccessToAllCollectionItems = false,
|
||||
UseRiskInsights = false,
|
||||
UseAdminSponsoredFamilies = false
|
||||
});
|
||||
|
||||
var organizationDomain = new OrganizationDomain
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
DomainName = domainName,
|
||||
Txt = "btw+12345",
|
||||
};
|
||||
organizationDomain.SetVerifiedDate();
|
||||
organizationDomain.SetNextRunDate(12);
|
||||
organizationDomain.SetJobRunCount();
|
||||
await organizationDomainRepository.CreateAsync(organizationDomain);
|
||||
|
||||
var orgUser1 = await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
Id = CoreHelpers.GenerateComb(),
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user1.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Type = OrganizationUserType.Owner,
|
||||
ResetPasswordKey = "resetpasswordkey1",
|
||||
AccessSecretsManager = false
|
||||
});
|
||||
|
||||
await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
Id = CoreHelpers.GenerateComb(),
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user2.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Type = OrganizationUserType.User,
|
||||
ResetPasswordKey = "resetpasswordkey1",
|
||||
AccessSecretsManager = false
|
||||
});
|
||||
|
||||
await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
Id = CoreHelpers.GenerateComb(),
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user3.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Type = OrganizationUserType.User,
|
||||
ResetPasswordKey = "resetpasswordkey1",
|
||||
AccessSecretsManager = false
|
||||
});
|
||||
|
||||
var responseModel = await organizationUserRepository.GetManyByOrganizationWithClaimedDomainsAsync(organization.Id);
|
||||
|
||||
Assert.NotNull(responseModel);
|
||||
Assert.Single(responseModel);
|
||||
Assert.Equal(orgUser1.Id, responseModel.Single().Id);
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task CreateManyAsync_NoId_Works(IOrganizationRepository organizationRepository,
|
||||
IUserRepository userRepository,
|
||||
@@ -369,7 +665,7 @@ public class OrganizationUserRepositoryTests
|
||||
{
|
||||
Name = $"test-{Guid.NewGuid()}",
|
||||
BillingEmail = "billing@example.com", // TODO: EF does not enforce this being NOT NULL
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULl
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULL
|
||||
});
|
||||
|
||||
var orgUsers = users.Select(u => new OrganizationUser
|
||||
@@ -403,7 +699,7 @@ public class OrganizationUserRepositoryTests
|
||||
{
|
||||
Name = $"test-{Guid.NewGuid()}",
|
||||
BillingEmail = "billing@example.com", // TODO: EF does not enforce this being NOT NULL
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULl
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULL
|
||||
});
|
||||
|
||||
var orgUsers = users.Select(u => new OrganizationUser
|
||||
@@ -435,8 +731,8 @@ public class OrganizationUserRepositoryTests
|
||||
var organization = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = "Test Org",
|
||||
BillingEmail = "billing@test.com", // TODO: EF does not enfore this being NOT NULL
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULl,
|
||||
BillingEmail = "billing@test.com", // TODO: EF does not enforce this being NOT NULL
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULL,
|
||||
CreationDate = requestTime
|
||||
});
|
||||
|
||||
@@ -862,119 +1158,6 @@ public class OrganizationUserRepositoryTests
|
||||
Assert.DoesNotContain(user1Result.Collections, c => c.Id == defaultUserCollection.Id);
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task GetManyByOrganizationWithClaimedDomainsAsync_WithVerifiedDomain_WithOneMatchingEmailDomain_ReturnsSingle(
|
||||
IUserRepository userRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
IOrganizationDomainRepository organizationDomainRepository)
|
||||
{
|
||||
var id = Guid.NewGuid();
|
||||
var domainName = $"{id}.example.com";
|
||||
var requestTime = DateTime.UtcNow;
|
||||
|
||||
var user1 = await userRepository.CreateAsync(new User
|
||||
{
|
||||
Id = CoreHelpers.GenerateComb(),
|
||||
Name = "Test User 1",
|
||||
Email = $"test+{id}@{domainName}",
|
||||
ApiKey = "TEST",
|
||||
SecurityStamp = "stamp",
|
||||
CreationDate = requestTime,
|
||||
RevisionDate = requestTime,
|
||||
AccountRevisionDate = requestTime
|
||||
});
|
||||
|
||||
var user2 = await userRepository.CreateAsync(new User
|
||||
{
|
||||
Id = CoreHelpers.GenerateComb(),
|
||||
Name = "Test User 2",
|
||||
Email = $"test+{id}@x-{domainName}", // Different domain
|
||||
ApiKey = "TEST",
|
||||
SecurityStamp = "stamp",
|
||||
CreationDate = requestTime,
|
||||
RevisionDate = requestTime,
|
||||
AccountRevisionDate = requestTime
|
||||
});
|
||||
|
||||
var user3 = await userRepository.CreateAsync(new User
|
||||
{
|
||||
Id = CoreHelpers.GenerateComb(),
|
||||
Name = "Test User 3",
|
||||
Email = $"test+{id}@{domainName}.example.com", // Different domain
|
||||
ApiKey = "TEST",
|
||||
SecurityStamp = "stamp",
|
||||
CreationDate = requestTime,
|
||||
RevisionDate = requestTime,
|
||||
AccountRevisionDate = requestTime
|
||||
});
|
||||
|
||||
var organization = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Id = CoreHelpers.GenerateComb(),
|
||||
Name = $"Test Org {id}",
|
||||
BillingEmail = user1.Email,
|
||||
Plan = "Test",
|
||||
Enabled = true,
|
||||
CreationDate = requestTime,
|
||||
RevisionDate = requestTime
|
||||
});
|
||||
|
||||
var organizationDomain = new OrganizationDomain
|
||||
{
|
||||
Id = CoreHelpers.GenerateComb(),
|
||||
OrganizationId = organization.Id,
|
||||
DomainName = domainName,
|
||||
Txt = "btw+12345",
|
||||
CreationDate = requestTime
|
||||
};
|
||||
organizationDomain.SetNextRunDate(12);
|
||||
organizationDomain.SetVerifiedDate();
|
||||
organizationDomain.SetJobRunCount();
|
||||
await organizationDomainRepository.CreateAsync(organizationDomain);
|
||||
|
||||
var orgUser1 = await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
Id = CoreHelpers.GenerateComb(),
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user1.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Type = OrganizationUserType.Owner,
|
||||
CreationDate = requestTime,
|
||||
RevisionDate = requestTime
|
||||
});
|
||||
|
||||
await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
Id = CoreHelpers.GenerateComb(),
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user2.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Type = OrganizationUserType.User,
|
||||
CreationDate = requestTime,
|
||||
RevisionDate = requestTime
|
||||
});
|
||||
|
||||
await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
Id = CoreHelpers.GenerateComb(),
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user3.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Type = OrganizationUserType.User,
|
||||
CreationDate = requestTime,
|
||||
RevisionDate = requestTime
|
||||
});
|
||||
|
||||
var responseModel = await organizationUserRepository.GetManyByOrganizationWithClaimedDomainsAsync(organization.Id);
|
||||
|
||||
Assert.NotNull(responseModel);
|
||||
Assert.Single(responseModel);
|
||||
Assert.Equal(orgUser1.Id, responseModel.Single().Id);
|
||||
Assert.Equal(user1.Id, responseModel.Single().UserId);
|
||||
Assert.Equal(organization.Id, responseModel.Single().OrganizationId);
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task GetManyByOrganizationWithClaimedDomainsAsync_WithNoVerifiedDomain_ReturnsEmpty(
|
||||
IUserRepository userRepository,
|
||||
@@ -1039,6 +1222,120 @@ public class OrganizationUserRepositoryTests
|
||||
Assert.Empty(responseModel);
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task DeleteAsync_WithNullEmail_DoesNotSetDefaultUserCollectionEmail(IUserRepository userRepository,
|
||||
ICollectionRepository collectionRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository
|
||||
)
|
||||
{
|
||||
var user = await userRepository.CreateAsync(new User
|
||||
{
|
||||
Name = "Test User",
|
||||
Email = $"test+{Guid.NewGuid()}@example.com",
|
||||
ApiKey = "TEST",
|
||||
SecurityStamp = "stamp",
|
||||
});
|
||||
|
||||
var organization = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = "Test Org",
|
||||
BillingEmail = user.Email,
|
||||
Plan = "Test",
|
||||
});
|
||||
|
||||
var orgUser = await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Email = null
|
||||
});
|
||||
|
||||
var defaultUserCollection = await collectionRepository.CreateAsync(new Collection
|
||||
{
|
||||
Name = "Test Collection",
|
||||
Id = user.Id,
|
||||
Type = CollectionType.DefaultUserCollection,
|
||||
OrganizationId = organization.Id
|
||||
});
|
||||
|
||||
await collectionRepository.UpdateUsersAsync(defaultUserCollection.Id, new List<CollectionAccessSelection>()
|
||||
{
|
||||
new CollectionAccessSelection
|
||||
{
|
||||
Id = orgUser.Id,
|
||||
HidePasswords = false,
|
||||
ReadOnly = false,
|
||||
Manage = true
|
||||
},
|
||||
});
|
||||
|
||||
await organizationUserRepository.DeleteAsync(orgUser);
|
||||
|
||||
var updatedCollection = await collectionRepository.GetByIdAsync(defaultUserCollection.Id);
|
||||
Assert.NotNull(updatedCollection);
|
||||
Assert.Equal(CollectionType.SharedCollection, updatedCollection.Type);
|
||||
Assert.Equal(user.Email, updatedCollection.DefaultUserCollectionEmail);
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task DeleteAsync_WithEmptyEmail_DoesNotSetDefaultUserCollectionEmail(IUserRepository userRepository,
|
||||
ICollectionRepository collectionRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository
|
||||
)
|
||||
{
|
||||
var user = await userRepository.CreateAsync(new User
|
||||
{
|
||||
Name = "Test User",
|
||||
Email = $"test+{Guid.NewGuid()}@example.com",
|
||||
ApiKey = "TEST",
|
||||
SecurityStamp = "stamp",
|
||||
});
|
||||
|
||||
var organization = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = "Test Org",
|
||||
BillingEmail = user.Email,
|
||||
Plan = "Test",
|
||||
});
|
||||
|
||||
var orgUser = await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
UserId = user.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Email = "" // Empty string email
|
||||
});
|
||||
|
||||
var defaultUserCollection = await collectionRepository.CreateAsync(new Collection
|
||||
{
|
||||
Name = "Test Collection",
|
||||
Id = user.Id,
|
||||
Type = CollectionType.DefaultUserCollection,
|
||||
OrganizationId = organization.Id
|
||||
});
|
||||
|
||||
await collectionRepository.UpdateUsersAsync(defaultUserCollection.Id, new List<CollectionAccessSelection>()
|
||||
{
|
||||
new CollectionAccessSelection
|
||||
{
|
||||
Id = orgUser.Id,
|
||||
HidePasswords = false,
|
||||
ReadOnly = false,
|
||||
Manage = true
|
||||
},
|
||||
});
|
||||
|
||||
await organizationUserRepository.DeleteAsync(orgUser);
|
||||
|
||||
var updatedCollection = await collectionRepository.GetByIdAsync(defaultUserCollection.Id);
|
||||
Assert.NotNull(updatedCollection);
|
||||
Assert.Equal(CollectionType.SharedCollection, updatedCollection.Type);
|
||||
Assert.Equal(user.Email, updatedCollection.DefaultUserCollectionEmail);
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task ReplaceAsync_PreservesDefaultCollections_WhenUpdatingCollectionAccess(
|
||||
IUserRepository userRepository,
|
||||
|
||||
@@ -55,7 +55,7 @@ public class UserRepositoryTests
|
||||
var organization = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = "Test Org",
|
||||
BillingEmail = user3.Email, // TODO: EF does not enfore this being NOT NULL
|
||||
BillingEmail = user3.Email, // TODO: EF does not enforce this being NOT NULL
|
||||
Plan = "Test", // TODO: EF does not enforce this being NOT NULl
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user