Skip to content

Commit

Permalink
feat(auth): [PM-9693] Refresh LoginDecryptionOptionsComponent (#11782)
Browse files Browse the repository at this point in the history
Creates a refreshed and consolidated `LoginDecryptionOptionsComponent` for use on all visual clients, which will be used when the `UnauthenticatedExtensionUIRefresh` feature flag is on.
  • Loading branch information
rr-bw authored Nov 21, 2024
1 parent 228817b commit 9f99454
Show file tree
Hide file tree
Showing 31 changed files with 742 additions and 38 deletions.
15 changes: 15 additions & 0 deletions apps/browser/src/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3287,9 +3287,18 @@
"opensInANewWindow": {
"message": "Opens in a new window"
},
"rememberThisDeviceToMakeFutureLoginsSeamless": {
"message": "Remember this device to make future logins seamless"
},
"deviceApprovalRequired": {
"message": "Device approval required. Select an approval option below:"
},
"deviceApprovalRequiredV2": {
"message": "Device approval required"
},
"selectAnApprovalOptionBelow": {
"message": "Select an approval option below"
},
"rememberThisDevice": {
"message": "Remember this device"
},
Expand Down Expand Up @@ -3363,6 +3372,9 @@
"userEmailMissing": {
"message": "User email missing"
},
"activeUserEmailNotFoundLoggingYouOut": {
"message": "Active user email not found. Logging you out."
},
"deviceTrusted": {
"message": "Device trusted"
},
Expand Down Expand Up @@ -3799,6 +3811,9 @@
"accessing": {
"message": "Accessing"
},
"loggedInExclamation": {
"message": "Logged in!"
},
"passkeyNotCopied": {
"message": "Passkey will not be copied"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Router } from "@angular/router";
import { MockProxy, mock } from "jest-mock-extended";
import { BehaviorSubject } from "rxjs";

import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";

import { postLogoutMessageListener$ } from "../utils/post-logout-message-listener";

import { ExtensionLoginDecryptionOptionsService } from "./extension-login-decryption-options.service";

// Mock the module providing postLogoutMessageListener$
jest.mock("../utils/post-logout-message-listener", () => {
return {
postLogoutMessageListener$: new BehaviorSubject<string>(""), // Replace with mock subject
};
});

describe("ExtensionLoginDecryptionOptionsService", () => {
let service: ExtensionLoginDecryptionOptionsService;

let messagingService: MockProxy<MessagingService>;
let router: MockProxy<Router>;
let postLogoutMessageSubject: BehaviorSubject<string>;

beforeEach(() => {
messagingService = mock<MessagingService>();
router = mock<Router>();

// Cast postLogoutMessageListener$ to BehaviorSubject for dynamic control
postLogoutMessageSubject = postLogoutMessageListener$ as BehaviorSubject<string>;

service = new ExtensionLoginDecryptionOptionsService(messagingService, router);
});

it("should instantiate the service", () => {
expect(service).not.toBeFalsy();
});

describe("logOut()", () => {
it("should send a logout message", async () => {
postLogoutMessageSubject.next("switchAccountFinish");

await service.logOut();

expect(messagingService.send).toHaveBeenCalledWith("logout");
});

it("should navigate to root on 'switchAccountFinish'", async () => {
postLogoutMessageSubject.next("switchAccountFinish");

await service.logOut();

expect(router.navigate).toHaveBeenCalledWith(["/"]);
});

it("should not navigate for 'doneLoggingOut'", async () => {
postLogoutMessageSubject.next("doneLoggingOut");

await service.logOut();

expect(router.navigate).not.toHaveBeenCalled();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Router } from "@angular/router";
import { firstValueFrom } from "rxjs";

import {
DefaultLoginDecryptionOptionsService,
LoginDecryptionOptionsService,
} from "@bitwarden/auth/angular";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";

import { postLogoutMessageListener$ } from "../utils/post-logout-message-listener";

export class ExtensionLoginDecryptionOptionsService
extends DefaultLoginDecryptionOptionsService
implements LoginDecryptionOptionsService
{
constructor(
protected messagingService: MessagingService,
private router: Router,
) {
super(messagingService);
}

override async logOut(): Promise<void> {
// start listening for "switchAccountFinish" or "doneLoggingOut"
const messagePromise = firstValueFrom(postLogoutMessageListener$);

super.logOut();

// wait for messages
const command = await messagePromise;

// doneLoggingOut already has a message handler that will navigate us
if (command === "switchAccountFinish") {
await this.router.navigate(["/"]);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { Component } from "@angular/core";
import { firstValueFrom } from "rxjs";

import { BaseLoginDecryptionOptionsComponent } from "@bitwarden/angular/auth/components/base-login-decryption-options.component";
import { BaseLoginDecryptionOptionsComponentV1 } from "@bitwarden/angular/auth/components/base-login-decryption-options-v1.component";

import { postLogoutMessageListener$ } from "../utils/post-logout-message-listener";

@Component({
selector: "browser-login-decryption-options",
templateUrl: "login-decryption-options.component.html",
templateUrl: "login-decryption-options-v1.component.html",
})
export class LoginDecryptionOptionsComponent extends BaseLoginDecryptionOptionsComponent {
export class LoginDecryptionOptionsComponentV1 extends BaseLoginDecryptionOptionsComponentV1 {
override async createUser(): Promise<void> {
try {
await super.createUser();
Expand Down
28 changes: 20 additions & 8 deletions apps/browser/src/popup/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import { extensionRefreshSwap } from "@bitwarden/angular/utils/extension-refresh
import {
AnonLayoutWrapperComponent,
AnonLayoutWrapperData,
DevicesIcon,
LoginComponent,
LoginSecondaryContentComponent,
LockIcon,
Expand All @@ -37,6 +36,8 @@ import {
SetPasswordJitComponent,
UserLockIcon,
VaultIcon,
LoginDecryptionOptionsComponent,
DevicesIcon,
} from "@bitwarden/auth/angular";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";

Expand All @@ -51,7 +52,7 @@ import {
import { HintComponent } from "../auth/popup/hint.component";
import { HomeComponent } from "../auth/popup/home.component";
import { LockComponent } from "../auth/popup/lock.component";
import { LoginDecryptionOptionsComponent } from "../auth/popup/login-decryption-options/login-decryption-options.component";
import { LoginDecryptionOptionsComponentV1 } from "../auth/popup/login-decryption-options/login-decryption-options-v1.component";
import { LoginComponentV1 } from "../auth/popup/login-v1.component";
import { LoginViaAuthRequestComponentV1 } from "../auth/popup/login-via-auth-request-v1.component";
import { RegisterComponent } from "../auth/popup/register.component";
Expand Down Expand Up @@ -206,12 +207,6 @@ const routes: Routes = [
canActivate: [unauthGuardFn(unauthRouteOverrides)],
data: { state: "2fa-options" } satisfies RouteDataProperties,
},
{
path: "login-initiated",
component: LoginDecryptionOptionsComponent,
canActivate: [tdeDecryptionRequiredGuard()],
data: { state: "login-initiated" } satisfies RouteDataProperties,
},
{
path: "sso",
component: SsoComponent,
Expand Down Expand Up @@ -534,6 +529,23 @@ const routes: Routes = [
],
},
),
...unauthUiRefreshSwap(
LoginDecryptionOptionsComponentV1,
ExtensionAnonLayoutWrapperComponent,
{
path: "login-initiated",
canActivate: [tdeDecryptionRequiredGuard()],
data: { state: "login-initiated" } satisfies RouteDataProperties,
},
{
path: "login-initiated",
canActivate: [tdeDecryptionRequiredGuard()],
data: {
pageIcon: DevicesIcon,
},
children: [{ path: "", component: LoginDecryptionOptionsComponent }],
},
),
{
path: "",
component: ExtensionAnonLayoutWrapperComponent,
Expand Down
4 changes: 2 additions & 2 deletions apps/browser/src/popup/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { ExtensionAnonLayoutWrapperComponent } from "../auth/popup/extension-ano
import { HintComponent } from "../auth/popup/hint.component";
import { HomeComponent } from "../auth/popup/home.component";
import { LockComponent } from "../auth/popup/lock.component";
import { LoginDecryptionOptionsComponent } from "../auth/popup/login-decryption-options/login-decryption-options.component";
import { LoginDecryptionOptionsComponentV1 } from "../auth/popup/login-decryption-options/login-decryption-options-v1.component";
import { LoginComponentV1 } from "../auth/popup/login-v1.component";
import { LoginViaAuthRequestComponentV1 } from "../auth/popup/login-via-auth-request-v1.component";
import { RegisterComponent } from "../auth/popup/register.component";
Expand Down Expand Up @@ -161,7 +161,7 @@ import "../platform/popup/locales";
LockComponent,
LoginViaAuthRequestComponentV1,
LoginComponentV1,
LoginDecryptionOptionsComponent,
LoginDecryptionOptionsComponentV1,
NotificationsSettingsV1Component,
AppearanceComponent,
GeneratorComponent,
Expand Down
8 changes: 8 additions & 0 deletions apps/browser/src/popup/services/services.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { APP_INITIALIZER, NgModule, NgZone } from "@angular/core";
import { Router } from "@angular/router";
import { Subject, merge, of } from "rxjs";

import { CollectionService } from "@bitwarden/admin-console/common";
Expand All @@ -22,6 +23,7 @@ import {
AnonLayoutWrapperDataService,
LoginComponentService,
LockComponentService,
LoginDecryptionOptionsService,
} from "@bitwarden/auth/angular";
import { LockService, LoginEmailService, PinServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
Expand Down Expand Up @@ -115,6 +117,7 @@ import { PasswordRepromptService } from "@bitwarden/vault";
import { ForegroundLockService } from "../../auth/popup/accounts/foreground-lock.service";
import { ExtensionAnonLayoutWrapperDataService } from "../../auth/popup/extension-anon-layout-wrapper/extension-anon-layout-wrapper-data.service";
import { ExtensionLoginComponentService } from "../../auth/popup/login/extension-login-component.service";
import { ExtensionLoginDecryptionOptionsService } from "../../auth/popup/login-decryption-options/extension-login-decryption-options.service";
import { AutofillService as AutofillServiceAbstraction } from "../../autofill/services/abstractions/autofill.service";
import AutofillService from "../../autofill/services/autofill.service";
import { InlineMenuFieldQualificationService } from "../../autofill/services/inline-menu-field-qualification.service";
Expand Down Expand Up @@ -591,6 +594,11 @@ const safeProviders: SafeProvider[] = [
useExisting: PopupCompactModeService,
deps: [],
}),
safeProvider({
provide: LoginDecryptionOptionsService,
useClass: ExtensionLoginDecryptionOptionsService,
deps: [MessagingServiceAbstraction, Router],
}),
];

@NgModule({
Expand Down
26 changes: 19 additions & 7 deletions apps/desktop/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import { extensionRefreshRedirect } from "@bitwarden/angular/utils/extension-ref
import {
AnonLayoutWrapperComponent,
AnonLayoutWrapperData,
DevicesIcon,
LoginComponent,
LoginSecondaryContentComponent,
LockIcon,
Expand All @@ -34,6 +33,8 @@ import {
SetPasswordJitComponent,
UserLockIcon,
VaultIcon,
LoginDecryptionOptionsComponent,
DevicesIcon,
} from "@bitwarden/auth/angular";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";

Expand All @@ -42,7 +43,7 @@ import { AccessibilityCookieComponent } from "../auth/accessibility-cookie.compo
import { maxAccountsGuardFn } from "../auth/guards/max-accounts.guard";
import { HintComponent } from "../auth/hint.component";
import { LockComponent } from "../auth/lock.component";
import { LoginDecryptionOptionsComponent } from "../auth/login/login-decryption-options/login-decryption-options.component";
import { LoginDecryptionOptionsComponentV1 } from "../auth/login/login-decryption-options/login-decryption-options-v1.component";
import { LoginComponentV1 } from "../auth/login/login-v1.component";
import { LoginViaAuthRequestComponentV1 } from "../auth/login/login-via-auth-request-v1.component";
import { RegisterComponent } from "../auth/register.component";
Expand Down Expand Up @@ -95,11 +96,6 @@ const routes: Routes = [
],
},
),
{
path: "login-initiated",
component: LoginDecryptionOptionsComponent,
canActivate: [tdeDecryptionRequiredGuard()],
},
{ path: "register", component: RegisterComponent },
{
path: "vault",
Expand Down Expand Up @@ -241,6 +237,22 @@ const routes: Routes = [
],
},
),
...unauthUiRefreshSwap(
LoginDecryptionOptionsComponentV1,
AnonLayoutWrapperComponent,
{
path: "login-initiated",
canActivate: [tdeDecryptionRequiredGuard()],
},
{
path: "login-initiated",
canActivate: [tdeDecryptionRequiredGuard()],
data: {
pageIcon: DevicesIcon,
},
children: [{ path: "", component: LoginDecryptionOptionsComponent }],
},
),
{
path: "",
component: AnonLayoutWrapperComponent,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Component } from "@angular/core";

import { BaseLoginDecryptionOptionsComponent } from "@bitwarden/angular/auth/components/base-login-decryption-options.component";
import { BaseLoginDecryptionOptionsComponentV1 } from "@bitwarden/angular/auth/components/base-login-decryption-options-v1.component";

@Component({
selector: "desktop-login-decryption-options",
templateUrl: "login-decryption-options.component.html",
templateUrl: "login-decryption-options-v1.component.html",
})
export class LoginDecryptionOptionsComponent extends BaseLoginDecryptionOptionsComponent {
export class LoginDecryptionOptionsComponentV1 extends BaseLoginDecryptionOptionsComponentV1 {
override async createUser(): Promise<void> {
try {
await super.createUser();
Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/auth/login/login.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { EnvironmentSelectorComponent } from "@bitwarden/angular/auth/components

import { SharedModule } from "../../app/shared/shared.module";

import { LoginDecryptionOptionsComponent } from "./login-decryption-options/login-decryption-options.component";
import { LoginDecryptionOptionsComponentV1 } from "./login-decryption-options/login-decryption-options-v1.component";
import { LoginComponentV1 } from "./login-v1.component";
import { LoginViaAuthRequestComponentV1 } from "./login-via-auth-request-v1.component";

Expand All @@ -15,7 +15,7 @@ import { LoginViaAuthRequestComponentV1 } from "./login-via-auth-request-v1.comp
LoginComponentV1,
LoginViaAuthRequestComponentV1,
EnvironmentSelectorComponent,
LoginDecryptionOptionsComponent,
LoginDecryptionOptionsComponentV1,
],
exports: [LoginComponentV1, LoginViaAuthRequestComponentV1],
})
Expand Down
Loading

0 comments on commit 9f99454

Please sign in to comment.