From 4b67cd24b451255981218cb5e9436b23fbbda5e7 Mon Sep 17 00:00:00 2001 From: Jared Snider <116684653+JaredSnider-Bitwarden@users.noreply.github.com> Date: Wed, 16 Oct 2024 18:28:27 -0400 Subject: [PATCH 01/10] Auth/PM-8112 - UI refresh - Registration Components (#11353) * PM-8112 - Update classes of existing registration icons * PM-8112 - Add new icons * PM-8112 - Export icons from libs/auth * PM-8112 - RegistrationStart - Add new user icon as page icon * PM-8112 - Replace RegistrationCheckEmailIcon with new icon so it displays properly * PM-8112 - RegistrationFinish - Add new icon across clients * PM-8112 - Registration start comp - update page icon and page title on state change to match figma * PM-8112 - RegistrationFinish - adding most of framework for changing page title & subtitle when an org invite is in state. * PM-8112 - Add joinOrganizationName to all clients translations * PM-8112 - RegistrationFinish - Remove default page title & subtitle and let onInit logic figure out what to set based on flows. * PM-8112 - RegistrationStart - Fix setAnonLayoutWrapperData calls * PM-8112 - RegistrationFinish - simplify qParams init logic to make handling loading and page title and subtitle setting easier. * PM-8112 - Registration Link expired - move icon to page icon out of main content * PM-8112 - RegistrationFinish - Refactor init logic further into distinct flows. * PM-8112 - Fix icons * PM-8112 - Extension AppRoutingModule - move sign up start & finish routes under extension anon layout * PM-8112 - Fix storybook * PM-8112 - Clean up unused prop * PM-8112 - RegistrationLockAltIcon tweaks * PM-8112 - Update icons to have proper styling * PM-8112 - RegistrationUserAddIcon - remove unnecessary svg class * PM-8112 - Fix icons --- apps/browser/src/_locales/en/messages.json | 9 ++ apps/browser/src/popup/app-routing.module.ts | 86 ++++++------ apps/desktop/src/app/app-routing.module.ts | 10 +- apps/desktop/src/locales/en/messages.json | 9 ++ .../web-registration-finish.service.spec.ts | 30 +++++ .../web-registration-finish.service.ts | 9 ++ apps/web/src/app/oss-routing.module.ts | 12 +- apps/web/src/locales/en/messages.json | 9 ++ libs/auth/src/angular/icons/index.ts | 3 + .../icons/registration-check-email.icon.ts | 29 +++-- .../icons/registration-expired-link.icon.ts | 21 +-- .../icons/registration-lock-alt.icon.ts | 41 ++++++ .../icons/registration-user-add.icon.ts | 24 ++++ ...efault-registration-finish.service.spec.ts | 8 ++ .../default-registration-finish.service.ts | 4 + .../registration-finish.component.ts | 123 +++++++++++------- .../registration-finish.service.ts | 9 +- .../registration-link-expired.component.html | 2 - .../registration-start.component.html | 13 -- .../registration-start.component.ts | 16 ++- .../registration-start.stories.ts | 10 ++ 21 files changed, 336 insertions(+), 141 deletions(-) create mode 100644 libs/auth/src/angular/icons/registration-lock-alt.icon.ts create mode 100644 libs/auth/src/angular/icons/registration-user-add.icon.ts diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index 25386222d4..290663f434 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -71,6 +71,15 @@ "joinOrganization": { "message": "Join organization" }, + "joinOrganizationName": { + "message": "Join $ORGANIZATIONNAME$", + "placeholders": { + "organizationName": { + "content": "$1", + "example": "My Org Name" + } + } + }, "finishJoiningThisOrganizationBySettingAMasterPassword": { "message": "Finish joining this organization by setting a master password." }, diff --git a/apps/browser/src/popup/app-routing.module.ts b/apps/browser/src/popup/app-routing.module.ts index 0bf26f8c07..1a95ad7483 100644 --- a/apps/browser/src/popup/app-routing.module.ts +++ b/apps/browser/src/popup/app-routing.module.ts @@ -20,9 +20,11 @@ import { LockV2Component, PasswordHintComponent, RegistrationFinishComponent, + RegistrationLockAltIcon, RegistrationStartComponent, RegistrationStartSecondaryComponent, RegistrationStartSecondaryComponentData, + RegistrationUserAddIcon, SetPasswordJitComponent, UserLockIcon, } from "@bitwarden/auth/angular"; @@ -448,6 +450,47 @@ const routes: Routes = [ path: "", component: ExtensionAnonLayoutWrapperComponent, children: [ + { + path: "signup", + canActivate: [canAccessFeature(FeatureFlag.EmailVerification), unauthGuardFn()], + data: { + state: "signup", + pageIcon: RegistrationUserAddIcon, + pageTitle: { + key: "createAccount", + }, + showBackButton: true, + } satisfies RouteDataProperties & ExtensionAnonLayoutWrapperData, + children: [ + { + path: "", + component: RegistrationStartComponent, + }, + { + path: "", + component: RegistrationStartSecondaryComponent, + outlet: "secondary", + data: { + loginRoute: "/home", + } satisfies RegistrationStartSecondaryComponentData, + }, + ], + }, + { + path: "finish-signup", + canActivate: [canAccessFeature(FeatureFlag.EmailVerification), unauthGuardFn()], + data: { + pageIcon: RegistrationLockAltIcon, + state: "finish-signup", + showBackButton: true, + } satisfies RouteDataProperties & ExtensionAnonLayoutWrapperData, + children: [ + { + path: "", + component: RegistrationFinishComponent, + }, + ], + }, { path: "lockV2", canActivate: [canAccessFeature(FeatureFlag.ExtensionRefresh), lockGuard()], @@ -472,49 +515,6 @@ const routes: Routes = [ path: "", component: AnonLayoutWrapperComponent, children: [ - { - path: "signup", - canActivate: [canAccessFeature(FeatureFlag.EmailVerification), unauthGuardFn()], - data: { - state: "signup", - pageTitle: { - key: "createAccount", - }, - } satisfies RouteDataProperties & AnonLayoutWrapperData, - children: [ - { - path: "", - component: RegistrationStartComponent, - }, - { - path: "", - component: RegistrationStartSecondaryComponent, - outlet: "secondary", - data: { - loginRoute: "/home", - } satisfies RegistrationStartSecondaryComponentData, - }, - ], - }, - { - path: "finish-signup", - canActivate: [canAccessFeature(FeatureFlag.EmailVerification), unauthGuardFn()], - data: { - pageTitle: { - key: "setAStrongPassword", - }, - pageSubtitle: { - key: "finishCreatingYourAccountBySettingAPassword", - }, - state: "finish-signup", - } satisfies RouteDataProperties & AnonLayoutWrapperData, - children: [ - { - path: "", - component: RegistrationFinishComponent, - }, - ], - }, { path: "set-password-jit", canActivate: [canAccessFeature(FeatureFlag.EmailVerification)], diff --git a/apps/desktop/src/app/app-routing.module.ts b/apps/desktop/src/app/app-routing.module.ts index e8ae31e78a..8b8f62047f 100644 --- a/apps/desktop/src/app/app-routing.module.ts +++ b/apps/desktop/src/app/app-routing.module.ts @@ -19,9 +19,11 @@ import { LockV2Component, PasswordHintComponent, RegistrationFinishComponent, + RegistrationLockAltIcon, RegistrationStartComponent, RegistrationStartSecondaryComponent, RegistrationStartSecondaryComponentData, + RegistrationUserAddIcon, SetPasswordJitComponent, UserLockIcon, } from "@bitwarden/auth/angular"; @@ -169,6 +171,7 @@ const routes: Routes = [ path: "signup", canActivate: [canAccessFeature(FeatureFlag.EmailVerification), unauthGuardFn()], data: { + pageIcon: RegistrationUserAddIcon, pageTitle: { key: "createAccount", }, @@ -192,12 +195,7 @@ const routes: Routes = [ path: "finish-signup", canActivate: [canAccessFeature(FeatureFlag.EmailVerification), unauthGuardFn()], data: { - pageTitle: { - key: "setAStrongPassword", - }, - pageSubtitle: { - key: "finishCreatingYourAccountBySettingAPassword", - }, + pageIcon: RegistrationLockAltIcon, } satisfies AnonLayoutWrapperData, children: [ { diff --git a/apps/desktop/src/locales/en/messages.json b/apps/desktop/src/locales/en/messages.json index 4647853f71..9924a91fa3 100644 --- a/apps/desktop/src/locales/en/messages.json +++ b/apps/desktop/src/locales/en/messages.json @@ -602,6 +602,15 @@ "joinOrganization": { "message": "Join organization" }, + "joinOrganizationName": { + "message": "Join $ORGANIZATIONNAME$", + "placeholders": { + "organizationName": { + "content": "$1", + "example": "My Org Name" + } + } + }, "finishJoiningThisOrganizationBySettingAMasterPassword": { "message": "Finish joining this organization by setting a master password." }, diff --git a/apps/web/src/app/auth/core/services/registration/web-registration-finish.service.spec.ts b/apps/web/src/app/auth/core/services/registration/web-registration-finish.service.spec.ts index 2faf3f85d1..45eb3c5c0d 100644 --- a/apps/web/src/app/auth/core/services/registration/web-registration-finish.service.spec.ts +++ b/apps/web/src/app/auth/core/services/registration/web-registration-finish.service.spec.ts @@ -52,6 +52,36 @@ describe("DefaultRegistrationFinishService", () => { expect(service).not.toBeFalsy(); }); + describe("getOrgNameFromOrgInvite()", () => { + let orgInvite: OrganizationInvite | null; + + beforeEach(() => { + orgInvite = new OrganizationInvite(); + orgInvite.organizationId = "organizationId"; + orgInvite.organizationUserId = "organizationUserId"; + orgInvite.token = "orgInviteToken"; + orgInvite.email = "email"; + }); + + it("returns null when the org invite is null", async () => { + acceptOrgInviteService.getOrganizationInvite.mockResolvedValue(null); + + const result = await service.getOrgNameFromOrgInvite(); + + expect(result).toBeNull(); + expect(acceptOrgInviteService.getOrganizationInvite).toHaveBeenCalled(); + }); + + it("returns the organization name from the organization invite when it exists", async () => { + acceptOrgInviteService.getOrganizationInvite.mockResolvedValue(orgInvite); + + const result = await service.getOrgNameFromOrgInvite(); + + expect(result).toEqual(orgInvite.organizationName); + expect(acceptOrgInviteService.getOrganizationInvite).toHaveBeenCalled(); + }); + }); + describe("getMasterPasswordPolicyOptsFromOrgInvite()", () => { let orgInvite: OrganizationInvite | null; diff --git a/apps/web/src/app/auth/core/services/registration/web-registration-finish.service.ts b/apps/web/src/app/auth/core/services/registration/web-registration-finish.service.ts index 5239601bbc..560196dd19 100644 --- a/apps/web/src/app/auth/core/services/registration/web-registration-finish.service.ts +++ b/apps/web/src/app/auth/core/services/registration/web-registration-finish.service.ts @@ -32,6 +32,15 @@ export class WebRegistrationFinishService super(cryptoService, accountApiService); } + override async getOrgNameFromOrgInvite(): Promise { + const orgInvite = await this.acceptOrgInviteService.getOrganizationInvite(); + if (orgInvite == null) { + return null; + } + + return orgInvite.organizationName; + } + override async getMasterPasswordPolicyOptsFromOrgInvite(): Promise { // If there's a deep linked org invite, use it to get the password policies const orgInvite = await this.acceptOrgInviteService.getOrganizationInvite(); diff --git a/apps/web/src/app/oss-routing.module.ts b/apps/web/src/app/oss-routing.module.ts index fa4da88ce7..8822800b36 100644 --- a/apps/web/src/app/oss-routing.module.ts +++ b/apps/web/src/app/oss-routing.module.ts @@ -25,6 +25,9 @@ import { LockV2Component, LockIcon, UserLockIcon, + RegistrationUserAddIcon, + RegistrationLockAltIcon, + RegistrationExpiredLinkIcon, } from "@bitwarden/auth/angular"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; @@ -234,6 +237,7 @@ const routes: Routes = [ path: "signup", canActivate: [canAccessFeature(FeatureFlag.EmailVerification), unauthGuardFn()], data: { + pageIcon: RegistrationUserAddIcon, pageTitle: { key: "createAccount", }, @@ -258,12 +262,7 @@ const routes: Routes = [ path: "finish-signup", canActivate: [canAccessFeature(FeatureFlag.EmailVerification), unauthGuardFn()], data: { - pageTitle: { - key: "setAStrongPassword", - }, - pageSubtitle: { - key: "finishCreatingYourAccountBySettingAPassword", - }, + pageIcon: RegistrationLockAltIcon, titleId: "setAStrongPassword", } satisfies RouteDataProperties & AnonLayoutWrapperData, children: [ @@ -310,6 +309,7 @@ const routes: Routes = [ path: "signup-link-expired", canActivate: [canAccessFeature(FeatureFlag.EmailVerification), unauthGuardFn()], data: { + pageIcon: RegistrationExpiredLinkIcon, pageTitle: { key: "expiredLink", }, diff --git a/apps/web/src/locales/en/messages.json b/apps/web/src/locales/en/messages.json index 96e987a7f6..5125bb1bfe 100644 --- a/apps/web/src/locales/en/messages.json +++ b/apps/web/src/locales/en/messages.json @@ -3781,6 +3781,15 @@ "joinOrganization": { "message": "Join organization" }, + "joinOrganizationName": { + "message": "Join $ORGANIZATIONNAME$", + "placeholders": { + "organizationName": { + "content": "$1", + "example": "My Org Name" + } + } + }, "joinOrganizationDesc": { "message": "You've been invited to join the organization listed above. To accept the invitation, you need to log in or create a new Bitwarden account." }, diff --git a/libs/auth/src/angular/icons/index.ts b/libs/auth/src/angular/icons/index.ts index cfcad992e3..26e668b784 100644 --- a/libs/auth/src/angular/icons/index.ts +++ b/libs/auth/src/angular/icons/index.ts @@ -3,3 +3,6 @@ export * from "./bitwarden-shield.icon"; export * from "./lock.icon"; export * from "./user-lock.icon"; export * from "./user-verification-biometrics-fingerprint.icon"; +export * from "./registration-user-add.icon"; +export * from "./registration-lock-alt.icon"; +export * from "./registration-expired-link.icon"; diff --git a/libs/auth/src/angular/icons/registration-check-email.icon.ts b/libs/auth/src/angular/icons/registration-check-email.icon.ts index 1d173ff585..6f7dd6a2d6 100644 --- a/libs/auth/src/angular/icons/registration-check-email.icon.ts +++ b/libs/auth/src/angular/icons/registration-check-email.icon.ts @@ -1,12 +1,23 @@ import { svgIcon } from "@bitwarden/components"; export const RegistrationCheckEmailIcon = svgIcon` - - - - - - - - -`; + + + + + + + + + + + +`; diff --git a/libs/auth/src/angular/icons/registration-expired-link.icon.ts b/libs/auth/src/angular/icons/registration-expired-link.icon.ts index 50bcc53808..3323c7f0b2 100644 --- a/libs/auth/src/angular/icons/registration-expired-link.icon.ts +++ b/libs/auth/src/angular/icons/registration-expired-link.icon.ts @@ -1,20 +1,9 @@ import { svgIcon } from "@bitwarden/components"; export const RegistrationExpiredLinkIcon = svgIcon` - - - - - - - - - - + + + `; diff --git a/libs/auth/src/angular/icons/registration-lock-alt.icon.ts b/libs/auth/src/angular/icons/registration-lock-alt.icon.ts new file mode 100644 index 0000000000..511f9710dc --- /dev/null +++ b/libs/auth/src/angular/icons/registration-lock-alt.icon.ts @@ -0,0 +1,41 @@ +import { svgIcon } from "@bitwarden/components"; + +export const RegistrationLockAltIcon = svgIcon` + + + + + + + + + + + + + +`; diff --git a/libs/auth/src/angular/icons/registration-user-add.icon.ts b/libs/auth/src/angular/icons/registration-user-add.icon.ts new file mode 100644 index 0000000000..69240cd029 --- /dev/null +++ b/libs/auth/src/angular/icons/registration-user-add.icon.ts @@ -0,0 +1,24 @@ +import { svgIcon } from "@bitwarden/components"; + +export const RegistrationUserAddIcon = svgIcon` + + + + + + + + + + +`; diff --git a/libs/auth/src/angular/registration/registration-finish/default-registration-finish.service.spec.ts b/libs/auth/src/angular/registration/registration-finish/default-registration-finish.service.spec.ts index 5417d617a9..fe6b9b2c7d 100644 --- a/libs/auth/src/angular/registration/registration-finish/default-registration-finish.service.spec.ts +++ b/libs/auth/src/angular/registration/registration-finish/default-registration-finish.service.spec.ts @@ -37,6 +37,14 @@ describe("DefaultRegistrationFinishService", () => { }); }); + describe("getOrgNameFromOrgInvite()", () => { + it("returns null", async () => { + const result = await service.getOrgNameFromOrgInvite(); + + expect(result).toBeNull(); + }); + }); + describe("finishRegistration()", () => { let email: string; let emailVerificationToken: string; diff --git a/libs/auth/src/angular/registration/registration-finish/default-registration-finish.service.ts b/libs/auth/src/angular/registration/registration-finish/default-registration-finish.service.ts index 63b01be995..6d77c77749 100644 --- a/libs/auth/src/angular/registration/registration-finish/default-registration-finish.service.ts +++ b/libs/auth/src/angular/registration/registration-finish/default-registration-finish.service.ts @@ -15,6 +15,10 @@ export class DefaultRegistrationFinishService implements RegistrationFinishServi protected accountApiService: AccountApiService, ) {} + getOrgNameFromOrgInvite(): Promise { + return null; + } + getMasterPasswordPolicyOptsFromOrgInvite(): Promise { return null; } diff --git a/libs/auth/src/angular/registration/registration-finish/registration-finish.component.ts b/libs/auth/src/angular/registration/registration-finish/registration-finish.component.ts index ef40d95dce..be9d8abe5b 100644 --- a/libs/auth/src/angular/registration/registration-finish/registration-finish.component.ts +++ b/libs/auth/src/angular/registration/registration-finish/registration-finish.component.ts @@ -1,7 +1,7 @@ import { CommonModule } from "@angular/common"; import { Component, OnDestroy, OnInit } from "@angular/core"; import { ActivatedRoute, Params, Router, RouterModule } from "@angular/router"; -import { EMPTY, Subject, from, switchMap, takeUntil, tap } from "rxjs"; +import { Subject, firstValueFrom } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options"; @@ -15,6 +15,7 @@ import { ValidationService } from "@bitwarden/common/platform/abstractions/valid import { ToastService } from "@bitwarden/components"; import { LoginStrategyServiceAbstraction, PasswordLoginCredentials } from "../../../common"; +import { AnonLayoutWrapperDataService } from "../../anon-layout/anon-layout-wrapper-data.service"; import { InputPasswordComponent } from "../../input-password/input-password.component"; import { PasswordInputResult } from "../../input-password/password-input-result"; @@ -60,55 +61,72 @@ export class RegistrationFinishComponent implements OnInit, OnDestroy { private accountApiService: AccountApiService, private loginStrategyService: LoginStrategyServiceAbstraction, private logService: LogService, + private anonLayoutWrapperDataService: AnonLayoutWrapperDataService, ) {} async ngOnInit() { - this.listenForQueryParamChanges(); - this.masterPasswordPolicyOptions = - await this.registrationFinishService.getMasterPasswordPolicyOptsFromOrgInvite(); + const qParams = await firstValueFrom(this.activatedRoute.queryParams); + this.handleQueryParams(qParams); + + if ( + qParams.fromEmail && + qParams.fromEmail === "true" && + this.email && + this.emailVerificationToken + ) { + await this.initEmailVerificationFlow(); + } else { + // Org Invite flow OR registration with email verification disabled Flow + const orgInviteFlow = await this.initOrgInviteFlowIfPresent(); + + if (!orgInviteFlow) { + this.initRegistrationWithEmailVerificationDisabledFlow(); + } + } + + this.loading = false; } - private listenForQueryParamChanges() { - this.activatedRoute.queryParams - .pipe( - tap((qParams: Params) => { - if (qParams.email != null && qParams.email.indexOf("@") > -1) { - this.email = qParams.email; - } + private handleQueryParams(qParams: Params) { + if (qParams.email != null && qParams.email.indexOf("@") > -1) { + this.email = qParams.email; + } - if (qParams.token != null) { - this.emailVerificationToken = qParams.token; - } + if (qParams.token != null) { + this.emailVerificationToken = qParams.token; + } - if (qParams.orgSponsoredFreeFamilyPlanToken != null) { - this.orgSponsoredFreeFamilyPlanToken = qParams.orgSponsoredFreeFamilyPlanToken; - } + if (qParams.orgSponsoredFreeFamilyPlanToken != null) { + this.orgSponsoredFreeFamilyPlanToken = qParams.orgSponsoredFreeFamilyPlanToken; + } - if (qParams.acceptEmergencyAccessInviteToken != null && qParams.emergencyAccessId) { - this.acceptEmergencyAccessInviteToken = qParams.acceptEmergencyAccessInviteToken; - this.emergencyAccessId = qParams.emergencyAccessId; - } - }), - switchMap((qParams: Params) => { - if ( - qParams.fromEmail && - qParams.fromEmail === "true" && - this.email && - this.emailVerificationToken - ) { - return from( - this.registerVerificationEmailClicked(this.email, this.emailVerificationToken), - ); - } else { - // org invite flow - this.loading = false; - return EMPTY; - } - }), + if (qParams.acceptEmergencyAccessInviteToken != null && qParams.emergencyAccessId) { + this.acceptEmergencyAccessInviteToken = qParams.acceptEmergencyAccessInviteToken; + this.emergencyAccessId = qParams.emergencyAccessId; + } + } - takeUntil(this.destroy$), - ) - .subscribe(); + private async initOrgInviteFlowIfPresent(): Promise { + this.masterPasswordPolicyOptions = + await this.registrationFinishService.getMasterPasswordPolicyOptsFromOrgInvite(); + + const orgName = await this.registrationFinishService.getOrgNameFromOrgInvite(); + if (orgName) { + // Org invite exists + // Set the page title and subtitle appropriately + this.anonLayoutWrapperDataService.setAnonLayoutWrapperData({ + pageTitle: { + key: "joinOrganizationName", + placeholders: [orgName], + }, + pageSubtitle: { + key: "finishJoiningThisOrganizationBySettingAMasterPassword", + }, + }); + return true; + } + + return false; } async handlePasswordFormSubmit(passwordInputResult: PasswordInputResult) { @@ -162,9 +180,24 @@ export class RegistrationFinishComponent implements OnInit, OnDestroy { this.submitting = false; } + private setDefaultPageTitleAndSubtitle() { + this.anonLayoutWrapperDataService.setAnonLayoutWrapperData({ + pageTitle: { + key: "setAStrongPassword", + }, + pageSubtitle: { + key: "finishCreatingYourAccountBySettingAPassword", + }, + }); + } + + private async initEmailVerificationFlow() { + this.setDefaultPageTitleAndSubtitle(); + await this.registerVerificationEmailClicked(this.email, this.emailVerificationToken); + } + private async registerVerificationEmailClicked(email: string, emailVerificationToken: string) { const request = new RegisterVerificationEmailClickedRequest(email, emailVerificationToken); - try { const result = await this.accountApiService.registerVerificationEmailClicked(request); @@ -174,11 +207,9 @@ export class RegistrationFinishComponent implements OnInit, OnDestroy { message: this.i18nService.t("emailVerifiedV2"), variant: "success", }); - this.loading = false; } } catch (e) { await this.handleRegisterVerificationEmailClickedError(e); - this.loading = false; } } @@ -204,6 +235,10 @@ export class RegistrationFinishComponent implements OnInit, OnDestroy { } } + private initRegistrationWithEmailVerificationDisabledFlow() { + this.setDefaultPageTitleAndSubtitle(); + } + ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); diff --git a/libs/auth/src/angular/registration/registration-finish/registration-finish.service.ts b/libs/auth/src/angular/registration/registration-finish/registration-finish.service.ts index b585aa78ed..b7abd38108 100644 --- a/libs/auth/src/angular/registration/registration-finish/registration-finish.service.ts +++ b/libs/auth/src/angular/registration/registration-finish/registration-finish.service.ts @@ -3,6 +3,13 @@ import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/mod import { PasswordInputResult } from "../../input-password/password-input-result"; export abstract class RegistrationFinishService { + /** + * Retrieves the organization name from an organization invite if it exists. + * Organization invites can currently only be accepted on the web. + * @returns a promise which resolves to the organization name string or null if no invite exists. + */ + abstract getOrgNameFromOrgInvite(): Promise; + /** * Gets the master password policy options from an organization invite if it exits. * Organization invites can currently only be accepted on the web. @@ -18,7 +25,7 @@ export abstract class RegistrationFinishService { * @param orgSponsoredFreeFamilyPlanToken The optional org sponsored free family plan token. * @param acceptEmergencyAccessInviteToken The optional accept emergency access invite token. * @param emergencyAccessId The optional emergency access id which is required to validate the emergency access invite token. - * Returns a promise which resolves to the captcha bypass token string upon a successful account creation. + * @returns a promise which resolves to the captcha bypass token string upon a successful account creation. */ abstract finishRegistration( email: string, diff --git a/libs/auth/src/angular/registration/registration-link-expired/registration-link-expired.component.html b/libs/auth/src/angular/registration/registration-link-expired/registration-link-expired.component.html index 5aa6866bbe..7714990231 100644 --- a/libs/auth/src/angular/registration/registration-link-expired/registration-link-expired.component.html +++ b/libs/auth/src/angular/registration/registration-link-expired/registration-link-expired.component.html @@ -1,6 +1,4 @@
- -

- - -

- {{ "checkYourEmail" | i18n }} -

-

{{ "collectionManagement" | i18n }}

{{ "collectionManagementDesc" | i18n }}

@@ -60,12 +64,24 @@ {{ "allowAdminAccessToAllCollectionItemsDesc" | i18n }} - - {{ "limitCollectionCreationDeletionDesc" | i18n }} - - + + + {{ "limitCollectionCreationDesc" | i18n }} + + + + {{ "limitCollectionDeletionDesc" | i18n }} + + + + + + {{ "limitCollectionCreationDeletionDesc" | i18n }} + + + -