mirror of
https://github.com/bitwarden/server.git
synced 2024-12-03 14:03:33 +01:00
8d3fe12170
* [EC-787] Add new stored procedure OrganizationUser_ReadByUserIdWithPolicyDetails * [EC-787] Add new method IOrganizationUserRepository.GetByUserIdWithPolicyDetailsAsync * [EC-787] Add OrganizationUserPolicyDetails to represent policies applicable to a specific user * [EC-787] Add method IPolicyService.GetPoliciesApplicableToUser to filter the obtained policy data * [EC-787] Returning PolicyData on stored procedures * [EC-787] Changed GetPoliciesApplicableToUserAsync to return ICollection * [EC-787] Switched all usings of IPolicyRepository.GetManyByTypeApplicableToUserIdAsync to IPolicyService.GetPoliciesApplicableToUserAsync * [EC-787] Removed policy logic from BaseRequestValidator and added usage of IPolicyService.GetPoliciesApplicableToUserAsync * [EC-787] Added unit tests for IPolicyService.GetPoliciesApplicableToUserAsync * [EC-787] Added unit tests for OrganizationUserRepository.GetByUserIdWithPolicyDetailsAsync * [EC-787] Changed integration test to check for single result * [EC-787] Marked IPolicyRepository methods GetManyByTypeApplicableToUserIdAsync and GetCountByTypeApplicableToUserIdAsync as obsolete * [EC-787] Returning OrganizationUserId on OrganizationUser_ReadByUserIdWithPolicyDetails * [EC-787] Remove deprecated stored procedures Policy_CountByTypeApplicableToUser, Policy_ReadByTypeApplicableToUser and function PolicyApplicableToUser * [EC-787] Added method IPolicyService.AnyPoliciesApplicableToUserAsync * [EC-787] Removed 'OrganizationUserType' parameter from queries * [EC-787] Formatted OrganizationUserPolicyDetailsCompare * [EC-787] Renamed SQL migration files * [EC-787] Changed OrganizationUser_ReadByUserIdWithPolicyDetails to return Permissions json * [EC-787] Refactored excluded user types for each Policy * [EC-787] Updated dates on dbo_future files * [EC-787] Remove dbo_future files from sql proj * [EC-787] Added parameter PolicyType to IOrganizationUserRepository.GetByUserIdWithPolicyDetailsAsync * [EC-787] Rewrote OrganizationUser_ReadByUserIdWithPolicyDetails and added parameter for PolicyType * Update util/Migrator/DbScripts/2023-03-10_00_OrganizationUserReadByUserIdWithPolicyDetails.sql Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com> --------- Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
287 lines
13 KiB
C#
287 lines
13 KiB
C#
using System.Text.Json;
|
|
using Bit.Core.Entities;
|
|
using Bit.Core.Entities.Provider;
|
|
using Bit.Core.Enums;
|
|
using Bit.Core.Models.Data;
|
|
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
|
|
using Bit.Core.Repositories;
|
|
using Bit.Core.Test.AutoFixture.Attributes;
|
|
using Bit.Infrastructure.EFIntegration.Test.AutoFixture;
|
|
using Bit.Infrastructure.EFIntegration.Test.Repositories.EqualityComparers;
|
|
using Xunit;
|
|
using EfRepo = Bit.Infrastructure.EntityFramework.Repositories;
|
|
using OrganizationUser = Bit.Core.Entities.OrganizationUser;
|
|
using SqlRepo = Bit.Infrastructure.Dapper.Repositories;
|
|
|
|
namespace Bit.Infrastructure.EFIntegration.Test.Repositories;
|
|
|
|
public class OrganizationUserRepositoryTests
|
|
{
|
|
[CiSkippedTheory, EfOrganizationUserAutoData]
|
|
public async void CreateAsync_Works_DataMatches(OrganizationUser orgUser, User user, Organization org,
|
|
OrganizationUserCompare equalityComparer, List<EfRepo.OrganizationUserRepository> suts,
|
|
List<EfRepo.OrganizationRepository> efOrgRepos, List<EfRepo.UserRepository> efUserRepos,
|
|
SqlRepo.OrganizationUserRepository sqlOrgUserRepo, SqlRepo.UserRepository sqlUserRepo,
|
|
SqlRepo.OrganizationRepository sqlOrgRepo)
|
|
{
|
|
var savedOrgUsers = new List<OrganizationUser>();
|
|
foreach (var sut in suts)
|
|
{
|
|
var i = suts.IndexOf(sut);
|
|
var postEfUser = await efUserRepos[i].CreateAsync(user);
|
|
var postEfOrg = await efOrgRepos[i].CreateAsync(org);
|
|
sut.ClearChangeTracking();
|
|
|
|
orgUser.UserId = postEfUser.Id;
|
|
orgUser.OrganizationId = postEfOrg.Id;
|
|
var postEfOrgUser = await sut.CreateAsync(orgUser);
|
|
sut.ClearChangeTracking();
|
|
|
|
var savedOrgUser = await sut.GetByIdAsync(postEfOrgUser.Id);
|
|
savedOrgUsers.Add(savedOrgUser);
|
|
}
|
|
|
|
var postSqlUser = await sqlUserRepo.CreateAsync(user);
|
|
var postSqlOrg = await sqlOrgRepo.CreateAsync(org);
|
|
|
|
orgUser.UserId = postSqlUser.Id;
|
|
orgUser.OrganizationId = postSqlOrg.Id;
|
|
var sqlOrgUser = await sqlOrgUserRepo.CreateAsync(orgUser);
|
|
|
|
var savedSqlOrgUser = await sqlOrgUserRepo.GetByIdAsync(sqlOrgUser.Id);
|
|
savedOrgUsers.Add(savedSqlOrgUser);
|
|
|
|
var distinctItems = savedOrgUsers.Distinct(equalityComparer);
|
|
Assert.True(!distinctItems.Skip(1).Any());
|
|
}
|
|
|
|
[CiSkippedTheory, EfOrganizationUserAutoData]
|
|
public async void ReplaceAsync_Works_DataMatches(
|
|
OrganizationUser postOrgUser,
|
|
OrganizationUser replaceOrgUser,
|
|
User user,
|
|
Organization org,
|
|
OrganizationUserCompare equalityComparer,
|
|
List<EfRepo.OrganizationUserRepository> suts,
|
|
List<EfRepo.UserRepository> efUserRepos,
|
|
List<EfRepo.OrganizationRepository> efOrgRepos,
|
|
SqlRepo.OrganizationUserRepository sqlOrgUserRepo,
|
|
SqlRepo.UserRepository sqlUserRepo,
|
|
SqlRepo.OrganizationRepository sqlOrgRepo
|
|
)
|
|
{
|
|
var savedOrgUsers = new List<OrganizationUser>();
|
|
foreach (var sut in suts)
|
|
{
|
|
var i = suts.IndexOf(sut);
|
|
var postEfUser = await efUserRepos[i].CreateAsync(user);
|
|
var postEfOrg = await efOrgRepos[i].CreateAsync(org);
|
|
sut.ClearChangeTracking();
|
|
|
|
postOrgUser.UserId = replaceOrgUser.UserId = postEfUser.Id;
|
|
postOrgUser.OrganizationId = replaceOrgUser.OrganizationId = postEfOrg.Id;
|
|
var postEfOrgUser = await sut.CreateAsync(postOrgUser);
|
|
sut.ClearChangeTracking();
|
|
|
|
replaceOrgUser.Id = postOrgUser.Id;
|
|
await sut.ReplaceAsync(replaceOrgUser);
|
|
sut.ClearChangeTracking();
|
|
|
|
var replacedOrganizationUser = await sut.GetByIdAsync(replaceOrgUser.Id);
|
|
savedOrgUsers.Add(replacedOrganizationUser);
|
|
}
|
|
|
|
var postSqlUser = await sqlUserRepo.CreateAsync(user);
|
|
var postSqlOrg = await sqlOrgRepo.CreateAsync(org);
|
|
|
|
postOrgUser.UserId = replaceOrgUser.UserId = postSqlUser.Id;
|
|
postOrgUser.OrganizationId = replaceOrgUser.OrganizationId = postSqlOrg.Id;
|
|
var postSqlOrgUser = await sqlOrgUserRepo.CreateAsync(postOrgUser);
|
|
|
|
replaceOrgUser.Id = postSqlOrgUser.Id;
|
|
await sqlOrgUserRepo.ReplaceAsync(replaceOrgUser);
|
|
|
|
var replacedSqlUser = await sqlOrgUserRepo.GetByIdAsync(replaceOrgUser.Id);
|
|
|
|
var distinctItems = savedOrgUsers.Distinct(equalityComparer);
|
|
Assert.True(!distinctItems.Skip(1).Any());
|
|
}
|
|
|
|
[CiSkippedTheory, EfOrganizationUserAutoData]
|
|
public async void DeleteAsync_Works_DataMatches(OrganizationUser orgUser, User user, Organization org, List<EfRepo.OrganizationUserRepository> suts,
|
|
List<EfRepo.UserRepository> efUserRepos, List<EfRepo.OrganizationRepository> efOrgRepos,
|
|
SqlRepo.OrganizationUserRepository sqlOrgUserRepo, SqlRepo.UserRepository sqlUserRepo,
|
|
SqlRepo.OrganizationRepository sqlOrgRepo)
|
|
{
|
|
foreach (var sut in suts)
|
|
{
|
|
var i = suts.IndexOf(sut);
|
|
var postEfUser = await efUserRepos[i].CreateAsync(user);
|
|
var postEfOrg = await efOrgRepos[i].CreateAsync(org);
|
|
sut.ClearChangeTracking();
|
|
|
|
orgUser.UserId = postEfUser.Id;
|
|
orgUser.OrganizationId = postEfOrg.Id;
|
|
var postEfOrgUser = await sut.CreateAsync(orgUser);
|
|
sut.ClearChangeTracking();
|
|
|
|
var savedEfOrgUser = await sut.GetByIdAsync(postEfOrgUser.Id);
|
|
Assert.True(savedEfOrgUser != null);
|
|
sut.ClearChangeTracking();
|
|
|
|
await sut.DeleteAsync(savedEfOrgUser);
|
|
sut.ClearChangeTracking();
|
|
|
|
savedEfOrgUser = await sut.GetByIdAsync(savedEfOrgUser.Id);
|
|
Assert.True(savedEfOrgUser == null);
|
|
}
|
|
|
|
var postSqlUser = await sqlUserRepo.CreateAsync(user);
|
|
var postSqlOrg = await sqlOrgRepo.CreateAsync(org);
|
|
|
|
orgUser.UserId = postSqlUser.Id;
|
|
orgUser.OrganizationId = postSqlOrg.Id;
|
|
var postSqlOrgUser = await sqlOrgUserRepo.CreateAsync(orgUser);
|
|
|
|
var savedSqlOrgUser = await sqlOrgUserRepo.GetByIdAsync(postSqlOrgUser.Id);
|
|
Assert.True(savedSqlOrgUser != null);
|
|
|
|
await sqlOrgUserRepo.DeleteAsync(postSqlOrgUser);
|
|
savedSqlOrgUser = await sqlOrgUserRepo.GetByIdAsync(postSqlOrgUser.Id);
|
|
Assert.True(savedSqlOrgUser == null);
|
|
}
|
|
|
|
[CiSkippedTheory]
|
|
[EfPolicyApplicableToUserInlineAutoData(OrganizationUserType.User, false, OrganizationUserStatusType.Confirmed, true, false)] // Ordinary user
|
|
[EfPolicyApplicableToUserInlineAutoData(OrganizationUserType.User, false, OrganizationUserStatusType.Invited, true, false)] // Invited user
|
|
[EfPolicyApplicableToUserInlineAutoData(OrganizationUserType.Owner, false, OrganizationUserStatusType.Confirmed, true, false)] // Owner
|
|
[EfPolicyApplicableToUserInlineAutoData(OrganizationUserType.Admin, false, OrganizationUserStatusType.Confirmed, true, false)] // Admin
|
|
[EfPolicyApplicableToUserInlineAutoData(OrganizationUserType.User, true, OrganizationUserStatusType.Confirmed, true, false)] // canManagePolicies
|
|
[EfPolicyApplicableToUserInlineAutoData(OrganizationUserType.User, false, OrganizationUserStatusType.Confirmed, true, true)] // Provider
|
|
[EfPolicyApplicableToUserInlineAutoData(OrganizationUserType.User, false, OrganizationUserStatusType.Confirmed, false, false)] // Policy disabled
|
|
[EfPolicyApplicableToUserInlineAutoData(OrganizationUserType.User, false, OrganizationUserStatusType.Confirmed, true, false)] // No policy of Type
|
|
[EfPolicyApplicableToUserInlineAutoData(OrganizationUserType.User, false, OrganizationUserStatusType.Invited, true, false)] // User not minStatus
|
|
public async void GetByUserIdWithPolicyDetailsAsync_Works_DataMatches(
|
|
// Inline data
|
|
OrganizationUserType userType,
|
|
bool canManagePolicies,
|
|
OrganizationUserStatusType orgUserStatus,
|
|
bool policyEnabled,
|
|
bool isProvider,
|
|
|
|
// Auto data - models
|
|
Policy policy,
|
|
User user,
|
|
Organization organization,
|
|
OrganizationUser orgUser,
|
|
Provider provider,
|
|
ProviderOrganization providerOrganization,
|
|
ProviderUser providerUser,
|
|
OrganizationUserPolicyDetailsCompare equalityComparer,
|
|
|
|
// Auto data - EF repos
|
|
List<EfRepo.PolicyRepository> efPolicyRepository,
|
|
List<EfRepo.UserRepository> efUserRepository,
|
|
List<EfRepo.OrganizationRepository> efOrganizationRepository,
|
|
List<EfRepo.OrganizationUserRepository> suts,
|
|
List<EfRepo.ProviderRepository> efProviderRepository,
|
|
List<EfRepo.ProviderOrganizationRepository> efProviderOrganizationRepository,
|
|
List<EfRepo.ProviderUserRepository> efProviderUserRepository,
|
|
|
|
// Auto data - SQL repos
|
|
SqlRepo.PolicyRepository sqlPolicyRepo,
|
|
SqlRepo.UserRepository sqlUserRepo,
|
|
SqlRepo.OrganizationRepository sqlOrganizationRepo,
|
|
SqlRepo.ProviderRepository sqlProviderRepo,
|
|
SqlRepo.OrganizationUserRepository sqlOrganizationUserRepo,
|
|
SqlRepo.ProviderOrganizationRepository sqlProviderOrganizationRepo,
|
|
SqlRepo.ProviderUserRepository sqlProviderUserRepo
|
|
)
|
|
{
|
|
// Combine EF and SQL repos into one list per type
|
|
var policyRepos = efPolicyRepository.ToList<IPolicyRepository>();
|
|
policyRepos.Add(sqlPolicyRepo);
|
|
var userRepos = efUserRepository.ToList<IUserRepository>();
|
|
userRepos.Add(sqlUserRepo);
|
|
var orgRepos = efOrganizationRepository.ToList<IOrganizationRepository>();
|
|
orgRepos.Add(sqlOrganizationRepo);
|
|
var orgUserRepos = suts.ToList<IOrganizationUserRepository>();
|
|
orgUserRepos.Add(sqlOrganizationUserRepo);
|
|
var providerRepos = efProviderRepository.ToList<IProviderRepository>();
|
|
providerRepos.Add(sqlProviderRepo);
|
|
var providerOrgRepos = efProviderOrganizationRepository.ToList<IProviderOrganizationRepository>();
|
|
providerOrgRepos.Add(sqlProviderOrganizationRepo);
|
|
var providerUserRepos = efProviderUserRepository.ToList<IProviderUserRepository>();
|
|
providerUserRepos.Add(sqlProviderUserRepo);
|
|
|
|
// Arrange data
|
|
var savedPolicyType = PolicyType.SingleOrg;
|
|
|
|
orgUser.Type = userType;
|
|
orgUser.Status = orgUserStatus;
|
|
var permissionsData = new Permissions { ManagePolicies = canManagePolicies };
|
|
orgUser.Permissions = JsonSerializer.Serialize(permissionsData, new JsonSerializerOptions
|
|
{
|
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
});
|
|
|
|
policy.Enabled = policyEnabled;
|
|
policy.Type = savedPolicyType;
|
|
|
|
var results = new List<OrganizationUserPolicyDetails>();
|
|
|
|
foreach (var policyRepo in policyRepos)
|
|
{
|
|
var i = policyRepos.IndexOf(policyRepo);
|
|
|
|
// Seed database
|
|
user.CreationDate = user.RevisionDate = DateTime.Now;
|
|
var savedUser = await userRepos[i].CreateAsync(user);
|
|
var savedOrg = await orgRepos[i].CreateAsync(organization);
|
|
|
|
// Invited orgUsers are not associated with an account yet, so they are identified by Email not UserId
|
|
if (orgUserStatus == OrganizationUserStatusType.Invited)
|
|
{
|
|
orgUser.Email = savedUser.Email;
|
|
orgUser.UserId = null;
|
|
}
|
|
else
|
|
{
|
|
orgUser.UserId = savedUser.Id;
|
|
}
|
|
|
|
orgUser.OrganizationId = savedOrg.Id;
|
|
await orgUserRepos[i].CreateAsync(orgUser);
|
|
|
|
if (isProvider)
|
|
{
|
|
var savedProvider = await providerRepos[i].CreateAsync(provider);
|
|
|
|
providerOrganization.OrganizationId = savedOrg.Id;
|
|
providerOrganization.ProviderId = savedProvider.Id;
|
|
await providerOrgRepos[i].CreateAsync(providerOrganization);
|
|
|
|
providerUser.UserId = savedUser.Id;
|
|
providerUser.ProviderId = savedProvider.Id;
|
|
await providerUserRepos[i].CreateAsync(providerUser);
|
|
}
|
|
|
|
policy.OrganizationId = savedOrg.Id;
|
|
await policyRepo.CreateAsync(policy);
|
|
if (efPolicyRepository.Contains(policyRepo))
|
|
{
|
|
(policyRepo as EfRepo.BaseEntityFrameworkRepository).ClearChangeTracking();
|
|
}
|
|
|
|
// Act
|
|
var result = await orgUserRepos[i].GetByUserIdWithPolicyDetailsAsync(savedUser.Id, policy.Type);
|
|
results.Add(result.FirstOrDefault());
|
|
}
|
|
|
|
// Assert
|
|
var distinctItems = results.Distinct(equalityComparer);
|
|
|
|
Assert.Single(distinctItems);
|
|
}
|
|
}
|