1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-30 07:36:14 -05:00

[PM-13274] [Unified] Add integration tests for creating and updating collections (#5814)

This commit is contained in:
Thomas Rittson
2025-05-23 11:27:37 +10:00
committed by GitHub
parent 328b84eea0
commit 83478f9c69
4 changed files with 263 additions and 145 deletions

View File

@ -1,5 +1,6 @@
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;
@ -26,15 +27,23 @@ public static class OrganizationTestHelpers
});
}
/// <summary>
/// Creates an Enterprise organization.
/// </summary>
public static Task<Organization> CreateTestOrganizationAsync(this IOrganizationRepository organizationRepository,
string identifier = "test")
=> organizationRepository.CreateAsync(new Organization
{
Name = $"{identifier}-{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 = "Enterprise (Annually)", // TODO: EF does not enforce this being NOT NULl
PlanType = PlanType.EnterpriseAnnually
});
/// <summary>
/// Creates a confirmed Owner for the specified organization and user.
/// Does not include any cryptographic material.
/// </summary>
public static Task<OrganizationUser> CreateTestOrganizationUserAsync(
this IOrganizationUserRepository organizationUserRepository,
Organization organization,

View File

@ -0,0 +1,105 @@
using Bit.Core.AdminConsole.Repositories;
using Bit.Core.Entities;
using Bit.Core.Models.Data;
using Bit.Core.Repositories;
using Xunit;
namespace Bit.Infrastructure.IntegrationTest.AdminConsole.Repositories.CollectionRepository;
public class CollectionRepositoryCreateTests
{
[DatabaseTheory, DatabaseData]
public async Task CreateAsync_WithAccess_Works(
IUserRepository userRepository,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository,
IGroupRepository groupRepository,
ICollectionRepository collectionRepository)
{
// Arrange
var organization = await organizationRepository.CreateTestOrganizationAsync();
var user1 = await userRepository.CreateTestUserAsync();
var orgUser1 = await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user1);
var user2 = await userRepository.CreateTestUserAsync();
var orgUser2 = await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user2);
var group1 = await groupRepository.CreateTestGroupAsync(organization);
var group2 = await groupRepository.CreateTestGroupAsync(organization);
var collection = new Collection
{
Name = "Test Collection Name",
OrganizationId = organization.Id,
};
// Act
await collectionRepository.CreateAsync(collection,
[
new CollectionAccessSelection { Id = group1.Id, Manage = true, HidePasswords = true, ReadOnly = false, },
new CollectionAccessSelection { Id = group2.Id, Manage = false, HidePasswords = false, ReadOnly = true, },
],
[
new CollectionAccessSelection { Id = orgUser1.Id, Manage = true, HidePasswords = false, ReadOnly = true },
new CollectionAccessSelection { Id = orgUser2.Id, Manage = false, HidePasswords = true, ReadOnly = false },
]
);
// Assert
var (actualCollection, actualAccess) = await collectionRepository.GetByIdWithAccessAsync(collection.Id);
Assert.NotNull(actualCollection);
Assert.Equal("Test Collection Name", actualCollection.Name);
var groups = actualAccess.Groups.ToArray();
Assert.Equal(2, groups.Length);
Assert.Single(groups, g => g.Id == group1.Id && g.Manage && g.HidePasswords && !g.ReadOnly);
Assert.Single(groups, g => g.Id == group2.Id && !g.Manage && !g.HidePasswords && g.ReadOnly);
var users = actualAccess.Users.ToArray();
Assert.Equal(2, users.Length);
Assert.Single(users, u => u.Id == orgUser1.Id && u.Manage && !u.HidePasswords && u.ReadOnly);
Assert.Single(users, u => u.Id == orgUser2.Id && !u.Manage && u.HidePasswords && !u.ReadOnly);
// Clean up data
await userRepository.DeleteAsync(user1);
await userRepository.DeleteAsync(user2);
await organizationRepository.DeleteAsync(organization);
await groupRepository.DeleteManyAsync([group1.Id, group2.Id]);
await organizationUserRepository.DeleteManyAsync([orgUser1.Id, orgUser2.Id]);
}
/// <remarks>
/// Makes sure that the sproc handles empty sets.
/// </remarks>
[DatabaseTheory, DatabaseData]
public async Task CreateAsync_WithNoAccess_Works(
IOrganizationRepository organizationRepository,
ICollectionRepository collectionRepository)
{
// Arrange
var organization = await organizationRepository.CreateTestOrganizationAsync();
var collection = new Collection
{
Name = "Test Collection Name",
OrganizationId = organization.Id,
};
// Act
await collectionRepository.CreateAsync(collection, [], []);
// Assert
var (actualCollection, actualAccess) = await collectionRepository.GetByIdWithAccessAsync(collection.Id);
Assert.NotNull(actualCollection);
Assert.Equal("Test Collection Name", actualCollection.Name);
Assert.Empty(actualAccess.Groups);
Assert.Empty(actualAccess.Users);
// Clean up
await organizationRepository.DeleteAsync(organization);
}
}

