mirror of
https://github.com/bitwarden/server.git
synced 2026-04-11 14:39:36 -05:00
* Fix UpdateCollectionCommand to set RevisionDate using TimeProvider and update corresponding tests. Adjust tests to verify correct RevisionDate assignment during collection updates. * Enhance BulkAddCollectionAccessCommand to include revision date in access updates. Update ICollectionRepository and its implementations to accept revision date parameter. Modify stored procedure to update collection revision dates accordingly. Add tests to verify correct behavior of access creation and revision date updates. * Update GroupRepository and stored procedures to bump RevisionDate for affected collections during group creation and updates. Enhance integration tests to verify that collection revision dates are correctly updated when groups are created or modified. * Implement revision date updates for affected collections in OrganizationUserRepository and related stored procedures. Add integration tests to ensure revision dates are correctly bumped during organization user creation and updates. * Update database migration script * Update migration script summary * Refactor OrganizationUserReplaceTests to create collection first * Refactor stored procedures to use Common Table Expressions (CTEs) for updating RevisionDate of affected collections. This change improves readability and maintainability by consolidating the logic for identifying affected collections in Group_UpdateWithCollections and OrganizationUser_UpdateWithCollections procedures. * Enhance OrganizationUser_CreateManyWithCollectionsAndGroups stored procedure to accept RevisionDate parameter for updating affected collections. Update OrganizationUserRepository to utilize the provided RevisionDate when available, ensuring accurate revision date management during organization user operations. * Refactor OrganizationUser_CreateManyWithCollectionsGroups and migration script to utilize temporary table for CollectionUser data insertion. This change improves performance and maintains consistency in updating RevisionDate for affected collections. * Refactor OrganizationUserRepository to consistently use RevisionDate from created OrganizationUsers when updating affected collections. This change enhances the accuracy of revision date management across the repository. * Refactor tests to ensure consistent handling of RevisionDate across Group and Collection repositories. Update assertions to compare RevisionDate directly, improving accuracy in revision date management during tests. * Restore BOM in Group_UpdateWithCollections and OrganizationUser_UpdateWithCollections * Refactor GroupRepository and OrganizationUserRepository to improve handling of RevisionDate. Updated collection filtering logic to use HashSet for efficiency and ensured that affected collections are filtered by OrganizationId, enhancing accuracy in revision date management. * Bump migration script date * Remove internal set from RevisionDate on Group and OrganizationUser The Dapper repositories use a System.Text.Json serialize/deserialize round-trip to build *WithCollections objects. System.Text.Json silently skips properties with non-public setters, so RevisionDate was reverting to DateTime.UtcNow instead of preserving the value set in C#. * Refactor OrganizationUser_CreateManyWithCollectionsGroups and migration script to improve the logic for updating RevisionDate. The update now uses INNER JOINs to ensure accurate filtering of collections based on OrganizationId and CollectionUser data, enhancing the precision of revision date management. * Fix sprocs styling * Added early return to OrganizationUserRepository.CreateManyAsync if the supplied parameter is empty
98 lines
4.6 KiB
C#
98 lines
4.6 KiB
C#
using Bit.Core.Enums;
|
|
using Bit.Core.Models.Data;
|
|
using Bit.Core.Repositories;
|
|
using Xunit;
|
|
|
|
namespace Bit.Infrastructure.IntegrationTest.AdminConsole.Repositories.OrganizationUserRepository;
|
|
|
|
public class OrganizationUserReplaceTests
|
|
{
|
|
/// <summary>
|
|
/// Specifically tests OrganizationUsers in the invited state, which is unique because
|
|
/// they're not linked to a UserId.
|
|
/// </summary>
|
|
[DatabaseTheory, DatabaseData]
|
|
public async Task ReplaceAsync_WithCollectionAccess_WhenUserIsInvited_Success(
|
|
IOrganizationRepository organizationRepository,
|
|
IOrganizationUserRepository organizationUserRepository,
|
|
ICollectionRepository collectionRepository)
|
|
{
|
|
var organization = await organizationRepository.CreateTestOrganizationAsync();
|
|
var collection = await collectionRepository.CreateTestCollectionAsync(organization);
|
|
|
|
var orgUser = await organizationUserRepository.CreateTestOrganizationUserInviteAsync(organization);
|
|
|
|
// Act: update the user, including collection access so we test this overloaded method
|
|
orgUser.Type = OrganizationUserType.Admin;
|
|
orgUser.AccessSecretsManager = true;
|
|
orgUser.RevisionDate = DateTime.UtcNow.AddMinutes(10);
|
|
|
|
await organizationUserRepository.ReplaceAsync(orgUser, [
|
|
new CollectionAccessSelection { Id = collection.Id, Manage = true }
|
|
]);
|
|
|
|
// Assert
|
|
var (actualOrgUser, actualCollections) = await organizationUserRepository.GetByIdWithCollectionsAsync(orgUser.Id);
|
|
Assert.NotNull(actualOrgUser);
|
|
Assert.Equal(OrganizationUserType.Admin, actualOrgUser.Type);
|
|
Assert.True(actualOrgUser.AccessSecretsManager);
|
|
|
|
var collectionAccess = Assert.Single(actualCollections);
|
|
Assert.Equal(collection.Id, collectionAccess.Id);
|
|
Assert.True(collectionAccess.Manage);
|
|
|
|
// Collection revision date should match the orgUser's RevisionDate
|
|
var (actualCollection, _) = await collectionRepository.GetByIdWithAccessAsync(collection.Id);
|
|
Assert.NotNull(actualCollection);
|
|
Assert.Equal(orgUser.RevisionDate, actualCollection.RevisionDate, TimeSpan.FromMilliseconds(10));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests OrganizationUsers in the Confirmed status, which is a stand-in for all other
|
|
/// non-Invited statuses (which are all linked to a UserId).
|
|
/// </summary>
|
|
[DatabaseTheory, DatabaseData]
|
|
public async Task ReplaceAsync_WithCollectionAccess_WhenUserIsConfirmed_Success(
|
|
IUserRepository userRepository,
|
|
IOrganizationRepository organizationRepository,
|
|
IOrganizationUserRepository organizationUserRepository,
|
|
ICollectionRepository collectionRepository)
|
|
{
|
|
var organization = await organizationRepository.CreateTestOrganizationAsync();
|
|
var collection = await collectionRepository.CreateTestCollectionAsync(organization);
|
|
|
|
var user = await userRepository.CreateTestUserAsync();
|
|
// OrganizationUser is linked with the User in the Confirmed status
|
|
var orgUser = await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user);
|
|
|
|
// Act: update the user, including collection access so we test this overloaded method
|
|
orgUser.Type = OrganizationUserType.Admin;
|
|
orgUser.AccessSecretsManager = true;
|
|
orgUser.RevisionDate = DateTime.UtcNow.AddMinutes(10);
|
|
|
|
await organizationUserRepository.ReplaceAsync(orgUser, [
|
|
new CollectionAccessSelection { Id = collection.Id, Manage = true }
|
|
]);
|
|
|
|
// Assert
|
|
var (actualOrgUser, actualCollections) = await organizationUserRepository.GetByIdWithCollectionsAsync(orgUser.Id);
|
|
Assert.NotNull(actualOrgUser);
|
|
Assert.Equal(OrganizationUserType.Admin, actualOrgUser.Type);
|
|
Assert.True(actualOrgUser.AccessSecretsManager);
|
|
|
|
var collectionAccess = Assert.Single(actualCollections);
|
|
Assert.Equal(collection.Id, collectionAccess.Id);
|
|
Assert.True(collectionAccess.Manage);
|
|
|
|
// Account revision date should be updated to a later date
|
|
var actualUser = await userRepository.GetByIdAsync(user.Id);
|
|
Assert.NotNull(actualUser);
|
|
Assert.True(actualUser.AccountRevisionDate.CompareTo(user.AccountRevisionDate) > 0);
|
|
|
|
// Collection revision date should match the orgUser's RevisionDate
|
|
var (actualCollection, _) = await collectionRepository.GetByIdWithAccessAsync(collection.Id);
|
|
Assert.NotNull(actualCollection);
|
|
Assert.Equal(orgUser.RevisionDate, actualCollection.RevisionDate, TimeSpan.FromMilliseconds(10));
|
|
}
|
|
}
|