mirror of
https://github.com/bitwarden/server.git
synced 2024-12-04 14:13:28 +01:00
Use delegates to simplify mocking
This commit is contained in:
parent
b3006ef64e
commit
4983e413e4
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
using Bit.Core.AdminConsole.Entities;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Bit.Core.AdminConsole.Enums;
|
using Bit.Core.AdminConsole.Enums;
|
||||||
using Bit.Core.Entities;
|
|
||||||
|
|
||||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
namespace Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
||||||
|
|
||||||
@ -26,7 +25,7 @@ public interface IPolicyDefinition
|
|||||||
/// <param name="currentPolicy">The current policy, if any</param>
|
/// <param name="currentPolicy">The current policy, if any</param>
|
||||||
/// <param name="modifiedPolicy">The modified policy to be saved</param>
|
/// <param name="modifiedPolicy">The modified policy to be saved</param>
|
||||||
/// <returns>A sequence of validation errors if validation was unsuccessful</returns>
|
/// <returns>A sequence of validation errors if validation was unsuccessful</returns>
|
||||||
public Task<string?> ValidateAsync(Policy? currentPolicy, Policy modifiedPolicy);
|
public Func<Policy?, Policy, Task<string?>> Validate { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Optionally performs side effects after a policy is validated but before it is saved.
|
/// Optionally performs side effects after a policy is validated but before it is saved.
|
||||||
@ -34,5 +33,5 @@ public interface IPolicyDefinition
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="currentPolicy">The current policy, if any</param>
|
/// <param name="currentPolicy">The current policy, if any</param>
|
||||||
/// <param name="modifiedPolicy">The modified policy to be saved</param>
|
/// <param name="modifiedPolicy">The modified policy to be saved</param>
|
||||||
public Task OnSaveSideEffectsAsync(Policy? currentPolicy, Policy modifiedPolicy);
|
public Func<Policy?, Policy, Task> OnSaveSideEffects { get; }
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
using System.ComponentModel;
|
|
||||||
using Bit.Core.AdminConsole.Entities;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Bit.Core.AdminConsole.Enums;
|
using Bit.Core.AdminConsole.Enums;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
|
||||||
using Bit.Core.Auth.Enums;
|
using Bit.Core.Auth.Enums;
|
||||||
using Bit.Core.Auth.Repositories;
|
using Bit.Core.Auth.Repositories;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
using Bit.Core.Entities;
|
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
@ -40,13 +37,27 @@ public class SingleOrgPolicyDefinition : IPolicyDefinition
|
|||||||
_currentContext = currentContext;
|
_currentContext = currentContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task OnSaveSideEffectsAsync(Policy? currentPolicy, Policy modifiedPolicy)
|
public Func<Policy?, Policy, Task<string?>> Validate => async (currentPolicy, modifiedPolicy) =>
|
||||||
|
{
|
||||||
|
var organizationId = modifiedPolicy.OrganizationId;
|
||||||
|
|
||||||
|
// Do not allow this policy to be disabled if Key Connector is being used
|
||||||
|
var ssoConfig = await _ssoConfigRepository.GetByOrganizationIdAsync(organizationId);
|
||||||
|
if (ssoConfig?.GetData()?.MemberDecryptionType == MemberDecryptionType.KeyConnector)
|
||||||
|
{
|
||||||
|
return "Key Connector is enabled.";
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
public Func<Policy?, Policy, Task> OnSaveSideEffects => async (currentPolicy, modifiedPolicy) =>
|
||||||
{
|
{
|
||||||
if (currentPolicy is null or { Enabled: false } && modifiedPolicy is { Enabled: true })
|
if (currentPolicy is null or { Enabled: false } && modifiedPolicy is { Enabled: true })
|
||||||
{
|
{
|
||||||
await RemoveNonCompliantUsersAsync(modifiedPolicy.OrganizationId);
|
await RemoveNonCompliantUsersAsync(modifiedPolicy.OrganizationId);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
private async Task RemoveNonCompliantUsersAsync(Guid organizationId)
|
private async Task RemoveNonCompliantUsersAsync(Guid organizationId)
|
||||||
{
|
{
|
||||||
@ -85,17 +96,4 @@ public class SingleOrgPolicyDefinition : IPolicyDefinition
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string?> ValidateAsync(Policy? currentPolicy, Policy modifiedPolicy)
|
|
||||||
{
|
|
||||||
var organizationId = modifiedPolicy.OrganizationId;
|
|
||||||
|
|
||||||
// Do not allow this policy to be disabled if Key Connector is being used
|
|
||||||
var ssoConfig = await _ssoConfigRepository.GetByOrganizationIdAsync(organizationId);
|
|
||||||
if (ssoConfig?.GetData()?.MemberDecryptionType == MemberDecryptionType.KeyConnector)
|
|
||||||
{
|
|
||||||
return "Key Connector is enabled.";
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -82,21 +82,21 @@ public class PolicyServicevNext : IPolicyServicevNext
|
|||||||
.Where(otherPolicy => otherPolicy is { Enabled: true })
|
.Where(otherPolicy => otherPolicy is { Enabled: true })
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (dependentPolicies is { Count: > 0})
|
if (dependentPolicies is { Count: > 0 })
|
||||||
{
|
{
|
||||||
throw new BadRequestException("This policy is required by " + dependentPolicies.First() + ". Try disabling that policy first." );
|
throw new BadRequestException("This policy is required by " + dependentPolicies.First() + ". Try disabling that policy first.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run other validation
|
// Run other validation
|
||||||
var validationError = await policyDefinition.ValidateAsync(currentPolicy, policy);
|
var validationError = await policyDefinition.Validate(currentPolicy, policy);
|
||||||
if (validationError != null)
|
if (validationError != null)
|
||||||
{
|
{
|
||||||
throw new BadRequestException(validationError);
|
throw new BadRequestException(validationError);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run side effects
|
// Run side effects
|
||||||
await policyDefinition.OnSaveSideEffectsAsync(currentPolicy, policy);
|
await policyDefinition.OnSaveSideEffects(currentPolicy, policy);
|
||||||
|
|
||||||
var now = DateTime.UtcNow;
|
var now = DateTime.UtcNow;
|
||||||
if (policy.Id == default)
|
if (policy.Id == default)
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using AutoFixture;
|
|
||||||
using AutoFixture.Kernel;
|
using AutoFixture.Kernel;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
||||||
using Bit.Core.AdminConsole.Services.Implementations;
|
using Bit.Core.AdminConsole.Services.Implementations;
|
||||||
using Bit.Test.Common.AutoFixture.Attributes;
|
|
||||||
|
|
||||||
namespace Bit.Core.Test.AdminConsole.AutoFixture;
|
namespace Bit.Core.Test.AdminConsole.AutoFixture;
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
using Bit.Core.AdminConsole.Entities;
|
#nullable enable
|
||||||
|
|
||||||
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Bit.Core.AdminConsole.Enums;
|
using Bit.Core.AdminConsole.Enums;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using NSubstitute.ExceptionExtensions;
|
|
||||||
|
|
||||||
namespace Bit.Core.Test.AdminConsole.Services;
|
namespace Bit.Core.Test.AdminConsole.Services;
|
||||||
|
|
||||||
@ -10,18 +11,15 @@ public class FakeSingleOrgPolicyDefinition : IPolicyDefinition
|
|||||||
{
|
{
|
||||||
public PolicyType Type => PolicyType.SingleOrg;
|
public PolicyType Type => PolicyType.SingleOrg;
|
||||||
public IEnumerable<PolicyType> RequiredPolicies => Array.Empty<PolicyType>();
|
public IEnumerable<PolicyType> RequiredPolicies => Array.Empty<PolicyType>();
|
||||||
|
public Func<Policy?, Policy, Task<string?>> Validate => Substitute.For<Func<Policy?, Policy, Task<string?>>>();
|
||||||
public readonly Func<Policy?, Policy, Task<string?>> ValidateAsyncMock = Substitute.For<Func<Policy, Policy, Task<string>>>();
|
public Func<Policy?, Policy, Task> OnSaveSideEffects => Substitute.For<Func<Policy?, Policy, Task>>();
|
||||||
public readonly Action<Policy?, Policy> OnSaveSideEffectsAsyncMock = Substitute.For<Action<Policy, Policy>>();
|
|
||||||
|
|
||||||
public Task<string>? ValidateAsync(Policy? currentPolicy, Policy modifiedPolicy)
|
|
||||||
{
|
|
||||||
return ValidateAsyncMock(currentPolicy, modifiedPolicy);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task OnSaveSideEffectsAsync(Policy? currentPolicy, Policy modifiedPolicy)
|
|
||||||
{
|
|
||||||
OnSaveSideEffectsAsyncMock(currentPolicy, modifiedPolicy);
|
|
||||||
return Task.FromResult(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class FakeRequireSsoPolicyDefinition : IPolicyDefinition
|
||||||
|
{
|
||||||
|
public PolicyType Type => PolicyType.RequireSso;
|
||||||
|
public IEnumerable<PolicyType> RequiredPolicies => [PolicyType.SingleOrg];
|
||||||
|
public Func<Policy?, Policy, Task<string?>> Validate => Substitute.For<Func<Policy?, Policy, Task<string?>>>();
|
||||||
|
public Func<Policy?, Policy, Task> OnSaveSideEffects => Substitute.For<Func<Policy?, Policy, Task>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -10,9 +10,9 @@ using Bit.Core.Services;
|
|||||||
using Bit.Core.Test.AdminConsole.AutoFixture;
|
using Bit.Core.Test.AdminConsole.AutoFixture;
|
||||||
using Bit.Test.Common.AutoFixture;
|
using Bit.Test.Common.AutoFixture;
|
||||||
using Bit.Test.Common.AutoFixture.Attributes;
|
using Bit.Test.Common.AutoFixture.Attributes;
|
||||||
using AdminConsoleFixtures = Bit.Core.Test.AdminConsole.AutoFixture;
|
|
||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
using AdminConsoleFixtures = Bit.Core.Test.AdminConsole.AutoFixture;
|
||||||
|
|
||||||
namespace Bit.Core.Test.AdminConsole.Services;
|
namespace Bit.Core.Test.AdminConsole.Services;
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ public class PolicyServicevNextTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Theory, BitAutoData]
|
[Theory, BitAutoData]
|
||||||
public async Task SaveAsync_PolicyDefinitionNotFound_Throws([Policy(PolicyType.SingleOrg)]Policy policy)
|
public async Task SaveAsync_PolicyDefinitionNotFound_Throws([Policy(PolicyType.SingleOrg)] Policy policy)
|
||||||
{
|
{
|
||||||
var sutProvider = SutProviderFactory();
|
var sutProvider = SutProviderFactory();
|
||||||
ArrangeOrganization(sutProvider, policy);
|
ArrangeOrganization(sutProvider, policy);
|
||||||
@ -91,7 +91,7 @@ public class PolicyServicevNextTests
|
|||||||
public async Task SaveAsync_ThrowsOnValidationError([AdminConsoleFixtures.Policy(PolicyType.SingleOrg)] Policy policy)
|
public async Task SaveAsync_ThrowsOnValidationError([AdminConsoleFixtures.Policy(PolicyType.SingleOrg)] Policy policy)
|
||||||
{
|
{
|
||||||
var fakePolicyDefinition = new FakeSingleOrgPolicyDefinition();
|
var fakePolicyDefinition = new FakeSingleOrgPolicyDefinition();
|
||||||
fakePolicyDefinition.ValidateAsyncMock(null, policy).Returns("Validation error!");
|
fakePolicyDefinition.Validate(null, policy).Returns("Validation error!");
|
||||||
var sutProvider = SutProviderFactory([fakePolicyDefinition]);
|
var sutProvider = SutProviderFactory([fakePolicyDefinition]);
|
||||||
|
|
||||||
ArrangeOrganization(sutProvider, policy);
|
ArrangeOrganization(sutProvider, policy);
|
||||||
|
Loading…
Reference in New Issue
Block a user