1
0
mirror of https://github.com/bitwarden/server synced 2025-12-24 20:23:21 +00:00

Merge branch 'main' of github.com:bitwarden/server into arch/seeder-api

# Conflicts:
#	util/Seeder/Recipes/OrganizationWithUsersRecipe.cs
This commit is contained in:
Hinton
2025-12-16 16:48:29 +01:00
484 changed files with 43837 additions and 8360 deletions

View File

@@ -93,7 +93,8 @@ public static class OrganizationTestHelpers
UseOrganizationDomains = true,
UseAdminSponsoredFamilies = true,
SyncSeats = false,
UseAutomaticUserConfirmation = true
UseAutomaticUserConfirmation = true,
UsePhishingBlocker = true,
});
}

View File

@@ -673,7 +673,8 @@ public class OrganizationUserRepositoryTests
LimitItemDeletion = false,
AllowAdminAccessToAllCollectionItems = false,
UseRiskInsights = false,
UseAdminSponsoredFamilies = false
UseAdminSponsoredFamilies = false,
UsePhishingBlocker = false,
});
var organizationDomain = new OrganizationDomain

View File

@@ -89,6 +89,286 @@ public class ProviderUserRepositoryTests
Assert.Equal(serializedSsoConfigData, orgWithSsoDetails.SsoConfig);
}
[Theory, DatabaseData]
public async Task GetManyByManyUsersAsync_WithMultipleUsers_ReturnsAllProviderUsers(
IUserRepository userRepository,
IProviderRepository providerRepository,
IProviderUserRepository providerUserRepository)
{
var user1 = await userRepository.CreateTestUserAsync();
var user2 = await userRepository.CreateTestUserAsync();
var user3 = await userRepository.CreateTestUserAsync();
var provider1 = await providerRepository.CreateAsync(new Provider
{
Name = "Test Provider 1",
Enabled = true,
Type = ProviderType.Msp
});
var provider2 = await providerRepository.CreateAsync(new Provider
{
Name = "Test Provider 2",
Enabled = true,
Type = ProviderType.Reseller
});
var providerUser1 = await providerUserRepository.CreateAsync(new ProviderUser
{
Id = Guid.NewGuid(),
ProviderId = provider1.Id,
UserId = user1.Id,
Status = ProviderUserStatusType.Confirmed,
Type = ProviderUserType.ProviderAdmin
});
var providerUser2 = await providerUserRepository.CreateAsync(new ProviderUser
{
Id = Guid.NewGuid(),
ProviderId = provider1.Id,
UserId = user2.Id,
Status = ProviderUserStatusType.Invited,
Type = ProviderUserType.ServiceUser
});
var providerUser3 = await providerUserRepository.CreateAsync(new ProviderUser
{
Id = Guid.NewGuid(),
ProviderId = provider2.Id,
UserId = user3.Id,
Status = ProviderUserStatusType.Confirmed,
Type = ProviderUserType.ProviderAdmin
});
var userIds = new[] { user1.Id, user2.Id, user3.Id };
var results = (await providerUserRepository.GetManyByManyUsersAsync(userIds)).ToList();
Assert.Equal(3, results.Count);
Assert.Contains(results, pu => pu.Id == providerUser1.Id && pu.UserId == user1.Id);
Assert.Contains(results, pu => pu.Id == providerUser2.Id && pu.UserId == user2.Id);
Assert.Contains(results, pu => pu.Id == providerUser3.Id && pu.UserId == user3.Id);
}
[Theory, DatabaseData]
public async Task GetManyByManyUsersAsync_WithSingleUser_ReturnsSingleProviderUser(
IUserRepository userRepository,
IProviderRepository providerRepository,
IProviderUserRepository providerUserRepository)
{
var user = await userRepository.CreateTestUserAsync();
var provider = await providerRepository.CreateAsync(new Provider
{
Name = "Test Provider",
Enabled = true,
Type = ProviderType.Msp
});
var providerUser = await providerUserRepository.CreateAsync(new ProviderUser
{
Id = Guid.NewGuid(),
ProviderId = provider.Id,
UserId = user.Id,
Status = ProviderUserStatusType.Confirmed,
Type = ProviderUserType.ProviderAdmin
});
var results = (await providerUserRepository.GetManyByManyUsersAsync([user.Id])).ToList();
Assert.Single(results);
Assert.Equal(user.Id, results[0].UserId);
Assert.Equal(provider.Id, results[0].ProviderId);
}
[Theory, DatabaseData]
public async Task GetManyByManyUsersAsync_WithUserHavingMultipleProviders_ReturnsAllProviderUsers(
IUserRepository userRepository,
IProviderRepository providerRepository,
IProviderUserRepository providerUserRepository)
{
var user = await userRepository.CreateTestUserAsync();
var provider1 = await providerRepository.CreateAsync(new Provider
{
Name = "Test Provider 1",
Enabled = true,
Type = ProviderType.Msp
});
var provider2 = await providerRepository.CreateAsync(new Provider
{
Name = "Test Provider 2",
Enabled = true,
Type = ProviderType.Reseller
});
var providerUser1 = await providerUserRepository.CreateAsync(new ProviderUser
{
ProviderId = provider1.Id,
UserId = user.Id,
Status = ProviderUserStatusType.Confirmed,
Type = ProviderUserType.ProviderAdmin
});
var providerUser2 = await providerUserRepository.CreateAsync(new ProviderUser
{
ProviderId = provider2.Id,
UserId = user.Id,
Status = ProviderUserStatusType.Confirmed,
Type = ProviderUserType.ServiceUser
});
var results = (await providerUserRepository.GetManyByManyUsersAsync([user.Id])).ToList();
Assert.Equal(2, results.Count);
Assert.Contains(results, pu => pu.Id == providerUser1.Id);
Assert.Contains(results, pu => pu.Id == providerUser2.Id);
}
[Theory, DatabaseData]
public async Task GetManyByManyUsersAsync_WithEmptyUserIds_ReturnsEmpty(
IProviderUserRepository providerUserRepository)
{
var results = await providerUserRepository.GetManyByManyUsersAsync(Array.Empty<Guid>());
Assert.Empty(results);
}
[Theory, DatabaseData]
public async Task GetManyByManyUsersAsync_WithNonExistentUserIds_ReturnsEmpty(
IProviderUserRepository providerUserRepository)
{
var nonExistentUserIds = new[] { Guid.NewGuid(), Guid.NewGuid() };
var results = await providerUserRepository.GetManyByManyUsersAsync(nonExistentUserIds);
Assert.Empty(results);
}
[Theory, DatabaseData]
public async Task GetManyByManyUsersAsync_WithMixedExistentAndNonExistentUserIds_ReturnsOnlyExistent(
IUserRepository userRepository,
IProviderRepository providerRepository,
IProviderUserRepository providerUserRepository)
{
var existingUser = await userRepository.CreateTestUserAsync();
var provider = await providerRepository.CreateAsync(new Provider
{
Name = "Test Provider",
Enabled = true,
Type = ProviderType.Msp
});
var providerUser = await providerUserRepository.CreateAsync(new ProviderUser
{
ProviderId = provider.Id,
UserId = existingUser.Id,
Status = ProviderUserStatusType.Confirmed,
Type = ProviderUserType.ProviderAdmin
});
var userIds = new[] { existingUser.Id, Guid.NewGuid(), Guid.NewGuid() };
var results = (await providerUserRepository.GetManyByManyUsersAsync(userIds)).ToList();
Assert.Single(results);
Assert.Equal(existingUser.Id, results[0].UserId);
}
[Theory, DatabaseData]
public async Task GetManyByManyUsersAsync_ReturnsAllStatuses(
IUserRepository userRepository,
IProviderRepository providerRepository,
IProviderUserRepository providerUserRepository)
{
var user1 = await userRepository.CreateTestUserAsync();
var user2 = await userRepository.CreateTestUserAsync();
var user3 = await userRepository.CreateTestUserAsync();
var provider = await providerRepository.CreateAsync(new Provider
{
Name = "Test Provider",
Enabled = true,
Type = ProviderType.Msp
});
await providerUserRepository.CreateAsync(new ProviderUser
{
ProviderId = provider.Id,
UserId = user1.Id,
Status = ProviderUserStatusType.Invited,
Type = ProviderUserType.ServiceUser
});
await providerUserRepository.CreateAsync(new ProviderUser
{
ProviderId = provider.Id,
UserId = user2.Id,
Status = ProviderUserStatusType.Accepted,
Type = ProviderUserType.ServiceUser
});
await providerUserRepository.CreateAsync(new ProviderUser
{
ProviderId = provider.Id,
UserId = user3.Id,
Status = ProviderUserStatusType.Confirmed,
Type = ProviderUserType.ProviderAdmin
});
var userIds = new[] { user1.Id, user2.Id, user3.Id };
var results = (await providerUserRepository.GetManyByManyUsersAsync(userIds)).ToList();
Assert.Equal(3, results.Count);
Assert.Contains(results, pu => pu.UserId == user1.Id && pu.Status == ProviderUserStatusType.Invited);
Assert.Contains(results, pu => pu.UserId == user2.Id && pu.Status == ProviderUserStatusType.Accepted);
Assert.Contains(results, pu => pu.UserId == user3.Id && pu.Status == ProviderUserStatusType.Confirmed);
}
[Theory, DatabaseData]
public async Task GetManyByManyUsersAsync_ReturnsAllProviderUserTypes(
IUserRepository userRepository,
IProviderRepository providerRepository,
IProviderUserRepository providerUserRepository)
{
var user1 = await userRepository.CreateTestUserAsync();
var user2 = await userRepository.CreateTestUserAsync();
var provider = await providerRepository.CreateAsync(new Provider
{
Name = "Test Provider",
Enabled = true,
Type = ProviderType.Msp
});
await providerUserRepository.CreateAsync(new ProviderUser
{
ProviderId = provider.Id,
UserId = user1.Id,
Status = ProviderUserStatusType.Confirmed,
Type = ProviderUserType.ServiceUser
});
await providerUserRepository.CreateAsync(new ProviderUser
{
ProviderId = provider.Id,
UserId = user2.Id,
Status = ProviderUserStatusType.Confirmed,
Type = ProviderUserType.ProviderAdmin
});
var userIds = new[] { user1.Id, user2.Id };
var results = (await providerUserRepository.GetManyByManyUsersAsync(userIds)).ToList();
Assert.Equal(2, results.Count);
Assert.Contains(results, pu => pu.UserId == user1.Id && pu.Type == ProviderUserType.ServiceUser);
Assert.Contains(results, pu => pu.UserId == user2.Id && pu.Type == ProviderUserType.ProviderAdmin);
}
private static void AssertProviderOrganizationDetails(
ProviderUserOrganizationDetails actual,
Organization expectedOrganization,
@@ -139,4 +419,6 @@ public class ProviderUserRepositoryTests
Assert.Equal(expectedProviderUser.Status, actual.Status);
Assert.Equal(expectedProviderUser.Type, actual.Type);
}
}

