mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 13:23:34 +00:00
[PM-8161] Payment optional trial MVP (#10872)
* Initial comment * Add changes for the create org with payment method * Add the secrets manager trail flow * Add the banners * Add changes for the Disabled Org * Add banner to payment method page * Refactoring changes * Resolve the bug on tha payment method * Resolve lint error * Resolve Pr comments * resolve the lint issue * Resolve the lint wrong file issue * Rename object properly * Resolve pr comments from sm team * Resolve the pr comments from sm team * Fix the failing test * Resolve some issue with vault * Resolve the comments from sm team * Resolve some pr comments from vault team * Resolve pr comments from auth team * Exported ValidOrgParams enum * Removed unnecessary interpolation * Corrected bit-banner id for trial * Resolve pr comments from auth team * Resolve pr comments from auth team * Removed unnecessary method * Made OrganizationCreateRequest a subtype of OrganizationNoPaymentMethodCreateRequest * Resolve review changes from sm * Resolve review changes from dm * Resolve the pr comments from billing * move the free-trial to core * Move free-trial change to right file * Revert changes on the free trial page * Resolve the comment on protected trial page * Resolve the comment on protected trial page * Revert the next async change * resolve pr comment fro vault team * resolve the default message comments * remove unused method * resolve email sending issue * Fix the pop issue on payment method * Fix some console errors * Fix the pop refresh page * move the trial services to billing folder * resolve pr comments * Resolve the import issues * Move the observable up * Resolve blank payment method for trialing org * Changes to disable icon is removed onsubmit * Remove unused references * add a missing a period at the end of it * resolve the reload issue * Resolve the disable icon issue * Fix the admin access bug * Resolve the lint issue * Fix the message incorrect format * Formatting fixed * Resolve the access issue of other users role
This commit is contained in:
@@ -6,6 +6,7 @@ import { SecretVerificationRequest } from "../../../auth/models/request/secret-v
|
||||
import { ApiKeyResponse } from "../../../auth/models/response/api-key.response";
|
||||
import { OrganizationSsoResponse } from "../../../auth/models/response/organization-sso.response";
|
||||
import { ExpandedTaxInfoUpdateRequest } from "../../../billing/models/request/expanded-tax-info-update.request";
|
||||
import { OrganizationNoPaymentMethodCreateRequest } from "../../../billing/models/request/organization-no-payment-method-create-request";
|
||||
import { OrganizationSmSubscriptionUpdateRequest } from "../../../billing/models/request/organization-sm-subscription-update.request";
|
||||
import { OrganizationSubscriptionUpdateRequest } from "../../../billing/models/request/organization-subscription-update.request";
|
||||
import { PaymentRequest } from "../../../billing/models/request/payment.request";
|
||||
@@ -40,6 +41,9 @@ export class OrganizationApiServiceAbstraction {
|
||||
getLicense: (id: string, installationId: string) => Promise<unknown>;
|
||||
getAutoEnrollStatus: (identifier: string) => Promise<OrganizationAutoEnrollStatusResponse>;
|
||||
create: (request: OrganizationCreateRequest) => Promise<OrganizationResponse>;
|
||||
createWithoutPayment: (
|
||||
request: OrganizationNoPaymentMethodCreateRequest,
|
||||
) => Promise<OrganizationResponse>;
|
||||
createLicense: (data: FormData) => Promise<OrganizationResponse>;
|
||||
save: (id: string, request: OrganizationUpdateRequest) => Promise<OrganizationResponse>;
|
||||
updatePayment: (id: string, request: PaymentRequest) => Promise<void>;
|
||||
|
||||
@@ -1,32 +1,7 @@
|
||||
import { PaymentMethodType, PlanType } from "../../../billing/enums";
|
||||
import { InitiationPath } from "../../../models/request/reference-event.request";
|
||||
import { PaymentMethodType } from "../../../billing/enums";
|
||||
import { OrganizationNoPaymentMethodCreateRequest } from "../../../billing/models/request/organization-no-payment-method-create-request";
|
||||
|
||||
import { OrganizationKeysRequest } from "./organization-keys.request";
|
||||
|
||||
export class OrganizationCreateRequest {
|
||||
name: string;
|
||||
businessName: string;
|
||||
billingEmail: string;
|
||||
planType: PlanType;
|
||||
key: string;
|
||||
keys: OrganizationKeysRequest;
|
||||
export class OrganizationCreateRequest extends OrganizationNoPaymentMethodCreateRequest {
|
||||
paymentMethodType: PaymentMethodType;
|
||||
paymentToken: string;
|
||||
additionalSeats: number;
|
||||
maxAutoscaleSeats: number;
|
||||
additionalStorageGb: number;
|
||||
premiumAccessAddon: boolean;
|
||||
collectionName: string;
|
||||
taxIdNumber: string;
|
||||
billingAddressLine1: string;
|
||||
billingAddressLine2: string;
|
||||
billingAddressCity: string;
|
||||
billingAddressState: string;
|
||||
billingAddressPostalCode: string;
|
||||
billingAddressCountry: string;
|
||||
useSecretsManager: boolean;
|
||||
additionalSmSeats: number;
|
||||
additionalServiceAccounts: number;
|
||||
isFromSecretsManagerTrial: boolean;
|
||||
initiationPath: InitiationPath;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { SecretVerificationRequest } from "../../../auth/models/request/secret-v
|
||||
import { ApiKeyResponse } from "../../../auth/models/response/api-key.response";
|
||||
import { OrganizationSsoResponse } from "../../../auth/models/response/organization-sso.response";
|
||||
import { ExpandedTaxInfoUpdateRequest } from "../../../billing/models/request/expanded-tax-info-update.request";
|
||||
import { OrganizationNoPaymentMethodCreateRequest } from "../../../billing/models/request/organization-no-payment-method-create-request";
|
||||
import { OrganizationSmSubscriptionUpdateRequest } from "../../../billing/models/request/organization-sm-subscription-update.request";
|
||||
import { OrganizationSubscriptionUpdateRequest } from "../../../billing/models/request/organization-subscription-update.request";
|
||||
import { PaymentRequest } from "../../../billing/models/request/payment.request";
|
||||
@@ -107,6 +108,21 @@ export class OrganizationApiService implements OrganizationApiServiceAbstraction
|
||||
return new OrganizationResponse(r);
|
||||
}
|
||||
|
||||
async createWithoutPayment(
|
||||
request: OrganizationNoPaymentMethodCreateRequest,
|
||||
): Promise<OrganizationResponse> {
|
||||
const r = await this.apiService.send(
|
||||
"POST",
|
||||
"/organizations/create-without-payment",
|
||||
request,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
// Forcing a sync will notify organization service that they need to repull
|
||||
await this.syncService.fullSync(true);
|
||||
return new OrganizationResponse(r);
|
||||
}
|
||||
|
||||
async createLicense(data: FormData): Promise<OrganizationResponse> {
|
||||
const r = await this.apiService.send(
|
||||
"POST",
|
||||
|
||||
@@ -44,4 +44,8 @@ export abstract class OrganizationBillingServiceAbstraction {
|
||||
purchaseSubscription: (subscription: SubscriptionInformation) => Promise<OrganizationResponse>;
|
||||
|
||||
startFree: (subscription: SubscriptionInformation) => Promise<OrganizationResponse>;
|
||||
|
||||
purchaseSubscriptionNoPaymentMethod: (
|
||||
subscription: SubscriptionInformation,
|
||||
) => Promise<OrganizationResponse>;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { OrganizationKeysRequest } from "../../../admin-console/models/request/organization-keys.request";
|
||||
import { InitiationPath } from "../../../models/request/reference-event.request";
|
||||
import { PlanType } from "../../enums";
|
||||
|
||||
export class OrganizationNoPaymentMethodCreateRequest {
|
||||
name: string;
|
||||
businessName: string;
|
||||
billingEmail: string;
|
||||
planType: PlanType;
|
||||
key: string;
|
||||
keys: OrganizationKeysRequest;
|
||||
additionalSeats: number;
|
||||
maxAutoscaleSeats: number;
|
||||
additionalStorageGb: number;
|
||||
premiumAccessAddon: boolean;
|
||||
collectionName: string;
|
||||
taxIdNumber: string;
|
||||
billingAddressLine1: string;
|
||||
billingAddressLine2: string;
|
||||
billingAddressCity: string;
|
||||
billingAddressState: string;
|
||||
billingAddressPostalCode: string;
|
||||
billingAddressCountry: string;
|
||||
useSecretsManager: boolean;
|
||||
additionalSmSeats: number;
|
||||
additionalServiceAccounts: number;
|
||||
isFromSecretsManagerTrial: boolean;
|
||||
initiationPath: InitiationPath;
|
||||
}
|
||||
@@ -4,11 +4,13 @@ export class OrganizationBillingMetadataResponse extends BaseResponse {
|
||||
isEligibleForSelfHost: boolean;
|
||||
isManaged: boolean;
|
||||
isOnSecretsManagerStandalone: boolean;
|
||||
isSubscriptionUnpaid: boolean;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
this.isEligibleForSelfHost = this.getResponseProperty("IsEligibleForSelfHost");
|
||||
this.isManaged = this.getResponseProperty("IsManaged");
|
||||
this.isOnSecretsManagerStandalone = this.getResponseProperty("IsOnSecretsManagerStandalone");
|
||||
this.isSubscriptionUnpaid = this.getResponseProperty("IsSubscriptionUnpaid");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
SubscriptionInformation,
|
||||
} from "../abstractions/organization-billing.service";
|
||||
import { PlanType } from "../enums";
|
||||
import { OrganizationNoPaymentMethodCreateRequest } from "../models/request/organization-no-payment-method-create-request";
|
||||
|
||||
interface OrganizationKeys {
|
||||
encryptedKey: EncString;
|
||||
@@ -77,6 +78,28 @@ export class OrganizationBillingService implements OrganizationBillingServiceAbs
|
||||
return response;
|
||||
}
|
||||
|
||||
async purchaseSubscriptionNoPaymentMethod(
|
||||
subscription: SubscriptionInformation,
|
||||
): Promise<OrganizationResponse> {
|
||||
const request = new OrganizationNoPaymentMethodCreateRequest();
|
||||
|
||||
const organizationKeys = await this.makeOrganizationKeys();
|
||||
|
||||
this.setOrganizationKeys(request, organizationKeys);
|
||||
|
||||
this.setOrganizationInformation(request, subscription.organization);
|
||||
|
||||
this.setPlanInformation(request, subscription.plan);
|
||||
|
||||
const response = await this.organizationApiService.createWithoutPayment(request);
|
||||
|
||||
await this.apiService.refreshIdentityToken();
|
||||
|
||||
await this.syncService.fullSync(true);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private async makeOrganizationKeys(): Promise<OrganizationKeys> {
|
||||
const [encryptedKey, key] = await this.keyService.makeOrgKey<OrgKey>();
|
||||
const [publicKey, encryptedPrivateKey] = await this.keyService.makeKeyPair(key);
|
||||
@@ -106,7 +129,7 @@ export class OrganizationBillingService implements OrganizationBillingServiceAbs
|
||||
}
|
||||
|
||||
private setOrganizationInformation(
|
||||
request: OrganizationCreateRequest,
|
||||
request: OrganizationCreateRequest | OrganizationNoPaymentMethodCreateRequest,
|
||||
information: OrganizationInformation,
|
||||
): void {
|
||||
request.name = information.name;
|
||||
@@ -115,7 +138,10 @@ export class OrganizationBillingService implements OrganizationBillingServiceAbs
|
||||
request.initiationPath = information.initiationPath;
|
||||
}
|
||||
|
||||
private setOrganizationKeys(request: OrganizationCreateRequest, keys: OrganizationKeys): void {
|
||||
private setOrganizationKeys(
|
||||
request: OrganizationCreateRequest | OrganizationNoPaymentMethodCreateRequest,
|
||||
keys: OrganizationKeys,
|
||||
): void {
|
||||
request.key = keys.encryptedKey.encryptedString;
|
||||
request.keys = new OrganizationKeysRequest(
|
||||
keys.publicKey,
|
||||
@@ -146,7 +172,7 @@ export class OrganizationBillingService implements OrganizationBillingServiceAbs
|
||||
}
|
||||
|
||||
private setPlanInformation(
|
||||
request: OrganizationCreateRequest,
|
||||
request: OrganizationCreateRequest | OrganizationNoPaymentMethodCreateRequest,
|
||||
information: PlanInformation,
|
||||
): void {
|
||||
request.planType = information.type;
|
||||
|
||||
@@ -38,6 +38,7 @@ export enum FeatureFlag {
|
||||
Pm13322AddPolicyDefinitions = "pm-13322-add-policy-definitions",
|
||||
LimitCollectionCreationDeletionSplit = "pm-10863-limit-collection-creation-deletion-split",
|
||||
CriticalApps = "pm-14466-risk-insights-critical-application",
|
||||
TrialPaymentOptional = "PM-8163-trial-payment",
|
||||
}
|
||||
|
||||
export type AllowedFeatureFlagTypes = boolean | number | string;
|
||||
@@ -86,6 +87,7 @@ export const DefaultFeatureFlagValue = {
|
||||
[FeatureFlag.Pm13322AddPolicyDefinitions]: FALSE,
|
||||
[FeatureFlag.LimitCollectionCreationDeletionSplit]: FALSE,
|
||||
[FeatureFlag.CriticalApps]: FALSE,
|
||||
[FeatureFlag.TrialPaymentOptional]: FALSE,
|
||||
} satisfies Record<FeatureFlag, AllowedFeatureFlagTypes>;
|
||||
|
||||
export type DefaultFeatureFlagValueType = typeof DefaultFeatureFlagValue;
|
||||
|
||||
Reference in New Issue
Block a user