View File

@ -0,0 +1,147 @@
using Bit.Core.AdminConsole.Repositories;
using Bit.Core.Entities;
using Bit.Core.Models.Data;
using Bit.Core.Repositories;
using Xunit;
namespace Bit.Infrastructure.IntegrationTest.AdminConsole.Repositories.CollectionRepository;
public class CollectionRepositoryReplaceTests
{
[DatabaseTheory, DatabaseData]
public async Task ReplaceAsync_WithAccess_Works(
IUserRepository userRepository,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository,
IGroupRepository groupRepository,
ICollectionRepository collectionRepository)
{
// Arrange
var organization = await organizationRepository.CreateTestOrganizationAsync();
var user1 = await userRepository.CreateTestUserAsync();
var orgUser1 = await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user1);
var user2 = await userRepository.CreateTestUserAsync();
var orgUser2 = await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user2);
var user3 = await userRepository.CreateTestUserAsync();
var orgUser3 = await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user3);
var group1 = await groupRepository.CreateTestGroupAsync(organization);
var group2 = await groupRepository.CreateTestGroupAsync(organization);
var group3 = await groupRepository.CreateTestGroupAsync(organization);
var collection = new Collection
{
Name = "Test Collection Name",
OrganizationId = organization.Id,
};
await collectionRepository.CreateAsync(collection,
[
new CollectionAccessSelection { Id = group1.Id, Manage = true, HidePasswords = true, ReadOnly = false, },
new CollectionAccessSelection { Id = group2.Id, Manage = false, HidePasswords = false, ReadOnly = true, },
],
[
new CollectionAccessSelection { Id = orgUser1.Id, Manage = true, HidePasswords = false, ReadOnly = true },
new CollectionAccessSelection { Id = orgUser2.Id, Manage = false, HidePasswords = true, ReadOnly = false },
]
);
// Act
collection.Name = "Updated Collection Name";
await collectionRepository.ReplaceAsync(collection,
[
// Delete group1
// Update group2:
new CollectionAccessSelection { Id = group2.Id, Manage = true, HidePasswords = true, ReadOnly = false, },
// Add group3:
new CollectionAccessSelection { Id = group3.Id, Manage = false, HidePasswords = false, ReadOnly = true, },
],
[
// Delete orgUser1
// Update orgUser2:
new CollectionAccessSelection { Id = orgUser2.Id, Manage = false, HidePasswords = false, ReadOnly = true },
// Add orgUser3:
new CollectionAccessSelection { Id = orgUser3.Id, Manage = true, HidePasswords = false, ReadOnly = true },
]
);
// Assert
var (actualCollection, actualAccess) = await collectionRepository.GetByIdWithAccessAsync(collection.Id);
Assert.NotNull(actualCollection);
Assert.Equal("Updated Collection Name", actualCollection.Name);
var groups = actualAccess.Groups.ToArray();
Assert.Equal(2, groups.Length);
Assert.Single(groups, g => g.Id == group2.Id && g.Manage && g.HidePasswords && !g.ReadOnly);
Assert.Single(groups, g => g.Id == group3.Id && !g.Manage && !g.HidePasswords && g.ReadOnly);
var users = actualAccess.Users.ToArray();
Assert.Equal(2, users.Length);
Assert.Single(users, u => u.Id == orgUser2.Id && !u.Manage && !u.HidePasswords && u.ReadOnly);
Assert.Single(users, u => u.Id == orgUser3.Id && u.Manage && !u.HidePasswords && u.ReadOnly);
// Clean up data
await userRepository.DeleteAsync(user1);
await userRepository.DeleteAsync(user2);
await userRepository.DeleteAsync(user3);
await organizationRepository.DeleteAsync(organization);
}
/// <remarks>
/// Makes sure that the sproc handles empty sets.
/// </remarks>
[DatabaseTheory, DatabaseData]
public async Task ReplaceAsync_WithNoAccess_Works(
IUserRepository userRepository,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository,
IGroupRepository groupRepository,
ICollectionRepository collectionRepository)
{
// Arrange
var organization = await organizationRepository.CreateTestOrganizationAsync();
var user = await userRepository.CreateTestUserAsync();
var orgUser = await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user);
var group = await groupRepository.CreateTestGroupAsync(organization);
var collection = new Collection
{
Name = "Test Collection Name",
OrganizationId = organization.Id,
};
await collectionRepository.CreateAsync(collection,
[
new CollectionAccessSelection { Id = group.Id, Manage = true, HidePasswords = false, ReadOnly = true },
],
[
new CollectionAccessSelection { Id = orgUser.Id, Manage = true, HidePasswords = false, ReadOnly = true },
]);
// Act
collection.Name = "Updated Collection Name";
await collectionRepository.ReplaceAsync(collection, [], []);
// Assert
var (actualCollection, actualAccess) = await collectionRepository.GetByIdWithAccessAsync(collection.Id);
Assert.NotNull(actualCollection);
Assert.Equal("Updated Collection Name", actualCollection.Name);
Assert.Empty(actualAccess.Groups);
Assert.Empty(actualAccess.Users);
// Clean up
await userRepository.DeleteAsync(user);
await organizationRepository.DeleteAsync(organization);
}
}

