diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml
index 24a8df084a2..e626b629f5c 100644
--- a/.github/workflows/build-web.yml
+++ b/.github/workflows/build-web.yml
@@ -112,7 +112,7 @@ jobs:
npm_command: dist:bit:selfhost
- artifact_name: selfhosted-DEV
license_type: "commercial"
- image_name: web
+ image_name: web-dev
npm_command: build:bit:selfhost:dev
git_metadata: true
- artifact_name: cloud-QA
diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json
index 90cc4a5c338..68149a9781e 100644
--- a/apps/browser/src/_locales/en/messages.json
+++ b/apps/browser/src/_locales/en/messages.json
@@ -2473,6 +2473,9 @@
"permanentlyDeletedItem": {
"message": "Item permanently deleted"
},
+ "archivedItemRestored": {
+ "message": "Archived item restored"
+ },
"restoreItem": {
"message": "Restore item"
},
diff --git a/apps/browser/src/vault/popup/components/vault-v2/autofill-confirmation-dialog/autofill-confirmation-dialog.component.spec.ts b/apps/browser/src/vault/popup/components/vault-v2/autofill-confirmation-dialog/autofill-confirmation-dialog.component.spec.ts
index a28b8730109..93cc2cf248a 100644
--- a/apps/browser/src/vault/popup/components/vault-v2/autofill-confirmation-dialog/autofill-confirmation-dialog.component.spec.ts
+++ b/apps/browser/src/vault/popup/components/vault-v2/autofill-confirmation-dialog/autofill-confirmation-dialog.component.spec.ts
@@ -91,10 +91,18 @@ describe("AutofillConfirmationDialogComponent", () => {
jest.resetAllMocks();
});
- const findShowAll = (inFx?: ComponentFixture) =>
- (inFx || fixture).nativeElement.querySelector(
- "button.tw-text-sm.tw-font-medium.tw-cursor-pointer",
- ) as HTMLButtonElement | null;
+ const findShowAll = (inFx?: ComponentFixture) => {
+ // Find the button by its text content (showAll or showLess)
+ const buttons = Array.from(
+ (inFx || fixture).nativeElement.querySelectorAll("button"),
+ ) as HTMLButtonElement[];
+ return (
+ buttons.find((btn) => {
+ const text = btn.textContent?.trim() || "";
+ return text === "showAll" || text === "showLess";
+ }) || null
+ );
+ };
it("normalizes currentUrl and savedUrls via Utils.getHostname", () => {
expect(Utils.getHostname).toHaveBeenCalledTimes(1 + (params.savedUrls?.length ?? 0));
diff --git a/apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.html b/apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.html
index 6382b5fee0e..34454371f21 100644
--- a/apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.html
+++ b/apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.html
@@ -20,7 +20,13 @@
{{ "emptyVaultDescription" | i18n }}
-
+
{{ "newLogin" | i18n }}
diff --git a/apps/browser/src/vault/popup/settings/trash-list-items-container/trash-list-items-container.component.ts b/apps/browser/src/vault/popup/settings/trash-list-items-container/trash-list-items-container.component.ts
index bad6011b2d8..edebdab062f 100644
--- a/apps/browser/src/vault/popup/settings/trash-list-items-container/trash-list-items-container.component.ts
+++ b/apps/browser/src/vault/popup/settings/trash-list-items-container/trash-list-items-container.component.ts
@@ -115,15 +115,22 @@ export class TrashListItemsContainerComponent {
}
async restore(cipher: PopupCipherViewLike) {
+ let toastMessage;
try {
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
await this.cipherService.restoreWithServer(cipher.id as string, activeUserId);
+ if (cipher.archivedDate) {
+ toastMessage = this.i18nService.t("archivedItemRestored");
+ } else {
+ toastMessage = this.i18nService.t("restoredItem");
+ }
+
await this.router.navigate(["/trash"]);
this.toastService.showToast({
variant: "success",
title: null,
- message: this.i18nService.t("restoredItem"),
+ message: toastMessage,
});
} catch (e) {
this.logService.error(e);
diff --git a/apps/desktop/native-messaging-test-runner/package-lock.json b/apps/desktop/native-messaging-test-runner/package-lock.json
index 9e3b6ba23e0..f3650b3aaf6 100644
--- a/apps/desktop/native-messaging-test-runner/package-lock.json
+++ b/apps/desktop/native-messaging-test-runner/package-lock.json
@@ -15,8 +15,8 @@
"@bitwarden/storage-core": "file:../../../libs/storage-core",
"module-alias": "2.2.3",
"ts-node": "10.9.2",
- "uuid": "13.0.0",
- "yargs": "18.0.0"
+ "uuid": "9.0.1",
+ "yargs": "17.7.2"
},
"devDependencies": {
"@types/node": "22.19.3",
@@ -121,7 +121,6 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.3.tgz",
"integrity": "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"undici-types": "~6.21.0"
}
@@ -150,30 +149,6 @@
"node": ">=0.4.0"
}
},
- "node_modules/ansi-regex": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
- "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
- "node_modules/ansi-styles": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
- "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
"node_modules/arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
@@ -181,19 +156,83 @@
"license": "MIT"
},
"node_modules/cliui": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz",
- "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==",
- "license": "ISC",
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
"dependencies": {
- "string-width": "^7.2.0",
- "strip-ansi": "^7.1.0",
- "wrap-ansi": "^9.0.0"
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
},
"engines": {
- "node": ">=20"
+ "node": ">=12"
}
},
+ "node_modules/cliui/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/cliui/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
@@ -209,12 +248,6 @@
"node": ">=0.3.1"
}
},
- "node_modules/emoji-regex": {
- "version": "10.4.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
- "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
- "license": "MIT"
- },
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -233,16 +266,12 @@
"node": "6.* || 8.* || >= 10.*"
}
},
- "node_modules/get-east-asian-width": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz",
- "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==",
- "license": "MIT",
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">=8"
}
},
"node_modules/make-error": {
@@ -257,36 +286,49 @@
"integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==",
"license": "MIT"
},
- "node_modules/string-width": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
- "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^10.3.0",
- "get-east-asian-width": "^1.0.0",
- "strip-ansi": "^7.1.0"
- },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">=0.10.0"
}
},
- "node_modules/strip-ansi": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "license": "MIT",
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dependencies": {
- "ansi-regex": "^6.0.1"
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
},
"engines": {
- "node": ">=12"
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "node_modules/string-width/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
},
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ "engines": {
+ "node": ">=8"
}
},
"node_modules/ts-node": {
@@ -337,7 +379,6 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz",
"integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==",
"license": "Apache-2.0",
- "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -353,16 +394,15 @@
"license": "MIT"
},
"node_modules/uuid": {
- "version": "13.0.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz",
- "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==",
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
- "license": "MIT",
"bin": {
- "uuid": "dist-node/bin/uuid"
+ "uuid": "dist/bin/uuid"
}
},
"node_modules/v8-compile-cache-lib": {
@@ -371,23 +411,6 @@
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"license": "MIT"
},
- "node_modules/wrap-ansi": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
- "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^6.2.1",
- "string-width": "^7.0.0",
- "strip-ansi": "^7.1.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
@@ -398,29 +421,28 @@
}
},
"node_modules/yargs": {
- "version": "18.0.0",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz",
- "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==",
- "license": "MIT",
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
"dependencies": {
- "cliui": "^9.0.1",
+ "cliui": "^8.0.1",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
- "string-width": "^7.2.0",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
"y18n": "^5.0.5",
- "yargs-parser": "^22.0.0"
+ "yargs-parser": "^21.1.1"
},
"engines": {
- "node": "^20.19.0 || ^22.12.0 || >=23"
+ "node": ">=12"
}
},
"node_modules/yargs-parser": {
- "version": "22.0.0",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz",
- "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==",
- "license": "ISC",
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"engines": {
- "node": "^20.19.0 || ^22.12.0 || >=23"
+ "node": ">=12"
}
},
"node_modules/yn": {
diff --git a/apps/desktop/native-messaging-test-runner/package.json b/apps/desktop/native-messaging-test-runner/package.json
index 050bb653445..cdc9158bdca 100644
--- a/apps/desktop/native-messaging-test-runner/package.json
+++ b/apps/desktop/native-messaging-test-runner/package.json
@@ -20,8 +20,8 @@
"@bitwarden/logging": "dist/libs/logging/src",
"module-alias": "2.2.3",
"ts-node": "10.9.2",
- "uuid": "13.0.0",
- "yargs": "18.0.0"
+ "uuid": "9.0.1",
+ "yargs": "17.7.2"
},
"devDependencies": {
"@types/node": "22.19.3",
@@ -31,6 +31,12 @@
"@bitwarden/common": "dist/libs/common/src",
"@bitwarden/node/services/node-crypto-function.service": "dist/libs/node/src/services/node-crypto-function.service",
"@bitwarden/storage-core": "dist/libs/storage-core/src",
- "@bitwarden/logging": "dist/libs/logging/src"
+ "@bitwarden/logging": "dist/libs/logging/src",
+ "@bitwarden/client-type": "dist/libs/client-type/src",
+ "@bitwarden/state": "dist/libs/state/src",
+ "@bitwarden/state-internal": "dist/libs/state-internal/src",
+ "@bitwarden/messaging": "dist/libs/messaging/src",
+ "@bitwarden/guid": "dist/libs/guid/src",
+ "@bitwarden/serialization": "dist/libs/serialization/src"
}
}
diff --git a/apps/desktop/native-messaging-test-runner/src/commands/bw-credential-create.ts b/apps/desktop/native-messaging-test-runner/src/commands/bw-credential-create.ts
index 8d2d734677a..46021eb72ca 100644
--- a/apps/desktop/native-messaging-test-runner/src/commands/bw-credential-create.ts
+++ b/apps/desktop/native-messaging-test-runner/src/commands/bw-credential-create.ts
@@ -11,6 +11,7 @@ import { NativeMessagingVersion } from "@bitwarden/common/enums";
import { CredentialCreatePayload } from "../../../src/models/native-messaging/encrypted-message-payloads/credential-create-payload";
import { LogUtils } from "../log-utils";
import NativeMessageService from "../native-message.service";
+import { TestRunnerSdkLoadService } from "../sdk-load.service";
import * as config from "../variables";
const argv: any = yargs(hideBin(process.argv)).option("name", {
@@ -25,6 +26,10 @@ const { name } = argv;
// 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
(async () => {
+ // Initialize SDK before using crypto functions
+ const sdkLoadService = new TestRunnerSdkLoadService();
+ await sdkLoadService.loadAndInit();
+
const nativeMessageService = new NativeMessageService(NativeMessagingVersion.One);
// Handshake
LogUtils.logInfo("Sending Handshake");
@@ -42,7 +47,10 @@ const { name } = argv;
// Get active account userId
const status = await nativeMessageService.checkStatus(handshakeResponse.sharedKey);
- const activeUser = status.payload.filter((a) => a.active === true && a.status === "unlocked")[0];
+ const activeUser = status.payload.filter(
+ (a: { active: boolean; status: string; id: string }) =>
+ a.active === true && a.status === "unlocked",
+ )[0];
if (activeUser === undefined) {
LogUtils.logError("No active or unlocked user");
}
diff --git a/apps/desktop/native-messaging-test-runner/src/commands/bw-credential-retrieval.ts b/apps/desktop/native-messaging-test-runner/src/commands/bw-credential-retrieval.ts
index 2e55afbb36f..70b0bad9d66 100644
--- a/apps/desktop/native-messaging-test-runner/src/commands/bw-credential-retrieval.ts
+++ b/apps/desktop/native-messaging-test-runner/src/commands/bw-credential-retrieval.ts
@@ -7,6 +7,7 @@ import { NativeMessagingVersion } from "@bitwarden/common/enums";
import { LogUtils } from "../log-utils";
import NativeMessageService from "../native-message.service";
+import { TestRunnerSdkLoadService } from "../sdk-load.service";
import * as config from "../variables";
const argv: any = yargs(hideBin(process.argv)).option("uri", {
@@ -21,6 +22,10 @@ const { uri } = argv;
// 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
(async () => {
+ // Initialize SDK before using crypto functions
+ const sdkLoadService = new TestRunnerSdkLoadService();
+ await sdkLoadService.loadAndInit();
+
const nativeMessageService = new NativeMessageService(NativeMessagingVersion.One);
// Handshake
LogUtils.logInfo("Sending Handshake");
diff --git a/apps/desktop/native-messaging-test-runner/src/commands/bw-credential-update.ts b/apps/desktop/native-messaging-test-runner/src/commands/bw-credential-update.ts
index 93598bf9eef..7ba5eef143a 100644
--- a/apps/desktop/native-messaging-test-runner/src/commands/bw-credential-update.ts
+++ b/apps/desktop/native-messaging-test-runner/src/commands/bw-credential-update.ts
@@ -11,6 +11,7 @@ import { NativeMessagingVersion } from "@bitwarden/common/enums";
import { CredentialUpdatePayload } from "../../../src/models/native-messaging/encrypted-message-payloads/credential-update-payload";
import { LogUtils } from "../log-utils";
import NativeMessageService from "../native-message.service";
+import { TestRunnerSdkLoadService } from "../sdk-load.service";
import * as config from "../variables";
// Command line arguments
@@ -49,6 +50,10 @@ const { name, username, password, uri, credentialId } = argv;
// 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
(async () => {
+ // Initialize SDK before using crypto functions
+ const sdkLoadService = new TestRunnerSdkLoadService();
+ await sdkLoadService.loadAndInit();
+
const nativeMessageService = new NativeMessageService(NativeMessagingVersion.One);
// Handshake
LogUtils.logInfo("Sending Handshake");
@@ -67,7 +72,10 @@ const { name, username, password, uri, credentialId } = argv;
// Get active account userId
const status = await nativeMessageService.checkStatus(handshakeResponse.sharedKey);
- const activeUser = status.payload.filter((a) => a.active === true && a.status === "unlocked")[0];
+ const activeUser = status.payload.filter(
+ (a: { active: boolean; status: string; id: string }) =>
+ a.active === true && a.status === "unlocked",
+ )[0];
if (activeUser === undefined) {
LogUtils.logError("No active or unlocked user");
}
diff --git a/apps/desktop/native-messaging-test-runner/src/commands/bw-generate-password.ts b/apps/desktop/native-messaging-test-runner/src/commands/bw-generate-password.ts
index da914c67b4a..a0b449b02c7 100644
--- a/apps/desktop/native-messaging-test-runner/src/commands/bw-generate-password.ts
+++ b/apps/desktop/native-messaging-test-runner/src/commands/bw-generate-password.ts
@@ -7,6 +7,7 @@ import { NativeMessagingVersion } from "@bitwarden/common/enums";
import { LogUtils } from "../log-utils";
import NativeMessageService from "../native-message.service";
+import { TestRunnerSdkLoadService } from "../sdk-load.service";
import * as config from "../variables";
const argv: any = yargs(hideBin(process.argv)).option("userId", {
@@ -21,6 +22,10 @@ const { userId } = argv;
// 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
(async () => {
+ // Initialize SDK before using crypto functions
+ const sdkLoadService = new TestRunnerSdkLoadService();
+ await sdkLoadService.loadAndInit();
+
const nativeMessageService = new NativeMessageService(NativeMessagingVersion.One);
// Handshake
LogUtils.logInfo("Sending Handshake");
diff --git a/apps/desktop/native-messaging-test-runner/src/commands/bw-handshake.ts b/apps/desktop/native-messaging-test-runner/src/commands/bw-handshake.ts
index 2ba5d469aaa..77a6ac652ad 100644
--- a/apps/desktop/native-messaging-test-runner/src/commands/bw-handshake.ts
+++ b/apps/desktop/native-messaging-test-runner/src/commands/bw-handshake.ts
@@ -4,11 +4,16 @@ import { NativeMessagingVersion } from "@bitwarden/common/enums";
import { LogUtils } from "../log-utils";
import NativeMessageService from "../native-message.service";
+import { TestRunnerSdkLoadService } from "../sdk-load.service";
import * as config from "../variables";
// 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
(async () => {
+ // Initialize SDK before using crypto functions
+ const sdkLoadService = new TestRunnerSdkLoadService();
+ await sdkLoadService.loadAndInit();
+
const nativeMessageService = new NativeMessageService(NativeMessagingVersion.One);
const response = await nativeMessageService.sendHandshake(
diff --git a/apps/desktop/native-messaging-test-runner/src/commands/bw-status.ts b/apps/desktop/native-messaging-test-runner/src/commands/bw-status.ts
index 466e3fca52b..7014c4713c2 100644
--- a/apps/desktop/native-messaging-test-runner/src/commands/bw-status.ts
+++ b/apps/desktop/native-messaging-test-runner/src/commands/bw-status.ts
@@ -4,11 +4,16 @@ import { NativeMessagingVersion } from "@bitwarden/common/enums";
import { LogUtils } from "../log-utils";
import NativeMessageService from "../native-message.service";
+import { TestRunnerSdkLoadService } from "../sdk-load.service";
import * as config from "../variables";
// 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
(async () => {
+ // Initialize SDK before using crypto functions
+ const sdkLoadService = new TestRunnerSdkLoadService();
+ await sdkLoadService.loadAndInit();
+
const nativeMessageService = new NativeMessageService(NativeMessagingVersion.One);
LogUtils.logInfo("Sending Handshake");
diff --git a/apps/desktop/native-messaging-test-runner/src/deferred.ts b/apps/desktop/native-messaging-test-runner/src/deferred.ts
index da34d80ebb2..d3350ade5a4 100644
--- a/apps/desktop/native-messaging-test-runner/src/deferred.ts
+++ b/apps/desktop/native-messaging-test-runner/src/deferred.ts
@@ -4,8 +4,8 @@
// while allowing an unrelated event to fulfill it elsewhere.
export default class Deferred {
private promise: Promise;
- private resolver: (T?) => void;
- private rejecter: (Error?) => void;
+ private resolver!: (value?: T) => void;
+ private rejecter!: (reason?: Error) => void;
constructor() {
this.promise = new Promise((resolve, reject) => {
diff --git a/apps/desktop/native-messaging-test-runner/src/ipc.service.ts b/apps/desktop/native-messaging-test-runner/src/ipc.service.ts
index d8616e9757a..adb1e693d24 100644
--- a/apps/desktop/native-messaging-test-runner/src/ipc.service.ts
+++ b/apps/desktop/native-messaging-test-runner/src/ipc.service.ts
@@ -13,7 +13,7 @@ import { race } from "./race";
const DEFAULT_MESSAGE_TIMEOUT = 10 * 1000; // 10 seconds
-export type MessageHandler = (MessageCommon) => void;
+export type MessageHandler = (message: MessageCommon) => void;
// FIXME: update to use a const object instead of a typescript enum
// eslint-disable-next-line @bitwarden/platform/no-enums
diff --git a/apps/desktop/native-messaging-test-runner/src/race.ts b/apps/desktop/native-messaging-test-runner/src/race.ts
index 5ed778aa35b..a1c6cb04c5f 100644
--- a/apps/desktop/native-messaging-test-runner/src/race.ts
+++ b/apps/desktop/native-messaging-test-runner/src/race.ts
@@ -8,8 +8,8 @@ export const race = ({
promise: Promise;
timeout: number;
error?: Error;
-}) => {
- let timer = null;
+}): Promise => {
+ let timer: NodeJS.Timeout | null = null;
// Similar to Promise.all, but instead of waiting for all, it resolves once one promise finishes.
// Using this so we can reject if the timeout threshold is hit
@@ -20,7 +20,9 @@ export const race = ({
}),
promise.then((value) => {
- clearTimeout(timer);
+ if (timer != null) {
+ clearTimeout(timer);
+ }
return value;
}),
]);
diff --git a/apps/desktop/native-messaging-test-runner/src/sdk-load.service.ts b/apps/desktop/native-messaging-test-runner/src/sdk-load.service.ts
new file mode 100644
index 00000000000..d3f8289dffb
--- /dev/null
+++ b/apps/desktop/native-messaging-test-runner/src/sdk-load.service.ts
@@ -0,0 +1,22 @@
+import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service";
+
+import { LogUtils } from "./log-utils";
+
+/**
+ * SDK Load Service for the native messaging test runner.
+ * For Node.js environments, the SDK's Node.js build automatically loads WASM from the filesystem.
+ * No additional initialization is needed.
+ */
+export class TestRunnerSdkLoadService extends SdkLoadService {
+ async load(): Promise {
+ // In Node.js, @bitwarden/sdk-internal automatically loads the WASM file
+ // from node/bitwarden_wasm_internal_bg.wasm using fs.readFileSync.
+ // No explicit loading is required.
+ }
+
+ override async loadAndInit(): Promise {
+ LogUtils.logInfo("Initializing SDK");
+ await super.loadAndInit();
+ LogUtils.logSuccess("SDK initialized");
+ }
+}
diff --git a/apps/desktop/native-messaging-test-runner/tsconfig.json b/apps/desktop/native-messaging-test-runner/tsconfig.json
index dcdf992f986..708559efc07 100644
--- a/apps/desktop/native-messaging-test-runner/tsconfig.json
+++ b/apps/desktop/native-messaging-test-runner/tsconfig.json
@@ -1,4 +1,5 @@
{
+ "extends": "../../../tsconfig.base.json",
"compilerOptions": {
"baseUrl": "./",
"outDir": "dist",
@@ -18,7 +19,13 @@
"@bitwarden/auth/*": ["../../../libs/auth/src/*"],
"@bitwarden/common/*": ["../../../libs/common/src/*"],
"@bitwarden/key-management": ["../../../libs/key-management/src/"],
- "@bitwarden/node/*": ["../../../libs/node/src/*"]
+ "@bitwarden/node/*": ["../../../libs/node/src/*"],
+ "@bitwarden/state": ["../../../libs/state/src/index.ts"],
+ "@bitwarden/state-internal": ["../../../libs/state-internal/src/index.ts"],
+ "@bitwarden/client-type": ["../../../libs/client-type/src/index.ts"],
+ "@bitwarden/messaging": ["../../../libs/messaging/src/index.ts"],
+ "@bitwarden/guid": ["../../../libs/guid/src/index.ts"],
+ "@bitwarden/serialization": ["../../../libs/serialization/src/index.ts"]
},
"plugins": [
{
@@ -26,5 +33,6 @@
}
]
},
- "exclude": ["node_modules"]
+ "include": ["src/**/*"],
+ "exclude": ["node_modules", "dist"]
}
diff --git a/apps/desktop/src/locales/en/messages.json b/apps/desktop/src/locales/en/messages.json
index f9947e16692..0ce98b8c62b 100644
--- a/apps/desktop/src/locales/en/messages.json
+++ b/apps/desktop/src/locales/en/messages.json
@@ -2092,6 +2092,9 @@
"permanentlyDeletedItem": {
"message": "Item permanently deleted"
},
+ "archivedItemRestored": {
+ "message": "Archived item restored"
+ },
"restoredItem": {
"message": "Item restored"
},
diff --git a/apps/desktop/src/vault/app/vault/item-footer.component.ts b/apps/desktop/src/vault/app/vault/item-footer.component.ts
index c80e4e59ae4..3f22a08d00e 100644
--- a/apps/desktop/src/vault/app/vault/item-footer.component.ts
+++ b/apps/desktop/src/vault/app/vault/item-footer.component.ts
@@ -173,16 +173,23 @@ export class ItemFooterComponent implements OnInit, OnChanges {
}
async restore(): Promise {
+ let toastMessage;
if (!this.cipher.isDeleted) {
return false;
}
+ if (this.cipher.isArchived) {
+ toastMessage = this.i18nService.t("archivedItemRestored");
+ } else {
+ toastMessage = this.i18nService.t("restoredItem");
+ }
+
try {
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
await this.restoreCipher(activeUserId);
this.toastService.showToast({
variant: "success",
- message: this.i18nService.t("restoredItem"),
+ message: toastMessage,
});
this.onRestore.emit(this.cipher);
} catch (e) {
diff --git a/apps/web/src/app/dirt/reports/pages/inactive-two-factor-report.component.html b/apps/web/src/app/dirt/reports/pages/inactive-two-factor-report.component.html
index 1fcc2cd3246..96f20c5e408 100644
--- a/apps/web/src/app/dirt/reports/pages/inactive-two-factor-report.component.html
+++ b/apps/web/src/app/dirt/reports/pages/inactive-two-factor-report.component.html
@@ -35,89 +35,80 @@
}
}
-
+
@if (!isAdminConsoleActive) {
-
- |
- {{ "name" | i18n }} |
- {{ "owner" | i18n }} |
- |
-
+ |
+ {{ "name" | i18n }} |
+ {{ "owner" | i18n }} |
+ |
}
-
-
-
- @for (r of (rows$ | async); track r) {
-
- |
-
- |
-
- @if (!organization || canManageCipher(r)) {
- {{ r.name }}
- } @else {
- {{ r.name }}
- }
- @if (!organization && r.organizationId) {
-
- {{ "shared" | i18n }}
- }
- @if (r.hasAttachments) {
-
- {{ "attachments" | i18n }}
- }
-
- {{ r.subTitle }}
- |
-
- @if (!organization) {
-
-
- }
- |
-
- @if (cipherDocs.has(r.id)) {
-
- {{ "instructions" | i18n }}
- }
- |
-
+
+
+
+ |
+
+ @if (!organization || canManageCipher(row)) {
+
+ {{ row.name }}
+
+ } @else {
+
+ {{ row.name }}
+
}
-
- |
+ @if (!organization && row.organizationId) {
+
+
+ {{ "shared" | i18n }}
+
+ }
+ @if (row.hasAttachments) {
+
+
+ {{ "attachments" | i18n }}
+
+ }
+
+ {{ row.subTitle }}
+
+
+ @if (!organization) {
+
+ }
+ |
+
+ @if (cipherDocs.has(row.id)) {
+
+ {{ "instructions" | i18n }}
+ }
+ |
+
+
}
}
diff --git a/apps/web/src/app/dirt/reports/pages/unsecured-websites-report.component.html b/apps/web/src/app/dirt/reports/pages/unsecured-websites-report.component.html
index 336a0558bbc..23ea3cdbe75 100644
--- a/apps/web/src/app/dirt/reports/pages/unsecured-websites-report.component.html
+++ b/apps/web/src/app/dirt/reports/pages/unsecured-websites-report.component.html
@@ -35,75 +35,65 @@
}
}
-
+
@if (!isAdminConsoleActive) {
-
- |
- {{ "name" | i18n }} |
- {{ "owner" | i18n }} |
- |
-
+ |
+ {{ "name" | i18n }} |
+ {{ "owner" | i18n }} |
}
-
-
- @for (r of (rows$ | async); track r) {
-
- |
-
- |
-
- @if (!organization || canManageCipher(r)) {
- {{ r.name }}
- } @else {
- {{ r.name }}
- }
- @if (!organization && r.organizationId) {
-
- {{ "shared" | i18n }}
- }
- @if (r.hasAttachments) {
-
- {{ "attachments" | i18n }}
- }
-
- {{ r.subTitle }}
- |
-
- @if (!organization) {
-
-
- }
- |
-
- }
+
+
+
+ |
+
+ @if (!organization || canManageCipher(row)) {
+ {{ row.name }}
+ } @else {
+ {{ row.name }}
+ }
+ @if (!organization && row.organizationId) {
+
+ {{ "shared" | i18n }}
+ }
+ @if (row.hasAttachments) {
+
+ {{ "attachments" | i18n }}
+ }
+
+ {{ row.subTitle }}
+ |
+
+ @if (!organization) {
+
+
+ }
+ |
-
+
}
}
diff --git a/apps/web/src/app/dirt/reports/reports-layout.component.ts b/apps/web/src/app/dirt/reports/reports-layout.component.ts
index c2fbf858590..a6d84ccb037 100644
--- a/apps/web/src/app/dirt/reports/reports-layout.component.ts
+++ b/apps/web/src/app/dirt/reports/reports-layout.component.ts
@@ -1,6 +1,6 @@
-import { Component, OnDestroy } from "@angular/core";
+import { Component } from "@angular/core";
+import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { NavigationEnd, Router } from "@angular/router";
-import { Subscription } from "rxjs";
import { filter } from "rxjs/operators";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
@@ -10,20 +10,20 @@ import { filter } from "rxjs/operators";
templateUrl: "reports-layout.component.html",
standalone: false,
})
-export class ReportsLayoutComponent implements OnDestroy {
+export class ReportsLayoutComponent {
homepage = true;
- subscription: Subscription;
constructor(router: Router) {
- this.subscription = router.events
- .pipe(filter((event) => event instanceof NavigationEnd))
- // eslint-disable-next-line rxjs-angular/prefer-takeuntil
+ const reportsHomeRoute = "/reports";
+
+ this.homepage = router.url === reportsHomeRoute;
+ router.events
+ .pipe(
+ takeUntilDestroyed(),
+ filter((event) => event instanceof NavigationEnd),
+ )
.subscribe((event) => {
- this.homepage = (event as NavigationEnd).url == "/reports";
+ this.homepage = (event as NavigationEnd).url == reportsHomeRoute;
});
}
-
- ngOnDestroy(): void {
- this.subscription?.unsubscribe();
- }
}
diff --git a/apps/web/src/app/vault/components/vault-item-dialog/vault-item-dialog.component.html b/apps/web/src/app/vault/components/vault-item-dialog/vault-item-dialog.component.html
index 640febf41d2..e4030a7ab18 100644
--- a/apps/web/src/app/vault/components/vault-item-dialog/vault-item-dialog.component.html
+++ b/apps/web/src/app/vault/components/vault-item-dialog/vault-item-dialog.component.html
@@ -86,7 +86,7 @@
@if (showActionButtons) {
- @if (userCanArchive$ | async) {
+ @if ((userCanArchive$ | async) && !params.isAdminConsoleAction) {
@if (isCipherArchived) {