1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-02 16:42:50 -05:00

[PM-8445] Update trial initiation UI (#4712)

* Add the feature flag

Signed-off-by: Cy Okeke <cokeke@bitwarden.com>

* Initial comment

Signed-off-by: Cy Okeke <cokeke@bitwarden.com>

* changes to subscribe with payment method

Signed-off-by: Cy Okeke <cokeke@bitwarden.com>

* Add new objects

* Implementation for subscription without payment method

Signed-off-by: Cy Okeke <cokeke@bitwarden.com>

* Remove unused codes and classes

Signed-off-by: Cy Okeke <cokeke@bitwarden.com>

* Rename the flag properly

Signed-off-by: Cy Okeke <cokeke@bitwarden.com>

* remove implementation that is no longer needed

Signed-off-by: Cy Okeke <cokeke@bitwarden.com>

* revert the changes on some code removal

Signed-off-by: Cy Okeke <cokeke@bitwarden.com>

* Resolve the pr comment

Signed-off-by: Cy Okeke <cokeke@bitwarden.com>

* format the data annotations line breaks

Signed-off-by: Cy Okeke <cokeke@bitwarden.com>

---------

Signed-off-by: Cy Okeke <cokeke@bitwarden.com>
This commit is contained in:
cyprain-okeke
2024-09-27 19:39:44 +01:00
committed by GitHub
parent 8c8956da37
commit c66879eb89
7 changed files with 245 additions and 4 deletions

View File

@ -171,6 +171,21 @@ public class OrganizationsController : Controller
return new OrganizationResponseModel(result.Item1);
}
[HttpPost("create-without-payment")]
[SelfHosted(NotSelfHostedOnly = true)]
public async Task<OrganizationResponseModel> CreateWithoutPaymentAsync([FromBody] OrganizationNoPaymentCreateRequest model)
{
var user = await _userService.GetUserByPrincipalAsync(User);
if (user == null)
{
throw new UnauthorizedAccessException();
}
var organizationSignup = model.ToOrganizationSignup(user);
var result = await _organizationService.SignUpAsync(organizationSignup);
return new OrganizationResponseModel(result.Item1);
}
[HttpPut("{id}")]
[HttpPost("{id}")]
public async Task<OrganizationResponseModel> Put(string id, [FromBody] OrganizationUpdateRequestModel model)

View File

@ -14,42 +14,63 @@ public class OrganizationCreateRequestModel : IValidatableObject
[StringLength(50, ErrorMessage = "The field Name exceeds the maximum length.")]
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string Name { get; set; }
[StringLength(50, ErrorMessage = "The field Business Name exceeds the maximum length.")]
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string BusinessName { get; set; }
[Required]
[StringLength(256)]
[EmailAddress]
public string BillingEmail { get; set; }
public PlanType PlanType { get; set; }
[Required]
public string Key { get; set; }
public OrganizationKeysRequestModel Keys { get; set; }
public PaymentMethodType? PaymentMethodType { get; set; }
public string PaymentToken { get; set; }
[Range(0, int.MaxValue)]
public int AdditionalSeats { get; set; }
[Range(0, 99)]
public short? AdditionalStorageGb { get; set; }
public bool PremiumAccessAddon { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string CollectionName { get; set; }
public string TaxIdNumber { get; set; }
public string BillingAddressLine1 { get; set; }
public string BillingAddressLine2 { get; set; }
public string BillingAddressCity { get; set; }
public string BillingAddressState { get; set; }
public string BillingAddressPostalCode { get; set; }
[StringLength(2)]
public string BillingAddressCountry { get; set; }
public int? MaxAutoscaleSeats { get; set; }
[Range(0, int.MaxValue)]
public int? AdditionalSmSeats { get; set; }
[Range(0, int.MaxValue)]
public int? AdditionalServiceAccounts { get; set; }
[Required]
public bool UseSecretsManager { get; set; }
public bool IsFromSecretsManagerTrial { get; set; }
public string InitiationPath { get; set; }
@ -99,16 +120,19 @@ public class OrganizationCreateRequestModel : IValidatableObject
{
yield return new ValidationResult("Payment required.", new string[] { nameof(PaymentToken) });
}
if (PlanType != PlanType.Free && !PaymentMethodType.HasValue)
{
yield return new ValidationResult("Payment method type required.",
new string[] { nameof(PaymentMethodType) });
}
if (PlanType != PlanType.Free && string.IsNullOrWhiteSpace(BillingAddressCountry))
{
yield return new ValidationResult("Country required.",
new string[] { nameof(BillingAddressCountry) });
}
if (PlanType != PlanType.Free && BillingAddressCountry == "US" &&
string.IsNullOrWhiteSpace(BillingAddressPostalCode))
{
@ -117,3 +141,4 @@ public class OrganizationCreateRequestModel : IValidatableObject
}
}
}

