diff --git a/apps/web/src/app/vault/individual-vault/vault.component.ts b/apps/web/src/app/vault/individual-vault/vault.component.ts index ce61cd51fc..9d235784d0 100644 --- a/apps/web/src/app/vault/individual-vault/vault.component.ts +++ b/apps/web/src/app/vault/individual-vault/vault.component.ts @@ -32,11 +32,11 @@ import { } from "rxjs/operators"; import { - Unassigned, - CollectionService, CollectionData, CollectionDetailsResponse, + CollectionService, CollectionView, + Unassigned, } from "@bitwarden/admin-console/common"; import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe"; import { ModalService } from "@bitwarden/angular/services/modal.service"; @@ -47,6 +47,7 @@ import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-conso import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; +import { OrganizationBillingServiceAbstraction } from "@bitwarden/common/billing/abstractions"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction"; import { EventType } from "@bitwarden/common/enums"; @@ -241,6 +242,7 @@ export class VaultComponent implements OnInit, OnDestroy { private organizationApiService: OrganizationApiServiceAbstraction, protected billingApiService: BillingApiServiceAbstraction, private trialFlowService: TrialFlowService, + private organizationBillingService: OrganizationBillingServiceAbstraction, ) {} async ngOnInit() { @@ -437,13 +439,13 @@ export class VaultComponent implements OnInit, OnDestroy { .map((org) => combineLatest([ this.organizationApiService.getSubscription(org.id), - this.organizationApiService.getBilling(org.id), + this.organizationBillingService.getPaymentSource(org.id), ]).pipe( - map(([subscription, billing]) => { + map(([subscription, paymentSource]) => { return this.trialFlowService.checkForOrgsWithUpcomingPaymentIssues( org, subscription, - billing?.paymentSource, + paymentSource, ); }), ), diff --git a/apps/web/src/app/vault/org-vault/vault.component.ts b/apps/web/src/app/vault/org-vault/vault.component.ts index 64318047b9..18cc6e49ab 100644 --- a/apps/web/src/app/vault/org-vault/vault.component.ts +++ b/apps/web/src/app/vault/org-vault/vault.component.ts @@ -48,6 +48,7 @@ import { SearchService } from "@bitwarden/common/abstractions/search.service"; import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; +import { OrganizationBillingServiceAbstraction } from "@bitwarden/common/billing/abstractions"; import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction"; import { EventType } from "@bitwarden/common/enums"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; @@ -252,6 +253,7 @@ export class VaultComponent implements OnInit, OnDestroy { private organizationApiService: OrganizationApiServiceAbstraction, private trialFlowService: TrialFlowService, protected billingApiService: BillingApiServiceAbstraction, + private organizationBillingService: OrganizationBillingServiceAbstraction, ) {} async ngOnInit() { @@ -595,15 +597,11 @@ export class VaultComponent implements OnInit, OnDestroy { combineLatest([ of(org), this.organizationApiService.getSubscription(org.id), - this.organizationApiService.getBilling(org.id), + this.organizationBillingService.getPaymentSource(org.id), ]), ), - map(([org, sub, billing]) => { - return this.trialFlowService.checkForOrgsWithUpcomingPaymentIssues( - org, - sub, - billing?.paymentSource, - ); + map(([org, sub, paymentSource]) => { + return this.trialFlowService.checkForOrgsWithUpcomingPaymentIssues(org, sub, paymentSource); }), ); diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts index bf2dbb76ad..3585f09faf 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts @@ -20,6 +20,7 @@ import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe"; import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; +import { OrganizationBillingServiceAbstraction } from "@bitwarden/common/billing/abstractions"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; @@ -114,9 +115,9 @@ export class OverviewComponent implements OnInit, OnDestroy { private smOnboardingTasksService: SMOnboardingTasksService, private logService: LogService, private router: Router, - private organizationApiService: OrganizationApiServiceAbstraction, private trialFlowService: TrialFlowService, + private organizationBillingService: OrganizationBillingServiceAbstraction, ) {} ngOnInit() { @@ -144,15 +145,11 @@ export class OverviewComponent implements OnInit, OnDestroy { combineLatest([ of(org), this.organizationApiService.getSubscription(org.id), - this.organizationApiService.getBilling(org.id), + this.organizationBillingService.getPaymentSource(org.id), ]), ), - map(([org, sub, billing]) => { - return this.trialFlowService.checkForOrgsWithUpcomingPaymentIssues( - org, - sub, - billing?.paymentSource, - ); + map(([org, sub, paymentSource]) => { + return this.trialFlowService.checkForOrgsWithUpcomingPaymentIssues(org, sub, paymentSource); }), takeUntil(this.destroy$), ); diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index 0208a3cdc7..a43f1fa07a 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -1213,6 +1213,8 @@ const safeProviders: SafeProvider[] = [ useClass: OrganizationBillingService, deps: [ ApiServiceAbstraction, + BillingApiServiceAbstraction, + ConfigService, KeyServiceAbstraction, EncryptService, I18nServiceAbstraction, diff --git a/libs/common/src/billing/abstractions/organization-billing.service.ts b/libs/common/src/billing/abstractions/organization-billing.service.ts index 72902baa30..0bc1f3bc55 100644 --- a/libs/common/src/billing/abstractions/organization-billing.service.ts +++ b/libs/common/src/billing/abstractions/organization-billing.service.ts @@ -1,3 +1,6 @@ +import { BillingSourceResponse } from "@bitwarden/common/billing/models/response/billing.response"; +import { PaymentSourceResponse } from "@bitwarden/common/billing/models/response/payment-source.response"; + import { OrganizationResponse } from "../../admin-console/models/response/organization.response"; import { InitiationPath } from "../../models/request/reference-event.request"; import { PaymentMethodType, PlanType } from "../enums"; @@ -41,11 +44,15 @@ export type SubscriptionInformation = { }; export abstract class OrganizationBillingServiceAbstraction { - purchaseSubscription: (subscription: SubscriptionInformation) => Promise; + getPaymentSource: ( + organizationId: string, + ) => Promise; - startFree: (subscription: SubscriptionInformation) => Promise; + purchaseSubscription: (subscription: SubscriptionInformation) => Promise; purchaseSubscriptionNoPaymentMethod: ( subscription: SubscriptionInformation, ) => Promise; + + startFree: (subscription: SubscriptionInformation) => Promise; } diff --git a/libs/common/src/billing/services/organization-billing.service.ts b/libs/common/src/billing/services/organization-billing.service.ts index efc3627853..487098620b 100644 --- a/libs/common/src/billing/services/organization-billing.service.ts +++ b/libs/common/src/billing/services/organization-billing.service.ts @@ -1,4 +1,18 @@ -import { KeyService } from "../../../../key-management/src/abstractions/key.service"; +import { + BillingApiServiceAbstraction, + OrganizationBillingServiceAbstraction, + OrganizationInformation, + PaymentInformation, + PlanInformation, + SubscriptionInformation, +} from "@bitwarden/common/billing/abstractions"; +import { BillingSourceResponse } from "@bitwarden/common/billing/models/response/billing.response"; +import { PaymentSourceResponse } from "@bitwarden/common/billing/models/response/payment-source.response"; +import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; +import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; +import { SyncService } from "@bitwarden/common/platform/sync"; +import { KeyService } from "@bitwarden/key-management"; + import { ApiService } from "../../abstractions/api.service"; import { OrganizationApiServiceAbstraction as OrganizationApiService } from "../../admin-console/abstractions/organization/organization-api.service.abstraction"; import { OrganizationCreateRequest } from "../../admin-console/models/request/organization-create.request"; @@ -8,14 +22,6 @@ import { EncryptService } from "../../platform/abstractions/encrypt.service"; import { I18nService } from "../../platform/abstractions/i18n.service"; import { EncString } from "../../platform/models/domain/enc-string"; import { OrgKey } from "../../types/key"; -import { SyncService } from "../../vault/abstractions/sync/sync.service.abstraction"; -import { - OrganizationBillingServiceAbstraction, - OrganizationInformation, - PaymentInformation, - PlanInformation, - SubscriptionInformation, -} from "../abstractions/organization-billing.service"; import { PlanType } from "../enums"; import { OrganizationNoPaymentMethodCreateRequest } from "../models/request/organization-no-payment-method-create-request"; @@ -29,6 +35,8 @@ interface OrganizationKeys { export class OrganizationBillingService implements OrganizationBillingServiceAbstraction { constructor( private apiService: ApiService, + private billingApiService: BillingApiServiceAbstraction, + private configService: ConfigService, private keyService: KeyService, private encryptService: EncryptService, private i18nService: I18nService, @@ -36,6 +44,23 @@ export class OrganizationBillingService implements OrganizationBillingServiceAbs private syncService: SyncService, ) {} + async getPaymentSource( + organizationId: string, + ): Promise { + const deprecateStripeSourcesAPI = await this.configService.getFeatureFlag( + FeatureFlag.AC2476_DeprecateStripeSourcesAPI, + ); + + if (deprecateStripeSourcesAPI) { + const paymentMethod = + await this.billingApiService.getOrganizationPaymentMethod(organizationId); + return paymentMethod.paymentSource; + } else { + const billing = await this.organizationApiService.getBilling(organizationId); + return billing.paymentSource; + } + } + async purchaseSubscription(subscription: SubscriptionInformation): Promise { const request = new OrganizationCreateRequest(); @@ -58,26 +83,6 @@ export class OrganizationBillingService implements OrganizationBillingServiceAbs return response; } - async startFree(subscription: SubscriptionInformation): Promise { - const request = new OrganizationCreateRequest(); - - const organizationKeys = await this.makeOrganizationKeys(); - - this.setOrganizationKeys(request, organizationKeys); - - this.setOrganizationInformation(request, subscription.organization); - - this.setPlanInformation(request, subscription.plan); - - const response = await this.organizationApiService.create(request); - - await this.apiService.refreshIdentityToken(); - - await this.syncService.fullSync(true); - - return response; - } - async purchaseSubscriptionNoPaymentMethod( subscription: SubscriptionInformation, ): Promise { @@ -100,6 +105,26 @@ export class OrganizationBillingService implements OrganizationBillingServiceAbs return response; } + async startFree(subscription: SubscriptionInformation): Promise { + const request = new OrganizationCreateRequest(); + + const organizationKeys = await this.makeOrganizationKeys(); + + this.setOrganizationKeys(request, organizationKeys); + + this.setOrganizationInformation(request, subscription.organization); + + this.setPlanInformation(request, subscription.plan); + + const response = await this.organizationApiService.create(request); + + await this.apiService.refreshIdentityToken(); + + await this.syncService.fullSync(true); + + return response; + } + private async makeOrganizationKeys(): Promise { const [encryptedKey, key] = await this.keyService.makeOrgKey(); const [publicKey, encryptedPrivateKey] = await this.keyService.makeKeyPair(key);