1
0
mirror of https://github.com/bitwarden/server.git synced 2025-05-20 11:04:31 -05:00

[AC-2184] Force sync after opting in to Flexible Collections (#3766)

This commit is contained in:
Thomas Rittson 2024-02-09 10:27:47 +10:00 committed by GitHub
parent 636f716d62
commit b6255a64fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 33 additions and 2 deletions

View File

@ -57,6 +57,7 @@ public class OrganizationsController : Controller
private readonly IUpdateSecretsManagerSubscriptionCommand _updateSecretsManagerSubscriptionCommand; private readonly IUpdateSecretsManagerSubscriptionCommand _updateSecretsManagerSubscriptionCommand;
private readonly IUpgradeOrganizationPlanCommand _upgradeOrganizationPlanCommand; private readonly IUpgradeOrganizationPlanCommand _upgradeOrganizationPlanCommand;
private readonly IAddSecretsManagerSubscriptionCommand _addSecretsManagerSubscriptionCommand; private readonly IAddSecretsManagerSubscriptionCommand _addSecretsManagerSubscriptionCommand;
private readonly IPushNotificationService _pushNotificationService;
public OrganizationsController( public OrganizationsController(
IOrganizationRepository organizationRepository, IOrganizationRepository organizationRepository,
@ -78,7 +79,8 @@ public class OrganizationsController : Controller
ILicensingService licensingService, ILicensingService licensingService,
IUpdateSecretsManagerSubscriptionCommand updateSecretsManagerSubscriptionCommand, IUpdateSecretsManagerSubscriptionCommand updateSecretsManagerSubscriptionCommand,
IUpgradeOrganizationPlanCommand upgradeOrganizationPlanCommand, IUpgradeOrganizationPlanCommand upgradeOrganizationPlanCommand,
IAddSecretsManagerSubscriptionCommand addSecretsManagerSubscriptionCommand) IAddSecretsManagerSubscriptionCommand addSecretsManagerSubscriptionCommand,
IPushNotificationService pushNotificationService)
{ {
_organizationRepository = organizationRepository; _organizationRepository = organizationRepository;
_organizationUserRepository = organizationUserRepository; _organizationUserRepository = organizationUserRepository;
@ -100,6 +102,7 @@ public class OrganizationsController : Controller
_updateSecretsManagerSubscriptionCommand = updateSecretsManagerSubscriptionCommand; _updateSecretsManagerSubscriptionCommand = updateSecretsManagerSubscriptionCommand;
_upgradeOrganizationPlanCommand = upgradeOrganizationPlanCommand; _upgradeOrganizationPlanCommand = upgradeOrganizationPlanCommand;
_addSecretsManagerSubscriptionCommand = addSecretsManagerSubscriptionCommand; _addSecretsManagerSubscriptionCommand = addSecretsManagerSubscriptionCommand;
_pushNotificationService = pushNotificationService;
} }
[HttpGet("{id}")] [HttpGet("{id}")]
@ -846,6 +849,14 @@ public class OrganizationsController : Controller
organization.FlexibleCollections = true; organization.FlexibleCollections = true;
await _organizationService.ReplaceAndUpdateCacheAsync(organization); await _organizationService.ReplaceAndUpdateCacheAsync(organization);
// Force a vault sync for all owners and admins of the organization so that changes show immediately
// Custom users are intentionally not handled as they are likely to be less impacted and we want to limit simultaneous syncs
var orgUsers = await _organizationUserRepository.GetManyByOrganizationAsync(id, null);
await Task.WhenAll(orgUsers
.Where(ou => ou.UserId.HasValue &&
ou.Type is OrganizationUserType.Admin or OrganizationUserType.Owner)
.Select(ou => _pushNotificationService.PushSyncVaultAsync(ou.UserId.Value)));
} }
private async Task TryGrantOwnerAccessToSecretsManagerAsync(Guid organizationId, Guid userId) private async Task TryGrantOwnerAccessToSecretsManagerAsync(Guid organizationId, Guid userId)

View File