View File

@ -0,0 +1,466 @@
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.Models.Data;
using Bit.Core.Repositories;
using Xunit;
namespace Bit.Infrastructure.IntegrationTest.AdminConsole.Repositories.CollectionRepository;
public class CollectionRepositoryTests
{
/// <summary>
/// Test to ensure that access relationships are retrieved when requested
/// </summary>
[DatabaseTheory, DatabaseData]
public async Task GetByIdWithPermissionsAsync_WithRelationships_Success(IUserRepository userRepository,
IOrganizationRepository organizationRepository,
ICollectionRepository collectionRepository,
IOrganizationUserRepository organizationUserRepository, IGroupRepository groupRepository)
{
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 group = await groupRepository.CreateAsync(new Group
{
Name = "Test Group",
OrganizationId = organization.Id,
});
var collection = new Collection { Name = "Test Collection", OrganizationId = organization.Id, };
await collectionRepository.CreateAsync(collection, groups: new[]
{
new CollectionAccessSelection
{
Id = group.Id, HidePasswords = false, ReadOnly = true, Manage = false
}
}, users: new[]
{
new CollectionAccessSelection()
{
Id = orgUser.Id, HidePasswords = false, ReadOnly = false, Manage = true
}
});
var collectionWithPermissions = await collectionRepository.GetByIdWithPermissionsAsync(collection.Id, user.Id, true);
Assert.NotNull(collectionWithPermissions);
Assert.Equal(1, collectionWithPermissions.Users?.Count());
Assert.Equal(1, collectionWithPermissions.Groups?.Count());
Assert.True(collectionWithPermissions.Assigned);
Assert.True(collectionWithPermissions.Manage);
Assert.False(collectionWithPermissions.ReadOnly);
Assert.False(collectionWithPermissions.HidePasswords);
}
/// <summary>
/// Test to ensure that a user's explicitly assigned permissions replaces any group permissions
/// that user may belong to
/// </summary>
[DatabaseTheory, DatabaseData]
public async Task GetByIdWithPermissionsAsync_UserOverrideGroup_Success(IUserRepository userRepository,
IOrganizationRepository organizationRepository,
ICollectionRepository collectionRepository,
IOrganizationUserRepository organizationUserRepository, IGroupRepository groupRepository)
{
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 group = await groupRepository.CreateAsync(new Group
{
Name = "Test Group",
OrganizationId = organization.Id,
});
// Assign the test user to the test group
await groupRepository.UpdateUsersAsync(group.Id, new[] { orgUser.Id });
var collection = new Collection { Name = "Test Collection", OrganizationId = organization.Id, };
await collectionRepository.CreateAsync(collection, groups: new[]
{
new CollectionAccessSelection
{
Id = group.Id, HidePasswords = false, ReadOnly = false, Manage = true // Group is Manage
}
}, users: new[]
{
new CollectionAccessSelection()
{
Id = orgUser.Id, HidePasswords = false, ReadOnly = true, Manage = false // User is given ReadOnly (should override group)
}
});
var collectionWithPermissions = await collectionRepository.GetByIdWithPermissionsAsync(collection.Id, user.Id, true);
Assert.NotNull(collectionWithPermissions);
Assert.Equal(1, collectionWithPermissions.Users?.Count());
Assert.Equal(1, collectionWithPermissions.Groups?.Count());
Assert.True(collectionWithPermissions.Assigned);
Assert.False(collectionWithPermissions.Manage);
Assert.True(collectionWithPermissions.ReadOnly);
Assert.False(collectionWithPermissions.HidePasswords);
}
/// <summary>
/// Test to ensure that the returned permissions are the most permissive combination of group permissions when
/// multiple groups are assigned to the same collection with different permissions
/// </summary>
[DatabaseTheory, DatabaseData]
public async Task GetByIdWithPermissionsAsync_CombineGroupPermissions_Success(IUserRepository userRepository,
IOrganizationRepository organizationRepository,
ICollectionRepository collectionRepository,
IOrganizationUserRepository organizationUserRepository, IGroupRepository groupRepository)
{
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 group = await groupRepository.CreateAsync(new Group
{
Name = "Test Group",
OrganizationId = organization.Id,
});
var group2 = await groupRepository.CreateAsync(new Group
{
Name = "Test Group 2",
OrganizationId = organization.Id,
});
// Assign the test user to the test groups
await groupRepository.UpdateUsersAsync(group.Id, new[] { orgUser.Id });
await groupRepository.UpdateUsersAsync(group2.Id, new[] { orgUser.Id });
var collection = new Collection { Name = "Test Collection", OrganizationId = organization.Id, };
await collectionRepository.CreateAsync(collection, groups: new[]
{
new CollectionAccessSelection
{
Id = group.Id, HidePasswords = false, ReadOnly = true, Manage = false // Group 1 is ReadOnly
},
new CollectionAccessSelection
{
Id = group2.Id, HidePasswords = false, ReadOnly = false, Manage = true // Group 2 is Manage
}
}, users: new List<CollectionAccessSelection>()); // No explicit user permissions for this test
var collectionWithPermissions = await collectionRepository.GetByIdWithPermissionsAsync(collection.Id, user.Id, true);
Assert.NotNull(collectionWithPermissions);
Assert.Equal(2, collectionWithPermissions.Groups?.Count());
Assert.True(collectionWithPermissions.Assigned);
// Since Group2 is Manage the user should have Manage
Assert.True(collectionWithPermissions.Manage);
// Similarly, ReadOnly and HidePassword should be false
Assert.False(collectionWithPermissions.ReadOnly);
Assert.False(collectionWithPermissions.HidePasswords);
}
/// <summary>
/// Test to ensure the basic usage works as expected
/// </summary>
[DatabaseTheory, DatabaseData]
public async Task GetManyByOrganizationIdWithPermissionsAsync_Success(IUserRepository userRepository,
IOrganizationRepository organizationRepository,
ICollectionRepository collectionRepository,
IOrganizationUserRepository organizationUserRepository, IGroupRepository groupRepository)
{
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 group = await groupRepository.CreateAsync(new Group
{
Name = "Test Group",
OrganizationId = organization.Id,
});
var collection1 = new Collection { Name = "Collection 1", OrganizationId = organization.Id, };
await collectionRepository.CreateAsync(collection1, groups: new[]
{
new CollectionAccessSelection
{
Id = group.Id, HidePasswords = false, ReadOnly = true, Manage = false
}
}, users: new[]
{
new CollectionAccessSelection()
{
Id = orgUser.Id, HidePasswords = false, ReadOnly = false, Manage = true
}
});
var collection2 = new Collection { Name = "Collection 2", OrganizationId = organization.Id, };
await collectionRepository.CreateAsync(collection2, null, users: new[]
{
new CollectionAccessSelection()
{
Id = orgUser.Id, HidePasswords = false, ReadOnly = true, Manage = false
}
});
var collection3 = new Collection { Name = "Collection 3", OrganizationId = organization.Id, };
await collectionRepository.CreateAsync(collection3, groups: new[]
{
new CollectionAccessSelection()
{
Id = group.Id, HidePasswords = false, ReadOnly = false, Manage = true
}
}, null);
var collections = await collectionRepository.GetManyByOrganizationIdWithPermissionsAsync(organization.Id, user.Id, true);
Assert.NotNull(collections);
collections = collections.OrderBy(c => c.Name).ToList();
Assert.Collection(collections, c1 =>
{
Assert.NotNull(c1);
Assert.Equal(1, c1.Users?.Count());
Assert.Equal(1, c1.Groups?.Count());
Assert.True(c1.Assigned);
Assert.True(c1.Manage);
Assert.False(c1.ReadOnly);
Assert.False(c1.HidePasswords);
Assert.False(c1.Unmanaged);
}, c2 =>
{
Assert.NotNull(c2);
Assert.Equal(1, c2.Users?.Count());
Assert.Equal(0, c2.Groups?.Count());
Assert.True(c2.Assigned);
Assert.False(c2.Manage);
Assert.True(c2.ReadOnly);
Assert.False(c2.HidePasswords);
Assert.True(c2.Unmanaged);
}, c3 =>
{
Assert.NotNull(c3);
Assert.Equal(0, c3.Users?.Count());
Assert.Equal(1, c3.Groups?.Count());
Assert.False(c3.Assigned);
Assert.False(c3.Manage);
Assert.False(c3.ReadOnly);
Assert.False(c3.HidePasswords);
Assert.False(c3.Unmanaged);
});
}
/// <summary>
/// Test to ensure collections assigned to multiple groups do not duplicate in the results
/// </summary>
[DatabaseTheory, DatabaseData]
public async Task GetManyByOrganizationIdWithPermissionsAsync_GroupBy_Success(IUserRepository userRepository,
IOrganizationRepository organizationRepository,
ICollectionRepository collectionRepository,
IOrganizationUserRepository organizationUserRepository, IGroupRepository groupRepository)
{
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 group = await groupRepository.CreateAsync(new Group
{
Name = "Test Group",
OrganizationId = organization.Id,
});
var group2 = await groupRepository.CreateAsync(new Group
{
Name = "Test Group 2",
OrganizationId = organization.Id,
});
// Assign the test user to the test groups
await groupRepository.UpdateUsersAsync(group.Id, new[] { orgUser.Id });
await groupRepository.UpdateUsersAsync(group2.Id, new[] { orgUser.Id });
var collection1 = new Collection { Name = "Collection 1", OrganizationId = organization.Id, };
await collectionRepository.CreateAsync(collection1, groups: new[]
{
new CollectionAccessSelection
{
Id = group.Id, HidePasswords = false, ReadOnly = true, Manage = false
},
}, users: new[]
{
new CollectionAccessSelection()
{
Id = orgUser.Id, HidePasswords = false, ReadOnly = false, Manage = true
}
});
var collection2 = new Collection { Name = "Collection 2", OrganizationId = organization.Id, };
await collectionRepository.CreateAsync(collection2, null, users: new[]
{
new CollectionAccessSelection()
{
Id = orgUser.Id, HidePasswords = false, ReadOnly = true, Manage = false
}
});
var collection3 = new Collection { Name = "Collection 3", OrganizationId = organization.Id, };
await collectionRepository.CreateAsync(collection3, groups: new[]
{
new CollectionAccessSelection()
{
Id = group.Id, HidePasswords = false, ReadOnly = false, Manage = true
},
new CollectionAccessSelection()
{
Id = group2.Id, HidePasswords = false, ReadOnly = true, Manage = false
}
}, null);
var collections = await collectionRepository.GetManyByOrganizationIdWithPermissionsAsync(organization.Id, user.Id, true);
Assert.NotNull(collections);
Assert.Equal(3, collections.Count);
collections = collections.OrderBy(c => c.Name).ToList();
Assert.Collection(collections, c1 =>
{
Assert.NotNull(c1);
Assert.Equal(1, c1.Users?.Count());
Assert.Equal(1, c1.Groups?.Count());
Assert.True(c1.Assigned);
Assert.True(c1.Manage);
Assert.False(c1.ReadOnly);
Assert.False(c1.HidePasswords);
Assert.False(c1.Unmanaged);
}, c2 =>
{
Assert.NotNull(c2);
Assert.Equal(1, c2.Users?.Count());
Assert.Equal(0, c2.Groups?.Count());
Assert.True(c2.Assigned);
Assert.False(c2.Manage);
Assert.True(c2.ReadOnly);
Assert.False(c2.HidePasswords);
Assert.True(c2.Unmanaged);
}, c3 =>
{
Assert.NotNull(c3);
Assert.Equal(0, c3.Users?.Count());
Assert.Equal(2, c3.Groups?.Count());
Assert.True(c3.Assigned); // User is a member of both Groups
Assert.True(c3.Manage); // Group 2 is Manage
Assert.False(c3.ReadOnly);
Assert.False(c3.HidePasswords);
Assert.False(c3.Unmanaged);
});
}
}