mirror of
https://github.com/bitwarden/browser
synced 2026-02-08 04:33:38 +00:00
ensure files moved to @bitwarden/logging appear as moves in history
This commit is contained in:
@@ -7,11 +7,6 @@ import { ReplaySubject, Subject, firstValueFrom, map, switchMap, takeUntil } fro
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import {
|
||||
SemanticLogger,
|
||||
disabledSemanticLoggerProvider,
|
||||
ifEnabledSemanticLoggerProvider,
|
||||
} from "@bitwarden/common/tools/log";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { ButtonModule, DialogService } from "@bitwarden/components";
|
||||
import {
|
||||
@@ -19,6 +14,11 @@ import {
|
||||
EmptyCredentialHistoryComponent,
|
||||
} from "@bitwarden/generator-components";
|
||||
import { GeneratorHistoryService } from "@bitwarden/generator-history";
|
||||
import {
|
||||
disabledSemanticLoggerProvider,
|
||||
ifEnabledSemanticLoggerProvider,
|
||||
SemanticLogger,
|
||||
} from "@bitwarden/logging";
|
||||
|
||||
import { PopOutComponent } from "../../../platform/popup/components/pop-out.component";
|
||||
import { PopupFooterComponent } from "../../../platform/popup/layout/popup-footer.component";
|
||||
|
||||
@@ -3,14 +3,13 @@ import { Router, UrlTree } from "@angular/router";
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
import { firstValueFrom, NEVER } from "rxjs";
|
||||
|
||||
import { LOG_PROVIDER } from "@bitwarden/angular/services/injection-tokens";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
import { StateProvider } from "@bitwarden/common/platform/state";
|
||||
import { mockAccountServiceWith, FakeStateProvider } from "@bitwarden/common/spec";
|
||||
import { SemanticLogger } from "@bitwarden/common/tools/log";
|
||||
import { SystemServiceProvider } from "@bitwarden/common/tools/providers";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { SYSTEM_SERVICE_PROVIDER } from "@bitwarden/generator-components";
|
||||
import { LogProvider, SemanticLogger } from "@bitwarden/logging";
|
||||
|
||||
import { DefaultSendAccessService } from "./default-send-access-service";
|
||||
import { SEND_RESPONSE_KEY, SEND_CONTEXT_KEY } from "./send-access-memory";
|
||||
@@ -21,7 +20,7 @@ describe("DefaultSendAccessService", () => {
|
||||
let sendApiService: MockProxy<SendApiService>;
|
||||
let router: MockProxy<Router>;
|
||||
let logger: MockProxy<SemanticLogger>;
|
||||
let systemServiceProvider: MockProxy<SystemServiceProvider>;
|
||||
let logProvider: LogProvider;
|
||||
|
||||
beforeEach(() => {
|
||||
const accountService = mockAccountServiceWith("user-id" as UserId);
|
||||
@@ -29,9 +28,7 @@ describe("DefaultSendAccessService", () => {
|
||||
sendApiService = mock<SendApiService>();
|
||||
router = mock<Router>();
|
||||
logger = mock<SemanticLogger>();
|
||||
systemServiceProvider = mock<SystemServiceProvider>();
|
||||
|
||||
systemServiceProvider.log.mockReturnValue(logger);
|
||||
logProvider = jest.fn().mockReturnValue(logger) as any;
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
@@ -39,7 +36,7 @@ describe("DefaultSendAccessService", () => {
|
||||
{ provide: StateProvider, useValue: stateProvider },
|
||||
{ provide: SendApiService, useValue: sendApiService },
|
||||
{ provide: Router, useValue: router },
|
||||
{ provide: SYSTEM_SERVICE_PROVIDER, useValue: systemServiceProvider },
|
||||
{ provide: LOG_PROVIDER, useValue: logProvider },
|
||||
],
|
||||
});
|
||||
|
||||
@@ -48,7 +45,7 @@ describe("DefaultSendAccessService", () => {
|
||||
|
||||
describe("constructor", () => {
|
||||
it("creates logger with type 'SendAccessAuthenticationService' when initialized", () => {
|
||||
expect(systemServiceProvider.log).toHaveBeenCalledWith({
|
||||
expect(logProvider).toHaveBeenCalledWith({
|
||||
type: "SendAccessAuthenticationService",
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,13 +2,12 @@ import { Injectable, Inject } from "@angular/core";
|
||||
import { Router, UrlTree } from "@angular/router";
|
||||
import { map, of, from, catchError, timeout } from "rxjs";
|
||||
|
||||
import { LOG_PROVIDER } from "@bitwarden/angular/services/injection-tokens";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
import { StateProvider } from "@bitwarden/common/platform/state";
|
||||
import { SemanticLogger } from "@bitwarden/common/tools/log";
|
||||
import { SystemServiceProvider } from "@bitwarden/common/tools/providers";
|
||||
import { SendAccessRequest } from "@bitwarden/common/tools/send/models/request/send-access.request";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { SYSTEM_SERVICE_PROVIDER } from "@bitwarden/generator-components";
|
||||
import { LogProvider, SemanticLogger } from "@bitwarden/logging";
|
||||
|
||||
import { SEND_RESPONSE_KEY, SEND_CONTEXT_KEY } from "./send-access-memory";
|
||||
import { SendAccessService } from "./send-access-service.abstraction";
|
||||
@@ -24,9 +23,9 @@ export class DefaultSendAccessService implements SendAccessService {
|
||||
private readonly state: StateProvider,
|
||||
private readonly api: SendApiService,
|
||||
private readonly router: Router,
|
||||
@Inject(SYSTEM_SERVICE_PROVIDER) system: SystemServiceProvider,
|
||||
@Inject(LOG_PROVIDER) log: LogProvider,
|
||||
) {
|
||||
this.logger = system.log({ type: "SendAccessAuthenticationService" });
|
||||
this.logger = log({ type: "SendAccessAuthenticationService" });
|
||||
}
|
||||
|
||||
redirect$(sendId: string) {
|
||||
|
||||
@@ -2,9 +2,8 @@ import { TestBed } from "@angular/core/testing";
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from "@angular/router";
|
||||
import { firstValueFrom, Observable, of } from "rxjs";
|
||||
|
||||
import { SemanticLogger } from "@bitwarden/common/tools/log";
|
||||
import { SystemServiceProvider } from "@bitwarden/common/tools/providers";
|
||||
import { SYSTEM_SERVICE_PROVIDER } from "@bitwarden/generator-components";
|
||||
import { LOG_PROVIDER } from "@bitwarden/angular/services/injection-tokens";
|
||||
import { LogProvider, SemanticLogger } from "@bitwarden/logging";
|
||||
|
||||
import { SendAccessService } from "./send-access-service.abstraction";
|
||||
import { trySendAccess } from "./try-send-access.guard";
|
||||
@@ -22,10 +21,8 @@ function createMockLogger(): SemanticLogger {
|
||||
} as any as SemanticLogger;
|
||||
}
|
||||
|
||||
function createMockSystemServiceProvider(): SystemServiceProvider {
|
||||
return {
|
||||
log: jest.fn().mockReturnValue(createMockLogger()),
|
||||
} as any as SystemServiceProvider;
|
||||
function createMockLogProvider(): LogProvider {
|
||||
return jest.fn().mockReturnValue(createMockLogger()) as any;
|
||||
}
|
||||
|
||||
function createMockSendAccessService() {
|
||||
@@ -38,18 +35,18 @@ function createMockSendAccessService() {
|
||||
|
||||
describe("trySendAccess", () => {
|
||||
let mockSendAccessService: ReturnType<typeof createMockSendAccessService>;
|
||||
let mockSystemServiceProvider: SystemServiceProvider;
|
||||
let mockLogProvider: LogProvider;
|
||||
let mockRouterState: RouterStateSnapshot;
|
||||
|
||||
beforeEach(() => {
|
||||
mockSendAccessService = createMockSendAccessService();
|
||||
mockSystemServiceProvider = createMockSystemServiceProvider();
|
||||
mockLogProvider = createMockLogProvider();
|
||||
mockRouterState = {} as RouterStateSnapshot;
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
{ provide: SendAccessService, useValue: mockSendAccessService },
|
||||
{ provide: SYSTEM_SERVICE_PROVIDER, useValue: mockSystemServiceProvider },
|
||||
{ provide: LOG_PROVIDER, useValue: mockLogProvider },
|
||||
],
|
||||
});
|
||||
});
|
||||
@@ -97,7 +94,7 @@ describe("trySendAccess", () => {
|
||||
await expect(firstValueFrom(guardResult!)).resolves.toEqual(expectedUrlTree);
|
||||
|
||||
// Logger methods should not be called for warnings or panics
|
||||
const mockLogger = (mockSystemServiceProvider.log as jest.Mock).mock.results[0].value;
|
||||
const mockLogger = (mockLogProvider as jest.Mock).mock.results[0].value;
|
||||
expect(mockLogger.warn).not.toHaveBeenCalled();
|
||||
expect(mockLogger.panic).not.toHaveBeenCalled();
|
||||
});
|
||||
@@ -116,7 +113,7 @@ describe("trySendAccess", () => {
|
||||
sendIdValue === undefined ? { key } : { sendId: sendIdValue, key },
|
||||
);
|
||||
const mockLogger = createMockLogger();
|
||||
(mockSystemServiceProvider.log as jest.Mock).mockReturnValue(mockLogger);
|
||||
(mockLogProvider as jest.Mock).mockReturnValue(mockLogger);
|
||||
|
||||
await expect(async () => {
|
||||
const result$ = TestBed.runInInjectionContext(() =>
|
||||
@@ -125,7 +122,7 @@ describe("trySendAccess", () => {
|
||||
await firstValueFrom(result$);
|
||||
}).rejects.toThrow("Logger panic called");
|
||||
|
||||
expect(mockSystemServiceProvider.log).toHaveBeenCalledWith({
|
||||
expect(mockLogProvider).toHaveBeenCalledWith({
|
||||
function: "trySendAccess",
|
||||
});
|
||||
expect(mockLogger.warn).toHaveBeenCalledWith(
|
||||
@@ -142,7 +139,7 @@ describe("trySendAccess", () => {
|
||||
const key = "valid-key";
|
||||
const mockRoute = createMockRoute({ sendId: value, key });
|
||||
const mockLogger = createMockLogger();
|
||||
(mockSystemServiceProvider.log as jest.Mock).mockReturnValue(mockLogger);
|
||||
(mockLogProvider as jest.Mock).mockReturnValue(mockLogger);
|
||||
|
||||
await expect(async () => {
|
||||
const result$ = TestBed.runInInjectionContext(() =>
|
||||
@@ -151,7 +148,7 @@ describe("trySendAccess", () => {
|
||||
await firstValueFrom(result$);
|
||||
}).rejects.toThrow("Logger panic called");
|
||||
|
||||
expect(mockSystemServiceProvider.log).toHaveBeenCalledWith({ function: "trySendAccess" });
|
||||
expect(mockLogProvider).toHaveBeenCalledWith({ function: "trySendAccess" });
|
||||
expect(mockLogger.panic).toHaveBeenCalledWith(
|
||||
{ expected: "string", actual: type },
|
||||
"sendId has invalid type",
|
||||
@@ -167,7 +164,7 @@ describe("trySendAccess", () => {
|
||||
invalidSendId === undefined ? { key } : { sendId: invalidSendId, key },
|
||||
);
|
||||
const mockLogger = createMockLogger();
|
||||
(mockSystemServiceProvider.log as jest.Mock).mockReturnValue(mockLogger);
|
||||
(mockLogProvider as jest.Mock).mockReturnValue(mockLogger);
|
||||
|
||||
await expect(async () => {
|
||||
const result$ = TestBed.runInInjectionContext(() =>
|
||||
@@ -189,7 +186,7 @@ describe("trySendAccess", () => {
|
||||
keyValue === undefined ? { sendId } : { sendId, key: keyValue },
|
||||
);
|
||||
const mockLogger = createMockLogger();
|
||||
(mockSystemServiceProvider.log as jest.Mock).mockReturnValue(mockLogger);
|
||||
(mockLogProvider as jest.Mock).mockReturnValue(mockLogger);
|
||||
|
||||
await expect(async () => {
|
||||
const result$ = TestBed.runInInjectionContext(() =>
|
||||
@@ -198,7 +195,7 @@ describe("trySendAccess", () => {
|
||||
await firstValueFrom(result$);
|
||||
}).rejects.toThrow("Logger panic called");
|
||||
|
||||
expect(mockSystemServiceProvider.log).toHaveBeenCalledWith({ function: "trySendAccess" });
|
||||
expect(mockLogProvider).toHaveBeenCalledWith({ function: "trySendAccess" });
|
||||
expect(mockLogger.panic).toHaveBeenCalledWith("key missing from the route parameters");
|
||||
});
|
||||
|
||||
@@ -210,7 +207,7 @@ describe("trySendAccess", () => {
|
||||
const sendId = "valid-send-id";
|
||||
const mockRoute = createMockRoute({ sendId, key: value });
|
||||
const mockLogger = createMockLogger();
|
||||
(mockSystemServiceProvider.log as jest.Mock).mockReturnValue(mockLogger);
|
||||
(mockLogProvider as jest.Mock).mockReturnValue(mockLogger);
|
||||
|
||||
await expect(async () => {
|
||||
const result$ = TestBed.runInInjectionContext(() =>
|
||||
@@ -219,7 +216,7 @@ describe("trySendAccess", () => {
|
||||
await firstValueFrom(result$);
|
||||
}).rejects.toThrow("Logger panic called");
|
||||
|
||||
expect(mockSystemServiceProvider.log).toHaveBeenCalledWith({ function: "trySendAccess" });
|
||||
expect(mockLogProvider).toHaveBeenCalledWith({ function: "trySendAccess" });
|
||||
expect(mockLogger.panic).toHaveBeenCalledWith(
|
||||
{ expected: "string", actual: type },
|
||||
"key has invalid type",
|
||||
@@ -235,7 +232,7 @@ describe("trySendAccess", () => {
|
||||
invalidKey === undefined ? { sendId } : { sendId, key: invalidKey },
|
||||
);
|
||||
const mockLogger = createMockLogger();
|
||||
(mockSystemServiceProvider.log as jest.Mock).mockReturnValue(mockLogger);
|
||||
(mockLogProvider as jest.Mock).mockReturnValue(mockLogger);
|
||||
|
||||
await expect(async () => {
|
||||
const result$ = TestBed.runInInjectionContext(() =>
|
||||
|
||||
@@ -2,8 +2,8 @@ import { inject } from "@angular/core";
|
||||
import { ActivatedRouteSnapshot, CanActivateFn, RouterStateSnapshot } from "@angular/router";
|
||||
import { from, ignoreElements, concat } from "rxjs";
|
||||
|
||||
import { SystemServiceProvider } from "@bitwarden/common/tools/providers";
|
||||
import { SYSTEM_SERVICE_PROVIDER } from "@bitwarden/generator-components";
|
||||
import { LOG_PROVIDER } from "@bitwarden/angular/services/injection-tokens";
|
||||
import { LogProvider } from "@bitwarden/logging";
|
||||
|
||||
import { SendAccessService } from "./send-access-service.abstraction";
|
||||
|
||||
@@ -12,8 +12,8 @@ export const trySendAccess: CanActivateFn = (
|
||||
_state: RouterStateSnapshot,
|
||||
) => {
|
||||
const sendAccess = inject(SendAccessService);
|
||||
const system = inject<SystemServiceProvider>(SYSTEM_SERVICE_PROVIDER);
|
||||
const logger = system.log({ function: "trySendAccess" });
|
||||
const log = inject<LogProvider>(LOG_PROVIDER);
|
||||
const logger = log({ function: "trySendAccess" });
|
||||
|
||||
const { sendId, key } = route.params;
|
||||
if (!sendId) {
|
||||
|
||||
@@ -15,10 +15,12 @@ import {
|
||||
import { Theme } from "@bitwarden/common/platform/enums";
|
||||
import { Message } from "@bitwarden/common/platform/messaging";
|
||||
import { HttpOperations } from "@bitwarden/common/services/api.service";
|
||||
import { LogProvider } from "@bitwarden/logging";
|
||||
import { SafeInjectionToken } from "@bitwarden/ui-common";
|
||||
// Re-export the SafeInjectionToken from ui-common
|
||||
export { SafeInjectionToken } from "@bitwarden/ui-common";
|
||||
|
||||
export const LOG_PROVIDER = new SafeInjectionToken<LogProvider>("LogProvider");
|
||||
export const WINDOW = new SafeInjectionToken<Window>("WINDOW");
|
||||
export const DOCUMENT = new SafeInjectionToken<Document>("DOCUMENT");
|
||||
export const OBSERVABLE_MEMORY_STORAGE = new SafeInjectionToken<
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { mock } from "jest-mock-extended";
|
||||
import { BehaviorSubject, firstValueFrom } from "rxjs";
|
||||
|
||||
import { disabledSemanticLoggerProvider } from "@bitwarden/logging";
|
||||
|
||||
import { FakeAccountService, FakeStateProvider, awaitAsync } from "../../../spec";
|
||||
import { Account } from "../../auth/abstractions/account.service";
|
||||
import { EXTENSION_DISK, UserKeyDefinition } from "../../platform/state";
|
||||
import { UserId } from "../../types/guid";
|
||||
import { LegacyEncryptorProvider } from "../cryptography/legacy-encryptor-provider";
|
||||
import { UserEncryptor } from "../cryptography/user-encryptor.abstraction";
|
||||
import { disabledSemanticLoggerProvider } from "../log";
|
||||
import { UserStateSubjectDependencyProvider } from "../state/user-state-subject-dependency-provider";
|
||||
|
||||
import { Site } from "./data";
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { shareReplay } from "rxjs";
|
||||
|
||||
import { SemanticLogger } from "@bitwarden/logging";
|
||||
|
||||
import { Account } from "../../auth/abstractions/account.service";
|
||||
import { BoundDependency } from "../dependencies";
|
||||
import { SemanticLogger } from "../log";
|
||||
import { UserStateSubject } from "../state/user-state-subject";
|
||||
import { UserStateSubjectDependencyProvider } from "../state/user-state-subject-dependency-provider";
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { SemanticLogger } from "@bitwarden/logging";
|
||||
|
||||
import { StateProvider } from "../../platform/state";
|
||||
import { LegacyEncryptorProvider } from "../cryptography/legacy-encryptor-provider";
|
||||
import { SemanticLogger } from "../log";
|
||||
|
||||
/** Aggregates user state subject dependencies */
|
||||
export abstract class UserStateSubjectDependencyProvider {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// @ts-strict-ignore
|
||||
import { BehaviorSubject, of, Subject } from "rxjs";
|
||||
|
||||
import { disabledSemanticLoggerProvider } from "@bitwarden/logging";
|
||||
|
||||
import {
|
||||
awaitAsync,
|
||||
FakeAccountService,
|
||||
@@ -13,7 +15,6 @@ import { GENERATOR_DISK, UserKeyDefinition } from "../../platform/state";
|
||||
import { UserId } from "../../types/guid";
|
||||
import { LegacyEncryptorProvider } from "../cryptography/legacy-encryptor-provider";
|
||||
import { UserEncryptor } from "../cryptography/user-encryptor.abstraction";
|
||||
import { disabledSemanticLoggerProvider } from "../log";
|
||||
import { PrivateClassifier } from "../private-classifier";
|
||||
import { StateConstraints } from "../types";
|
||||
|
||||
|
||||
@@ -29,11 +29,12 @@ import {
|
||||
switchMap,
|
||||
} from "rxjs";
|
||||
|
||||
import { SemanticLogger } from "@bitwarden/logging";
|
||||
|
||||
import { Account } from "../../auth/abstractions/account.service";
|
||||
import { EncString } from "../../key-management/crypto/models/enc-string";
|
||||
import { SingleUserState, UserKeyDefinition } from "../../platform/state";
|
||||
import { UserEncryptor } from "../cryptography/user-encryptor.abstraction";
|
||||
import { SemanticLogger } from "../log";
|
||||
import { anyComplete, pin, ready, withLatestReady } from "../rx";
|
||||
import { Constraints, SubjectConstraints, WithConstraints } from "../types";
|
||||
|
||||
|
||||
@@ -1,3 +1,50 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { SemanticLogger } from "./semantic-logger.abstraction";
|
||||
|
||||
export { LogService } from "./log.service";
|
||||
export { LogLevel } from "./log-level";
|
||||
export { ConsoleLogService } from "./console-log.service";
|
||||
export { SemanticLogger } from "./semantic-logger.abstraction";
|
||||
export { DISABLED_LOGGER } from "./disabled-logger";
|
||||
export {
|
||||
disabledSemanticLoggerProvider,
|
||||
consoleSemanticLoggerProvider,
|
||||
enableLogForTypes,
|
||||
ifEnabledSemanticLoggerProvider,
|
||||
} from "./factory";
|
||||
|
||||
/**
|
||||
* Creates a semantic logger with a fixed context that is included in all log messages.
|
||||
*
|
||||
* @param context - Contextual metadata that will be included in every log entry
|
||||
* emitted by the returned logger. This is used to identify the source or scope
|
||||
* of log messages (e.g., `{ type: "ImportService" }` or `{ accountId: "123" }`).
|
||||
*
|
||||
* @returns A SemanticLogger instance that includes the provided context in all log output.
|
||||
*
|
||||
* @remarks
|
||||
* By convention, avoid using the following field names in the context object, as they
|
||||
* may conflict with fields added by the semantic logging implementation:
|
||||
* - `message` - The log message text
|
||||
* - `level` - The log level (debug, info, warn, error, panic)
|
||||
* - `provider` - The logging provider identifier
|
||||
* - `content` - Additional data passed to individual log calls
|
||||
*
|
||||
* Note: These field names are not enforced at compile-time or runtime, but using them
|
||||
* may result in unexpected behavior or field name collisions in log output.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Create a logger for a service
|
||||
* const log = logProvider({ type: "ImportService" });
|
||||
*
|
||||
* // All logs from this logger will include { type: "ImportService" }
|
||||
* log.debug("Starting import");
|
||||
* // Output: { type: "ImportService", level: "debug", message: "Starting import" }
|
||||
*
|
||||
* log.info({ itemCount: 42 }, "Import complete");
|
||||
* // Output: { type: "ImportService", level: "info", content: { itemCount: 42 }, message: "Import complete" }
|
||||
* ```
|
||||
*/
|
||||
export type LogProvider = <Context extends object>(context: Jsonify<Context>) => SemanticLogger;
|
||||
|
||||
@@ -1,8 +1,93 @@
|
||||
import * as lib from "./index";
|
||||
import { mock } from "jest-mock-extended";
|
||||
|
||||
describe("logging", () => {
|
||||
// This test will fail until something is exported from index.ts
|
||||
it("should work", () => {
|
||||
expect(lib).toBeDefined();
|
||||
import * as lib from "./index";
|
||||
import { SemanticLogger } from "./index";
|
||||
|
||||
describe("logging module", () => {
|
||||
describe("public API", () => {
|
||||
it("should export LogService", () => {
|
||||
expect(lib.LogService).toBeDefined();
|
||||
});
|
||||
|
||||
it("should export LogLevel", () => {
|
||||
expect(lib.LogLevel).toBeDefined();
|
||||
});
|
||||
|
||||
it("should export ConsoleLogService", () => {
|
||||
expect(lib.ConsoleLogService).toBeDefined();
|
||||
});
|
||||
|
||||
it("should export DISABLED_LOGGER", () => {
|
||||
expect(lib.DISABLED_LOGGER).toBeDefined();
|
||||
});
|
||||
|
||||
it("should export disabledSemanticLoggerProvider", () => {
|
||||
expect(lib.disabledSemanticLoggerProvider).toBeDefined();
|
||||
});
|
||||
|
||||
it("should export consoleSemanticLoggerProvider", () => {
|
||||
expect(lib.consoleSemanticLoggerProvider).toBeDefined();
|
||||
});
|
||||
|
||||
it("should export enableLogForTypes", () => {
|
||||
expect(lib.enableLogForTypes).toBeDefined();
|
||||
});
|
||||
|
||||
it("should export ifEnabledSemanticLoggerProvider", () => {
|
||||
expect(lib.ifEnabledSemanticLoggerProvider).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("SemanticLogger", () => {
|
||||
let logger: SemanticLogger;
|
||||
|
||||
beforeEach(() => {
|
||||
logger = mock<SemanticLogger>();
|
||||
});
|
||||
|
||||
describe("logging methods", () => {
|
||||
it("should accept a message string", () => {
|
||||
logger.debug("debug message");
|
||||
logger.info("info message");
|
||||
logger.warn("warn message");
|
||||
logger.error("error message");
|
||||
|
||||
expect(logger.debug).toHaveBeenCalledWith("debug message");
|
||||
expect(logger.info).toHaveBeenCalledWith("info message");
|
||||
expect(logger.warn).toHaveBeenCalledWith("warn message");
|
||||
expect(logger.error).toHaveBeenCalledWith("error message");
|
||||
});
|
||||
|
||||
it("should accept content object and optional message", () => {
|
||||
logger.debug({ step: 1 }, "processing step");
|
||||
logger.info({ count: 42 }, "items processed");
|
||||
logger.warn({ threshold: 100 }, "approaching limit");
|
||||
logger.error({ code: 500 }, "server error");
|
||||
|
||||
expect(logger.debug).toHaveBeenCalledWith({ step: 1 }, "processing step");
|
||||
expect(logger.info).toHaveBeenCalledWith({ count: 42 }, "items processed");
|
||||
expect(logger.warn).toHaveBeenCalledWith({ threshold: 100 }, "approaching limit");
|
||||
expect(logger.error).toHaveBeenCalledWith({ code: 500 }, "server error");
|
||||
});
|
||||
});
|
||||
|
||||
describe("panic", () => {
|
||||
beforeEach(() => {
|
||||
logger.panic = jest.fn((content: any, msg?: string) => {
|
||||
const errorMsg = msg || (typeof content === "string" ? content : "panic");
|
||||
throw new Error(errorMsg);
|
||||
}) as any;
|
||||
});
|
||||
|
||||
it("should throw when called with a message", () => {
|
||||
expect(() => logger.panic("critical error")).toThrow("critical error");
|
||||
});
|
||||
|
||||
it("should throw when called with content and message", () => {
|
||||
expect(() => logger.panic({ reason: "invalid state" }, "system panic")).toThrow(
|
||||
"system panic",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,14 +15,14 @@ import {
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import {
|
||||
SemanticLogger,
|
||||
disabledSemanticLoggerProvider,
|
||||
ifEnabledSemanticLoggerProvider,
|
||||
} from "@bitwarden/common/tools/log";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { ButtonModule, DialogModule, DialogService } from "@bitwarden/components";
|
||||
import { GeneratorHistoryService } from "@bitwarden/generator-history";
|
||||
import {
|
||||
disabledSemanticLoggerProvider,
|
||||
ifEnabledSemanticLoggerProvider,
|
||||
SemanticLogger,
|
||||
} from "@bitwarden/logging";
|
||||
|
||||
import { CredentialGeneratorHistoryComponent as CredentialGeneratorHistoryToolsComponent } from "./credential-generator-history.component";
|
||||
import { EmptyCredentialHistoryComponent } from "./empty-credential-history.component";
|
||||
|
||||
@@ -8,11 +8,6 @@ import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { Account } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import {
|
||||
SemanticLogger,
|
||||
disabledSemanticLoggerProvider,
|
||||
ifEnabledSemanticLoggerProvider,
|
||||
} from "@bitwarden/common/tools/log";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import {
|
||||
ColorPasswordModule,
|
||||
@@ -22,6 +17,11 @@ import {
|
||||
} from "@bitwarden/components";
|
||||
import { AlgorithmsByType, CredentialGeneratorService } from "@bitwarden/generator-core";
|
||||
import { GeneratedCredential, GeneratorHistoryService } from "@bitwarden/generator-history";
|
||||
import {
|
||||
disabledSemanticLoggerProvider,
|
||||
ifEnabledSemanticLoggerProvider,
|
||||
SemanticLogger,
|
||||
} from "@bitwarden/logging";
|
||||
|
||||
import { GeneratorModule } from "./generator.module";
|
||||
import { translate } from "./util";
|
||||
|
||||
@@ -31,11 +31,6 @@ import { Account, AccountService } from "@bitwarden/common/auth/abstractions/acc
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { VendorId } from "@bitwarden/common/tools/extension";
|
||||
import {
|
||||
SemanticLogger,
|
||||
disabledSemanticLoggerProvider,
|
||||
ifEnabledSemanticLoggerProvider,
|
||||
} from "@bitwarden/common/tools/log";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { ToastService, Option } from "@bitwarden/components";
|
||||
import {
|
||||
@@ -55,6 +50,11 @@ import {
|
||||
Type,
|
||||
} from "@bitwarden/generator-core";
|
||||
import { GeneratorHistoryService } from "@bitwarden/generator-history";
|
||||
import {
|
||||
disabledSemanticLoggerProvider,
|
||||
ifEnabledSemanticLoggerProvider,
|
||||
SemanticLogger,
|
||||
} from "@bitwarden/logging";
|
||||
|
||||
import { translate } from "./util";
|
||||
|
||||
|
||||
@@ -2,4 +2,5 @@ export { CredentialGeneratorHistoryComponent } from "./credential-generator-hist
|
||||
export { CredentialGeneratorHistoryDialogComponent } from "./credential-generator-history-dialog.component";
|
||||
export { EmptyCredentialHistoryComponent } from "./empty-credential-history.component";
|
||||
export { GeneratorModule } from "./generator.module";
|
||||
export { GeneratorServicesModule, SYSTEM_SERVICE_PROVIDER } from "./generator-services.module";
|
||||
export { GeneratorServicesModule } from "./generator-services.module";
|
||||
export { LOG_PROVIDER } from "@bitwarden/angular/services/injection-tokens";
|
||||
|
||||
@@ -15,16 +15,16 @@ import { skip, takeUntil, Subject, map, withLatestFrom, ReplaySubject, tap } fro
|
||||
import { Account } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import {
|
||||
SemanticLogger,
|
||||
disabledSemanticLoggerProvider,
|
||||
ifEnabledSemanticLoggerProvider,
|
||||
} from "@bitwarden/common/tools/log";
|
||||
import {
|
||||
CredentialGeneratorService,
|
||||
PassphraseGenerationOptions,
|
||||
BuiltIn,
|
||||
} from "@bitwarden/generator-core";
|
||||
import {
|
||||
disabledSemanticLoggerProvider,
|
||||
ifEnabledSemanticLoggerProvider,
|
||||
SemanticLogger,
|
||||
} from "@bitwarden/logging";
|
||||
|
||||
const Controls = Object.freeze({
|
||||
numWords: "numWords",
|
||||
|
||||
@@ -27,11 +27,6 @@ import {
|
||||
import { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import {
|
||||
SemanticLogger,
|
||||
disabledSemanticLoggerProvider,
|
||||
ifEnabledSemanticLoggerProvider,
|
||||
} from "@bitwarden/common/tools/log";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { ToastService, Option } from "@bitwarden/components";
|
||||
import {
|
||||
@@ -49,6 +44,11 @@ import {
|
||||
Profile,
|
||||
} from "@bitwarden/generator-core";
|
||||
import { GeneratorHistoryService } from "@bitwarden/generator-history";
|
||||
import {
|
||||
disabledSemanticLoggerProvider,
|
||||
ifEnabledSemanticLoggerProvider,
|
||||
SemanticLogger,
|
||||
} from "@bitwarden/logging";
|
||||
|
||||
import { toAlgorithmInfo, translate } from "./util";
|
||||
|
||||
|
||||
@@ -32,11 +32,6 @@ import { Account, AccountService } from "@bitwarden/common/auth/abstractions/acc
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { VendorId } from "@bitwarden/common/tools/extension";
|
||||
import {
|
||||
SemanticLogger,
|
||||
disabledSemanticLoggerProvider,
|
||||
ifEnabledSemanticLoggerProvider,
|
||||
} from "@bitwarden/common/tools/log";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { ToastService, Option } from "@bitwarden/components";
|
||||
import {
|
||||
@@ -55,6 +50,11 @@ import {
|
||||
Algorithm,
|
||||
} from "@bitwarden/generator-core";
|
||||
import { GeneratorHistoryService } from "@bitwarden/generator-history";
|
||||
import {
|
||||
disabledSemanticLoggerProvider,
|
||||
ifEnabledSemanticLoggerProvider,
|
||||
SemanticLogger,
|
||||
} from "@bitwarden/logging";
|
||||
|
||||
import { toAlgorithmInfo, translate } from "./util";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { SemanticLogger } from "@bitwarden/common/tools/log";
|
||||
import { UserStateSubjectDependencyProvider } from "@bitwarden/common/tools/state/user-state-subject-dependency-provider";
|
||||
import { Constraints, StateConstraints } from "@bitwarden/common/tools/types";
|
||||
import { SemanticLogger } from "@bitwarden/logging";
|
||||
|
||||
import { CredentialAlgorithm, CredentialType } from "../metadata";
|
||||
import { CredentialPreference } from "../types";
|
||||
|
||||
@@ -5,7 +5,6 @@ import { PolicyService } from "@bitwarden/common/admin-console/abstractions/poli
|
||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
|
||||
import { Account } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { LegacyEncryptorProvider } from "@bitwarden/common/tools/cryptography/legacy-encryptor-provider";
|
||||
import { UserEncryptor } from "@bitwarden/common/tools/cryptography/user-encryptor.abstraction";
|
||||
import {
|
||||
@@ -17,13 +16,11 @@ import {
|
||||
} from "@bitwarden/common/tools/extension";
|
||||
import { ExtensionService } from "@bitwarden/common/tools/extension/extension.service";
|
||||
import { Bitwarden } from "@bitwarden/common/tools/extension/vendor/bitwarden";
|
||||
import { disabledSemanticLoggerProvider } from "@bitwarden/common/tools/log";
|
||||
import { SystemServiceProvider } from "@bitwarden/common/tools/providers";
|
||||
import { UserStateSubject } from "@bitwarden/common/tools/state/user-state-subject";
|
||||
import { UserStateSubjectDependencyProvider } from "@bitwarden/common/tools/state/user-state-subject-dependency-provider";
|
||||
import { deepFreeze } from "@bitwarden/common/tools/util";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { BitwardenClient } from "@bitwarden/sdk-internal";
|
||||
import { disabledSemanticLoggerProvider } from "@bitwarden/logging";
|
||||
|
||||
import { FakeAccountService, FakeStateProvider } from "../../../../../common/spec";
|
||||
import { Algorithm, AlgorithmsByType, CredentialAlgorithm, Type, Types } from "../metadata";
|
||||
@@ -91,27 +88,6 @@ const SomePolicyService = mock<PolicyService>();
|
||||
|
||||
const SomeExtensionService = mock<ExtensionService>();
|
||||
|
||||
const SomeConfigService = mock<ConfigService>;
|
||||
|
||||
const SomeSdkService = mock<BitwardenClient>;
|
||||
|
||||
const ApplicationProvider = {
|
||||
/** Policy configured by the administrative console */
|
||||
policy: SomePolicyService,
|
||||
|
||||
/** Client extension metadata and profile access */
|
||||
extension: SomeExtensionService,
|
||||
|
||||
/** Event monitoring and diagnostic interfaces */
|
||||
log: disabledSemanticLoggerProvider,
|
||||
|
||||
/** Feature flag retrieval */
|
||||
configService: SomeConfigService,
|
||||
|
||||
/** SDK access for password generation */
|
||||
sdk: SomeSdkService,
|
||||
} as unknown as SystemServiceProvider;
|
||||
|
||||
describe("GeneratorMetadataProvider", () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
@@ -121,17 +97,26 @@ describe("GeneratorMetadataProvider", () => {
|
||||
describe("constructor", () => {
|
||||
it("throws when the forwarder site isn't defined by the extension service", () => {
|
||||
SomeExtensionService.site.mockReturnValue(undefined);
|
||||
expect(() => new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, [])).toThrow(
|
||||
"forwarder extension site not found",
|
||||
);
|
||||
expect(
|
||||
() =>
|
||||
new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[],
|
||||
),
|
||||
).toThrow("forwarder extension site not found");
|
||||
});
|
||||
});
|
||||
|
||||
describe("metadata", () => {
|
||||
it("returns algorithm metadata", async () => {
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, [
|
||||
password,
|
||||
]);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[password],
|
||||
);
|
||||
|
||||
const metadata = provider.metadata(password.id);
|
||||
|
||||
@@ -145,13 +130,15 @@ describe("GeneratorMetadataProvider", () => {
|
||||
host: { authentication: true, selfHost: "maybe", baseUrl: "https://www.example.com" },
|
||||
requestedFields: [],
|
||||
};
|
||||
const application = {
|
||||
...ApplicationProvider,
|
||||
extension: mock<ExtensionService>({
|
||||
site: () => new ExtensionSite(SomeSite, new Map([[Bitwarden.id, extensionMetadata]])),
|
||||
}),
|
||||
};
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, application, []);
|
||||
const extension = mock<ExtensionService>({
|
||||
site: () => new ExtensionSite(SomeSite, new Map([[Bitwarden.id, extensionMetadata]])),
|
||||
});
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
extension,
|
||||
[],
|
||||
);
|
||||
|
||||
const metadata = provider.metadata({ forwarder: Bitwarden.id });
|
||||
|
||||
@@ -159,13 +146,23 @@ describe("GeneratorMetadataProvider", () => {
|
||||
});
|
||||
|
||||
it("panics when metadata not found", async () => {
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, []);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[],
|
||||
);
|
||||
|
||||
expect(() => provider.metadata("not found" as any)).toThrow("metadata not found");
|
||||
});
|
||||
|
||||
it("panics when an extension not found", async () => {
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, []);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[],
|
||||
);
|
||||
|
||||
expect(() => provider.metadata({ forwarder: "not found" as any })).toThrow(
|
||||
"extension not found",
|
||||
@@ -175,7 +172,12 @@ describe("GeneratorMetadataProvider", () => {
|
||||
|
||||
describe("types", () => {
|
||||
it("returns the credential types", async () => {
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, []);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[],
|
||||
);
|
||||
|
||||
const result = provider.types();
|
||||
|
||||
@@ -185,7 +187,12 @@ describe("GeneratorMetadataProvider", () => {
|
||||
|
||||
describe("algorithms", () => {
|
||||
it("returns the password category's algorithms", () => {
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, []);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[],
|
||||
);
|
||||
|
||||
const result = provider.algorithms({ type: Type.password });
|
||||
|
||||
@@ -193,7 +200,12 @@ describe("GeneratorMetadataProvider", () => {
|
||||
});
|
||||
|
||||
it("returns the username category's algorithms", () => {
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, []);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[],
|
||||
);
|
||||
|
||||
const result = provider.algorithms({ type: Type.username });
|
||||
|
||||
@@ -201,7 +213,12 @@ describe("GeneratorMetadataProvider", () => {
|
||||
});
|
||||
|
||||
it("returns the email category's algorithms", () => {
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, []);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[],
|
||||
);
|
||||
|
||||
const result = provider.algorithms({ type: Type.email });
|
||||
|
||||
@@ -215,13 +232,15 @@ describe("GeneratorMetadataProvider", () => {
|
||||
host: { authentication: true, selfHost: "maybe", baseUrl: "https://www.example.com" },
|
||||
requestedFields: [],
|
||||
};
|
||||
const application = {
|
||||
...ApplicationProvider,
|
||||
extension: mock<ExtensionService>({
|
||||
site: () => new ExtensionSite(SomeSite, new Map([[Bitwarden.id, extensionMetadata]])),
|
||||
}),
|
||||
};
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, application, []);
|
||||
const extension = mock<ExtensionService>({
|
||||
site: () => new ExtensionSite(SomeSite, new Map([[Bitwarden.id, extensionMetadata]])),
|
||||
});
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
extension,
|
||||
[],
|
||||
);
|
||||
|
||||
const result = provider.algorithms({ type: Type.email });
|
||||
|
||||
@@ -235,7 +254,12 @@ describe("GeneratorMetadataProvider", () => {
|
||||
[Algorithm.plusAddress],
|
||||
[Algorithm.username],
|
||||
])("returns explicit algorithms (=%p)", (algorithm) => {
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, []);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[],
|
||||
);
|
||||
|
||||
const result = provider.algorithms({ algorithm });
|
||||
|
||||
@@ -249,13 +273,15 @@ describe("GeneratorMetadataProvider", () => {
|
||||
host: { authentication: true, selfHost: "maybe", baseUrl: "https://www.example.com" },
|
||||
requestedFields: [],
|
||||
};
|
||||
const application = {
|
||||
...ApplicationProvider,
|
||||
extension: mock<ExtensionService>({
|
||||
site: () => new ExtensionSite(SomeSite, new Map([[Bitwarden.id, extensionMetadata]])),
|
||||
}),
|
||||
};
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, application, []);
|
||||
const extension = mock<ExtensionService>({
|
||||
site: () => new ExtensionSite(SomeSite, new Map([[Bitwarden.id, extensionMetadata]])),
|
||||
});
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
extension,
|
||||
[],
|
||||
);
|
||||
|
||||
const result = provider.algorithms({ algorithm: { forwarder: Bitwarden.id } });
|
||||
|
||||
@@ -263,7 +289,12 @@ describe("GeneratorMetadataProvider", () => {
|
||||
});
|
||||
|
||||
it("returns an empty array when the algorithm is invalid", () => {
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, []);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[],
|
||||
);
|
||||
|
||||
// `any` cast required because this test subverts the type system
|
||||
const result = provider.algorithms({ algorithm: "an invalid algorithm" as any });
|
||||
@@ -278,13 +309,15 @@ describe("GeneratorMetadataProvider", () => {
|
||||
host: { authentication: true, selfHost: "maybe", baseUrl: "https://www.example.com" },
|
||||
requestedFields: [],
|
||||
};
|
||||
const application = {
|
||||
...ApplicationProvider,
|
||||
extension: mock<ExtensionService>({
|
||||
site: () => new ExtensionSite(SomeSite, new Map([[Bitwarden.id, extensionMetadata]])),
|
||||
}),
|
||||
};
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, application, []);
|
||||
const extension = mock<ExtensionService>({
|
||||
site: () => new ExtensionSite(SomeSite, new Map([[Bitwarden.id, extensionMetadata]])),
|
||||
});
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
extension,
|
||||
[],
|
||||
);
|
||||
|
||||
// `any` cast required because this test subverts the type system
|
||||
const result = provider.algorithms({
|
||||
@@ -295,7 +328,12 @@ describe("GeneratorMetadataProvider", () => {
|
||||
});
|
||||
|
||||
it("panics when neither an algorithm nor a category is specified", () => {
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, []);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[],
|
||||
);
|
||||
|
||||
// `any` cast required because this test subverts the type system
|
||||
expect(() => provider.algorithms({} as any)).toThrow("algorithm or type required");
|
||||
@@ -309,9 +347,12 @@ describe("GeneratorMetadataProvider", () => {
|
||||
[Algorithm.password, password],
|
||||
])("gets a specific algorithm", async (algorithm, metadata) => {
|
||||
SomePolicyService.policiesByType$.mockReturnValue(new BehaviorSubject([]));
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, [
|
||||
metadata,
|
||||
]);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[metadata],
|
||||
);
|
||||
const result = new ReplaySubject<CredentialAlgorithm[]>(1);
|
||||
|
||||
provider.algorithms$({ algorithm }, { account$: SomeAccount$ }).subscribe(result);
|
||||
@@ -325,7 +366,12 @@ describe("GeneratorMetadataProvider", () => {
|
||||
[Type.password, [password, passphrase]],
|
||||
])("gets a category of algorithms", async (category, metadata) => {
|
||||
SomePolicyService.policiesByType$.mockReturnValue(new BehaviorSubject([]));
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, metadata);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
metadata,
|
||||
);
|
||||
const result = new ReplaySubject<CredentialAlgorithm[]>(1);
|
||||
|
||||
provider.algorithms$({ type: category }, { account$: SomeAccount$ }).subscribe(result);
|
||||
@@ -344,7 +390,12 @@ describe("GeneratorMetadataProvider", () => {
|
||||
} as any);
|
||||
SomePolicyService.policiesByType$.mockReturnValue(new BehaviorSubject([policy]));
|
||||
const metadata = [password, passphrase];
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, metadata);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
metadata,
|
||||
);
|
||||
const algorithmResult = new ReplaySubject<CredentialAlgorithm[]>(1);
|
||||
const categoryResult = new ReplaySubject<CredentialAlgorithm[]>(1);
|
||||
|
||||
@@ -361,9 +412,12 @@ describe("GeneratorMetadataProvider", () => {
|
||||
|
||||
it("omits algorithms whose metadata is unavailable", async () => {
|
||||
SomePolicyService.policiesByType$.mockReturnValue(new BehaviorSubject([]));
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, [
|
||||
password,
|
||||
]);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[password],
|
||||
);
|
||||
const algorithmResult = new ReplaySubject<CredentialAlgorithm[]>(1);
|
||||
const categoryResult = new ReplaySubject<CredentialAlgorithm[]>(1);
|
||||
|
||||
@@ -379,7 +433,12 @@ describe("GeneratorMetadataProvider", () => {
|
||||
});
|
||||
|
||||
it("panics when neither algorithm nor category are specified", () => {
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, []);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[],
|
||||
);
|
||||
|
||||
expect(() => provider.algorithms$({} as any, { account$: SomeAccount$ })).toThrow(
|
||||
"algorithm or type required",
|
||||
@@ -403,9 +462,12 @@ describe("GeneratorMetadataProvider", () => {
|
||||
[Type.password, password],
|
||||
])("emits the user's %s preference", async (type, metadata) => {
|
||||
SomePolicyService.policiesByType$.mockReturnValue(new BehaviorSubject([]));
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, [
|
||||
metadata,
|
||||
]);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[metadata],
|
||||
);
|
||||
const result = new ReplaySubject<CredentialAlgorithm | undefined>(1);
|
||||
|
||||
provider.preference$(type, { account$: SomeAccount$ }).subscribe(result);
|
||||
@@ -415,9 +477,12 @@ describe("GeneratorMetadataProvider", () => {
|
||||
|
||||
it("emits a default when the user's preference is unavailable", async () => {
|
||||
SomePolicyService.policiesByType$.mockReturnValue(new BehaviorSubject([]));
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, [
|
||||
plusAddress,
|
||||
]);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[plusAddress],
|
||||
);
|
||||
const result = new ReplaySubject<CredentialAlgorithm | undefined>(1);
|
||||
|
||||
// precondition: the preferred email is excluded from the provided metadata
|
||||
@@ -430,7 +495,12 @@ describe("GeneratorMetadataProvider", () => {
|
||||
|
||||
it("emits the original preference when the user's preference is unavailable and there is no metadata", async () => {
|
||||
SomePolicyService.policiesByType$.mockReturnValue(new BehaviorSubject([]));
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, []);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[],
|
||||
);
|
||||
const result = new ReplaySubject<CredentialAlgorithm | undefined>(1);
|
||||
|
||||
provider.preference$(Type.email, { account$: SomeAccount$ }).subscribe(result);
|
||||
@@ -441,7 +511,12 @@ describe("GeneratorMetadataProvider", () => {
|
||||
|
||||
describe("preferences", () => {
|
||||
it("returns a user state subject", () => {
|
||||
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, []);
|
||||
const provider = new GeneratorMetadataProvider(
|
||||
SystemProvider,
|
||||
SomePolicyService,
|
||||
SomeExtensionService,
|
||||
[],
|
||||
);
|
||||
|
||||
const subject = provider.preferences({ account$: SomeAccount$ });
|
||||
|
||||
|
||||
@@ -8,12 +8,12 @@ import { Account } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { GENERATOR_DISK, UserKeyDefinition } from "@bitwarden/common/platform/state";
|
||||
import { LegacyEncryptorProvider } from "@bitwarden/common/tools/cryptography/legacy-encryptor-provider";
|
||||
import { UserEncryptor } from "@bitwarden/common/tools/cryptography/user-encryptor.abstraction";
|
||||
import { disabledSemanticLoggerProvider } from "@bitwarden/common/tools/log";
|
||||
import { PrivateClassifier } from "@bitwarden/common/tools/private-classifier";
|
||||
import { IdentityConstraint } from "@bitwarden/common/tools/state/identity-state-constraint";
|
||||
import { UserStateSubjectDependencyProvider } from "@bitwarden/common/tools/state/user-state-subject-dependency-provider";
|
||||
import { StateConstraints } from "@bitwarden/common/tools/types";
|
||||
import { OrganizationId, PolicyId, UserId } from "@bitwarden/common/types/guid";
|
||||
import { disabledSemanticLoggerProvider } from "@bitwarden/logging";
|
||||
|
||||
import { FakeStateProvider, FakeAccountService, awaitAsync } from "../../../../../common/spec";
|
||||
import { CoreProfileMetadata, ProfileContext } from "../metadata/profile-metadata";
|
||||
|
||||
@@ -12,10 +12,10 @@ import {
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { Account } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { BoundDependency } from "@bitwarden/common/tools/dependencies";
|
||||
import { SemanticLogger } from "@bitwarden/common/tools/log";
|
||||
import { anyComplete } from "@bitwarden/common/tools/rx";
|
||||
import { UserStateSubject } from "@bitwarden/common/tools/state/user-state-subject";
|
||||
import { UserStateSubjectDependencyProvider } from "@bitwarden/common/tools/state/user-state-subject-dependency-provider";
|
||||
import { SemanticLogger } from "@bitwarden/logging";
|
||||
|
||||
import { ProfileContext, CoreProfileMetadata, ProfileMetadata } from "../metadata";
|
||||
import { GeneratorConstraints } from "../types/generator-constraints";
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { mock } from "jest-mock-extended";
|
||||
import { BehaviorSubject, Subject, firstValueFrom, of } from "rxjs";
|
||||
|
||||
import { Account } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service";
|
||||
import { Site, VendorId } from "@bitwarden/common/tools/extension";
|
||||
import { Bitwarden } from "@bitwarden/common/tools/extension/vendor/bitwarden";
|
||||
import { Vendor } from "@bitwarden/common/tools/extension/vendor/data";
|
||||
import { SemanticLogger, ifEnabledSemanticLoggerProvider } from "@bitwarden/common/tools/log";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { LogProvider, SemanticLogger } from "@bitwarden/logging";
|
||||
|
||||
import { awaitAsync } from "../../../../../common/spec";
|
||||
import {
|
||||
@@ -40,16 +40,20 @@ type MockTwoLevelPartial<T> = {
|
||||
describe("DefaultCredentialGeneratorService", () => {
|
||||
let service: DefaultCredentialGeneratorService;
|
||||
let providers: MockTwoLevelPartial<CredentialGeneratorProviders>;
|
||||
let system: any;
|
||||
let log: SemanticLogger;
|
||||
let mockExtension: { settings: jest.Mock };
|
||||
let mockLogger: SemanticLogger;
|
||||
let logProvider: LogProvider;
|
||||
let account: Account;
|
||||
let createService: (overrides?: any) => DefaultCredentialGeneratorService;
|
||||
|
||||
beforeEach(() => {
|
||||
log = ifEnabledSemanticLoggerProvider(false, new ConsoleLogService(true), {
|
||||
from: "DefaultCredentialGeneratorService tests",
|
||||
});
|
||||
mockLogger = mock<SemanticLogger>();
|
||||
// Override panic to throw errors as expected by tests
|
||||
mockLogger.panic = jest.fn((context: any, msg?: string) => {
|
||||
const errorMsg = msg || (typeof context === "string" ? context : context?.message || "panic");
|
||||
throw new Error(errorMsg);
|
||||
}) as any;
|
||||
logProvider = () => mockLogger;
|
||||
|
||||
mockExtension = { settings: jest.fn() };
|
||||
|
||||
@@ -61,11 +65,6 @@ describe("DefaultCredentialGeneratorService", () => {
|
||||
name: "Test User",
|
||||
};
|
||||
|
||||
system = {
|
||||
log: jest.fn().mockReturnValue(log),
|
||||
extension: mockExtension,
|
||||
};
|
||||
|
||||
providers = {
|
||||
metadata: {
|
||||
metadata: jest.fn(),
|
||||
@@ -87,7 +86,11 @@ describe("DefaultCredentialGeneratorService", () => {
|
||||
// similar to how the overrides are applied
|
||||
const providersCast = providers as unknown as CredentialGeneratorProviders;
|
||||
|
||||
const instance = new DefaultCredentialGeneratorService(providersCast, system);
|
||||
const instance = new DefaultCredentialGeneratorService(
|
||||
providersCast,
|
||||
mockExtension as any,
|
||||
logProvider,
|
||||
);
|
||||
Object.assign(instance, overrides);
|
||||
return instance;
|
||||
};
|
||||
|
||||
@@ -18,10 +18,10 @@ import {
|
||||
import { Account } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { BoundDependency, OnDependency } from "@bitwarden/common/tools/dependencies";
|
||||
import { VendorId } from "@bitwarden/common/tools/extension";
|
||||
import { SemanticLogger } from "@bitwarden/common/tools/log";
|
||||
import { SystemServiceProvider } from "@bitwarden/common/tools/providers";
|
||||
import { ExtensionService } from "@bitwarden/common/tools/extension/extension.service";
|
||||
import { anyComplete, memoizedMap } from "@bitwarden/common/tools/rx";
|
||||
import { UserStateSubject } from "@bitwarden/common/tools/state/user-state-subject";
|
||||
import { LogProvider, SemanticLogger } from "@bitwarden/logging";
|
||||
|
||||
import { CredentialGeneratorService } from "../abstractions";
|
||||
import {
|
||||
@@ -43,13 +43,15 @@ const THREE_MINUTES = 3 * 60 * 1000;
|
||||
export class DefaultCredentialGeneratorService implements CredentialGeneratorService {
|
||||
/** Instantiate the `DefaultCredentialGeneratorService`.
|
||||
* @param provide application services required by the credential generator.
|
||||
* @param system low-level services required by the credential generator.
|
||||
* @param extension service for managing forwarder extensions.
|
||||
* @param log factory for creating semantic loggers.
|
||||
*/
|
||||
constructor(
|
||||
private readonly provide: CredentialGeneratorProviders,
|
||||
private readonly system: SystemServiceProvider,
|
||||
private readonly extension: ExtensionService,
|
||||
log: LogProvider,
|
||||
) {
|
||||
this.log = system.log({ type: "DefaultCredentialGeneratorService" });
|
||||
this.log = log({ type: "DefaultCredentialGeneratorService" });
|
||||
}
|
||||
|
||||
private readonly log: SemanticLogger;
|
||||
@@ -192,7 +194,7 @@ export class DefaultCredentialGeneratorService implements CredentialGeneratorSer
|
||||
}
|
||||
|
||||
this.log.info({ profile, vendor, site: activeProfile.site }, "loading extension profile");
|
||||
settings = this.system.extension.settings(activeProfile, vendor, dependencies);
|
||||
settings = this.extension.settings(activeProfile, vendor, dependencies);
|
||||
} else {
|
||||
this.log.info({ profile, algorithm: metadata.id }, "loading generator profile");
|
||||
settings = this.provide.profile.settings(activeProfile, dependencies);
|
||||
|
||||
Reference in New Issue
Block a user