mirror of
https://github.com/bitwarden/server.git
synced 2025-04-05 13:08:17 -05:00
[PM-12490] Extract OrganizationService.EnableAsync into commands (#5321)
* Add organization enable command implementation * Add unit tests for OrganizationEnableCommand * Add organization enable command registration for dependency injection * Refactor payment and subscription handlers to use IOrganizationEnableCommand for organization enabling * Remove EnableAsync methods from IOrganizationService and OrganizationService * Add xmldoc to IOrganizationEnableCommand * Refactor OrganizationEnableCommand to consolidate enable logic and add optional expiration
This commit is contained in:
parent
f4341b2f3b
commit
f4c37df883
@ -1,4 +1,5 @@
|
|||||||
using Bit.Billing.Constants;
|
using Bit.Billing.Constants;
|
||||||
|
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations.Interfaces;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
@ -17,7 +18,6 @@ public class PaymentSucceededHandler : IPaymentSucceededHandler
|
|||||||
{
|
{
|
||||||
private readonly ILogger<PaymentSucceededHandler> _logger;
|
private readonly ILogger<PaymentSucceededHandler> _logger;
|
||||||
private readonly IStripeEventService _stripeEventService;
|
private readonly IStripeEventService _stripeEventService;
|
||||||
private readonly IOrganizationService _organizationService;
|
|
||||||
private readonly IUserService _userService;
|
private readonly IUserService _userService;
|
||||||
private readonly IStripeFacade _stripeFacade;
|
private readonly IStripeFacade _stripeFacade;
|
||||||
private readonly IProviderRepository _providerRepository;
|
private readonly IProviderRepository _providerRepository;
|
||||||
@ -27,6 +27,7 @@ public class PaymentSucceededHandler : IPaymentSucceededHandler
|
|||||||
private readonly IUserRepository _userRepository;
|
private readonly IUserRepository _userRepository;
|
||||||
private readonly IStripeEventUtilityService _stripeEventUtilityService;
|
private readonly IStripeEventUtilityService _stripeEventUtilityService;
|
||||||
private readonly IPushNotificationService _pushNotificationService;
|
private readonly IPushNotificationService _pushNotificationService;
|
||||||
|
private readonly IOrganizationEnableCommand _organizationEnableCommand;
|
||||||
|
|
||||||
public PaymentSucceededHandler(
|
public PaymentSucceededHandler(
|
||||||
ILogger<PaymentSucceededHandler> logger,
|
ILogger<PaymentSucceededHandler> logger,
|
||||||
@ -39,8 +40,8 @@ public class PaymentSucceededHandler : IPaymentSucceededHandler
|
|||||||
IUserRepository userRepository,
|
IUserRepository userRepository,
|
||||||
IStripeEventUtilityService stripeEventUtilityService,
|
IStripeEventUtilityService stripeEventUtilityService,
|
||||||
IUserService userService,
|
IUserService userService,
|
||||||
IOrganizationService organizationService,
|
IPushNotificationService pushNotificationService,
|
||||||
IPushNotificationService pushNotificationService)
|
IOrganizationEnableCommand organizationEnableCommand)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_stripeEventService = stripeEventService;
|
_stripeEventService = stripeEventService;
|
||||||
@ -52,8 +53,8 @@ public class PaymentSucceededHandler : IPaymentSucceededHandler
|
|||||||
_userRepository = userRepository;
|
_userRepository = userRepository;
|
||||||
_stripeEventUtilityService = stripeEventUtilityService;
|
_stripeEventUtilityService = stripeEventUtilityService;
|
||||||
_userService = userService;
|
_userService = userService;
|
||||||
_organizationService = organizationService;
|
|
||||||
_pushNotificationService = pushNotificationService;
|
_pushNotificationService = pushNotificationService;
|
||||||
|
_organizationEnableCommand = organizationEnableCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -142,7 +143,7 @@ public class PaymentSucceededHandler : IPaymentSucceededHandler
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _organizationService.EnableAsync(organizationId.Value, subscription.CurrentPeriodEnd);
|
await _organizationEnableCommand.EnableAsync(organizationId.Value, subscription.CurrentPeriodEnd);
|
||||||
var organization = await _organizationRepository.GetByIdAsync(organizationId.Value);
|
var organization = await _organizationRepository.GetByIdAsync(organizationId.Value);
|
||||||
await _pushNotificationService.PushSyncOrganizationStatusAsync(organization);
|
await _pushNotificationService.PushSyncOrganizationStatusAsync(organization);
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using Bit.Billing.Constants;
|
using Bit.Billing.Constants;
|
||||||
using Bit.Billing.Jobs;
|
using Bit.Billing.Jobs;
|
||||||
using Bit.Core;
|
using Bit.Core;
|
||||||
|
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations.Interfaces;
|
||||||
using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces;
|
using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces;
|
||||||
using Bit.Core.Platform.Push;
|
using Bit.Core.Platform.Push;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
@ -24,6 +25,7 @@ public class SubscriptionUpdatedHandler : ISubscriptionUpdatedHandler
|
|||||||
private readonly IOrganizationRepository _organizationRepository;
|
private readonly IOrganizationRepository _organizationRepository;
|
||||||
private readonly ISchedulerFactory _schedulerFactory;
|
private readonly ISchedulerFactory _schedulerFactory;
|
||||||
private readonly IFeatureService _featureService;
|
private readonly IFeatureService _featureService;
|
||||||
|
private readonly IOrganizationEnableCommand _organizationEnableCommand;
|
||||||
|
|
||||||
public SubscriptionUpdatedHandler(
|
public SubscriptionUpdatedHandler(
|
||||||
IStripeEventService stripeEventService,
|
IStripeEventService stripeEventService,
|
||||||
@ -35,7 +37,8 @@ public class SubscriptionUpdatedHandler : ISubscriptionUpdatedHandler
|
|||||||
IPushNotificationService pushNotificationService,
|
IPushNotificationService pushNotificationService,
|
||||||
IOrganizationRepository organizationRepository,
|
IOrganizationRepository organizationRepository,
|
||||||
ISchedulerFactory schedulerFactory,
|
ISchedulerFactory schedulerFactory,
|
||||||
IFeatureService featureService)
|
IFeatureService featureService,
|
||||||
|
IOrganizationEnableCommand organizationEnableCommand)
|
||||||
{
|
{
|
||||||
_stripeEventService = stripeEventService;
|
_stripeEventService = stripeEventService;
|
||||||
_stripeEventUtilityService = stripeEventUtilityService;
|
_stripeEventUtilityService = stripeEventUtilityService;
|
||||||
@ -47,6 +50,7 @@ public class SubscriptionUpdatedHandler : ISubscriptionUpdatedHandler
|
|||||||
_organizationRepository = organizationRepository;
|
_organizationRepository = organizationRepository;
|
||||||
_schedulerFactory = schedulerFactory;
|
_schedulerFactory = schedulerFactory;
|
||||||
_featureService = featureService;
|
_featureService = featureService;
|
||||||
|
_organizationEnableCommand = organizationEnableCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -90,7 +94,7 @@ public class SubscriptionUpdatedHandler : ISubscriptionUpdatedHandler
|
|||||||
}
|
}
|
||||||
case StripeSubscriptionStatus.Active when organizationId.HasValue:
|
case StripeSubscriptionStatus.Active when organizationId.HasValue:
|
||||||
{
|
{
|
||||||
await _organizationService.EnableAsync(organizationId.Value);
|
await _organizationEnableCommand.EnableAsync(organizationId.Value);
|
||||||
var organization = await _organizationRepository.GetByIdAsync(organizationId.Value);
|
var organization = await _organizationRepository.GetByIdAsync(organizationId.Value);
|
||||||
await _pushNotificationService.PushSyncOrganizationStatusAsync(organization);
|
await _pushNotificationService.PushSyncOrganizationStatusAsync(organization);
|
||||||
break;
|
break;
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
namespace Bit.Core.AdminConsole.OrganizationFeatures.Organizations.Interfaces;
|
||||||
|
|
||||||
|
public interface IOrganizationEnableCommand
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Enables an organization that is currently disabled and has a gateway configured.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="organizationId">The unique identifier of the organization to enable.</param>
|
||||||
|
/// <param name="expirationDate">When provided, sets the date the organization's subscription will expire. If not provided, no expiration date will be set.</param>
|
||||||
|
Task EnableAsync(Guid organizationId, DateTime? expirationDate = null);
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations.Interfaces;
|
||||||
|
using Bit.Core.Repositories;
|
||||||
|
using Bit.Core.Services;
|
||||||
|
|
||||||
|
namespace Bit.Core.AdminConsole.OrganizationFeatures.Organizations;
|
||||||
|
|
||||||
|
public class OrganizationEnableCommand : IOrganizationEnableCommand
|
||||||
|
{
|
||||||
|
private readonly IApplicationCacheService _applicationCacheService;
|
||||||
|
private readonly IOrganizationRepository _organizationRepository;
|
||||||
|
|
||||||
|
public OrganizationEnableCommand(
|
||||||
|
IApplicationCacheService applicationCacheService,
|
||||||
|
IOrganizationRepository organizationRepository)
|
||||||
|
{
|
||||||
|
_applicationCacheService = applicationCacheService;
|
||||||
|
_organizationRepository = organizationRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task EnableAsync(Guid organizationId, DateTime? expirationDate = null)
|
||||||
|
{
|
||||||
|
var organization = await _organizationRepository.GetByIdAsync(organizationId);
|
||||||
|
if (organization is null || organization.Enabled || expirationDate is not null && organization.Gateway is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
organization.Enabled = true;
|
||||||
|
|
||||||
|
if (expirationDate is not null && organization.Gateway is not null)
|
||||||
|
{
|
||||||
|
organization.ExpirationDate = expirationDate;
|
||||||
|
organization.RevisionDate = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
await _organizationRepository.ReplaceAsync(organization);
|
||||||
|
await _applicationCacheService.UpsertOrganizationAbilityAsync(organization);
|
||||||
|
}
|
||||||
|
}
|
@ -28,10 +28,8 @@ public interface IOrganizationService
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Task<(Organization organization, OrganizationUser organizationUser)> SignUpAsync(OrganizationLicense license, User owner,
|
Task<(Organization organization, OrganizationUser organizationUser)> SignUpAsync(OrganizationLicense license, User owner,
|
||||||
string ownerKey, string collectionName, string publicKey, string privateKey);
|
string ownerKey, string collectionName, string publicKey, string privateKey);
|
||||||
Task EnableAsync(Guid organizationId, DateTime? expirationDate);
|
|
||||||
Task DisableAsync(Guid organizationId, DateTime? expirationDate);
|
Task DisableAsync(Guid organizationId, DateTime? expirationDate);
|
||||||
Task UpdateExpirationDateAsync(Guid organizationId, DateTime? expirationDate);
|
Task UpdateExpirationDateAsync(Guid organizationId, DateTime? expirationDate);
|
||||||
Task EnableAsync(Guid organizationId);
|
|
||||||
Task UpdateAsync(Organization organization, bool updateBilling = false, EventType eventType = EventType.Organization_Updated);
|
Task UpdateAsync(Organization organization, bool updateBilling = false, EventType eventType = EventType.Organization_Updated);
|
||||||
Task UpdateTwoFactorProviderAsync(Organization organization, TwoFactorProviderType type);
|
Task UpdateTwoFactorProviderAsync(Organization organization, TwoFactorProviderType type);
|
||||||
Task DisableTwoFactorProviderAsync(Organization organization, TwoFactorProviderType type);
|
Task DisableTwoFactorProviderAsync(Organization organization, TwoFactorProviderType type);
|
||||||
|
@ -686,18 +686,6 @@ public class OrganizationService : IOrganizationService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task EnableAsync(Guid organizationId, DateTime? expirationDate)
|
|
||||||
{
|
|
||||||
var org = await GetOrgById(organizationId);
|
|
||||||
if (org != null && !org.Enabled && org.Gateway.HasValue)
|
|
||||||
{
|
|
||||||
org.Enabled = true;
|
|
||||||
org.ExpirationDate = expirationDate;
|
|
||||||
org.RevisionDate = DateTime.UtcNow;
|
|
||||||
await ReplaceAndUpdateCacheAsync(org);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DisableAsync(Guid organizationId, DateTime? expirationDate)
|
public async Task DisableAsync(Guid organizationId, DateTime? expirationDate)
|
||||||
{
|
{
|
||||||
var org = await GetOrgById(organizationId);
|
var org = await GetOrgById(organizationId);
|
||||||
@ -723,16 +711,6 @@ public class OrganizationService : IOrganizationService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task EnableAsync(Guid organizationId)
|
|
||||||
{
|
|
||||||
var org = await GetOrgById(organizationId);
|
|
||||||
if (org != null && !org.Enabled)
|
|
||||||
{
|
|
||||||
org.Enabled = true;
|
|
||||||
await ReplaceAndUpdateCacheAsync(org);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task UpdateAsync(Organization organization, bool updateBilling = false, EventType eventType = EventType.Organization_Updated)
|
public async Task UpdateAsync(Organization organization, bool updateBilling = false, EventType eventType = EventType.Organization_Updated)
|
||||||
{
|
{
|
||||||
if (organization.Id == default(Guid))
|
if (organization.Id == default(Guid))
|
||||||
|
@ -54,6 +54,7 @@ public static class OrganizationServiceCollectionExtensions
|
|||||||
services.AddOrganizationDomainCommandsQueries();
|
services.AddOrganizationDomainCommandsQueries();
|
||||||
services.AddOrganizationSignUpCommands();
|
services.AddOrganizationSignUpCommands();
|
||||||
services.AddOrganizationDeleteCommands();
|
services.AddOrganizationDeleteCommands();
|
||||||
|
services.AddOrganizationEnableCommands();
|
||||||
services.AddOrganizationAuthCommands();
|
services.AddOrganizationAuthCommands();
|
||||||
services.AddOrganizationUserCommands();
|
services.AddOrganizationUserCommands();
|
||||||
services.AddOrganizationUserCommandsQueries();
|
services.AddOrganizationUserCommandsQueries();
|
||||||
@ -69,6 +70,9 @@ public static class OrganizationServiceCollectionExtensions
|
|||||||
services.AddScoped<IOrganizationInitiateDeleteCommand, OrganizationInitiateDeleteCommand>();
|
services.AddScoped<IOrganizationInitiateDeleteCommand, OrganizationInitiateDeleteCommand>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void AddOrganizationEnableCommands(this IServiceCollection services) =>
|
||||||
|
services.AddScoped<IOrganizationEnableCommand, OrganizationEnableCommand>();
|
||||||
|
|
||||||
private static void AddOrganizationConnectionCommands(this IServiceCollection services)
|
private static void AddOrganizationConnectionCommands(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddScoped<ICreateOrganizationConnectionCommand, CreateOrganizationConnectionCommand>();
|
services.AddScoped<ICreateOrganizationConnectionCommand, CreateOrganizationConnectionCommand>();
|
||||||
|
@ -0,0 +1,147 @@
|
|||||||
|
using Bit.Core.AdminConsole.Entities;
|
||||||
|
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Repositories;
|
||||||
|
using Bit.Core.Services;
|
||||||
|
using Bit.Test.Common.AutoFixture;
|
||||||
|
using Bit.Test.Common.AutoFixture.Attributes;
|
||||||
|
using NSubstitute;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.Organizations;
|
||||||
|
|
||||||
|
[SutProviderCustomize]
|
||||||
|
public class OrganizationEnableCommandTests
|
||||||
|
{
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task EnableAsync_WhenOrganizationDoesNotExist_DoesNothing(
|
||||||
|
Guid organizationId,
|
||||||
|
SutProvider<OrganizationEnableCommand> sutProvider)
|
||||||
|
{
|
||||||
|
sutProvider.GetDependency<IOrganizationRepository>()
|
||||||
|
.GetByIdAsync(organizationId)
|
||||||
|
.Returns((Organization)null);
|
||||||
|
|
||||||
|
await sutProvider.Sut.EnableAsync(organizationId);
|
||||||
|
|
||||||
|
await sutProvider.GetDependency<IOrganizationRepository>()
|
||||||
|
.DidNotReceive()
|
||||||
|
.ReplaceAsync(Arg.Any<Organization>());
|
||||||
|
await sutProvider.GetDependency<IApplicationCacheService>()
|
||||||
|
.DidNotReceive()
|
||||||
|
.UpsertOrganizationAbilityAsync(Arg.Any<Organization>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task EnableAsync_WhenOrganizationAlreadyEnabled_DoesNothing(
|
||||||
|
Organization organization,
|
||||||
|
SutProvider<OrganizationEnableCommand> sutProvider)
|
||||||
|
{
|
||||||
|
organization.Enabled = true;
|
||||||
|
sutProvider.GetDependency<IOrganizationRepository>()
|
||||||
|
.GetByIdAsync(organization.Id)
|
||||||
|
.Returns(organization);
|
||||||
|
|
||||||
|
await sutProvider.Sut.EnableAsync(organization.Id);
|
||||||
|
|
||||||
|
await sutProvider.GetDependency<IOrganizationRepository>()
|
||||||
|
.DidNotReceive()
|
||||||
|
.ReplaceAsync(Arg.Any<Organization>());
|
||||||
|
await sutProvider.GetDependency<IApplicationCacheService>()
|
||||||
|
.DidNotReceive()
|
||||||
|
.UpsertOrganizationAbilityAsync(Arg.Any<Organization>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task EnableAsync_WhenOrganizationDisabled_EnablesAndSaves(
|
||||||
|
Organization organization,
|
||||||
|
SutProvider<OrganizationEnableCommand> sutProvider)
|
||||||
|
{
|
||||||
|
organization.Enabled = false;
|
||||||
|
sutProvider.GetDependency<IOrganizationRepository>()
|
||||||
|
.GetByIdAsync(organization.Id)
|
||||||
|
.Returns(organization);
|
||||||
|
|
||||||
|
await sutProvider.Sut.EnableAsync(organization.Id);
|
||||||
|
|
||||||
|
Assert.True(organization.Enabled);
|
||||||
|
await sutProvider.GetDependency<IOrganizationRepository>()
|
||||||
|
.Received(1)
|
||||||
|
.ReplaceAsync(organization);
|
||||||
|
await sutProvider.GetDependency<IApplicationCacheService>()
|
||||||
|
.Received(1)
|
||||||
|
.UpsertOrganizationAbilityAsync(organization);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task EnableAsync_WithExpiration_WhenOrganizationHasNoGateway_DoesNothing(
|
||||||
|
Organization organization,
|
||||||
|
DateTime expirationDate,
|
||||||
|
SutProvider<OrganizationEnableCommand> sutProvider)
|
||||||
|
{
|
||||||
|
organization.Enabled = false;
|
||||||
|
organization.Gateway = null;
|
||||||
|
sutProvider.GetDependency<IOrganizationRepository>()
|
||||||
|
.GetByIdAsync(organization.Id)
|
||||||
|
.Returns(organization);
|
||||||
|
|
||||||
|
await sutProvider.Sut.EnableAsync(organization.Id, expirationDate);
|
||||||
|
|
||||||
|
await sutProvider.GetDependency<IOrganizationRepository>()
|
||||||
|
.DidNotReceive()
|
||||||
|
.ReplaceAsync(Arg.Any<Organization>());
|
||||||
|
await sutProvider.GetDependency<IApplicationCacheService>()
|
||||||
|
.DidNotReceive()
|
||||||
|
.UpsertOrganizationAbilityAsync(Arg.Any<Organization>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task EnableAsync_WithExpiration_WhenValid_EnablesAndSetsExpiration(
|
||||||
|
Organization organization,
|
||||||
|
DateTime expirationDate,
|
||||||
|
SutProvider<OrganizationEnableCommand> sutProvider)
|
||||||
|
{
|
||||||
|
organization.Enabled = false;
|
||||||
|
organization.Gateway = GatewayType.Stripe;
|
||||||
|
organization.RevisionDate = DateTime.UtcNow.AddDays(-1);
|
||||||
|
var originalRevisionDate = organization.RevisionDate;
|
||||||
|
sutProvider.GetDependency<IOrganizationRepository>()
|
||||||
|
.GetByIdAsync(organization.Id)
|
||||||
|
.Returns(organization);
|
||||||
|
|
||||||
|
await sutProvider.Sut.EnableAsync(organization.Id, expirationDate);
|
||||||
|
|
||||||
|
Assert.True(organization.Enabled);
|
||||||
|
Assert.Equal(expirationDate, organization.ExpirationDate);
|
||||||
|
Assert.True(organization.RevisionDate > originalRevisionDate);
|
||||||
|
await sutProvider.GetDependency<IOrganizationRepository>()
|
||||||
|
.Received(1)
|
||||||
|
.ReplaceAsync(organization);
|
||||||
|
await sutProvider.GetDependency<IApplicationCacheService>()
|
||||||
|
.Received(1)
|
||||||
|
.UpsertOrganizationAbilityAsync(organization);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task EnableAsync_WithoutExpiration_DoesNotUpdateRevisionDate(
|
||||||
|
Organization organization,
|
||||||
|
SutProvider<OrganizationEnableCommand> sutProvider)
|
||||||
|
{
|
||||||
|
organization.Enabled = false;
|
||||||
|
var originalRevisionDate = organization.RevisionDate;
|
||||||
|
sutProvider.GetDependency<IOrganizationRepository>()
|
||||||
|
.GetByIdAsync(organization.Id)
|
||||||
|
.Returns(organization);
|
||||||
|
|
||||||
|
await sutProvider.Sut.EnableAsync(organization.Id);
|
||||||
|
|
||||||
|
Assert.True(organization.Enabled);
|
||||||
|
Assert.Equal(originalRevisionDate, organization.RevisionDate);
|
||||||
|
await sutProvider.GetDependency<IOrganizationRepository>()
|
||||||
|
.Received(1)
|
||||||
|
.ReplaceAsync(organization);
|
||||||
|
await sutProvider.GetDependency<IApplicationCacheService>()
|
||||||
|
.Received(1)
|
||||||
|
.UpsertOrganizationAbilityAsync(organization);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user