mirror of
https://github.com/bitwarden/server.git
synced 2025-07-06 18:42:49 -05:00
Merge branch 'main' into jmccannon/ac/pm-16811-scim-invite-optimization
# Conflicts: # src/Core/AdminConsole/Services/Implementations/OrganizationService.cs # test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepositoryTests.cs
This commit is contained in:
@ -306,4 +306,81 @@ public class OrganizationDomainRepositoryTests
|
||||
var expectedDomain = domains.FirstOrDefault(domain => domain.DomainName == organizationDomain.DomainName);
|
||||
Assert.Null(expectedDomain);
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task GetVerifiedDomainsByOrganizationIdsAsync_ShouldVerifiedDomainsMatchesOrganizationIds(
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationDomainRepository organizationDomainRepository)
|
||||
{
|
||||
// Arrange
|
||||
var guid1 = Guid.NewGuid();
|
||||
var guid2 = Guid.NewGuid();
|
||||
|
||||
var organization1 = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = $"Test Org {guid1}",
|
||||
BillingEmail = $"test+{guid1}@example.com",
|
||||
Plan = "Test",
|
||||
PrivateKey = "privatekey",
|
||||
|
||||
});
|
||||
|
||||
var organization1Domain1 = new OrganizationDomain
|
||||
{
|
||||
OrganizationId = organization1.Id,
|
||||
DomainName = $"domain1+{guid1}@example.com",
|
||||
Txt = "btw+12345"
|
||||
};
|
||||
|
||||
const int arbitraryNextIteration = 1;
|
||||
organization1Domain1.SetNextRunDate(arbitraryNextIteration);
|
||||
organization1Domain1.SetVerifiedDate();
|
||||
|
||||
await organizationDomainRepository.CreateAsync(organization1Domain1);
|
||||
|
||||
var organization1Domain2 = new OrganizationDomain
|
||||
{
|
||||
OrganizationId = organization1.Id,
|
||||
DomainName = $"domain2+{guid1}@example.com",
|
||||
Txt = "btw+12345"
|
||||
};
|
||||
|
||||
organization1Domain2.SetNextRunDate(arbitraryNextIteration);
|
||||
|
||||
await organizationDomainRepository.CreateAsync(organization1Domain2);
|
||||
|
||||
var organization2 = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = $"Test Org {guid2}",
|
||||
BillingEmail = $"test+{guid2}@example.com",
|
||||
Plan = "Test",
|
||||
PrivateKey = "privatekey",
|
||||
|
||||
});
|
||||
|
||||
var organization2Domain1 = new OrganizationDomain
|
||||
{
|
||||
OrganizationId = organization2.Id,
|
||||
DomainName = $"domain+{guid2}@example.com",
|
||||
Txt = "btw+12345"
|
||||
};
|
||||
organization2Domain1.SetVerifiedDate();
|
||||
organization2Domain1.SetNextRunDate(arbitraryNextIteration);
|
||||
|
||||
await organizationDomainRepository.CreateAsync(organization2Domain1);
|
||||
|
||||
|
||||
// Act
|
||||
var domains = await organizationDomainRepository.GetVerifiedDomainsByOrganizationIdsAsync(new[] { organization1.Id });
|
||||
|
||||
// Assert
|
||||
var expectedDomain = domains.FirstOrDefault(domain => domain.DomainName == organization1Domain1.DomainName);
|
||||
Assert.NotNull(expectedDomain);
|
||||
|
||||
var unverifiedDomain = domains.FirstOrDefault(domain => domain.DomainName == organization1Domain2.DomainName);
|
||||
var otherOrganizationDomain = domains.FirstOrDefault(domain => domain.DomainName == organization2Domain1.DomainName);
|
||||
|
||||
Assert.Null(otherOrganizationDomain);
|
||||
Assert.Null(unverifiedDomain);
|
||||
}
|
||||
}
|
||||
|
@ -359,6 +359,75 @@ public class OrganizationUserRepositoryTests
|
||||
Assert.Equal(orgUser1.Id, responseModel.Single().Id);
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task CreateManyAsync_NoId_Works(IOrganizationRepository organizationRepository,
|
||||
IUserRepository userRepository,
|
||||
IOrganizationUserRepository organizationUserRepository)
|
||||
{
|
||||
// Arrange
|
||||
var user1 = await userRepository.CreateTestUserAsync("user1");
|
||||
var user2 = await userRepository.CreateTestUserAsync("user2");
|
||||
var user3 = await userRepository.CreateTestUserAsync("user3");
|
||||
List<User> users = [user1, user2, user3];
|
||||
|
||||
var org = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
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
|
||||
});
|
||||
|
||||
var orgUsers = users.Select(u => new OrganizationUser
|
||||
{
|
||||
OrganizationId = org.Id,
|
||||
UserId = u.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Type = OrganizationUserType.Owner
|
||||
});
|
||||
|
||||
var createdOrgUserIds = await organizationUserRepository.CreateManyAsync(orgUsers);
|
||||
|
||||
var readOrgUsers = await organizationUserRepository.GetManyByOrganizationAsync(org.Id, null);
|
||||
var readOrgUserIds = readOrgUsers.Select(ou => ou.Id);
|
||||
|
||||
Assert.Equal(createdOrgUserIds.ToHashSet(), readOrgUserIds.ToHashSet());
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task CreateManyAsync_WithId_Works(IOrganizationRepository organizationRepository,
|
||||
IUserRepository userRepository,
|
||||
IOrganizationUserRepository organizationUserRepository)
|
||||
{
|
||||
// Arrange
|
||||
var user1 = await userRepository.CreateTestUserAsync("user1");
|
||||
var user2 = await userRepository.CreateTestUserAsync("user2");
|
||||
var user3 = await userRepository.CreateTestUserAsync("user3");
|
||||
List<User> users = [user1, user2, user3];
|
||||
|
||||
var org = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
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
|
||||
});
|
||||
|
||||
var orgUsers = users.Select(u => new OrganizationUser
|
||||
{
|
||||
Id = CoreHelpers.GenerateComb(), // generate ID ahead of time
|
||||
OrganizationId = org.Id,
|
||||
UserId = u.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Type = OrganizationUserType.Owner
|
||||
});
|
||||
|
||||
var createdOrgUserIds = await organizationUserRepository.CreateManyAsync(orgUsers);
|
||||
|
||||
var readOrgUsers = await organizationUserRepository.GetManyByOrganizationAsync(org.Id, null);
|
||||
var readOrgUserIds = readOrgUsers.Select(ou => ou.Id);
|
||||
|
||||
Assert.Equal(createdOrgUserIds.ToHashSet(), readOrgUserIds.ToHashSet());
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task CreateManyAsync_WithCollectionAndGroup_SaveSuccessfully(
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
|
@ -433,4 +433,454 @@ public class CipherRepositoryTests
|
||||
Assert.False(unassignedCipherPermission.Read);
|
||||
Assert.False(unassignedCipherPermission.ViewPassword);
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task GetCipherPermissionsForOrganizationAsync_ManageProperty_RespectsCollectionUserRules(
|
||||
ICipherRepository cipherRepository,
|
||||
IUserRepository userRepository,
|
||||
ICollectionCipherRepository collectionCipherRepository,
|
||||
ICollectionRepository collectionRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository)
|
||||
{
|
||||
var (user, organization, orgUser) = await CreateTestUserAndOrganization(userRepository, organizationRepository, organizationUserRepository);
|
||||
|
||||
var manageCipher = await CreateCipherInOrganizationCollection(
|
||||
organization, orgUser, cipherRepository, collectionRepository, collectionCipherRepository,
|
||||
hasManagePermission: true, "Manage Collection");
|
||||
|
||||
var nonManageCipher = await CreateCipherInOrganizationCollection(
|
||||
organization, orgUser, cipherRepository, collectionRepository, collectionCipherRepository,
|
||||
hasManagePermission: false, "Non-Manage Collection");
|
||||
|
||||
var permissions = await cipherRepository.GetCipherPermissionsForOrganizationAsync(organization.Id, user.Id);
|
||||
Assert.Equal(2, permissions.Count);
|
||||
|
||||
var managePermission = permissions.FirstOrDefault(c => c.Id == manageCipher.Id);
|
||||
Assert.NotNull(managePermission);
|
||||
Assert.True(managePermission.Manage, "Collection with Manage=true should grant Manage permission");
|
||||
|
||||
var nonManagePermission = permissions.FirstOrDefault(c => c.Id == nonManageCipher.Id);
|
||||
Assert.NotNull(nonManagePermission);
|
||||
Assert.False(nonManagePermission.Manage, "Collection with Manage=false should not grant Manage permission");
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task GetCipherPermissionsForOrganizationAsync_ManageProperty_RespectsCollectionGroupRules(
|
||||
ICipherRepository cipherRepository,
|
||||
IUserRepository userRepository,
|
||||
ICollectionCipherRepository collectionCipherRepository,
|
||||
ICollectionRepository collectionRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
IGroupRepository groupRepository)
|
||||
{
|
||||
var (user, organization, orgUser) = await CreateTestUserAndOrganization(userRepository, organizationRepository, organizationUserRepository);
|
||||
|
||||
var group = await groupRepository.CreateAsync(new Group
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
Name = "Test Group",
|
||||
});
|
||||
await groupRepository.UpdateUsersAsync(group.Id, new[] { orgUser.Id });
|
||||
|
||||
var (manageCipher, nonManageCipher) = await CreateCipherInOrganizationCollectionWithGroup(
|
||||
organization, group, cipherRepository, collectionRepository, collectionCipherRepository, groupRepository);
|
||||
|
||||
var permissions = await cipherRepository.GetCipherPermissionsForOrganizationAsync(organization.Id, user.Id);
|
||||
Assert.Equal(2, permissions.Count);
|
||||
|
||||
var managePermission = permissions.FirstOrDefault(c => c.Id == manageCipher.Id);
|
||||
Assert.NotNull(managePermission);
|
||||
Assert.True(managePermission.Manage, "Collection with Group Manage=true should grant Manage permission");
|
||||
|
||||
var nonManagePermission = permissions.FirstOrDefault(c => c.Id == nonManageCipher.Id);
|
||||
Assert.NotNull(nonManagePermission);
|
||||
Assert.False(nonManagePermission.Manage, "Collection with Group Manage=false should not grant Manage permission");
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task GetManyByUserIdAsync_ManageProperty_RespectsCollectionAndOwnershipRules(
|
||||
ICipherRepository cipherRepository,
|
||||
IUserRepository userRepository,
|
||||
ICollectionCipherRepository collectionCipherRepository,
|
||||
ICollectionRepository collectionRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository)
|
||||
{
|
||||
var (user, organization, orgUser) = await CreateTestUserAndOrganization(userRepository, organizationRepository, organizationUserRepository);
|
||||
|
||||
var manageCipher = await CreateCipherInOrganizationCollection(
|
||||
organization, orgUser, cipherRepository, collectionRepository, collectionCipherRepository,
|
||||
hasManagePermission: true, "Manage Collection");
|
||||
|
||||
var nonManageCipher = await CreateCipherInOrganizationCollection(
|
||||
organization, orgUser, cipherRepository, collectionRepository, collectionCipherRepository,
|
||||
hasManagePermission: false, "Non-Manage Collection");
|
||||
|
||||
var personalCipher = await CreatePersonalCipher(user, cipherRepository);
|
||||
|
||||
var userCiphers = await cipherRepository.GetManyByUserIdAsync(user.Id);
|
||||
Assert.Equal(3, userCiphers.Count);
|
||||
|
||||
var managePermission = userCiphers.FirstOrDefault(c => c.Id == manageCipher.Id);
|
||||
Assert.NotNull(managePermission);
|
||||
Assert.True(managePermission.Manage, "Collection with Manage=true should grant Manage permission");
|
||||
|
||||
var nonManagePermission = userCiphers.FirstOrDefault(c => c.Id == nonManageCipher.Id);
|
||||
Assert.NotNull(nonManagePermission);
|
||||
Assert.False(nonManagePermission.Manage, "Collection with Manage=false should not grant Manage permission");
|
||||
|
||||
var personalPermission = userCiphers.FirstOrDefault(c => c.Id == personalCipher.Id);
|
||||
Assert.NotNull(personalPermission);
|
||||
Assert.True(personalPermission.Manage, "Personal ciphers should always have Manage permission");
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task GetByIdAsync_ManageProperty_RespectsCollectionAndOwnershipRules(
|
||||
ICipherRepository cipherRepository,
|
||||
IUserRepository userRepository,
|
||||
ICollectionCipherRepository collectionCipherRepository,
|
||||
ICollectionRepository collectionRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository)
|
||||
{
|
||||
var (user, organization, orgUser) = await CreateTestUserAndOrganization(userRepository, organizationRepository, organizationUserRepository);
|
||||
|
||||
var manageCipher = await CreateCipherInOrganizationCollection(
|
||||
organization, orgUser, cipherRepository, collectionRepository, collectionCipherRepository,
|
||||
hasManagePermission: true, "Manage Collection");
|
||||
|
||||
var nonManageCipher = await CreateCipherInOrganizationCollection(
|
||||
organization, orgUser, cipherRepository, collectionRepository, collectionCipherRepository,
|
||||
hasManagePermission: false, "Non-Manage Collection");
|
||||
|
||||
var personalCipher = await CreatePersonalCipher(user, cipherRepository);
|
||||
|
||||
var manageDetails = await cipherRepository.GetByIdAsync(manageCipher.Id, user.Id);
|
||||
Assert.NotNull(manageDetails);
|
||||
Assert.True(manageDetails.Manage, "Collection with Manage=true should grant Manage permission");
|
||||
|
||||
var nonManageDetails = await cipherRepository.GetByIdAsync(nonManageCipher.Id, user.Id);
|
||||
Assert.NotNull(nonManageDetails);
|
||||
Assert.False(nonManageDetails.Manage, "Collection with Manage=false should not grant Manage permission");
|
||||
|
||||
var personalDetails = await cipherRepository.GetByIdAsync(personalCipher.Id, user.Id);
|
||||
Assert.NotNull(personalDetails);
|
||||
Assert.True(personalDetails.Manage, "Personal ciphers should always have Manage permission");
|
||||
}
|
||||
|
||||
private async Task<(User user, Organization org, OrganizationUser orgUser)> CreateTestUserAndOrganization(
|
||||
IUserRepository userRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
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 Organization",
|
||||
BillingEmail = user.Email,
|
||||
Plan = "Test"
|
||||
});
|
||||
|
||||
var orgUser = await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
UserId = user.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Type = OrganizationUserType.Owner,
|
||||
});
|
||||
|
||||
return (user, organization, orgUser);
|
||||
}
|
||||
|
||||
private async Task<Cipher> CreateCipherInOrganizationCollection(
|
||||
Organization organization,
|
||||
OrganizationUser orgUser,
|
||||
ICipherRepository cipherRepository,
|
||||
ICollectionRepository collectionRepository,
|
||||
ICollectionCipherRepository collectionCipherRepository,
|
||||
bool hasManagePermission,
|
||||
string collectionName)
|
||||
{
|
||||
var collection = await collectionRepository.CreateAsync(new Collection
|
||||
{
|
||||
Name = collectionName,
|
||||
OrganizationId = organization.Id,
|
||||
});
|
||||
|
||||
var cipher = await cipherRepository.CreateAsync(new Cipher
|
||||
{
|
||||
Type = CipherType.Login,
|
||||
OrganizationId = organization.Id,
|
||||
Data = ""
|
||||
});
|
||||
|
||||
await collectionCipherRepository.UpdateCollectionsForAdminAsync(cipher.Id, organization.Id,
|
||||
new List<Guid> { collection.Id });
|
||||
|
||||
await collectionRepository.UpdateUsersAsync(collection.Id, new List<CollectionAccessSelection>
|
||||
{
|
||||
new() { Id = orgUser.Id, HidePasswords = false, ReadOnly = false, Manage = hasManagePermission }
|
||||
});
|
||||
|
||||
return cipher;
|
||||
}
|
||||
|
||||
private async Task<(Cipher manageCipher, Cipher nonManageCipher)> CreateCipherInOrganizationCollectionWithGroup(
|
||||
Organization organization,
|
||||
Group group,
|
||||
ICipherRepository cipherRepository,
|
||||
ICollectionRepository collectionRepository,
|
||||
ICollectionCipherRepository collectionCipherRepository,
|
||||
IGroupRepository groupRepository)
|
||||
{
|
||||
var manageCollection = await collectionRepository.CreateAsync(new Collection
|
||||
{
|
||||
Name = "Group Manage Collection",
|
||||
OrganizationId = organization.Id,
|
||||
});
|
||||
|
||||
var nonManageCollection = await collectionRepository.CreateAsync(new Collection
|
||||
{
|
||||
Name = "Group Non-Manage Collection",
|
||||
OrganizationId = organization.Id,
|
||||
});
|
||||
|
||||
var manageCipher = await cipherRepository.CreateAsync(new Cipher
|
||||
{
|
||||
Type = CipherType.Login,
|
||||
OrganizationId = organization.Id,
|
||||
Data = ""
|
||||
});
|
||||
|
||||
var nonManageCipher = await cipherRepository.CreateAsync(new Cipher
|
||||
{
|
||||
Type = CipherType.Login,
|
||||
OrganizationId = organization.Id,
|
||||
Data = ""
|
||||
});
|
||||
|
||||
await collectionCipherRepository.UpdateCollectionsForAdminAsync(manageCipher.Id, organization.Id,
|
||||
new List<Guid> { manageCollection.Id });
|
||||
await collectionCipherRepository.UpdateCollectionsForAdminAsync(nonManageCipher.Id, organization.Id,
|
||||
new List<Guid> { nonManageCollection.Id });
|
||||
|
||||
await groupRepository.ReplaceAsync(group,
|
||||
new[]
|
||||
{
|
||||
new CollectionAccessSelection
|
||||
{
|
||||
Id = manageCollection.Id,
|
||||
HidePasswords = false,
|
||||
ReadOnly = false,
|
||||
Manage = true
|
||||
},
|
||||
new CollectionAccessSelection
|
||||
{
|
||||
Id = nonManageCollection.Id,
|
||||
HidePasswords = false,
|
||||
ReadOnly = false,
|
||||
Manage = false
|
||||
}
|
||||
});
|
||||
|
||||
return (manageCipher, nonManageCipher);
|
||||
}
|
||||
|
||||
private async Task<Cipher> CreatePersonalCipher(User user, ICipherRepository cipherRepository)
|
||||
{
|
||||
return await cipherRepository.CreateAsync(new Cipher
|
||||
{
|
||||
Type = CipherType.Login,
|
||||
UserId = user.Id,
|
||||
Data = ""
|
||||
});
|
||||
}
|
||||
|
||||
[DatabaseTheory, DatabaseData]
|
||||
public async Task GetUserSecurityTasksByCipherIdsAsync_Works(
|
||||
ICipherRepository cipherRepository,
|
||||
IUserRepository userRepository,
|
||||
ICollectionCipherRepository collectionCipherRepository,
|
||||
ICollectionRepository collectionRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
IGroupRepository groupRepository
|
||||
)
|
||||
{
|
||||
// Users
|
||||
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",
|
||||
});
|
||||
|
||||
// Organization
|
||||
var organization = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = "Test Organization",
|
||||
BillingEmail = user1.Email,
|
||||
Plan = "Test"
|
||||
});
|
||||
|
||||
// Org Users
|
||||
var orgUser1 = await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
UserId = user1.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Type = OrganizationUserType.Owner,
|
||||
});
|
||||
|
||||
var orgUser2 = await organizationUserRepository.CreateAsync(new OrganizationUser
|
||||
{
|
||||
UserId = user2.Id,
|
||||
OrganizationId = organization.Id,
|
||||
Status = OrganizationUserStatusType.Confirmed,
|
||||
Type = OrganizationUserType.User,
|
||||
});
|
||||
|
||||
// A group that will be assigned Edit permissions to any collections
|
||||
var editGroup = await groupRepository.CreateAsync(new Group
|
||||
{
|
||||
OrganizationId = organization.Id,
|
||||
Name = "Edit Group",
|
||||
});
|
||||
await groupRepository.UpdateUsersAsync(editGroup.Id, new[] { orgUser1.Id });
|
||||
|
||||
// Add collections to Org
|
||||
var manageCollection = await collectionRepository.CreateAsync(new Collection
|
||||
{
|
||||
Name = "Manage Collection",
|
||||
OrganizationId = organization.Id
|
||||
});
|
||||
|
||||
// Use a 2nd collection to differentiate between the two users
|
||||
var manageCollection2 = await collectionRepository.CreateAsync(new Collection
|
||||
{
|
||||
Name = "Manage Collection 2",
|
||||
OrganizationId = organization.Id
|
||||
});
|
||||
var viewOnlyCollection = await collectionRepository.CreateAsync(new Collection
|
||||
{
|
||||
Name = "View Only Collection",
|
||||
OrganizationId = organization.Id
|
||||
});
|
||||
|
||||
// Ciphers
|
||||
var manageCipher1 = await cipherRepository.CreateAsync(new Cipher
|
||||
{
|
||||
Type = CipherType.Login,
|
||||
OrganizationId = organization.Id,
|
||||
Data = ""
|
||||
});
|
||||
|
||||
var manageCipher2 = await cipherRepository.CreateAsync(new Cipher
|
||||
{
|
||||
Type = CipherType.Login,
|
||||
OrganizationId = organization.Id,
|
||||
Data = ""
|
||||
});
|
||||
|
||||
var viewOnlyCipher = await cipherRepository.CreateAsync(new Cipher
|
||||
{
|
||||
Type = CipherType.Login,
|
||||
OrganizationId = organization.Id,
|
||||
Data = ""
|
||||
});
|
||||
|
||||
await collectionCipherRepository.UpdateCollectionsForAdminAsync(manageCipher1.Id, organization.Id,
|
||||
new List<Guid> { manageCollection.Id });
|
||||
|
||||
await collectionCipherRepository.UpdateCollectionsForAdminAsync(manageCipher2.Id, organization.Id,
|
||||
new List<Guid> { manageCollection2.Id });
|
||||
|
||||
await collectionCipherRepository.UpdateCollectionsForAdminAsync(viewOnlyCipher.Id, organization.Id,
|
||||
new List<Guid> { viewOnlyCollection.Id });
|
||||
|
||||
await collectionRepository.UpdateUsersAsync(manageCollection.Id, new List<CollectionAccessSelection>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Id = orgUser1.Id,
|
||||
HidePasswords = false,
|
||||
ReadOnly = false,
|
||||
Manage = true
|
||||
},
|
||||
new()
|
||||
{
|
||||
Id = orgUser2.Id,
|
||||
HidePasswords = false,
|
||||
ReadOnly = false,
|
||||
Manage = true
|
||||
}
|
||||
});
|
||||
|
||||
// Only add second user to the second manage collection
|
||||
await collectionRepository.UpdateUsersAsync(manageCollection2.Id, new List<CollectionAccessSelection>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Id = orgUser2.Id,
|
||||
HidePasswords = false,
|
||||
ReadOnly = false,
|
||||
Manage = true
|
||||
},
|
||||
});
|
||||
|
||||
await collectionRepository.UpdateUsersAsync(viewOnlyCollection.Id, new List<CollectionAccessSelection>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Id = orgUser1.Id,
|
||||
HidePasswords = false,
|
||||
ReadOnly = false,
|
||||
Manage = false
|
||||
}
|
||||
});
|
||||
|
||||
var securityTasks = new List<SecurityTask>
|
||||
{
|
||||
new SecurityTask { CipherId = manageCipher1.Id, Id = Guid.NewGuid() },
|
||||
new SecurityTask { CipherId = manageCipher2.Id, Id = Guid.NewGuid() },
|
||||
new SecurityTask { CipherId = viewOnlyCipher.Id, Id = Guid.NewGuid() }
|
||||
};
|
||||
|
||||
var userSecurityTaskCiphers = await cipherRepository.GetUserSecurityTasksByCipherIdsAsync(organization.Id, securityTasks);
|
||||
|
||||
Assert.NotEmpty(userSecurityTaskCiphers);
|
||||
Assert.Equal(3, userSecurityTaskCiphers.Count);
|
||||
|
||||
var user1TaskCiphers = userSecurityTaskCiphers.Where(t => t.UserId == user1.Id);
|
||||
Assert.Single(user1TaskCiphers);
|
||||
Assert.Equal(user1.Email, user1TaskCiphers.First().Email);
|
||||
Assert.Equal(user1.Id, user1TaskCiphers.First().UserId);
|
||||
Assert.Equal(manageCipher1.Id, user1TaskCiphers.First().CipherId);
|
||||
|
||||
var user2TaskCiphers = userSecurityTaskCiphers.Where(t => t.UserId == user2.Id);
|
||||
Assert.NotNull(user2TaskCiphers);
|
||||
Assert.Equal(2, user2TaskCiphers.Count());
|
||||
Assert.Equal(user2.Email, user2TaskCiphers.Last().Email);
|
||||
Assert.Equal(user2.Id, user2TaskCiphers.Last().UserId);
|
||||
Assert.Contains(user2TaskCiphers, t => t.CipherId == manageCipher1.Id && t.TaskId == securityTasks[0].Id);
|
||||
Assert.Contains(user2TaskCiphers, t => t.CipherId == manageCipher2.Id && t.TaskId == securityTasks[1].Id);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user