View File

@ -0,0 +1,116 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using Bit.Core.Billing.Enums;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Models.Business;
using Bit.Core.Utilities;
namespace Bit.Api.AdminConsole.Models.Request.Organizations;
public class OrganizationNoPaymentCreateRequest
{
[Required]
[StringLength(50, ErrorMessage = "The field Name exceeds the maximum length.")]
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string Name { get; set; }
[StringLength(50, ErrorMessage = "The field Business Name exceeds the maximum length.")]
[JsonConverter(typeof(HtmlEncodingStringConverter))]
public string BusinessName { get; set; }
[Required]
[StringLength(256)]
[EmailAddress]
public string BillingEmail { get; set; }
public PlanType PlanType { get; set; }
[Required]
public string Key { get; set; }
public OrganizationKeysRequestModel Keys { get; set; }
public PaymentMethodType? PaymentMethodType { get; set; }
public string PaymentToken { get; set; }
[Range(0, int.MaxValue)]
public int AdditionalSeats { get; set; }
[Range(0, 99)]
public short? AdditionalStorageGb { get; set; }
public bool PremiumAccessAddon { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string CollectionName { get; set; }
public string TaxIdNumber { get; set; }
public string BillingAddressLine1 { get; set; }
public string BillingAddressLine2 { get; set; }
public string BillingAddressCity { get; set; }
public string BillingAddressState { get; set; }
public string BillingAddressPostalCode { get; set; }
[StringLength(2)]
public string BillingAddressCountry { get; set; }
public int? MaxAutoscaleSeats { get; set; }
[Range(0, int.MaxValue)]
public int? AdditionalSmSeats { get; set; }
[Range(0, int.MaxValue)]
public int? AdditionalServiceAccounts { get; set; }
[Required]
public bool UseSecretsManager { get; set; }
public bool IsFromSecretsManagerTrial { get; set; }
public string InitiationPath { get; set; }
public virtual OrganizationSignup ToOrganizationSignup(User user)
{
var orgSignup = new OrganizationSignup
{
Owner = user,
OwnerKey = Key,
Name = Name,
Plan = PlanType,
PaymentMethodType = PaymentMethodType,
PaymentToken = PaymentToken,
AdditionalSeats = AdditionalSeats,
MaxAutoscaleSeats = MaxAutoscaleSeats,
AdditionalStorageGb = AdditionalStorageGb.GetValueOrDefault(0),
PremiumAccessAddon = PremiumAccessAddon,
BillingEmail = BillingEmail,
BusinessName = BusinessName,
CollectionName = CollectionName,
AdditionalSmSeats = AdditionalSmSeats.GetValueOrDefault(),
AdditionalServiceAccounts = AdditionalServiceAccounts.GetValueOrDefault(),
UseSecretsManager = UseSecretsManager,
IsFromSecretsManagerTrial = IsFromSecretsManagerTrial,
TaxInfo = new TaxInfo
{
TaxIdNumber = TaxIdNumber,
BillingAddressLine1 = BillingAddressLine1,
BillingAddressLine2 = BillingAddressLine2,
BillingAddressCity = BillingAddressCity,
BillingAddressState = BillingAddressState,
BillingAddressPostalCode = BillingAddressPostalCode,
BillingAddressCountry = BillingAddressCountry,
},
InitiationPath = InitiationPath,
};
Keys?.ToOrganizationSignup(orgSignup);
return orgSignup;
}
}