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

Auth/PM-9449 - UI Refresh + Client component consolidation into new LockV2 Component (#10451)

* PM-9449 - Init stub of new lock comp

* PM-9449 - (1) Add new lock screen title to all clients (2) Add to temp web routing module config

* PM-9449 - LockV2Comp - Building now with web HTML

* PM-9449 - Libs/Auth LockComp - bring in all desktop ts code; WIP, need to stand up LockCompService to facilitate ipc communication.

* PM-9449 - Create LockComponentService for facilitating client logic; potentially will decompose later.

* PM-9449 - Add extension lock comp service.

* PM-9449 - Libs/auth LockComp - bring in browser extension logic

* PM-9449 - Libs/auth LockComp html start

* PM-9449 - Libs/Auth LockComp - (1) Remove unused dep (2) Update setEmailAsPageSubtitle to work.

* PM-9449 - Add getBiometricsError to lock comp service for extension.

* PM-9449 - LockComp - (1) Save off client type as public comp var (2) Rename biometricLock as biometricLockSet

* PM-9449 - Work on lock comp service getAvailableUnlockOptions

* PM-9449 - WIP libs/auth LockComp

* PM-9449 - (1) Remove default lock comp svc (2) Add web lock comp svc.

* PM-9449 - UnlockOptions - replace incorrect type

* PM-9449 - DesktopLockComponentService -get most of observable based getAvailableUnlockOptions$ logic in place.

* PM-9449 - LockCompSvc - getAvailableUnlockOptions in place for all clients.

* PM-9449 - Add getBiometricsUnlockBtnText to LockCompSvc and put TODO for wiring it up later

* PM-9449 - Lock Comp - Replace all manual bools with unlock options.

* PM-9449 - Desktop Lock Comp Svc - adjust spacing

* PM-9449 - LockCompSvc - remove biometricsEnabled method

* PM-9449 - LockComp - Clean up commented out code

* PM-9449 - LockComp - webVaultHostname --> envHostName

* PM-9449 - Fix lock comp svc deps

* PM-9449 - LockComp - HTML progress

* PM-9449 - LockComp cleanup

* PM-9449 - Web Routing Module - wire up lock vs lockv2 using extension swap

* PM-9449 - Wire up loading state

* PM-9449 - LockComp - start wiring up listenForActiveUnlockOptionChanges logic with reactivity

* PM-9449 - Update desktop & extension lock comp service to use new biometrics service vs platform utils for biometrics information.

* PM-9449 - LockV2 - Swap platform util usage with toast svc

* PM-9449 - LockV2Comp - Bring over user id logic from PM-8933

* PM-9449 - LockV2Comp - Adjust everything to use activeAccount.id.

* PM-9449 - LockV2Comp - Progress on wiring up unlock option reactive stream.

* PM-9449 - LockComp ts - some refactoring and minor progress.

* PM-9449 - LockComp HTML - refactoring based on new idea to keep unlock options as separate as possible.

* PM-9449 - Add PIN translation to web

* PM-9449 - (1) Lock HTML refactor to make as independent verticals as possible (2) Refactor Lock ts (3) LockSvc - replace type with enum.

* PM-9449 - LockV2Comp - remove hardcoded await.

* PM-9449 - LockComp HTML - add todo

* PM-9449 - Web - Routing module - cleanup commented out stuff

* PM-9449 - LockV2Comp - Wire up biometrics + mild refactor.

* PM-9449 - Desktop - Wire up lockV2 redirection

* PM-9449 - LockV2 - Desktop - don't focus until unlock opts defined.

* PM-9449 - Fix accidental check in

* PM-9449 - LockV2 - loading state depends on unlock opts

* PM-9449 - LockV2 comp - remove unnecessary hr

* PM-9449 - Migrate  "yourVaultIsLockedV2" translation to desktop & browser.

* PM-9449 - LockV2 - Layout tweaks for biometrics

* PM-9449 - LockV2 - Biometric btn text

* PM-9449 - LockV2 - Wire up biometrics loading / disable state + remove unnecessary conditions around biometricsUnlockBtnText

* PM-9449 - DesktopLockSvc - Per discussion with Bernd, remove interval polling and just check once for biometric support and availability.

* PM-9449 - AuthGuard - Add todo to remove promptBiometric

* PM-9449 - LockV2 - Refactor primary and desktop init logic + misc clean up

* PM-9449 - LockV2 - Reorder init methods

* PM-9449 - LockV2 - Per discussion with Product, deprecate windows biometric settings update warning

* PM-9449 - Add TODO per discussion with Justin and remove TODO

* PM-9449 - LockV2 - Restore hide password on desktop window hidden functionality.

* PM-9449 - Clean up accomplished todo

* PM-9449 - LockV2 - Refactor func name.

* PM-9449 - LockV2 Comp - (1) TODO cleanup (2) Add browser logic to handleBiometricsUnlockEnabled

* PM-9449 - LockCompSvc changes - (1) Observability for isFido2Session (2) Adjust errors and returns per discussion with Justin

* PM-9449 - Per product, no longer need to support special fido2 case on extension.

* PM-9449 - LockCompSvc - add getPreviousUrl support

* PM-9449 - LockV2 - Continued ts cleanup

* PM-9449 - LockV2Comp - clean up unused props

* PM-9449 - LockV2Comp - Rename response to masterPasswordVerificationResponse

* PM-9449 - LockV2 - Remove unused formPromise prop

* PM-9449 - Add missing translations + update desktop to showReadonlyHostName

* PM-9449 - LockV2 - cleanup TODO

* PM-9449 - LockV2 - more cleanup

* PM-9449 - Desktop Routing Module - only allow LockV2 access if extension refresh flag is enabled.

* PM-9449 - Extension - AppRoutingModule - Add extension redirect + new lockV2 route.

* PM-9449 - Extension - AppRoutingModule - Add lockV2 to the ExtensionAnonLayoutWrapperComponent intead of the regular one.

* PM-9449 - Extension - CurrentAccountComp - add null checks as anon layout components don't have a state today. This prevents the account switcher from working on the new lockV2 comp.

* PM-9449 - Extension AppRoutingModule - LockV2 should use ExtensionAnonLayoutWrapperData

* PM-9449 - LockComp - BiometricUnlock - cancelling is a valid action.

* PM-9449 - LockV2 - Biometric autoprompt cleanup

* PM-9449 - LockV2 - (1) Add TODO for KM team (2) Fix submit logic.

* PM-9449 - Tweak TODO to add task #

* PM-9449 - Test WebLockComponentService

* PM-9449 - ExtensionLockComponentService tested

* PM-9449 - Tweak extension lock comp svc test

* PM-9449 - DesktopLockComponentService tested

* PM-9449 - Add task # to TODO

* PM-9449 - Update apps/browser/src/services/extension-lock-component.service.ts per PR feedback

Co-authored-by: Justin Baur <19896123+justindbaur@users.noreply.github.com>

* PM-9449 - Per PR feedback, replace from with defer for better reactive execution of promise based functions.

* PM-9449 - Per PR feedback replace enum with type.

* PM-9449 - Fix imports and tests due to key management file moves.

* PM-9449 - Another test file import fix

---------

Co-authored-by: Justin Baur <19896123+justindbaur@users.noreply.github.com>
This commit is contained in:
Jared Snider
2024-10-01 16:06:18 -04:00
committed by GitHub
parent dab60dbaea
commit 9ff1db7573
22 changed files with 2139 additions and 21 deletions

View File

@@ -1,3 +1,4 @@
export * from "./webauthn-login";
export * from "./set-password-jit";
export * from "./registration";
export * from "./web-lock-component.service";

View File

@@ -0,0 +1,94 @@
import { TestBed } from "@angular/core/testing";
import { mock, MockProxy } from "jest-mock-extended";
import { firstValueFrom, of } from "rxjs";
import { UserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
import { UserId } from "@bitwarden/common/types/guid";
import { WebLockComponentService } from "./web-lock-component.service";
describe("WebLockComponentService", () => {
let service: WebLockComponentService;
let userDecryptionOptionsService: MockProxy<UserDecryptionOptionsServiceAbstraction>;
beforeEach(() => {
userDecryptionOptionsService = mock<UserDecryptionOptionsServiceAbstraction>();
TestBed.configureTestingModule({
providers: [
WebLockComponentService,
{
provide: UserDecryptionOptionsServiceAbstraction,
useValue: userDecryptionOptionsService,
},
],
});
service = TestBed.inject(WebLockComponentService);
});
it("instantiates", () => {
expect(service).not.toBeFalsy();
});
describe("getBiometricsError", () => {
it("throws an error when given a null input", () => {
expect(() => service.getBiometricsError(null)).toThrow(
"Biometric unlock is not supported in the web app. See getAvailableUnlockOptions$",
);
});
it("throws an error when given a non-null input", () => {
expect(() => service.getBiometricsError("error")).toThrow(
"Biometric unlock is not supported in the web app. See getAvailableUnlockOptions$",
);
});
});
describe("getPreviousUrl", () => {
it("returns null", () => {
expect(service.getPreviousUrl()).toBeNull();
});
});
describe("isWindowVisible", () => {
it("throws an error", async () => {
await expect(service.isWindowVisible()).rejects.toThrow("Method not implemented.");
});
});
describe("getBiometricsUnlockBtnText", () => {
it("throws an error", () => {
expect(() => service.getBiometricsUnlockBtnText()).toThrow(
"Biometric unlock is not supported in the web app. See getAvailableUnlockOptions$",
);
});
});
describe("getAvailableUnlockOptions$", () => {
it("returns an observable of unlock options", async () => {
const userId = "user-id" as UserId;
const userDecryptionOptions = {
hasMasterPassword: true,
};
userDecryptionOptionsService.userDecryptionOptionsById$.mockReturnValueOnce(
of(userDecryptionOptions),
);
const unlockOptions = await firstValueFrom(service.getAvailableUnlockOptions$(userId));
expect(unlockOptions).toEqual({
masterPassword: {
enabled: true,
},
pin: {
enabled: false,
},
biometrics: {
enabled: false,
disableReason: null,
},
});
});
});
});

View File

@@ -0,0 +1,55 @@
import { inject } from "@angular/core";
import { map, Observable } from "rxjs";
import { LockComponentService, UnlockOptions } from "@bitwarden/auth/angular";
import {
UserDecryptionOptions,
UserDecryptionOptionsServiceAbstraction,
} from "@bitwarden/auth/common";
import { UserId } from "@bitwarden/common/types/guid";
export class WebLockComponentService implements LockComponentService {
private readonly userDecryptionOptionsService = inject(UserDecryptionOptionsServiceAbstraction);
constructor() {}
getBiometricsError(error: any): string | null {
throw new Error(
"Biometric unlock is not supported in the web app. See getAvailableUnlockOptions$",
);
}
getPreviousUrl(): string | null {
return null;
}
async isWindowVisible(): Promise<boolean> {
throw new Error("Method not implemented.");
}
getBiometricsUnlockBtnText(): string {
throw new Error(
"Biometric unlock is not supported in the web app. See getAvailableUnlockOptions$",
);
}
getAvailableUnlockOptions$(userId: UserId): Observable<UnlockOptions> {
return this.userDecryptionOptionsService.userDecryptionOptionsById$(userId).pipe(
map((userDecryptionOptions: UserDecryptionOptions) => {
const unlockOpts: UnlockOptions = {
masterPassword: {
enabled: userDecryptionOptions.hasMasterPassword,
},
pin: {
enabled: false,
},
biometrics: {
enabled: false,
disableReason: null,
},
};
return unlockOpts;
}),
);
}
}

View File

@@ -20,6 +20,7 @@ import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.
import { ModalService as ModalServiceAbstraction } from "@bitwarden/angular/services/modal.service";
import {
RegistrationFinishService as RegistrationFinishServiceAbstraction,
LockComponentService,
SetPasswordJitService,
} from "@bitwarden/auth/angular";
import { InternalUserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
@@ -62,7 +63,11 @@ import { VaultTimeout, VaultTimeoutStringType } from "@bitwarden/common/types/va
import { BiometricsService } from "@bitwarden/key-management";
import { PolicyListService } from "../admin-console/core/policy-list.service";
import { WebRegistrationFinishService, WebSetPasswordJitService } from "../auth";
import {
WebSetPasswordJitService,
WebRegistrationFinishService,
WebLockComponentService,
} from "../auth";
import { AcceptOrganizationInviteService } from "../auth/organization-invite/accept-organization.service";
import { HtmlStorageService } from "../core/html-storage.service";
import { I18nService } from "../core/i18n.service";
@@ -197,6 +202,11 @@ const safeProviders: SafeProvider[] = [
PolicyService,
],
}),
safeProvider({
provide: LockComponentService,
useClass: WebLockComponentService,
deps: [],
}),
safeProvider({
provide: SetPasswordJitService,
useClass: WebSetPasswordJitService,

View File

@@ -10,6 +10,7 @@ import {
unauthGuardFn,
} from "@bitwarden/angular/auth/guards";
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";
import { extensionRefreshSwap } from "@bitwarden/angular/utils/extension-refresh-swap";
import {
AnonLayoutWrapperComponent,
AnonLayoutWrapperData,
@@ -20,6 +21,7 @@ import {
RegistrationStartSecondaryComponentData,
SetPasswordJitComponent,
RegistrationLinkExpiredComponent,
LockV2Component,
LockIcon,
UserLockIcon,
} from "@bitwarden/auth/angular";
@@ -337,21 +339,41 @@ const routes: Routes = [
pageTitle: "logIn",
},
},
{
path: "lock",
canActivate: [deepLinkGuard(), lockGuard()],
children: [
{
path: "",
component: LockComponent,
},
],
data: {
pageTitle: "yourVaultIsLockedV2",
pageIcon: LockIcon,
showReadonlyHostname: true,
} satisfies AnonLayoutWrapperData,
},
...extensionRefreshSwap(
LockComponent,
LockV2Component,
{
path: "lock",
canActivate: [deepLinkGuard(), lockGuard()],
children: [
{
path: "",
component: LockComponent,
},
],
data: {
pageTitle: "yourVaultIsLockedV2",
pageIcon: LockIcon,
showReadonlyHostname: true,
} satisfies AnonLayoutWrapperData,
},
{
path: "lock",
canActivate: [deepLinkGuard(), lockGuard()],
children: [
{
path: "",
component: LockV2Component,
},
],
data: {
pageTitle: "yourAccountIsLocked",
pageIcon: LockIcon,
showReadonlyHostname: true,
} satisfies AnonLayoutWrapperData,
},
),
{
path: "2fa",
canActivate: [unauthGuardFn()],

View File

@@ -1099,8 +1099,11 @@
"yourVaultIsLockedV2": {
"message": "Your vault is locked"
},
"uuid": {
"message": "UUID"
"yourAccountIsLocked": {
"message": "Your account is locked"
},
"uuid":{
"message" : "UUID"
},
"unlock": {
"message": "Unlock"
@@ -3169,6 +3172,10 @@
"incorrectPin": {
"message": "Incorrect PIN"
},
"pin": {
"message": "PIN",
"description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device."
},
"exportedVault": {
"message": "Vault exported"
},
@@ -7463,6 +7470,15 @@
"or": {
"message": "or"
},
"unlockWithBiometrics": {
"message": "Unlock with biometrics"
},
"unlockWithPin": {
"message": "Unlock with PIN"
},
"unlockWithMasterPassword": {
"message": "Unlock with master password"
},
"licenseAndBillingManagement": {
"message": "License and billing management"
},