1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 15:53:27 +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:
Jared Snider
2024-06-14 11:40:56 -04:00
committed by GitHub
parent eb96f7dbfb
commit 215bbc2f8e
42 changed files with 584 additions and 88 deletions

View File

@@ -1,5 +1,27 @@
import { RegisterSendVerificationEmailRequest } from "../models/request/registration/register-send-verification-email.request";
import { Verification } from "../types/verification";
export abstract class AccountApiService {
/**
* Deletes an account that has confirmed the operation is authorized
*
* @param verification - authorizes the account deletion operation.
* @returns A promise that resolves when the account is
* successfully deleted.
*/
abstract deleteAccount(verification: Verification): Promise<void>;
/**
* Sends a verification email as part of the registration process.
*
* @param request - The request object containing
* information needed to send the verification email, such as the user's email address.
* @returns A promise that resolves to a string tokencontaining the user's encrypted
* information which must be submitted to complete registration or `null` if
* email verification is enabled (users must get the token by clicking a
* link in the email that will be sent to them).
*/
abstract registerSendVerificationEmail(
request: RegisterSendVerificationEmailRequest,
): Promise<null | string>;
}

View File

@@ -0,0 +1,7 @@
export class RegisterSendVerificationEmailRequest {
constructor(
public email: string,
public name: string,
public receiveMarketingEmails: boolean,
) {}
}

View File

@@ -1,8 +1,13 @@
import { firstValueFrom } from "rxjs";
import { ApiService } from "../../abstractions/api.service";
import { ErrorResponse } from "../../models/response/error.response";
import { EnvironmentService } from "../../platform/abstractions/environment.service";
import { LogService } from "../../platform/abstractions/log.service";
import { AccountApiService } from "../abstractions/account-api.service";
import { InternalAccountService } from "../abstractions/account.service";
import { UserVerificationService } from "../abstractions/user-verification/user-verification.service.abstraction";
import { RegisterSendVerificationEmailRequest } from "../models/request/registration/register-send-verification-email.request";
import { Verification } from "../types/verification";
export class AccountApiServiceImplementation implements AccountApiService {
@@ -11,6 +16,7 @@ export class AccountApiServiceImplementation implements AccountApiService {
private userVerificationService: UserVerificationService,
private logService: LogService,
private accountService: InternalAccountService,
private environmentService: EnvironmentService,
) {}
async deleteAccount(verification: Verification): Promise<void> {
@@ -23,4 +29,33 @@ export class AccountApiServiceImplementation implements AccountApiService {
throw e;
}
}
async registerSendVerificationEmail(
request: RegisterSendVerificationEmailRequest,
): Promise<null | string> {
const env = await firstValueFrom(this.environmentService.environment$);
try {
const response = await this.apiService.send(
"POST",
"/accounts/register/send-verification-email",
request,
false,
true,
env.getIdentityUrl(),
);
return response;
} catch (e: unknown) {
if (e instanceof ErrorResponse) {
if (e.statusCode === 204) {
// No content is a success response.
return null;
}
}
this.logService.error(e);
throw e;
}
}
}

View File

@@ -17,6 +17,7 @@ export enum FeatureFlag {
RestrictProviderAccess = "restrict-provider-access",
UseTreeWalkerApiForPageDetailsCollection = "use-tree-walker-api-for-page-details-collection",
BulkDeviceApproval = "bulk-device-approval",
EmailVerification = "email-verification",
}
export type AllowedFeatureFlagTypes = boolean | number | string;
@@ -44,6 +45,7 @@ export const DefaultFeatureFlagValue = {
[FeatureFlag.RestrictProviderAccess]: FALSE,
[FeatureFlag.UseTreeWalkerApiForPageDetailsCollection]: FALSE,
[FeatureFlag.BulkDeviceApproval]: FALSE,
[FeatureFlag.EmailVerification]: FALSE,
} satisfies Record<FeatureFlag, AllowedFeatureFlagTypes>;
export type DefaultFeatureFlagValueType = typeof DefaultFeatureFlagValue;