-
diff --git a/apps/browser/src/autofill/popup/settings/notifications-v1.component.ts b/apps/browser/src/autofill/popup/settings/notifications-v1.component.ts
deleted file mode 100644
index 442e91e55eb..00000000000
--- a/apps/browser/src/autofill/popup/settings/notifications-v1.component.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import { Component, OnInit } from "@angular/core";
-import { firstValueFrom } from "rxjs";
-
-import { UserNotificationSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/user-notification-settings.service";
-import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service";
-
-import { enableAccountSwitching } from "../../../platform/flags";
-
-@Component({
- selector: "autofill-notification-v1-settings",
- templateUrl: "notifications-v1.component.html",
-})
-export class NotificationsSettingsV1Component implements OnInit {
- enableAddLoginNotification = false;
- enableChangedPasswordNotification = false;
- enablePasskeys = true;
- accountSwitcherEnabled = false;
-
- constructor(
- private userNotificationSettingsService: UserNotificationSettingsServiceAbstraction,
- private vaultSettingsService: VaultSettingsService,
- ) {
- this.accountSwitcherEnabled = enableAccountSwitching();
- }
-
- async ngOnInit() {
- this.enableAddLoginNotification = await firstValueFrom(
- this.userNotificationSettingsService.enableAddedLoginPrompt$,
- );
-
- this.enableChangedPasswordNotification = await firstValueFrom(
- this.userNotificationSettingsService.enableChangedPasswordPrompt$,
- );
-
- this.enablePasskeys = await firstValueFrom(this.vaultSettingsService.enablePasskeys$);
- }
-
- async updateAddLoginNotification() {
- await this.userNotificationSettingsService.setEnableAddedLoginPrompt(
- this.enableAddLoginNotification,
- );
- }
-
- async updateChangedPasswordNotification() {
- await this.userNotificationSettingsService.setEnableChangedPasswordPrompt(
- this.enableChangedPasswordNotification,
- );
- }
-
- async updateEnablePasskeys() {
- await this.vaultSettingsService.setEnablePasskeys(this.enablePasskeys);
- }
-}
diff --git a/apps/browser/src/autofill/services/autofill-overlay-content.service.ts b/apps/browser/src/autofill/services/autofill-overlay-content.service.ts
index daa65d74ae6..acf0dedde27 100644
--- a/apps/browser/src/autofill/services/autofill-overlay-content.service.ts
+++ b/apps/browser/src/autofill/services/autofill-overlay-content.service.ts
@@ -957,8 +957,17 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
accountCreationFieldType: autofillFieldData?.accountCreationFieldType,
};
+ const allFields = this.formFieldElements;
+ const allFieldsRect = [];
+
+ for (const key of allFields.keys()) {
+ const rect = await this.getMostRecentlyFocusedFieldRects(key);
+ allFieldsRect.push({ ...allFields.get(key), rect }); // Add the combined result to the array
+ }
+
await this.sendExtensionMessage("updateFocusedFieldData", {
focusedFieldData: this.focusedFieldData,
+ allFieldsRect,
});
}
@@ -1408,6 +1417,8 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
url.origin + pathWithoutTrailingSlashAndSearch,
url.origin + pathWithoutTrailingSlashSearchAndHash,
]);
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (_error) {
return null;
}
diff --git a/apps/browser/src/autofill/services/dom-query.service.ts b/apps/browser/src/autofill/services/dom-query.service.ts
index 0dbc246b235..16310397a03 100644
--- a/apps/browser/src/autofill/services/dom-query.service.ts
+++ b/apps/browser/src/autofill/services/dom-query.service.ts
@@ -235,6 +235,8 @@ export class DomQueryService implements DomQueryServiceInterface {
if ((chrome as any).dom?.openOrClosedShadowRoot) {
try {
return (chrome as any).dom.openOrClosedShadowRoot(node);
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
return null;
}
diff --git a/apps/browser/src/autofill/utils/index.ts b/apps/browser/src/autofill/utils/index.ts
index 12d26914d82..0e102dcfd99 100644
--- a/apps/browser/src/autofill/utils/index.ts
+++ b/apps/browser/src/autofill/utils/index.ts
@@ -1,5 +1,6 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
+import { FieldRect } from "../background/abstractions/overlay.background";
import { AutofillPort } from "../enums/autofill-port.enum";
import { FillableFormFieldElement, FormElementWithAttribute, FormFieldElement } from "../types";
@@ -545,6 +546,17 @@ export const specialCharacterToKeyMap: Record = {
"/": "forwardSlashCharacterDescriptor",
};
+/**
+ * Determines if the current rect values are not all 0.
+ */
+export function rectHasSize(rect: FieldRect): boolean {
+ if (rect.right > 0 && rect.left > 0 && rect.top > 0 && rect.bottom > 0) {
+ return true;
+ }
+
+ return false;
+}
+
/**
* Checks if all the values corresponding to the specified keys in an object are null.
* If no keys are specified, checks all keys in the object.
diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts
index 4bec3d6cc0a..5d09122bbd6 100644
--- a/apps/browser/src/background/main.background.ts
+++ b/apps/browser/src/background/main.background.ts
@@ -632,11 +632,6 @@ export default class MainBackground {
this.i18nService = new I18nService(BrowserApi.getUILanguage(), this.globalStateProvider);
- this.biometricsService = new BackgroundBrowserBiometricsService(
- runtimeNativeMessagingBackground,
- this.logService,
- );
-
this.kdfConfigService = new DefaultKdfConfigService(this.stateProvider);
this.pinService = new PinService(
@@ -665,6 +660,14 @@ export default class MainBackground {
this.kdfConfigService,
);
+ this.biometricsService = new BackgroundBrowserBiometricsService(
+ runtimeNativeMessagingBackground,
+ this.logService,
+ this.keyService,
+ this.biometricStateService,
+ this.messagingService,
+ );
+
this.appIdService = new AppIdService(this.storageService, this.logService);
this.userDecryptionOptionsService = new UserDecryptionOptionsService(this.stateProvider);
diff --git a/apps/browser/src/background/nativeMessaging.background.ts b/apps/browser/src/background/nativeMessaging.background.ts
index 116d048d2e8..b08f1c8b566 100644
--- a/apps/browser/src/background/nativeMessaging.background.ts
+++ b/apps/browser/src/background/nativeMessaging.background.ts
@@ -257,7 +257,7 @@ export class NativeMessagingBackground {
message.command == BiometricsCommands.Unlock ||
message.command == BiometricsCommands.IsAvailable
) {
- // TODO remove after 2025.01
+ // TODO remove after 2025.3
// wait until there is no other callbacks, or timeout
const call = await firstValueFrom(
race(
@@ -342,6 +342,8 @@ export class NativeMessagingBackground {
};
}
this.port.postMessage(msg);
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
this.logService.info(
"[Native Messaging IPC] Disconnected from Bitwarden Desktop app because of the native port disconnecting.",
diff --git a/apps/browser/src/background/runtime.background.ts b/apps/browser/src/background/runtime.background.ts
index 863ca26b36e..38bb2ec50c9 100644
--- a/apps/browser/src/background/runtime.background.ts
+++ b/apps/browser/src/background/runtime.background.ts
@@ -259,9 +259,7 @@ export default class RuntimeBackground {
await this.main.refreshBadge();
await this.main.refreshMenu(false);
- if (await this.configService.getFeatureFlag(FeatureFlag.ExtensionRefresh)) {
- await this.autofillService.setAutoFillOnPageLoadOrgPolicy();
- }
+ await this.autofillService.setAutoFillOnPageLoadOrgPolicy();
break;
}
case "addToLockedVaultPendingNotifications":
@@ -288,9 +286,7 @@ export default class RuntimeBackground {
await this.configService.ensureConfigFetched();
await this.main.updateOverlayCiphers();
- if (await this.configService.getFeatureFlag(FeatureFlag.ExtensionRefresh)) {
- await this.autofillService.setAutoFillOnPageLoadOrgPolicy();
- }
+ await this.autofillService.setAutoFillOnPageLoadOrgPolicy();
}
break;
case "openPopup":
diff --git a/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts b/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts
index 8e6fc562d14..54b6faad84c 100644
--- a/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts
+++ b/apps/browser/src/key-management/biometrics/background-browser-biometrics.service.ts
@@ -1,9 +1,18 @@
import { Injectable } from "@angular/core";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
+import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
+import { Utils } from "@bitwarden/common/platform/misc/utils";
+import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { UserId } from "@bitwarden/common/types/guid";
import { UserKey } from "@bitwarden/common/types/key";
-import { BiometricsService, BiometricsCommands, BiometricsStatus } from "@bitwarden/key-management";
+import {
+ BiometricsService,
+ BiometricsCommands,
+ BiometricsStatus,
+ KeyService,
+ BiometricStateService,
+} from "@bitwarden/key-management";
import { NativeMessagingBackground } from "../../background/nativeMessaging.background";
import { BrowserApi } from "../../platform/browser/browser-api";
@@ -13,6 +22,9 @@ export class BackgroundBrowserBiometricsService extends BiometricsService {
constructor(
private nativeMessagingBackground: () => NativeMessagingBackground,
private logService: LogService,
+ private keyService: KeyService,
+ private biometricStateService: BiometricStateService,
+ private messagingService: MessagingService,
) {
super();
}
@@ -65,6 +77,8 @@ export class BackgroundBrowserBiometricsService extends BiometricsService {
}
}
return BiometricsStatus.Available;
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
return BiometricsStatus.DesktopDisconnected;
}
@@ -74,12 +88,22 @@ export class BackgroundBrowserBiometricsService extends BiometricsService {
try {
await this.ensureConnected();
+ // todo remove after 2025.3
if (this.nativeMessagingBackground().isConnectedToOutdatedDesktopClient) {
const response = await this.nativeMessagingBackground().callCommand({
command: BiometricsCommands.Unlock,
});
if (response.response == "unlocked") {
- return response.userKeyB64;
+ const decodedUserkey = Utils.fromB64ToArray(response.userKeyB64);
+ const userKey = new SymmetricCryptoKey(decodedUserkey) as UserKey;
+ if (await this.keyService.validateUserKey(userKey, userId)) {
+ await this.biometricStateService.setBiometricUnlockEnabled(true);
+ await this.biometricStateService.setFingerprintValidated(true);
+ await this.keyService.setUserKey(userKey, userId);
+ // to update badge and other things
+ this.messagingService.send("switchAccount", { userId });
+ return userKey;
+ }
} else {
return null;
}
@@ -89,7 +113,17 @@ export class BackgroundBrowserBiometricsService extends BiometricsService {
userId: userId,
});
if (response.response) {
- return response.userKeyB64;
+ // In case the requesting foreground context dies (popup), the userkey should still be set, so the user is unlocked / the setting should be enabled
+ const decodedUserkey = Utils.fromB64ToArray(response.userKeyB64);
+ const userKey = new SymmetricCryptoKey(decodedUserkey) as UserKey;
+ if (await this.keyService.validateUserKey(userKey, userId)) {
+ await this.biometricStateService.setBiometricUnlockEnabled(true);
+ await this.biometricStateService.setFingerprintValidated(true);
+ await this.keyService.setUserKey(userKey, userId);
+ // to update badge and other things
+ this.messagingService.send("switchAccount", { userId });
+ return userKey;
+ }
} else {
return null;
}
@@ -98,6 +132,8 @@ export class BackgroundBrowserBiometricsService extends BiometricsService {
this.logService.info("Biometric unlock for user failed", e);
throw new Error("Biometric unlock failed");
}
+
+ return null;
}
async getBiometricsStatusForUser(id: UserId): Promise {
@@ -114,6 +150,8 @@ export class BackgroundBrowserBiometricsService extends BiometricsService {
userId: id,
})
).response;
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
return BiometricsStatus.DesktopDisconnected;
}
diff --git a/apps/browser/src/key-management/biometrics/foreground-browser-biometrics.ts b/apps/browser/src/key-management/biometrics/foreground-browser-biometrics.ts
index 0235ad5bd9c..d248a630cc6 100644
--- a/apps/browser/src/key-management/biometrics/foreground-browser-biometrics.ts
+++ b/apps/browser/src/key-management/biometrics/foreground-browser-biometrics.ts
@@ -29,13 +29,13 @@ export class ForegroundBrowserBiometricsService extends BiometricsService {
async unlockWithBiometricsForUser(userId: UserId): Promise {
const response = await BrowserApi.sendMessageWithResponse<{
- result: string;
+ result: UserKey;
error: string;
}>(BiometricsCommands.UnlockWithBiometricsForUser, { userId });
if (!response.result) {
return null;
}
- return SymmetricCryptoKey.fromString(response.result) as UserKey;
+ return SymmetricCryptoKey.fromString(response.result.keyB64) as UserKey;
}
async getBiometricsStatusForUser(id: UserId): Promise {
diff --git a/apps/browser/src/key-management/lock/services/extension-lock-component.service.spec.ts b/apps/browser/src/key-management/lock/services/extension-lock-component.service.spec.ts
index 4b0323d5ebe..92830c35aca 100644
--- a/apps/browser/src/key-management/lock/services/extension-lock-component.service.spec.ts
+++ b/apps/browser/src/key-management/lock/services/extension-lock-component.service.spec.ts
@@ -9,7 +9,12 @@ import {
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { UserId } from "@bitwarden/common/types/guid";
-import { KeyService, BiometricsService, BiometricsStatus } from "@bitwarden/key-management";
+import {
+ KeyService,
+ BiometricsService,
+ BiometricsStatus,
+ BiometricStateService,
+} from "@bitwarden/key-management";
import { UnlockOptions } from "@bitwarden/key-management/angular";
import { BrowserRouterService } from "../../../platform/popup/services/browser-router.service";
@@ -26,6 +31,7 @@ describe("ExtensionLockComponentService", () => {
let vaultTimeoutSettingsService: MockProxy;
let keyService: MockProxy;
let routerService: MockProxy;
+ let biometricStateService: MockProxy;
beforeEach(() => {
userDecryptionOptionsService = mock();
@@ -35,6 +41,7 @@ describe("ExtensionLockComponentService", () => {
vaultTimeoutSettingsService = mock();
keyService = mock();
routerService = mock();
+ biometricStateService = mock();
TestBed.configureTestingModule({
providers: [
@@ -67,6 +74,10 @@ describe("ExtensionLockComponentService", () => {
provide: BrowserRouterService,
useValue: routerService,
},
+ {
+ provide: BiometricStateService,
+ useValue: biometricStateService,
+ },
],
});
@@ -306,6 +317,7 @@ describe("ExtensionLockComponentService", () => {
platformUtilsService.supportsSecureStorage.mockReturnValue(
mockInputs.platformSupportsSecureStorage,
);
+ biometricStateService.biometricUnlockEnabled$ = of(true);
// PIN
pinService.isPinDecryptionAvailable.mockResolvedValue(mockInputs.pinDecryptionAvailable);
diff --git a/apps/browser/src/key-management/lock/services/extension-lock-component.service.ts b/apps/browser/src/key-management/lock/services/extension-lock-component.service.ts
index f21beb91cff..711ae4e378f 100644
--- a/apps/browser/src/key-management/lock/services/extension-lock-component.service.ts
+++ b/apps/browser/src/key-management/lock/services/extension-lock-component.service.ts
@@ -1,14 +1,18 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { inject } from "@angular/core";
-import { combineLatest, defer, map, Observable } from "rxjs";
+import { combineLatest, defer, firstValueFrom, map, Observable } from "rxjs";
import {
PinServiceAbstraction,
UserDecryptionOptionsServiceAbstraction,
} from "@bitwarden/auth/common";
import { UserId } from "@bitwarden/common/types/guid";
-import { BiometricsService, BiometricsStatus } from "@bitwarden/key-management";
+import {
+ BiometricsService,
+ BiometricsStatus,
+ BiometricStateService,
+} from "@bitwarden/key-management";
import { LockComponentService, UnlockOptions } from "@bitwarden/key-management/angular";
import { BiometricErrors, BiometricErrorTypes } from "../../../models/biometricErrors";
@@ -19,6 +23,7 @@ export class ExtensionLockComponentService implements LockComponentService {
private readonly biometricsService = inject(BiometricsService);
private readonly pinService = inject(PinServiceAbstraction);
private readonly routerService = inject(BrowserRouterService);
+ private readonly biometricStateService = inject(BiometricStateService);
getPreviousUrl(): string | null {
return this.routerService.getPreviousUrl();
@@ -45,7 +50,21 @@ export class ExtensionLockComponentService implements LockComponentService {
getAvailableUnlockOptions$(userId: UserId): Observable {
return combineLatest([
// Note: defer is preferable b/c it delays the execution of the function until the observable is subscribed to
- defer(async () => await this.biometricsService.getBiometricsStatusForUser(userId)),
+ defer(async () => {
+ if (!(await firstValueFrom(this.biometricStateService.biometricUnlockEnabled$))) {
+ return BiometricsStatus.NotEnabledLocally;
+ } else {
+ // TODO remove after 2025.3
+ // remove after backward compatibility code for old biometrics ipc protocol is removed
+ const result: BiometricsStatus = (await Promise.race([
+ this.biometricsService.getBiometricsStatusForUser(userId),
+ new Promise((resolve) =>
+ setTimeout(() => resolve(BiometricsStatus.DesktopDisconnected), 1000),
+ ),
+ ])) as BiometricsStatus;
+ return result;
+ }
+ }),
this.userDecryptionOptionsService.userDecryptionOptionsById$(userId),
defer(() => this.pinService.isPinDecryptionAvailable(userId)),
]).pipe(
diff --git a/apps/browser/src/manifest.json b/apps/browser/src/manifest.json
index 9e4eb78291a..86ea0eebbc8 100644
--- a/apps/browser/src/manifest.json
+++ b/apps/browser/src/manifest.json
@@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "__MSG_extName__",
"short_name": "__MSG_appName__",
- "version": "2025.1.0",
+ "version": "2025.1.1",
"description": "__MSG_extDesc__",
"default_locale": "en",
"author": "Bitwarden Inc.",
diff --git a/apps/browser/src/manifest.v3.json b/apps/browser/src/manifest.v3.json
index ef7ede6b056..ae7c888eb9b 100644
--- a/apps/browser/src/manifest.v3.json
+++ b/apps/browser/src/manifest.v3.json
@@ -3,7 +3,7 @@
"minimum_chrome_version": "102.0",
"name": "__MSG_extName__",
"short_name": "__MSG_appName__",
- "version": "2025.1.0",
+ "version": "2025.1.1",
"description": "__MSG_extDesc__",
"default_locale": "en",
"author": "Bitwarden Inc.",
diff --git a/apps/browser/src/platform/flags.ts b/apps/browser/src/platform/flags.ts
index 383e982f065..2b1040bcd8a 100644
--- a/apps/browser/src/platform/flags.ts
+++ b/apps/browser/src/platform/flags.ts
@@ -11,13 +11,11 @@ import { GroupPolicyEnvironment } from "../admin-console/types/group-policy-envi
import { BrowserApi } from "./browser/browser-api";
// required to avoid linting errors when there are no flags
-// eslint-disable-next-line @typescript-eslint/ban-types
export type Flags = {
accountSwitching?: boolean;
} & SharedFlags;
// required to avoid linting errors when there are no flags
-// eslint-disable-next-line @typescript-eslint/ban-types
export type DevFlags = {
managedEnvironment?: GroupPolicyEnvironment;
} & SharedDevFlags;
diff --git a/apps/browser/src/platform/offscreen-document/offscreen-document.spec.ts b/apps/browser/src/platform/offscreen-document/offscreen-document.spec.ts
index 4065f2e46d7..67fa920d18d 100644
--- a/apps/browser/src/platform/offscreen-document/offscreen-document.spec.ts
+++ b/apps/browser/src/platform/offscreen-document/offscreen-document.spec.ts
@@ -8,6 +8,8 @@ describe("OffscreenDocument", () => {
const browserClipboardServiceReadSpy = jest.spyOn(BrowserClipboardService, "read");
const consoleErrorSpy = jest.spyOn(console, "error");
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
require("../offscreen-document/offscreen-document");
describe("init", () => {
diff --git a/apps/browser/src/platform/services/browser-script-injector.service.spec.ts b/apps/browser/src/platform/services/browser-script-injector.service.spec.ts
index 0919de46776..b177497305b 100644
--- a/apps/browser/src/platform/services/browser-script-injector.service.spec.ts
+++ b/apps/browser/src/platform/services/browser-script-injector.service.spec.ts
@@ -63,7 +63,7 @@ describe("ScriptInjectorService", () => {
configService.getFeatureFlag$.mockImplementation(() => of(false));
domainSettingsService = new DefaultDomainSettingsService(fakeStateProvider, configService);
domainSettingsService.equivalentDomains$ = of(mockEquivalentDomains);
- domainSettingsService.blockedInteractionsUris$ = of(null);
+ domainSettingsService.blockedInteractionsUris$ = of({});
scriptInjectorService = new BrowserScriptInjectorService(
domainSettingsService,
platformUtilsService,
diff --git a/apps/browser/src/platform/services/local-backed-session-storage.service.spec.ts b/apps/browser/src/platform/services/local-backed-session-storage.service.spec.ts
index 949ecebde8a..4d6a403a18a 100644
--- a/apps/browser/src/platform/services/local-backed-session-storage.service.spec.ts
+++ b/apps/browser/src/platform/services/local-backed-session-storage.service.spec.ts
@@ -48,6 +48,8 @@ describe("LocalBackedSessionStorage", () => {
localStorage.internalStore["session_test"] = encrypted.encryptedString;
encryptService.decryptToUtf8.mockResolvedValue(JSON.stringify("decrypted"));
const result = await sut.get("test");
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
expect(encryptService.decryptToUtf8).toHaveBeenCalledWith(
encrypted,
sessionKey,
@@ -69,6 +71,8 @@ describe("LocalBackedSessionStorage", () => {
localStorage.internalStore["session_test"] = encrypted.encryptedString;
encryptService.decryptToUtf8.mockResolvedValue(JSON.stringify("decrypted"));
const result = await sut.get("test");
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
expect(encryptService.decryptToUtf8).toHaveBeenCalledWith(
encrypted,
sessionKey,
diff --git a/apps/browser/src/platform/services/local-backed-session-storage.service.ts b/apps/browser/src/platform/services/local-backed-session-storage.service.ts
index bdc0bed80c0..900212ddefa 100644
--- a/apps/browser/src/platform/services/local-backed-session-storage.service.ts
+++ b/apps/browser/src/platform/services/local-backed-session-storage.service.ts
@@ -198,6 +198,8 @@ export class LocalBackedSessionStorageService
private compareValues(value1: T, value2: T): boolean {
try {
return compareValues(value1, value2);
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
this.logService.error(
`error comparing values\n${JSON.stringify(value1)}\n${JSON.stringify(value2)}`,
diff --git a/apps/browser/src/platform/services/sdk/browser-sdk-client-factory.ts b/apps/browser/src/platform/services/sdk/browser-sdk-client-factory.ts
index a2f0c78cd52..0499f34a4ae 100644
--- a/apps/browser/src/platform/services/sdk/browser-sdk-client-factory.ts
+++ b/apps/browser/src/platform/services/sdk/browser-sdk-client-factory.ts
@@ -17,6 +17,8 @@ const supported = (() => {
return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
}
}
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
// ignore
}
diff --git a/apps/browser/src/popup/app-routing.module.ts b/apps/browser/src/popup/app-routing.module.ts
index 8e48104737a..d55bebfa0c3 100644
--- a/apps/browser/src/popup/app-routing.module.ts
+++ b/apps/browser/src/popup/app-routing.module.ts
@@ -17,7 +17,6 @@ import {
unauthGuardFn,
} from "@bitwarden/angular/auth/guards";
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";
-import { extensionRefreshSwap } from "@bitwarden/angular/utils/extension-refresh-swap";
import { twofactorRefactorSwap } from "@bitwarden/angular/utils/two-factor-component-refactor-route-swap";
import { NewDeviceVerificationNoticeGuard } from "@bitwarden/angular/vault/guards";
import {
@@ -71,14 +70,10 @@ import { TwoFactorAuthComponent } from "../auth/popup/two-factor-auth.component"
import { TwoFactorOptionsComponent } from "../auth/popup/two-factor-options.component";
import { TwoFactorComponent } from "../auth/popup/two-factor.component";
import { UpdateTempPasswordComponent } from "../auth/popup/update-temp-password.component";
-import { Fido2V1Component } from "../autofill/popup/fido2/fido2-v1.component";
import { Fido2Component } from "../autofill/popup/fido2/fido2.component";
-import { AutofillV1Component } from "../autofill/popup/settings/autofill-v1.component";
import { AutofillComponent } from "../autofill/popup/settings/autofill.component";
import { BlockedDomainsComponent } from "../autofill/popup/settings/blocked-domains.component";
-import { ExcludedDomainsV1Component } from "../autofill/popup/settings/excluded-domains-v1.component";
import { ExcludedDomainsComponent } from "../autofill/popup/settings/excluded-domains.component";
-import { NotificationsSettingsV1Component } from "../autofill/popup/settings/notifications-v1.component";
import { NotificationsSettingsComponent } from "../autofill/popup/settings/notifications.component";
import { PremiumV2Component } from "../billing/popup/settings/premium-v2.component";
import BrowserPopupUtils from "../platform/popup/browser-popup-utils";
@@ -148,11 +143,12 @@ const routes: Routes = [
canActivate: [unauthGuardFn(unauthRouteOverrides), unauthUiRefreshRedirect("/login")],
data: { elevation: 1 } satisfies RouteDataProperties,
},
- ...extensionRefreshSwap(Fido2V1Component, Fido2Component, {
+ {
path: "fido2",
+ component: Fido2Component,
canActivate: [fido2AuthGuard],
data: { elevation: 1 } satisfies RouteDataProperties,
- }),
+ },
...twofactorRefactorSwap(
TwoFactorComponent,
AnonLayoutWrapperComponent,
@@ -321,22 +317,24 @@ const routes: Routes = [
canActivate: [authGuard],
data: { elevation: 2 } satisfies RouteDataProperties,
},
- ...extensionRefreshSwap(AutofillV1Component, AutofillComponent, {
+ {
path: "autofill",
+ component: AutofillComponent,
canActivate: [authGuard],
data: { elevation: 1 } satisfies RouteDataProperties,
- }),
+ },
{
path: "account-security",
component: AccountSecurityComponent,
canActivate: [authGuard],
data: { elevation: 1 } satisfies RouteDataProperties,
},
- ...extensionRefreshSwap(NotificationsSettingsV1Component, NotificationsSettingsComponent, {
+ {
path: "notifications",
+ component: NotificationsSettingsComponent,
canActivate: [authGuard],
data: { elevation: 1 } satisfies RouteDataProperties,
- }),
+ },
{
path: "vault-settings",
component: VaultSettingsV2Component,
@@ -355,11 +353,12 @@ const routes: Routes = [
canActivate: [authGuard],
data: { elevation: 2 } satisfies RouteDataProperties,
},
- ...extensionRefreshSwap(ExcludedDomainsV1Component, ExcludedDomainsComponent, {
+ {
path: "excluded-domains",
+ component: ExcludedDomainsComponent,
canActivate: [authGuard],
data: { elevation: 2 } satisfies RouteDataProperties,
- }),
+ },
{
path: "premium",
component: PremiumV2Component,
diff --git a/apps/browser/src/popup/app.component.ts b/apps/browser/src/popup/app.component.ts
index e8a660620a9..9d4835889b9 100644
--- a/apps/browser/src/popup/app.component.ts
+++ b/apps/browser/src/popup/app.component.ts
@@ -21,7 +21,7 @@ import {
ToastOptions,
ToastService,
} from "@bitwarden/components";
-import { BiometricStateService } from "@bitwarden/key-management";
+import { BiometricsService, BiometricStateService } from "@bitwarden/key-management";
import { PopupCompactModeService } from "../platform/popup/layout/popup-compact-mode.service";
import { PopupViewCacheService } from "../platform/popup/view-cache/popup-view-cache.service";
@@ -66,6 +66,7 @@ export class AppComponent implements OnInit, OnDestroy {
private accountService: AccountService,
private animationControlService: AnimationControlService,
private biometricStateService: BiometricStateService,
+ private biometricsService: BiometricsService,
) {}
async ngOnInit() {
@@ -102,7 +103,7 @@ export class AppComponent implements OnInit, OnDestroy {
this.messageListener.allMessages$
.pipe(
- tap((msg: any) => {
+ tap(async (msg: any) => {
if (msg.command === "doneLoggingOut") {
// TODO: PM-8544 - why do we call logout in the popup after receiving the doneLoggingOut message? Hasn't this already completeted logout?
this.authService.logOut(async () => {
@@ -119,6 +120,7 @@ export class AppComponent implements OnInit, OnDestroy {
msg.command === "locked" &&
(msg.userId == null || msg.userId == this.activeUserId)
) {
+ await this.biometricsService.setShouldAutopromptNow(false);
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.router.navigate(["lock"]);
@@ -135,8 +137,8 @@ export class AppComponent implements OnInit, OnDestroy {
this.toastService._showToast(msg);
} else if (msg.command === "reloadProcess") {
if (this.platformUtilsService.isSafari()) {
- window.setTimeout(() => {
- this.biometricStateService.updateLastProcessReload();
+ window.setTimeout(async () => {
+ await this.biometricStateService.updateLastProcessReload();
window.location.reload();
}, 2000);
}
diff --git a/apps/browser/src/popup/app.module.ts b/apps/browser/src/popup/app.module.ts
index 1fe8f1f18db..15a898aef53 100644
--- a/apps/browser/src/popup/app.module.ts
+++ b/apps/browser/src/popup/app.module.ts
@@ -35,17 +35,7 @@ import { SsoComponentV1 } from "../auth/popup/sso-v1.component";
import { TwoFactorOptionsComponent } from "../auth/popup/two-factor-options.component";
import { TwoFactorComponent } from "../auth/popup/two-factor.component";
import { UpdateTempPasswordComponent } from "../auth/popup/update-temp-password.component";
-import { Fido2CipherRowV1Component } from "../autofill/popup/fido2/fido2-cipher-row-v1.component";
-import { Fido2CipherRowComponent } from "../autofill/popup/fido2/fido2-cipher-row.component";
-import { Fido2UseBrowserLinkV1Component } from "../autofill/popup/fido2/fido2-use-browser-link-v1.component";
-import { Fido2UseBrowserLinkComponent } from "../autofill/popup/fido2/fido2-use-browser-link.component";
-import { Fido2V1Component } from "../autofill/popup/fido2/fido2-v1.component";
-import { Fido2Component } from "../autofill/popup/fido2/fido2.component";
-import { AutofillV1Component } from "../autofill/popup/settings/autofill-v1.component";
import { AutofillComponent } from "../autofill/popup/settings/autofill.component";
-import { ExcludedDomainsV1Component } from "../autofill/popup/settings/excluded-domains-v1.component";
-import { ExcludedDomainsComponent } from "../autofill/popup/settings/excluded-domains.component";
-import { NotificationsSettingsV1Component } from "../autofill/popup/settings/notifications-v1.component";
import { NotificationsSettingsComponent } from "../autofill/popup/settings/notifications.component";
import { PopOutComponent } from "../platform/popup/components/pop-out.component";
import { HeaderComponent } from "../platform/popup/header.component";
@@ -87,10 +77,6 @@ import "../platform/popup/locales";
ScrollingModule,
ServicesModule,
DialogModule,
- ExcludedDomainsComponent,
- Fido2CipherRowComponent,
- Fido2Component,
- Fido2UseBrowserLinkComponent,
FilePopoutCalloutComponent,
AvatarModule,
AccountComponent,
@@ -112,15 +98,11 @@ import "../platform/popup/locales";
ColorPasswordPipe,
ColorPasswordCountPipe,
EnvironmentComponent,
- ExcludedDomainsV1Component,
- Fido2CipherRowV1Component,
- Fido2UseBrowserLinkV1Component,
HintComponent,
HomeComponent,
LoginViaAuthRequestComponentV1,
LoginComponentV1,
LoginDecryptionOptionsComponentV1,
- NotificationsSettingsV1Component,
RegisterComponent,
SetPasswordComponent,
SsoComponentV1,
@@ -131,8 +113,6 @@ import "../platform/popup/locales";
UserVerificationComponent,
VaultTimeoutInputComponent,
RemovePasswordComponent,
- Fido2V1Component,
- AutofillV1Component,
EnvironmentSelectorComponent,
],
exports: [],
diff --git a/apps/browser/src/popup/main.ts b/apps/browser/src/popup/main.ts
index 8ffe0743bf6..dadd7917b99 100644
--- a/apps/browser/src/popup/main.ts
+++ b/apps/browser/src/popup/main.ts
@@ -4,7 +4,9 @@ import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
import { PopupSizeService } from "../platform/popup/layout/popup-size.service";
import { BrowserPlatformUtilsService } from "../platform/services/platform-utils/browser-platform-utils.service";
+// eslint-disable-next-line @typescript-eslint/no-require-imports
require("./scss/popup.scss");
+// eslint-disable-next-line @typescript-eslint/no-require-imports
require("./scss/tailwind.css");
import { AppModule } from "./app.module";
diff --git a/apps/browser/src/tools/background/fileless-importer.background.spec.ts b/apps/browser/src/tools/background/fileless-importer.background.spec.ts
index 429a0e12184..409fac9790f 100644
--- a/apps/browser/src/tools/background/fileless-importer.background.spec.ts
+++ b/apps/browser/src/tools/background/fileless-importer.background.spec.ts
@@ -39,7 +39,7 @@ describe("FilelessImporterBackground ", () => {
let tabMock: chrome.tabs.Tab;
beforeEach(() => {
- domainSettingsService.blockedInteractionsUris$ = of(null);
+ domainSettingsService.blockedInteractionsUris$ = of({});
policyService.policyAppliesToActiveUser$.mockImplementation(() => of(true));
scriptInjectorService = new BrowserScriptInjectorService(
domainSettingsService,
diff --git a/apps/browser/src/tools/content/lp-fileless-importer.spec.ts b/apps/browser/src/tools/content/lp-fileless-importer.spec.ts
index 432754ab91c..21fa44b8d3f 100644
--- a/apps/browser/src/tools/content/lp-fileless-importer.spec.ts
+++ b/apps/browser/src/tools/content/lp-fileless-importer.spec.ts
@@ -12,6 +12,8 @@ describe("LpFilelessImporter", () => {
chrome.runtime.connect = jest.fn(() => portSpy);
beforeEach(() => {
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
require("./lp-fileless-importer");
lpFilelessImporter = (globalThis as any).lpFilelessImporter;
});
diff --git a/apps/browser/src/tools/content/lp-suppress-import-download-script-append.mv2.spec.ts b/apps/browser/src/tools/content/lp-suppress-import-download-script-append.mv2.spec.ts
index 95b49ea00ec..8479235cc17 100644
--- a/apps/browser/src/tools/content/lp-suppress-import-download-script-append.mv2.spec.ts
+++ b/apps/browser/src/tools/content/lp-suppress-import-download-script-append.mv2.spec.ts
@@ -7,6 +7,8 @@ describe("LP Suppress Import Download for Manifest v2", () => {
return node;
});
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
require("./lp-suppress-import-download-script-append.mv2");
expect(window.document.createElement).toHaveBeenCalledWith("script");
diff --git a/apps/browser/src/tools/content/lp-suppress-import-download.spec.ts b/apps/browser/src/tools/content/lp-suppress-import-download.spec.ts
index bfff3787506..ff0ed381599 100644
--- a/apps/browser/src/tools/content/lp-suppress-import-download.spec.ts
+++ b/apps/browser/src/tools/content/lp-suppress-import-download.spec.ts
@@ -10,6 +10,8 @@ describe("LP Suppress Import Download", () => {
jest.spyOn(Element.prototype, "appendChild");
jest.spyOn(window, "addEventListener");
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
require("./lp-suppress-import-download");
anchor = document.createElement("a");
diff --git a/apps/browser/src/vault/popup/components/vault-v2/autofill-vault-list-items/autofill-vault-list-items.component.html b/apps/browser/src/vault/popup/components/vault-v2/autofill-vault-list-items/autofill-vault-list-items.component.html
index 7c4ea3e5b46..eae8e2cc980 100644
--- a/apps/browser/src/vault/popup/components/vault-v2/autofill-vault-list-items/autofill-vault-list-items.component.html
+++ b/apps/browser/src/vault/popup/components/vault-v2/autofill-vault-list-items/autofill-vault-list-items.component.html
@@ -1,7 +1,7 @@
=
+ this.vaultPopupAutofillService.currentTabIsOnBlocklist$;
+
constructor(
private vaultPopupItemsService: VaultPopupItemsService,
private vaultPopupAutofillService: VaultPopupAutofillService,
diff --git a/apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.html b/apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.html
new file mode 100644
index 00000000000..05db600bd5a
--- /dev/null
+++ b/apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.html
@@ -0,0 +1,10 @@
+
+ {{ "autofillBlockedNoticeV2" | i18n }}
+
+ {{ "autofillBlockedNoticeGuidance" | i18n }}
+
+
diff --git a/apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts b/apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts
new file mode 100644
index 00000000000..3a17825f4fb
--- /dev/null
+++ b/apps/browser/src/vault/popup/components/vault-v2/blocked-injection-banner/blocked-injection-banner.component.ts
@@ -0,0 +1,53 @@
+import { CommonModule } from "@angular/common";
+import { Component, OnInit } from "@angular/core";
+import { RouterModule } from "@angular/router";
+import { Observable } from "rxjs";
+
+import { JslibModule } from "@bitwarden/angular/jslib.module";
+import {
+ BannerModule,
+ IconButtonModule,
+ LinkModule,
+ TypographyModule,
+} from "@bitwarden/components";
+
+import { VaultPopupAutofillService } from "../../../services/vault-popup-autofill.service";
+
+const blockedURISettingsRoute = "/blocked-domains";
+
+@Component({
+ standalone: true,
+ imports: [
+ BannerModule,
+ CommonModule,
+ IconButtonModule,
+ JslibModule,
+ LinkModule,
+ RouterModule,
+ TypographyModule,
+ ],
+ selector: "blocked-injection-banner",
+ templateUrl: "blocked-injection-banner.component.html",
+})
+export class BlockedInjectionBanner implements OnInit {
+ /**
+ * Flag indicating that the banner should be shown
+ */
+ protected showCurrentTabIsBlockedBanner$: Observable =
+ this.vaultPopupAutofillService.showCurrentTabIsBlockedBanner$;
+
+ /**
+ * Hostname for current tab
+ */
+ protected currentTabHostname?: string;
+
+ blockedURISettingsRoute: string = blockedURISettingsRoute;
+
+ constructor(private vaultPopupAutofillService: VaultPopupAutofillService) {}
+
+ async ngOnInit() {}
+
+ async handleCurrentTabIsBlockedBannerDismiss() {
+ await this.vaultPopupAutofillService.dismissCurrentTabIsBlockedBanner();
+ }
+}
diff --git a/apps/browser/src/vault/popup/components/vault-v2/vault-header/vault-header-v2.component.spec.ts b/apps/browser/src/vault/popup/components/vault-v2/vault-header/vault-header-v2.component.spec.ts
index 38ec6056d19..1f67dd51c21 100644
--- a/apps/browser/src/vault/popup/components/vault-v2/vault-header/vault-header-v2.component.spec.ts
+++ b/apps/browser/src/vault/popup/components/vault-v2/vault-header/vault-header-v2.component.spec.ts
@@ -152,7 +152,7 @@ describe("VaultHeaderV2Component", () => {
it("defaults the initial state to true", (done) => {
// The initial value of the `state$` variable above is undefined
component["initialDisclosureVisibility$"].subscribe((initialVisibility) => {
- expect(initialVisibility).toBeTrue();
+ expect(initialVisibility).toBe(true);
done();
});
diff --git a/apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.html b/apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.html
index b5d92a386b3..c55e8d9fb26 100644
--- a/apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.html
+++ b/apps/browser/src/vault/popup/components/vault-v2/vault-list-items-container/vault-list-items-container.component.html
@@ -1,23 +1,76 @@
0 || description" [disableMargin]="disableSectionMargin">
-
-
-
- {{ title }}
-
-
- {{ ciphers.length }}
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+ {{ ciphers.length }}
+
+
+
+
+
+
+
+
+
{{ description }}
+
+
+
diff --git a/apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.ts b/apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.ts
index a3d8f3ffe31..a0c54987357 100644
--- a/apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.ts
+++ b/apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.ts
@@ -21,6 +21,7 @@ import { VaultPopupItemsService } from "../../services/vault-popup-items.service
import { VaultPopupListFiltersService } from "../../services/vault-popup-list-filters.service";
import { VaultUiOnboardingService } from "../../services/vault-ui-onboarding.service";
+import { BlockedInjectionBanner } from "./blocked-injection-banner/blocked-injection-banner.component";
import {
NewItemDropdownV2Component,
NewItemInitialValues,
@@ -40,6 +41,7 @@ enum VaultState {
templateUrl: "vault-v2.component.html",
standalone: true,
imports: [
+ BlockedInjectionBanner,
PopupPageComponent,
PopupHeaderComponent,
PopOutComponent,
diff --git a/apps/browser/src/vault/popup/components/vault-v2/view-v2/view-v2.component.spec.ts b/apps/browser/src/vault/popup/components/vault-v2/view-v2/view-v2.component.spec.ts
index 7ee15aa833b..526ab2e2579 100644
--- a/apps/browser/src/vault/popup/components/vault-v2/view-v2/view-v2.component.spec.ts
+++ b/apps/browser/src/vault/popup/components/vault-v2/view-v2/view-v2.component.spec.ts
@@ -179,7 +179,7 @@ describe("ViewV2Component", () => {
flush(); // Resolve all promises
- expect(doAutofill).toHaveBeenCalledOnce();
+ expect(doAutofill).toHaveBeenCalledTimes(1);
}));
it('invokes `copy` when action="copy-username"', fakeAsync(() => {
@@ -187,7 +187,7 @@ describe("ViewV2Component", () => {
flush(); // Resolve all promises
- expect(copy).toHaveBeenCalledOnce();
+ expect(copy).toHaveBeenCalledTimes(1);
}));
it('invokes `copy` when action="copy-password"', fakeAsync(() => {
@@ -195,7 +195,7 @@ describe("ViewV2Component", () => {
flush(); // Resolve all promises
- expect(copy).toHaveBeenCalledOnce();
+ expect(copy).toHaveBeenCalledTimes(1);
}));
it('invokes `copy` when action="copy-totp"', fakeAsync(() => {
@@ -203,7 +203,7 @@ describe("ViewV2Component", () => {
flush(); // Resolve all promises
- expect(copy).toHaveBeenCalledOnce();
+ expect(copy).toHaveBeenCalledTimes(1);
}));
it("closes the popout after a load action", fakeAsync(() => {
@@ -218,9 +218,9 @@ describe("ViewV2Component", () => {
flush(); // Resolve all promises
- expect(doAutofill).toHaveBeenCalledOnce();
+ expect(doAutofill).toHaveBeenCalledTimes(1);
expect(focusSpy).toHaveBeenCalledWith(99);
- expect(closeSpy).toHaveBeenCalledOnce();
+ expect(closeSpy).toHaveBeenCalledTimes(1);
}));
});
});
diff --git a/apps/browser/src/vault/popup/services/vault-popup-autofill.service.spec.ts b/apps/browser/src/vault/popup/services/vault-popup-autofill.service.spec.ts
index ae8d4666651..2dad1e3034c 100644
--- a/apps/browser/src/vault/popup/services/vault-popup-autofill.service.spec.ts
+++ b/apps/browser/src/vault/popup/services/vault-popup-autofill.service.spec.ts
@@ -4,6 +4,7 @@ import { mock } from "jest-mock-extended";
import { BehaviorSubject, of } from "rxjs";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
+import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@@ -44,6 +45,7 @@ describe("VaultPopupAutofillService", () => {
// Create mocks for VaultPopupAutofillService
const mockAutofillService = mock();
+ const mockDomainSettingsService = mock();
const mockI18nService = mock();
const mockToastService = mock();
const mockPlatformUtilsService = mock();
@@ -71,6 +73,7 @@ describe("VaultPopupAutofillService", () => {
testBed = TestBed.configureTestingModule({
providers: [
{ provide: AutofillService, useValue: mockAutofillService },
+ { provide: DomainSettingsService, useValue: mockDomainSettingsService },
{ provide: I18nService, useValue: mockI18nService },
{ provide: ToastService, useValue: mockToastService },
{ provide: PlatformUtilsService, useValue: mockPlatformUtilsService },
diff --git a/apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts b/apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts
index 586e9182819..ff282d7a6d0 100644
--- a/apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts
+++ b/apps/browser/src/vault/popup/services/vault-popup-autofill.service.ts
@@ -15,6 +15,7 @@ import {
} from "rxjs";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
+import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@@ -67,6 +68,74 @@ export class VaultPopupAutofillService {
shareReplay({ refCount: false, bufferSize: 1 }),
);
+ currentTabIsOnBlocklist$: Observable = combineLatest([
+ this.domainSettingsService.blockedInteractionsUris$,
+ this.currentAutofillTab$,
+ ]).pipe(
+ map(([blockedInteractionsUris, currentTab]) => {
+ if (blockedInteractionsUris && currentTab?.url?.length) {
+ const tabURL = new URL(currentTab.url);
+ const tabIsBlocked = Object.keys(blockedInteractionsUris).includes(tabURL.hostname);
+
+ if (tabIsBlocked) {
+ return true;
+ }
+ }
+
+ return false;
+ }),
+ shareReplay({ refCount: false, bufferSize: 1 }),
+ );
+
+ showCurrentTabIsBlockedBanner$: Observable = combineLatest([
+ this.domainSettingsService.blockedInteractionsUris$,
+ this.currentAutofillTab$,
+ ]).pipe(
+ map(([blockedInteractionsUris, currentTab]) => {
+ if (blockedInteractionsUris && currentTab?.url?.length) {
+ const tabURL = new URL(currentTab.url);
+ const tabIsBlocked = Object.keys(blockedInteractionsUris).includes(tabURL.hostname);
+
+ const showScriptInjectionIsBlockedBanner =
+ tabIsBlocked && !blockedInteractionsUris[tabURL.hostname]?.bannerIsDismissed;
+
+ return showScriptInjectionIsBlockedBanner;
+ }
+
+ return false;
+ }),
+ shareReplay({ refCount: false, bufferSize: 1 }),
+ );
+
+ async dismissCurrentTabIsBlockedBanner() {
+ try {
+ const currentTab = await firstValueFrom(this.currentAutofillTab$);
+ const currentTabURL = currentTab?.url.length && new URL(currentTab.url);
+
+ const currentTabHostname = currentTabURL && currentTabURL.hostname;
+
+ if (!currentTabHostname) {
+ return;
+ }
+
+ const blockedURIs = await firstValueFrom(this.domainSettingsService.blockedInteractionsUris$);
+ const tabIsBlocked = Object.keys(blockedURIs).includes(currentTabHostname);
+
+ if (tabIsBlocked) {
+ void this.domainSettingsService.setBlockedInteractionsUris({
+ ...blockedURIs,
+ [currentTabHostname as string]: { bannerIsDismissed: true },
+ });
+ }
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ } catch (e) {
+ throw new Error(
+ "There was a problem dismissing the blocked interaction URI notification banner",
+ );
+ }
+ }
+
/**
* Observable that indicates whether autofill is allowed in the current context.
* Autofill is allowed when there is a current tab and the popup is not in a popout window.
@@ -125,6 +194,7 @@ export class VaultPopupAutofillService {
constructor(
private autofillService: AutofillService,
+ private domainSettingsService: DomainSettingsService,
private i18nService: I18nService,
private toastService: ToastService,
private platformUtilService: PlatformUtilsService,
diff --git a/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.spec.ts b/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.spec.ts
index 0eb91c6cbe2..e1236be08f9 100644
--- a/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.spec.ts
+++ b/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.spec.ts
@@ -488,7 +488,7 @@ describe("VaultPopupListFiltersService", () => {
state$.next(true);
service.filterVisibilityState$.subscribe((filterVisibility) => {
- expect(filterVisibility).toBeTrue();
+ expect(filterVisibility).toBe(true);
done();
});
});
@@ -496,7 +496,7 @@ describe("VaultPopupListFiltersService", () => {
it("updates stored filter state", async () => {
await service.updateFilterVisibility(false);
- expect(update).toHaveBeenCalledOnce();
+ expect(update).toHaveBeenCalledTimes(1);
// Get callback passed to `update`
const updateCallback = update.mock.calls[0][0];
expect(updateCallback()).toBe(false);
diff --git a/apps/browser/src/vault/popup/services/vault-popup-section.service.ts b/apps/browser/src/vault/popup/services/vault-popup-section.service.ts
new file mode 100644
index 00000000000..ed641e0cdf7
--- /dev/null
+++ b/apps/browser/src/vault/popup/services/vault-popup-section.service.ts
@@ -0,0 +1,129 @@
+import { computed, effect, inject, Injectable, signal, Signal } from "@angular/core";
+import { toSignal } from "@angular/core/rxjs-interop";
+import { map } from "rxjs";
+
+import {
+ KeyDefinition,
+ StateProvider,
+ VAULT_SETTINGS_DISK,
+} from "@bitwarden/common/platform/state";
+
+import { VaultPopupItemsService } from "./vault-popup-items.service";
+
+export type PopupSectionOpen = {
+ favorites: boolean;
+ allItems: boolean;
+};
+
+const SECTION_OPEN_KEY = new KeyDefinition(VAULT_SETTINGS_DISK, "sectionOpen", {
+ deserializer: (obj) => obj,
+});
+
+const INITIAL_OPEN: PopupSectionOpen = {
+ favorites: true,
+ allItems: true,
+};
+
+@Injectable({
+ providedIn: "root",
+})
+export class VaultPopupSectionService {
+ private vaultPopupItemsService = inject(VaultPopupItemsService);
+ private stateProvider = inject(StateProvider);
+
+ private hasFilterOrSearchApplied = toSignal(
+ this.vaultPopupItemsService.hasFilterApplied$.pipe(map((hasFilter) => hasFilter)),
+ );
+
+ /**
+ * Used to change the open/close state without persisting it to the local disk. Reflects
+ * application-applied overrides.
+ * `null` means there is no current override
+ */
+ private temporaryStateOverride = signal | null>(null);
+
+ constructor() {
+ effect(
+ () => {
+ /**
+ * auto-open all sections when search or filter is applied, and remove
+ * override when search or filter is removed
+ */
+ if (this.hasFilterOrSearchApplied()) {
+ this.temporaryStateOverride.set(INITIAL_OPEN);
+ } else {
+ this.temporaryStateOverride.set(null);
+ }
+ },
+ {
+ allowSignalWrites: true,
+ },
+ );
+ }
+
+ /**
+ * Stored disk state for the open/close state of the sections. Will be `null` if user has never
+ * opened/closed a section
+ */
+ private sectionOpenStateProvider = this.stateProvider.getGlobal(SECTION_OPEN_KEY);
+
+ /**
+ * Stored disk state for the open/close state of the sections, with an initial value provided
+ * if the stored disk state does not yet exist.
+ */
+ private sectionOpenStoredState = toSignal(
+ this.sectionOpenStateProvider.state$.pipe(map((sectionOpen) => sectionOpen ?? INITIAL_OPEN)),
+ // Indicates that the state value is loading
+ { initialValue: null },
+ );
+
+ /**
+ * Indicates the current open/close display state of each section, accounting for temporary
+ * non-persisted overrides.
+ */
+ sectionOpenDisplayState: Signal> = computed(() => ({
+ ...this.sectionOpenStoredState(),
+ ...this.temporaryStateOverride(),
+ }));
+
+ /**
+ * Retrieve the open/close display state for a given section.
+ *
+ * @param sectionKey section key
+ */
+ getOpenDisplayStateForSection(sectionKey: keyof PopupSectionOpen): Signal {
+ return computed(() => this.sectionOpenDisplayState()?.[sectionKey]);
+ }
+
+ /**
+ * Updates the stored open/close state of a given section. Should be called only when a user action
+ * is taken directly to change the open/close state.
+ *
+ * Removes any current temporary override for the given section, as direct user action should
+ * supersede any application-applied overrides.
+ *
+ * @param sectionKey section key
+ */
+ async updateSectionOpenStoredState(
+ sectionKey: keyof PopupSectionOpen,
+ open: boolean,
+ ): Promise {
+ await this.sectionOpenStateProvider.update((currentState) => {
+ return {
+ ...(currentState ?? INITIAL_OPEN),
+ [sectionKey]: open,
+ };
+ });
+
+ this.temporaryStateOverride.update((prev) => {
+ if (prev !== null) {
+ return {
+ ...prev,
+ [sectionKey]: open,
+ };
+ }
+
+ return prev;
+ });
+ }
+}
diff --git a/apps/browser/store/locales/zh_CN/copy.resx b/apps/browser/store/locales/zh_CN/copy.resx
index 3348cf1910c..0f73ccd6619 100644
--- a/apps/browser/store/locales/zh_CN/copy.resx
+++ b/apps/browser/store/locales/zh_CN/copy.resx
@@ -135,11 +135,12 @@
每个人都应该拥有的保持在线安全的工具
使用 Bitwarden 是免费的,没有广告,不会出售数据。Bitwarden 相信每个人都应该拥有保持在线安全的能力。高级计划提供了对高级功能的访问。
-使用 BITWARDEN 为您的团队提供支持
+使用 Bitwarden 为您的团队提供支持
团队计划和企业计划具有专业的商业功能。例如 SSO 集成、自托管、目录集成,以及 SCIM 配置、全局策略、API 访问、事件日志等。
使用 Bitwarden 保护您的劳动成果,并与同事共享敏感信息。
+
选择 Bitwarden 的更多理由:
世界级加密
@@ -164,7 +165,7 @@ Bitwarden 的翻译涵盖 60 多种语言,由全球社区使用 Crowdin 翻译
从任何浏览器、移动设备或桌面操作系统中安全地访问和共享 Bitwarden 密码库中的敏感数据。
Bitwarden 保护的不仅仅是密码
-Bitwarden 的端对端加密凭据管理解决方案使组织能够保护所有内容,包括开发人员机密和通行密钥体验。访问 Bitwarden.com 了解更多关于 Bitwarden Secrets Manager 和 Bitwarden Passwordless.dev 的信息!
+Bitwarden 的端对端加密凭据管理解决方案使组织能够保护所有内容,包括开发人员机密和通行密钥体验。访问 Bitwarden.com 进一步了解 Bitwarden Secrets Manager 和 Bitwarden Passwordless.dev!
无论是在家中、工作中还是在旅途中,Bitwarden 都可以轻松地保护您的所有密码、通行密钥和敏感信息。
diff --git a/apps/cli/package.json b/apps/cli/package.json
index 28432bd5558..8a6dffb1cb3 100644
--- a/apps/cli/package.json
+++ b/apps/cli/package.json
@@ -1,7 +1,7 @@
{
"name": "@bitwarden/cli",
"description": "A secure and free password manager for all of your devices.",
- "version": "2025.1.0",
+ "version": "2025.1.1",
"keywords": [
"bitwarden",
"password",
diff --git a/apps/cli/src/admin-console/commands/share.command.ts b/apps/cli/src/admin-console/commands/share.command.ts
index 5b351efe459..e26d073326e 100644
--- a/apps/cli/src/admin-console/commands/share.command.ts
+++ b/apps/cli/src/admin-console/commands/share.command.ts
@@ -34,6 +34,8 @@ export class ShareCommand {
if (req == null || req.length === 0) {
return Response.badRequest("You must provide at least one collection id for this item.");
}
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
return Response.badRequest("Error parsing the encoded request data.");
}
diff --git a/apps/cli/src/auth/commands/login.command.ts b/apps/cli/src/auth/commands/login.command.ts
index 2a3d5d85408..359ed08ca99 100644
--- a/apps/cli/src/auth/commands/login.command.ts
+++ b/apps/cli/src/auth/commands/login.command.ts
@@ -165,6 +165,8 @@ export class LoginCommand {
if (options.method != null) {
twoFactorMethod = parseInt(options.method, null);
}
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
return Response.error("Invalid two-step login method.");
}
@@ -240,6 +242,8 @@ export class LoginCommand {
if (twoFactorMethod != null) {
try {
selectedProvider = twoFactorProviders.filter((p) => p.type === twoFactorMethod)[0];
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
return Response.error("Invalid two-step login method.");
}
diff --git a/apps/cli/src/commands/edit.command.ts b/apps/cli/src/commands/edit.command.ts
index dd99d03b086..8efb414f5b2 100644
--- a/apps/cli/src/commands/edit.command.ts
+++ b/apps/cli/src/commands/edit.command.ts
@@ -57,6 +57,8 @@ export class EditCommand {
try {
const reqJson = Buffer.from(requestJson, "base64").toString();
req = JSON.parse(reqJson);
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
return Response.badRequest("Error parsing the encoded request data.");
}
diff --git a/apps/cli/src/platform/flags.ts b/apps/cli/src/platform/flags.ts
index dc0103e2436..a762053da35 100644
--- a/apps/cli/src/platform/flags.ts
+++ b/apps/cli/src/platform/flags.ts
@@ -7,11 +7,9 @@ import {
} from "@bitwarden/common/platform/misc/flags";
// required to avoid linting errors when there are no flags
-// eslint-disable-next-line @typescript-eslint/ban-types
export type Flags = {} & SharedFlags;
// required to avoid linting errors when there are no flags
-// eslint-disable-next-line @typescript-eslint/ban-types
export type DevFlags = {} & SharedDevFlags;
export function flagEnabled(flag: keyof Flags): boolean {
diff --git a/apps/cli/src/platform/services/node-env-secure-storage.service.ts b/apps/cli/src/platform/services/node-env-secure-storage.service.ts
index 5e9fdd26b3c..2807509e428 100644
--- a/apps/cli/src/platform/services/node-env-secure-storage.service.ts
+++ b/apps/cli/src/platform/services/node-env-secure-storage.service.ts
@@ -87,6 +87,8 @@ export class NodeEnvSecureStorageService implements AbstractStorageService {
}
return Utils.fromBufferToB64(decValue);
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
this.logService.info("Decrypt error.");
return null;
@@ -104,6 +106,8 @@ export class NodeEnvSecureStorageService implements AbstractStorageService {
}
}
}
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
this.logService.info("Session key is invalid.");
}
diff --git a/apps/cli/src/tools/send/commands/create.command.ts b/apps/cli/src/tools/send/commands/create.command.ts
index eff351be22a..a9264c50126 100644
--- a/apps/cli/src/tools/send/commands/create.command.ts
+++ b/apps/cli/src/tools/send/commands/create.command.ts
@@ -49,6 +49,8 @@ export class SendCreateCommand {
if (req == null) {
throw new Error("Null request");
}
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
return Response.badRequest("Error parsing the encoded request data.");
}
diff --git a/apps/cli/src/tools/send/commands/edit.command.ts b/apps/cli/src/tools/send/commands/edit.command.ts
index 11508d5c417..ed719b58311 100644
--- a/apps/cli/src/tools/send/commands/edit.command.ts
+++ b/apps/cli/src/tools/send/commands/edit.command.ts
@@ -41,6 +41,8 @@ export class SendEditCommand {
try {
const reqJson = Buffer.from(requestJson, "base64").toString();
req = SendResponse.fromJson(reqJson);
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
return Response.badRequest("Error parsing the encoded request data.");
}
diff --git a/apps/cli/src/tools/send/commands/receive.command.ts b/apps/cli/src/tools/send/commands/receive.command.ts
index d27ba4f88ec..41a6681af55 100644
--- a/apps/cli/src/tools/send/commands/receive.command.ts
+++ b/apps/cli/src/tools/send/commands/receive.command.ts
@@ -47,6 +47,8 @@ export class SendReceiveCommand extends DownloadCommand {
let urlObject: URL;
try {
urlObject = new URL(url);
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
return Response.badRequest("Failed to parse the provided Send url");
}
diff --git a/apps/cli/src/vault/create.command.ts b/apps/cli/src/vault/create.command.ts
index 13cd666754f..a28d070d19e 100644
--- a/apps/cli/src/vault/create.command.ts
+++ b/apps/cli/src/vault/create.command.ts
@@ -66,6 +66,8 @@ export class CreateCommand {
try {
const reqJson = Buffer.from(requestJson, "base64").toString();
req = JSON.parse(reqJson);
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
return Response.badRequest("Error parsing the encoded request data.");
}
diff --git a/apps/desktop/config/config.js b/apps/desktop/config/config.js
index 404295dd0db..30a5c16bb2a 100644
--- a/apps/desktop/config/config.js
+++ b/apps/desktop/config/config.js
@@ -32,6 +32,8 @@ function log(configObj) {
function loadConfig(configName) {
try {
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
return require(`./${configName}.json`);
} catch (e) {
if (e instanceof Error && e.code === "MODULE_NOT_FOUND") {
diff --git a/apps/desktop/electron-builder.json b/apps/desktop/electron-builder.json
index c8114d947e4..4302f302473 100644
--- a/apps/desktop/electron-builder.json
+++ b/apps/desktop/electron-builder.json
@@ -20,7 +20,7 @@
"**/node_modules/@bitwarden/desktop-napi/index.js",
"**/node_modules/@bitwarden/desktop-napi/desktop_napi.${platform}-${arch}*.node"
],
- "electronVersion": "33.2.1",
+ "electronVersion": "33.3.1",
"generateUpdatesFilesForAllChannels": true,
"publish": {
"provider": "generic",
diff --git a/apps/desktop/package.json b/apps/desktop/package.json
index c55f39d1b2a..8f6c6525a39 100644
--- a/apps/desktop/package.json
+++ b/apps/desktop/package.json
@@ -1,7 +1,7 @@
{
"name": "@bitwarden/desktop",
"description": "A secure and free password manager for all of your devices.",
- "version": "2025.1.0",
+ "version": "2025.1.2",
"keywords": [
"bitwarden",
"password",
diff --git a/apps/desktop/postcss.config.js b/apps/desktop/postcss.config.js
index c4513687e89..c39e7ea0355 100644
--- a/apps/desktop/postcss.config.js
+++ b/apps/desktop/postcss.config.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-undef */
+/* eslint-disable @typescript-eslint/no-require-imports, no-undef */
module.exports = {
plugins: [require("tailwindcss"), require("autoprefixer"), require("postcss-nested")],
};
diff --git a/apps/desktop/resources/com.bitwarden.desktop.devel.yaml b/apps/desktop/resources/com.bitwarden.desktop.devel.yaml
index 02f2474927e..fea28052f8d 100644
--- a/apps/desktop/resources/com.bitwarden.desktop.devel.yaml
+++ b/apps/desktop/resources/com.bitwarden.desktop.devel.yaml
@@ -8,7 +8,6 @@ command: bitwarden.sh
finish-args:
- --share=ipc
- --share=network
- - --socket=wayland
- --socket=x11
- --device=dri
- --env=XDG_CURRENT_DESKTOP=Unity
@@ -43,5 +42,4 @@ modules:
commands:
- ulimit -c 0
- export TMPDIR="$XDG_RUNTIME_DIR/app/$FLATPAK_ID"
- - exec zypak-wrapper /app/bin/bitwarden-app --ozone-platform-hint=auto
- --enable-features=WaylandWindowDecorations "$@"
+ - exec zypak-wrapper /app/bin/bitwarden-app "$@"
diff --git a/apps/desktop/scripts/after-pack.js b/apps/desktop/scripts/after-pack.js
index fd16cd5ffbe..30b17a44d12 100644
--- a/apps/desktop/scripts/after-pack.js
+++ b/apps/desktop/scripts/after-pack.js
@@ -1,4 +1,4 @@
-/* eslint-disable @typescript-eslint/no-var-requires, no-console */
+/* eslint-disable @typescript-eslint/no-require-imports, no-console */
require("dotenv").config();
const child_process = require("child_process");
const path = require("path");
diff --git a/apps/desktop/scripts/after-sign.js b/apps/desktop/scripts/after-sign.js
index dc60e9d1838..20c24c8a76b 100644
--- a/apps/desktop/scripts/after-sign.js
+++ b/apps/desktop/scripts/after-sign.js
@@ -1,4 +1,4 @@
-/* eslint-disable @typescript-eslint/no-var-requires, no-console */
+/* eslint-disable @typescript-eslint/no-require-imports, no-console */
require("dotenv").config();
const path = require("path");
diff --git a/apps/desktop/scripts/build-macos-extension.js b/apps/desktop/scripts/build-macos-extension.js
index 4cb643c34d4..649fe3b6736 100644
--- a/apps/desktop/scripts/build-macos-extension.js
+++ b/apps/desktop/scripts/build-macos-extension.js
@@ -1,4 +1,4 @@
-/* eslint-disable @typescript-eslint/no-var-requires, no-console */
+/* eslint-disable @typescript-eslint/no-require-imports, no-console */
const child = require("child_process");
const { exit } = require("process");
diff --git a/apps/desktop/scripts/start.js b/apps/desktop/scripts/start.js
index c1a2fb3cffc..d2c984a6f24 100644
--- a/apps/desktop/scripts/start.js
+++ b/apps/desktop/scripts/start.js
@@ -1,4 +1,4 @@
-/* eslint-disable @typescript-eslint/no-var-requires */
+/* eslint-disable @typescript-eslint/no-require-imports */
const concurrently = require("concurrently");
const rimraf = require("rimraf");
diff --git a/apps/desktop/sign.js b/apps/desktop/sign.js
index 74c63932306..f0110ea195b 100644
--- a/apps/desktop/sign.js
+++ b/apps/desktop/sign.js
@@ -1,4 +1,4 @@
-/* eslint-disable @typescript-eslint/no-var-requires, no-console */
+/* eslint-disable @typescript-eslint/no-require-imports, no-console */
exports.default = async function (configuration) {
if (parseInt(process.env.ELECTRON_BUILDER_SIGN) === 1 && configuration.path.slice(-4) == ".exe") {
diff --git a/apps/desktop/src/app/accounts/settings.component.ts b/apps/desktop/src/app/accounts/settings.component.ts
index 19748e797bb..f3440975cf2 100644
--- a/apps/desktop/src/app/accounts/settings.component.ts
+++ b/apps/desktop/src/app/accounts/settings.component.ts
@@ -650,7 +650,7 @@ export class SettingsComponent implements OnInit, OnDestroy {
const skipSupportedPlatformCheck =
ipc.platform.allowBrowserintegrationOverride || ipc.platform.isDev;
- if (skipSupportedPlatformCheck) {
+ if (!skipSupportedPlatformCheck) {
if (
ipc.platform.deviceType === DeviceType.MacOsDesktop &&
!this.platformUtilsService.isMacAppStore()
diff --git a/apps/desktop/src/app/app-routing.module.ts b/apps/desktop/src/app/app-routing.module.ts
index e4ee5ec0473..e565681de93 100644
--- a/apps/desktop/src/app/app-routing.module.ts
+++ b/apps/desktop/src/app/app-routing.module.ts
@@ -67,6 +67,7 @@ import { SendComponent } from "./tools/send/send.component";
/**
* Data properties acceptable for use in route objects in the desktop
*/
+// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface RouteDataProperties {
// For any new route data properties, add them here.
// then assert that the data object satisfies this interface in the route object.
diff --git a/apps/desktop/src/app/app.component.ts b/apps/desktop/src/app/app.component.ts
index 5fefbf9ddff..a05b09e139e 100644
--- a/apps/desktop/src/app/app.component.ts
+++ b/apps/desktop/src/app/app.component.ts
@@ -330,6 +330,20 @@ export class AppComponent implements OnInit, OnDestroy {
}
break;
}
+ case "upgradeOrganization": {
+ const upgradeConfirmed = await this.dialogService.openSimpleDialog({
+ title: { key: "upgradeOrganization" },
+ content: { key: "upgradeOrganizationDesc" },
+ acceptButtonText: { key: "learnMore" },
+ type: "info",
+ });
+ if (upgradeConfirmed) {
+ this.platformUtilsService.launchUri(
+ "https://bitwarden.com/help/upgrade-from-individual-to-org/",
+ );
+ }
+ break;
+ }
case "emailVerificationRequired": {
const emailVerificationConfirmed = await this.dialogService.openSimpleDialog({
title: { key: "emailVerificationRequired" },
diff --git a/apps/desktop/src/app/main.ts b/apps/desktop/src/app/main.ts
index a0b490edaa6..287d66795d2 100644
--- a/apps/desktop/src/app/main.ts
+++ b/apps/desktop/src/app/main.ts
@@ -1,7 +1,9 @@
import { enableProdMode } from "@angular/core";
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
+// eslint-disable-next-line @typescript-eslint/no-require-imports
require("../scss/styles.scss");
+// eslint-disable-next-line @typescript-eslint/no-require-imports
require("../scss/tailwind.css");
import { AppModule } from "./app.module";
diff --git a/apps/desktop/src/auth/login/desktop-login-component.service.ts b/apps/desktop/src/auth/login/desktop-login-component.service.ts
index 8a2daef49ff..dbf689e801c 100644
--- a/apps/desktop/src/auth/login/desktop-login-component.service.ts
+++ b/apps/desktop/src/auth/login/desktop-login-component.service.ts
@@ -65,6 +65,8 @@ export class DesktopLoginComponentService
try {
await ipc.platform.localhostCallbackService.openSsoPrompt(codeChallenge, state);
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (err) {
this.toastService.showToast({
variant: "error",
diff --git a/apps/desktop/src/auth/login/login-v1.component.ts b/apps/desktop/src/auth/login/login-v1.component.ts
index 5b1a1c68d29..e0c3f794dba 100644
--- a/apps/desktop/src/auth/login/login-v1.component.ts
+++ b/apps/desktop/src/auth/login/login-v1.component.ts
@@ -249,6 +249,8 @@ export class LoginComponentV1 extends BaseLoginComponent implements OnInit, OnDe
await this.ssoLoginService.setCodeVerifier(ssoCodeVerifier);
try {
await ipc.platform.localhostCallbackService.openSsoPrompt(codeChallenge, state);
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (err) {
this.platformUtilsService.showToast(
"error",
diff --git a/apps/desktop/src/locales/af/messages.json b/apps/desktop/src/locales/af/messages.json
index 9339d31aa9e..5ee3ba7e029 100644
--- a/apps/desktop/src/locales/af/messages.json
+++ b/apps/desktop/src/locales/af/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Swak wagwoord geidentifiseer en gevind in 'n data lekkasie. Gebruik 'n sterk en unieke wagwoord om jou rekening te beskerm. Is jy seker dat jy hierdie wagwoord wil gebruik?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Kontroleer bekende data lekkasies vir hierdie wagwoord"
},
diff --git a/apps/desktop/src/locales/ar/messages.json b/apps/desktop/src/locales/ar/messages.json
index bb21e0db35f..132021f7760 100644
--- a/apps/desktop/src/locales/ar/messages.json
+++ b/apps/desktop/src/locales/ar/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "كلمة مرور ضعيفة محددة وموجودة في خرق البيانات. استخدم كلمة مرور قوية وفريدة لحماية حسابك. هل أنت متأكد من أنك تريد استخدام كلمة المرور هذه؟"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "تحقق من خروقات البيانات المعروفة لكلمة المرور هذه"
},
diff --git a/apps/desktop/src/locales/az/messages.json b/apps/desktop/src/locales/az/messages.json
index 82fbee81114..9af089d1ef9 100644
--- a/apps/desktop/src/locales/az/messages.json
+++ b/apps/desktop/src/locales/az/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Zəif parol məlumat pozuntusunda aşkarlandı və tapıldı. Hesabınızı qorumaq üçün güclü və unikal bir parol istifadə edin. Bu parolu istifadə etmək istədiyinizə əminsiniz?"
},
+ "useThisPassword": {
+ "message": "Bu parolu istifadə et"
+ },
+ "useThisUsername": {
+ "message": "Bu istifadəçi adını istifadə et"
+ },
"checkForBreaches": {
"message": "Bu parol üçün bilinən məlumat pozuntularını yoxlayın"
},
diff --git a/apps/desktop/src/locales/be/messages.json b/apps/desktop/src/locales/be/messages.json
index 288ba2bede4..e778c59525f 100644
--- a/apps/desktop/src/locales/be/messages.json
+++ b/apps/desktop/src/locales/be/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Вызначаны ненадзейны пароль, які знойдзены ва ўцечках даных. Выкарыстоўвайце надзейныя і ўнікальныя паролі для абароны свайго ўліковага запісу. Вы сапраўды хочаце выкарыстоўваць гэты пароль?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Праверыць у вядомых уцечках даных для гэтага пароля"
},
diff --git a/apps/desktop/src/locales/bg/messages.json b/apps/desktop/src/locales/bg/messages.json
index 3d730a67892..9b000177bbe 100644
--- a/apps/desktop/src/locales/bg/messages.json
+++ b/apps/desktop/src/locales/bg/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Разпозната е слаба парола. Използвайте силна парола, за да защитете данните си. Наистина ли искате да използвате слаба парола?"
},
+ "useThisPassword": {
+ "message": "Използване на тази парола"
+ },
+ "useThisUsername": {
+ "message": "Използване на това потребителско име"
+ },
"checkForBreaches": {
"message": "Проверяване в известните случаи на изтекли данни за тази парола"
},
diff --git a/apps/desktop/src/locales/bn/messages.json b/apps/desktop/src/locales/bn/messages.json
index e4eb247c59e..069c58d751d 100644
--- a/apps/desktop/src/locales/bn/messages.json
+++ b/apps/desktop/src/locales/bn/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/bs/messages.json b/apps/desktop/src/locales/bs/messages.json
index 9b91d3d7c43..f5052559de9 100644
--- a/apps/desktop/src/locales/bs/messages.json
+++ b/apps/desktop/src/locales/bs/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/ca/messages.json b/apps/desktop/src/locales/ca/messages.json
index 2367af72d5c..9d82ad59fad 100644
--- a/apps/desktop/src/locales/ca/messages.json
+++ b/apps/desktop/src/locales/ca/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Contrasenya feble identificada i trobada en una filtració de dades. Utilitzeu una contrasenya única i segura per protegir el vostre compte. Esteu segur que voleu utilitzar aquesta contrasenya?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Comproveu les filtracions de dades conegudes per a aquesta contrasenya"
},
diff --git a/apps/desktop/src/locales/cs/messages.json b/apps/desktop/src/locales/cs/messages.json
index 01d3380d27f..83f2840b724 100644
--- a/apps/desktop/src/locales/cs/messages.json
+++ b/apps/desktop/src/locales/cs/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Slabé heslo bylo nalezeno mezi odhalenými hesly. K zabezpečení Vašeho účtu používejte silné a jedinečné heslo. Opravdu chcete používat toto heslo?"
},
+ "useThisPassword": {
+ "message": "Použít toto heslo"
+ },
+ "useThisUsername": {
+ "message": "Použít toto uživatelské jméno"
+ },
"checkForBreaches": {
"message": "Zkontrolovat heslo, zda nebylo odhaleno"
},
diff --git a/apps/desktop/src/locales/cy/messages.json b/apps/desktop/src/locales/cy/messages.json
index 907f7498f2f..f4e0853a933 100644
--- a/apps/desktop/src/locales/cy/messages.json
+++ b/apps/desktop/src/locales/cy/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/da/messages.json b/apps/desktop/src/locales/da/messages.json
index 766f0cf5e71..ebe74818f47 100644
--- a/apps/desktop/src/locales/da/messages.json
+++ b/apps/desktop/src/locales/da/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Svag adgangskode identificeret og fundet i datalæk. Brug en unik adgangskode til at beskytte din konto. Sikker på, at at denne adgangskode skal bruges?"
},
+ "useThisPassword": {
+ "message": "Anvend denne adgangskode"
+ },
+ "useThisUsername": {
+ "message": "Anvend dette brugernavn"
+ },
"checkForBreaches": {
"message": "Tjek kendte datalæk for denne adgangskode"
},
diff --git a/apps/desktop/src/locales/de/messages.json b/apps/desktop/src/locales/de/messages.json
index d8e946bc3ee..133d98c3faa 100644
--- a/apps/desktop/src/locales/de/messages.json
+++ b/apps/desktop/src/locales/de/messages.json
@@ -250,17 +250,17 @@
"message": "Fehler"
},
"decryptionError": {
- "message": "Decryption error"
+ "message": "Entschlüsselungsfehler"
},
"couldNotDecryptVaultItemsBelow": {
- "message": "Bitwarden could not decrypt the vault item(s) listed below."
+ "message": "Bitwarden konnte folgende(n) Tresor-Eintrag/Einträge nicht entschlüsseln."
},
"contactCSToAvoidDataLossPart1": {
- "message": "Contact customer success",
+ "message": "Kundensupport kontaktieren",
"description": "This is part of a larger sentence. The full sentence will read 'Contact customer success to avoid additional data loss.'"
},
"contactCSToAvoidDataLossPart2": {
- "message": "to avoid additional data loss.",
+ "message": "um zusätzlichen Datenverlust zu vermeiden.",
"description": "This is part of a larger sentence. The full sentence will read 'Contact customer success to avoid additional data loss.'"
},
"january": {
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Schwaches Passwort erkannt und in einem Datendiebstahl gefunden. Verwende ein starkes und einzigartiges Passwort, um dein Konto zu schützen. Bist du sicher, dass du dieses Passwort verwenden möchtest?"
},
+ "useThisPassword": {
+ "message": "Dieses Passwort verwenden"
+ },
+ "useThisUsername": {
+ "message": "Diesen Benutzernamen verwenden"
+ },
"checkForBreaches": {
"message": "Bekannte Datendiebstähle auf dieses Passwort überprüfen"
},
@@ -3377,19 +3383,19 @@
"message": "Es konnten keine freien Ports für die SSO-Anmeldung gefunden werden."
},
"biometricsStatusHelptextUnlockNeeded": {
- "message": "Biometric unlock is unavailable because PIN or password unlock is required first."
+ "message": "Biometrisches Entsperren ist nicht verfügbar, da zuerst mit PIN oder Passwort entsperrt werden muss."
},
"biometricsStatusHelptextHardwareUnavailable": {
- "message": "Biometric unlock is currently unavailable."
+ "message": "Biometrisches Entsperren ist derzeit nicht verfügbar."
},
"biometricsStatusHelptextAutoSetupNeeded": {
- "message": "Biometric unlock is unavailable due to misconfigured system files."
+ "message": "Biometrisches Entsperren ist aufgrund falsch konfigurierter Systemdateien nicht verfügbar."
},
"biometricsStatusHelptextManualSetupNeeded": {
- "message": "Biometric unlock is unavailable due to misconfigured system files."
+ "message": "Biometrisches Entsperren ist aufgrund falsch konfigurierter Systemdateien nicht verfügbar."
},
"biometricsStatusHelptextNotEnabledLocally": {
- "message": "Biometric unlock is unavailable because it is not enabled for $EMAIL$ in the Bitwarden desktop app.",
+ "message": "Biometrisches Entsperren ist nicht verfügbar, da es für $EMAIL$ in der Bitwarden Desktop-App nicht aktiviert ist.",
"placeholders": {
"email": {
"content": "$1",
@@ -3398,7 +3404,7 @@
}
},
"biometricsStatusHelptextUnavailableReasonUnknown": {
- "message": "Biometric unlock is currently unavailable for an unknown reason."
+ "message": "Biometrisches Entsperren ist derzeit aus einem unbekannten Grund nicht verfügbar."
},
"authorize": {
"message": "Autorisieren"
diff --git a/apps/desktop/src/locales/el/messages.json b/apps/desktop/src/locales/el/messages.json
index b134c0d3db8..145f386c6b9 100644
--- a/apps/desktop/src/locales/el/messages.json
+++ b/apps/desktop/src/locales/el/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Βρέθηκε και ταυτοποιήθηκε αδύναμος κωδικός σε μια διαρροή δεδομένων. Χρησιμοποιήστε ένα ισχυρό και μοναδικό κωδικό πρόσβασης για την προστασία του λογαριασμού σας. Είστε σίγουροι ότι θέλετε να χρησιμοποιήσετε αυτόν τον κωδικό πρόσβασης;"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Ελέγξτε γνωστές διαρροές δεδομένων για αυτόν τον κωδικό"
},
diff --git a/apps/desktop/src/locales/en/messages.json b/apps/desktop/src/locales/en/messages.json
index 35d5cf8c03c..bca12f16a7d 100644
--- a/apps/desktop/src/locales/en/messages.json
+++ b/apps/desktop/src/locales/en/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
@@ -3468,5 +3474,14 @@
},
"changeAcctEmail": {
"message": "Change account email"
+ },
+ "organizationUpgradeRequired": {
+ "message": "Organization upgrade required"
+ },
+ "upgradeOrganization": {
+ "message": "Upgrade organization"
+ },
+ "upgradeOrganizationDesc": {
+ "message": "This feature is not available for free organizations. Switch to a paid plan to unlock more features."
}
}
diff --git a/apps/desktop/src/locales/en_GB/messages.json b/apps/desktop/src/locales/en_GB/messages.json
index 1f705b54329..acca06b8b4f 100644
--- a/apps/desktop/src/locales/en_GB/messages.json
+++ b/apps/desktop/src/locales/en_GB/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/en_IN/messages.json b/apps/desktop/src/locales/en_IN/messages.json
index bdabdb2f376..122217dae9d 100644
--- a/apps/desktop/src/locales/en_IN/messages.json
+++ b/apps/desktop/src/locales/en_IN/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/eo/messages.json b/apps/desktop/src/locales/eo/messages.json
index 7cbd15b5965..a4621439f50 100644
--- a/apps/desktop/src/locales/eo/messages.json
+++ b/apps/desktop/src/locales/eo/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/es/messages.json b/apps/desktop/src/locales/es/messages.json
index 27f694ec189..1915002b6bd 100644
--- a/apps/desktop/src/locales/es/messages.json
+++ b/apps/desktop/src/locales/es/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Contraseña débil encontrada en una filtración de datos. Utilice una contraseña única para proteger su cuenta. ¿Está seguro de que desea utilizar una contraseña comprometida?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Comprobar filtración de datos conocidos para esta contraseña"
},
diff --git a/apps/desktop/src/locales/et/messages.json b/apps/desktop/src/locales/et/messages.json
index ec73ac1e8b2..8396316416b 100644
--- a/apps/desktop/src/locales/et/messages.json
+++ b/apps/desktop/src/locales/et/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Tuvastati nõrk ning andmelekkes lekkinud ülemparool. Kasuta konto paremaks turvamiseks tugevamat parooli. Oled kindel, et soovid nõrga parooliga jätkata?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Otsi seda parooli teadaolevatest andmeleketest"
},
diff --git a/apps/desktop/src/locales/eu/messages.json b/apps/desktop/src/locales/eu/messages.json
index 0147b474ab1..2daed855e52 100644
--- a/apps/desktop/src/locales/eu/messages.json
+++ b/apps/desktop/src/locales/eu/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/fa/messages.json b/apps/desktop/src/locales/fa/messages.json
index a04c39d4ae0..b79dc2d90ee 100644
--- a/apps/desktop/src/locales/fa/messages.json
+++ b/apps/desktop/src/locales/fa/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "کلمه عبور ضعیف شناسایی و در یک نقض داده پیدا شد. از یک کلمه عبور قوی و منحصر به فرد برای محافظت از حساب خود استفاده کنید. آیا مطمئنید که میخواهید از این کلمه عبور استفاده کنید؟"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "نقض اطلاعات شناخته شده برای این کلمه عبور را بررسی کنید"
},
diff --git a/apps/desktop/src/locales/fi/messages.json b/apps/desktop/src/locales/fi/messages.json
index 193553cac83..2d0a8cae996 100644
--- a/apps/desktop/src/locales/fi/messages.json
+++ b/apps/desktop/src/locales/fi/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Havaittiin heikko ja tietovuodosta löytynyt salasana. Sinun tulisi suojata tilisi vahvalla ja ainutlaatuisella salasanalla. Haluatko varmasti käyttää tätä salasanaa?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Tarkasta esiintyykö salasanaa tunnetuissa tietovuodoissa"
},
diff --git a/apps/desktop/src/locales/fil/messages.json b/apps/desktop/src/locales/fil/messages.json
index 53b2ef9ffba..1f77b85e3c5 100644
--- a/apps/desktop/src/locales/fil/messages.json
+++ b/apps/desktop/src/locales/fil/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Mahinang password na nakilala at nakita sa data breach. Gamitin ang malakas at natatanging password upang makaproteksyon sa iyong account. Sigurado ka ba na gusto mong gamitin ang password na ito?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Tingnan ang kilalang breaches ng data para sa password na ito"
},
diff --git a/apps/desktop/src/locales/fr/messages.json b/apps/desktop/src/locales/fr/messages.json
index f1bf4243874..f0ab36ba636 100644
--- a/apps/desktop/src/locales/fr/messages.json
+++ b/apps/desktop/src/locales/fr/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Mot de passe faible identifié et trouvé dans une brèche de données. Utilisez un mot de passe robuste et unique pour protéger votre compte. Êtes-vous sûr de vouloir utiliser ce mot de passe ?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Vérifier les brèches de données connues pour ce mot de passe"
},
diff --git a/apps/desktop/src/locales/gl/messages.json b/apps/desktop/src/locales/gl/messages.json
index 35d5cf8c03c..1a02e5db4e7 100644
--- a/apps/desktop/src/locales/gl/messages.json
+++ b/apps/desktop/src/locales/gl/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/he/messages.json b/apps/desktop/src/locales/he/messages.json
index 09d6e321a12..df61cefe73d 100644
--- a/apps/desktop/src/locales/he/messages.json
+++ b/apps/desktop/src/locales/he/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/hi/messages.json b/apps/desktop/src/locales/hi/messages.json
index 3263191cd31..723ea0f6992 100644
--- a/apps/desktop/src/locales/hi/messages.json
+++ b/apps/desktop/src/locales/hi/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/hr/messages.json b/apps/desktop/src/locales/hr/messages.json
index b1def7c192c..109a1abff21 100644
--- a/apps/desktop/src/locales/hr/messages.json
+++ b/apps/desktop/src/locales/hr/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Slaba lozinka je nađena među ukradenima tijekom krađa podataka. Za zaštitu svog računa koristi jaku i jedinstvenu lozinku. Želiš li svejedno korisiti slabu, ukradenu lozinku?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Provjeri je li lozinka ukradena prilikom krađe podataka"
},
diff --git a/apps/desktop/src/locales/hu/messages.json b/apps/desktop/src/locales/hu/messages.json
index fb94d34b387..3716e1e67a9 100644
--- a/apps/desktop/src/locales/hu/messages.json
+++ b/apps/desktop/src/locales/hu/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Gyenge jelszó lett azonosítva és megtalálva egy adatvédelmi incidens során. A fók védelme érdekében használjunk erős és egyedi jelszót. Biztosan használni szeretnénk ezt a jelszót?"
},
+ "useThisPassword": {
+ "message": "Jelszó használata"
+ },
+ "useThisUsername": {
+ "message": "Felhasználónév használata"
+ },
"checkForBreaches": {
"message": "Az ehhez a jelszóhoz tartozó ismert adatvédelmi incidensek ellenőrzése"
},
diff --git a/apps/desktop/src/locales/id/messages.json b/apps/desktop/src/locales/id/messages.json
index 989177b1b43..d4bcded0ee8 100644
--- a/apps/desktop/src/locales/id/messages.json
+++ b/apps/desktop/src/locales/id/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Periksa pelanggaran data yang diketahui untuk kata sandi ini"
},
diff --git a/apps/desktop/src/locales/it/messages.json b/apps/desktop/src/locales/it/messages.json
index 13e4c692f69..c85127fce20 100644
--- a/apps/desktop/src/locales/it/messages.json
+++ b/apps/desktop/src/locales/it/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Password debole e trovata in una violazione dei dati. Usa una password forte e unica per proteggere il tuo account. Sei sicuro di voler usare questa password?"
},
+ "useThisPassword": {
+ "message": "Usa questa parola d'accesso"
+ },
+ "useThisUsername": {
+ "message": "Usa questo nome utente"
+ },
"checkForBreaches": {
"message": "Controlla se la tua password è presente in una violazione dei dati"
},
diff --git a/apps/desktop/src/locales/ja/messages.json b/apps/desktop/src/locales/ja/messages.json
index 364de39788b..9ce8f6a3ea7 100644
--- a/apps/desktop/src/locales/ja/messages.json
+++ b/apps/desktop/src/locales/ja/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "入力されたパスワードは脆弱かつすでに流出済みです。アカウントを守るためより強力で一意なパスワードを使用してください。本当にこの脆弱なパスワードを使用しますか?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "このパスワードの既知のデータ流出を確認"
},
diff --git a/apps/desktop/src/locales/ka/messages.json b/apps/desktop/src/locales/ka/messages.json
index fef2d56a7c2..bf434a6c29f 100644
--- a/apps/desktop/src/locales/ka/messages.json
+++ b/apps/desktop/src/locales/ka/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/km/messages.json b/apps/desktop/src/locales/km/messages.json
index 35d5cf8c03c..1a02e5db4e7 100644
--- a/apps/desktop/src/locales/km/messages.json
+++ b/apps/desktop/src/locales/km/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/kn/messages.json b/apps/desktop/src/locales/kn/messages.json
index 9ce484b3810..f3401477f4a 100644
--- a/apps/desktop/src/locales/kn/messages.json
+++ b/apps/desktop/src/locales/kn/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/ko/messages.json b/apps/desktop/src/locales/ko/messages.json
index 19a13ef3e81..1aafdc4bc6d 100644
--- a/apps/desktop/src/locales/ko/messages.json
+++ b/apps/desktop/src/locales/ko/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/lt/messages.json b/apps/desktop/src/locales/lt/messages.json
index c1fafc59f12..11c70dd4197 100644
--- a/apps/desktop/src/locales/lt/messages.json
+++ b/apps/desktop/src/locales/lt/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Silpnas slaptažodis nustatytas ir rastas per duomenų pažeidimą. Norėdami apsaugoti paskyrą, naudokite stiprų ir unikalų slaptažodį. Ar tikrai norite naudoti šį slaptažodį?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Patikrinti žinomus šio slaptažodžio duomenų pažeidimus"
},
diff --git a/apps/desktop/src/locales/lv/messages.json b/apps/desktop/src/locales/lv/messages.json
index f2317e1d0bb..68495a25137 100644
--- a/apps/desktop/src/locales/lv/messages.json
+++ b/apps/desktop/src/locales/lv/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Noteikta vāja parole, un tā ir atrasta datu noplūdē. Jāizmanto spēcīga un neatkārtojama parole, lai aizsargātu savu kontu. Vai tiešām izmantot šo paroli?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Meklēt šo paroli zināmās datu noplūdēs"
},
diff --git a/apps/desktop/src/locales/me/messages.json b/apps/desktop/src/locales/me/messages.json
index 50a6ee8df58..ac9994c3134 100644
--- a/apps/desktop/src/locales/me/messages.json
+++ b/apps/desktop/src/locales/me/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/ml/messages.json b/apps/desktop/src/locales/ml/messages.json
index e1516b99b23..15d4de334eb 100644
--- a/apps/desktop/src/locales/ml/messages.json
+++ b/apps/desktop/src/locales/ml/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/mr/messages.json b/apps/desktop/src/locales/mr/messages.json
index 35d5cf8c03c..1a02e5db4e7 100644
--- a/apps/desktop/src/locales/mr/messages.json
+++ b/apps/desktop/src/locales/mr/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/my/messages.json b/apps/desktop/src/locales/my/messages.json
index ce5a50e1f70..ca399731495 100644
--- a/apps/desktop/src/locales/my/messages.json
+++ b/apps/desktop/src/locales/my/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/nb/messages.json b/apps/desktop/src/locales/nb/messages.json
index 00970fb0fc6..0ebecf3be8f 100644
--- a/apps/desktop/src/locales/nb/messages.json
+++ b/apps/desktop/src/locales/nb/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/ne/messages.json b/apps/desktop/src/locales/ne/messages.json
index 6a5ae864fc1..624547d2121 100644
--- a/apps/desktop/src/locales/ne/messages.json
+++ b/apps/desktop/src/locales/ne/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/nl/messages.json b/apps/desktop/src/locales/nl/messages.json
index 729a093927e..6f3670afa3d 100644
--- a/apps/desktop/src/locales/nl/messages.json
+++ b/apps/desktop/src/locales/nl/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Zwak wachtwoord geïdentificeerd en gevonden in een datalek. Gebruik een sterk en uniek wachtwoord om je account te beschermen. Weet je zeker dat je dit wachtwoord wilt gebruiken?"
},
+ "useThisPassword": {
+ "message": "Dit wachtwoord gebruiken"
+ },
+ "useThisUsername": {
+ "message": "Deze gebruikersnaam gebruiken"
+ },
"checkForBreaches": {
"message": "Bekende datalekken voor dit wachtwoord controleren"
},
diff --git a/apps/desktop/src/locales/nn/messages.json b/apps/desktop/src/locales/nn/messages.json
index 7e18c7b77d2..df2f70ae839 100644
--- a/apps/desktop/src/locales/nn/messages.json
+++ b/apps/desktop/src/locales/nn/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/or/messages.json b/apps/desktop/src/locales/or/messages.json
index 903fe83af70..ea55a1c6029 100644
--- a/apps/desktop/src/locales/or/messages.json
+++ b/apps/desktop/src/locales/or/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/pl/messages.json b/apps/desktop/src/locales/pl/messages.json
index 59cf3a96ab9..d7b950100f5 100644
--- a/apps/desktop/src/locales/pl/messages.json
+++ b/apps/desktop/src/locales/pl/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Słabe hasło ujawnione w wyniku naruszenia ochrony danych. Użyj silnego i unikalnego hasła, aby chronić swoje konto. Czy na pewno chcesz użyć tego hasła?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Sprawdź znane naruszenia ochrony danych tego hasła"
},
diff --git a/apps/desktop/src/locales/pt_BR/messages.json b/apps/desktop/src/locales/pt_BR/messages.json
index 0e35de82e7c..312fe4e8e89 100644
--- a/apps/desktop/src/locales/pt_BR/messages.json
+++ b/apps/desktop/src/locales/pt_BR/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Senha fraca identificada e encontrada em um vazamento de dados. Use uma senha forte e única para proteger a sua conta. Tem certeza de que deseja usar essa senha?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Verificar vazamentos de dados conhecidos para esta senha"
},
diff --git a/apps/desktop/src/locales/pt_PT/messages.json b/apps/desktop/src/locales/pt_PT/messages.json
index a63fbca2ebc..d88862a7980 100644
--- a/apps/desktop/src/locales/pt_PT/messages.json
+++ b/apps/desktop/src/locales/pt_PT/messages.json
@@ -250,17 +250,17 @@
"message": "Erro"
},
"decryptionError": {
- "message": "Decryption error"
+ "message": "Erro de desencriptação"
},
"couldNotDecryptVaultItemsBelow": {
- "message": "Bitwarden could not decrypt the vault item(s) listed below."
+ "message": "O Bitwarden não conseguiu desencriptar o(s) item(ns) do cofre listado(s) abaixo."
},
"contactCSToAvoidDataLossPart1": {
- "message": "Contact customer success",
+ "message": "Contacte o serviço de apoio ao cliente",
"description": "This is part of a larger sentence. The full sentence will read 'Contact customer success to avoid additional data loss.'"
},
"contactCSToAvoidDataLossPart2": {
- "message": "to avoid additional data loss.",
+ "message": "para evitar perdas adicionais de dados.",
"description": "This is part of a larger sentence. The full sentence will read 'Contact customer success to avoid additional data loss.'"
},
"january": {
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Palavra-passe fraca identificada e encontrada numa violação de dados. Utilize uma palavra-passe forte e única para proteger a sua conta. Tem a certeza de que pretende utilizar esta palavra-passe?"
},
+ "useThisPassword": {
+ "message": "Utilizar esta palavra-passe"
+ },
+ "useThisUsername": {
+ "message": "Utilizar este nome de utilizador"
+ },
"checkForBreaches": {
"message": "Verificar violações de dados conhecidas para esta palavra-passe"
},
@@ -3377,19 +3383,19 @@
"message": "Não foi possível encontrar portas livres para o início de sessão sso."
},
"biometricsStatusHelptextUnlockNeeded": {
- "message": "Biometric unlock is unavailable because PIN or password unlock is required first."
+ "message": "O desbloqueio biométrico não está disponível porque o desbloqueio por PIN ou palavra-passe é necessário primeiro."
},
"biometricsStatusHelptextHardwareUnavailable": {
- "message": "Biometric unlock is currently unavailable."
+ "message": "O desbloqueio biométrico está atualmente indisponível."
},
"biometricsStatusHelptextAutoSetupNeeded": {
- "message": "Biometric unlock is unavailable due to misconfigured system files."
+ "message": "O desbloqueio biométrico não está disponível devido a ficheiros de sistema mal configurados."
},
"biometricsStatusHelptextManualSetupNeeded": {
- "message": "Biometric unlock is unavailable due to misconfigured system files."
+ "message": "O desbloqueio biométrico não está disponível devido a ficheiros de sistema mal configurados."
},
"biometricsStatusHelptextNotEnabledLocally": {
- "message": "Biometric unlock is unavailable because it is not enabled for $EMAIL$ in the Bitwarden desktop app.",
+ "message": "O desbloqueio biométrico não está disponível porque não está ativado para $EMAIL$ na app Bitwarden para computador.",
"placeholders": {
"email": {
"content": "$1",
@@ -3398,7 +3404,7 @@
}
},
"biometricsStatusHelptextUnavailableReasonUnknown": {
- "message": "Biometric unlock is currently unavailable for an unknown reason."
+ "message": "O desbloqueio biométrico está atualmente indisponível por um motivo desconhecido."
},
"authorize": {
"message": "Autorizar"
diff --git a/apps/desktop/src/locales/ro/messages.json b/apps/desktop/src/locales/ro/messages.json
index 939c3295898..d4ca5e21a5e 100644
--- a/apps/desktop/src/locales/ro/messages.json
+++ b/apps/desktop/src/locales/ro/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/ru/messages.json b/apps/desktop/src/locales/ru/messages.json
index d8aa6556a0d..46e04b77704 100644
--- a/apps/desktop/src/locales/ru/messages.json
+++ b/apps/desktop/src/locales/ru/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Обнаружен слабый пароль, найденный в утечке данных. Используйте надежный и уникальный пароль для защиты вашего аккаунта. Вы уверены, что хотите использовать этот пароль?"
},
+ "useThisPassword": {
+ "message": "Использовать этот пароль"
+ },
+ "useThisUsername": {
+ "message": "Использовать это имя пользователя"
+ },
"checkForBreaches": {
"message": "Проверять известные случаи утечки данных для этого пароля"
},
diff --git a/apps/desktop/src/locales/si/messages.json b/apps/desktop/src/locales/si/messages.json
index 210ccc7383b..5372bf59637 100644
--- a/apps/desktop/src/locales/si/messages.json
+++ b/apps/desktop/src/locales/si/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/sk/messages.json b/apps/desktop/src/locales/sk/messages.json
index bfcfb56f984..07851ddc47e 100644
--- a/apps/desktop/src/locales/sk/messages.json
+++ b/apps/desktop/src/locales/sk/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Nájdené slabé heslo v uniknuných údajoch. Na ochranu svojho účtu používajte silné a jedinečné heslo. Naozaj chcete používať toto heslo?"
},
+ "useThisPassword": {
+ "message": "Použiť toto heslo"
+ },
+ "useThisUsername": {
+ "message": "Použiť toto používateľské meno"
+ },
"checkForBreaches": {
"message": "Skontrolovať známe úniky údajov pre toto heslo"
},
diff --git a/apps/desktop/src/locales/sl/messages.json b/apps/desktop/src/locales/sl/messages.json
index 0270b7ba3f1..c4fae11c815 100644
--- a/apps/desktop/src/locales/sl/messages.json
+++ b/apps/desktop/src/locales/sl/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/sr/messages.json b/apps/desktop/src/locales/sr/messages.json
index d8544d8285a..03cc5b8c265 100644
--- a/apps/desktop/src/locales/sr/messages.json
+++ b/apps/desktop/src/locales/sr/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Идентификована је слаба лозинка и пронађена у упаду података. Користите јаку и јединствену лозинку да заштитите свој налог. Да ли сте сигурни да желите да користите ову лозинку?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Проверите познате упада података за ову лозинку"
},
diff --git a/apps/desktop/src/locales/sv/messages.json b/apps/desktop/src/locales/sv/messages.json
index 023b74b12b4..920981908fa 100644
--- a/apps/desktop/src/locales/sv/messages.json
+++ b/apps/desktop/src/locales/sv/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Lösenordet är svagt och avslöjades vid ett dataintrång. Använd ett starkt och unikt lösenord för att skydda ditt konto. Är det säkert att du vill använda detta lösenord?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Kontrollera kända dataintrång för detta lösenord"
},
diff --git a/apps/desktop/src/locales/te/messages.json b/apps/desktop/src/locales/te/messages.json
index 35d5cf8c03c..1a02e5db4e7 100644
--- a/apps/desktop/src/locales/te/messages.json
+++ b/apps/desktop/src/locales/te/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/th/messages.json b/apps/desktop/src/locales/th/messages.json
index b5cc86b1e54..7f7e373132c 100644
--- a/apps/desktop/src/locales/th/messages.json
+++ b/apps/desktop/src/locales/th/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Check known data breaches for this password"
},
diff --git a/apps/desktop/src/locales/tr/messages.json b/apps/desktop/src/locales/tr/messages.json
index 5f11450a207..2fbd751ddb8 100644
--- a/apps/desktop/src/locales/tr/messages.json
+++ b/apps/desktop/src/locales/tr/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Hem zayıf hem de veri ihlalinde yer alan bir tespit edildi. Hesabınızı korumak için güçlü bir parola seçin ve o parolayı başka yerlerde kullanmayın. Bu parolayı kullanmak istediğinizden emin misiniz?"
},
+ "useThisPassword": {
+ "message": "Bu parolayı kullan"
+ },
+ "useThisUsername": {
+ "message": "Bu kullanıcı adını kullan"
+ },
"checkForBreaches": {
"message": "Bilinen veri ihlallerinde bu parolayı kontrol et"
},
diff --git a/apps/desktop/src/locales/uk/messages.json b/apps/desktop/src/locales/uk/messages.json
index d4126a6b647..db0259adc05 100644
--- a/apps/desktop/src/locales/uk/messages.json
+++ b/apps/desktop/src/locales/uk/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Виявлено слабкий пароль, який знайдено у витоку даних. Використовуйте надійний та унікальний пароль для захисту свого облікового запису. Ви дійсно хочете використати цей пароль?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Перевірити відомі витоки даних для цього пароля"
},
diff --git a/apps/desktop/src/locales/vi/messages.json b/apps/desktop/src/locales/vi/messages.json
index fcd113f3071..07dcdfd373c 100644
--- a/apps/desktop/src/locales/vi/messages.json
+++ b/apps/desktop/src/locales/vi/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "Mật khẩu yếu này đã bị rò rỉ trong một vụ tấn công dữ liệu. Dùng mật khẩu mới và an toàn để bảo vệ tài khoản bạn. Bạn có chắc muốn sử dụng mật khẩu đã bị rò rỉ?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "Kiểm tra mật khẩu có lộ trong các vụ rò rỉ dữ liệu hay không"
},
diff --git a/apps/desktop/src/locales/zh_CN/messages.json b/apps/desktop/src/locales/zh_CN/messages.json
index 0285842f04e..c9046b34a55 100644
--- a/apps/desktop/src/locales/zh_CN/messages.json
+++ b/apps/desktop/src/locales/zh_CN/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "识别到弱密码且其出现在数据泄露中。请使用一个强且唯一的密码以保护你的账户。确定要使用这个密码吗?"
},
+ "useThisPassword": {
+ "message": "使用此密码"
+ },
+ "useThisUsername": {
+ "message": "使用此用户名"
+ },
"checkForBreaches": {
"message": "检查已知的数据泄露是否包含此密码"
},
diff --git a/apps/desktop/src/locales/zh_TW/messages.json b/apps/desktop/src/locales/zh_TW/messages.json
index b5ca02d6c8b..a9206a50df6 100644
--- a/apps/desktop/src/locales/zh_TW/messages.json
+++ b/apps/desktop/src/locales/zh_TW/messages.json
@@ -2879,6 +2879,12 @@
"weakAndBreachedMasterPasswordDesc": {
"message": "密碼強度不足,且該密碼已洩露。請使用一個強度足夠和獨特的密碼來保護您的帳戶。您確定要使用這個密碼嗎?"
},
+ "useThisPassword": {
+ "message": "Use this password"
+ },
+ "useThisUsername": {
+ "message": "Use this username"
+ },
"checkForBreaches": {
"message": "檢查外洩的密碼資料庫中是否包含此密碼"
},
diff --git a/apps/desktop/src/main/native-messaging.main.ts b/apps/desktop/src/main/native-messaging.main.ts
index 6915a18deda..107d546811c 100644
--- a/apps/desktop/src/main/native-messaging.main.ts
+++ b/apps/desktop/src/main/native-messaging.main.ts
@@ -405,6 +405,8 @@ export class NativeMessagingMain {
this.logService.info(`Error reading preferences: ${e}`);
}
}
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
// Browser is not installed, we can just skip it
}
diff --git a/apps/desktop/src/package-lock.json b/apps/desktop/src/package-lock.json
index f93d9059bc7..d878e1af2aa 100644
--- a/apps/desktop/src/package-lock.json
+++ b/apps/desktop/src/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@bitwarden/desktop",
- "version": "2025.1.0",
+ "version": "2025.1.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@bitwarden/desktop",
- "version": "2025.1.0",
+ "version": "2025.1.2",
"license": "GPL-3.0",
"dependencies": {
"@bitwarden/desktop-napi": "file:../desktop_native/napi"
diff --git a/apps/desktop/src/package.json b/apps/desktop/src/package.json
index 39e16815020..08bdd745063 100644
--- a/apps/desktop/src/package.json
+++ b/apps/desktop/src/package.json
@@ -2,7 +2,7 @@
"name": "@bitwarden/desktop",
"productName": "Bitwarden",
"description": "A secure and free password manager for all of your devices.",
- "version": "2025.1.0",
+ "version": "2025.1.2",
"author": "Bitwarden Inc. (https://bitwarden.com)",
"homepage": "https://bitwarden.com",
"license": "GPL-3.0",
diff --git a/apps/desktop/src/platform/flags.ts b/apps/desktop/src/platform/flags.ts
index dc0103e2436..a762053da35 100644
--- a/apps/desktop/src/platform/flags.ts
+++ b/apps/desktop/src/platform/flags.ts
@@ -7,11 +7,9 @@ import {
} from "@bitwarden/common/platform/misc/flags";
// required to avoid linting errors when there are no flags
-// eslint-disable-next-line @typescript-eslint/ban-types
export type Flags = {} & SharedFlags;
// required to avoid linting errors when there are no flags
-// eslint-disable-next-line @typescript-eslint/ban-types
export type DevFlags = {} & SharedDevFlags;
export function flagEnabled(flag: keyof Flags): boolean {
diff --git a/apps/desktop/src/platform/services/ssh-agent.service.ts b/apps/desktop/src/platform/services/ssh-agent.service.ts
index 726d28022e5..d4c7c5f460e 100644
--- a/apps/desktop/src/platform/services/ssh-agent.service.ts
+++ b/apps/desktop/src/platform/services/ssh-agent.service.ts
@@ -83,6 +83,15 @@ export class SshAgentService implements OnDestroy {
this.messageListener
.messages$(new CommandDefinition("sshagent.signrequest"))
.pipe(
+ withLatestFrom(this.desktopSettingsService.sshAgentEnabled$),
+ concatMap(async ([message, enabled]) => {
+ if (!enabled) {
+ await ipc.platform.sshAgent.signRequestResponse(message.requestId as number, false);
+ }
+ return { message, enabled };
+ }),
+ filter(({ enabled }) => enabled),
+ map(({ message }) => message),
withLatestFrom(this.authService.activeAccountStatus$),
// This switchMap handles unlocking the vault if it is locked:
// - If the vault is locked, we will wait for it to be unlocked.
diff --git a/apps/desktop/src/services/biometric-message-handler.service.ts b/apps/desktop/src/services/biometric-message-handler.service.ts
index ea1e7e76c56..74f80785fca 100644
--- a/apps/desktop/src/services/biometric-message-handler.service.ts
+++ b/apps/desktop/src/services/biometric-message-handler.service.ts
@@ -188,7 +188,7 @@ export class BiometricMessageHandlerService {
appId,
);
}
- // TODO: legacy, remove after 2025.01
+ // TODO: legacy, remove after 2025.3
case BiometricsCommands.IsAvailable: {
const available =
(await this.biometricsService.getBiometricsStatus()) == BiometricsStatus.Available;
@@ -200,7 +200,7 @@ export class BiometricMessageHandlerService {
appId,
);
}
- // TODO: legacy, remove after 2025.01
+ // TODO: legacy, remove after 2025.3
case BiometricsCommands.Unlock: {
const isTemporarilyDisabled =
(await this.biometricStateService.getBiometricUnlockEnabled(message.userId as UserId)) &&
@@ -265,6 +265,8 @@ export class BiometricMessageHandlerService {
} else {
await this.send({ command: "biometricUnlock", response: "canceled" }, appId);
}
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
await this.send({ command: "biometricUnlock", response: "canceled" }, appId);
}
@@ -342,6 +344,8 @@ export class BiometricMessageHandlerService {
appId,
);
}
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
await this.send(
{ command: BiometricsCommands.UnlockWithBiometricsForUser, messageId, response: false },
diff --git a/apps/desktop/src/services/duckduckgo-message-handler.service.ts b/apps/desktop/src/services/duckduckgo-message-handler.service.ts
index 9a914f238b5..fa5c2f4d9f7 100644
--- a/apps/desktop/src/services/duckduckgo-message-handler.service.ts
+++ b/apps/desktop/src/services/duckduckgo-message-handler.service.ts
@@ -130,6 +130,8 @@ export class DuckDuckGoMessageHandlerService {
sharedKey: Utils.fromBufferToB64(encryptedSecret),
},
});
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
this.sendResponse({
messageId: messageId,
@@ -153,6 +155,8 @@ export class DuckDuckGoMessageHandlerService {
await this.encryptedMessageHandlerService.responseDataForCommand(decryptedCommandData);
await this.sendEncryptedResponse(message, { command, payload: responseData });
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
diff --git a/apps/desktop/src/services/encrypted-message-handler.service.ts b/apps/desktop/src/services/encrypted-message-handler.service.ts
index 09c0fe2a07c..43c4b9065a7 100644
--- a/apps/desktop/src/services/encrypted-message-handler.service.ts
+++ b/apps/desktop/src/services/encrypted-message-handler.service.ts
@@ -178,6 +178,8 @@ export class EncryptedMessageHandlerService {
await this.messagingService.send("refreshCiphers");
return { status: "success" };
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
return { status: "failure" };
}
@@ -222,6 +224,8 @@ export class EncryptedMessageHandlerService {
await this.messagingService.send("refreshCiphers");
return { status: "success" };
+ // FIXME: Remove when updating file. Eslint update
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
return { status: "failure" };
}
diff --git a/apps/desktop/src/vault/app/vault/credential-generator-dialog.component.html b/apps/desktop/src/vault/app/vault/credential-generator-dialog.component.html
index a294ce1f63f..d16f8e4f1cb 100644
--- a/apps/desktop/src/vault/app/vault/credential-generator-dialog.component.html
+++ b/apps/desktop/src/vault/app/vault/credential-generator-dialog.component.html
@@ -4,6 +4,7 @@
-
-
-
- {{ "cancel" | i18n }}
+ {{ buttonLabel }}
diff --git a/apps/desktop/src/vault/app/vault/credential-generator-dialog.component.ts b/apps/desktop/src/vault/app/vault/credential-generator-dialog.component.ts
index abf74371912..ae6f031005e 100644
--- a/apps/desktop/src/vault/app/vault/credential-generator-dialog.component.ts
+++ b/apps/desktop/src/vault/app/vault/credential-generator-dialog.component.ts
@@ -14,6 +14,7 @@ import {
CredentialGeneratorHistoryDialogComponent,
GeneratorModule,
} from "@bitwarden/generator-components";
+import { AlgorithmInfo } from "@bitwarden/generator-core";
import { CipherFormGeneratorComponent } from "@bitwarden/vault";
type CredentialGeneratorParams = {
@@ -38,12 +39,17 @@ type CredentialGeneratorParams = {
})
export class CredentialGeneratorDialogComponent {
credentialValue?: string;
+ buttonLabel?: string;
constructor(
@Inject(DIALOG_DATA) protected data: CredentialGeneratorParams,
private dialogService: DialogService,
) {}
+ algorithm = (selected: AlgorithmInfo) => {
+ this.buttonLabel = selected.useGeneratedValue;
+ };
+
applyCredentials = () => {
this.data.onCredentialGenerated(this.credentialValue);
};
diff --git a/apps/desktop/src/vault/app/vault/view.component.html b/apps/desktop/src/vault/app/vault/view.component.html
index 59e609312d7..f589ba53046 100644
--- a/apps/desktop/src/vault/app/vault/view.component.html
+++ b/apps/desktop/src/vault/app/vault/view.component.html
@@ -186,6 +186,16 @@