@ -50,6 +50,7 @@ public class OrganizationsControllerTests : IDisposable
private readonly IUpdateSecretsManagerSubscriptionCommand _updateSecretsManagerSubscriptionCommand; private readonly IUpdateSecretsManagerSubscriptionCommand _updateSecretsManagerSubscriptionCommand;
private readonly IUpgradeOrganizationPlanCommand _upgradeOrganizationPlanCommand; private readonly IUpgradeOrganizationPlanCommand _upgradeOrganizationPlanCommand;
private readonly IAddSecretsManagerSubscriptionCommand _addSecretsManagerSubscriptionCommand; private readonly IAddSecretsManagerSubscriptionCommand _addSecretsManagerSubscriptionCommand;
private readonly IPushNotificationService _pushNotificationService;
private readonly OrganizationsController _sut; private readonly OrganizationsController _sut;
@ -75,6 +76,7 @@ public class OrganizationsControllerTests : IDisposable
_updateSecretsManagerSubscriptionCommand = Substitute.For<IUpdateSecretsManagerSubscriptionCommand>(); _updateSecretsManagerSubscriptionCommand = Substitute.For<IUpdateSecretsManagerSubscriptionCommand>();
_upgradeOrganizationPlanCommand = Substitute.For<IUpgradeOrganizationPlanCommand>(); _upgradeOrganizationPlanCommand = Substitute.For<IUpgradeOrganizationPlanCommand>();
_addSecretsManagerSubscriptionCommand = Substitute.For<IAddSecretsManagerSubscriptionCommand>(); _addSecretsManagerSubscriptionCommand = Substitute.For<IAddSecretsManagerSubscriptionCommand>();
_pushNotificationService = Substitute.For<IPushNotificationService>();
_sut = new OrganizationsController( _sut = new OrganizationsController(
_organizationRepository, _organizationRepository,
@ -96,7 +98,8 @@ public class OrganizationsControllerTests : IDisposable
_licensingService, _licensingService,
_updateSecretsManagerSubscriptionCommand, _updateSecretsManagerSubscriptionCommand,
_upgradeOrganizationPlanCommand, _upgradeOrganizationPlanCommand,
_addSecretsManagerSubscriptionCommand); _addSecretsManagerSubscriptionCommand,
_pushNotificationService);
} }
public void Dispose() public void Dispose()
@ -358,8 +361,20 @@ public class OrganizationsControllerTests : IDisposable
public async Task EnableCollectionEnhancements_Success(Organization organization) public async Task EnableCollectionEnhancements_Success(Organization organization)
{ {
organization.FlexibleCollections = false; organization.FlexibleCollections = false;
var admin = new OrganizationUser { UserId = Guid.NewGuid(), Type = OrganizationUserType.Admin };
var owner = new OrganizationUser { UserId = Guid.NewGuid(), Type = OrganizationUserType.Owner };
var user = new OrganizationUser { UserId = Guid.NewGuid(), Type = OrganizationUserType.User };
var invited = new OrganizationUser
{
UserId = null,
Type = OrganizationUserType.Admin,
Email = "invited@example.com"
};
var orgUsers = new List<OrganizationUser> { admin, owner, user, invited };
_currentContext.OrganizationOwner(organization.Id).Returns(true); _currentContext.OrganizationOwner(organization.Id).Returns(true);
_organizationRepository.GetByIdAsync(organization.Id).Returns(organization); _organizationRepository.GetByIdAsync(organization.Id).Returns(organization);
_organizationUserRepository.GetManyByOrganizationAsync(organization.Id, null).Returns(orgUsers);
await _sut.EnableCollectionEnhancements(organization.Id); await _sut.EnableCollectionEnhancements(organization.Id);
@ -368,6 +383,9 @@ public class OrganizationsControllerTests : IDisposable
Arg.Is<Organization>(o => Arg.Is<Organization>(o =>
o.Id == organization.Id && o.Id == organization.Id &&
o.FlexibleCollections)); o.FlexibleCollections));
await _pushNotificationService.Received(1).PushSyncVaultAsync(admin.UserId.Value);
await _pushNotificationService.Received(1).PushSyncVaultAsync(owner.UserId.Value);
await _pushNotificationService.DidNotReceive().PushSyncVaultAsync(user.UserId.Value);
} }
[Theory, AutoData] [Theory, AutoData]
@ -381,6 +399,7 @@ public class OrganizationsControllerTests : IDisposable
await _organizationRepository.DidNotReceiveWithAnyArgs().EnableCollectionEnhancements(Arg.Any<Guid>()); await _organizationRepository.DidNotReceiveWithAnyArgs().EnableCollectionEnhancements(Arg.Any<Guid>());
await _organizationService.DidNotReceiveWithAnyArgs().ReplaceAndUpdateCacheAsync(Arg.Any<Organization>()); await _organizationService.DidNotReceiveWithAnyArgs().ReplaceAndUpdateCacheAsync(Arg.Any<Organization>());
await _pushNotificationService.DidNotReceiveWithAnyArgs().PushSyncVaultAsync(Arg.Any<Guid>());
} }
[Theory, AutoData] [Theory, AutoData]
@ -395,5 +414,6 @@ public class OrganizationsControllerTests : IDisposable
await _organizationRepository.DidNotReceiveWithAnyArgs().EnableCollectionEnhancements(Arg.Any<Guid>()); await _organizationRepository.DidNotReceiveWithAnyArgs().EnableCollectionEnhancements(Arg.Any<Guid>());
await _organizationService.DidNotReceiveWithAnyArgs().ReplaceAndUpdateCacheAsync(Arg.Any<Organization>()); await _organizationService.DidNotReceiveWithAnyArgs().ReplaceAndUpdateCacheAsync(Arg.Any<Organization>());
await _pushNotificationService.DidNotReceiveWithAnyArgs().PushSyncVaultAsync(Arg.Any<Guid>());
} }
} }