mirror of
https://github.com/bitwarden/server.git
synced 2025-05-23 04:21:05 -05:00
Merge branch 'main' into ac/pm-18238/add-requiretwofactorpolicyrequirement
This commit is contained in:
commit
b20acfe99e
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@ -636,7 +636,9 @@ jobs:
|
|||||||
|
|
||||||
setup-ephemeral-environment:
|
setup-ephemeral-environment:
|
||||||
name: Setup Ephemeral Environment
|
name: Setup Ephemeral Environment
|
||||||
needs: build-docker
|
needs:
|
||||||
|
- build-artifacts
|
||||||
|
- build-docker
|
||||||
if: |
|
if: |
|
||||||
needs.build-artifacts.outputs.has_secrets == 'true'
|
needs.build-artifacts.outputs.has_secrets == 'true'
|
||||||
&& github.event_name == 'pull_request'
|
&& github.event_name == 'pull_request'
|
||||||
|
@ -3,9 +3,9 @@ using Bit.Core.AdminConsole.Enums.Provider;
|
|||||||
using Bit.Core.AdminConsole.Providers.Interfaces;
|
using Bit.Core.AdminConsole.Providers.Interfaces;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.AdminConsole.Services;
|
using Bit.Core.AdminConsole.Services;
|
||||||
using Bit.Core.Billing.Entities;
|
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
|
@ -7,6 +7,7 @@ using Bit.Core.AdminConsole.Repositories;
|
|||||||
using Bit.Core.Billing.Constants;
|
using Bit.Core.Billing.Constants;
|
||||||
using Bit.Core.Billing.Extensions;
|
using Bit.Core.Billing.Extensions;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Services;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
|
@ -5,12 +5,13 @@ using Bit.Core.AdminConsole.Entities.Provider;
|
|||||||
using Bit.Core.AdminConsole.Enums.Provider;
|
using Bit.Core.AdminConsole.Enums.Provider;
|
||||||
using Bit.Core.AdminConsole.Models.Business.Provider;
|
using Bit.Core.AdminConsole.Models.Business.Provider;
|
||||||
using Bit.Core.AdminConsole.Models.Business.Tokenables;
|
using Bit.Core.AdminConsole.Models.Business.Tokenables;
|
||||||
|
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.AdminConsole.Services;
|
using Bit.Core.AdminConsole.Services;
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Models;
|
using Bit.Core.Billing.Models;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
@ -53,6 +54,7 @@ public class ProviderService : IProviderService
|
|||||||
private readonly IApplicationCacheService _applicationCacheService;
|
private readonly IApplicationCacheService _applicationCacheService;
|
||||||
private readonly IProviderBillingService _providerBillingService;
|
private readonly IProviderBillingService _providerBillingService;
|
||||||
private readonly IPricingClient _pricingClient;
|
private readonly IPricingClient _pricingClient;
|
||||||
|
private readonly IProviderClientOrganizationSignUpCommand _providerClientOrganizationSignUpCommand;
|
||||||
|
|
||||||
public ProviderService(IProviderRepository providerRepository, IProviderUserRepository providerUserRepository,
|
public ProviderService(IProviderRepository providerRepository, IProviderUserRepository providerUserRepository,
|
||||||
IProviderOrganizationRepository providerOrganizationRepository, IUserRepository userRepository,
|
IProviderOrganizationRepository providerOrganizationRepository, IUserRepository userRepository,
|
||||||
@ -61,7 +63,8 @@ public class ProviderService : IProviderService
|
|||||||
IOrganizationRepository organizationRepository, GlobalSettings globalSettings,
|
IOrganizationRepository organizationRepository, GlobalSettings globalSettings,
|
||||||
ICurrentContext currentContext, IStripeAdapter stripeAdapter, IFeatureService featureService,
|
ICurrentContext currentContext, IStripeAdapter stripeAdapter, IFeatureService featureService,
|
||||||
IDataProtectorTokenFactory<ProviderDeleteTokenable> providerDeleteTokenDataFactory,
|
IDataProtectorTokenFactory<ProviderDeleteTokenable> providerDeleteTokenDataFactory,
|
||||||
IApplicationCacheService applicationCacheService, IProviderBillingService providerBillingService, IPricingClient pricingClient)
|
IApplicationCacheService applicationCacheService, IProviderBillingService providerBillingService, IPricingClient pricingClient,
|
||||||
|
IProviderClientOrganizationSignUpCommand providerClientOrganizationSignUpCommand)
|
||||||
{
|
{
|
||||||
_providerRepository = providerRepository;
|
_providerRepository = providerRepository;
|
||||||
_providerUserRepository = providerUserRepository;
|
_providerUserRepository = providerUserRepository;
|
||||||
@ -81,6 +84,7 @@ public class ProviderService : IProviderService
|
|||||||
_applicationCacheService = applicationCacheService;
|
_applicationCacheService = applicationCacheService;
|
||||||
_providerBillingService = providerBillingService;
|
_providerBillingService = providerBillingService;
|
||||||
_pricingClient = pricingClient;
|
_pricingClient = pricingClient;
|
||||||
|
_providerClientOrganizationSignUpCommand = providerClientOrganizationSignUpCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Provider> CompleteSetupAsync(Provider provider, Guid ownerUserId, string token, string key, TaxInfo taxInfo, TokenizedPaymentSource tokenizedPaymentSource = null)
|
public async Task<Provider> CompleteSetupAsync(Provider provider, Guid ownerUserId, string token, string key, TaxInfo taxInfo, TokenizedPaymentSource tokenizedPaymentSource = null)
|
||||||
@ -560,12 +564,12 @@ public class ProviderService : IProviderService
|
|||||||
|
|
||||||
ThrowOnInvalidPlanType(provider.Type, organizationSignup.Plan);
|
ThrowOnInvalidPlanType(provider.Type, organizationSignup.Plan);
|
||||||
|
|
||||||
var (organization, _, defaultCollection) = await _organizationService.SignupClientAsync(organizationSignup);
|
var signUpResponse = await _providerClientOrganizationSignUpCommand.SignUpClientOrganizationAsync(organizationSignup);
|
||||||
|
|
||||||
var providerOrganization = new ProviderOrganization
|
var providerOrganization = new ProviderOrganization
|
||||||
{
|
{
|
||||||
ProviderId = providerId,
|
ProviderId = providerId,
|
||||||
OrganizationId = organization.Id,
|
OrganizationId = signUpResponse.Organization.Id,
|
||||||
Key = organizationSignup.OwnerKey,
|
Key = organizationSignup.OwnerKey,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -574,12 +578,12 @@ public class ProviderService : IProviderService
|
|||||||
|
|
||||||
// Give the owner Can Manage access over the default collection
|
// Give the owner Can Manage access over the default collection
|
||||||
// The orgUser is not available when the org is created so we have to do it here as part of the invite
|
// The orgUser is not available when the org is created so we have to do it here as part of the invite
|
||||||
var defaultOwnerAccess = defaultCollection != null
|
var defaultOwnerAccess = signUpResponse.DefaultCollection != null
|
||||||
?
|
?
|
||||||
[
|
[
|
||||||
new CollectionAccessSelection
|
new CollectionAccessSelection
|
||||||
{
|
{
|
||||||
Id = defaultCollection.Id,
|
Id = signUpResponse.DefaultCollection.Id,
|
||||||
HidePasswords = false,
|
HidePasswords = false,
|
||||||
ReadOnly = false,
|
ReadOnly = false,
|
||||||
Manage = true
|
Manage = true
|
||||||
@ -587,7 +591,7 @@ public class ProviderService : IProviderService
|
|||||||
]
|
]
|
||||||
: Array.Empty<CollectionAccessSelection>();
|
: Array.Empty<CollectionAccessSelection>();
|
||||||
|
|
||||||
await _organizationService.InviteUsersAsync(organization.Id, user.Id, systemUser: null,
|
await _organizationService.InviteUsersAsync(signUpResponse.Organization.Id, user.Id, systemUser: null,
|
||||||
new (OrganizationUserInvite, string)[]
|
new (OrganizationUserInvite, string)[]
|
||||||
{
|
{
|
||||||
(
|
(
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using Bit.Core.Billing.Entities;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
using CsvHelper.Configuration.Attributes;
|
using CsvHelper.Configuration.Attributes;
|
||||||
|
|
||||||
namespace Bit.Commercial.Core.Billing.Models;
|
namespace Bit.Commercial.Core.Billing.Providers.Models;
|
||||||
|
|
||||||
public class ProviderClientInvoiceReportRow
|
public class ProviderClientInvoiceReportRow
|
||||||
{
|
{
|
@ -7,11 +7,12 @@ using Bit.Core.AdminConsole.Enums.Provider;
|
|||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Billing;
|
using Bit.Core.Billing;
|
||||||
using Bit.Core.Billing.Constants;
|
using Bit.Core.Billing.Constants;
|
||||||
using Bit.Core.Billing.Entities;
|
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Extensions;
|
using Bit.Core.Billing.Extensions;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Services;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
@ -24,7 +25,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using OneOf;
|
using OneOf;
|
||||||
using Stripe;
|
using Stripe;
|
||||||
|
|
||||||
namespace Bit.Commercial.Core.Billing;
|
namespace Bit.Commercial.Core.Billing.Providers.Services;
|
||||||
|
|
||||||
[RequireFeature(FeatureFlagKeys.PM18770_EnableOrganizationBusinessUnitConversion)]
|
[RequireFeature(FeatureFlagKeys.PM18770_EnableOrganizationBusinessUnitConversion)]
|
||||||
public class BusinessUnitConverter(
|
public class BusinessUnitConverter(
|
@ -1,5 +1,5 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using Bit.Commercial.Core.Billing.Models;
|
using Bit.Commercial.Core.Billing.Providers.Models;
|
||||||
using Bit.Core;
|
using Bit.Core;
|
||||||
using Bit.Core.AdminConsole.Entities;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Bit.Core.AdminConsole.Entities.Provider;
|
using Bit.Core.AdminConsole.Entities.Provider;
|
||||||
@ -8,14 +8,15 @@ using Bit.Core.AdminConsole.Repositories;
|
|||||||
using Bit.Core.Billing;
|
using Bit.Core.Billing;
|
||||||
using Bit.Core.Billing.Caches;
|
using Bit.Core.Billing.Caches;
|
||||||
using Bit.Core.Billing.Constants;
|
using Bit.Core.Billing.Constants;
|
||||||
using Bit.Core.Billing.Entities;
|
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Extensions;
|
using Bit.Core.Billing.Extensions;
|
||||||
using Bit.Core.Billing.Models;
|
using Bit.Core.Billing.Models;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
|
using Bit.Core.Billing.Providers.Models;
|
||||||
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Services;
|
||||||
using Bit.Core.Billing.Services.Contracts;
|
|
||||||
using Bit.Core.Billing.Tax.Models;
|
using Bit.Core.Billing.Tax.Models;
|
||||||
using Bit.Core.Billing.Tax.Services;
|
using Bit.Core.Billing.Tax.Services;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
@ -28,12 +29,11 @@ using Braintree;
|
|||||||
using CsvHelper;
|
using CsvHelper;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Stripe;
|
using Stripe;
|
||||||
|
|
||||||
using static Bit.Core.Billing.Utilities;
|
using static Bit.Core.Billing.Utilities;
|
||||||
using Customer = Stripe.Customer;
|
using Customer = Stripe.Customer;
|
||||||
using Subscription = Stripe.Subscription;
|
using Subscription = Stripe.Subscription;
|
||||||
|
|
||||||
namespace Bit.Commercial.Core.Billing;
|
namespace Bit.Commercial.Core.Billing.Providers.Services;
|
||||||
|
|
||||||
public class ProviderBillingService(
|
public class ProviderBillingService(
|
||||||
IBraintreeGateway braintreeGateway,
|
IBraintreeGateway braintreeGateway,
|
@ -6,7 +6,7 @@ using Bit.Core.Billing;
|
|||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Stripe;
|
using Stripe;
|
||||||
|
|
||||||
namespace Bit.Commercial.Core.Billing;
|
namespace Bit.Commercial.Core.Billing.Providers.Services;
|
||||||
|
|
||||||
public static class ProviderPriceAdapter
|
public static class ProviderPriceAdapter
|
||||||
{
|
{
|
@ -1,9 +1,9 @@
|
|||||||
using Bit.Commercial.Core.AdminConsole.Providers;
|
using Bit.Commercial.Core.AdminConsole.Providers;
|
||||||
using Bit.Commercial.Core.AdminConsole.Services;
|
using Bit.Commercial.Core.AdminConsole.Services;
|
||||||
using Bit.Commercial.Core.Billing;
|
using Bit.Commercial.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.AdminConsole.Providers.Interfaces;
|
using Bit.Core.AdminConsole.Providers.Interfaces;
|
||||||
using Bit.Core.AdminConsole.Services;
|
using Bit.Core.AdminConsole.Services;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace Bit.Commercial.Core.Utilities;
|
namespace Bit.Commercial.Core.Utilities;
|
||||||
|
@ -8,6 +8,7 @@ using Bit.Core.AdminConsole.Repositories;
|
|||||||
using Bit.Core.Billing.Constants;
|
using Bit.Core.Billing.Constants;
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Services;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
|
@ -6,11 +6,12 @@ using Bit.Core.AdminConsole.Entities.Provider;
|
|||||||
using Bit.Core.AdminConsole.Enums.Provider;
|
using Bit.Core.AdminConsole.Enums.Provider;
|
||||||
using Bit.Core.AdminConsole.Models.Business.Provider;
|
using Bit.Core.AdminConsole.Models.Business.Provider;
|
||||||
using Bit.Core.AdminConsole.Models.Business.Tokenables;
|
using Bit.Core.AdminConsole.Models.Business.Tokenables;
|
||||||
|
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Models;
|
using Bit.Core.Billing.Models;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
@ -717,8 +718,8 @@ public class ProviderServiceTests
|
|||||||
|
|
||||||
sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider);
|
sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider);
|
||||||
var providerOrganizationRepository = sutProvider.GetDependency<IProviderOrganizationRepository>();
|
var providerOrganizationRepository = sutProvider.GetDependency<IProviderOrganizationRepository>();
|
||||||
sutProvider.GetDependency<IOrganizationService>().SignupClientAsync(organizationSignup)
|
sutProvider.GetDependency<IProviderClientOrganizationSignUpCommand>().SignUpClientOrganizationAsync(organizationSignup)
|
||||||
.Returns((organization, null as OrganizationUser, new Collection()));
|
.Returns(new ProviderClientOrganizationSignUpResponse(organization, new Collection()));
|
||||||
|
|
||||||
var providerOrganization =
|
var providerOrganization =
|
||||||
await sutProvider.Sut.CreateOrganizationAsync(provider.Id, organizationSignup, clientOwnerEmail, user);
|
await sutProvider.Sut.CreateOrganizationAsync(provider.Id, organizationSignup, clientOwnerEmail, user);
|
||||||
@ -755,8 +756,8 @@ public class ProviderServiceTests
|
|||||||
|
|
||||||
var providerOrganizationRepository = sutProvider.GetDependency<IProviderOrganizationRepository>();
|
var providerOrganizationRepository = sutProvider.GetDependency<IProviderOrganizationRepository>();
|
||||||
|
|
||||||
sutProvider.GetDependency<IOrganizationService>().SignupClientAsync(organizationSignup)
|
sutProvider.GetDependency<IProviderClientOrganizationSignUpCommand>().SignUpClientOrganizationAsync(organizationSignup)
|
||||||
.Returns((organization, null as OrganizationUser, new Collection()));
|
.Returns(new ProviderClientOrganizationSignUpResponse(organization, new Collection()));
|
||||||
|
|
||||||
await Assert.ThrowsAsync<BadRequestException>(() =>
|
await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||||
sutProvider.Sut.CreateOrganizationAsync(provider.Id, organizationSignup, clientOwnerEmail, user));
|
sutProvider.Sut.CreateOrganizationAsync(provider.Id, organizationSignup, clientOwnerEmail, user));
|
||||||
@ -782,8 +783,8 @@ public class ProviderServiceTests
|
|||||||
|
|
||||||
var providerOrganizationRepository = sutProvider.GetDependency<IProviderOrganizationRepository>();
|
var providerOrganizationRepository = sutProvider.GetDependency<IProviderOrganizationRepository>();
|
||||||
|
|
||||||
sutProvider.GetDependency<IOrganizationService>().SignupClientAsync(organizationSignup)
|
sutProvider.GetDependency<IProviderClientOrganizationSignUpCommand>().SignUpClientOrganizationAsync(organizationSignup)
|
||||||
.Returns((organization, null as OrganizationUser, new Collection()));
|
.Returns(new ProviderClientOrganizationSignUpResponse(organization, new Collection()));
|
||||||
|
|
||||||
var providerOrganization = await sutProvider.Sut.CreateOrganizationAsync(provider.Id, organizationSignup, clientOwnerEmail, user);
|
var providerOrganization = await sutProvider.Sut.CreateOrganizationAsync(provider.Id, organizationSignup, clientOwnerEmail, user);
|
||||||
|
|
||||||
@ -821,8 +822,8 @@ public class ProviderServiceTests
|
|||||||
|
|
||||||
sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider);
|
sutProvider.GetDependency<IProviderRepository>().GetByIdAsync(provider.Id).Returns(provider);
|
||||||
var providerOrganizationRepository = sutProvider.GetDependency<IProviderOrganizationRepository>();
|
var providerOrganizationRepository = sutProvider.GetDependency<IProviderOrganizationRepository>();
|
||||||
sutProvider.GetDependency<IOrganizationService>().SignupClientAsync(organizationSignup)
|
sutProvider.GetDependency<IProviderClientOrganizationSignUpCommand>().SignUpClientOrganizationAsync(organizationSignup)
|
||||||
.Returns((organization, null as OrganizationUser, defaultCollection));
|
.Returns(new ProviderClientOrganizationSignUpResponse(organization, defaultCollection));
|
||||||
|
|
||||||
var providerOrganization =
|
var providerOrganization =
|
||||||
await sutProvider.Sut.CreateOrganizationAsync(provider.Id, organizationSignup, clientOwnerEmail, user);
|
await sutProvider.Sut.CreateOrganizationAsync(provider.Id, organizationSignup, clientOwnerEmail, user);
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Bit.Commercial.Core.Billing;
|
using Bit.Commercial.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.AdminConsole.Entities;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Bit.Core.AdminConsole.Entities.Provider;
|
using Bit.Core.AdminConsole.Entities.Provider;
|
||||||
using Bit.Core.AdminConsole.Enums.Provider;
|
using Bit.Core.AdminConsole.Enums.Provider;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Billing;
|
using Bit.Core.Billing;
|
||||||
using Bit.Core.Billing.Constants;
|
using Bit.Core.Billing.Constants;
|
||||||
using Bit.Core.Billing.Entities;
|
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Services;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
@ -25,7 +25,7 @@ using NSubstitute;
|
|||||||
using Stripe;
|
using Stripe;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Bit.Commercial.Core.Test.Billing;
|
namespace Bit.Commercial.Core.Test.Billing.Providers;
|
||||||
|
|
||||||
public class BusinessUnitConverterTests
|
public class BusinessUnitConverterTests
|
||||||
{
|
{
|
@ -1,7 +1,7 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Bit.Commercial.Core.Billing;
|
using Bit.Commercial.Core.Billing.Providers.Models;
|
||||||
using Bit.Commercial.Core.Billing.Models;
|
using Bit.Commercial.Core.Billing.Providers.Services;
|
||||||
using Bit.Core;
|
using Bit.Core;
|
||||||
using Bit.Core.AdminConsole.Entities;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Bit.Core.AdminConsole.Entities.Provider;
|
using Bit.Core.AdminConsole.Entities.Provider;
|
||||||
@ -10,13 +10,13 @@ using Bit.Core.AdminConsole.Models.Data.Provider;
|
|||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Billing.Caches;
|
using Bit.Core.Billing.Caches;
|
||||||
using Bit.Core.Billing.Constants;
|
using Bit.Core.Billing.Constants;
|
||||||
using Bit.Core.Billing.Entities;
|
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Models;
|
using Bit.Core.Billing.Models;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
|
using Bit.Core.Billing.Providers.Models;
|
||||||
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Services;
|
||||||
using Bit.Core.Billing.Services.Contracts;
|
|
||||||
using Bit.Core.Billing.Tax.Services;
|
using Bit.Core.Billing.Tax.Services;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
@ -40,7 +40,7 @@ using Customer = Stripe.Customer;
|
|||||||
using PaymentMethod = Stripe.PaymentMethod;
|
using PaymentMethod = Stripe.PaymentMethod;
|
||||||
using Subscription = Stripe.Subscription;
|
using Subscription = Stripe.Subscription;
|
||||||
|
|
||||||
namespace Bit.Commercial.Core.Test.Billing;
|
namespace Bit.Commercial.Core.Test.Billing.Providers;
|
||||||
|
|
||||||
[SutProviderCustomize]
|
[SutProviderCustomize]
|
||||||
public class ProviderBillingServiceTests
|
public class ProviderBillingServiceTests
|
@ -1,11 +1,11 @@
|
|||||||
using Bit.Commercial.Core.Billing;
|
using Bit.Commercial.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.AdminConsole.Entities.Provider;
|
using Bit.Core.AdminConsole.Entities.Provider;
|
||||||
using Bit.Core.AdminConsole.Enums.Provider;
|
using Bit.Core.AdminConsole.Enums.Provider;
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Stripe;
|
using Stripe;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Bit.Commercial.Core.Test.Billing;
|
namespace Bit.Commercial.Core.Test.Billing.Providers;
|
||||||
|
|
||||||
public class ProviderPriceAdapterTests
|
public class ProviderPriceAdapterTests
|
||||||
{
|
{
|
@ -3,7 +3,7 @@ using Bit.Test.Common.AutoFixture;
|
|||||||
using Bit.Test.Common.AutoFixture.Attributes;
|
using Bit.Test.Common.AutoFixture.Attributes;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Bit.Commercial.Core.Test.Billing;
|
namespace Bit.Commercial.Core.Test.Billing.Tax;
|
||||||
|
|
||||||
[SutProviderCustomize]
|
[SutProviderCustomize]
|
||||||
public class TaxServiceTests
|
public class TaxServiceTests
|
@ -11,7 +11,7 @@ using Bit.Core.AdminConsole.Repositories;
|
|||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Extensions;
|
using Bit.Core.Billing.Extensions;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Models.OrganizationConnectionConfigs;
|
using Bit.Core.Models.OrganizationConnectionConfigs;
|
||||||
|
@ -10,13 +10,13 @@ using Bit.Core.AdminConsole.Providers.Interfaces;
|
|||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.AdminConsole.Services;
|
using Bit.Core.AdminConsole.Services;
|
||||||
using Bit.Core.Billing.Constants;
|
using Bit.Core.Billing.Constants;
|
||||||
using Bit.Core.Billing.Entities;
|
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Extensions;
|
using Bit.Core.Billing.Extensions;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Providers.Models;
|
||||||
using Bit.Core.Billing.Services.Contracts;
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
using Bit.Core.AdminConsole.Entities.Provider;
|
using Bit.Core.AdminConsole.Entities.Provider;
|
||||||
using Bit.Core.AdminConsole.Enums.Provider;
|
using Bit.Core.AdminConsole.Enums.Provider;
|
||||||
using Bit.Core.AdminConsole.Models.Data.Provider;
|
using Bit.Core.AdminConsole.Models.Data.Provider;
|
||||||
using Bit.Core.Billing.Entities;
|
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.SharedWeb.Utilities;
|
using Bit.SharedWeb.Utilities;
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
using Bit.Core.AdminConsole.Entities.Provider;
|
using Bit.Core.AdminConsole.Entities.Provider;
|
||||||
using Bit.Core.AdminConsole.Enums.Provider;
|
using Bit.Core.AdminConsole.Enums.Provider;
|
||||||
using Bit.Core.AdminConsole.Models.Data.Provider;
|
using Bit.Core.AdminConsole.Models.Data.Provider;
|
||||||
using Bit.Core.Billing.Entities;
|
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
|
|
||||||
namespace Bit.Admin.AdminConsole.Models;
|
namespace Bit.Admin.AdminConsole.Models;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ using Bit.Core.AdminConsole.Entities;
|
|||||||
using Bit.Core.AdminConsole.Entities.Provider;
|
using Bit.Core.AdminConsole.Entities.Provider;
|
||||||
using Bit.Core.AdminConsole.Enums.Provider;
|
using Bit.Core.AdminConsole.Enums.Provider;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
using Bit.Admin.Billing.Models;
|
using Bit.Admin.Billing.Models;
|
||||||
using Bit.Admin.Enums;
|
using Bit.Admin.Enums;
|
||||||
using Bit.Admin.Utilities;
|
using Bit.Admin.Utilities;
|
||||||
using Bit.Core.Billing.Migration.Models;
|
using Bit.Core.Billing.Providers.Migration.Models;
|
||||||
using Bit.Core.Billing.Migration.Services;
|
using Bit.Core.Billing.Providers.Migration.Services;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using Bit.Core.Billing.Entities;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
|
|
||||||
namespace Bit.Admin.Billing.Models;
|
namespace Bit.Admin.Billing.Models;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
@using System.Text.Json
|
@using System.Text.Json
|
||||||
@model Bit.Core.Billing.Migration.Models.ProviderMigrationResult
|
@model Bit.Core.Billing.Providers.Migration.Models.ProviderMigrationResult
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Results";
|
ViewData["Title"] = "Results";
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@model Bit.Core.Billing.Migration.Models.ProviderMigrationResult[]
|
@model Bit.Core.Billing.Providers.Migration.Models.ProviderMigrationResult[]
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Results";
|
ViewData["Title"] = "Results";
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Mvc.Razor;
|
|||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using Bit.Admin.Services;
|
using Bit.Admin.Services;
|
||||||
using Bit.Core.Billing.Extensions;
|
using Bit.Core.Billing.Extensions;
|
||||||
using Bit.Core.Billing.Migration;
|
using Bit.Core.Billing.Providers.Migration;
|
||||||
|
|
||||||
#if !OSS
|
#if !OSS
|
||||||
using Bit.Commercial.Core.Utilities;
|
using Bit.Commercial.Core.Utilities;
|
||||||
|
@ -2,13 +2,11 @@
|
|||||||
using Bit.Api.AdminConsole.Models.Request.Organizations;
|
using Bit.Api.AdminConsole.Models.Request.Organizations;
|
||||||
using Bit.Api.AdminConsole.Models.Response.Organizations;
|
using Bit.Api.AdminConsole.Models.Response.Organizations;
|
||||||
using Bit.Api.Models.Response;
|
using Bit.Api.Models.Response;
|
||||||
using Bit.Core;
|
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfaces;
|
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfaces;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
using Bit.Core.Utilities;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
@ -137,7 +135,6 @@ public class OrganizationDomainController : Controller
|
|||||||
|
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[HttpPost("domain/sso/verified")]
|
[HttpPost("domain/sso/verified")]
|
||||||
[RequireFeature(FeatureFlagKeys.VerifiedSsoDomainEndpoint)]
|
|
||||||
public async Task<VerifiedOrganizationDomainSsoDetailsResponseModel> GetVerifiedOrgDomainSsoDetailsAsync(
|
public async Task<VerifiedOrganizationDomainSsoDetailsResponseModel> GetVerifiedOrgDomainSsoDetailsAsync(
|
||||||
[FromBody] OrganizationDomainSsoDetailsRequestModel model)
|
[FromBody] OrganizationDomainSsoDetailsRequestModel model)
|
||||||
{
|
{
|
||||||
|
@ -25,7 +25,7 @@ using Bit.Core.Auth.Services;
|
|||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Extensions;
|
using Bit.Core.Billing.Extensions;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
using Bit.Api.Billing.Models.Requests;
|
using Bit.Api.Billing.Models.Requests;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.AdminConsole.Services;
|
using Bit.Core.AdminConsole.Services;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Models.Business;
|
using Bit.Core.Models.Business;
|
||||||
|
@ -8,6 +8,7 @@ using Bit.Core;
|
|||||||
using Bit.Core.Billing.Models;
|
using Bit.Core.Billing.Models;
|
||||||
using Bit.Core.Billing.Models.Sales;
|
using Bit.Core.Billing.Models.Sales;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Services;
|
||||||
using Bit.Core.Billing.Tax.Models;
|
using Bit.Core.Billing.Tax.Models;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
@ -301,8 +302,12 @@ public class OrganizationBillingController(
|
|||||||
Debug.Assert(org is not null, "This organization has already been found via this same ID, this should be fine.");
|
Debug.Assert(org is not null, "This organization has already been found via this same ID, this should be fine.");
|
||||||
var paymentSource = new TokenizedPaymentSource(organizationSignup.PaymentMethodType.Value, organizationSignup.PaymentToken);
|
var paymentSource = new TokenizedPaymentSource(organizationSignup.PaymentMethodType.Value, organizationSignup.PaymentToken);
|
||||||
var taxInformation = TaxInformation.From(organizationSignup.TaxInfo);
|
var taxInformation = TaxInformation.From(organizationSignup.TaxInfo);
|
||||||
await organizationBillingService.UpdatePaymentMethod(org, paymentSource, taxInformation);
|
|
||||||
await organizationBillingService.Finalize(sale);
|
await organizationBillingService.Finalize(sale);
|
||||||
|
var updatedOrg = await organizationRepository.GetByIdAsync(organizationId);
|
||||||
|
if (updatedOrg != null)
|
||||||
|
{
|
||||||
|
await organizationBillingService.UpdatePaymentMethod(updatedOrg, paymentSource, taxInformation);
|
||||||
|
}
|
||||||
|
|
||||||
return TypedResults.Ok();
|
return TypedResults.Ok();
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
using Bit.Api.Billing.Models.Requests;
|
using Bit.Api.Billing.Models.Requests;
|
||||||
using Bit.Api.Billing.Models.Responses;
|
using Bit.Api.Billing.Models.Responses;
|
||||||
|
using Bit.Commercial.Core.Billing.Providers.Services;
|
||||||
using Bit.Core;
|
using Bit.Core;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Billing.Models;
|
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Models;
|
||||||
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Services;
|
||||||
using Bit.Core.Billing.Tax.Models;
|
using Bit.Core.Billing.Tax.Models;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
@ -148,13 +150,33 @@ public class ProviderBillingController(
|
|||||||
|
|
||||||
var providerPlans = await providerPlanRepository.GetByProviderId(provider.Id);
|
var providerPlans = await providerPlanRepository.GetByProviderId(provider.Id);
|
||||||
|
|
||||||
|
var getProviderPriceFromStripe = featureService.IsEnabled(FeatureFlagKeys.PM21383_GetProviderPriceFromStripe);
|
||||||
|
|
||||||
var configuredProviderPlans = await Task.WhenAll(providerPlans.Select(async providerPlan =>
|
var configuredProviderPlans = await Task.WhenAll(providerPlans.Select(async providerPlan =>
|
||||||
{
|
{
|
||||||
var plan = await pricingClient.GetPlanOrThrow(providerPlan.PlanType);
|
var plan = await pricingClient.GetPlanOrThrow(providerPlan.PlanType);
|
||||||
|
|
||||||
|
decimal unitAmount;
|
||||||
|
|
||||||
|
if (getProviderPriceFromStripe)
|
||||||
|
{
|
||||||
|
var priceId = ProviderPriceAdapter.GetPriceId(provider, subscription, plan.Type);
|
||||||
|
var price = await stripeAdapter.PriceGetAsync(priceId);
|
||||||
|
|
||||||
|
unitAmount = price.UnitAmountDecimal.HasValue
|
||||||
|
? price.UnitAmountDecimal.Value / 100M
|
||||||
|
: plan.PasswordManager.ProviderPortalSeatPrice;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unitAmount = plan.PasswordManager.ProviderPortalSeatPrice;
|
||||||
|
}
|
||||||
|
|
||||||
return new ConfiguredProviderPlan(
|
return new ConfiguredProviderPlan(
|
||||||
providerPlan.Id,
|
providerPlan.Id,
|
||||||
providerPlan.ProviderId,
|
providerPlan.ProviderId,
|
||||||
plan,
|
plan,
|
||||||
|
unitAmount,
|
||||||
providerPlan.SeatMinimum ?? 0,
|
providerPlan.SeatMinimum ?? 0,
|
||||||
providerPlan.PurchasedSeats ?? 0,
|
providerPlan.PurchasedSeats ?? 0,
|
||||||
providerPlan.AllocatedSeats ?? 0);
|
providerPlan.AllocatedSeats ?? 0);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using Bit.Core.AdminConsole.Enums.Provider;
|
using Bit.Core.AdminConsole.Enums.Provider;
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Models;
|
using Bit.Core.Billing.Models;
|
||||||
|
using Bit.Core.Billing.Providers.Models;
|
||||||
using Bit.Core.Billing.Tax.Models;
|
using Bit.Core.Billing.Tax.Models;
|
||||||
using Stripe;
|
using Stripe;
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ public record ProviderSubscriptionResponse(
|
|||||||
.Select(providerPlan =>
|
.Select(providerPlan =>
|
||||||
{
|
{
|
||||||
var plan = providerPlan.Plan;
|
var plan = providerPlan.Plan;
|
||||||
var cost = (providerPlan.SeatMinimum + providerPlan.PurchasedSeats) * plan.PasswordManager.ProviderPortalSeatPrice;
|
var cost = (providerPlan.SeatMinimum + providerPlan.PurchasedSeats) * providerPlan.Price;
|
||||||
var cadence = plan.IsAnnual ? _annualCadence : _monthlyCadence;
|
var cadence = plan.IsAnnual ? _annualCadence : _monthlyCadence;
|
||||||
return new ProviderPlanResponse(
|
return new ProviderPlanResponse(
|
||||||
plan.Name,
|
plan.Name,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
using Bit.Billing.Constants;
|
using Bit.Billing.Constants;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Billing.Entities;
|
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
using Stripe;
|
using Stripe;
|
||||||
|
@ -0,0 +1,187 @@
|
|||||||
|
using Bit.Core.AdminConsole.Entities;
|
||||||
|
using Bit.Core.Billing.Pricing;
|
||||||
|
using Bit.Core.Context;
|
||||||
|
using Bit.Core.Entities;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Exceptions;
|
||||||
|
using Bit.Core.Models.Business;
|
||||||
|
using Bit.Core.Models.StaticStore;
|
||||||
|
using Bit.Core.Repositories;
|
||||||
|
using Bit.Core.Services;
|
||||||
|
using Bit.Core.Tools.Enums;
|
||||||
|
using Bit.Core.Tools.Models.Business;
|
||||||
|
using Bit.Core.Tools.Services;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
|
|
||||||
|
namespace Bit.Core.AdminConsole.OrganizationFeatures.Organizations;
|
||||||
|
|
||||||
|
public record ProviderClientOrganizationSignUpResponse(
|
||||||
|
Organization Organization,
|
||||||
|
Collection DefaultCollection);
|
||||||
|
|
||||||
|
public interface IProviderClientOrganizationSignUpCommand
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Sign up a new client organization for a provider.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="signup">The signup information.</param>
|
||||||
|
/// <returns>A tuple containing the new organization and its default collection.</returns>
|
||||||
|
Task<ProviderClientOrganizationSignUpResponse> SignUpClientOrganizationAsync(OrganizationSignup signup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ProviderClientOrganizationSignUpCommand : IProviderClientOrganizationSignUpCommand
|
||||||
|
{
|
||||||
|
public const string PlanNullErrorMessage = "Password Manager Plan was null.";
|
||||||
|
public const string PlanDisabledErrorMessage = "Password Manager Plan is disabled.";
|
||||||
|
public const string AdditionalSeatsNegativeErrorMessage = "You can't subtract Password Manager seats!";
|
||||||
|
|
||||||
|
private readonly ICurrentContext _currentContext;
|
||||||
|
private readonly IPricingClient _pricingClient;
|
||||||
|
private readonly IReferenceEventService _referenceEventService;
|
||||||
|
private readonly IOrganizationRepository _organizationRepository;
|
||||||
|
private readonly IOrganizationApiKeyRepository _organizationApiKeyRepository;
|
||||||
|
private readonly IApplicationCacheService _applicationCacheService;
|
||||||
|
private readonly ICollectionRepository _collectionRepository;
|
||||||
|
|
||||||
|
public ProviderClientOrganizationSignUpCommand(
|
||||||
|
ICurrentContext currentContext,
|
||||||
|
IPricingClient pricingClient,
|
||||||
|
IReferenceEventService referenceEventService,
|
||||||
|
IOrganizationRepository organizationRepository,
|
||||||
|
IOrganizationApiKeyRepository organizationApiKeyRepository,
|
||||||
|
IApplicationCacheService applicationCacheService,
|
||||||
|
ICollectionRepository collectionRepository)
|
||||||
|
{
|
||||||
|
_currentContext = currentContext;
|
||||||
|
_pricingClient = pricingClient;
|
||||||
|
_referenceEventService = referenceEventService;
|
||||||
|
_organizationRepository = organizationRepository;
|
||||||
|
_organizationApiKeyRepository = organizationApiKeyRepository;
|
||||||
|
_applicationCacheService = applicationCacheService;
|
||||||
|
_collectionRepository = collectionRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ProviderClientOrganizationSignUpResponse> SignUpClientOrganizationAsync(OrganizationSignup signup)
|
||||||
|
{
|
||||||
|
var plan = await _pricingClient.GetPlanOrThrow(signup.Plan);
|
||||||
|
|
||||||
|
ValidatePlan(plan, signup.AdditionalSeats);
|
||||||
|
|
||||||
|
var organization = new Organization
|
||||||
|
{
|
||||||
|
// Pre-generate the org id so that we can save it with the Stripe subscription.
|
||||||
|
Id = CoreHelpers.GenerateComb(),
|
||||||
|
Name = signup.Name,
|
||||||
|
BillingEmail = signup.BillingEmail,
|
||||||
|
PlanType = plan!.Type,
|
||||||
|
Seats = signup.AdditionalSeats,
|
||||||
|
MaxCollections = plan.PasswordManager.MaxCollections,
|
||||||
|
MaxStorageGb = 1,
|
||||||
|
UsePolicies = plan.HasPolicies,
|
||||||
|
UseSso = plan.HasSso,
|
||||||
|
UseOrganizationDomains = plan.HasOrganizationDomains,
|
||||||
|
UseGroups = plan.HasGroups,
|
||||||
|
UseEvents = plan.HasEvents,
|
||||||
|
UseDirectory = plan.HasDirectory,
|
||||||
|
UseTotp = plan.HasTotp,
|
||||||
|
Use2fa = plan.Has2fa,
|
||||||
|
UseApi = plan.HasApi,
|
||||||
|
UseResetPassword = plan.HasResetPassword,
|
||||||
|
SelfHost = plan.HasSelfHost,
|
||||||
|
UsersGetPremium = plan.UsersGetPremium,
|
||||||
|
UseCustomPermissions = plan.HasCustomPermissions,
|
||||||
|
UseScim = plan.HasScim,
|
||||||
|
Plan = plan.Name,
|
||||||
|
Gateway = GatewayType.Stripe,
|
||||||
|
ReferenceData = signup.Owner.ReferenceData,
|
||||||
|
Enabled = true,
|
||||||
|
LicenseKey = CoreHelpers.SecureRandomString(20),
|
||||||
|
PublicKey = signup.PublicKey,
|
||||||
|
PrivateKey = signup.PrivateKey,
|
||||||
|
CreationDate = DateTime.UtcNow,
|
||||||
|
RevisionDate = DateTime.UtcNow,
|
||||||
|
Status = OrganizationStatusType.Created,
|
||||||
|
UsePasswordManager = true,
|
||||||
|
// Secrets Manager not available for purchase with Consolidated Billing.
|
||||||
|
UseSecretsManager = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
var returnValue = await SignUpAsync(organization, signup.CollectionName);
|
||||||
|
|
||||||
|
await _referenceEventService.RaiseEventAsync(
|
||||||
|
new ReferenceEvent(ReferenceEventType.Signup, organization, _currentContext)
|
||||||
|
{
|
||||||
|
PlanName = plan.Name,
|
||||||
|
PlanType = plan.Type,
|
||||||
|
Seats = returnValue.Organization.Seats,
|
||||||
|
SignupInitiationPath = signup.InitiationPath,
|
||||||
|
Storage = returnValue.Organization.MaxStorageGb,
|
||||||
|
});
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ValidatePlan(Plan plan, int additionalSeats)
|
||||||
|
{
|
||||||
|
if (plan is null)
|
||||||
|
{
|
||||||
|
throw new BadRequestException(PlanNullErrorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plan.Disabled)
|
||||||
|
{
|
||||||
|
throw new BadRequestException(PlanDisabledErrorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (additionalSeats < 0)
|
||||||
|
{
|
||||||
|
throw new BadRequestException(AdditionalSeatsNegativeErrorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Private helper method to create a new organization.
|
||||||
|
/// </summary>
|
||||||
|
private async Task<ProviderClientOrganizationSignUpResponse> SignUpAsync(
|
||||||
|
Organization organization, string collectionName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _organizationRepository.CreateAsync(organization);
|
||||||
|
await _organizationApiKeyRepository.CreateAsync(new OrganizationApiKey
|
||||||
|
{
|
||||||
|
OrganizationId = organization.Id,
|
||||||
|
ApiKey = CoreHelpers.SecureRandomString(30),
|
||||||
|
Type = OrganizationApiKeyType.Default,
|
||||||
|
RevisionDate = DateTime.UtcNow,
|
||||||
|
});
|
||||||
|
await _applicationCacheService.UpsertOrganizationAbilityAsync(organization);
|
||||||
|
|
||||||
|
Collection defaultCollection = null;
|
||||||
|
if (!string.IsNullOrWhiteSpace(collectionName))
|
||||||
|
{
|
||||||
|
defaultCollection = new Collection
|
||||||
|
{
|
||||||
|
Name = collectionName,
|
||||||
|
OrganizationId = organization.Id,
|
||||||
|
CreationDate = organization.CreationDate,
|
||||||
|
RevisionDate = organization.CreationDate
|
||||||
|
};
|
||||||
|
|
||||||
|
await _collectionRepository.CreateAsync(defaultCollection, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ProviderClientOrganizationSignUpResponse(organization, defaultCollection);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
if (organization.Id != default)
|
||||||
|
{
|
||||||
|
await _organizationRepository.DeleteAsync(organization);
|
||||||
|
await _applicationCacheService.DeleteOrganizationAbilityAsync(organization.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,9 +18,6 @@ public interface IOrganizationService
|
|||||||
Task AutoAddSeatsAsync(Organization organization, int seatsToAdd);
|
Task AutoAddSeatsAsync(Organization organization, int seatsToAdd);
|
||||||
Task<string> AdjustSeatsAsync(Guid organizationId, int seatAdjustment);
|
Task<string> AdjustSeatsAsync(Guid organizationId, int seatAdjustment);
|
||||||
Task VerifyBankAsync(Guid organizationId, int amount1, int amount2);
|
Task VerifyBankAsync(Guid organizationId, int amount1, int amount2);
|
||||||
#nullable enable
|
|
||||||
Task<(Organization organization, OrganizationUser organizationUser, Collection defaultCollection)> SignupClientAsync(OrganizationSignup signup);
|
|
||||||
#nullable disable
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new organization on a self-hosted instance
|
/// Create a new organization on a self-hosted instance
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -403,66 +403,6 @@ public class OrganizationService : IOrganizationService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(Organization organization, OrganizationUser organizationUser, Collection defaultCollection)> SignupClientAsync(OrganizationSignup signup)
|
|
||||||
{
|
|
||||||
var plan = await _pricingClient.GetPlanOrThrow(signup.Plan);
|
|
||||||
|
|
||||||
ValidatePlan(plan, signup.AdditionalSeats, "Password Manager");
|
|
||||||
|
|
||||||
var organization = new Organization
|
|
||||||
{
|
|
||||||
// Pre-generate the org id so that we can save it with the Stripe subscription.
|
|
||||||
Id = CoreHelpers.GenerateComb(),
|
|
||||||
Name = signup.Name,
|
|
||||||
BillingEmail = signup.BillingEmail,
|
|
||||||
PlanType = plan!.Type,
|
|
||||||
Seats = signup.AdditionalSeats,
|
|
||||||
MaxCollections = plan.PasswordManager.MaxCollections,
|
|
||||||
MaxStorageGb = 1,
|
|
||||||
UsePolicies = plan.HasPolicies,
|
|
||||||
UseSso = plan.HasSso,
|
|
||||||
UseOrganizationDomains = plan.HasOrganizationDomains,
|
|
||||||
UseGroups = plan.HasGroups,
|
|
||||||
UseEvents = plan.HasEvents,
|
|
||||||
UseDirectory = plan.HasDirectory,
|
|
||||||
UseTotp = plan.HasTotp,
|
|
||||||
Use2fa = plan.Has2fa,
|
|
||||||
UseApi = plan.HasApi,
|
|
||||||
UseResetPassword = plan.HasResetPassword,
|
|
||||||
SelfHost = plan.HasSelfHost,
|
|
||||||
UsersGetPremium = plan.UsersGetPremium,
|
|
||||||
UseCustomPermissions = plan.HasCustomPermissions,
|
|
||||||
UseScim = plan.HasScim,
|
|
||||||
Plan = plan.Name,
|
|
||||||
Gateway = GatewayType.Stripe,
|
|
||||||
ReferenceData = signup.Owner.ReferenceData,
|
|
||||||
Enabled = true,
|
|
||||||
LicenseKey = CoreHelpers.SecureRandomString(20),
|
|
||||||
PublicKey = signup.PublicKey,
|
|
||||||
PrivateKey = signup.PrivateKey,
|
|
||||||
CreationDate = DateTime.UtcNow,
|
|
||||||
RevisionDate = DateTime.UtcNow,
|
|
||||||
Status = OrganizationStatusType.Created,
|
|
||||||
UsePasswordManager = true,
|
|
||||||
// Secrets Manager not available for purchase with Consolidated Billing.
|
|
||||||
UseSecretsManager = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
var returnValue = await SignUpAsync(organization, default, signup.OwnerKey, signup.CollectionName, false);
|
|
||||||
|
|
||||||
await _referenceEventService.RaiseEventAsync(
|
|
||||||
new ReferenceEvent(ReferenceEventType.Signup, organization, _currentContext)
|
|
||||||
{
|
|
||||||
PlanName = plan.Name,
|
|
||||||
PlanType = plan.Type,
|
|
||||||
Seats = returnValue.Item1.Seats,
|
|
||||||
SignupInitiationPath = signup.InitiationPath,
|
|
||||||
Storage = returnValue.Item1.MaxStorageGb,
|
|
||||||
});
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ValidateSignUpPoliciesAsync(Guid ownerId)
|
private async Task ValidateSignUpPoliciesAsync(Guid ownerId)
|
||||||
{
|
{
|
||||||
var anySingleOrgPolicies = await _policyService.AnyPoliciesApplicableToUserAsync(ownerId, PolicyType.SingleOrg);
|
var anySingleOrgPolicies = await _policyService.AnyPoliciesApplicableToUserAsync(ownerId, PolicyType.SingleOrg);
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
#nullable enable
|
||||||
|
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
|
||||||
#nullable enable
|
namespace Bit.Core.Billing.Providers.Entities;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Entities;
|
|
||||||
|
|
||||||
public class ClientOrganizationMigrationRecord : ITableObject<Guid>
|
public class ClientOrganizationMigrationRecord : ITableObject<Guid>
|
||||||
{
|
{
|
@ -1,10 +1,10 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
#nullable enable
|
||||||
|
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
|
||||||
#nullable enable
|
namespace Bit.Core.Billing.Providers.Entities;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Entities;
|
|
||||||
|
|
||||||
public class ProviderInvoiceItem : ITableObject<Guid>
|
public class ProviderInvoiceItem : ITableObject<Guid>
|
||||||
{
|
{
|
@ -1,10 +1,10 @@
|
|||||||
using Bit.Core.Billing.Enums;
|
#nullable enable
|
||||||
|
|
||||||
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
|
||||||
#nullable enable
|
namespace Bit.Core.Billing.Providers.Entities;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Entities;
|
|
||||||
|
|
||||||
public class ProviderPlan : ITableObject<Guid>
|
public class ProviderPlan : ITableObject<Guid>
|
||||||
{
|
{
|
@ -1,4 +1,4 @@
|
|||||||
namespace Bit.Core.Billing.Migration.Models;
|
namespace Bit.Core.Billing.Providers.Migration.Models;
|
||||||
|
|
||||||
public enum ClientMigrationProgress
|
public enum ClientMigrationProgress
|
||||||
{
|
{
|
@ -1,6 +1,6 @@
|
|||||||
using Bit.Core.Billing.Entities;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Migration.Models;
|
namespace Bit.Core.Billing.Providers.Migration.Models;
|
||||||
|
|
||||||
public class ProviderMigrationResult
|
public class ProviderMigrationResult
|
||||||
{
|
{
|
@ -1,4 +1,4 @@
|
|||||||
namespace Bit.Core.Billing.Migration.Models;
|
namespace Bit.Core.Billing.Providers.Migration.Models;
|
||||||
|
|
||||||
public enum ProviderMigrationProgress
|
public enum ProviderMigrationProgress
|
||||||
{
|
{
|
@ -1,8 +1,8 @@
|
|||||||
using Bit.Core.Billing.Migration.Services;
|
using Bit.Core.Billing.Providers.Migration.Services;
|
||||||
using Bit.Core.Billing.Migration.Services.Implementations;
|
using Bit.Core.Billing.Providers.Migration.Services.Implementations;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Migration;
|
namespace Bit.Core.Billing.Providers.Migration;
|
||||||
|
|
||||||
public static class ServiceCollectionExtensions
|
public static class ServiceCollectionExtensions
|
||||||
{
|
{
|
@ -1,8 +1,8 @@
|
|||||||
using Bit.Core.AdminConsole.Entities;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Bit.Core.AdminConsole.Entities.Provider;
|
using Bit.Core.AdminConsole.Entities.Provider;
|
||||||
using Bit.Core.Billing.Migration.Models;
|
using Bit.Core.Billing.Providers.Migration.Models;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Migration.Services;
|
namespace Bit.Core.Billing.Providers.Migration.Services;
|
||||||
|
|
||||||
public interface IMigrationTrackerCache
|
public interface IMigrationTrackerCache
|
||||||
{
|
{
|
@ -1,6 +1,6 @@
|
|||||||
using Bit.Core.AdminConsole.Entities;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Migration.Services;
|
namespace Bit.Core.Billing.Providers.Migration.Services;
|
||||||
|
|
||||||
public interface IOrganizationMigrator
|
public interface IOrganizationMigrator
|
||||||
{
|
{
|
@ -1,6 +1,6 @@
|
|||||||
using Bit.Core.Billing.Migration.Models;
|
using Bit.Core.Billing.Providers.Migration.Models;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Migration.Services;
|
namespace Bit.Core.Billing.Providers.Migration.Services;
|
||||||
|
|
||||||
public interface IProviderMigrator
|
public interface IProviderMigrator
|
||||||
{
|
{
|
@ -1,11 +1,11 @@
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using Bit.Core.AdminConsole.Entities;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Bit.Core.AdminConsole.Entities.Provider;
|
using Bit.Core.AdminConsole.Entities.Provider;
|
||||||
using Bit.Core.Billing.Migration.Models;
|
using Bit.Core.Billing.Providers.Migration.Models;
|
||||||
using Microsoft.Extensions.Caching.Distributed;
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Migration.Services.Implementations;
|
namespace Bit.Core.Billing.Providers.Migration.Services.Implementations;
|
||||||
|
|
||||||
public class MigrationTrackerDistributedCache(
|
public class MigrationTrackerDistributedCache(
|
||||||
[FromKeyedServices("persistent")]
|
[FromKeyedServices("persistent")]
|
@ -1,10 +1,10 @@
|
|||||||
using Bit.Core.AdminConsole.Entities;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Bit.Core.Billing.Constants;
|
using Bit.Core.Billing.Constants;
|
||||||
using Bit.Core.Billing.Entities;
|
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Migration.Models;
|
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
|
using Bit.Core.Billing.Providers.Migration.Models;
|
||||||
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
using Bit.Core.Services;
|
using Bit.Core.Services;
|
||||||
@ -12,7 +12,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using Stripe;
|
using Stripe;
|
||||||
using Plan = Bit.Core.Models.StaticStore.Plan;
|
using Plan = Bit.Core.Models.StaticStore.Plan;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Migration.Services.Implementations;
|
namespace Bit.Core.Billing.Providers.Migration.Services.Implementations;
|
||||||
|
|
||||||
public class OrganizationMigrator(
|
public class OrganizationMigrator(
|
||||||
IClientOrganizationMigrationRecordRepository clientOrganizationMigrationRecordRepository,
|
IClientOrganizationMigrationRecordRepository clientOrganizationMigrationRecordRepository,
|
@ -3,18 +3,18 @@ using Bit.Core.AdminConsole.Entities.Provider;
|
|||||||
using Bit.Core.AdminConsole.Enums.Provider;
|
using Bit.Core.AdminConsole.Enums.Provider;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Billing.Constants;
|
using Bit.Core.Billing.Constants;
|
||||||
using Bit.Core.Billing.Entities;
|
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Migration.Models;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Migration.Models;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Providers.Models;
|
||||||
using Bit.Core.Billing.Services.Contracts;
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
using Bit.Core.Services;
|
using Bit.Core.Services;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Stripe;
|
using Stripe;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Migration.Services.Implementations;
|
namespace Bit.Core.Billing.Providers.Migration.Services.Implementations;
|
||||||
|
|
||||||
public class ProviderMigrator(
|
public class ProviderMigrator(
|
||||||
IClientOrganizationMigrationRecordRepository clientOrganizationMigrationRecordRepository,
|
IClientOrganizationMigrationRecordRepository clientOrganizationMigrationRecordRepository,
|
@ -1,4 +1,4 @@
|
|||||||
namespace Bit.Core.Billing.Models;
|
namespace Bit.Core.Billing.Providers.Models;
|
||||||
|
|
||||||
public record AddableOrganization(
|
public record AddableOrganization(
|
||||||
Guid Id,
|
Guid Id,
|
@ -1,7 +1,7 @@
|
|||||||
using Bit.Core.AdminConsole.Entities.Provider;
|
using Bit.Core.AdminConsole.Entities.Provider;
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Services.Contracts;
|
namespace Bit.Core.Billing.Providers.Models;
|
||||||
|
|
||||||
public record ChangeProviderPlanCommand(
|
public record ChangeProviderPlanCommand(
|
||||||
Provider Provider,
|
Provider Provider,
|
@ -1,11 +1,12 @@
|
|||||||
using Bit.Core.Models.StaticStore;
|
using Bit.Core.Models.StaticStore;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Models;
|
namespace Bit.Core.Billing.Providers.Models;
|
||||||
|
|
||||||
public record ConfiguredProviderPlan(
|
public record ConfiguredProviderPlan(
|
||||||
Guid Id,
|
Guid Id,
|
||||||
Guid ProviderId,
|
Guid ProviderId,
|
||||||
Plan Plan,
|
Plan Plan,
|
||||||
|
decimal Price,
|
||||||
int SeatMinimum,
|
int SeatMinimum,
|
||||||
int PurchasedSeats,
|
int PurchasedSeats,
|
||||||
int AssignedSeats);
|
int AssignedSeats);
|
@ -1,7 +1,7 @@
|
|||||||
using Bit.Core.AdminConsole.Entities.Provider;
|
using Bit.Core.AdminConsole.Entities.Provider;
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Services.Contracts;
|
namespace Bit.Core.Billing.Providers.Models;
|
||||||
|
|
||||||
/// <param name="Provider">The provider to update the seat minimums for.</param>
|
/// <param name="Provider">The provider to update the seat minimums for.</param>
|
||||||
/// <param name="Configuration">The new seat minimums for the provider.</param>
|
/// <param name="Configuration">The new seat minimums for the provider.</param>
|
@ -1,7 +1,7 @@
|
|||||||
using Bit.Core.Billing.Entities;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Repositories;
|
namespace Bit.Core.Billing.Providers.Repositories;
|
||||||
|
|
||||||
public interface IClientOrganizationMigrationRecordRepository : IRepository<ClientOrganizationMigrationRecord, Guid>
|
public interface IClientOrganizationMigrationRecordRepository : IRepository<ClientOrganizationMigrationRecord, Guid>
|
||||||
{
|
{
|
@ -1,7 +1,7 @@
|
|||||||
using Bit.Core.Billing.Entities;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Repositories;
|
namespace Bit.Core.Billing.Providers.Repositories;
|
||||||
|
|
||||||
public interface IProviderInvoiceItemRepository : IRepository<ProviderInvoiceItem, Guid>
|
public interface IProviderInvoiceItemRepository : IRepository<ProviderInvoiceItem, Guid>
|
||||||
{
|
{
|
@ -1,7 +1,7 @@
|
|||||||
using Bit.Core.Billing.Entities;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Repositories;
|
namespace Bit.Core.Billing.Providers.Repositories;
|
||||||
|
|
||||||
public interface IProviderPlanRepository : IRepository<ProviderPlan, Guid>
|
public interface IProviderPlanRepository : IRepository<ProviderPlan, Guid>
|
||||||
{
|
{
|
@ -3,7 +3,7 @@ using Bit.Core.AdminConsole.Entities.Provider;
|
|||||||
using Bit.Core.AdminConsole.Enums.Provider;
|
using Bit.Core.AdminConsole.Enums.Provider;
|
||||||
using OneOf;
|
using OneOf;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Services;
|
namespace Bit.Core.Billing.Providers.Services;
|
||||||
|
|
||||||
public interface IBusinessUnitConverter
|
public interface IBusinessUnitConverter
|
||||||
{
|
{
|
@ -1,14 +1,14 @@
|
|||||||
using Bit.Core.AdminConsole.Entities;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Bit.Core.AdminConsole.Entities.Provider;
|
using Bit.Core.AdminConsole.Entities.Provider;
|
||||||
using Bit.Core.Billing.Entities;
|
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Models;
|
using Bit.Core.Billing.Models;
|
||||||
using Bit.Core.Billing.Services.Contracts;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
|
using Bit.Core.Billing.Providers.Models;
|
||||||
using Bit.Core.Billing.Tax.Models;
|
using Bit.Core.Billing.Tax.Models;
|
||||||
using Bit.Core.Models.Business;
|
using Bit.Core.Models.Business;
|
||||||
using Stripe;
|
using Stripe;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Services;
|
namespace Bit.Core.Billing.Providers.Services;
|
||||||
|
|
||||||
public interface IProviderBillingService
|
public interface IProviderBillingService
|
||||||
{
|
{
|
@ -2,7 +2,7 @@
|
|||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Services.Contracts;
|
namespace Bit.Core.Billing.Tax.Models;
|
||||||
|
|
||||||
public class AutomaticTaxFactoryParameters
|
public class AutomaticTaxFactoryParameters
|
||||||
{
|
{
|
@ -1,4 +1,4 @@
|
|||||||
using Bit.Core.Billing.Services.Contracts;
|
using Bit.Core.Billing.Tax.Models;
|
||||||
|
|
||||||
namespace Bit.Core.Billing.Tax.Services;
|
namespace Bit.Core.Billing.Tax.Services;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Services.Contracts;
|
using Bit.Core.Billing.Tax.Models;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
using Bit.Core.Services;
|
using Bit.Core.Services;
|
||||||
|
|
||||||
|
@ -150,6 +150,7 @@ public static class FeatureFlagKeys
|
|||||||
public const string UseOrganizationWarningsService = "use-organization-warnings-service";
|
public const string UseOrganizationWarningsService = "use-organization-warnings-service";
|
||||||
public const string PM20322_AllowTrialLength0 = "pm-20322-allow-trial-length-0";
|
public const string PM20322_AllowTrialLength0 = "pm-20322-allow-trial-length-0";
|
||||||
public const string PM21092_SetNonUSBusinessUseToReverseCharge = "pm-21092-set-non-us-business-use-to-reverse-charge";
|
public const string PM21092_SetNonUSBusinessUseToReverseCharge = "pm-21092-set-non-us-business-use-to-reverse-charge";
|
||||||
|
public const string PM21383_GetProviderPriceFromStripe = "pm-21383-get-provider-price-from-stripe";
|
||||||
|
|
||||||
/* Data Insights and Reporting Team */
|
/* Data Insights and Reporting Team */
|
||||||
public const string RiskInsightsCriticalApplication = "pm-14466-risk-insights-critical-application";
|
public const string RiskInsightsCriticalApplication = "pm-14466-risk-insights-critical-application";
|
||||||
|
@ -69,8 +69,11 @@ public static class OrganizationServiceCollectionExtensions
|
|||||||
services.AddBaseOrganizationSubscriptionCommandsQueries();
|
services.AddBaseOrganizationSubscriptionCommandsQueries();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IServiceCollection AddOrganizationSignUpCommands(this IServiceCollection services) =>
|
private static void AddOrganizationSignUpCommands(this IServiceCollection services)
|
||||||
|
{
|
||||||
services.AddScoped<ICloudOrganizationSignUpCommand, CloudOrganizationSignUpCommand>();
|
services.AddScoped<ICloudOrganizationSignUpCommand, CloudOrganizationSignUpCommand>();
|
||||||
|
services.AddScoped<IProviderClientOrganizationSignUpCommand, ProviderClientOrganizationSignUpCommand>();
|
||||||
|
}
|
||||||
|
|
||||||
private static void AddOrganizationDeleteCommands(this IServiceCollection services)
|
private static void AddOrganizationDeleteCommands(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
@ -57,4 +57,5 @@ public interface IStripeAdapter
|
|||||||
Task<SetupIntent> SetupIntentGet(string id, SetupIntentGetOptions options = null);
|
Task<SetupIntent> SetupIntentGet(string id, SetupIntentGetOptions options = null);
|
||||||
Task SetupIntentVerifyMicroDeposit(string id, SetupIntentVerifyMicrodepositsOptions options);
|
Task SetupIntentVerifyMicroDeposit(string id, SetupIntentVerifyMicrodepositsOptions options);
|
||||||
Task<List<Stripe.TestHelpers.TestClock>> TestClockListAsync();
|
Task<List<Stripe.TestHelpers.TestClock>> TestClockListAsync();
|
||||||
|
Task<Price> PriceGetAsync(string id, PriceGetOptions options = null);
|
||||||
}
|
}
|
||||||
|
@ -283,4 +283,7 @@ public class StripeAdapter : IStripeAdapter
|
|||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task<Price> PriceGetAsync(string id, PriceGetOptions options = null)
|
||||||
|
=> _priceService.GetAsync(id, options);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ using Bit.Core.Billing.Extensions;
|
|||||||
using Bit.Core.Billing.Models;
|
using Bit.Core.Billing.Models;
|
||||||
using Bit.Core.Billing.Models.Business;
|
using Bit.Core.Billing.Models.Business;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Services.Contracts;
|
using Bit.Core.Billing.Tax.Models;
|
||||||
using Bit.Core.Billing.Tax.Requests;
|
using Bit.Core.Billing.Tax.Requests;
|
||||||
using Bit.Core.Billing.Tax.Responses;
|
using Bit.Core.Billing.Tax.Responses;
|
||||||
using Bit.Core.Billing.Tax.Services;
|
using Bit.Core.Billing.Tax.Services;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using System.Data;
|
using System.Data;
|
||||||
using Bit.Core.Billing.Entities;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
using Bit.Core.Settings;
|
using Bit.Core.Settings;
|
||||||
using Bit.Infrastructure.Dapper.Repositories;
|
using Bit.Infrastructure.Dapper.Repositories;
|
||||||
using Dapper;
|
using Dapper;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using System.Data;
|
using System.Data;
|
||||||
using Bit.Core.Billing.Entities;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
using Bit.Core.Settings;
|
using Bit.Core.Settings;
|
||||||
using Bit.Infrastructure.Dapper.Repositories;
|
using Bit.Infrastructure.Dapper.Repositories;
|
||||||
using Dapper;
|
using Dapper;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using System.Data;
|
using System.Data;
|
||||||
using Bit.Core.Billing.Entities;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
using Bit.Core.Settings;
|
using Bit.Core.Settings;
|
||||||
using Bit.Infrastructure.Dapper.Repositories;
|
using Bit.Infrastructure.Dapper.Repositories;
|
||||||
using Dapper;
|
using Dapper;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Auth.Repositories;
|
using Bit.Core.Auth.Repositories;
|
||||||
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Repositories;
|
||||||
using Bit.Core.KeyManagement.Repositories;
|
using Bit.Core.KeyManagement.Repositories;
|
||||||
using Bit.Core.NotificationCenter.Repositories;
|
using Bit.Core.NotificationCenter.Repositories;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Bit.Infrastructure.EntityFramework.Billing.Models;
|
namespace Bit.Infrastructure.EntityFramework.Billing.Models;
|
||||||
|
|
||||||
public class ClientOrganizationMigrationRecord : Core.Billing.Entities.ClientOrganizationMigrationRecord
|
public class ClientOrganizationMigrationRecord : Core.Billing.Providers.Entities.ClientOrganizationMigrationRecord
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -11,6 +11,6 @@ public class ClientOrganizationMigrationRecordProfile : Profile
|
|||||||
{
|
{
|
||||||
public ClientOrganizationMigrationRecordProfile()
|
public ClientOrganizationMigrationRecordProfile()
|
||||||
{
|
{
|
||||||
CreateMap<Core.Billing.Entities.ClientOrganizationMigrationRecord, ClientOrganizationMigrationRecord>().ReverseMap();
|
CreateMap<Core.Billing.Providers.Entities.ClientOrganizationMigrationRecord, ClientOrganizationMigrationRecord>().ReverseMap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ using Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider;
|
|||||||
namespace Bit.Infrastructure.EntityFramework.Billing.Models;
|
namespace Bit.Infrastructure.EntityFramework.Billing.Models;
|
||||||
|
|
||||||
// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global
|
// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global
|
||||||
public class ProviderInvoiceItem : Core.Billing.Entities.ProviderInvoiceItem
|
public class ProviderInvoiceItem : Core.Billing.Providers.Entities.ProviderInvoiceItem
|
||||||
{
|
{
|
||||||
public virtual Provider Provider { get; set; }
|
public virtual Provider Provider { get; set; }
|
||||||
}
|
}
|
||||||
@ -13,6 +13,6 @@ public class ProviderInvoiceItemMapperProfile : Profile
|
|||||||
{
|
{
|
||||||
public ProviderInvoiceItemMapperProfile()
|
public ProviderInvoiceItemMapperProfile()
|
||||||
{
|
{
|
||||||
CreateMap<Core.Billing.Entities.ProviderInvoiceItem, ProviderInvoiceItem>().ReverseMap();
|
CreateMap<Core.Billing.Providers.Entities.ProviderInvoiceItem, ProviderInvoiceItem>().ReverseMap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ using Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider;
|
|||||||
namespace Bit.Infrastructure.EntityFramework.Billing.Models;
|
namespace Bit.Infrastructure.EntityFramework.Billing.Models;
|
||||||
|
|
||||||
// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global
|
// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global
|
||||||
public class ProviderPlan : Core.Billing.Entities.ProviderPlan
|
public class ProviderPlan : Core.Billing.Providers.Entities.ProviderPlan
|
||||||
{
|
{
|
||||||
public virtual Provider Provider { get; set; }
|
public virtual Provider Provider { get; set; }
|
||||||
}
|
}
|
||||||
@ -13,6 +13,6 @@ public class ProviderPlanMapperProfile : Profile
|
|||||||
{
|
{
|
||||||
public ProviderPlanMapperProfile()
|
public ProviderPlanMapperProfile()
|
||||||
{
|
{
|
||||||
CreateMap<Core.Billing.Entities.ProviderPlan, ProviderPlan>().ReverseMap();
|
CreateMap<Core.Billing.Providers.Entities.ProviderPlan, ProviderPlan>().ReverseMap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Bit.Core.Billing.Entities;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
using Bit.Infrastructure.EntityFramework.Repositories;
|
using Bit.Infrastructure.EntityFramework.Repositories;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Bit.Core.Billing.Entities;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
using Bit.Infrastructure.EntityFramework.Repositories;
|
using Bit.Infrastructure.EntityFramework.Repositories;
|
||||||
using LinqToDB;
|
using LinqToDB;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Bit.Core.Billing.Entities;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
using Bit.Infrastructure.EntityFramework.Repositories;
|
using Bit.Infrastructure.EntityFramework.Repositories;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Auth.Repositories;
|
using Bit.Core.Auth.Repositories;
|
||||||
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Repositories;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.KeyManagement.Repositories;
|
using Bit.Core.KeyManagement.Repositories;
|
||||||
|
@ -5,7 +5,7 @@ using Bit.Core.AdminConsole.Entities.Provider;
|
|||||||
using Bit.Core.AdminConsole.Enums.Provider;
|
using Bit.Core.AdminConsole.Enums.Provider;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
using Bit.Test.Common.AutoFixture;
|
using Bit.Test.Common.AutoFixture;
|
||||||
|
@ -21,7 +21,7 @@ using Bit.Core.Auth.Repositories;
|
|||||||
using Bit.Core.Auth.Services;
|
using Bit.Core.Auth.Services;
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
|
@ -6,7 +6,7 @@ using Bit.Core.AdminConsole.Entities.Provider;
|
|||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.AdminConsole.Services;
|
using Bit.Core.AdminConsole.Services;
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
using Bit.Api.Billing.Controllers;
|
using Bit.Api.Billing.Controllers;
|
||||||
using Bit.Api.Billing.Models.Requests;
|
using Bit.Api.Billing.Models.Requests;
|
||||||
using Bit.Api.Billing.Models.Responses;
|
using Bit.Api.Billing.Models.Responses;
|
||||||
|
using Bit.Commercial.Core.Billing.Providers.Services;
|
||||||
|
using Bit.Core;
|
||||||
using Bit.Core.AdminConsole.Entities.Provider;
|
using Bit.Core.AdminConsole.Entities.Provider;
|
||||||
using Bit.Core.AdminConsole.Enums.Provider;
|
using Bit.Core.AdminConsole.Enums.Provider;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Billing.Constants;
|
using Bit.Core.Billing.Constants;
|
||||||
using Bit.Core.Billing.Entities;
|
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
|
using Bit.Core.Billing.Providers.Services;
|
||||||
using Bit.Core.Billing.Services;
|
using Bit.Core.Billing.Services;
|
||||||
using Bit.Core.Billing.Tax.Models;
|
using Bit.Core.Billing.Tax.Models;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
@ -285,6 +288,19 @@ public class ProviderBillingControllerTests
|
|||||||
Discount = new Discount { Coupon = new Coupon { PercentOff = 10 } },
|
Discount = new Discount { Coupon = new Coupon { PercentOff = 10 } },
|
||||||
TaxIds = new StripeList<TaxId> { Data = [new TaxId { Value = "123456789" }] }
|
TaxIds = new StripeList<TaxId> { Data = [new TaxId { Value = "123456789" }] }
|
||||||
},
|
},
|
||||||
|
Items = new StripeList<SubscriptionItem>
|
||||||
|
{
|
||||||
|
Data = [
|
||||||
|
new SubscriptionItem
|
||||||
|
{
|
||||||
|
Price = new Price { Id = ProviderPriceAdapter.MSP.Active.Enterprise }
|
||||||
|
},
|
||||||
|
new SubscriptionItem
|
||||||
|
{
|
||||||
|
Price = new Price { Id = ProviderPriceAdapter.MSP.Active.Teams }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
Status = "unpaid",
|
Status = "unpaid",
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -330,11 +346,21 @@ public class ProviderBillingControllerTests
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IFeatureService>().IsEnabled(FeatureFlagKeys.PM21383_GetProviderPriceFromStripe)
|
||||||
|
.Returns(true);
|
||||||
|
|
||||||
sutProvider.GetDependency<IProviderPlanRepository>().GetByProviderId(provider.Id).Returns(providerPlans);
|
sutProvider.GetDependency<IProviderPlanRepository>().GetByProviderId(provider.Id).Returns(providerPlans);
|
||||||
|
|
||||||
foreach (var providerPlan in providerPlans)
|
foreach (var providerPlan in providerPlans)
|
||||||
{
|
{
|
||||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(providerPlan.PlanType).Returns(StaticStore.GetPlan(providerPlan.PlanType));
|
var plan = StaticStore.GetPlan(providerPlan.PlanType);
|
||||||
|
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(providerPlan.PlanType).Returns(plan);
|
||||||
|
var priceId = ProviderPriceAdapter.GetPriceId(provider, subscription, providerPlan.PlanType);
|
||||||
|
sutProvider.GetDependency<IStripeAdapter>().PriceGetAsync(priceId)
|
||||||
|
.Returns(new Price
|
||||||
|
{
|
||||||
|
UnitAmountDecimal = plan.PasswordManager.ProviderPortalSeatPrice * 100
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await sutProvider.Sut.GetSubscriptionAsync(provider.Id);
|
var result = await sutProvider.Sut.GetSubscriptionAsync(provider.Id);
|
||||||
|
@ -4,10 +4,10 @@ using Bit.Billing.Test.Utilities;
|
|||||||
using Bit.Core.AdminConsole.Entities;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Bit.Core.AdminConsole.Models.Data.Provider;
|
using Bit.Core.AdminConsole.Models.Data.Provider;
|
||||||
using Bit.Core.AdminConsole.Repositories;
|
using Bit.Core.AdminConsole.Repositories;
|
||||||
using Bit.Core.Billing.Entities;
|
|
||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Repositories;
|
using Bit.Core.Billing.Providers.Entities;
|
||||||
|
using Bit.Core.Billing.Providers.Repositories;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
@ -0,0 +1,169 @@
|
|||||||
|
using Bit.Core.AdminConsole.Entities;
|
||||||
|
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations;
|
||||||
|
using Bit.Core.Billing.Enums;
|
||||||
|
using Bit.Core.Billing.Pricing;
|
||||||
|
using Bit.Core.Entities;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Exceptions;
|
||||||
|
using Bit.Core.Models.Business;
|
||||||
|
using Bit.Core.Models.Data;
|
||||||
|
using Bit.Core.Models.StaticStore;
|
||||||
|
using Bit.Core.Repositories;
|
||||||
|
using Bit.Core.Services;
|
||||||
|
using Bit.Core.Tools.Enums;
|
||||||
|
using Bit.Core.Tools.Models.Business;
|
||||||
|
using Bit.Core.Tools.Services;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
|
using Bit.Test.Common.AutoFixture;
|
||||||
|
using Bit.Test.Common.AutoFixture.Attributes;
|
||||||
|
using NSubstitute;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.Organizations.OrganizationSignUp;
|
||||||
|
|
||||||
|
[SutProviderCustomize]
|
||||||
|
public class ProviderClientOrganizationSignUpCommandTests
|
||||||
|
{
|
||||||
|
[Theory]
|
||||||
|
[BitAutoData(PlanType.TeamsAnnually)]
|
||||||
|
[BitAutoData(PlanType.TeamsMonthly)]
|
||||||
|
[BitAutoData(PlanType.EnterpriseAnnually)]
|
||||||
|
[BitAutoData(PlanType.EnterpriseMonthly)]
|
||||||
|
public async Task SignupClientAsync_ValidParameters_CreatesOrganizationSuccessfully(
|
||||||
|
PlanType planType,
|
||||||
|
OrganizationSignup signup,
|
||||||
|
string collectionName,
|
||||||
|
SutProvider<ProviderClientOrganizationSignUpCommand> sutProvider)
|
||||||
|
{
|
||||||
|
signup.Plan = planType;
|
||||||
|
signup.AdditionalSeats = 15;
|
||||||
|
signup.CollectionName = collectionName;
|
||||||
|
|
||||||
|
var plan = StaticStore.GetPlan(signup.Plan);
|
||||||
|
sutProvider.GetDependency<IPricingClient>()
|
||||||
|
.GetPlanOrThrow(signup.Plan)
|
||||||
|
.Returns(plan);
|
||||||
|
|
||||||
|
var result = await sutProvider.Sut.SignUpClientOrganizationAsync(signup);
|
||||||
|
|
||||||
|
Assert.NotNull(result.Organization);
|
||||||
|
Assert.NotNull(result.DefaultCollection);
|
||||||
|
Assert.Equal(collectionName, result.DefaultCollection.Name);
|
||||||
|
|
||||||
|
await sutProvider.GetDependency<IOrganizationRepository>()
|
||||||
|
.Received(1)
|
||||||
|
.CreateAsync(
|
||||||
|
Arg.Is<Organization>(o =>
|
||||||
|
o.Name == signup.Name &&
|
||||||
|
o.BillingEmail == signup.BillingEmail &&
|
||||||
|
o.PlanType == plan.Type &&
|
||||||
|
o.Seats == signup.AdditionalSeats &&
|
||||||
|
o.MaxCollections == plan.PasswordManager.MaxCollections &&
|
||||||
|
o.UsePasswordManager == true &&
|
||||||
|
o.UseSecretsManager == false &&
|
||||||
|
o.Status == OrganizationStatusType.Created
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
await sutProvider.GetDependency<IReferenceEventService>()
|
||||||
|
.Received(1)
|
||||||
|
.RaiseEventAsync(Arg.Is<ReferenceEvent>(referenceEvent =>
|
||||||
|
referenceEvent.Type == ReferenceEventType.Signup &&
|
||||||
|
referenceEvent.PlanName == plan.Name &&
|
||||||
|
referenceEvent.PlanType == plan.Type &&
|
||||||
|
referenceEvent.Seats == result.Organization.Seats &&
|
||||||
|
referenceEvent.Storage == result.Organization.MaxStorageGb &&
|
||||||
|
referenceEvent.SignupInitiationPath == signup.InitiationPath
|
||||||
|
));
|
||||||
|
|
||||||
|
await sutProvider.GetDependency<ICollectionRepository>()
|
||||||
|
.Received(1)
|
||||||
|
.CreateAsync(
|
||||||
|
Arg.Is<Collection>(c =>
|
||||||
|
c.Name == collectionName &&
|
||||||
|
c.OrganizationId == result.Organization.Id
|
||||||
|
),
|
||||||
|
Arg.Any<IEnumerable<CollectionAccessSelection>>(),
|
||||||
|
Arg.Any<IEnumerable<CollectionAccessSelection>>()
|
||||||
|
);
|
||||||
|
|
||||||
|
await sutProvider.GetDependency<IOrganizationApiKeyRepository>()
|
||||||
|
.Received(1)
|
||||||
|
.CreateAsync(
|
||||||
|
Arg.Is<OrganizationApiKey>(k =>
|
||||||
|
k.OrganizationId == result.Organization.Id &&
|
||||||
|
k.Type == OrganizationApiKeyType.Default
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
await sutProvider.GetDependency<IApplicationCacheService>()
|
||||||
|
.Received(1)
|
||||||
|
.UpsertOrganizationAbilityAsync(Arg.Is<Organization>(o => o.Id == result.Organization.Id));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[BitAutoData]
|
||||||
|
public async Task SignupClientAsync_NullPlan_ThrowsBadRequestException(
|
||||||
|
OrganizationSignup signup,
|
||||||
|
SutProvider<ProviderClientOrganizationSignUpCommand> sutProvider)
|
||||||
|
{
|
||||||
|
sutProvider.GetDependency<IPricingClient>()
|
||||||
|
.GetPlanOrThrow(signup.Plan)
|
||||||
|
.Returns((Plan)null);
|
||||||
|
|
||||||
|
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||||
|
() => sutProvider.Sut.SignUpClientOrganizationAsync(signup));
|
||||||
|
|
||||||
|
Assert.Contains(ProviderClientOrganizationSignUpCommand.PlanNullErrorMessage, exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[BitAutoData]
|
||||||
|
public async Task SignupClientAsync_NegativeAdditionalSeats_ThrowsBadRequestException(
|
||||||
|
OrganizationSignup signup,
|
||||||
|
SutProvider<ProviderClientOrganizationSignUpCommand> sutProvider)
|
||||||
|
{
|
||||||
|
signup.Plan = PlanType.TeamsMonthly;
|
||||||
|
signup.AdditionalSeats = -5;
|
||||||
|
|
||||||
|
var plan = StaticStore.GetPlan(signup.Plan);
|
||||||
|
sutProvider.GetDependency<IPricingClient>()
|
||||||
|
.GetPlanOrThrow(signup.Plan)
|
||||||
|
.Returns(plan);
|
||||||
|
|
||||||
|
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||||
|
() => sutProvider.Sut.SignUpClientOrganizationAsync(signup));
|
||||||
|
|
||||||
|
Assert.Contains(ProviderClientOrganizationSignUpCommand.AdditionalSeatsNegativeErrorMessage, exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[BitAutoData(PlanType.TeamsAnnually)]
|
||||||
|
public async Task SignupClientAsync_WhenExceptionIsThrown_CleanupIsPerformed(
|
||||||
|
PlanType planType,
|
||||||
|
OrganizationSignup signup,
|
||||||
|
SutProvider<ProviderClientOrganizationSignUpCommand> sutProvider)
|
||||||
|
{
|
||||||
|
signup.Plan = planType;
|
||||||
|
|
||||||
|
var plan = StaticStore.GetPlan(signup.Plan);
|
||||||
|
sutProvider.GetDependency<IPricingClient>()
|
||||||
|
.GetPlanOrThrow(signup.Plan)
|
||||||
|
.Returns(plan);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IOrganizationApiKeyRepository>()
|
||||||
|
.When(x => x.CreateAsync(Arg.Any<OrganizationApiKey>()))
|
||||||
|
.Do(_ => throw new Exception());
|
||||||
|
|
||||||
|
var thrownException = await Assert.ThrowsAsync<Exception>(
|
||||||
|
() => sutProvider.Sut.SignUpClientOrganizationAsync(signup));
|
||||||
|
|
||||||
|
await sutProvider.GetDependency<IOrganizationRepository>()
|
||||||
|
.Received(1)
|
||||||
|
.DeleteAsync(Arg.Is<Organization>(o => o.Name == signup.Name));
|
||||||
|
|
||||||
|
await sutProvider.GetDependency<IApplicationCacheService>()
|
||||||
|
.Received(1)
|
||||||
|
.DeleteOrganizationAbilityAsync(Arg.Any<Guid>());
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,6 @@ using Bit.Core.Auth.Models.Business.Tokenables;
|
|||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
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.Models.Business;
|
using Bit.Core.Models.Business;
|
||||||
@ -177,47 +176,6 @@ public class OrganizationServiceTests
|
|||||||
referenceEvent.Users == expectedNewUsersCount));
|
referenceEvent.Users == expectedNewUsersCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory, BitAutoData]
|
|
||||||
public async Task SignupClientAsync_Succeeds(
|
|
||||||
OrganizationSignup signup,
|
|
||||||
SutProvider<OrganizationService> sutProvider)
|
|
||||||
{
|
|
||||||
signup.Plan = PlanType.TeamsMonthly;
|
|
||||||
|
|
||||||
var plan = StaticStore.GetPlan(signup.Plan);
|
|
||||||
|
|
||||||
sutProvider.GetDependency<IPricingClient>().GetPlanOrThrow(signup.Plan).Returns(plan);
|
|
||||||
|
|
||||||
var (organization, _, _) = await sutProvider.Sut.SignupClientAsync(signup);
|
|
||||||
|
|
||||||
await sutProvider.GetDependency<IOrganizationRepository>().Received(1).CreateAsync(Arg.Is<Organization>(org =>
|
|
||||||
org.Id == organization.Id &&
|
|
||||||
org.Name == signup.Name &&
|
|
||||||
org.Plan == plan.Name &&
|
|
||||||
org.PlanType == plan.Type &&
|
|
||||||
org.UsePolicies == plan.HasPolicies &&
|
|
||||||
org.PublicKey == signup.PublicKey &&
|
|
||||||
org.PrivateKey == signup.PrivateKey &&
|
|
||||||
org.UseSecretsManager == false));
|
|
||||||
|
|
||||||
await sutProvider.GetDependency<IOrganizationApiKeyRepository>().Received(1)
|
|
||||||
.CreateAsync(Arg.Is<OrganizationApiKey>(orgApiKey =>
|
|
||||||
orgApiKey.OrganizationId == organization.Id));
|
|
||||||
|
|
||||||
await sutProvider.GetDependency<IApplicationCacheService>().Received(1)
|
|
||||||
.UpsertOrganizationAbilityAsync(organization);
|
|
||||||
|
|
||||||
await sutProvider.GetDependency<IOrganizationUserRepository>().DidNotReceiveWithAnyArgs().CreateAsync(default);
|
|
||||||
|
|
||||||
await sutProvider.GetDependency<ICollectionRepository>().Received(1)
|
|
||||||
.CreateAsync(Arg.Is<Collection>(c => c.Name == signup.CollectionName && c.OrganizationId == organization.Id), null, null);
|
|
||||||
|
|
||||||
await sutProvider.GetDependency<IReferenceEventService>().Received(1).RaiseEventAsync(Arg.Is<ReferenceEvent>(
|
|
||||||
re =>
|
|
||||||
re.Type == ReferenceEventType.Signup &&
|
|
||||||
re.PlanType == plan.Type));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[OrganizationInviteCustomize(InviteeUserType = OrganizationUserType.User,
|
[OrganizationInviteCustomize(InviteeUserType = OrganizationUserType.User,
|
||||||
InvitorUserType = OrganizationUserType.Owner), OrganizationCustomize, BitAutoData]
|
InvitorUserType = OrganizationUserType.Owner), OrganizationCustomize, BitAutoData]
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Models.StaticStore.Plans;
|
using Bit.Core.Billing.Models.StaticStore.Plans;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Services.Contracts;
|
using Bit.Core.Billing.Tax.Models;
|
||||||
using Bit.Core.Billing.Tax.Services.Implementations;
|
using Bit.Core.Billing.Tax.Services.Implementations;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
using Bit.Test.Common.AutoFixture;
|
using Bit.Test.Common.AutoFixture;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
using Bit.Core.Billing.Enums;
|
using Bit.Core.Billing.Enums;
|
||||||
using Bit.Core.Billing.Models.StaticStore.Plans;
|
using Bit.Core.Billing.Models.StaticStore.Plans;
|
||||||
using Bit.Core.Billing.Pricing;
|
using Bit.Core.Billing.Pricing;
|
||||||
using Bit.Core.Billing.Services.Contracts;
|
using Bit.Core.Billing.Tax.Models;
|
||||||
using Bit.Core.Billing.Tax.Requests;
|
using Bit.Core.Billing.Tax.Requests;
|
||||||
using Bit.Core.Billing.Tax.Services;
|
using Bit.Core.Billing.Tax.Services;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user