From b89f31101ff2c6b5a66a92f48e0edb62a06839fb Mon Sep 17 00:00:00 2001 From: Thomas Rittson <31796059+eliykat@users.noreply.github.com> Date: Sat, 5 Aug 2023 07:52:55 +1000 Subject: [PATCH] [AC-1512] Feature: Secrets Manager billing - round 2 (#5854) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [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-1423] Simply sort function * [AC-1423] Remove header border * [AC-1423] Make "Password Manager" the default fallback for product name * [AC-1420] Add Secrets Manager subscribe component (#5617) * [AC-1418] Add secrets manager manage subscription component (#5661) * [AC-1423] Add minWidth input to bit-progress component * [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-1423] Simply sort function * [AC-1423] Remove header border * [AC-1423] Remove redundant condition * [AC-1423] Remove ineffective div * [AC-1423] Make "Password Manager" the default fallback for product name * Revert "[AC-1423] Add minWidth input to bit-progress component" This reverts commit 95b2223a30e45966988bfed2e08a9631fa8980b9. * [AC-1423] Remove minWidth attribute * [AC-1423] Switch to AddonProductType enum instead of boolean * Revert "[AC-1423] Switch to AddonProductType enum instead of boolean" This reverts commit 204f64b4e7f76cf43a7dbc6161332553047592df. * [AC-1423] Tweak sorting comment * [AC-1418] Add initial SecretsManagerAdjustSubscription component * [AC-1418] Add initial SM adjustment form * [AC-1418] Adjust organization-subscription-update.request.ts to support both PM and SM * [AC-1418] Rename service account fields in the options interface * [AC-1418] Add api service call to update SM subscription * [AC-1418] Cleanup form html * [AC-1418] Add missing SM plan properties * [AC-1418] Add SM subscription adjust form and logic to hide it * [AC-1418] Add better docs to options interface * [AC-1418] Fix conflicting required/optional labels for auto-scaling limits * [AC-1418] Adjust labels and appearance to better match design * [AC-1418] Use the SM plan for billing interval * [AC-1418] Hide SM billing adjustment component behind feature flag * [AC-1418] Update request model to match server * [AC-1418] Cleanup BitwardenProductType after merge Add to barrel file and update applicable imports. * [AC-1418] Revert change to update PM subscription request model * [AC-1418] Add new update SM subscription request model * [AC-1418] Add new service method to update SM subscription * [AC-1418] Use new model and service method * [AC-1418] Cleanup SM subscription UI flags * [AC-1418] Move SM adjust subscription component into SM billing module * [AC-1418] Update SM seat count minimum to 1 * [AC-1418] Add missing currency codes * [AC-1418] Simplify monthly price calculation * [AC-1418] Increase PM adjust subscription form input width * [AC-1418] Add check for null subscription --------- Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com> * add the 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 --------- Co-authored-by: Shane Melton * [AC-1473] SM beta ending callout (#5719) * [AC-1423] Add minWidth input to bit-progress component * [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-1423] Simply sort function * [AC-1423] Remove header border * [AC-1423] Remove redundant condition * [AC-1423] Remove ineffective div * [AC-1423] Make "Password Manager" the default fallback for product name * Revert "[AC-1423] Add minWidth input to bit-progress component" This reverts commit 95b2223a30e45966988bfed2e08a9631fa8980b9. * [AC-1423] Remove minWidth attribute * [AC-1423] Switch to AddonProductType enum instead of boolean * Revert "[AC-1423] Switch to AddonProductType enum instead of boolean" This reverts commit 204f64b4e7f76cf43a7dbc6161332553047592df. * [AC-1423] Tweak sorting comment * [AC-1418] Add initial SecretsManagerAdjustSubscription component * [AC-1418] Add initial SM adjustment form * [AC-1418] Adjust organization-subscription-update.request.ts to support both PM and SM * [AC-1418] Rename service account fields in the options interface * [AC-1418] Add api service call to update SM subscription * [AC-1418] Cleanup form html * [AC-1418] Add missing SM plan properties * [AC-1418] Add SM subscription adjust form and logic to hide it * [AC-1418] Add better docs to options interface * [AC-1418] Fix conflicting required/optional labels for auto-scaling limits * [AC-1418] Adjust labels and appearance to better match design * [AC-1418] Use the SM plan for billing interval * [AC-1418] Hide SM billing adjustment component behind feature flag * [AC-1418] Update request model to match server * [AC-1418] Cleanup BitwardenProductType after merge Add to barrel file and update applicable imports. * [AC-1418] Revert change to update PM subscription request model * [AC-1418] Add new update SM subscription request model * [AC-1418] Add new service method to update SM subscription * [AC-1418] Use new model and service method * [AC-1418] Cleanup SM subscription UI flags * [AC-1418] Move SM adjust subscription component into SM billing module * [AC-1418] Update SM seat count minimum to 1 * [AC-1418] Add missing currency codes * [AC-1418] Simplify monthly price calculation * add daysRemaining util function and unit tests * [AC-1474] update organization models to include SM beta flag * add SM beta callout to org subscription page * update messages.json * remove beta field from profile org response * improve daysRemaining code clarity * set SM beta in org model constructor * tweak free SM row visibility * refactor callout description * Revert "remove beta field from profile org response" This reverts commit 6c6249e1ec3c54b08f21f0895f9e2c23fbd58e9c. * fix dates * [AC-1468]: hide adjust SM component if beta user * add sm beta field to org sub response; remove everywhere else * fix copy --------- Co-authored-by: Shane Melton Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com> Co-authored-by: Thomas Rittson * [AC-1531] Fix SM subscribe component not showing in free org billing tab (#5848) Also: * Fix spacing in layout * Send zero values for free plans * Fix: properly delete enroll component * remove the beta end message for free org (#5877) * [AC-1458] Update local organization data after subscribing to Secrets Manager (#5888) * [AC-1567] Fix max additional service account cost estimate (#5923) * Fix max additional service account cost estimate * Update i18n string ref * Make i18n string keys consistent * [AC-1461] Secrets Manager seat autoscaling cleanup (#5924) * Remove unused return value from putOrganizationUserBulkEnableSecretsManager * Fix service account limit validator (#5926) * Updated Utils.daysRemaining method to calculate result using Math.floor and updated unit tests. --------- Co-authored-by: Shane Melton Co-authored-by: cyprain-okeke <108260115+cyprain-okeke@users.noreply.github.com> Co-authored-by: Rui Tome Co-authored-by: Will Martin Co-authored-by: Álison Fernandes Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com> --- .../browser/src/background/main.background.ts | 2 +- ...nization-subscription-cloud.component.html | 21 +++++++++++- ...ganization-subscription-cloud.component.ts | 17 +++++++++- .../sm-adjust-subscription.component.html | 19 +++++------ .../sm-adjust-subscription.component.ts | 20 ++++++------ .../sm-subscribe-standalone.component.ts | 15 +++++++-- .../sm-subscribe.component.html | 11 ++++--- apps/web/src/locales/en/messages.json | 32 ++++++++++++++++--- .../src/services/jslib-services.module.ts | 4 +-- .../organization-user.service.ts | 2 +- .../organization-api.service.abstraction.ts | 6 +++- .../organization.service.abstraction.ts | 3 +- .../organization/organization-api.service.ts | 8 +++-- .../organization/organization.service.ts | 2 +- .../organization-subscription.response.ts | 2 ++ libs/common/src/platform/misc/utils.spec.ts | 28 ++++++++++++++++ libs/common/src/platform/misc/utils.ts | 10 ++++++ ...rganization-user.service.implementation.ts | 7 ++-- .../src/vault/services/sync/sync.service.ts | 4 +-- 19 files changed, 167 insertions(+), 46 deletions(-) diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index b0f5d7f3da..4e31035469 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -9,7 +9,7 @@ import { SettingsService as SettingsServiceAbstraction } from "@bitwarden/common import { TotpService as TotpServiceAbstraction } from "@bitwarden/common/abstractions/totp.service"; import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeout.service"; import { VaultTimeoutSettingsService as VaultTimeoutSettingsServiceAbstraction } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeoutSettings.service"; -import { InternalOrganizationService as InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; +import { InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction"; import { InternalPolicyService as InternalPolicyServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { ProviderService as ProviderServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/provider.service"; diff --git a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.html b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.html index 78841dc74f..4508b6cd07 100644 --- a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.html +++ b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.html @@ -87,13 +87,32 @@ {{ "passwordManager" | i18n }} - {{ "freeOrganization" | i18n }} {{ "free" | i18n }} - + {{ "secretsManager" | i18n }} - {{ "freeOrganization" | i18n }} {{ "free" | i18n }} + + + {{ "secretsManager" | i18n }} - + {{ "beta" | i18n }} + ({{ "annually" | i18n }}) @ + {{ 0 | currency : "$" }} + {{ + "betaEnding" | i18n | uppercase + }} + + {{ 0 | currency : "$" }} /{{ "year" | i18n }} + + + {{ smBetaEndedDesc }} + diff --git a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts index df58f31bcd..f03fb72faf 100644 --- a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts +++ b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts @@ -1,3 +1,4 @@ +import { DatePipe } from "@angular/common"; import { Component, OnDestroy, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { concatMap, Subject, takeUntil } from "rxjs"; @@ -17,6 +18,7 @@ import { ConfigServiceAbstraction } from "@bitwarden/common/platform/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"; +import { Utils } from "@bitwarden/common/platform/misc/utils"; import { BillingSyncApiKeyComponent, @@ -45,6 +47,9 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy firstLoaded = false; loading: boolean; + private readonly _smBetaEndingDate = new Date(2023, 7, 25); + private readonly _smGracePeriodEndingDate = new Date(2023, 9, 24); + private destroy$ = new Subject(); constructor( @@ -57,7 +62,8 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy private organizationApiService: OrganizationApiServiceAbstraction, private route: ActivatedRoute, private dialogService: DialogServiceAbstraction, - private configService: ConfigServiceAbstraction + private configService: ConfigServiceAbstraction, + private datePipe: DatePipe ) {} async ngOnInit() { @@ -122,6 +128,7 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy this.userOrg.useSecretsManager && this.subscription != null && this.sub.secretsManagerPlan?.hasAdditionalSeatsOption && + !this.sub.secretsManagerBeta && !this.subscription.cancelled && !this.subscriptionMarkedForCancel; @@ -256,6 +263,14 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy ); } + get smBetaEndedDesc() { + return this.i18nService.translate( + "smBetaEndedDesc", + this.datePipe.transform(this._smBetaEndingDate), + Utils.daysRemaining(this._smGracePeriodEndingDate).toString() + ); + } + cancel = async () => { if (this.loading) { return; diff --git a/apps/web/src/app/billing/organizations/secrets-manager/sm-adjust-subscription.component.html b/apps/web/src/app/billing/organizations/secrets-manager/sm-adjust-subscription.component.html index be882cf66b..6aece8fe89 100644 --- a/apps/web/src/app/billing/organizations/secrets-manager/sm-adjust-subscription.component.html +++ b/apps/web/src/app/billing/organizations/secrets-manager/sm-adjust-subscription.component.html @@ -5,7 +5,7 @@ {{ "total" | i18n }}: {{ formGroup.value.seatCount || 0 }} × {{ options.seatPrice | currency : "$" }} = - {{ seatTotal | currency : "$" }} / {{ options.interval | i18n }} + {{ seatTotalCost | currency : "$" }} / {{ options.interval | i18n }} @@ -28,7 +28,7 @@ {{ "maxSeatCost" | i18n }}: {{ formGroup.value.maxAutoscaleSeats || 0 }} × - {{ options.seatPrice | currency : "$" }} = {{ maxSeatTotal | currency : "$" }} / + {{ options.seatPrice | currency : "$" }} = {{ maxSeatTotalCost | currency : "$" }} / {{ options.interval | i18n }} @@ -44,16 +44,14 @@ />
- {{ - "additionalServiceAccountsDesc" - | i18n : options.baseServiceAccountCount : (monthlyServiceAccountPrice | currency : "$") - }} + {{ "includedServiceAccounts" | i18n : options.baseServiceAccountCount }} + {{ "addAdditionalServiceAccounts" | i18n : (monthlyServiceAccountPrice | currency : "$") }}
{{ "total" | i18n }}: {{ formGroup.value.additionalServiceAccounts || 0 }} × {{ options.additionalServiceAccountPrice | currency : "$" }} = - {{ serviceAccountTotal | currency : "$" }} / {{ options.interval | i18n }} + {{ serviceAccountTotalCost | currency : "$" }} / {{ options.interval | i18n }}
@@ -80,10 +78,13 @@ [min]="formGroup.value.additionalServiceAccounts" /> +
+ {{ "includedServiceAccounts" | i18n : options.baseServiceAccountCount }} +
{{ "maxServiceAccountCost" | i18n }}: - {{ formGroup.value.maxAutoscaleServiceAccounts || 0 }} × + {{ maxAdditionalServiceAccounts }} × {{ options.additionalServiceAccountPrice | currency : "$" }} = - {{ maxServiceAccountTotal | currency : "$" }} / {{ options.interval | i18n }} + {{ maxServiceAccountTotalCost | currency : "$" }} / {{ options.interval | i18n }}