1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-09 12:03:33 +00:00

[AC-1486] Feature: SM Billing Round 1 (#5747)

* [AC-1423] Update organization subscription cloud page (#5614)

* [AC-1423] Add ProgressModule to shared.module.ts

* [AC-1423] Update cloud subscription page styles

- Remove bootstrap styles
- Use CL components where applicable
- Use CL typography directives
- Update heading levels to prepare for new SM sections

* [AC-1423] Add usePasswordManager boolean to organization domain

* [AC-1423] Introduce BitwardenProductType enum

* [AC-1423] Update Organization subscription line items

- Add product type prefix
- Indent addon services like additional storage and service accounts
- Show line items for free plans

* [AC-1420] Add Secrets Manager subscribe component (#5617)

* [AC-1418] Add secrets manager manage subscription component (#5661)

* add additional properties (#5743)

* Allow autoscale limits to be removed, update naming (#5781)

* [AC-1488] Store Organization.SmServiceAccounts as total not additional (#5784)

* Allow autoscale limits to be removed, update naming

* Display additional service accounts only

* [AC-1531] Fix SM subscribe component not showing in free org billing tab (#5848)

---------

Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
Co-authored-by: cyprain-okeke <108260115+cyprain-okeke@users.noreply.github.com>
Co-authored-by: Rui Tome <rtome@bitwarden.com>
This commit is contained in:
Álison Fernandes
2023-07-25 00:07:21 +01:00
committed by GitHub
parent 1a6573ba96
commit 34533f62a9
39 changed files with 1146 additions and 271 deletions

View File

@@ -9,8 +9,11 @@ import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-conso
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { OrganizationApiKeyType } from "@bitwarden/common/admin-console/enums";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { PlanType } from "@bitwarden/common/billing/enums";
import { BitwardenProductType, PlanType } from "@bitwarden/common/billing/enums";
import { OrganizationSubscriptionResponse } from "@bitwarden/common/billing/models/response/organization-subscription.response";
import { BillingSubscriptionItemResponse } from "@bitwarden/common/billing/models/response/subscription.response";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
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";
@@ -19,6 +22,7 @@ import {
BillingSyncApiKeyComponent,
BillingSyncApiModalData,
} from "./billing-sync-api-key.component";
import { SecretsManagerSubscriptionOptions } from "./secrets-manager/sm-adjust-subscription.component";
@Component({
selector: "app-org-subscription-cloud",
@@ -26,6 +30,7 @@ import {
})
export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy {
sub: OrganizationSubscriptionResponse;
lineItems: BillingSubscriptionItemResponse[] = [];
organizationId: string;
userOrg: Organization;
showChangePlan = false;
@@ -33,6 +38,9 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
adjustStorageAdd = true;
showAdjustStorage = false;
hasBillingSyncToken: boolean;
showAdjustSecretsManager = false;
showSecretsManagerSubscribe = false;
firstLoaded = false;
loading: boolean;
@@ -48,7 +56,8 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
private organizationService: OrganizationService,
private organizationApiService: OrganizationApiServiceAbstraction,
private route: ActivatedRoute,
private dialogService: DialogServiceAbstraction
private dialogService: DialogServiceAbstraction,
private configService: ConfigServiceAbstraction
) {}
async ngOnInit() {
@@ -68,6 +77,17 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
.subscribe();
}
productName(product: BitwardenProductType) {
switch (product) {
case BitwardenProductType.PasswordManager:
return this.i18nService.t("passwordManager");
case BitwardenProductType.SecretsManager:
return this.i18nService.t("secretsManager");
default:
return this.i18nService.t("passwordManager");
}
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
@@ -81,6 +101,7 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
this.userOrg = this.organizationService.get(this.organizationId);
if (this.userOrg.canViewSubscription) {
this.sub = await this.organizationApiService.getSubscription(this.organizationId);
this.lineItems = this.sub?.subscription?.items?.sort(sortSubscriptionItems) ?? [];
}
const apiKeyResponse = await this.organizationApiService.getApiKeyInformation(
@@ -90,7 +111,28 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
(i) => i.keyType === OrganizationApiKeyType.BillingSync
);
this.showSecretsManagerSubscribe =
this.userOrg.canEditSubscription &&
!this.userOrg.useSecretsManager &&
!this.subscription?.cancelled &&
!this.subscriptionMarkedForCancel;
this.showAdjustSecretsManager =
this.userOrg.canEditSubscription &&
this.userOrg.useSecretsManager &&
this.subscription != null &&
this.sub.secretsManagerPlan?.hasAdditionalSeatsOption &&
!this.subscription.cancelled &&
!this.subscriptionMarkedForCancel;
this.loading = false;
// Remove the remaining lines when the sm-ga-billing flag is deleted
const smBillingEnabled = await this.configService.getFeatureFlagBool(
FeatureFlag.SecretsManagerBilling
);
this.showSecretsManagerSubscribe = this.showSecretsManagerSubscribe && smBillingEnabled;
this.showAdjustSecretsManager = this.showAdjustSecretsManager && smBillingEnabled;
}
get subscription() {
@@ -138,6 +180,20 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
return this.sub.seats;
}
get smOptions(): SecretsManagerSubscriptionOptions {
return {
seatCount: this.sub.smSeats,
maxAutoscaleSeats: this.sub.maxAutoscaleSmSeats,
seatPrice: this.sub.secretsManagerPlan.seatPrice,
maxAutoscaleServiceAccounts: this.sub.maxAutoscaleSmServiceAccounts,
additionalServiceAccounts:
this.sub.smServiceAccounts - this.sub.secretsManagerPlan.baseServiceAccount,
interval: this.sub.secretsManagerPlan.isAnnual ? "year" : "month",
additionalServiceAccountPrice: this.sub.secretsManagerPlan.additionalPricePerServiceAccount,
baseServiceAccountCount: this.sub.secretsManagerPlan.baseServiceAccount,
};
}
get maxAutoscaleSeats() {
return this.sub.maxAutoscaleSeats;
}
@@ -332,3 +388,23 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
return this.subscription == null && this.sub.planType === PlanType.Free && !this.showChangePlan;
}
}
/**
* Helper to sort subscription items by product type and then by addon status
*/
function sortSubscriptionItems(
a: BillingSubscriptionItemResponse,
b: BillingSubscriptionItemResponse
) {
if (a.bitwardenProduct == b.bitwardenProduct) {
if (a.addonSubscriptionItem == b.addonSubscriptionItem) {
return 0;
}
// sort addon items to the bottom
if (a.addonSubscriptionItem) {
return 1;
}
return -1;
}
return a.bitwardenProduct - b.bitwardenProduct;
}