1
0
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:
John Harrington
2025-10-10 07:43:36 -07:00
parent c0d15c19d4
commit b8eaa483ee
31 changed files with 405 additions and 192 deletions

View File

@@ -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";

View File

@@ -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",
});
});

View File

@@ -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) {

View File

@@ -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(() =>

View File

@@ -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) {

View File

@@ -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<

View File

@@ -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";

View File

@@ -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";

View File

@@ -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 {

View File

@@ -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";

View File

@@ -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";

View File

@@ -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;

View File

@@ -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",
);
});
});
});
});

View File

@@ -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";

View File

@@ -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";

View File

@@ -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";

View File

@@ -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";

View File

@@ -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",

View File

@@ -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";

View File

@@ -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";

View File

@@ -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";

View File

@@ -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$ });

View File

@@ -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";

View File

@@ -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";

View File

@@ -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;
};

View File

@@ -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);