From ac52048fdee02c3a7c86b5479cdc9723f08406d6 Mon Sep 17 00:00:00 2001 From: Rui Tome Date: Wed, 22 Oct 2025 16:52:53 +0100 Subject: [PATCH 1/7] Add PolicyValidatorsRefactor constant to FeatureFlagKeys in Constants.cs --- src/Core/Constants.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Core/Constants.cs b/src/Core/Constants.cs index da7b94aada5d..5a4935b42492 100644 --- a/src/Core/Constants.cs +++ b/src/Core/Constants.cs @@ -142,6 +142,7 @@ public static class FeatureFlagKeys public const string CreateDefaultLocation = "pm-19467-create-default-location"; public const string AutomaticConfirmUsers = "pm-19934-auto-confirm-organization-users"; public const string PM23845_VNextApplicationCache = "pm-24957-refactor-memory-application-cache"; + public const string PolicyValidatorsRefactor = "pm-26423-refactor-policy-side-effects"; /* Auth Team */ public const string TwoFactorExtensionDataPersistence = "pm-9115-two-factor-extension-data-persistence"; From 2c5490b232a73c6179da930e99fa9603897bcdd9 Mon Sep 17 00:00:00 2001 From: Rui Tome Date: Wed, 22 Oct 2025 16:54:47 +0100 Subject: [PATCH 2/7] Add Metadata property and ToSavePolicyModel method to PolicyUpdateRequestModel --- .../Request/PolicyUpdateRequestModel.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Api/AdminConsole/Public/Models/Request/PolicyUpdateRequestModel.cs b/src/Api/AdminConsole/Public/Models/Request/PolicyUpdateRequestModel.cs index 34675a6046c1..a75f1532a82c 100644 --- a/src/Api/AdminConsole/Public/Models/Request/PolicyUpdateRequestModel.cs +++ b/src/Api/AdminConsole/Public/Models/Request/PolicyUpdateRequestModel.cs @@ -8,6 +8,8 @@ namespace Bit.Api.AdminConsole.Public.Models.Request; public class PolicyUpdateRequestModel : PolicyBaseModel { + public Dictionary Metadata { get; set; } = new(); + public PolicyUpdate ToPolicyUpdate(Guid organizationId, PolicyType type) { var serializedData = PolicyDataValidator.ValidateAndSerialize(Data, type); @@ -21,4 +23,22 @@ public PolicyUpdate ToPolicyUpdate(Guid organizationId, PolicyType type) PerformedBy = new SystemUser(EventSystemUser.PublicApi) }; } + + public SavePolicyModel ToSavePolicyModel(Guid organizationId, PolicyType type) + { + var serializedData = PolicyDataValidator.ValidateAndSerialize(Data, type); + + var policyUpdate = new PolicyUpdate + { + Type = type, + OrganizationId = organizationId, + Data = serializedData, + Enabled = Enabled.GetValueOrDefault() + }; + + var performedBy = new SystemUser(EventSystemUser.PublicApi); + var metadata = PolicyDataValidator.ValidateAndDeserializeMetadata(Metadata, type); + + return new SavePolicyModel(policyUpdate, performedBy, metadata); + } } From dd28442663fb2e5972c56c17a11260dcc94737a0 Mon Sep 17 00:00:00 2001 From: Rui Tome Date: Wed, 22 Oct 2025 17:04:44 +0100 Subject: [PATCH 3/7] Refactor PoliciesController to utilize IVNextSavePolicyCommand based on feature flag - Added IFeatureService and IVNextSavePolicyCommand dependencies to PoliciesController. - Updated PutVNext method to conditionally use VNextSavePolicyCommand or SavePolicyCommand based on the PolicyValidatorsRefactor feature flag. - Enhanced unit tests to verify behavior for both enabled and disabled states of the feature flag. --- .../Controllers/PoliciesController.cs | 14 ++- .../Controllers/PoliciesControllerTests.cs | 99 +++++++++++++++++++ 2 files changed, 110 insertions(+), 3 deletions(-) diff --git a/src/Api/AdminConsole/Controllers/PoliciesController.cs b/src/Api/AdminConsole/Controllers/PoliciesController.cs index ce9232183379..1ee6dedf89a2 100644 --- a/src/Api/AdminConsole/Controllers/PoliciesController.cs +++ b/src/Api/AdminConsole/Controllers/PoliciesController.cs @@ -12,6 +12,7 @@ using Bit.Core.AdminConsole.Enums; using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfaces; using Bit.Core.AdminConsole.OrganizationFeatures.Policies; +using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyUpdateEvents.Interfaces; using Bit.Core.AdminConsole.Repositories; using Bit.Core.Auth.Models.Business.Tokenables; using Bit.Core.Context; @@ -41,8 +42,9 @@ public class PoliciesController : Controller private readonly IDataProtectorTokenFactory _orgUserInviteTokenDataFactory; private readonly IPolicyRepository _policyRepository; private readonly IUserService _userService; - + private readonly IFeatureService _featureService; private readonly ISavePolicyCommand _savePolicyCommand; + private readonly IVNextSavePolicyCommand _vNextSavePolicyCommand; public PoliciesController(IPolicyRepository policyRepository, IOrganizationUserRepository organizationUserRepository, @@ -53,7 +55,9 @@ public PoliciesController(IPolicyRepository policyRepository, IDataProtectorTokenFactory orgUserInviteTokenDataFactory, IOrganizationHasVerifiedDomainsQuery organizationHasVerifiedDomainsQuery, IOrganizationRepository organizationRepository, - ISavePolicyCommand savePolicyCommand) + IFeatureService featureService, + ISavePolicyCommand savePolicyCommand, + IVNextSavePolicyCommand vNextSavePolicyCommand) { _policyRepository = policyRepository; _organizationUserRepository = organizationUserRepository; @@ -65,7 +69,9 @@ public PoliciesController(IPolicyRepository policyRepository, _organizationRepository = organizationRepository; _orgUserInviteTokenDataFactory = orgUserInviteTokenDataFactory; _organizationHasVerifiedDomainsQuery = organizationHasVerifiedDomainsQuery; + _featureService = featureService; _savePolicyCommand = savePolicyCommand; + _vNextSavePolicyCommand = vNextSavePolicyCommand; } [HttpGet("{type}")] @@ -221,7 +227,9 @@ public async Task PutVNext(Guid orgId, [FromBody] SavePolic { var savePolicyRequest = await model.ToSavePolicyModelAsync(orgId, _currentContext); - var policy = await _savePolicyCommand.VNextSaveAsync(savePolicyRequest); + var policy = _featureService.IsEnabled(FeatureFlagKeys.PolicyValidatorsRefactor) ? + await _vNextSavePolicyCommand.SaveAsync(savePolicyRequest) : + await _savePolicyCommand.VNextSaveAsync(savePolicyRequest); return new PolicyResponseModel(policy); } diff --git a/test/Api.Test/Controllers/PoliciesControllerTests.cs b/test/Api.Test/Controllers/PoliciesControllerTests.cs index f5f3eddd3b9b..73cdd0fe2924 100644 --- a/test/Api.Test/Controllers/PoliciesControllerTests.cs +++ b/test/Api.Test/Controllers/PoliciesControllerTests.cs @@ -1,10 +1,15 @@ using System.Security.Claims; using System.Text.Json; using Bit.Api.AdminConsole.Controllers; +using Bit.Api.AdminConsole.Models.Request; using Bit.Api.AdminConsole.Models.Response.Organizations; +using Bit.Core; using Bit.Core.AdminConsole.Entities; using Bit.Core.AdminConsole.Enums; using Bit.Core.AdminConsole.Models.Data.Organizations.Policies; +using Bit.Core.AdminConsole.OrganizationFeatures.Policies; +using Bit.Core.AdminConsole.OrganizationFeatures.Policies.Models; +using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyUpdateEvents.Interfaces; using Bit.Core.AdminConsole.Repositories; using Bit.Core.Auth.Models.Business.Tokenables; using Bit.Core.Context; @@ -455,4 +460,98 @@ Organization organization Assert.Equal(enabledPolicy.Type, expectedPolicy.Type); Assert.Equal(enabledPolicy.Enabled, expectedPolicy.Enabled); } + + [Theory] + [BitAutoData] + public async Task PutVNext_WhenPolicyValidatorsRefactorEnabled_UsesVNextSavePolicyCommand( + SutProvider sutProvider, Guid orgId, + SavePolicyRequest model, Policy policy, Guid userId) + { + // Arrange + policy.Data = null; + + sutProvider.GetDependency() + .UserId + .Returns(userId); + + sutProvider.GetDependency() + .OrganizationOwner(orgId) + .Returns(true); + + sutProvider.GetDependency() + .IsEnabled(FeatureFlagKeys.PolicyValidatorsRefactor) + .Returns(true); + + sutProvider.GetDependency() + .SaveAsync(Arg.Any()) + .Returns(policy); + + // Act + var result = await sutProvider.Sut.PutVNext(orgId, model); + + // Assert + await sutProvider.GetDependency() + .Received(1) + .SaveAsync(Arg.Is( + m => m.PolicyUpdate.OrganizationId == orgId && + m.PolicyUpdate.Type == model.Policy.Type && + m.PolicyUpdate.Enabled == model.Policy.Enabled && + m.PerformedBy.UserId == userId && + m.PerformedBy.IsOrganizationOwnerOrProvider == true)); + + await sutProvider.GetDependency() + .DidNotReceiveWithAnyArgs() + .VNextSaveAsync(default); + + Assert.NotNull(result); + Assert.Equal(policy.Id, result.Id); + Assert.Equal(policy.Type, result.Type); + } + + [Theory] + [BitAutoData] + public async Task PutVNext_WhenPolicyValidatorsRefactorDisabled_UsesSavePolicyCommand( + SutProvider sutProvider, Guid orgId, + SavePolicyRequest model, Policy policy, Guid userId) + { + // Arrange + policy.Data = null; + + sutProvider.GetDependency() + .UserId + .Returns(userId); + + sutProvider.GetDependency() + .OrganizationOwner(orgId) + .Returns(true); + + sutProvider.GetDependency() + .IsEnabled(FeatureFlagKeys.PolicyValidatorsRefactor) + .Returns(false); + + sutProvider.GetDependency() + .VNextSaveAsync(Arg.Any()) + .Returns(policy); + + // Act + var result = await sutProvider.Sut.PutVNext(orgId, model); + + // Assert + await sutProvider.GetDependency() + .Received(1) + .VNextSaveAsync(Arg.Is( + m => m.PolicyUpdate.OrganizationId == orgId && + m.PolicyUpdate.Type == model.Policy.Type && + m.PolicyUpdate.Enabled == model.Policy.Enabled && + m.PerformedBy.UserId == userId && + m.PerformedBy.IsOrganizationOwnerOrProvider == true)); + + await sutProvider.GetDependency() + .DidNotReceiveWithAnyArgs() + .SaveAsync(default); + + Assert.NotNull(result); + Assert.Equal(policy.Id, result.Id); + Assert.Equal(policy.Type, result.Type); + } } From 172ca7e4098d5ba31a3e83c1e12449161ad45fed Mon Sep 17 00:00:00 2001 From: Rui Tome Date: Wed, 22 Oct 2025 17:07:09 +0100 Subject: [PATCH 4/7] Update public PoliciesController to to utilize IVNextSavePolicyCommand based on feature flag - Introduced IFeatureService and IVNextSavePolicyCommand to manage policy saving based on the PolicyValidatorsRefactor feature flag. - Updated the Put method to conditionally use the new VNextSavePolicyCommand or the legacy SavePolicyCommand. - Added unit tests to validate the behavior of the Put method for both enabled and disabled states of the feature flag. --- .../Public/Controllers/PoliciesController.cs | 25 +++++- .../Controllers/PoliciesControllerTests.cs | 87 +++++++++++++++++++ 2 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 test/Api.Test/AdminConsole/Public/Controllers/PoliciesControllerTests.cs diff --git a/src/Api/AdminConsole/Public/Controllers/PoliciesController.cs b/src/Api/AdminConsole/Public/Controllers/PoliciesController.cs index 1caf9cb06823..be0997f271dc 100644 --- a/src/Api/AdminConsole/Public/Controllers/PoliciesController.cs +++ b/src/Api/AdminConsole/Public/Controllers/PoliciesController.cs @@ -5,11 +5,15 @@ using Bit.Api.AdminConsole.Public.Models.Request; using Bit.Api.AdminConsole.Public.Models.Response; using Bit.Api.Models.Public.Response; +using Bit.Core; +using Bit.Core.AdminConsole.Entities; using Bit.Core.AdminConsole.Enums; using Bit.Core.AdminConsole.OrganizationFeatures.Policies; +using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyUpdateEvents.Interfaces; using Bit.Core.AdminConsole.Repositories; using Bit.Core.AdminConsole.Services; using Bit.Core.Context; +using Bit.Core.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -22,18 +26,24 @@ public class PoliciesController : Controller private readonly IPolicyRepository _policyRepository; private readonly IPolicyService _policyService; private readonly ICurrentContext _currentContext; + private readonly IFeatureService _featureService; private readonly ISavePolicyCommand _savePolicyCommand; + private readonly IVNextSavePolicyCommand _vNextSavePolicyCommand; public PoliciesController( IPolicyRepository policyRepository, IPolicyService policyService, ICurrentContext currentContext, - ISavePolicyCommand savePolicyCommand) + IFeatureService featureService, + ISavePolicyCommand savePolicyCommand, + IVNextSavePolicyCommand vNextSavePolicyCommand) { _policyRepository = policyRepository; _policyService = policyService; _currentContext = currentContext; + _featureService = featureService; _savePolicyCommand = savePolicyCommand; + _vNextSavePolicyCommand = vNextSavePolicyCommand; } /// @@ -87,8 +97,17 @@ public async Task List() [ProducesResponseType((int)HttpStatusCode.NotFound)] public async Task Put(PolicyType type, [FromBody] PolicyUpdateRequestModel model) { - var policyUpdate = model.ToPolicyUpdate(_currentContext.OrganizationId!.Value, type); - var policy = await _savePolicyCommand.SaveAsync(policyUpdate); + Policy policy; + if (_featureService.IsEnabled(FeatureFlagKeys.PolicyValidatorsRefactor)) + { + var savePolicyModel = model.ToSavePolicyModel(_currentContext.OrganizationId!.Value, type); + policy = await _vNextSavePolicyCommand.SaveAsync(savePolicyModel); + } + else + { + var policyUpdate = model.ToPolicyUpdate(_currentContext.OrganizationId!.Value, type); + policy = await _savePolicyCommand.SaveAsync(policyUpdate); + } var response = new PolicyResponseModel(policy); return new JsonResult(response); diff --git a/test/Api.Test/AdminConsole/Public/Controllers/PoliciesControllerTests.cs b/test/Api.Test/AdminConsole/Public/Controllers/PoliciesControllerTests.cs new file mode 100644 index 000000000000..c2360f5f9ad4 --- /dev/null +++ b/test/Api.Test/AdminConsole/Public/Controllers/PoliciesControllerTests.cs @@ -0,0 +1,87 @@ +using Bit.Api.AdminConsole.Public.Controllers; +using Bit.Api.AdminConsole.Public.Models.Request; +using Bit.Core; +using Bit.Core.AdminConsole.Entities; +using Bit.Core.AdminConsole.Enums; +using Bit.Core.AdminConsole.Models.Data; +using Bit.Core.AdminConsole.OrganizationFeatures.Policies; +using Bit.Core.AdminConsole.OrganizationFeatures.Policies.Models; +using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyUpdateEvents.Interfaces; +using Bit.Core.Context; +using Bit.Core.Services; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using NSubstitute; +using Xunit; + +namespace Bit.Api.Test.AdminConsole.Public.Controllers; + +[ControllerCustomize(typeof(PoliciesController))] +[SutProviderCustomize] +public class PoliciesControllerTests +{ + [Theory] + [BitAutoData] + public async Task Put_WhenPolicyValidatorsRefactorEnabled_UsesVNextSavePolicyCommand( + Guid organizationId, + PolicyType policyType, + PolicyUpdateRequestModel model, + Policy policy, + SutProvider sutProvider) + { + // Arrange + policy.Data = null; + sutProvider.GetDependency() + .OrganizationId.Returns(organizationId); + sutProvider.GetDependency() + .IsEnabled(FeatureFlagKeys.PolicyValidatorsRefactor) + .Returns(true); + sutProvider.GetDependency() + .SaveAsync(Arg.Any()) + .Returns(policy); + + // Act + await sutProvider.Sut.Put(policyType, model); + + // Assert + await sutProvider.GetDependency() + .Received(1) + .SaveAsync(Arg.Is(m => + m.PolicyUpdate.OrganizationId == organizationId && + m.PolicyUpdate.Type == policyType && + m.PolicyUpdate.Enabled == model.Enabled.GetValueOrDefault() && + m.PerformedBy is SystemUser)); + } + + [Theory] + [BitAutoData] + public async Task Put_WhenPolicyValidatorsRefactorDisabled_UsesLegacySavePolicyCommand( + Guid organizationId, + PolicyType policyType, + PolicyUpdateRequestModel model, + Policy policy, + SutProvider sutProvider) + { + // Arrange + policy.Data = null; + sutProvider.GetDependency() + .OrganizationId.Returns(organizationId); + sutProvider.GetDependency() + .IsEnabled(FeatureFlagKeys.PolicyValidatorsRefactor) + .Returns(false); + sutProvider.GetDependency() + .SaveAsync(Arg.Any()) + .Returns(policy); + + // Act + await sutProvider.Sut.Put(policyType, model); + + // Assert + await sutProvider.GetDependency() + .Received(1) + .SaveAsync(Arg.Is(p => + p.OrganizationId == organizationId && + p.Type == policyType && + p.Enabled == model.Enabled)); + } +} From d10e525b5114e40caad1d4837a94c4a07ed1543a Mon Sep 17 00:00:00 2001 From: Rui Tome Date: Wed, 22 Oct 2025 17:08:25 +0100 Subject: [PATCH 5/7] Refactor VerifyOrganizationDomainCommand to utilize IVNextSavePolicyCommand based on feature flag - Added IFeatureService and IVNextSavePolicyCommand dependencies to VerifyOrganizationDomainCommand. - Updated EnableSingleOrganizationPolicyAsync method to conditionally use VNextSavePolicyCommand or SavePolicyCommand based on the PolicyValidatorsRefactor feature flag. - Enhanced unit tests to validate the behavior when the feature flag is enabled. --- .../VerifyOrganizationDomainCommand.cs | 32 +++++++++++++------ .../VerifyOrganizationDomainCommandTests.cs | 32 +++++++++++++++++++ 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/Core/AdminConsole/OrganizationFeatures/OrganizationDomains/VerifyOrganizationDomainCommand.cs b/src/Core/AdminConsole/OrganizationFeatures/OrganizationDomains/VerifyOrganizationDomainCommand.cs index c03341bbc076..c68546c36389 100644 --- a/src/Core/AdminConsole/OrganizationFeatures/OrganizationDomains/VerifyOrganizationDomainCommand.cs +++ b/src/Core/AdminConsole/OrganizationFeatures/OrganizationDomains/VerifyOrganizationDomainCommand.cs @@ -6,6 +6,7 @@ using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfaces; using Bit.Core.AdminConsole.OrganizationFeatures.Policies; using Bit.Core.AdminConsole.OrganizationFeatures.Policies.Models; +using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyUpdateEvents.Interfaces; using Bit.Core.Context; using Bit.Core.Entities; using Bit.Core.Enums; @@ -24,7 +25,9 @@ public class VerifyOrganizationDomainCommand( IEventService eventService, IGlobalSettings globalSettings, ICurrentContext currentContext, + IFeatureService featureService, ISavePolicyCommand savePolicyCommand, + IVNextSavePolicyCommand vNextSavePolicyCommand, IMailService mailService, IOrganizationUserRepository organizationUserRepository, IOrganizationRepository organizationRepository, @@ -131,15 +134,26 @@ private async Task DomainVerificationSideEffectsAsync(OrganizationDomain domain, await SendVerifiedDomainUserEmailAsync(domain); } - private async Task EnableSingleOrganizationPolicyAsync(Guid organizationId, IActingUser actingUser) => - await savePolicyCommand.SaveAsync( - new PolicyUpdate - { - OrganizationId = organizationId, - Type = PolicyType.SingleOrg, - Enabled = true, - PerformedBy = actingUser - }); + private async Task EnableSingleOrganizationPolicyAsync(Guid organizationId, IActingUser actingUser) + { + var policyUpdate = new PolicyUpdate + { + OrganizationId = organizationId, + Type = PolicyType.SingleOrg, + Enabled = true, + PerformedBy = actingUser + }; + + if (featureService.IsEnabled(FeatureFlagKeys.PolicyValidatorsRefactor)) + { + var savePolicyModel = new SavePolicyModel(policyUpdate, actingUser, new EmptyMetadataModel()); + await vNextSavePolicyCommand.SaveAsync(savePolicyModel); + } + else + { + await savePolicyCommand.SaveAsync(policyUpdate); + } + } private async Task SendVerifiedDomainUserEmailAsync(OrganizationDomain domain) { diff --git a/test/Core.Test/AdminConsole/OrganizationFeatures/OrganizationDomains/VerifyOrganizationDomainCommandTests.cs b/test/Core.Test/AdminConsole/OrganizationFeatures/OrganizationDomains/VerifyOrganizationDomainCommandTests.cs index b0774927e3e4..3f0443d31b3f 100644 --- a/test/Core.Test/AdminConsole/OrganizationFeatures/OrganizationDomains/VerifyOrganizationDomainCommandTests.cs +++ b/test/Core.Test/AdminConsole/OrganizationFeatures/OrganizationDomains/VerifyOrganizationDomainCommandTests.cs @@ -4,6 +4,7 @@ using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains; using Bit.Core.AdminConsole.OrganizationFeatures.Policies; using Bit.Core.AdminConsole.OrganizationFeatures.Policies.Models; +using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyUpdateEvents.Interfaces; using Bit.Core.Context; using Bit.Core.Entities; using Bit.Core.Enums; @@ -191,6 +192,37 @@ x.PerformedBy is StandardUser && x.PerformedBy.UserId == userId)); } + [Theory, BitAutoData] + public async Task UserVerifyOrganizationDomainAsync_WhenPolicyValidatorsRefactorFlagEnabled_UsesVNextSavePolicyCommand( + OrganizationDomain domain, Guid userId, SutProvider sutProvider) + { + sutProvider.GetDependency() + .GetClaimedDomainsByDomainNameAsync(domain.DomainName) + .Returns([]); + + sutProvider.GetDependency() + .ResolveAsync(domain.DomainName, domain.Txt) + .Returns(true); + + sutProvider.GetDependency() + .UserId.Returns(userId); + + sutProvider.GetDependency() + .IsEnabled(FeatureFlagKeys.PolicyValidatorsRefactor) + .Returns(true); + + _ = await sutProvider.Sut.UserVerifyOrganizationDomainAsync(domain); + + await sutProvider.GetDependency() + .Received(1) + .SaveAsync(Arg.Is(m => + m.PolicyUpdate.Type == PolicyType.SingleOrg && + m.PolicyUpdate.OrganizationId == domain.OrganizationId && + m.PolicyUpdate.Enabled && + m.PerformedBy is StandardUser && + m.PerformedBy.UserId == userId)); + } + [Theory, BitAutoData] public async Task UserVerifyOrganizationDomainAsync_WhenDomainIsNotVerified_ThenSingleOrgPolicyShouldNotBeEnabled( OrganizationDomain domain, SutProvider sutProvider) From 6c161e9036272def711f5b062413b8d5ab9e5b1d Mon Sep 17 00:00:00 2001 From: Rui Tome Date: Wed, 22 Oct 2025 17:09:16 +0100 Subject: [PATCH 6/7] Enhance SsoConfigService to utilize IVNextSavePolicyCommand based on feature flag - Added IFeatureService and IVNextSavePolicyCommand dependencies to SsoConfigService. - Updated SaveAsync method to conditionally use VNextSavePolicyCommand or SavePolicyCommand based on the PolicyValidatorsRefactor feature flag. - Added unit tests to validate the behavior when the feature flag is enabled. --- .../Implementations/SsoConfigService.cs | 34 +++++++++--- .../Auth/Services/SsoConfigServiceTests.cs | 53 +++++++++++++++++++ 2 files changed, 80 insertions(+), 7 deletions(-) diff --git a/src/Core/Auth/Services/Implementations/SsoConfigService.cs b/src/Core/Auth/Services/Implementations/SsoConfigService.cs index fe8d9bdd6e0c..115fd6a71d4f 100644 --- a/src/Core/Auth/Services/Implementations/SsoConfigService.cs +++ b/src/Core/Auth/Services/Implementations/SsoConfigService.cs @@ -3,9 +3,11 @@ using Bit.Core.AdminConsole.Entities; using Bit.Core.AdminConsole.Enums; +using Bit.Core.AdminConsole.Models.Data; using Bit.Core.AdminConsole.Models.Data.Organizations.Policies; using Bit.Core.AdminConsole.OrganizationFeatures.Policies; using Bit.Core.AdminConsole.OrganizationFeatures.Policies.Models; +using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyUpdateEvents.Interfaces; using Bit.Core.AdminConsole.Repositories; using Bit.Core.Auth.Entities; using Bit.Core.Auth.Enums; @@ -24,7 +26,9 @@ public class SsoConfigService : ISsoConfigService private readonly IOrganizationRepository _organizationRepository; private readonly IOrganizationUserRepository _organizationUserRepository; private readonly IEventService _eventService; + private readonly IFeatureService _featureService; private readonly ISavePolicyCommand _savePolicyCommand; + private readonly IVNextSavePolicyCommand _vNextSavePolicyCommand; public SsoConfigService( ISsoConfigRepository ssoConfigRepository, @@ -32,14 +36,18 @@ public SsoConfigService( IOrganizationRepository organizationRepository, IOrganizationUserRepository organizationUserRepository, IEventService eventService, - ISavePolicyCommand savePolicyCommand) + IFeatureService featureService, + ISavePolicyCommand savePolicyCommand, + IVNextSavePolicyCommand vNextSavePolicyCommand) { _ssoConfigRepository = ssoConfigRepository; _policyRepository = policyRepository; _organizationRepository = organizationRepository; _organizationUserRepository = organizationUserRepository; _eventService = eventService; + _featureService = featureService; _savePolicyCommand = savePolicyCommand; + _vNextSavePolicyCommand = vNextSavePolicyCommand; } public async Task SaveAsync(SsoConfig config, Organization organization) @@ -67,13 +75,12 @@ public async Task SaveAsync(SsoConfig config, Organization organization) // Automatically enable account recovery, SSO required, and single org policies if trusted device encryption is selected if (config.GetData().MemberDecryptionType == MemberDecryptionType.TrustedDeviceEncryption) { - - await _savePolicyCommand.SaveAsync(new() + var singleOrgPolicy = new PolicyUpdate { OrganizationId = config.OrganizationId, Type = PolicyType.SingleOrg, Enabled = true - }); + }; var resetPasswordPolicy = new PolicyUpdate { @@ -82,14 +89,27 @@ await _savePolicyCommand.SaveAsync(new() Enabled = true, }; resetPasswordPolicy.SetDataModel(new ResetPasswordDataModel { AutoEnrollEnabled = true }); - await _savePolicyCommand.SaveAsync(resetPasswordPolicy); - await _savePolicyCommand.SaveAsync(new() + var requireSsoPolicy = new PolicyUpdate { OrganizationId = config.OrganizationId, Type = PolicyType.RequireSso, Enabled = true - }); + }; + + if (_featureService.IsEnabled(FeatureFlagKeys.PolicyValidatorsRefactor)) + { + var performedBy = new SystemUser(EventSystemUser.Unknown); + await _vNextSavePolicyCommand.SaveAsync(new SavePolicyModel(singleOrgPolicy, performedBy, new EmptyMetadataModel())); + await _vNextSavePolicyCommand.SaveAsync(new SavePolicyModel(resetPasswordPolicy, performedBy, new EmptyMetadataModel())); + await _vNextSavePolicyCommand.SaveAsync(new SavePolicyModel(requireSsoPolicy, performedBy, new EmptyMetadataModel())); + } + else + { + await _savePolicyCommand.SaveAsync(singleOrgPolicy); + await _savePolicyCommand.SaveAsync(resetPasswordPolicy); + await _savePolicyCommand.SaveAsync(requireSsoPolicy); + } } await LogEventsAsync(config, oldConfig); diff --git a/test/Core.Test/Auth/Services/SsoConfigServiceTests.cs b/test/Core.Test/Auth/Services/SsoConfigServiceTests.cs index 7beb772b9582..7319df17aa0a 100644 --- a/test/Core.Test/Auth/Services/SsoConfigServiceTests.cs +++ b/test/Core.Test/Auth/Services/SsoConfigServiceTests.cs @@ -1,8 +1,10 @@ using Bit.Core.AdminConsole.Entities; using Bit.Core.AdminConsole.Enums; +using Bit.Core.AdminConsole.Models.Data; using Bit.Core.AdminConsole.Models.Data.Organizations.Policies; using Bit.Core.AdminConsole.OrganizationFeatures.Policies; using Bit.Core.AdminConsole.OrganizationFeatures.Policies.Models; +using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyUpdateEvents.Interfaces; using Bit.Core.AdminConsole.Repositories; using Bit.Core.Auth.Entities; using Bit.Core.Auth.Enums; @@ -12,6 +14,7 @@ using Bit.Core.Exceptions; using Bit.Core.Models.Data.Organizations.OrganizationUsers; using Bit.Core.Repositories; +using Bit.Core.Services; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; @@ -364,4 +367,54 @@ await sutProvider.GetDependency().Received(1) await sutProvider.GetDependency().ReceivedWithAnyArgs() .UpsertAsync(default); } + + [Theory, BitAutoData] + public async Task SaveAsync_Tde_WhenPolicyValidatorsRefactorEnabled_UsesVNextSavePolicyCommand( + SutProvider sutProvider, Organization organization) + { + var ssoConfig = new SsoConfig + { + Id = default, + Data = new SsoConfigurationData + { + MemberDecryptionType = MemberDecryptionType.TrustedDeviceEncryption, + }.Serialize(), + Enabled = true, + OrganizationId = organization.Id, + }; + + sutProvider.GetDependency() + .IsEnabled(FeatureFlagKeys.PolicyValidatorsRefactor) + .Returns(true); + + await sutProvider.Sut.SaveAsync(ssoConfig, organization); + + await sutProvider.GetDependency() + .Received(1) + .SaveAsync(Arg.Is(m => + m.PolicyUpdate.Type == PolicyType.SingleOrg && + m.PolicyUpdate.OrganizationId == organization.Id && + m.PolicyUpdate.Enabled && + m.PerformedBy is SystemUser)); + + await sutProvider.GetDependency() + .Received(1) + .SaveAsync(Arg.Is(m => + m.PolicyUpdate.Type == PolicyType.ResetPassword && + m.PolicyUpdate.GetDataModel().AutoEnrollEnabled && + m.PolicyUpdate.OrganizationId == organization.Id && + m.PolicyUpdate.Enabled && + m.PerformedBy is SystemUser)); + + await sutProvider.GetDependency() + .Received(1) + .SaveAsync(Arg.Is(m => + m.PolicyUpdate.Type == PolicyType.RequireSso && + m.PolicyUpdate.OrganizationId == organization.Id && + m.PolicyUpdate.Enabled && + m.PerformedBy is SystemUser)); + + await sutProvider.GetDependency().ReceivedWithAnyArgs() + .UpsertAsync(default); + } } From cf6d0d1e1dd590f18a4d06b2d04df3b51cce83e2 Mon Sep 17 00:00:00 2001 From: Rui Tome Date: Mon, 27 Oct 2025 15:00:36 +0000 Subject: [PATCH 7/7] Refactor SavePolicyModel to simplify constructor usage by removing EmptyMetadataModel parameter. Update related usages across the codebase to reflect the new constructor overloads. --- .../VerifyOrganizationDomainCommand.cs | 2 +- .../Policies/Models/SavePolicyModel.cs | 14 +++++++++++ .../Implementations/SsoConfigService.cs | 6 ++--- ...miliesForEnterprisePolicyValidatorTests.cs | 4 ++-- ...zationDataOwnershipPolicyValidatorTests.cs | 24 +++++++++---------- .../RequireSsoPolicyValidatorTests.cs | 6 ++--- .../ResetPasswordPolicyValidatorTests.cs | 4 ++-- .../SingleOrgPolicyValidatorTests.cs | 6 ++--- ...actorAuthenticationPolicyValidatorTests.cs | 4 ++-- .../Policies/SavePolicyCommandTests.cs | 4 ++-- .../Policies/VNextSavePolicyCommandTests.cs | 22 ++++++++--------- 11 files changed, 55 insertions(+), 41 deletions(-) diff --git a/src/Core/AdminConsole/OrganizationFeatures/OrganizationDomains/VerifyOrganizationDomainCommand.cs b/src/Core/AdminConsole/OrganizationFeatures/OrganizationDomains/VerifyOrganizationDomainCommand.cs index c68546c36389..595e4875800e 100644 --- a/src/Core/AdminConsole/OrganizationFeatures/OrganizationDomains/VerifyOrganizationDomainCommand.cs +++ b/src/Core/AdminConsole/OrganizationFeatures/OrganizationDomains/VerifyOrganizationDomainCommand.cs @@ -146,7 +146,7 @@ private async Task EnableSingleOrganizationPolicyAsync(Guid organizationId, IAct if (featureService.IsEnabled(FeatureFlagKeys.PolicyValidatorsRefactor)) { - var savePolicyModel = new SavePolicyModel(policyUpdate, actingUser, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate, actingUser); await vNextSavePolicyCommand.SaveAsync(savePolicyModel); } else diff --git a/src/Core/AdminConsole/OrganizationFeatures/Policies/Models/SavePolicyModel.cs b/src/Core/AdminConsole/OrganizationFeatures/Policies/Models/SavePolicyModel.cs index 7c8d5126e86c..01168deea4ad 100644 --- a/src/Core/AdminConsole/OrganizationFeatures/Policies/Models/SavePolicyModel.cs +++ b/src/Core/AdminConsole/OrganizationFeatures/Policies/Models/SavePolicyModel.cs @@ -5,4 +5,18 @@ namespace Bit.Core.AdminConsole.OrganizationFeatures.Policies.Models; public record SavePolicyModel(PolicyUpdate PolicyUpdate, IActingUser? PerformedBy, IPolicyMetadataModel Metadata) { + public SavePolicyModel(PolicyUpdate PolicyUpdate) + : this(PolicyUpdate, null, new EmptyMetadataModel()) + { + } + + public SavePolicyModel(PolicyUpdate PolicyUpdate, IActingUser performedBy) + : this(PolicyUpdate, performedBy, new EmptyMetadataModel()) + { + } + + public SavePolicyModel(PolicyUpdate PolicyUpdate, IPolicyMetadataModel metadata) + : this(PolicyUpdate, null, metadata) + { + } } diff --git a/src/Core/Auth/Services/Implementations/SsoConfigService.cs b/src/Core/Auth/Services/Implementations/SsoConfigService.cs index 115fd6a71d4f..1a35585b2c71 100644 --- a/src/Core/Auth/Services/Implementations/SsoConfigService.cs +++ b/src/Core/Auth/Services/Implementations/SsoConfigService.cs @@ -100,9 +100,9 @@ public async Task SaveAsync(SsoConfig config, Organization organization) if (_featureService.IsEnabled(FeatureFlagKeys.PolicyValidatorsRefactor)) { var performedBy = new SystemUser(EventSystemUser.Unknown); - await _vNextSavePolicyCommand.SaveAsync(new SavePolicyModel(singleOrgPolicy, performedBy, new EmptyMetadataModel())); - await _vNextSavePolicyCommand.SaveAsync(new SavePolicyModel(resetPasswordPolicy, performedBy, new EmptyMetadataModel())); - await _vNextSavePolicyCommand.SaveAsync(new SavePolicyModel(requireSsoPolicy, performedBy, new EmptyMetadataModel())); + await _vNextSavePolicyCommand.SaveAsync(new SavePolicyModel(singleOrgPolicy, performedBy)); + await _vNextSavePolicyCommand.SaveAsync(new SavePolicyModel(resetPasswordPolicy, performedBy)); + await _vNextSavePolicyCommand.SaveAsync(new SavePolicyModel(requireSsoPolicy, performedBy)); } else { diff --git a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/FreeFamiliesForEnterprisePolicyValidatorTests.cs b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/FreeFamiliesForEnterprisePolicyValidatorTests.cs index 8f8fd939fe20..525169a1fbb4 100644 --- a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/FreeFamiliesForEnterprisePolicyValidatorTests.cs +++ b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/FreeFamiliesForEnterprisePolicyValidatorTests.cs @@ -92,7 +92,7 @@ public async Task ExecutePreUpsertSideEffectAsync_DoesNotNotifyUserWhenPolicyDis .GetManyBySponsoringOrganizationAsync(policyUpdate.OrganizationId) .Returns(organizationSponsorships); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); await sutProvider.Sut.ExecutePreUpsertSideEffectAsync(savePolicyModel, policy); @@ -120,7 +120,7 @@ public async Task ExecutePreUpsertSideEffectAsync_DoesNotifyUserWhenPolicyEnable .GetManyBySponsoringOrganizationAsync(policyUpdate.OrganizationId) .Returns(organizationSponsorships); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); await sutProvider.Sut.ExecutePreUpsertSideEffectAsync(savePolicyModel, policy); diff --git a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/OrganizationDataOwnershipPolicyValidatorTests.cs b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/OrganizationDataOwnershipPolicyValidatorTests.cs index a65290e6a708..e6677c8a2379 100644 --- a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/OrganizationDataOwnershipPolicyValidatorTests.cs +++ b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/OrganizationDataOwnershipPolicyValidatorTests.cs @@ -32,7 +32,7 @@ public async Task ExecuteSideEffectsAsync_FeatureFlagDisabled_DoesNothing( .IsEnabled(FeatureFlagKeys.CreateDefaultLocation) .Returns(false); - var policyRequest = new SavePolicyModel(policyUpdate, null, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); + var policyRequest = new SavePolicyModel(policyUpdate, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); // Act await sutProvider.Sut.ExecuteSideEffectsAsync(policyRequest, postUpdatedPolicy, previousPolicyState); @@ -58,7 +58,7 @@ public async Task ExecuteSideEffectsAsync_PolicyAlreadyEnabled_DoesNothing( .IsEnabled(FeatureFlagKeys.CreateDefaultLocation) .Returns(true); - var policyRequest = new SavePolicyModel(policyUpdate, null, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); + var policyRequest = new SavePolicyModel(policyUpdate, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); // Act await sutProvider.Sut.ExecuteSideEffectsAsync(policyRequest, postUpdatedPolicy, previousPolicyState); @@ -84,7 +84,7 @@ public async Task ExecuteSideEffectsAsync_PolicyBeingDisabled_DoesNothing( .IsEnabled(FeatureFlagKeys.CreateDefaultLocation) .Returns(true); - var policyRequest = new SavePolicyModel(policyUpdate, null, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); + var policyRequest = new SavePolicyModel(policyUpdate, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); // Act await sutProvider.Sut.ExecuteSideEffectsAsync(policyRequest, postUpdatedPolicy, previousPolicyState); @@ -110,7 +110,7 @@ public async Task ExecuteSideEffectsAsync_WhenNoUsersExist_DoNothing( var collectionRepository = Substitute.For(); var sut = ArrangeSut(factory, policyRepository, collectionRepository); - var policyRequest = new SavePolicyModel(policyUpdate, null, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); + var policyRequest = new SavePolicyModel(policyUpdate, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); // Act await sut.ExecuteSideEffectsAsync(policyRequest, postUpdatedPolicy, previousPolicyState); @@ -199,7 +199,7 @@ public async Task ExecuteSideEffectsAsync_WithRequirements_ShouldUpsertDefaultCo var collectionRepository = Substitute.For(); var sut = ArrangeSut(factory, policyRepository, collectionRepository); - var policyRequest = new SavePolicyModel(policyUpdate, null, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); + var policyRequest = new SavePolicyModel(policyUpdate, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); // Act await sut.ExecuteSideEffectsAsync(policyRequest, postUpdatedPolicy, previousPolicyState); @@ -238,7 +238,7 @@ public async Task ExecuteSideEffectsAsync_WhenDefaultCollectionNameIsInvalid_Doe .IsEnabled(FeatureFlagKeys.CreateDefaultLocation) .Returns(true); - var policyRequest = new SavePolicyModel(policyUpdate, null, metadata); + var policyRequest = new SavePolicyModel(policyUpdate, metadata); // Act await sutProvider.Sut.ExecuteSideEffectsAsync(policyRequest, postUpdatedPolicy, previousPolicyState); @@ -286,7 +286,7 @@ public async Task ExecutePostUpsertSideEffectAsync_FeatureFlagDisabled_DoesNothi .IsEnabled(FeatureFlagKeys.CreateDefaultLocation) .Returns(false); - var policyRequest = new SavePolicyModel(policyUpdate, null, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); + var policyRequest = new SavePolicyModel(policyUpdate, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); // Act await sutProvider.Sut.ExecutePostUpsertSideEffectAsync(policyRequest, postUpdatedPolicy, previousPolicyState); @@ -312,7 +312,7 @@ public async Task ExecutePostUpsertSideEffectAsync_PolicyAlreadyEnabled_DoesNoth .IsEnabled(FeatureFlagKeys.CreateDefaultLocation) .Returns(true); - var policyRequest = new SavePolicyModel(policyUpdate, null, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); + var policyRequest = new SavePolicyModel(policyUpdate, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); // Act await sutProvider.Sut.ExecutePostUpsertSideEffectAsync(policyRequest, postUpdatedPolicy, previousPolicyState); @@ -338,7 +338,7 @@ public async Task ExecutePostUpsertSideEffectAsync_PolicyBeingDisabled_DoesNothi .IsEnabled(FeatureFlagKeys.CreateDefaultLocation) .Returns(true); - var policyRequest = new SavePolicyModel(policyUpdate, null, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); + var policyRequest = new SavePolicyModel(policyUpdate, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); // Act await sutProvider.Sut.ExecutePostUpsertSideEffectAsync(policyRequest, postUpdatedPolicy, previousPolicyState); @@ -364,7 +364,7 @@ public async Task ExecutePostUpsertSideEffectAsync_WhenNoUsersExist_DoNothing( var collectionRepository = Substitute.For(); var sut = ArrangeSut(factory, policyRepository, collectionRepository); - var policyRequest = new SavePolicyModel(policyUpdate, null, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); + var policyRequest = new SavePolicyModel(policyUpdate, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); // Act await sut.ExecutePostUpsertSideEffectAsync(policyRequest, postUpdatedPolicy, previousPolicyState); @@ -404,7 +404,7 @@ public async Task ExecutePostUpsertSideEffectAsync_WithRequirements_ShouldUpsert var collectionRepository = Substitute.For(); var sut = ArrangeSut(factory, policyRepository, collectionRepository); - var policyRequest = new SavePolicyModel(policyUpdate, null, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); + var policyRequest = new SavePolicyModel(policyUpdate, new OrganizationModelOwnershipPolicyModel(_defaultUserCollectionName)); // Act await sut.ExecutePostUpsertSideEffectAsync(policyRequest, postUpdatedPolicy, previousPolicyState); @@ -436,7 +436,7 @@ public async Task ExecutePostUpsertSideEffectAsync_WhenDefaultCollectionNameIsIn .IsEnabled(FeatureFlagKeys.CreateDefaultLocation) .Returns(true); - var policyRequest = new SavePolicyModel(policyUpdate, null, metadata); + var policyRequest = new SavePolicyModel(policyUpdate, metadata); // Act await sutProvider.Sut.ExecutePostUpsertSideEffectAsync(policyRequest, postUpdatedPolicy, previousPolicyState); diff --git a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/RequireSsoPolicyValidatorTests.cs b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/RequireSsoPolicyValidatorTests.cs index 857aa5e09e31..6fc6b8566828 100644 --- a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/RequireSsoPolicyValidatorTests.cs +++ b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/RequireSsoPolicyValidatorTests.cs @@ -88,7 +88,7 @@ public async Task ValidateAsync_WithSavePolicyModel_DisablingPolicy_KeyConnector .GetByOrganizationIdAsync(policyUpdate.OrganizationId) .Returns(ssoConfig); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); var result = await sutProvider.Sut.ValidateAsync(savePolicyModel, policy); Assert.Contains("Key Connector is enabled", result, StringComparison.OrdinalIgnoreCase); @@ -109,7 +109,7 @@ public async Task ValidateAsync_WithSavePolicyModel_DisablingPolicy_TdeEnabled_V .GetByOrganizationIdAsync(policyUpdate.OrganizationId) .Returns(ssoConfig); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); var result = await sutProvider.Sut.ValidateAsync(savePolicyModel, policy); Assert.Contains("Trusted device encryption is on", result, StringComparison.OrdinalIgnoreCase); @@ -129,7 +129,7 @@ public async Task ValidateAsync_WithSavePolicyModel_DisablingPolicy_DecryptionOp .GetByOrganizationIdAsync(policyUpdate.OrganizationId) .Returns(ssoConfig); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); var result = await sutProvider.Sut.ValidateAsync(savePolicyModel, policy); Assert.True(string.IsNullOrEmpty(result)); diff --git a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/ResetPasswordPolicyValidatorTests.cs b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/ResetPasswordPolicyValidatorTests.cs index cdfd549454cb..b3d328c5abb5 100644 --- a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/ResetPasswordPolicyValidatorTests.cs +++ b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/ResetPasswordPolicyValidatorTests.cs @@ -94,7 +94,7 @@ public async Task ValidateAsync_WithSavePolicyModel_DisablingPolicy_TdeEnabled_V .GetByOrganizationIdAsync(policyUpdate.OrganizationId) .Returns(ssoConfig); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); var result = await sutProvider.Sut.ValidateAsync(savePolicyModel, policy); Assert.Contains("Trusted device encryption is on and requires this policy.", result, StringComparison.OrdinalIgnoreCase); @@ -118,7 +118,7 @@ public async Task ValidateAsync_WithSavePolicyModel_DisablingPolicy_TdeNotEnable .GetByOrganizationIdAsync(policyUpdate.OrganizationId) .Returns(ssoConfig); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); var result = await sutProvider.Sut.ValidateAsync(savePolicyModel, policy); Assert.True(string.IsNullOrEmpty(result)); diff --git a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/SingleOrgPolicyValidatorTests.cs b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/SingleOrgPolicyValidatorTests.cs index cea464c155dc..7c58d4663674 100644 --- a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/SingleOrgPolicyValidatorTests.cs +++ b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/SingleOrgPolicyValidatorTests.cs @@ -162,7 +162,7 @@ public async Task ValidateAsync_WithSavePolicyModel_DisablingPolicy_KeyConnector .GetByOrganizationIdAsync(policyUpdate.OrganizationId) .Returns(ssoConfig); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); var result = await sutProvider.Sut.ValidateAsync(savePolicyModel, policy); Assert.Contains("Key Connector is enabled", result, StringComparison.OrdinalIgnoreCase); @@ -186,7 +186,7 @@ public async Task ValidateAsync_WithSavePolicyModel_DisablingPolicy_KeyConnector .HasVerifiedDomainsAsync(policyUpdate.OrganizationId) .Returns(false); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); var result = await sutProvider.Sut.ValidateAsync(savePolicyModel, policy); Assert.True(string.IsNullOrEmpty(result)); @@ -256,7 +256,7 @@ public async Task ExecutePreUpsertSideEffectAsync_RevokesNonCompliantUsers( .RevokeNonCompliantOrganizationUsersAsync(Arg.Any()) .Returns(new CommandResult()); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); await sutProvider.Sut.ExecutePreUpsertSideEffectAsync(savePolicyModel, policy); diff --git a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/TwoFactorAuthenticationPolicyValidatorTests.cs b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/TwoFactorAuthenticationPolicyValidatorTests.cs index 9eadbcc3b89e..7d5aaf8d2142 100644 --- a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/TwoFactorAuthenticationPolicyValidatorTests.cs +++ b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/PolicyValidators/TwoFactorAuthenticationPolicyValidatorTests.cs @@ -169,7 +169,7 @@ public async Task ExecutePreUpsertSideEffectAsync_GivenNonCompliantUsersWithoutM (orgUserDetailUserWithout2Fa, false), }); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.ExecutePreUpsertSideEffectAsync(savePolicyModel, policy)); @@ -228,7 +228,7 @@ public async Task ExecutePreUpsertSideEffectAsync_RevokesOnlyNonCompliantUsers( .RevokeNonCompliantOrganizationUsersAsync(Arg.Any()) .Returns(new CommandResult()); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); // Act await sutProvider.Sut.ExecutePreUpsertSideEffectAsync(savePolicyModel, policy); diff --git a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/SavePolicyCommandTests.cs b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/SavePolicyCommandTests.cs index 6b857607943e..b1e3faf2578c 100644 --- a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/SavePolicyCommandTests.cs +++ b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/SavePolicyCommandTests.cs @@ -288,7 +288,7 @@ public async Task VNextSaveAsync_OrganizationDataOwnershipPolicy_ExecutesPostSav { // Arrange var sutProvider = SutProviderFactory(); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); currentPolicy.OrganizationId = policyUpdate.OrganizationId; sutProvider.GetDependency() @@ -332,7 +332,7 @@ public async Task VNextSaveAsync_NonOrganizationDataOwnershipPolicy_DoesNotExecu var sutProvider = SutProviderFactory(); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); sutProvider.GetDependency() .GetByOrganizationIdTypeAsync(policyUpdate.OrganizationId, policyUpdate.Type) diff --git a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/VNextSavePolicyCommandTests.cs b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/VNextSavePolicyCommandTests.cs index da10ea300fff..a7dc0402a23d 100644 --- a/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/VNextSavePolicyCommandTests.cs +++ b/test/Core.Test/AdminConsole/OrganizationFeatures/Policies/VNextSavePolicyCommandTests.cs @@ -33,7 +33,7 @@ public async Task SaveAsync_NewPolicy_Success([PolicyUpdate(PolicyType.SingleOrg fakePolicyValidationEvent ]); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); var newPolicy = new Policy { @@ -77,7 +77,7 @@ public async Task SaveAsync_ExistingPolicy_Success( fakePolicyValidationEvent ]); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); currentPolicy.OrganizationId = policyUpdate.OrganizationId; sutProvider.GetDependency() @@ -117,7 +117,7 @@ public async Task SaveAsync_OrganizationDoesNotExist_ThrowsBadRequest([PolicyUpd { // Arrange var sutProvider = SutProviderFactory(); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); sutProvider.GetDependency() .GetOrganizationAbilityAsync(policyUpdate.OrganizationId) @@ -137,7 +137,7 @@ public async Task SaveAsync_OrganizationCannotUsePolicies_ThrowsBadRequest([Poli { // Arrange var sutProvider = SutProviderFactory(); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); sutProvider.GetDependency() .GetOrganizationAbilityAsync(policyUpdate.OrganizationId) @@ -167,7 +167,7 @@ public async Task SaveAsync_RequiredPolicyIsNull_Throws( new FakeSingleOrgDependencyEvent() ]); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); var requireSsoPolicy = new Policy { @@ -202,7 +202,7 @@ public async Task SaveAsync_RequiredPolicyNotEnabled_Throws( new FakeSingleOrgDependencyEvent() ]); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); var requireSsoPolicy = new Policy { @@ -237,7 +237,7 @@ public async Task SaveAsync_RequiredPolicyEnabled_Success( new FakeSingleOrgDependencyEvent() ]); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); var requireSsoPolicy = new Policy { @@ -271,7 +271,7 @@ public async Task SaveAsync_DependentPolicyIsEnabled_Throws( new FakeSingleOrgDependencyEvent() ]); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); ArrangeOrganization(sutProvider, policyUpdate); sutProvider.GetDependency() @@ -302,7 +302,7 @@ public async Task SaveAsync_MultipleDependentPoliciesAreEnabled_Throws( new FakeVaultTimeoutDependencyEvent() ]); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); ArrangeOrganization(sutProvider, policyUpdate); sutProvider.GetDependency() @@ -331,7 +331,7 @@ public async Task SaveAsync_DependentPolicyNotEnabled_Success( new FakeSingleOrgDependencyEvent() ]); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); ArrangeOrganization(sutProvider, policyUpdate); sutProvider.GetDependency() @@ -356,7 +356,7 @@ public async Task SaveAsync_ThrowsOnValidationError([PolicyUpdate(PolicyType.Sin fakePolicyValidationEvent ]); - var savePolicyModel = new SavePolicyModel(policyUpdate, null, new EmptyMetadataModel()); + var savePolicyModel = new SavePolicyModel(policyUpdate); var singleOrgPolicy = new Policy {