mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 13:23:34 +00:00
feat(new-device-verification-screen): (Auth) [PM-17489] Back Button on New Device Verification Screen (#16599)
On Web and Desktop, show back button on `NewDeviceVerificationComponent` (route `/device-verification`). Do not show it on Extension, because Extension already has a back button in the header.
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
import { ExtensionNewDeviceVerificationComponentService } from "./extension-new-device-verification-component.service";
|
||||
|
||||
describe("ExtensionNewDeviceVerificationComponentService", () => {
|
||||
let sut: ExtensionNewDeviceVerificationComponentService;
|
||||
|
||||
beforeEach(() => {
|
||||
sut = new ExtensionNewDeviceVerificationComponentService();
|
||||
});
|
||||
|
||||
it("should instantiate the service", () => {
|
||||
expect(sut).not.toBeFalsy();
|
||||
});
|
||||
|
||||
describe("showBackButton()", () => {
|
||||
it("should return false", () => {
|
||||
const result = sut.showBackButton();
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
import {
|
||||
DefaultNewDeviceVerificationComponentService,
|
||||
NewDeviceVerificationComponentService,
|
||||
} from "@bitwarden/auth/angular";
|
||||
|
||||
export class ExtensionNewDeviceVerificationComponentService
|
||||
extends DefaultNewDeviceVerificationComponentService
|
||||
implements NewDeviceVerificationComponentService
|
||||
{
|
||||
showBackButton() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
TwoFactorAuthDuoComponentService,
|
||||
TwoFactorAuthWebAuthnComponentService,
|
||||
SsoComponentService,
|
||||
NewDeviceVerificationComponentService,
|
||||
} from "@bitwarden/auth/angular";
|
||||
import {
|
||||
LockService,
|
||||
@@ -36,6 +37,7 @@ import {
|
||||
SsoUrlService,
|
||||
LogoutService,
|
||||
} from "@bitwarden/auth/common";
|
||||
import { ExtensionNewDeviceVerificationComponentService } from "@bitwarden/browser/auth/services/new-device-verification/extension-new-device-verification-component.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
@@ -710,6 +712,11 @@ const safeProviders: SafeProvider[] = [
|
||||
useClass: DefaultCipherArchiveService,
|
||||
deps: [CipherService, ApiService, BillingAccountProfileStateService, ConfigService],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: NewDeviceVerificationComponentService,
|
||||
useClass: ExtensionNewDeviceVerificationComponentService,
|
||||
deps: [],
|
||||
}),
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
||||
@@ -20,11 +20,13 @@ import {
|
||||
import {
|
||||
DefaultLoginComponentService,
|
||||
DefaultLoginDecryptionOptionsService,
|
||||
DefaultNewDeviceVerificationComponentService,
|
||||
DefaultRegistrationFinishService,
|
||||
DefaultTwoFactorAuthComponentService,
|
||||
DefaultTwoFactorAuthWebAuthnComponentService,
|
||||
LoginComponentService,
|
||||
LoginDecryptionOptionsService,
|
||||
NewDeviceVerificationComponentService,
|
||||
RegistrationFinishService as RegistrationFinishServiceAbstraction,
|
||||
TwoFactorAuthComponentService,
|
||||
TwoFactorAuthWebAuthnComponentService,
|
||||
@@ -1646,6 +1648,11 @@ const safeProviders: SafeProvider[] = [
|
||||
ConfigService,
|
||||
],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: NewDeviceVerificationComponentService,
|
||||
useClass: DefaultNewDeviceVerificationComponentService,
|
||||
deps: [],
|
||||
}),
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
||||
@@ -59,6 +59,8 @@ export * from "./two-factor-auth";
|
||||
|
||||
// device verification
|
||||
export * from "./new-device-verification/new-device-verification.component";
|
||||
export * from "./new-device-verification/new-device-verification-component.service";
|
||||
export * from "./new-device-verification/default-new-device-verification-component.service";
|
||||
|
||||
// validators
|
||||
export * from "./validators/compare-inputs.validator";
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { DefaultNewDeviceVerificationComponentService } from "./default-new-device-verification-component.service";
|
||||
|
||||
describe("DefaultNewDeviceVerificationComponentService", () => {
|
||||
let sut: DefaultNewDeviceVerificationComponentService;
|
||||
|
||||
beforeEach(() => {
|
||||
sut = new DefaultNewDeviceVerificationComponentService();
|
||||
});
|
||||
|
||||
it("should instantiate the service", () => {
|
||||
expect(sut).not.toBeFalsy();
|
||||
});
|
||||
|
||||
describe("showBackButton()", () => {
|
||||
it("should return true", () => {
|
||||
const result = sut.showBackButton();
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
import { NewDeviceVerificationComponentService } from "./new-device-verification-component.service";
|
||||
|
||||
export class DefaultNewDeviceVerificationComponentService
|
||||
implements NewDeviceVerificationComponentService
|
||||
{
|
||||
showBackButton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export abstract class NewDeviceVerificationComponentService {
|
||||
/**
|
||||
* States whether component should show a back button. Can be overridden by client-specific component services.
|
||||
* - Default = `true`
|
||||
* - Extension = `false` (because Extension shows a back button in the header instead)
|
||||
*/
|
||||
abstract showBackButton: () => boolean;
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
{{ "resendCode" | i18n }}
|
||||
</button>
|
||||
|
||||
<div class="tw-flex tw-mt-4">
|
||||
<div class="tw-grid tw-gap-3 tw-mt-4">
|
||||
<button
|
||||
bitButton
|
||||
bitFormButton
|
||||
@@ -33,5 +33,13 @@
|
||||
>
|
||||
{{ "continueLoggingIn" | i18n }}
|
||||
</button>
|
||||
|
||||
@if (showBackButton) {
|
||||
<div class="tw-text-center">{{ "or" | i18n }}</div>
|
||||
|
||||
<button type="button" bitButton block buttonType="secondary" (click)="goBack()">
|
||||
{{ "back" | i18n }}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { CommonModule, Location } from "@angular/common";
|
||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
|
||||
import { Router } from "@angular/router";
|
||||
@@ -11,7 +11,6 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
|
||||
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { MasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop.
|
||||
@@ -26,6 +25,8 @@ import {
|
||||
|
||||
import { LoginStrategyServiceAbstraction } from "../../common/abstractions/login-strategy.service";
|
||||
|
||||
import { NewDeviceVerificationComponentService } from "./new-device-verification-component.service";
|
||||
|
||||
/**
|
||||
* Component for verifying a new device via a one-time password (OTP).
|
||||
*/
|
||||
@@ -57,6 +58,7 @@ export class NewDeviceVerificationComponent implements OnInit, OnDestroy {
|
||||
protected disableRequestOTP = false;
|
||||
private destroy$ = new Subject<void>();
|
||||
protected authenticationSessionTimeoutRoute = "/authentication-timeout";
|
||||
protected showBackButton = true;
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
@@ -66,12 +68,15 @@ export class NewDeviceVerificationComponent implements OnInit, OnDestroy {
|
||||
private logService: LogService,
|
||||
private i18nService: I18nService,
|
||||
private loginSuccessHandlerService: LoginSuccessHandlerService,
|
||||
private configService: ConfigService,
|
||||
private accountService: AccountService,
|
||||
private masterPasswordService: MasterPasswordServiceAbstraction,
|
||||
private newDeviceVerificationComponentService: NewDeviceVerificationComponentService,
|
||||
private location: Location,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
this.showBackButton = this.newDeviceVerificationComponentService.showBackButton();
|
||||
|
||||
// Redirect to timeout route if session expires
|
||||
this.loginStrategyService.authenticationSessionTimeout$
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
@@ -179,4 +184,8 @@ export class NewDeviceVerificationComponent implements OnInit, OnDestroy {
|
||||
codeControl.markAsTouched();
|
||||
}
|
||||
};
|
||||
|
||||
protected goBack() {
|
||||
this.location.back();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user