mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 00:03:56 +00:00
Auth/PM-7324 - Registration with Email Verification - Registration Start Component Implementation (#9573)
* PM-7324 - Register new registration start comp at signup route on web * PM-7324 - Add registerSendVerificationEmail logic in API service layer. * PM-7324 - Update registration start comp to actually send information to API and trigger email. * PM-7324 - progress on opt in for marketing emails redesign. * PM-7324 - Add feature flag and feature flag guard to sign up route. * PM-7324 - RegistrationEnvSelector - emit initial value * PM-7324 - Registration Start comp - wire up setReceiveMarketingEmailsByRegion logic. * PM-7324 - Registration start html - use proper link for email pref management. * PM-7324 - Translate text * PM-7324 - Design pass * PM-7324 - design pass v2 * PM-7324 - Update Tailwind config to add availability of anon layout to desktop and browser extension * PM-7324 - Desktop - AppRoutingModule - Add new signup route protected by the email verification feature flag. * PM-7324 - BrowserExtension - AppRoutingModule - Add signup route protected by feature flag * PM-7324 - Feature flag all register page navigations to redirect users to the new signup page. * PM-7324 - Update AnonLayoutWrapperComponent constructor logic to avoid passing undefined values into I18nService.t method * PM-7324 - Accept org invite web comp - adjust register url and qParams * PM-7324 - Add AnonLayoutWrapperData to desktop & browser since we don't need titleId. * PM-7324 - Revert anon layout wrapper comp changes as they were made separately and merged to main. * PM-7234 - Fix registration start component so the login route works for the browser extension. * PM-7324 - Registration start story now building again + fix storybook warning around BrowserAnimationsModule * PM-7324 - Registration Start - add missing tw-text-main to fix dark mode rendering. * PM-7324 - Update storybook docs * PM-7324 - Get stub of registration finish component so that the verify email has something to land on. * PM-7324 - Registration start - receive marketing materials should never be required. * PM-7324 - Add finish signup route + required translations to desktop & browser. * PM-7324 - AnonLayoutWrapperComponent - Resolve issues where navigating to a sibling anonymous route wouldn't update the AnonLayoutWrapperData. * PM-7324 - Remove unnecessary array * PM-7324 - Per PR feedback, improve setReceiveMarketingEmailsByRegion * PM-7324 - Per PR feedback, inject login routes via route data * PM-7324 - Document methods in account api service * PM-7324 - PR feedback - jsdoc tweaks
This commit is contained in:
@@ -27,7 +27,7 @@ export class AcceptFamilySponsorshipComponent extends BaseAcceptComponent {
|
||||
} else {
|
||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
this.router.navigate(["/register"], { queryParams: { email: qParams.email } });
|
||||
this.router.navigate([this.registerRoute], { queryParams: { email: qParams.email } });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<a
|
||||
bitButton
|
||||
buttonType="primary"
|
||||
routerLink="/register"
|
||||
[routerLink]="registerRoute"
|
||||
[queryParams]="{ email: email }"
|
||||
[block]="true"
|
||||
>
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Component } from "@angular/core";
|
||||
import { ActivatedRoute, Params, Router } from "@angular/router";
|
||||
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
|
||||
@@ -28,9 +29,10 @@ export class AcceptEmergencyComponent extends BaseAcceptComponent {
|
||||
i18nService: I18nService,
|
||||
route: ActivatedRoute,
|
||||
authService: AuthService,
|
||||
configService: ConfigService,
|
||||
private emergencyAccessService: EmergencyAccessService,
|
||||
) {
|
||||
super(router, platformUtilsService, i18nService, route, authService);
|
||||
super(router, platformUtilsService, i18nService, route, authService, configService);
|
||||
}
|
||||
|
||||
async authedHandler(qParams: Params): Promise<void> {
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<p class="tw-m-0 tw-text-sm">
|
||||
{{ "newAroundHere" | i18n }}
|
||||
<!--mousedown event is used over click because it prevents the validation from firing -->
|
||||
<a routerLink="/register" (mousedown)="goToRegister()">{{ "createAccount" | i18n }}</a>
|
||||
<a bitLink href="#" (mousedown)="goToRegister()">{{ "createAccount" | i18n }}</a>
|
||||
</p>
|
||||
</ng-container>
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/
|
||||
import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction";
|
||||
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -67,6 +68,7 @@ export class LoginComponent extends BaseLoginComponent implements OnInit {
|
||||
loginEmailService: LoginEmailServiceAbstraction,
|
||||
ssoLoginService: SsoLoginServiceAbstraction,
|
||||
webAuthnLoginService: WebAuthnLoginServiceAbstraction,
|
||||
configService: ConfigService,
|
||||
) {
|
||||
super(
|
||||
devicesApiService,
|
||||
@@ -87,6 +89,7 @@ export class LoginComponent extends BaseLoginComponent implements OnInit {
|
||||
loginEmailService,
|
||||
ssoLoginService,
|
||||
webAuthnLoginService,
|
||||
configService,
|
||||
);
|
||||
this.onSuccessfulLoginNavigate = this.goAfterLogIn;
|
||||
this.showPasswordless = flagEnabled("showPasswordless");
|
||||
@@ -165,11 +168,11 @@ export class LoginComponent extends BaseLoginComponent implements OnInit {
|
||||
const email = this.formGroup.value.email;
|
||||
|
||||
if (email) {
|
||||
await this.router.navigate(["/register"], { queryParams: { email: email } });
|
||||
await this.router.navigate([this.registerRoute], { queryParams: { email: email } });
|
||||
return;
|
||||
}
|
||||
|
||||
await this.router.navigate(["/register"]);
|
||||
await this.router.navigate([this.registerRoute]);
|
||||
}
|
||||
|
||||
protected override async handleMigrateEncryptionKey(result: AuthResult): Promise<boolean> {
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
{{ "logIn" | i18n }}
|
||||
</a>
|
||||
<a
|
||||
routerLink="/register"
|
||||
[routerLink]="registerRoute"
|
||||
[queryParams]="{ email: email }"
|
||||
class="btn btn-primary btn-block ml-2 mt-0"
|
||||
>
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Component } from "@angular/core";
|
||||
import { ActivatedRoute, Params, Router } from "@angular/router";
|
||||
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
|
||||
@@ -23,9 +24,10 @@ export class AcceptOrganizationComponent extends BaseAcceptComponent {
|
||||
i18nService: I18nService,
|
||||
route: ActivatedRoute,
|
||||
authService: AuthService,
|
||||
configService: ConfigService,
|
||||
private acceptOrganizationInviteService: AcceptOrganizationInviteService,
|
||||
) {
|
||||
super(router, platformUtilsService, i18nService, route, authService);
|
||||
super(router, platformUtilsService, i18nService, route, authService, configService);
|
||||
}
|
||||
|
||||
async authedHandler(qParams: Params): Promise<void> {
|
||||
@@ -86,8 +88,26 @@ export class AcceptOrganizationComponent extends BaseAcceptComponent {
|
||||
|
||||
// if SSO is disabled OR if sso is enabled but the SSO login required policy is not enabled
|
||||
// then send user to create account
|
||||
await this.router.navigate(["/register"], {
|
||||
queryParams: { email: invite.email, fromOrgInvite: true },
|
||||
|
||||
// TODO: update logic when email verification flag is removed
|
||||
let queryParams: Params;
|
||||
if (this.registerRoute === "/register") {
|
||||
queryParams = {
|
||||
fromOrgInvite: "true",
|
||||
email: invite.email,
|
||||
};
|
||||
} else if (this.registerRoute === "/signup") {
|
||||
// We have to override the base component route b/c it is correct for other components
|
||||
// that extend the base accept comp. We don't need users to complete email verification
|
||||
// if they are coming directly from an emailed org invite.
|
||||
this.registerRoute = "/finish-signup";
|
||||
queryParams = {
|
||||
email: invite.email,
|
||||
};
|
||||
}
|
||||
|
||||
await this.router.navigate([this.registerRoute], {
|
||||
queryParams: queryParams,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import { first, switchMap, takeUntil } from "rxjs/operators";
|
||||
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
|
||||
@@ -19,6 +21,9 @@ export abstract class BaseAcceptComponent implements OnInit {
|
||||
protected failedShortMessage = "inviteAcceptFailedShort";
|
||||
protected failedMessage = "inviteAcceptFailed";
|
||||
|
||||
// TODO: remove when email verification flag is removed
|
||||
registerRoute = "/register";
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
constructor(
|
||||
@@ -27,12 +32,22 @@ export abstract class BaseAcceptComponent implements OnInit {
|
||||
protected i18nService: I18nService,
|
||||
protected route: ActivatedRoute,
|
||||
protected authService: AuthService,
|
||||
private configService: ConfigService,
|
||||
) {}
|
||||
|
||||
abstract authedHandler(qParams: Params): Promise<void>;
|
||||
abstract unauthedHandler(qParams: Params): Promise<void>;
|
||||
|
||||
ngOnInit() {
|
||||
async ngOnInit() {
|
||||
// TODO: remove when email verification flag is removed
|
||||
const emailVerification = await this.configService.getFeatureFlag(
|
||||
FeatureFlag.EmailVerification,
|
||||
);
|
||||
|
||||
if (emailVerification) {
|
||||
this.registerRoute = "/signup";
|
||||
}
|
||||
|
||||
this.route.queryParams
|
||||
.pipe(
|
||||
first(),
|
||||
|
||||
@@ -9,7 +9,16 @@ import {
|
||||
UnauthGuard,
|
||||
unauthGuardFn,
|
||||
} from "@bitwarden/angular/auth/guards";
|
||||
import { AnonLayoutWrapperComponent, AnonLayoutWrapperData } from "@bitwarden/auth/angular";
|
||||
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";
|
||||
import {
|
||||
AnonLayoutWrapperComponent,
|
||||
AnonLayoutWrapperData,
|
||||
RegistrationFinishComponent,
|
||||
RegistrationStartComponent,
|
||||
RegistrationStartSecondaryComponent,
|
||||
RegistrationStartSecondaryComponentData,
|
||||
} from "@bitwarden/auth/angular";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
|
||||
import { flagEnabled, Flags } from "../utils/flags";
|
||||
|
||||
@@ -175,6 +184,41 @@ const routes: Routes = [
|
||||
path: "",
|
||||
component: AnonLayoutWrapperComponent,
|
||||
children: [
|
||||
{
|
||||
path: "signup",
|
||||
canActivate: [canAccessFeature(FeatureFlag.EmailVerification), unauthGuardFn()],
|
||||
data: { pageTitle: "createAccount", titleId: "createAccount" } satisfies DataProperties &
|
||||
AnonLayoutWrapperData,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
component: RegistrationStartComponent,
|
||||
},
|
||||
{
|
||||
path: "",
|
||||
component: RegistrationStartSecondaryComponent,
|
||||
outlet: "secondary",
|
||||
data: {
|
||||
loginRoute: "/login",
|
||||
} satisfies RegistrationStartSecondaryComponentData,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "finish-signup",
|
||||
canActivate: [canAccessFeature(FeatureFlag.EmailVerification), unauthGuardFn()],
|
||||
data: {
|
||||
pageTitle: "setAStrongPassword",
|
||||
pageSubtitle: "finishCreatingYourAccountBySettingAPassword",
|
||||
titleId: "setAStrongPassword",
|
||||
} satisfies DataProperties & AnonLayoutWrapperData,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
component: RegistrationFinishComponent,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "sso",
|
||||
canActivate: [unauthGuardFn()],
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
>Bitwarden Send</a
|
||||
>
|
||||
{{ "sendAccessTaglineOr" | i18n }}
|
||||
<a bitLink routerLink="/register" target="_blank" rel="noreferrer">{{
|
||||
<a bitLink [routerLink]="registerRoute" target="_blank" rel="noreferrer">{{
|
||||
"sendAccessTaglineSignUp" | i18n
|
||||
}}</a>
|
||||
{{ "sendAccessTaglineTryToday" | i18n }}
|
||||
|
||||
@@ -2,7 +2,9 @@ import { Component, OnInit } from "@angular/core";
|
||||
import { FormBuilder } from "@angular/forms";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -54,6 +56,9 @@ export class AccessComponent implements OnInit {
|
||||
|
||||
protected formGroup = this.formBuilder.group({});
|
||||
|
||||
// TODO: remove when email verification flag is removed
|
||||
registerRoute = "/register";
|
||||
|
||||
private id: string;
|
||||
private key: string;
|
||||
|
||||
@@ -64,6 +69,7 @@ export class AccessComponent implements OnInit {
|
||||
private sendApiService: SendApiService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private configService: ConfigService,
|
||||
protected formBuilder: FormBuilder,
|
||||
) {}
|
||||
|
||||
@@ -81,7 +87,16 @@ export class AccessComponent implements OnInit {
|
||||
return this.send.creatorIdentifier;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
async ngOnInit() {
|
||||
// TODO: remove when email verification flag is removed
|
||||
const emailVerification = await this.configService.getFeatureFlag(
|
||||
FeatureFlag.EmailVerification,
|
||||
);
|
||||
|
||||
if (emailVerification) {
|
||||
this.registerRoute = "/signup";
|
||||
}
|
||||
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
||||
this.route.params.subscribe(async (params) => {
|
||||
this.id = params.sendId;
|
||||
|
||||
@@ -713,6 +713,12 @@
|
||||
"createAccount": {
|
||||
"message": "Create account"
|
||||
},
|
||||
"setAStrongPassword": {
|
||||
"message": "Set a strong password"
|
||||
},
|
||||
"finishCreatingYourAccountBySettingAPassword": {
|
||||
"message": "Finish creating your account by setting a password"
|
||||
},
|
||||
"newAroundHere": {
|
||||
"message": "New around here?"
|
||||
},
|
||||
@@ -3724,6 +3730,21 @@
|
||||
"nothingSelected": {
|
||||
"message": "You have not selected anything."
|
||||
},
|
||||
"receiveMarketingEmails": {
|
||||
"message": "Get emails from Bitwarden for announcements, advice, and research opportunities."
|
||||
},
|
||||
"unsubscribe": {
|
||||
"message": "Unsubscribe"
|
||||
},
|
||||
"atAnyTime": {
|
||||
"message": "at any time."
|
||||
},
|
||||
"byContinuingYouAgreeToThe": {
|
||||
"message": "By continuing, you agree to the"
|
||||
},
|
||||
"and": {
|
||||
"message": "and"
|
||||
},
|
||||
"acceptPolicies": {
|
||||
"message": "By checking this box you agree to the following:"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user