1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 00:33:44 +00:00

WIP remove validated email& display extension back button

This commit is contained in:
Alec Rippberger
2024-10-18 17:07:34 -05:00
parent 493fbc0f32
commit 628acf0c16
7 changed files with 45 additions and 18 deletions

View File

@@ -10,6 +10,7 @@ import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legac
import { flagEnabled } from "../../../platform/flags"; import { flagEnabled } from "../../../platform/flags";
import { BrowserPlatformUtilsService } from "../../../platform/services/platform-utils/browser-platform-utils.service"; import { BrowserPlatformUtilsService } from "../../../platform/services/platform-utils/browser-platform-utils.service";
import { ExtensionAnonLayoutWrapperDataService } from "../extension-anon-layout-wrapper/extension-anon-layout-wrapper-data.service";
import { ExtensionLoginComponentService } from "./extension-login-component.service"; import { ExtensionLoginComponentService } from "./extension-login-component.service";
@@ -24,14 +25,14 @@ describe("ExtensionLoginComponentService", () => {
let passwordGenerationService: MockProxy<PasswordGenerationServiceAbstraction>; let passwordGenerationService: MockProxy<PasswordGenerationServiceAbstraction>;
let platformUtilsService: MockProxy<BrowserPlatformUtilsService>; let platformUtilsService: MockProxy<BrowserPlatformUtilsService>;
let ssoLoginService: MockProxy<SsoLoginServiceAbstraction>; let ssoLoginService: MockProxy<SsoLoginServiceAbstraction>;
let extensionAnonLayoutWrapperDataService: MockProxy<ExtensionAnonLayoutWrapperDataService>;
beforeEach(() => { beforeEach(() => {
cryptoFunctionService = mock<CryptoFunctionService>(); cryptoFunctionService = mock<CryptoFunctionService>();
environmentService = mock<EnvironmentService>(); environmentService = mock<EnvironmentService>();
passwordGenerationService = mock<PasswordGenerationServiceAbstraction>(); passwordGenerationService = mock<PasswordGenerationServiceAbstraction>();
platformUtilsService = mock<BrowserPlatformUtilsService>(); platformUtilsService = mock<BrowserPlatformUtilsService>();
ssoLoginService = mock<SsoLoginServiceAbstraction>(); ssoLoginService = mock<SsoLoginServiceAbstraction>();
extensionAnonLayoutWrapperDataService = mock<ExtensionAnonLayoutWrapperDataService>();
TestBed.configureTestingModule({ TestBed.configureTestingModule({
providers: [ providers: [
{ {
@@ -43,6 +44,7 @@ describe("ExtensionLoginComponentService", () => {
passwordGenerationService, passwordGenerationService,
platformUtilsService, platformUtilsService,
ssoLoginService, ssoLoginService,
extensionAnonLayoutWrapperDataService,
), ),
}, },
{ provide: DefaultLoginComponentService, useExisting: ExtensionLoginComponentService }, { provide: DefaultLoginComponentService, useExisting: ExtensionLoginComponentService },

View File

@@ -8,6 +8,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
import { flagEnabled } from "../../../platform/flags"; import { flagEnabled } from "../../../platform/flags";
import { ExtensionAnonLayoutWrapperDataService } from "../extension-anon-layout-wrapper/extension-anon-layout-wrapper-data.service";
@Injectable() @Injectable()
export class ExtensionLoginComponentService export class ExtensionLoginComponentService
@@ -20,6 +21,7 @@ export class ExtensionLoginComponentService
passwordGenerationService: PasswordGenerationServiceAbstraction, passwordGenerationService: PasswordGenerationServiceAbstraction,
platformUtilsService: PlatformUtilsService, platformUtilsService: PlatformUtilsService,
ssoLoginService: SsoLoginServiceAbstraction, ssoLoginService: SsoLoginServiceAbstraction,
private extensionAnonLayoutWrapperDataService: ExtensionAnonLayoutWrapperDataService,
) { ) {
super( super(
cryptoFunctionService, cryptoFunctionService,
@@ -34,4 +36,8 @@ export class ExtensionLoginComponentService
isLoginViaAuthRequestSupported(): boolean { isLoginViaAuthRequestSupported(): boolean {
return flagEnabled("showPasswordless"); return flagEnabled("showPasswordless");
} }
showBackButton(): void {
this.extensionAnonLayoutWrapperDataService.setAnonLayoutWrapperData({ showBackButton: true });
}
} }

View File

@@ -602,6 +602,7 @@ const safeProviders: SafeProvider[] = [
PasswordGenerationServiceAbstraction, PasswordGenerationServiceAbstraction,
PlatformUtilsServiceAbstraction, PlatformUtilsServiceAbstraction,
SsoLoginServiceAbstraction, SsoLoginServiceAbstraction,
ExtensionAnonLayoutWrapperDataService,
], ],
}), }),
safeProvider({ safeProvider({
@@ -619,6 +620,11 @@ const safeProviders: SafeProvider[] = [
useClass: LoginEmailService, useClass: LoginEmailService,
deps: [AccountService, AuthService, StateProvider], deps: [AccountService, AuthService, StateProvider],
}), }),
safeProvider({
provide: ExtensionAnonLayoutWrapperDataService,
useClass: ExtensionAnonLayoutWrapperDataService,
deps: [],
}),
]; ];
@NgModule({ @NgModule({

View File

@@ -89,4 +89,11 @@ export class DefaultLoginComponentService implements LoginComponentService {
encodeURIComponent(email), encodeURIComponent(email),
); );
} }
/**
* No-op implementation of showBackButton
*/
showBackButton(): void {
return;
}
} }

View File

@@ -38,4 +38,9 @@ export abstract class LoginComponentService {
* - Used by: Browser, Desktop * - Used by: Browser, Desktop
*/ */
launchSsoBrowserWindow: (email: string, clientId: "browser" | "desktop") => Promise<void>; launchSsoBrowserWindow: (email: string, clientId: "browser" | "desktop") => Promise<void>;
/**
* Shows the back button.
*/
showBackButton: () => void;
} }

View File

@@ -11,7 +11,7 @@
--> -->
<form [bitSubmit]="submit" [formGroup]="formGroup"> <form [bitSubmit]="submit" [formGroup]="formGroup">
<ng-container *ngIf="uiState === LoginUiState.EMAIL_ENTRY"> <ng-container *ngIf="loginUiState === LoginUiState.EMAIL_ENTRY">
<!-- Email Address input --> <!-- Email Address input -->
<bit-form-field class="!tw-mb-4"> <bit-form-field class="!tw-mb-4">
<bit-label>{{ "emailAddress" | i18n }}</bit-label> <bit-label>{{ "emailAddress" | i18n }}</bit-label>
@@ -84,7 +84,7 @@
</div> </div>
</ng-container> </ng-container>
<ng-container *ngIf="uiState === LoginUiState.MASTER_PASSWORD_ENTRY"> <ng-container *ngIf="loginUiState === LoginUiState.MASTER_PASSWORD_ENTRY">
<!-- Master Password input --> <!-- Master Password input -->
<bit-form-field class="!tw-mb-1"> <bit-form-field class="!tw-mb-1">
<bit-label>{{ "masterPass" | i18n }}</bit-label> <bit-label>{{ "masterPass" | i18n }}</bit-label>
@@ -132,13 +132,13 @@
</ng-container> </ng-container>
<!-- Back button --> <!-- Back button -->
<ng-container *ngIf="showBackButton()"> <ng-container *ngIf="shouldShowBackButton()">
<button <button
type="button" type="button"
bitButton bitButton
block block
buttonType="secondary" buttonType="secondary"
(click)="toggleValidateEmail(false)" (click)="toggleLoginUiState(LoginUiState.EMAIL_ENTRY)"
> >
{{ "back" | i18n }} {{ "back" | i18n }}
</button> </button>

View File

@@ -80,7 +80,7 @@ export class LoginComponent implements OnInit, OnDestroy {
LoginUiState = LoginUiState; LoginUiState = LoginUiState;
registerRoute$ = this.registerRouteService.registerRoute$(); // TODO: remove when email verification flag is removed registerRoute$ = this.registerRouteService.registerRoute$(); // TODO: remove when email verification flag is removed
isKnownDevice = false; isKnownDevice = false;
validatedEmail = false; loginUiState: LoginUiState = LoginUiState.EMAIL_ENTRY;
formGroup = this.formBuilder.group( formGroup = this.formBuilder.group(
{ {
@@ -98,10 +98,6 @@ export class LoginComponent implements OnInit, OnDestroy {
return this.formGroup.controls.email; return this.formGroup.controls.email;
} }
get uiState(): LoginUiState {
return this.validatedEmail ? LoginUiState.MASTER_PASSWORD_ENTRY : LoginUiState.EMAIL_ENTRY;
}
// Web properties // Web properties
enforcedPasswordPolicyOptions: MasterPasswordPolicyOptions; enforcedPasswordPolicyOptions: MasterPasswordPolicyOptions;
policies: Policy[]; policies: Policy[];
@@ -164,7 +160,7 @@ export class LoginComponent implements OnInit, OnDestroy {
submit = async (): Promise<void> => { submit = async (): Promise<void> => {
if (this.clientType === ClientType.Desktop) { if (this.clientType === ClientType.Desktop) {
if (!this.validatedEmail) { if (this.loginUiState !== LoginUiState.MASTER_PASSWORD_ENTRY) {
return; return;
} }
} }
@@ -323,7 +319,7 @@ export class LoginComponent implements OnInit, OnDestroy {
const emailValid = this.formGroup.controls.email.valid; const emailValid = this.formGroup.controls.email.valid;
if (emailValid) { if (emailValid) {
this.toggleValidateEmail(true); this.toggleLoginUiState(LoginUiState.MASTER_PASSWORD_ENTRY);
await this.getLoginWithDevice(this.emailFormControl.value); await this.getLoginWithDevice(this.emailFormControl.value);
this.anonLayoutWrapperDataService.setAnonLayoutWrapperData({ this.anonLayoutWrapperDataService.setAnonLayoutWrapperData({
@@ -334,10 +330,10 @@ export class LoginComponent implements OnInit, OnDestroy {
} }
} }
protected toggleValidateEmail(value: boolean): void { protected toggleLoginUiState(value: LoginUiState): void {
this.validatedEmail = value; this.loginUiState = value;
if (!this.validatedEmail) { if (this.loginUiState !== LoginUiState.MASTER_PASSWORD_ENTRY) {
// Reset master password only when going from validated to not validated so that autofill can work properly // Reset master password only when going from validated to not validated so that autofill can work properly
this.formGroup.controls.masterPassword.reset(); this.formGroup.controls.masterPassword.reset();
} else { } else {
@@ -352,6 +348,8 @@ export class LoginComponent implements OnInit, OnDestroy {
this.masterPasswordInputRef?.nativeElement?.focus(); this.masterPasswordInputRef?.nativeElement?.focus();
}); });
} }
this.loginComponentService.showBackButton();
} }
} }
@@ -551,7 +549,10 @@ export class LoginComponent implements OnInit, OnDestroy {
* Helper function to determine if the back button should be shown. * Helper function to determine if the back button should be shown.
* @returns true if the back button should be shown. * @returns true if the back button should be shown.
*/ */
protected showBackButton(): boolean { protected shouldShowBackButton(): boolean {
return this.validatedEmail && this.clientType !== ClientType.Browser; return (
this.loginUiState === LoginUiState.MASTER_PASSWORD_ENTRY &&
this.clientType !== ClientType.Browser
);
} }
} }