mirror of
https://github.com/bitwarden/browser
synced 2026-01-31 00:33:33 +00:00
* Add creationDate of account to AccountInfo * Added initialization of creationDate. * Removed extra changes. * Fixed tests to initialize creation date * Added helper method to abstract account initialization in tests. * More test updates. * Linting * Additional test fixes. * Fixed spec reference * Fixed imports * Linting. * Fixed browser test. * Modified tsconfig to reference spec file. * Fixed import. * Removed dependency on os. This is necessary so that the @bitwarden/common/spec lib package can be referenced in tests without node. * Revert "Removed dependency on os. This is necessary so that the @bitwarden/common/spec lib package can be referenced in tests without node." This reverts commit669f6557b6. * Updated stories to hard-code new field. * Removed changes to tsconfig * Revert "Removed changes to tsconfig" This reverts commitb7d916e8dc.
216 lines
8.3 KiB
TypeScript
216 lines
8.3 KiB
TypeScript
import { TestBed } from "@angular/core/testing";
|
|
import { Router } from "@angular/router";
|
|
import { RouterTestingModule } from "@angular/router/testing";
|
|
import { MockProxy, mock } from "jest-mock-extended";
|
|
import { BehaviorSubject, of } from "rxjs";
|
|
|
|
import { EmptyComponent } from "@bitwarden/angular/platform/guard/feature-flag.guard.spec";
|
|
import { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
|
import { ClientType } from "@bitwarden/common/enums";
|
|
import { DeviceTrustServiceAbstraction } from "@bitwarden/common/key-management/device-trust/abstractions/device-trust.service.abstraction";
|
|
import { KeyConnectorService } from "@bitwarden/common/key-management/key-connector/abstractions/key-connector.service";
|
|
import { KeyConnectorDomainConfirmation } from "@bitwarden/common/key-management/key-connector/models/key-connector-domain-confirmation";
|
|
import { VaultTimeoutSettingsService } from "@bitwarden/common/key-management/vault-timeout";
|
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
|
import { mockAccountInfoWith } from "@bitwarden/common/spec";
|
|
import { UserId } from "@bitwarden/common/types/guid";
|
|
import { KeyService } from "@bitwarden/key-management";
|
|
|
|
import { lockGuard } from "./lock.guard";
|
|
|
|
interface SetupParams {
|
|
authStatus: AuthenticationStatus;
|
|
canLock?: boolean;
|
|
clientType?: ClientType;
|
|
everHadUserKey?: boolean;
|
|
supportsDeviceTrust?: boolean;
|
|
hasMasterPassword?: boolean;
|
|
}
|
|
|
|
describe("lockGuard", () => {
|
|
const keyConnectorService = mock<KeyConnectorService>();
|
|
|
|
const setup = (setupParams: SetupParams) => {
|
|
const authService: MockProxy<AuthService> = mock<AuthService>();
|
|
authService.authStatusFor$.mockReturnValue(of(setupParams.authStatus));
|
|
|
|
const vaultTimeoutSettingsService: MockProxy<VaultTimeoutSettingsService> =
|
|
mock<VaultTimeoutSettingsService>();
|
|
vaultTimeoutSettingsService.canLock.mockResolvedValue(setupParams.canLock ?? true);
|
|
|
|
const keyService: MockProxy<KeyService> = mock<KeyService>();
|
|
keyService.everHadUserKey$.mockReturnValue(of(setupParams.everHadUserKey ?? true));
|
|
|
|
const platformUtilService: MockProxy<PlatformUtilsService> = mock<PlatformUtilsService>();
|
|
platformUtilService.getClientType.mockReturnValue(setupParams.clientType ?? ClientType.Web);
|
|
|
|
const messagingService: MockProxy<MessagingService> = mock<MessagingService>();
|
|
|
|
const deviceTrustService: MockProxy<DeviceTrustServiceAbstraction> =
|
|
mock<DeviceTrustServiceAbstraction>();
|
|
deviceTrustService.supportsDeviceTrust$ = of(setupParams.supportsDeviceTrust ?? false);
|
|
|
|
const userVerificationService: MockProxy<UserVerificationService> =
|
|
mock<UserVerificationService>();
|
|
userVerificationService.hasMasterPassword.mockResolvedValue(
|
|
setupParams.hasMasterPassword ?? true,
|
|
);
|
|
|
|
keyConnectorService.requiresDomainConfirmation$.mockReturnValue(of(null));
|
|
|
|
const accountService: MockProxy<AccountService> = mock<AccountService>();
|
|
const activeAccountSubject = new BehaviorSubject<Account | null>(null);
|
|
accountService.activeAccount$ = activeAccountSubject;
|
|
activeAccountSubject.next({
|
|
id: "test-id" as UserId,
|
|
...mockAccountInfoWith({
|
|
name: "Test User 1",
|
|
email: "test@email.com",
|
|
}),
|
|
});
|
|
|
|
const testBed = TestBed.configureTestingModule({
|
|
imports: [
|
|
RouterTestingModule.withRoutes([
|
|
{ path: "", component: EmptyComponent },
|
|
{ path: "lock", component: EmptyComponent, canActivate: [lockGuard()] },
|
|
{ path: "non-lock-route", component: EmptyComponent },
|
|
{ path: "confirm-key-connector-domain", component: EmptyComponent },
|
|
]),
|
|
],
|
|
providers: [
|
|
{ provide: AuthService, useValue: authService },
|
|
{ provide: MessagingService, useValue: messagingService },
|
|
{ provide: AccountService, useValue: accountService },
|
|
{ provide: VaultTimeoutSettingsService, useValue: vaultTimeoutSettingsService },
|
|
{ provide: KeyService, useValue: keyService },
|
|
{ provide: PlatformUtilsService, useValue: platformUtilService },
|
|
{ provide: DeviceTrustServiceAbstraction, useValue: deviceTrustService },
|
|
{ provide: UserVerificationService, useValue: userVerificationService },
|
|
{ provide: KeyConnectorService, useValue: keyConnectorService },
|
|
],
|
|
});
|
|
|
|
return {
|
|
router: testBed.inject(Router),
|
|
messagingService,
|
|
};
|
|
};
|
|
|
|
it("should be created", () => {
|
|
const { router } = setup({
|
|
authStatus: AuthenticationStatus.Locked,
|
|
});
|
|
expect(router).toBeTruthy();
|
|
});
|
|
|
|
it("should redirect to the root route when the user is Unlocked", async () => {
|
|
const { router } = setup({
|
|
authStatus: AuthenticationStatus.Unlocked,
|
|
});
|
|
|
|
await router.navigate(["lock"]);
|
|
expect(router.url).toBe("/");
|
|
});
|
|
|
|
it("should redirect to the root route when the user is LoggedOut", async () => {
|
|
const { router } = setup({
|
|
authStatus: AuthenticationStatus.LoggedOut,
|
|
});
|
|
|
|
await router.navigate(["lock"]);
|
|
expect(router.url).toBe("/");
|
|
});
|
|
|
|
it("should allow navigation to the lock route when the user is Locked and they can lock", async () => {
|
|
const { router } = setup({
|
|
authStatus: AuthenticationStatus.Locked,
|
|
canLock: true,
|
|
});
|
|
|
|
await router.navigate(["lock"]);
|
|
expect(router.url).toBe("/lock");
|
|
});
|
|
|
|
it("should allow navigation to the lock route when the user is locked, they can lock, and device trust is not supported", async () => {
|
|
const { router } = setup({
|
|
authStatus: AuthenticationStatus.Locked,
|
|
canLock: true,
|
|
supportsDeviceTrust: false,
|
|
});
|
|
|
|
await router.navigate(["lock"]);
|
|
expect(router.url).toBe("/lock");
|
|
});
|
|
|
|
it("should not allow navigation to the lock route when canLock is false", async () => {
|
|
const { router } = setup({
|
|
authStatus: AuthenticationStatus.Locked,
|
|
canLock: false,
|
|
});
|
|
|
|
await router.navigate(["lock"]);
|
|
expect(router.url).toBe("/");
|
|
});
|
|
|
|
it("should allow navigation to the lock route when device trust is supported, the user has a MP, and the user is coming from the login-initiated page", async () => {
|
|
const { router } = setup({
|
|
authStatus: AuthenticationStatus.Locked,
|
|
canLock: true,
|
|
clientType: ClientType.Web,
|
|
everHadUserKey: false,
|
|
supportsDeviceTrust: true,
|
|
hasMasterPassword: true,
|
|
});
|
|
|
|
await router.navigate(["lock"], { queryParams: { from: "login-initiated" } });
|
|
expect(router.url).toBe("/lock?from=login-initiated");
|
|
});
|
|
|
|
it("should allow navigation to the lock route when TDE is disabled, the user doesn't have a MP, and the user has had a user key", async () => {
|
|
const { router } = setup({
|
|
authStatus: AuthenticationStatus.Locked,
|
|
canLock: true,
|
|
supportsDeviceTrust: false,
|
|
hasMasterPassword: false,
|
|
everHadUserKey: true,
|
|
});
|
|
|
|
await router.navigate(["lock"]);
|
|
expect(router.url).toBe("/lock");
|
|
});
|
|
|
|
it("should not allow navigation to the lock route when device trust is supported and the user has not ever had a user key", async () => {
|
|
const { router } = setup({
|
|
authStatus: AuthenticationStatus.Locked,
|
|
canLock: true,
|
|
clientType: ClientType.Web,
|
|
everHadUserKey: false,
|
|
supportsDeviceTrust: true,
|
|
hasMasterPassword: false,
|
|
});
|
|
|
|
await router.navigate(["lock"]);
|
|
expect(router.url).toBe("/");
|
|
});
|
|
|
|
it("should redirect to the confirm-key-connector-domain route when the auth status is locked, can't lock and requires key connector domain confirmation", async () => {
|
|
const { router } = setup({
|
|
authStatus: AuthenticationStatus.Locked,
|
|
canLock: false,
|
|
});
|
|
keyConnectorService.requiresDomainConfirmation$.mockReturnValue(
|
|
of({
|
|
keyConnectorUrl: "https://example.com",
|
|
} as KeyConnectorDomainConfirmation),
|
|
);
|
|
|
|
await router.navigate(["lock"]);
|
|
expect(router.url).toBe("/confirm-key-connector-domain");
|
|
});
|
|
});
|