mirror of
https://github.com/bitwarden/server.git
synced 2025-12-10 00:42:07 -06:00
[PM-24067] Check for unverified bank account in free trial / inactive subscription warning (#6117)
* [NO LOGIC] Move query to core * Check for unverified bank account in free trial and inactive subscription warnings * Run dotnet format * fix test * Run dotnet format * Remove errant file
This commit is contained in:
parent
988b994624
commit
2d1f914eae
@ -3,10 +3,10 @@ using System.Diagnostics;
|
||||
using Bit.Api.AdminConsole.Models.Request.Organizations;
|
||||
using Bit.Api.Billing.Models.Requests;
|
||||
using Bit.Api.Billing.Models.Responses;
|
||||
using Bit.Api.Billing.Queries.Organizations;
|
||||
using Bit.Core.Billing.Enums;
|
||||
using Bit.Core.Billing.Models;
|
||||
using Bit.Core.Billing.Organizations.Models;
|
||||
using Bit.Core.Billing.Organizations.Queries;
|
||||
using Bit.Core.Billing.Organizations.Services;
|
||||
using Bit.Core.Billing.Pricing;
|
||||
using Bit.Core.Billing.Providers.Services;
|
||||
@ -28,7 +28,7 @@ public class OrganizationBillingController(
|
||||
ICurrentContext currentContext,
|
||||
IOrganizationBillingService organizationBillingService,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationWarningsQuery organizationWarningsQuery,
|
||||
IGetOrganizationWarningsQuery getOrganizationWarningsQuery,
|
||||
IPaymentService paymentService,
|
||||
IPricingClient pricingClient,
|
||||
ISubscriberService subscriberService,
|
||||
@ -363,7 +363,7 @@ public class OrganizationBillingController(
|
||||
public async Task<IResult> GetWarningsAsync([FromRoute] Guid organizationId)
|
||||
{
|
||||
/*
|
||||
* We'll keep these available at the User level, because we're hiding any pertinent information and
|
||||
* We'll keep these available at the User level because we're hiding any pertinent information, and
|
||||
* we want to throw as few errors as possible since these are not core features.
|
||||
*/
|
||||
if (!await currentContext.OrganizationUser(organizationId))
|
||||
@ -378,9 +378,9 @@ public class OrganizationBillingController(
|
||||
return Error.NotFound();
|
||||
}
|
||||
|
||||
var response = await organizationWarningsQuery.Run(organization);
|
||||
var warnings = await getOrganizationWarningsQuery.Run(organization);
|
||||
|
||||
return TypedResults.Ok(response);
|
||||
return TypedResults.Ok(warnings);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
using Bit.Api.Billing.Queries.Organizations;
|
||||
|
||||
namespace Bit.Api.Billing;
|
||||
|
||||
public static class Registrations
|
||||
{
|
||||
public static void AddBillingQueries(this IServiceCollection services)
|
||||
{
|
||||
services.AddTransient<IOrganizationWarningsQuery, OrganizationWarningsQuery>();
|
||||
}
|
||||
}
|
||||
@ -27,7 +27,6 @@ using Bit.Core.OrganizationFeatures.OrganizationSubscriptions;
|
||||
using Bit.Core.Tools.Entities;
|
||||
using Bit.Core.Vault.Entities;
|
||||
using Bit.Api.Auth.Models.Request.WebAuthn;
|
||||
using Bit.Api.Billing;
|
||||
using Bit.Core.Auth.Models.Data;
|
||||
using Bit.Core.Auth.Identity.TokenProviders;
|
||||
using Bit.Core.Tools.ImportFeatures;
|
||||
@ -184,7 +183,6 @@ public class Startup
|
||||
services.AddImportServices();
|
||||
services.AddPhishingDomainServices(globalSettings);
|
||||
|
||||
services.AddBillingQueries();
|
||||
services.AddSendServices();
|
||||
|
||||
// Authorization Handlers
|
||||
|
||||
@ -33,6 +33,7 @@ public static class ServiceCollectionExtensions
|
||||
services.AddTransient<IPreviewTaxAmountCommand, PreviewTaxAmountCommand>();
|
||||
services.AddPaymentOperations();
|
||||
services.AddOrganizationLicenseCommandsQueries();
|
||||
services.AddTransient<IGetOrganizationWarningsQuery, GetOrganizationWarningsQuery>();
|
||||
}
|
||||
|
||||
private static void AddOrganizationLicenseCommandsQueries(this IServiceCollection services)
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
#nullable enable
|
||||
namespace Bit.Api.Billing.Models.Responses.Organizations;
|
||||
namespace Bit.Core.Billing.Organizations.Models;
|
||||
|
||||
public record OrganizationWarningsResponse
|
||||
public record OrganizationWarnings
|
||||
{
|
||||
public FreeTrialWarning? FreeTrial { get; set; }
|
||||
public InactiveSubscriptionWarning? InactiveSubscription { get; set; }
|
||||
@ -1,42 +1,44 @@
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
#nullable enable
|
||||
|
||||
using Bit.Api.Billing.Models.Responses.Organizations;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Entities.Provider;
|
||||
using Bit.Core.AdminConsole.Enums.Provider;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.Billing.Caches;
|
||||
using Bit.Core.Billing.Constants;
|
||||
using Bit.Core.Billing.Extensions;
|
||||
using Bit.Core.Billing.Organizations.Models;
|
||||
using Bit.Core.Billing.Services;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Services;
|
||||
using Stripe;
|
||||
using static Bit.Core.Billing.Utilities;
|
||||
using FreeTrialWarning = Bit.Api.Billing.Models.Responses.Organizations.OrganizationWarningsResponse.FreeTrialWarning;
|
||||
using FreeTrialWarning = Bit.Core.Billing.Organizations.Models.OrganizationWarnings.FreeTrialWarning;
|
||||
using InactiveSubscriptionWarning =
|
||||
Bit.Api.Billing.Models.Responses.Organizations.OrganizationWarningsResponse.InactiveSubscriptionWarning;
|
||||
Bit.Core.Billing.Organizations.Models.OrganizationWarnings.InactiveSubscriptionWarning;
|
||||
using ResellerRenewalWarning =
|
||||
Bit.Api.Billing.Models.Responses.Organizations.OrganizationWarningsResponse.ResellerRenewalWarning;
|
||||
Bit.Core.Billing.Organizations.Models.OrganizationWarnings.ResellerRenewalWarning;
|
||||
|
||||
namespace Bit.Api.Billing.Queries.Organizations;
|
||||
namespace Bit.Core.Billing.Organizations.Queries;
|
||||
|
||||
public interface IOrganizationWarningsQuery
|
||||
using static StripeConstants;
|
||||
|
||||
public interface IGetOrganizationWarningsQuery
|
||||
{
|
||||
Task<OrganizationWarningsResponse> Run(
|
||||
Task<OrganizationWarnings> Run(
|
||||
Organization organization);
|
||||
}
|
||||
|
||||
public class OrganizationWarningsQuery(
|
||||
public class GetOrganizationWarningsQuery(
|
||||
ICurrentContext currentContext,
|
||||
IProviderRepository providerRepository,
|
||||
ISetupIntentCache setupIntentCache,
|
||||
IStripeAdapter stripeAdapter,
|
||||
ISubscriberService subscriberService) : IOrganizationWarningsQuery
|
||||
ISubscriberService subscriberService) : IGetOrganizationWarningsQuery
|
||||
{
|
||||
public async Task<OrganizationWarningsResponse> Run(
|
||||
public async Task<OrganizationWarnings> Run(
|
||||
Organization organization)
|
||||
{
|
||||
var response = new OrganizationWarningsResponse();
|
||||
var response = new OrganizationWarnings();
|
||||
|
||||
var subscription =
|
||||
await subscriberService.GetSubscription(organization,
|
||||
@ -69,7 +71,7 @@ public class OrganizationWarningsQuery(
|
||||
|
||||
if (subscription is not
|
||||
{
|
||||
Status: StripeConstants.SubscriptionStatus.Trialing,
|
||||
Status: SubscriptionStatus.Trialing,
|
||||
TrialEnd: not null,
|
||||
Customer: not null
|
||||
})
|
||||
@ -79,10 +81,13 @@ public class OrganizationWarningsQuery(
|
||||
|
||||
var customer = subscription.Customer;
|
||||
|
||||
var hasUnverifiedBankAccount = await HasUnverifiedBankAccount(organization);
|
||||
|
||||
var hasPaymentMethod =
|
||||
!string.IsNullOrEmpty(customer.InvoiceSettings.DefaultPaymentMethodId) ||
|
||||
!string.IsNullOrEmpty(customer.DefaultSourceId) ||
|
||||
customer.Metadata.ContainsKey(StripeConstants.MetadataKeys.BraintreeCustomerId);
|
||||
hasUnverifiedBankAccount ||
|
||||
customer.Metadata.ContainsKey(MetadataKeys.BraintreeCustomerId);
|
||||
|
||||
if (hasPaymentMethod)
|
||||
{
|
||||
@ -101,49 +106,58 @@ public class OrganizationWarningsQuery(
|
||||
Provider? provider,
|
||||
Subscription subscription)
|
||||
{
|
||||
if (organization.Enabled && subscription.Status is StripeConstants.SubscriptionStatus.Trialing)
|
||||
{
|
||||
var isStripeCustomerWithoutPayment =
|
||||
subscription.Customer.InvoiceSettings.DefaultPaymentMethodId is null;
|
||||
var isBraintreeCustomer =
|
||||
subscription.Customer.Metadata.ContainsKey(BraintreeCustomerIdKey);
|
||||
var hasNoPaymentMethod = isStripeCustomerWithoutPayment && !isBraintreeCustomer;
|
||||
var isOrganizationOwner = await currentContext.OrganizationOwner(organization.Id);
|
||||
|
||||
if (hasNoPaymentMethod && await currentContext.OrganizationOwner(organization.Id))
|
||||
{
|
||||
return new InactiveSubscriptionWarning { Resolution = "add_payment_method_optional_trial" };
|
||||
}
|
||||
}
|
||||
|
||||
if (organization.Enabled ||
|
||||
subscription.Status is not StripeConstants.SubscriptionStatus.Unpaid
|
||||
and not StripeConstants.SubscriptionStatus.Canceled)
|
||||
switch (organization.Enabled)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (provider != null)
|
||||
{
|
||||
return new InactiveSubscriptionWarning { Resolution = "contact_provider" };
|
||||
}
|
||||
|
||||
if (await currentContext.OrganizationOwner(organization.Id))
|
||||
{
|
||||
return subscription.Status switch
|
||||
{
|
||||
StripeConstants.SubscriptionStatus.Unpaid => new InactiveSubscriptionWarning
|
||||
// Member of an enabled, trialing organization.
|
||||
case true when subscription.Status is SubscriptionStatus.Trialing:
|
||||
{
|
||||
Resolution = "add_payment_method"
|
||||
},
|
||||
StripeConstants.SubscriptionStatus.Canceled => new InactiveSubscriptionWarning
|
||||
{
|
||||
Resolution = "resubscribe"
|
||||
},
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
var hasUnverifiedBankAccount = await HasUnverifiedBankAccount(organization);
|
||||
|
||||
return new InactiveSubscriptionWarning { Resolution = "contact_owner" };
|
||||
var hasPaymentMethod =
|
||||
!string.IsNullOrEmpty(subscription.Customer.InvoiceSettings.DefaultPaymentMethodId) ||
|
||||
!string.IsNullOrEmpty(subscription.Customer.DefaultSourceId) ||
|
||||
hasUnverifiedBankAccount ||
|
||||
subscription.Customer.Metadata.ContainsKey(MetadataKeys.BraintreeCustomerId);
|
||||
|
||||
// If this member is the owner and there's no payment method on file, ask them to add one.
|
||||
return isOrganizationOwner && !hasPaymentMethod
|
||||
? new InactiveSubscriptionWarning { Resolution = "add_payment_method_optional_trial" }
|
||||
: null;
|
||||
}
|
||||
// Member of disabled and unpaid or canceled organization.
|
||||
case false when subscription.Status is SubscriptionStatus.Unpaid or SubscriptionStatus.Canceled:
|
||||
{
|
||||
// If the organization is managed by a provider, return a warning asking them to contact the provider.
|
||||
if (provider != null)
|
||||
{
|
||||
return new InactiveSubscriptionWarning { Resolution = "contact_provider" };
|
||||
}
|
||||
|
||||
/* If the organization is not managed by a provider and this user is the owner, return an action warning based
|
||||
on the subscription status. */
|
||||
if (isOrganizationOwner)
|
||||
{
|
||||
return subscription.Status switch
|
||||
{
|
||||
SubscriptionStatus.Unpaid => new InactiveSubscriptionWarning
|
||||
{
|
||||
Resolution = "add_payment_method"
|
||||
},
|
||||
SubscriptionStatus.Canceled => new InactiveSubscriptionWarning
|
||||
{
|
||||
Resolution = "resubscribe"
|
||||
},
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
// Otherwise, this member is not the owner, and we need to ask them to contact the owner.
|
||||
return new InactiveSubscriptionWarning { Resolution = "contact_owner" };
|
||||
}
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<ResellerRenewalWarning?> GetResellerRenewalWarning(
|
||||
@ -158,7 +172,7 @@ public class OrganizationWarningsQuery(
|
||||
return null;
|
||||
}
|
||||
|
||||
if (subscription.CollectionMethod != StripeConstants.CollectionMethod.SendInvoice)
|
||||
if (subscription.CollectionMethod != CollectionMethod.SendInvoice)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@ -168,8 +182,8 @@ public class OrganizationWarningsQuery(
|
||||
// ReSharper disable once ConvertIfStatementToSwitchStatement
|
||||
if (subscription is
|
||||
{
|
||||
Status: StripeConstants.SubscriptionStatus.Trialing or StripeConstants.SubscriptionStatus.Active,
|
||||
LatestInvoice: null or { Status: StripeConstants.InvoiceStatus.Paid }
|
||||
Status: SubscriptionStatus.Trialing or SubscriptionStatus.Active,
|
||||
LatestInvoice: null or { Status: InvoiceStatus.Paid }
|
||||
} && (subscription.CurrentPeriodEnd - now).TotalDays <= 14)
|
||||
{
|
||||
return new ResellerRenewalWarning
|
||||
@ -184,8 +198,8 @@ public class OrganizationWarningsQuery(
|
||||
|
||||
if (subscription is
|
||||
{
|
||||
Status: StripeConstants.SubscriptionStatus.Active,
|
||||
LatestInvoice: { Status: StripeConstants.InvoiceStatus.Open, DueDate: not null }
|
||||
Status: SubscriptionStatus.Active,
|
||||
LatestInvoice: { Status: InvoiceStatus.Open, DueDate: not null }
|
||||
} && subscription.LatestInvoice.DueDate > now)
|
||||
{
|
||||
return new ResellerRenewalWarning
|
||||
@ -200,7 +214,7 @@ public class OrganizationWarningsQuery(
|
||||
}
|
||||
|
||||
// ReSharper disable once InvertIf
|
||||
if (subscription.Status == StripeConstants.SubscriptionStatus.PastDue)
|
||||
if (subscription.Status == SubscriptionStatus.PastDue)
|
||||
{
|
||||
var openInvoices = await stripeAdapter.InvoiceSearchAsync(new InvoiceSearchOptions
|
||||
{
|
||||
@ -226,4 +240,22 @@ public class OrganizationWarningsQuery(
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<bool> HasUnverifiedBankAccount(
|
||||
Organization organization)
|
||||
{
|
||||
var setupIntentId = await setupIntentCache.Get(organization.Id);
|
||||
|
||||
if (string.IsNullOrEmpty(setupIntentId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var setupIntent = await stripeAdapter.SetupIntentGet(setupIntentId, new SetupIntentGetOptions
|
||||
{
|
||||
Expand = ["payment_method"]
|
||||
});
|
||||
|
||||
return setupIntent.IsUnverifiedBankAccount();
|
||||
}
|
||||
}
|
||||
@ -14,7 +14,7 @@ using NSubstitute;
|
||||
using Xunit;
|
||||
using JsonSerializer = System.Text.Json.JsonSerializer;
|
||||
|
||||
namespace Bit.Core.Test.Billing.OrganizationFeatures.OrganizationLicenses;
|
||||
namespace Bit.Core.Test.Billing.Organizations.Commands;
|
||||
|
||||
[SutProviderCustomize]
|
||||
public class UpdateOrganizationLicenseCommandTests
|
||||
@ -18,7 +18,7 @@ using NSubstitute.ReturnsExtensions;
|
||||
using Stripe;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Core.Test.Billing.OrganizationFeatures.OrganizationLicenses;
|
||||
namespace Bit.Core.Test.Billing.Organizations.Queries;
|
||||
|
||||
[SubscriptionInfoCustomize]
|
||||
[OrganizationLicenseCustomize]
|
||||
@ -1,12 +1,13 @@
|
||||
using Bit.Api.Billing.Queries.Organizations;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Entities.Provider;
|
||||
using Bit.Core.AdminConsole.Enums.Provider;
|
||||
using Bit.Core.AdminConsole.Repositories;
|
||||
using Bit.Core.Billing.Caches;
|
||||
using Bit.Core.Billing.Constants;
|
||||
using Bit.Core.Billing.Organizations.Queries;
|
||||
using Bit.Core.Billing.Services;
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using NSubstitute;
|
||||
@ -15,17 +16,17 @@ using Stripe;
|
||||
using Stripe.TestHelpers;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Api.Test.Billing.Queries.Organizations;
|
||||
namespace Bit.Core.Test.Billing.Organizations.Queries;
|
||||
|
||||
[SutProviderCustomize]
|
||||
public class OrganizationWarningsQueryTests
|
||||
public class GetOrganizationWarningsQueryTests
|
||||
{
|
||||
private static readonly string[] _requiredExpansions = ["customer", "latest_invoice", "test_clock"];
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Run_NoSubscription_NoWarnings(
|
||||
Organization organization,
|
||||
SutProvider<OrganizationWarningsQuery> sutProvider)
|
||||
SutProvider<GetOrganizationWarningsQuery> sutProvider)
|
||||
{
|
||||
sutProvider.GetDependency<ISubscriberService>()
|
||||
.GetSubscription(organization, Arg.Is<SubscriptionGetOptions>(options =>
|
||||
@ -46,7 +47,7 @@ public class OrganizationWarningsQueryTests
|
||||
[Theory, BitAutoData]
|
||||
public async Task Run_Has_FreeTrialWarning(
|
||||
Organization organization,
|
||||
SutProvider<OrganizationWarningsQuery> sutProvider)
|
||||
SutProvider<GetOrganizationWarningsQuery> sutProvider)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
@ -70,6 +71,7 @@ public class OrganizationWarningsQueryTests
|
||||
});
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().EditSubscription(organization.Id).Returns(true);
|
||||
sutProvider.GetDependency<ISetupIntentCache>().Get(organization.Id).Returns((string?)null);
|
||||
|
||||
var response = await sutProvider.Sut.Run(organization);
|
||||
|
||||
@ -79,10 +81,90 @@ public class OrganizationWarningsQueryTests
|
||||
});
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Run_Has_FreeTrialWarning_WithUnverifiedBankAccount_NoWarning(
|
||||
Organization organization,
|
||||
SutProvider<GetOrganizationWarningsQuery> sutProvider)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
const string setupIntentId = "setup_intent_id";
|
||||
|
||||
sutProvider.GetDependency<ISubscriberService>()
|
||||
.GetSubscription(organization, Arg.Is<SubscriptionGetOptions>(options =>
|
||||
options.Expand.SequenceEqual(_requiredExpansions)
|
||||
))
|
||||
.Returns(new Subscription
|
||||
{
|
||||
Status = StripeConstants.SubscriptionStatus.Trialing,
|
||||
TrialEnd = now.AddDays(7),
|
||||
Customer = new Customer
|
||||
{
|
||||
InvoiceSettings = new CustomerInvoiceSettings(),
|
||||
Metadata = new Dictionary<string, string>()
|
||||
},
|
||||
TestClock = new TestClock
|
||||
{
|
||||
FrozenTime = now
|
||||
}
|
||||
});
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().EditSubscription(organization.Id).Returns(true);
|
||||
sutProvider.GetDependency<ISetupIntentCache>().Get(organization.Id).Returns(setupIntentId);
|
||||
sutProvider.GetDependency<IStripeAdapter>().SetupIntentGet(setupIntentId, Arg.Is<SetupIntentGetOptions>(
|
||||
options => options.Expand.Contains("payment_method"))).Returns(new SetupIntent
|
||||
{
|
||||
Status = "requires_action",
|
||||
NextAction = new SetupIntentNextAction
|
||||
{
|
||||
VerifyWithMicrodeposits = new SetupIntentNextActionVerifyWithMicrodeposits()
|
||||
},
|
||||
PaymentMethod = new PaymentMethod
|
||||
{
|
||||
UsBankAccount = new PaymentMethodUsBankAccount()
|
||||
}
|
||||
});
|
||||
|
||||
var response = await sutProvider.Sut.Run(organization);
|
||||
|
||||
Assert.Null(response.FreeTrial);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Run_Has_InactiveSubscriptionWarning_AddPaymentMethodOptionalTrial(
|
||||
Organization organization,
|
||||
SutProvider<GetOrganizationWarningsQuery> sutProvider)
|
||||
{
|
||||
organization.Enabled = true;
|
||||
|
||||
sutProvider.GetDependency<ISubscriberService>()
|
||||
.GetSubscription(organization, Arg.Is<SubscriptionGetOptions>(options =>
|
||||
options.Expand.SequenceEqual(_requiredExpansions)
|
||||
))
|
||||
.Returns(new Subscription
|
||||
{
|
||||
Status = StripeConstants.SubscriptionStatus.Trialing,
|
||||
Customer = new Customer
|
||||
{
|
||||
InvoiceSettings = new CustomerInvoiceSettings(),
|
||||
Metadata = new Dictionary<string, string>()
|
||||
}
|
||||
});
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().OrganizationOwner(organization.Id).Returns(true);
|
||||
sutProvider.GetDependency<ISetupIntentCache>().Get(organization.Id).Returns((string?)null);
|
||||
|
||||
var response = await sutProvider.Sut.Run(organization);
|
||||
|
||||
Assert.True(response is
|
||||
{
|
||||
InactiveSubscription.Resolution: "add_payment_method_optional_trial"
|
||||
});
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task Run_Has_InactiveSubscriptionWarning_ContactProvider(
|
||||
Organization organization,
|
||||
SutProvider<OrganizationWarningsQuery> sutProvider)
|
||||
SutProvider<GetOrganizationWarningsQuery> sutProvider)
|
||||
{
|
||||
organization.Enabled = false;
|
||||
|
||||
@ -109,7 +191,7 @@ public class OrganizationWarningsQueryTests
|
||||
[Theory, BitAutoData]
|
||||
public async Task Run_Has_InactiveSubscriptionWarning_AddPaymentMethod(
|
||||
Organization organization,
|
||||
SutProvider<OrganizationWarningsQuery> sutProvider)
|
||||
SutProvider<GetOrganizationWarningsQuery> sutProvider)
|
||||
{
|
||||
organization.Enabled = false;
|
||||
|
||||
@ -135,7 +217,7 @@ public class OrganizationWarningsQueryTests
|
||||
[Theory, BitAutoData]
|
||||
public async Task Run_Has_InactiveSubscriptionWarning_Resubscribe(
|
||||
Organization organization,
|
||||
SutProvider<OrganizationWarningsQuery> sutProvider)
|
||||
SutProvider<GetOrganizationWarningsQuery> sutProvider)
|
||||
{
|
||||
organization.Enabled = false;
|
||||
|
||||
@ -161,7 +243,7 @@ public class OrganizationWarningsQueryTests
|
||||
[Theory, BitAutoData]
|
||||
public async Task Run_Has_InactiveSubscriptionWarning_ContactOwner(
|
||||
Organization organization,
|
||||
SutProvider<OrganizationWarningsQuery> sutProvider)
|
||||
SutProvider<GetOrganizationWarningsQuery> sutProvider)
|
||||
{
|
||||
organization.Enabled = false;
|
||||
|
||||
@ -187,7 +269,7 @@ public class OrganizationWarningsQueryTests
|
||||
[Theory, BitAutoData]
|
||||
public async Task Run_Has_ResellerRenewalWarning_Upcoming(
|
||||
Organization organization,
|
||||
SutProvider<OrganizationWarningsQuery> sutProvider)
|
||||
SutProvider<GetOrganizationWarningsQuery> sutProvider)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
@ -225,7 +307,7 @@ public class OrganizationWarningsQueryTests
|
||||
[Theory, BitAutoData]
|
||||
public async Task Run_Has_ResellerRenewalWarning_Issued(
|
||||
Organization organization,
|
||||
SutProvider<OrganizationWarningsQuery> sutProvider)
|
||||
SutProvider<GetOrganizationWarningsQuery> sutProvider)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
@ -269,7 +351,7 @@ public class OrganizationWarningsQueryTests
|
||||
[Theory, BitAutoData]
|
||||
public async Task Run_Has_ResellerRenewalWarning_PastDue(
|
||||
Organization organization,
|
||||
SutProvider<OrganizationWarningsQuery> sutProvider)
|
||||
SutProvider<GetOrganizationWarningsQuery> sutProvider)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
@ -12,7 +12,7 @@ using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using Bit.Test.Common.Helpers;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Core.Test.Billing.OrganizationFeatures.OrganizationLicenses;
|
||||
namespace Bit.Core.Test.Billing.Organizations.Queries;
|
||||
|
||||
[SutProviderCustomize]
|
||||
public class GetSelfHostedOrganizationLicenseQueryTests
|
||||
Loading…
x
Reference in New Issue
Block a user