mirror of
https://github.com/bitwarden/server.git
synced 2025-05-12 15:12:16 -05:00
Rename ProviderClientOrganizationSignUpCommand
This commit is contained in:
parent
974ca2724c
commit
753d1311d4
@ -1,15 +0,0 @@
|
|||||||
using Bit.Core.AdminConsole.Entities;
|
|
||||||
using Bit.Core.Entities;
|
|
||||||
using Bit.Core.Models.Business;
|
|
||||||
|
|
||||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.Organizations.Interfaces;
|
|
||||||
|
|
||||||
public interface ISignUpProviderClientOrganizationCommand
|
|
||||||
{
|
|
||||||
/// <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<(Organization organization, Collection defaultCollection)> SignUpClientOrganizationAsync(OrganizationSignup signup);
|
|
||||||
}
|
|
@ -1,5 +1,4 @@
|
|||||||
using Bit.Core.AdminConsole.Entities;
|
using Bit.Core.AdminConsole.Entities;
|
||||||
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations.Interfaces;
|
|
||||||
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.Entities;
|
||||||
@ -16,7 +15,21 @@ using Bit.Core.Utilities;
|
|||||||
|
|
||||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.Organizations;
|
namespace Bit.Core.AdminConsole.OrganizationFeatures.Organizations;
|
||||||
|
|
||||||
public class SignUpProviderClientOrganizationCommand : ISignUpProviderClientOrganizationCommand
|
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
|
||||||
{
|
{
|
||||||
private readonly ICurrentContext _currentContext;
|
private readonly ICurrentContext _currentContext;
|
||||||
private readonly IPricingClient _pricingClient;
|
private readonly IPricingClient _pricingClient;
|
||||||
@ -25,19 +38,15 @@ public class SignUpProviderClientOrganizationCommand : ISignUpProviderClientOrga
|
|||||||
private readonly IOrganizationApiKeyRepository _organizationApiKeyRepository;
|
private readonly IOrganizationApiKeyRepository _organizationApiKeyRepository;
|
||||||
private readonly IApplicationCacheService _applicationCacheService;
|
private readonly IApplicationCacheService _applicationCacheService;
|
||||||
private readonly ICollectionRepository _collectionRepository;
|
private readonly ICollectionRepository _collectionRepository;
|
||||||
private readonly IDeviceRepository _deviceRepository;
|
|
||||||
private readonly IPaymentService _paymentService;
|
|
||||||
|
|
||||||
public SignUpProviderClientOrganizationCommand(
|
public ProviderClientOrganizationSignUpCommand(
|
||||||
ICurrentContext currentContext,
|
ICurrentContext currentContext,
|
||||||
IPricingClient pricingClient,
|
IPricingClient pricingClient,
|
||||||
IReferenceEventService referenceEventService,
|
IReferenceEventService referenceEventService,
|
||||||
IOrganizationRepository organizationRepository,
|
IOrganizationRepository organizationRepository,
|
||||||
IOrganizationApiKeyRepository organizationApiKeyRepository,
|
IOrganizationApiKeyRepository organizationApiKeyRepository,
|
||||||
IApplicationCacheService applicationCacheService,
|
IApplicationCacheService applicationCacheService,
|
||||||
ICollectionRepository collectionRepository,
|
ICollectionRepository collectionRepository)
|
||||||
IDeviceRepository deviceRepository,
|
|
||||||
IPaymentService paymentService)
|
|
||||||
{
|
{
|
||||||
_currentContext = currentContext;
|
_currentContext = currentContext;
|
||||||
_pricingClient = pricingClient;
|
_pricingClient = pricingClient;
|
||||||
@ -46,15 +55,13 @@ public class SignUpProviderClientOrganizationCommand : ISignUpProviderClientOrga
|
|||||||
_organizationApiKeyRepository = organizationApiKeyRepository;
|
_organizationApiKeyRepository = organizationApiKeyRepository;
|
||||||
_applicationCacheService = applicationCacheService;
|
_applicationCacheService = applicationCacheService;
|
||||||
_collectionRepository = collectionRepository;
|
_collectionRepository = collectionRepository;
|
||||||
_deviceRepository = deviceRepository;
|
|
||||||
_paymentService = paymentService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(Organization organization, Collection defaultCollection)> SignUpClientOrganizationAsync(OrganizationSignup signup)
|
public async Task<ProviderClientOrganizationSignUpResponse> SignUpClientOrganizationAsync(OrganizationSignup signup)
|
||||||
{
|
{
|
||||||
var plan = await _pricingClient.GetPlanOrThrow(signup.Plan);
|
var plan = await _pricingClient.GetPlanOrThrow(signup.Plan);
|
||||||
|
|
||||||
ValidatePlan(plan, signup.AdditionalSeats, "Password Manager");
|
ValidatePlan(plan, signup.AdditionalSeats);
|
||||||
|
|
||||||
var organization = new Organization
|
var organization = new Organization
|
||||||
{
|
{
|
||||||
@ -101,38 +108,37 @@ public class SignUpProviderClientOrganizationCommand : ISignUpProviderClientOrga
|
|||||||
{
|
{
|
||||||
PlanName = plan.Name,
|
PlanName = plan.Name,
|
||||||
PlanType = plan.Type,
|
PlanType = plan.Type,
|
||||||
Seats = returnValue.Item1.Seats,
|
Seats = returnValue.Organization.Seats,
|
||||||
SignupInitiationPath = signup.InitiationPath,
|
SignupInitiationPath = signup.InitiationPath,
|
||||||
Storage = returnValue.Item1.MaxStorageGb,
|
Storage = returnValue.Organization.MaxStorageGb,
|
||||||
});
|
});
|
||||||
|
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ValidatePlan(Plan plan, int additionalSeats, string productType)
|
private static void ValidatePlan(Plan plan, int additionalSeats)
|
||||||
{
|
{
|
||||||
if (plan is null)
|
if (plan is null)
|
||||||
{
|
{
|
||||||
throw new BadRequestException($"{productType} Plan was null.");
|
throw new BadRequestException("Password Manager Plan was null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plan.Disabled)
|
if (plan.Disabled)
|
||||||
{
|
{
|
||||||
throw new BadRequestException($"{productType} Plan not found.");
|
throw new BadRequestException("Password Manager Plan is disabled.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (additionalSeats < 0)
|
if (additionalSeats < 0)
|
||||||
{
|
{
|
||||||
throw new BadRequestException($"You can't subtract {productType} seats!");
|
throw new BadRequestException("You can't subtract Password Manager seats!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Private helper method to create a new organization.
|
/// Private helper method to create a new organization.
|
||||||
/// This is common code used by both the cloud and self-hosted methods.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task<(Organization organization, Collection defaultCollection)> SignUpAsync(Organization organization,
|
private async Task<ProviderClientOrganizationSignUpResponse> SignUpAsync(
|
||||||
string collectionName)
|
Organization organization, string collectionName)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -160,7 +166,7 @@ public class SignUpProviderClientOrganizationCommand : ISignUpProviderClientOrga
|
|||||||
await _collectionRepository.CreateAsync(defaultCollection, null, null);
|
await _collectionRepository.CreateAsync(defaultCollection, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (organization, defaultCollection);
|
return new ProviderClientOrganizationSignUpResponse(organization, defaultCollection);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@ -173,12 +179,4 @@ public class SignUpProviderClientOrganizationCommand : ISignUpProviderClientOrga
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<IEnumerable<string>> GetUserDeviceIdsAsync(Guid userId)
|
|
||||||
{
|
|
||||||
var devices = await _deviceRepository.GetManyByUserIdAsync(userId);
|
|
||||||
return devices
|
|
||||||
.Where(d => !string.IsNullOrWhiteSpace(d.PushToken))
|
|
||||||
.Select(d => d.Id.ToString());
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -19,10 +19,10 @@ using Bit.Test.Common.AutoFixture.Attributes;
|
|||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.Organizations;
|
namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.Organizations.OrganizationSignUp;
|
||||||
|
|
||||||
[SutProviderCustomize]
|
[SutProviderCustomize]
|
||||||
public class SignUpProviderClientOrganizationCommandTests
|
public class ProviderClientOrganizationSignUpCommandTests
|
||||||
{
|
{
|
||||||
[Theory]
|
[Theory]
|
||||||
[BitAutoData(PlanType.TeamsAnnually)]
|
[BitAutoData(PlanType.TeamsAnnually)]
|
||||||
@ -33,7 +33,7 @@ public class SignUpProviderClientOrganizationCommandTests
|
|||||||
PlanType planType,
|
PlanType planType,
|
||||||
OrganizationSignup signup,
|
OrganizationSignup signup,
|
||||||
string collectionName,
|
string collectionName,
|
||||||
SutProvider<SignUpProviderClientOrganizationCommand> sutProvider)
|
SutProvider<ProviderClientOrganizationSignUpCommand> sutProvider)
|
||||||
{
|
{
|
||||||
signup.Plan = planType;
|
signup.Plan = planType;
|
||||||
signup.AdditionalSeats = 15;
|
signup.AdditionalSeats = 15;
|
||||||
@ -46,9 +46,9 @@ public class SignUpProviderClientOrganizationCommandTests
|
|||||||
|
|
||||||
var result = await sutProvider.Sut.SignUpClientOrganizationAsync(signup);
|
var result = await sutProvider.Sut.SignUpClientOrganizationAsync(signup);
|
||||||
|
|
||||||
Assert.NotNull(result.organization);
|
Assert.NotNull(result.Organization);
|
||||||
Assert.NotNull(result.defaultCollection);
|
Assert.NotNull(result.DefaultCollection);
|
||||||
Assert.Equal(collectionName, result.defaultCollection.Name);
|
Assert.Equal(collectionName, result.DefaultCollection.Name);
|
||||||
|
|
||||||
await sutProvider.GetDependency<IOrganizationRepository>()
|
await sutProvider.GetDependency<IOrganizationRepository>()
|
||||||
.Received(1)
|
.Received(1)
|
||||||
@ -71,8 +71,8 @@ public class SignUpProviderClientOrganizationCommandTests
|
|||||||
referenceEvent.Type == ReferenceEventType.Signup &&
|
referenceEvent.Type == ReferenceEventType.Signup &&
|
||||||
referenceEvent.PlanName == plan.Name &&
|
referenceEvent.PlanName == plan.Name &&
|
||||||
referenceEvent.PlanType == plan.Type &&
|
referenceEvent.PlanType == plan.Type &&
|
||||||
referenceEvent.Seats == result.organization.Seats &&
|
referenceEvent.Seats == result.Organization.Seats &&
|
||||||
referenceEvent.Storage == result.organization.MaxStorageGb &&
|
referenceEvent.Storage == result.Organization.MaxStorageGb &&
|
||||||
referenceEvent.SignupInitiationPath == signup.InitiationPath
|
referenceEvent.SignupInitiationPath == signup.InitiationPath
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ public class SignUpProviderClientOrganizationCommandTests
|
|||||||
.CreateAsync(
|
.CreateAsync(
|
||||||
Arg.Is<Collection>(c =>
|
Arg.Is<Collection>(c =>
|
||||||
c.Name == collectionName &&
|
c.Name == collectionName &&
|
||||||
c.OrganizationId == result.organization.Id
|
c.OrganizationId == result.Organization.Id
|
||||||
),
|
),
|
||||||
Arg.Any<IEnumerable<CollectionAccessSelection>>(),
|
Arg.Any<IEnumerable<CollectionAccessSelection>>(),
|
||||||
Arg.Any<IEnumerable<CollectionAccessSelection>>()
|
Arg.Any<IEnumerable<CollectionAccessSelection>>()
|
||||||
@ -91,21 +91,21 @@ public class SignUpProviderClientOrganizationCommandTests
|
|||||||
.Received(1)
|
.Received(1)
|
||||||
.CreateAsync(
|
.CreateAsync(
|
||||||
Arg.Is<OrganizationApiKey>(k =>
|
Arg.Is<OrganizationApiKey>(k =>
|
||||||
k.OrganizationId == result.organization.Id &&
|
k.OrganizationId == result.Organization.Id &&
|
||||||
k.Type == OrganizationApiKeyType.Default
|
k.Type == OrganizationApiKeyType.Default
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
await sutProvider.GetDependency<IApplicationCacheService>()
|
await sutProvider.GetDependency<IApplicationCacheService>()
|
||||||
.Received(1)
|
.Received(1)
|
||||||
.UpsertOrganizationAbilityAsync(Arg.Is<Organization>(o => o.Id == result.organization.Id));
|
.UpsertOrganizationAbilityAsync(Arg.Is<Organization>(o => o.Id == result.Organization.Id));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[BitAutoData]
|
[BitAutoData]
|
||||||
public async Task SignupClientAsync_NullPlan_ThrowsBadRequestException(
|
public async Task SignupClientAsync_NullPlan_ThrowsBadRequestException(
|
||||||
OrganizationSignup signup,
|
OrganizationSignup signup,
|
||||||
SutProvider<SignUpProviderClientOrganizationCommand> sutProvider)
|
SutProvider<ProviderClientOrganizationSignUpCommand> sutProvider)
|
||||||
{
|
{
|
||||||
sutProvider.GetDependency<IPricingClient>()
|
sutProvider.GetDependency<IPricingClient>()
|
||||||
.GetPlanOrThrow(signup.Plan)
|
.GetPlanOrThrow(signup.Plan)
|
||||||
@ -121,7 +121,7 @@ public class SignUpProviderClientOrganizationCommandTests
|
|||||||
[BitAutoData]
|
[BitAutoData]
|
||||||
public async Task SignupClientAsync_NegativeAdditionalSeats_ThrowsBadRequestException(
|
public async Task SignupClientAsync_NegativeAdditionalSeats_ThrowsBadRequestException(
|
||||||
OrganizationSignup signup,
|
OrganizationSignup signup,
|
||||||
SutProvider<SignUpProviderClientOrganizationCommand> sutProvider)
|
SutProvider<ProviderClientOrganizationSignUpCommand> sutProvider)
|
||||||
{
|
{
|
||||||
signup.Plan = PlanType.TeamsMonthly;
|
signup.Plan = PlanType.TeamsMonthly;
|
||||||
signup.AdditionalSeats = -5;
|
signup.AdditionalSeats = -5;
|
||||||
@ -142,7 +142,7 @@ public class SignUpProviderClientOrganizationCommandTests
|
|||||||
public async Task SignupClientAsync_WhenExceptionIsThrown_CleanupIsPerformed(
|
public async Task SignupClientAsync_WhenExceptionIsThrown_CleanupIsPerformed(
|
||||||
PlanType planType,
|
PlanType planType,
|
||||||
OrganizationSignup signup,
|
OrganizationSignup signup,
|
||||||
SutProvider<SignUpProviderClientOrganizationCommand> sutProvider)
|
SutProvider<ProviderClientOrganizationSignUpCommand> sutProvider)
|
||||||
{
|
{
|
||||||
signup.Plan = planType;
|
signup.Plan = planType;
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user