1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-06 10:33:57 +00:00

Platform/pm 19/platform team file moves (#5460)

* Rename service-factory folder

* Move cryptographic service factories

* Move crypto models

* Move crypto services

* Move domain base class

* Platform code owners

* Move desktop log services

* Move log files

* Establish component library ownership

* Move background listeners

* Move background background

* Move localization to Platform

* Move browser alarms to Platform

* Move browser state to Platform

* Move CLI state to Platform

* Move Desktop native concerns to Platform

* Move flag and misc to Platform

* Lint fixes

* Move electron state to platform

* Move web state to Platform

* Move lib state to Platform

* Fix broken tests

* Rename interface to idiomatic TS

* `npm run prettier` 🤖

* Resolve review feedback

* Set platform as owners of web core and shared

* Expand moved services

* Fix test types

---------

Co-authored-by: Hinton <hinton@users.noreply.github.com>
This commit is contained in:
Matt Gibson
2023-06-06 15:34:53 -05:00
committed by GitHub
parent ce4fc31efd
commit 78248db590
869 changed files with 2840 additions and 2746 deletions

View File

@@ -1,60 +0,0 @@
import { systemPreferences } from "electron";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { passwords } from "@bitwarden/desktop-native";
import { OsBiometricService } from "./biometrics.service.abstraction";
export default class BiometricDarwinMain implements OsBiometricService {
constructor(private i18nservice: I18nService, private stateService: StateService) {}
async init() {
await this.stateService.setBiometricText("unlockWithTouchId");
await this.stateService.setNoAutoPromptBiometricsText("autoPromptTouchId");
}
async osSupportsBiometric(): Promise<boolean> {
return systemPreferences.canPromptTouchID();
}
async authenticateBiometric(): Promise<boolean> {
try {
await systemPreferences.promptTouchID(this.i18nservice.t("touchIdConsentMessage"));
return true;
} catch {
return false;
}
}
async getBiometricKey(service: string, key: string): Promise<string | null> {
const success = await this.authenticateBiometric();
if (!success) {
throw new Error("Biometric authentication failed");
}
return await passwords.getPassword(service, key);
}
async setBiometricKey(service: string, key: string, value: string): Promise<void> {
if (await this.valueUpToDate(service, key, value)) {
return;
}
return await passwords.setPassword(service, key, value);
}
async deleteBiometricKey(service: string, key: string): Promise<void> {
return await passwords.deletePassword(service, key);
}
private async valueUpToDate(service: string, key: string, value: string): Promise<boolean> {
try {
const existing = await passwords.getPassword(service, key);
return existing === value;
} catch {
return false;
}
}
}

View File

@@ -1,224 +0,0 @@
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { EncString } from "@bitwarden/common/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetric-crypto-key";
import { biometrics, passwords } from "@bitwarden/desktop-native";
import { ElectronStateService } from "../../services/electron-state.service.abstraction";
import { WindowMain } from "../window.main";
import { OsBiometricService } from "./biometrics.service.abstraction";
const KEY_WITNESS_SUFFIX = "_witness";
const WITNESS_VALUE = "known key";
export default class BiometricWindowsMain implements OsBiometricService {
// Use set helper method instead of direct access
private _iv: string | null = null;
// Use getKeyMaterial helper instead of direct access
private _osKeyHalf: string | null = null;
constructor(
private i18nService: I18nService,
private windowMain: WindowMain,
private stateService: ElectronStateService,
private logService: LogService
) {}
async init() {
await this.stateService.setBiometricText("unlockWithWindowsHello");
await this.stateService.setNoAutoPromptBiometricsText("autoPromptWindowsHello");
}
async osSupportsBiometric(): Promise<boolean> {
return await biometrics.available();
}
async getBiometricKey(
service: string,
storageKey: string,
clientKeyHalfB64: string
): Promise<string | null> {
const value = await passwords.getPassword(service, storageKey);
if (value == null || value == "") {
return null;
} else if (!EncString.isSerializedEncString(value)) {
// Update to format encrypted with client key half
const storageDetails = await this.getStorageDetails({
clientKeyHalfB64,
});
await biometrics.setBiometricSecret(
service,
storageKey,
value,
storageDetails.key_material,
storageDetails.ivB64
);
return value;
} else {
const encValue = new EncString(value);
this.setIv(encValue.iv);
const storageDetails = await this.getStorageDetails({
clientKeyHalfB64,
});
return await biometrics.getBiometricSecret(service, storageKey, storageDetails.key_material);
}
}
async setBiometricKey(
service: string,
storageKey: string,
value: string,
clientKeyPartB64: string | undefined
): Promise<void> {
const parsedValue = SymmetricCryptoKey.fromString(value);
if (await this.valueUpToDate({ value: parsedValue, clientKeyPartB64, service, storageKey })) {
return;
}
const storageDetails = await this.getStorageDetails({ clientKeyHalfB64: clientKeyPartB64 });
const storedValue = await biometrics.setBiometricSecret(
service,
storageKey,
value,
storageDetails.key_material,
storageDetails.ivB64
);
const parsedStoredValue = new EncString(storedValue);
await this.storeValueWitness(
parsedValue,
parsedStoredValue,
service,
storageKey,
clientKeyPartB64
);
}
async deleteBiometricKey(service: string, key: string): Promise<void> {
await passwords.deletePassword(service, key);
await passwords.deletePassword(service, key + KEY_WITNESS_SUFFIX);
}
async authenticateBiometric(): Promise<boolean> {
const hwnd = this.windowMain.win.getNativeWindowHandle();
return await biometrics.prompt(hwnd, this.i18nService.t("windowsHelloConsentMessage"));
}
private async getStorageDetails({
clientKeyHalfB64,
}: {
clientKeyHalfB64: string;
}): Promise<{ key_material: biometrics.KeyMaterial; ivB64: string }> {
if (this._osKeyHalf == null) {
// Prompts Windows Hello
const keyMaterial = await biometrics.deriveKeyMaterial(this._iv);
this._osKeyHalf = keyMaterial.keyB64;
this._iv = keyMaterial.ivB64;
}
return {
key_material: {
osKeyPartB64: this._osKeyHalf,
clientKeyPartB64: clientKeyHalfB64,
},
ivB64: this._iv,
};
}
// Nulls out key material in order to force a re-derive. This should only be used in getBiometricKey
// when we want to force a re-derive of the key material.
private setIv(iv: string) {
this._iv = iv;
this._osKeyHalf = null;
}
/**
* Stores a witness key alongside the encrypted value. This is used to determine if the value is up to date.
*
* @param unencryptedValue The key to store
* @param encryptedValue The encrypted value of the key to store. Used to sync IV of the witness key with the stored key.
* @param service The service to store the witness key under
* @param storageKey The key to store the witness key under. The witness key will be stored under storageKey + {@link KEY_WITNESS_SUFFIX}
* @returns
*/
private async storeValueWitness(
unencryptedValue: SymmetricCryptoKey,
encryptedValue: EncString,
service: string,
storageKey: string,
clientKeyPartB64: string
) {
if (encryptedValue.iv == null || encryptedValue == null) {
return;
}
const storageDetails = {
keyMaterial: this.witnessKeyMaterial(unencryptedValue, clientKeyPartB64),
ivB64: encryptedValue.iv,
};
await biometrics.setBiometricSecret(
service,
storageKey + KEY_WITNESS_SUFFIX,
WITNESS_VALUE,
storageDetails.keyMaterial,
storageDetails.ivB64
);
}
/**
* Uses a witness key stored alongside the encrypted value to determine if the value is up to date.
* @param value The value being validated
* @param service The service the value is stored under
* @param storageKey The key the value is stored under. The witness key will be stored under storageKey + {@link KEY_WITNESS_SUFFIX}
* @returns Boolean indicating if the value is up to date.
*/
// Uses a witness key stored alongside the encrypted value to determine if the value is up to date.
private async valueUpToDate({
value,
clientKeyPartB64,
service,
storageKey,
}: {
value: SymmetricCryptoKey;
clientKeyPartB64: string;
service: string;
storageKey: string;
}): Promise<boolean> {
const witnessKeyMaterial = this.witnessKeyMaterial(value, clientKeyPartB64);
if (witnessKeyMaterial == null) {
return false;
}
let witness = null;
try {
witness = await biometrics.getBiometricSecret(
service,
storageKey + KEY_WITNESS_SUFFIX,
witnessKeyMaterial
);
} catch {
this.logService.debug("Error retrieving witness key, assuming value is not up to date.");
return false;
}
if (witness === WITNESS_VALUE) {
return true;
}
return false;
}
/** Derives a witness key from a symmetric key being stored for biometric protection */
private witnessKeyMaterial(
symmetricKey: SymmetricCryptoKey,
clientKeyPartB64: string
): biometrics.KeyMaterial {
const key = symmetricKey?.macKeyB64 ?? symmetricKey?.keyB64;
return {
osKeyPartB64: key,
clientKeyPartB64,
};
}
}

View File

@@ -1,44 +0,0 @@
export abstract class BiometricsServiceAbstraction {
init: () => Promise<void>;
osSupportsBiometric: () => Promise<boolean>;
canAuthBiometric: ({
service,
key,
userId,
}: {
service: string;
key: string;
userId: string;
}) => Promise<boolean>;
authenticateBiometric: () => Promise<boolean>;
getBiometricKey: (service: string, key: string) => Promise<string | null>;
setBiometricKey: (service: string, key: string, value: string) => Promise<void>;
setEncryptionKeyHalf: ({
service,
key,
value,
}: {
service: string;
key: string;
value: string;
}) => void;
deleteBiometricKey: (service: string, key: string) => Promise<void>;
}
export interface OsBiometricService {
init: () => Promise<void>;
osSupportsBiometric: () => Promise<boolean>;
authenticateBiometric: () => Promise<boolean>;
getBiometricKey: (
service: string,
key: string,
clientKeyHalfB64: string | undefined
) => Promise<string | null>;
setBiometricKey: (
service: string,
key: string,
value: string,
clientKeyHalfB64: string | undefined
) => Promise<void>;
deleteBiometricKey: (service: string, key: string) => Promise<void>;
}

View File

@@ -1,128 +0,0 @@
import { mock, MockProxy } from "jest-mock-extended";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { ElectronStateService } from "../../services/electron-state.service.abstraction";
import { WindowMain } from "../window.main";
import BiometricDarwinMain from "./biometric.darwin.main";
import BiometricWindowsMain from "./biometric.windows.main";
import { BiometricsService } from "./biometrics.service";
import { OsBiometricService } from "./biometrics.service.abstraction";
jest.mock("@bitwarden/desktop-native", () => {
return {
biometrics: jest.fn(),
passwords: jest.fn(),
};
});
describe("biometrics tests", function () {
const i18nService = mock<I18nService>();
const windowMain = mock<WindowMain>();
const stateService = mock<ElectronStateService>();
const logService = mock<LogService>();
const messagingService = mock<MessagingService>();
it("Should call the platformspecific methods", async () => {
const sut = new BiometricsService(
i18nService,
windowMain,
stateService,
logService,
messagingService,
process.platform
);
const mockService = mock<OsBiometricService>();
(sut as any).platformSpecificService = mockService;
sut.init();
sut.setEncryptionKeyHalf({ service: "test", key: "test", value: "test" });
expect(mockService.init).toBeCalled();
await sut.canAuthBiometric({ service: "test", key: "test", userId: "test" });
expect(mockService.osSupportsBiometric).toBeCalled();
sut.authenticateBiometric();
expect(mockService.authenticateBiometric).toBeCalled();
});
describe("Should create a platform specific service", function () {
it("Should create a biometrics service specific for Windows", () => {
const sut = new BiometricsService(
i18nService,
windowMain,
stateService,
logService,
messagingService,
"win32"
);
const internalService = (sut as any).platformSpecificService;
expect(internalService).not.toBeNull();
expect(internalService).toBeInstanceOf(BiometricWindowsMain);
});
it("Should create a biometrics service specific for MacOs", () => {
const sut = new BiometricsService(
i18nService,
windowMain,
stateService,
logService,
messagingService,
"darwin"
);
const internalService = (sut as any).platformSpecificService;
expect(internalService).not.toBeNull();
expect(internalService).toBeInstanceOf(BiometricDarwinMain);
});
});
describe("can auth biometric", () => {
let sut: BiometricsService;
let innerService: MockProxy<OsBiometricService>;
beforeEach(() => {
sut = new BiometricsService(
i18nService,
windowMain,
stateService,
logService,
messagingService,
process.platform
);
innerService = mock();
(sut as any).platformSpecificService = innerService;
sut.init();
});
it("should return false if client key half is required and not provided", async () => {
stateService.getBiometricRequirePasswordOnStart.mockResolvedValue(true);
const result = await sut.canAuthBiometric({ service: "test", key: "test", userId: "test" });
expect(result).toBe(false);
});
it("should call osSupportsBiometric if client key half is provided", async () => {
sut.setEncryptionKeyHalf({ service: "test", key: "test", value: "test" });
expect(innerService.init).toBeCalled();
await sut.canAuthBiometric({ service: "test", key: "test", userId: "test" });
expect(innerService.osSupportsBiometric).toBeCalled();
});
it("should call osSupportBiometric if client key half is not required", async () => {
stateService.getBiometricRequirePasswordOnStart.mockResolvedValue(false);
innerService.osSupportsBiometric.mockResolvedValue(true);
const result = await sut.canAuthBiometric({ service: "test", key: "test", userId: "test" });
expect(result).toBe(true);
expect(innerService.osSupportsBiometric).toBeCalled();
});
});
});

View File

@@ -1,171 +0,0 @@
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { ElectronStateService } from "../../services/electron-state.service.abstraction";
import { WindowMain } from "../window.main";
import { BiometricsServiceAbstraction, OsBiometricService } from "./biometrics.service.abstraction";
export class BiometricsService implements BiometricsServiceAbstraction {
private platformSpecificService: OsBiometricService;
private clientKeyHalves = new Map<string, string>();
constructor(
private i18nService: I18nService,
private windowMain: WindowMain,
private stateService: ElectronStateService,
private logService: LogService,
private messagingService: MessagingService,
private platform: NodeJS.Platform
) {
this.loadPlatformSpecificService(this.platform);
}
private loadPlatformSpecificService(platform: NodeJS.Platform) {
if (platform === "win32") {
this.loadWindowsHelloService();
} else if (platform === "darwin") {
this.loadMacOSService();
}
}
private loadWindowsHelloService() {
// eslint-disable-next-line
const BiometricWindowsMain = require("./biometric.windows.main").default;
this.platformSpecificService = new BiometricWindowsMain(
this.i18nService,
this.windowMain,
this.stateService,
this.logService
);
}
private loadMacOSService() {
// eslint-disable-next-line
const BiometricDarwinMain = require("./biometric.darwin.main").default;
this.platformSpecificService = new BiometricDarwinMain(this.i18nService, this.stateService);
}
async init() {
return await this.platformSpecificService.init();
}
async osSupportsBiometric() {
return await this.platformSpecificService.osSupportsBiometric();
}
async canAuthBiometric({
service,
key,
userId,
}: {
service: string;
key: string;
userId: string;
}): Promise<boolean> {
const requireClientKeyHalf = await this.stateService.getBiometricRequirePasswordOnStart({
userId,
});
const clientKeyHalfB64 = this.getClientKeyHalf(service, key);
const clientKeyHalfSatisfied = !requireClientKeyHalf || !!clientKeyHalfB64;
return clientKeyHalfSatisfied && (await this.osSupportsBiometric());
}
async authenticateBiometric(): Promise<boolean> {
let result = false;
this.interruptProcessReload(
() => {
return this.platformSpecificService.authenticateBiometric();
},
(response) => {
result = response;
return !response;
}
);
return result;
}
async getBiometricKey(service: string, storageKey: string): Promise<string | null> {
return await this.interruptProcessReload(async () => {
await this.enforceClientKeyHalf(service, storageKey);
return await this.platformSpecificService.getBiometricKey(
service,
storageKey,
this.getClientKeyHalf(service, storageKey)
);
});
}
async setBiometricKey(service: string, storageKey: string, value: string): Promise<void> {
await this.enforceClientKeyHalf(service, storageKey);
return await this.platformSpecificService.setBiometricKey(
service,
storageKey,
value,
this.getClientKeyHalf(service, storageKey)
);
}
/** Registers the client-side encryption key half for the OS stored Biometric key. The other half is protected by the OS.*/
async setEncryptionKeyHalf({
service,
key,
value,
}: {
service: string;
key: string;
value: string;
}): Promise<void> {
if (value == null) {
this.clientKeyHalves.delete(this.clientKeyHalfKey(service, key));
} else {
this.clientKeyHalves.set(this.clientKeyHalfKey(service, key), value);
}
}
async deleteBiometricKey(service: string, storageKey: string): Promise<void> {
this.clientKeyHalves.delete(this.clientKeyHalfKey(service, storageKey));
return await this.platformSpecificService.deleteBiometricKey(service, storageKey);
}
private async interruptProcessReload<T>(
callback: () => Promise<T>,
restartReloadCallback: (arg: T) => boolean = () => false
): Promise<T> {
this.messagingService.send("cancelProcessReload");
let restartReload = false;
let response: T;
try {
response = await callback();
restartReload ||= restartReloadCallback(response);
} catch {
restartReload = true;
}
if (restartReload) {
this.messagingService.send("startProcessReload");
}
return response;
}
private clientKeyHalfKey(service: string, key: string): string {
return `${service}:${key}`;
}
private getClientKeyHalf(service: string, key: string): string | undefined {
return this.clientKeyHalves.get(this.clientKeyHalfKey(service, key)) ?? undefined;
}
private async enforceClientKeyHalf(service: string, storageKey: string): Promise<void> {
const requireClientKeyHalf = await this.stateService.getBiometricRequirePasswordOnStart();
const clientKeyHalfB64 = this.getClientKeyHalf(service, storageKey);
if (requireClientKeyHalf && !clientKeyHalfB64) {
throw new Error("Biometric key requirements not met. No client key half provided.");
}
}
}

View File

@@ -1,2 +0,0 @@
export * from "./biometrics.service.abstraction";
export * from "./biometrics.service";

View File

@@ -1,132 +0,0 @@
import { ipcMain } from "electron";
import { BiometricKey } from "@bitwarden/common/auth/types/biometric-key";
import { ConsoleLogService } from "@bitwarden/common/services/consoleLog.service";
import { passwords } from "@bitwarden/desktop-native";
import { BiometricMessage, BiometricStorageAction } from "../types/biometric-message";
import { BiometricsServiceAbstraction } from "./biometric/index";
const AuthRequiredSuffix = "_biometric";
export class DesktopCredentialStorageListener {
constructor(
private serviceName: string,
private biometricService: BiometricsServiceAbstraction,
private logService: ConsoleLogService
) {}
init() {
ipcMain.handle("keytar", async (event: any, message: any) => {
try {
let serviceName = this.serviceName;
message.keySuffix = "_" + (message.keySuffix ?? "");
if (message.keySuffix !== "_") {
serviceName += message.keySuffix;
}
let val: string | boolean = null;
if (message.action && message.key) {
if (message.action === "getPassword") {
val = await this.getPassword(serviceName, message.key, message.keySuffix);
} else if (message.action === "hasPassword") {
const result = await passwords.getPassword(serviceName, message.key);
val = result != null;
} else if (message.action === "setPassword" && message.value) {
await this.setPassword(serviceName, message.key, message.value, message.keySuffix);
} else if (message.action === "deletePassword") {
await this.deletePassword(serviceName, message.key, message.keySuffix);
}
}
return val;
} catch (e) {
if (
e.message === "Password not found." ||
e.message === "The specified item could not be found in the keychain."
) {
return null;
}
this.logService.info(e);
}
});
ipcMain.handle("biometric", async (event: any, message: BiometricMessage) => {
try {
let serviceName = this.serviceName;
message.keySuffix = "_" + (message.keySuffix ?? "");
if (message.keySuffix !== "_") {
serviceName += message.keySuffix;
}
let val: string | boolean = null;
if (!message.action) {
return val;
}
switch (message.action) {
case BiometricStorageAction.EnabledForUser:
if (!message.key || !message.userId) {
break;
}
val = await this.biometricService.canAuthBiometric({
service: serviceName,
key: message.key,
userId: message.userId,
});
break;
case BiometricStorageAction.OsSupported:
val = await this.biometricService.osSupportsBiometric();
break;
default:
}
return val;
} catch (e) {
this.logService.info(e);
}
});
}
// Gracefully handle old keytar values, and if detected updated the entry to the proper format
private async getPassword(serviceName: string, key: string, keySuffix: string) {
let val: string;
if (keySuffix === AuthRequiredSuffix) {
val = (await this.biometricService.getBiometricKey(serviceName, key)) ?? null;
} else {
val = await passwords.getPassword(serviceName, key);
}
try {
JSON.parse(val);
} catch (e) {
throw new Error("Password in bad format" + e + val);
}
return val;
}
private async setPassword(serviceName: string, key: string, value: string, keySuffix: string) {
if (keySuffix === AuthRequiredSuffix) {
const valueObj = JSON.parse(value) as BiometricKey;
await this.biometricService.setEncryptionKeyHalf({
service: serviceName,
key,
value: valueObj?.clientEncKeyHalf,
});
// Value is usually a JSON string, but we need to pass the key half as well, so we re-stringify key here.
await this.biometricService.setBiometricKey(serviceName, key, JSON.stringify(valueObj?.key));
} else {
await passwords.setPassword(serviceName, key, value);
}
}
private async deletePassword(serviceName: string, key: string, keySuffix: string) {
if (keySuffix === AuthRequiredSuffix) {
await this.biometricService.deleteBiometricKey(serviceName, key);
} else {
await passwords.deletePassword(serviceName, key);
}
}
}

View File

@@ -1,6 +1,6 @@
import { BrowserWindow, clipboard, dialog, MenuItemConstructorOptions } from "electron";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { isMacAppStore, isSnapStore, isWindowsStore } from "../../utils";
import { UpdaterMain } from "../updater.main";

View File

@@ -1,7 +1,7 @@
import { BrowserWindow, dialog, MenuItemConstructorOptions, shell } from "electron";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { isMacAppStore, isWindowsStore } from "../../utils";

View File

@@ -1,7 +1,7 @@
import { BrowserWindow, MenuItemConstructorOptions } from "electron";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { isMac } from "../../utils";
import { UpdaterMain } from "../updater.main";

View File

@@ -1,7 +1,7 @@
import { MenuItemConstructorOptions } from "electron";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { IMenubarMenu } from "./menubar";

View File

@@ -1,7 +1,7 @@
import { BrowserWindow, MenuItemConstructorOptions } from "electron";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { isMac, isMacAppStore } from "../../utils";
import { UpdaterMain } from "../updater.main";

View File

@@ -1,7 +1,7 @@
import { BrowserWindow, dialog, MenuItem, MenuItemConstructorOptions } from "electron";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { isMacAppStore, isSnapStore, isWindowsStore } from "../../utils";
import { UpdaterMain } from "../updater.main";

View File

@@ -1,6 +1,6 @@
import { shell, MenuItemConstructorOptions } from "electron";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { isMacAppStore, isWindowsStore } from "../../utils";

View File

@@ -1,8 +1,8 @@
import { app, Menu } from "electron";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { UpdaterMain } from "../updater.main";
import { WindowMain } from "../window.main";

View File

@@ -1,7 +1,7 @@
import { MenuItemConstructorOptions } from "electron";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { IMenubarMenu } from "./menubar";

View File

@@ -1,7 +1,7 @@
import { MenuItemConstructorOptions } from "electron";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { isMac } from "../../utils";
import { WindowMain } from "../window.main";

View File

@@ -1,7 +1,7 @@
import { Menu, MenuItemConstructorOptions } from "electron";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { isMac } from "../../utils";
import { UpdaterMain } from "../updater.main";

View File

@@ -3,7 +3,7 @@ import * as path from "path";
import { app, ipcMain } from "electron";
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { Main } from "../main";

View File

@@ -7,7 +7,7 @@ import * as util from "util";
import { ipcMain } from "electron";
import * as ipc from "node-ipc";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { getIpcSocketRoot } from "../proxy/ipc";

View File

@@ -2,8 +2,8 @@ import * as path from "path";
import { app, BrowserWindow, Menu, MenuItemConstructorOptions, nativeImage, Tray } from "electron";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { WindowMain } from "./window.main";

View File

@@ -2,7 +2,7 @@ import { dialog, shell } from "electron";
import log from "electron-log";
import { autoUpdater } from "electron-updater";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { isAppImage, isDev, isMacAppStore, isWindowsPortable, isWindowsStore } from "../utils";

View File

@@ -3,9 +3,9 @@ import * as url from "url";
import { app, BrowserWindow, screen } from "electron";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { StateService } from "@bitwarden/common/abstractions/state.service";
import { WindowState } from "@bitwarden/common/models/domain/window-state";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { cleanUserAgent, isDev, isMacAppStore, isSnapStore } from "../utils";