View File

@@ -179,4 +179,325 @@ public class UserRepositoryTests
Assert.Equal(CollectionType.SharedCollection, updatedCollection2.Type);
Assert.Equal(user2.Email, updatedCollection2.DefaultUserCollectionEmail);
}
[Theory, DatabaseData]
public async Task GetPremiumAccessAsync_WithPersonalPremium_ReturnsCorrectAccess(
IUserRepository userRepository)
{
// Arrange
var user = await userRepository.CreateAsync(new User
{
Name = "Premium User",
Email = $"premium+{Guid.NewGuid()}@example.com",
ApiKey = "TEST",
SecurityStamp = "stamp",
Premium = true
});
// Act
var result = await userRepository.GetPremiumAccessAsync(user.Id);
// Assert
Assert.NotNull(result);
Assert.True(result.PersonalPremium);
Assert.False(result.OrganizationPremium);
Assert.True(result.HasPremiumAccess);
}
[Theory, DatabaseData]
public async Task GetPremiumAccessAsync_WithOrganizationPremium_ReturnsCorrectAccess(
IUserRepository userRepository,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository)
{
// Arrange
var user = await userRepository.CreateAsync(new User
{
Name = "Org User",
Email = $"org+{Guid.NewGuid()}@example.com",
ApiKey = "TEST",
SecurityStamp = "stamp",
Premium = false
});
var organization = await organizationRepository.CreateTestOrganizationAsync();
await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user);
// Act
var result = await userRepository.GetPremiumAccessAsync(user.Id);
// Assert
Assert.NotNull(result);
Assert.False(result.PersonalPremium);
Assert.True(result.OrganizationPremium);
Assert.True(result.HasPremiumAccess);
}
[Theory, DatabaseData]
public async Task GetPremiumAccessAsync_WithDisabledOrganization_ReturnsNoOrganizationPremium(
IUserRepository userRepository,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository)
{
// Arrange
var user = await userRepository.CreateAsync(new User
{
Name = "User",
Email = $"user+{Guid.NewGuid()}@example.com",
ApiKey = "TEST",
SecurityStamp = "stamp",
Premium = false
});
var organization = await organizationRepository.CreateTestOrganizationAsync();
organization.Enabled = false;
await organizationRepository.ReplaceAsync(organization);
await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user);
// Act
var result = await userRepository.GetPremiumAccessAsync(user.Id);
// Assert
Assert.NotNull(result);
Assert.False(result.OrganizationPremium);
Assert.False(result.HasPremiumAccess);
}
[Theory, DatabaseData]
public async Task GetPremiumAccessAsync_WithOrganizationUsersGetPremiumFalse_ReturnsNoOrganizationPremium(
IUserRepository userRepository,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository)
{
// Arrange
var user = await userRepository.CreateAsync(new User
{
Name = "User",
Email = $"{Guid.NewGuid()}@example.com",
ApiKey = "TEST",
SecurityStamp = "stamp",
Premium = false
});
var organization = await organizationRepository.CreateTestOrganizationAsync();
organization.UsersGetPremium = false;
await organizationRepository.ReplaceAsync(organization);
await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user);
// Act
var result = await userRepository.GetPremiumAccessAsync(user.Id);
// Assert
Assert.NotNull(result);
Assert.False(result.OrganizationPremium);
Assert.False(result.HasPremiumAccess);
}
[Theory, DatabaseData]
public async Task GetPremiumAccessAsync_WithMultipleOrganizations_OneProvidesPremium_ReturnsOrganizationPremium(
IUserRepository userRepository,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository)
{
// Arrange
var user = await userRepository.CreateAsync(new User
{
Name = "User With Premium Org",
Email = $"{Guid.NewGuid()}@example.com",
ApiKey = "TEST",
SecurityStamp = "stamp",
Premium = false
});
var orgWithPremium = await organizationRepository.CreateTestOrganizationAsync();
await organizationUserRepository.CreateTestOrganizationUserAsync(orgWithPremium, user);
var orgNoPremium = await organizationRepository.CreateTestOrganizationAsync();
orgNoPremium.UsersGetPremium = false;
await organizationRepository.ReplaceAsync(orgNoPremium);
await organizationUserRepository.CreateTestOrganizationUserAsync(orgNoPremium, user);
// Act
var result = await userRepository.GetPremiumAccessAsync(user.Id);
// Assert
Assert.NotNull(result);
Assert.False(result.PersonalPremium);
Assert.True(result.OrganizationPremium);
Assert.True(result.HasPremiumAccess);
}
[Theory, DatabaseData]
public async Task GetPremiumAccessAsync_WithMultipleOrganizations_NoneProvidePremium_ReturnsNoOrganizationPremium(
IUserRepository userRepository,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository)
{
// Arrange
var user = await userRepository.CreateAsync(new User
{
Name = "User With No Premium Orgs",
Email = $"{Guid.NewGuid()}@example.com",
ApiKey = "TEST",
SecurityStamp = "stamp",
Premium = false
});
var disabledOrg = await organizationRepository.CreateTestOrganizationAsync();
disabledOrg.Enabled = false;
await organizationRepository.ReplaceAsync(disabledOrg);
await organizationUserRepository.CreateTestOrganizationUserAsync(disabledOrg, user);
var orgNoPremium = await organizationRepository.CreateTestOrganizationAsync();
orgNoPremium.UsersGetPremium = false;
await organizationRepository.ReplaceAsync(orgNoPremium);
await organizationUserRepository.CreateTestOrganizationUserAsync(orgNoPremium, user);
// Act
var result = await userRepository.GetPremiumAccessAsync(user.Id);
// Assert
Assert.NotNull(result);
Assert.False(result.PersonalPremium);
Assert.False(result.OrganizationPremium);
Assert.False(result.HasPremiumAccess);
}
[Theory, DatabaseData]
public async Task GetPremiumAccessAsync_NonExistentUser_ReturnsNull(
IUserRepository userRepository)
{
// Act
var result = await userRepository.GetPremiumAccessAsync(Guid.NewGuid());
// Assert
Assert.Null(result);
}
[Theory, DatabaseData]
public async Task GetPremiumAccessByIdsAsync_MultipleUsers_ReturnsCorrectAccessForEach(
IUserRepository userRepository,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository)
{
// Arrange
var personalPremiumUser = await userRepository.CreateAsync(new User
{
Name = "Personal Premium",
Email = $"{Guid.NewGuid()}@example.com",
ApiKey = "TEST",
SecurityStamp = "stamp",
Premium = true
});
var orgPremiumUser = await userRepository.CreateAsync(new User
{
Name = "Org Premium",
Email = $"{Guid.NewGuid()}@example.com",
ApiKey = "TEST",
SecurityStamp = "stamp",
Premium = false
});
var bothPremiumUser = await userRepository.CreateAsync(new User
{
Name = "Both Premium",
Email = $"{Guid.NewGuid()}@example.com",
ApiKey = "TEST",
SecurityStamp = "stamp",
Premium = true
});
var noPremiumUser = await userRepository.CreateAsync(new User
{
Name = "No Premium",
Email = $"{Guid.NewGuid()}@example.com",
ApiKey = "TEST",
SecurityStamp = "stamp",
Premium = false
});
var multiOrgUser = await userRepository.CreateAsync(new User
{
Name = "Multi Org User",
Email = $"{Guid.NewGuid()}@example.com",
ApiKey = "TEST",
SecurityStamp = "stamp",
Premium = false
});
var personalPremiumWithDisabledOrg = await userRepository.CreateAsync(new User
{
Name = "Personal Premium With Disabled Org",
Email = $"{Guid.NewGuid()}@example.com",
ApiKey = "TEST",
SecurityStamp = "stamp",
Premium = true
});
var organization = await organizationRepository.CreateTestOrganizationAsync();
await organizationUserRepository.CreateTestOrganizationUserAsync(organization, orgPremiumUser);
await organizationUserRepository.CreateTestOrganizationUserAsync(organization, bothPremiumUser);
await organizationUserRepository.CreateTestOrganizationUserAsync(organization, multiOrgUser);
var orgWithoutPremium = await organizationRepository.CreateTestOrganizationAsync();
orgWithoutPremium.UsersGetPremium = false;
await organizationRepository.ReplaceAsync(orgWithoutPremium);
await organizationUserRepository.CreateTestOrganizationUserAsync(orgWithoutPremium, multiOrgUser);
var disabledOrg = await organizationRepository.CreateTestOrganizationAsync();
disabledOrg.Enabled = false;
await organizationRepository.ReplaceAsync(disabledOrg);
await organizationUserRepository.CreateTestOrganizationUserAsync(disabledOrg, personalPremiumWithDisabledOrg);
// Act
var results = await userRepository.GetPremiumAccessByIdsAsync([
personalPremiumUser.Id,
orgPremiumUser.Id,
bothPremiumUser.Id,
noPremiumUser.Id,
multiOrgUser.Id,
personalPremiumWithDisabledOrg.Id
]);
var resultsList = results.ToList();
// Assert
Assert.Equal(6, resultsList.Count);
var personalResult = resultsList.First(r => r.Id == personalPremiumUser.Id);
Assert.True(personalResult.PersonalPremium);
Assert.False(personalResult.OrganizationPremium);
var orgResult = resultsList.First(r => r.Id == orgPremiumUser.Id);
Assert.False(orgResult.PersonalPremium);
Assert.True(orgResult.OrganizationPremium);
var bothResult = resultsList.First(r => r.Id == bothPremiumUser.Id);
Assert.True(bothResult.PersonalPremium);
Assert.True(bothResult.OrganizationPremium);
var noneResult = resultsList.First(r => r.Id == noPremiumUser.Id);
Assert.False(noneResult.PersonalPremium);
Assert.False(noneResult.OrganizationPremium);
var multiResult = resultsList.First(r => r.Id == multiOrgUser.Id);
Assert.False(multiResult.PersonalPremium);
Assert.True(multiResult.OrganizationPremium);
var personalWithDisabledOrgResult = resultsList.First(r => r.Id == personalPremiumWithDisabledOrg.Id);
Assert.True(personalWithDisabledOrgResult.PersonalPremium);
Assert.False(personalWithDisabledOrgResult.OrganizationPremium);
}
[Theory, DatabaseData]
public async Task GetPremiumAccessByIdsAsync_EmptyList_ReturnsEmptyResult(
IUserRepository userRepository)
{
// Act
var results = await userRepository.GetPremiumAccessByIdsAsync([]);
// Assert
Assert.Empty(results);
}
}