- |
-
- |
-
- {{ user.email }}
- {{ user.name }}
- |
-
+ |
-
@@ -95,55 +81,21 @@
-
+
- | {{ "member" | i18n }} |
- {{ "status" | i18n }} |
+
+ {{ (accountDeprovisioning.enabled ? "member" : "user") | i18n }}
+ |
+ {{ "status" | i18n }} |
-
-
-
-
-
-
- {{ user.email }}
- {{ user.name }}
-
-
- |
-
- {{ statuses.get(user.id) }}
- |
-
- {{ "bulkFilteredMessage" | i18n }}
- |
-
-
-
-
-
-
-
- | {{ "member" | i18n }} |
- {{ "status" | i18n }} |
-
-
-
-
-
-
-
-
-
-
- {{ user.email }}
- {{ user.name }}
-
-
+ |
+
|
{{ statuses.get(user.id) }}
From 59da9918b7061fb0f1274fde4e6fe8d01eca4cbf Mon Sep 17 00:00:00 2001
From: Bernd Schoolmann
Date: Thu, 6 Feb 2025 11:57:27 +0100
Subject: [PATCH 002/103] Fix typos in codeowners and codecov (#13284)
---
.github/CODEOWNERS | 2 +-
.github/codecov.yml | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index cc70d3f5b4a..436e2d4ad0f 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -134,7 +134,7 @@ libs/key-management @bitwarden/team-key-management-dev
libs/key-management-ui @bitwarden/team-key-management-dev
libs/common/src/key-management @bitwarden/team-key-management-dev
-apps/desktop/destkop_native/core/src/biometric/ @bitwarden/team-key-management-dev
+apps/desktop/desktop_native/core/src/biometric/ @bitwarden/team-key-management-dev
apps/desktop/src/services/native-messaging.service.ts @bitwarden/team-key-management-dev
apps/browser/src/background/nativeMessaging.background.ts @bitwarden/team-key-management-dev
apps/desktop/src/services/biometric-message-handler.service.ts @bitwarden/team-key-management-dev
diff --git a/.github/codecov.yml b/.github/codecov.yml
index b79cdd9f413..0a6b3ceacff 100644
--- a/.github/codecov.yml
+++ b/.github/codecov.yml
@@ -56,11 +56,11 @@ component_management:
- apps/browser/src/key-management/**
- apps/browser/src/background/nativeMessaging.background.ts
- apps/cli/src/key-management/**
- - apps/desktop/destkop_native/core/src/biometric/**
+ - apps/desktop/desktop_native/core/src/biometric/**
- apps/desktop/src/key-management/**
- apps/desktop/src/services/biometric-message-handler.service.ts
- apps/desktop/src/services/native-messaging.service.ts
- - apps/web/src/app/key-managemen/**
+ - apps/web/src/app/key-management/**
- libs/common/src/key-management/**
- libs/key-management/**
- libs/key-management-ui/**
From f9d0855433c954fb25730085470034d51889e9f4 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 6 Feb 2025 12:10:50 +0000
Subject: [PATCH 003/103] [deps] AC: Update ts-loader to v9.5.2 (#12953)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
package-lock.json | 8 ++++----
package.json | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 0ea31c0a8ad..7a265d75539 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -169,7 +169,7 @@
"style-loader": "4.0.0",
"tailwindcss": "3.4.17",
"ts-jest": "29.2.2",
- "ts-loader": "9.5.1",
+ "ts-loader": "9.5.2",
"tsconfig-paths-webpack-plugin": "4.2.0",
"type-fest": "2.19.0",
"typescript": "5.4.2",
@@ -31181,9 +31181,9 @@
}
},
"node_modules/ts-loader": {
- "version": "9.5.1",
- "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz",
- "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==",
+ "version": "9.5.2",
+ "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.2.tgz",
+ "integrity": "sha512-Qo4piXvOTWcMGIgRiuFa6nHNm+54HbYaZCKqc9eeZCLRy3XqafQgwX2F7mofrbJG3g7EEb+lkiR+z2Lic2s3Zw==",
"dev": true,
"license": "MIT",
"dependencies": {
diff --git a/package.json b/package.json
index a9a281db728..3c7f1d5ac5d 100644
--- a/package.json
+++ b/package.json
@@ -130,7 +130,7 @@
"style-loader": "4.0.0",
"tailwindcss": "3.4.17",
"ts-jest": "29.2.2",
- "ts-loader": "9.5.1",
+ "ts-loader": "9.5.2",
"tsconfig-paths-webpack-plugin": "4.2.0",
"type-fest": "2.19.0",
"typescript": "5.4.2",
From ba9d4df4f8a30b4c4718287b247dfa11c4ee179b Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 6 Feb 2025 12:40:35 +0000
Subject: [PATCH 004/103] [deps] AC: Update core-js to v3.40.0 (#12964)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
package-lock.json | 8 ++++----
package.json | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 7a265d75539..6a8390acf8a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -41,7 +41,7 @@
"bufferutil": "4.0.9",
"chalk": "4.1.2",
"commander": "11.1.0",
- "core-js": "3.39.0",
+ "core-js": "3.40.0",
"form-data": "4.0.1",
"https-proxy-agent": "7.0.5",
"inquirer": "8.2.6",
@@ -14451,9 +14451,9 @@
}
},
"node_modules/core-js": {
- "version": "3.39.0",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.39.0.tgz",
- "integrity": "sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==",
+ "version": "3.40.0",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.40.0.tgz",
+ "integrity": "sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==",
"hasInstallScript": true,
"license": "MIT",
"funding": {
diff --git a/package.json b/package.json
index 3c7f1d5ac5d..160777bb2ce 100644
--- a/package.json
+++ b/package.json
@@ -171,7 +171,7 @@
"bufferutil": "4.0.9",
"chalk": "4.1.2",
"commander": "11.1.0",
- "core-js": "3.39.0",
+ "core-js": "3.40.0",
"form-data": "4.0.1",
"https-proxy-agent": "7.0.5",
"inquirer": "8.2.6",
From 5da7d934cc0f3bca630c04d78ff26dc6b6e3ab42 Mon Sep 17 00:00:00 2001
From: Opeyemi
Date: Thu, 6 Feb 2025 13:15:43 +0000
Subject: [PATCH 005/103] Fix Browser version to 2025.1.3 (#13286)
---
apps/browser/package.json | 2 +-
apps/browser/src/manifest.json | 2 +-
apps/browser/src/manifest.v3.json | 2 +-
package-lock.json | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/apps/browser/package.json b/apps/browser/package.json
index 8fc1d733921..202ec1c4fe1 100644
--- a/apps/browser/package.json
+++ b/apps/browser/package.json
@@ -1,6 +1,6 @@
{
"name": "@bitwarden/browser",
- "version": "2025.1.4",
+ "version": "2025.1.3",
"scripts": {
"build": "npm run build:chrome",
"build:chrome": "cross-env BROWSER=chrome MANIFEST_VERSION=3 NODE_OPTIONS=\"--max-old-space-size=8192\" webpack",
diff --git a/apps/browser/src/manifest.json b/apps/browser/src/manifest.json
index 90ae271fd14..6a2e017d06c 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.4",
+ "version": "2025.1.3",
"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 c88796fd201..dee6ebef31c 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.4",
+ "version": "2025.1.3",
"description": "__MSG_extDesc__",
"default_locale": "en",
"author": "Bitwarden Inc.",
diff --git a/package-lock.json b/package-lock.json
index 6a8390acf8a..eb23447a93d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -190,7 +190,7 @@
},
"apps/browser": {
"name": "@bitwarden/browser",
- "version": "2025.1.4"
+ "version": "2025.1.3"
},
"apps/cli": {
"name": "@bitwarden/cli",
From 6a94b4d0ef86fb3e832fc554ce626bb646fc8f24 Mon Sep 17 00:00:00 2001
From: Alex Morask <144709477+amorask-bitwarden@users.noreply.github.com>
Date: Thu, 6 Feb 2025 08:54:23 -0500
Subject: [PATCH 006/103] Update marketing route for organizations when in
cloud (#13123)
---
.../shared/product-switcher.service.spec.ts | 27 ++++++++++++++++++-
.../shared/product-switcher.service.ts | 17 +++++++++---
2 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/apps/web/src/app/layouts/product-switcher/shared/product-switcher.service.spec.ts b/apps/web/src/app/layouts/product-switcher/shared/product-switcher.service.spec.ts
index 4187900060b..a1ac434d590 100644
--- a/apps/web/src/app/layouts/product-switcher/shared/product-switcher.service.spec.ts
+++ b/apps/web/src/app/layouts/product-switcher/shared/product-switcher.service.spec.ts
@@ -11,6 +11,7 @@ import { ProviderService } from "@bitwarden/common/admin-console/abstractions/pr
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { Provider } from "@bitwarden/common/admin-console/models/domain/provider";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
+import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { SyncService } from "@bitwarden/common/platform/sync";
import { FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/spec";
@@ -24,6 +25,7 @@ describe("ProductSwitcherService", () => {
let organizationService: MockProxy;
let providerService: MockProxy;
let accountService: FakeAccountService;
+ let platformUtilsService: MockProxy;
let activeRouteParams = convertToParamMap({ organizationId: "1234" });
const getLastSync = jest.fn().mockResolvedValue(new Date("2024-05-14"));
const userId = Utils.newGuid() as UserId;
@@ -43,11 +45,13 @@ describe("ProductSwitcherService", () => {
organizationService = mock();
providerService = mock();
accountService = mockAccountServiceWith(userId);
+ platformUtilsService = mock();
router.url = "/";
router.events = of({});
organizationService.organizations$.mockReturnValue(of([{}] as Organization[]));
providerService.getAll.mockResolvedValue([] as Provider[]);
+ platformUtilsService.isSelfHost.mockReturnValue(false);
TestBed.configureTestingModule({
providers: [
@@ -55,6 +59,7 @@ describe("ProductSwitcherService", () => {
{ provide: OrganizationService, useValue: organizationService },
{ provide: ProviderService, useValue: providerService },
{ provide: AccountService, useValue: accountService },
+ { provide: PlatformUtilsService, useValue: platformUtilsService },
{
provide: ActivatedRoute,
useValue: {
@@ -138,11 +143,31 @@ describe("ProductSwitcherService", () => {
});
describe("Admin/Organizations", () => {
- it("includes Organizations in other when there are organizations", async () => {
+ it("includes Organizations with the internal route in other when there are organizations on cloud", async () => {
initiateService();
const products = await firstValueFrom(service.products$);
+ const organizations = products.other.find((p) => p.name === "Organizations");
+ expect(organizations).toBeDefined();
+ expect(organizations.marketingRoute.route).toBe("/create-organization");
+ expect(organizations.marketingRoute.external).toBe(false);
+
+ expect(products.other.find((p) => p.name === "Organizations")).toBeDefined();
+ expect(products.bento.find((p) => p.name === "Admin Console")).toBeUndefined();
+ });
+
+ it("includes Organizations with the external route in other when there are organizations on Self-Host", async () => {
+ platformUtilsService.isSelfHost.mockReturnValue(true);
+ initiateService();
+
+ const products = await firstValueFrom(service.products$);
+
+ const organizations = products.other.find((p) => p.name === "Organizations");
+ expect(organizations).toBeDefined();
+ expect(organizations.marketingRoute.route).toBe("https://bitwarden.com/products/business/");
+ expect(organizations.marketingRoute.external).toBe(true);
+
expect(products.other.find((p) => p.name === "Organizations")).toBeDefined();
expect(products.bento.find((p) => p.name === "Admin Console")).toBeUndefined();
});
diff --git a/apps/web/src/app/layouts/product-switcher/shared/product-switcher.service.ts b/apps/web/src/app/layouts/product-switcher/shared/product-switcher.service.ts
index f962879d61a..1cc5c92c120 100644
--- a/apps/web/src/app/layouts/product-switcher/shared/product-switcher.service.ts
+++ b/apps/web/src/app/layouts/product-switcher/shared/product-switcher.service.ts
@@ -21,6 +21,7 @@ import {
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
+import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { SyncService } from "@bitwarden/common/platform/sync";
export type ProductSwitcherItem = {
@@ -101,6 +102,7 @@ export class ProductSwitcherService {
private i18n: I18nPipe,
private syncService: SyncService,
private accountService: AccountService,
+ private platformUtilsService: PlatformUtilsService,
) {
this.pollUntilSynced();
}
@@ -151,6 +153,16 @@ export class ProductSwitcherService {
// TODO: This should be migrated to an Observable provided by the provider service and moved to the combineLatest above. See AC-2092.
const providers = await this.providerService.getAll();
+ const orgsMarketingRoute = this.platformUtilsService.isSelfHost()
+ ? {
+ route: "https://bitwarden.com/products/business/",
+ external: true,
+ }
+ : {
+ route: "/create-organization",
+ external: false,
+ };
+
const products = {
pm: {
name: "Password Manager",
@@ -197,10 +209,7 @@ export class ProductSwitcherService {
orgs: {
name: "Organizations",
icon: "bwi-business",
- marketingRoute: {
- route: "https://bitwarden.com/products/business/",
- external: true,
- },
+ marketingRoute: orgsMarketingRoute,
otherProductOverrides: {
name: "Share your passwords",
supportingText: this.i18n.transform("protectYourFamilyOrBusiness"),
From 649255bef0e4fffea3e72fd4e225fc0a46e1d479 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 6 Feb 2025 08:57:21 -0500
Subject: [PATCH 007/103] [deps] Billing: Update braintree-web-drop-in to
v1.44.0 (#12967)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: cyprain-okeke <108260115+cyprain-okeke@users.noreply.github.com>
---
package-lock.json | 61 ++++++++++++++++++++++++++++++++++++++++-------
package.json | 2 +-
2 files changed, 53 insertions(+), 10 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index eb23447a93d..385869fa775 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -36,7 +36,7 @@
"argon2-browser": "1.18.0",
"big-integer": "1.6.52",
"bootstrap": "4.6.0",
- "braintree-web-drop-in": "1.43.0",
+ "braintree-web-drop-in": "1.44.0",
"buffer": "6.0.3",
"bufferutil": "4.0.9",
"chalk": "4.1.2",
@@ -7921,6 +7921,36 @@
"license": "MIT",
"optional": true
},
+ "node_modules/@paypal/accelerated-checkout-loader": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@paypal/accelerated-checkout-loader/-/accelerated-checkout-loader-1.1.0.tgz",
+ "integrity": "sha512-S2KkIpq15VnxYyI0tycvfYiNsqdsg2a92El2huYUVLsWnBbubl8toYK8khaP5nnxZ0MGl9mEB9Y9axmfOw2Yvg==",
+ "license": "MIT",
+ "dependencies": {
+ "@braintree/asset-loader": "2.0.0",
+ "envify": "^4.1.0",
+ "typescript": "^4.6.4"
+ }
+ },
+ "node_modules/@paypal/accelerated-checkout-loader/node_modules/@braintree/asset-loader": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@braintree/asset-loader/-/asset-loader-2.0.0.tgz",
+ "integrity": "sha512-7Zs3/g3lPTfkdtWr7cKh3tk1pDruXR++TXwGKkx7BPuTjjLNFul2JSfI+ScHzNU4u/gZNPNQagsSTlYxIhBgMA==",
+ "license": "MIT"
+ },
+ "node_modules/@paypal/accelerated-checkout-loader/node_modules/typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
"node_modules/@phc/format": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz",
@@ -12870,9 +12900,9 @@
}
},
"node_modules/braintree-web": {
- "version": "3.103.0",
- "resolved": "https://registry.npmjs.org/braintree-web/-/braintree-web-3.103.0.tgz",
- "integrity": "sha512-gwmC5LSUP5VUC2HmUyaFnEyLjRRAo1iKKHS5eD9KIAZHB7cAQ2il1V1q2f5zdz7+7EE11eSHXznj6n/Qm6jp6w==",
+ "version": "3.113.0",
+ "resolved": "https://registry.npmjs.org/braintree-web/-/braintree-web-3.113.0.tgz",
+ "integrity": "sha512-qykYxZyld4X1tRNgXZQ3ZGzmhDGTBTRQ6Q24KaG9PuYqo+P2TVDEDOVC6tRbkx2RUIdXLv2M6WpkG7oLqEia9Q==",
"license": "MIT",
"dependencies": {
"@braintree/asset-loader": "2.0.1",
@@ -12883,6 +12913,7 @@
"@braintree/sanitize-url": "7.0.4",
"@braintree/uuid": "1.0.0",
"@braintree/wrap-promise": "2.1.0",
+ "@paypal/accelerated-checkout-loader": "1.1.0",
"card-validator": "10.0.0",
"credit-card-type": "10.0.1",
"framebus": "6.0.0",
@@ -12892,9 +12923,9 @@
}
},
"node_modules/braintree-web-drop-in": {
- "version": "1.43.0",
- "resolved": "https://registry.npmjs.org/braintree-web-drop-in/-/braintree-web-drop-in-1.43.0.tgz",
- "integrity": "sha512-lkUpQfYXR0CGtR7mPRR17AnZoYkHjhycxVnMGIPcWT6JPagEZcG/7tYyy34iWjYZeGa2wsquLBDV2Xeita962Q==",
+ "version": "1.44.0",
+ "resolved": "https://registry.npmjs.org/braintree-web-drop-in/-/braintree-web-drop-in-1.44.0.tgz",
+ "integrity": "sha512-maOq9SwiXztIzixJhOras7K44x4UIqqnkyQMYAJqxQ8WkADv9AkflCu2j3IeVYCus/Th9gWWFHcBugn3C4sZGw==",
"license": "MIT",
"dependencies": {
"@braintree/asset-loader": "2.0.1",
@@ -12902,7 +12933,7 @@
"@braintree/event-emitter": "0.4.1",
"@braintree/uuid": "1.0.0",
"@braintree/wrap-promise": "2.1.0",
- "braintree-web": "3.103.0"
+ "braintree-web": "3.113.0"
}
},
"node_modules/browser-assert": {
@@ -15996,6 +16027,19 @@
"node": ">=6"
}
},
+ "node_modules/envify": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/envify/-/envify-4.1.0.tgz",
+ "integrity": "sha512-IKRVVoAYr4pIx4yIWNsz9mOsboxlNXiu7TNBnem/K/uTHdkyzXWDzHCK7UTolqBbgaBz0tQHsD3YNls0uIIjiw==",
+ "license": "MIT",
+ "dependencies": {
+ "esprima": "^4.0.0",
+ "through": "~2.3.4"
+ },
+ "bin": {
+ "envify": "bin/envify"
+ }
+ },
"node_modules/envinfo": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz",
@@ -16853,7 +16897,6 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
- "dev": true,
"license": "BSD-2-Clause",
"bin": {
"esparse": "bin/esparse.js",
diff --git a/package.json b/package.json
index 160777bb2ce..412fdd81b4e 100644
--- a/package.json
+++ b/package.json
@@ -166,7 +166,7 @@
"argon2-browser": "1.18.0",
"big-integer": "1.6.52",
"bootstrap": "4.6.0",
- "braintree-web-drop-in": "1.43.0",
+ "braintree-web-drop-in": "1.44.0",
"buffer": "6.0.3",
"bufferutil": "4.0.9",
"chalk": "4.1.2",
From b2de591be0d15ed725618d6806b922a7be1046d0 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 6 Feb 2025 14:29:22 +0000
Subject: [PATCH 008/103] [deps] AC: Update postcss to v8.5.1 (#12965)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
package-lock.json | 16 ++++++++--------
package.json | 2 +-
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 385869fa775..c60ae62e657 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -156,7 +156,7 @@
"lint-staged": "15.4.1",
"mini-css-extract-plugin": "2.9.2",
"node-ipc": "9.2.1",
- "postcss": "8.4.49",
+ "postcss": "8.5.1",
"postcss-loader": "8.1.1",
"prettier": "3.4.2",
"prettier-plugin-tailwindcss": "0.6.10",
@@ -25009,9 +25009,9 @@
}
},
"node_modules/nanoid": {
- "version": "3.3.7",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
- "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "version": "3.3.8",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
+ "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"dev": true,
"funding": [
{
@@ -27131,9 +27131,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.49",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
- "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
+ "version": "8.5.1",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz",
+ "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==",
"dev": true,
"funding": [
{
@@ -27151,7 +27151,7 @@
],
"license": "MIT",
"dependencies": {
- "nanoid": "^3.3.7",
+ "nanoid": "^3.3.8",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
diff --git a/package.json b/package.json
index 412fdd81b4e..5145b058f6f 100644
--- a/package.json
+++ b/package.json
@@ -117,7 +117,7 @@
"lint-staged": "15.4.1",
"mini-css-extract-plugin": "2.9.2",
"node-ipc": "9.2.1",
- "postcss": "8.4.49",
+ "postcss": "8.5.1",
"postcss-loader": "8.1.1",
"prettier": "3.4.2",
"prettier-plugin-tailwindcss": "0.6.10",
From 28d9202edb9ec5d6a0d6fa1996fc94384d5ed469 Mon Sep 17 00:00:00 2001
From: Daniel James Smith <2670567+djsmith85@users.noreply.github.com>
Date: Thu, 6 Feb 2025 17:00:14 +0100
Subject: [PATCH 009/103] [PM-16964] Format help links on vault import (#13262)
* Format help links on vault import
* Fix broken link ot gnome key-ring importer
---------
Co-authored-by: Daniel James Smith
---
.../src/components/import.component.html | 29 +++++++++++++++++--
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/libs/importer/src/components/import.component.html b/libs/importer/src/components/import.component.html
index c53a1d3f522..072271f8205 100644
--- a/libs/importer/src/components/import.component.html
+++ b/libs/importer/src/components/import.component.html
@@ -94,6 +94,8 @@
{{ "seeDetailedInstructions" | i18n }}
See detailed instructions on our help site at
-
+
https://bitwarden.com/help/import-from-chrome/
See detailed instructions on our help site at
See detailed instructions on our help site at
-
+
https://bitwarden.com/help/import-from-safari/.
@@ -199,6 +215,8 @@
>
See detailed instructions on our help site at
Make sure you have python-keyring and python-gnomekeyring installed. Save the
- GNOME Keyring Import/Export
python script to your desktop as pw_helper.py. Open terminal and run
From 276d9b9a9bf0b6f3edd5f50832f94f4050c4b3f9 Mon Sep 17 00:00:00 2001
From: Daniel Riera
Date: Thu, 6 Feb 2025 11:54:09 -0500
Subject: [PATCH 010/103] [PM-17487] Load cipher data into new notification
experience (#13185)
* PM-17487 - Initial structure
- Implement new getNotificationCipherData function in background
- Update stories to match new naming
- Edit types to be relevant to current functionality
* update jsdoc
* export types so eslint does not treat them as unused
* -Fix types -Promise.all on background
* clean comments
---
.../background/notification.background.ts | 37 +++++++++++++++++++
.../content/components/cipher/cipher-info.ts | 4 +-
.../content/components/cipher/cipher-item.ts | 4 +-
.../content/components/cipher/types.ts | 21 +++++++----
.../notification/body.lit-stories.ts | 6 +--
.../content/components/notification/body.ts | 4 +-
.../components/notification/container.ts | 15 ++------
apps/browser/src/autofill/notification/bar.ts | 26 +++++++------
8 files changed, 76 insertions(+), 41 deletions(-)
diff --git a/apps/browser/src/autofill/background/notification.background.ts b/apps/browser/src/autofill/background/notification.background.ts
index ad3bee97d8a..a091256b28d 100644
--- a/apps/browser/src/autofill/background/notification.background.ts
+++ b/apps/browser/src/autofill/background/notification.background.ts
@@ -25,6 +25,7 @@ import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-stat
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
import { CipherType } from "@bitwarden/common/vault/enums";
+import { buildCipherIcon } from "@bitwarden/common/vault/icon/build-cipher-icon";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { LoginUriView } from "@bitwarden/common/vault/models/view/login-uri.view";
import { LoginView } from "@bitwarden/common/vault/models/view/login.view";
@@ -32,6 +33,7 @@ import { LoginView } from "@bitwarden/common/vault/models/view/login.view";
import { openUnlockPopout } from "../../auth/popup/utils/auth-popout-window";
import { BrowserApi } from "../../platform/browser/browser-api";
import { openAddEditVaultItemPopout } from "../../vault/popup/utils/vault-popout-window";
+import { NotificationCipherData } from "../content/components/cipher/types";
import { NotificationQueueMessageType } from "../enums/notification-queue-message-type.enum";
import { AutofillService } from "../services/abstractions/autofill.service";
@@ -82,6 +84,7 @@ export default class NotificationBackground {
bgGetActiveUserServerConfig: () => this.getActiveUserServerConfig(),
getWebVaultUrlForNotification: () => this.getWebVaultUrl(),
notificationRefreshFlagValue: () => this.getNotificationFlag(),
+ bgGetDecryptedCiphers: () => this.getNotificationCipherData(),
};
private activeUserId$ = this.accountService.activeAccount$.pipe(map((a) => a?.id));
@@ -132,6 +135,40 @@ export default class NotificationBackground {
return await firstValueFrom(this.domainSettingsService.neverDomains$);
}
+ /**
+ *
+ * Gets the current active tab and retrieves all decrypted ciphers
+ * for the tab's URL. It constructs and returns an array of `NotificationCipherData` objects.
+ * If no active tab or URL is found, it returns an empty array.
+ *
+ * @returns {Promise}
+ */
+
+ async getNotificationCipherData(): Promise {
+ const [currentTab, showFavicons, env] = await Promise.all([
+ BrowserApi.getTabFromCurrentWindow(),
+ firstValueFrom(this.domainSettingsService.showFavicons$),
+ firstValueFrom(this.environmentService.environment$),
+ ]);
+ const iconsServerUrl = env.getIconsUrl();
+ const decryptedCiphers = await this.cipherService.getAllDecryptedForUrl(currentTab.url);
+
+ return decryptedCiphers.map((view) => {
+ const { id, name, reprompt, favorite, login } = view;
+ return {
+ id,
+ name,
+ type: CipherType.Login,
+ reprompt,
+ favorite,
+ icon: buildCipherIcon(iconsServerUrl, view, showFavicons),
+ login: login && {
+ username: login.username,
+ },
+ };
+ });
+ }
+
/**
* Gets the active user server config from the config service.
*/
diff --git a/apps/browser/src/autofill/content/components/cipher/cipher-info.ts b/apps/browser/src/autofill/content/components/cipher/cipher-info.ts
index de374b44a97..6ff32353938 100644
--- a/apps/browser/src/autofill/content/components/cipher/cipher-info.ts
+++ b/apps/browser/src/autofill/content/components/cipher/cipher-info.ts
@@ -6,10 +6,10 @@ import { Theme } from "@bitwarden/common/platform/enums";
import { themes, typography } from "../../../content/components/constants/styles";
import { CipherInfoIndicatorIcons } from "./cipher-indicator-icons";
-import { CipherData } from "./types";
+import { NotificationCipherData } from "./types";
// @TODO support other cipher types (card, identity, notes, etc)
-export function CipherInfo({ cipher, theme }: { cipher: CipherData; theme: Theme }) {
+export function CipherInfo({ cipher, theme }: { cipher: NotificationCipherData; theme: Theme }) {
const { name, login } = cipher;
return html`
diff --git a/apps/browser/src/autofill/content/components/cipher/cipher-item.ts b/apps/browser/src/autofill/content/components/cipher/cipher-item.ts
index 651c20cac3a..96b44d2c0cc 100644
--- a/apps/browser/src/autofill/content/components/cipher/cipher-item.ts
+++ b/apps/browser/src/autofill/content/components/cipher/cipher-item.ts
@@ -12,7 +12,7 @@ import {
import { CipherAction } from "./cipher-action";
import { CipherIcon } from "./cipher-icon";
import { CipherInfo } from "./cipher-info";
-import { CipherData } from "./types";
+import { NotificationCipherData } from "./types";
const cipherIconWidth = "24px";
@@ -22,7 +22,7 @@ export function CipherItem({
notificationType,
theme = ThemeTypes.Light,
}: {
- cipher: CipherData;
+ cipher: NotificationCipherData;
handleAction?: (e: Event) => void;
notificationType?: NotificationType;
theme: Theme;
diff --git a/apps/browser/src/autofill/content/components/cipher/types.ts b/apps/browser/src/autofill/content/components/cipher/types.ts
index acdee756570..ff29f9b559f 100644
--- a/apps/browser/src/autofill/content/components/cipher/types.ts
+++ b/apps/browser/src/autofill/content/components/cipher/types.ts
@@ -1,6 +1,4 @@
-// FIXME: Remove when updating file. Eslint update
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-const CipherTypes = {
+export const CipherTypes = {
Login: 1,
SecureNote: 2,
Card: 3,
@@ -9,9 +7,7 @@ const CipherTypes = {
type CipherType = (typeof CipherTypes)[keyof typeof CipherTypes];
-// FIXME: Remove when updating file. Eslint update
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-const CipherRepromptTypes = {
+export const CipherRepromptTypes = {
None: 0,
Password: 1,
} as const;
@@ -25,13 +21,16 @@ export type WebsiteIconData = {
icon: string;
};
-export type CipherData = {
+type BaseCipherData = {
id: string;
name: string;
- type: CipherType;
+ type: CipherTypeValue;
reprompt: CipherRepromptType;
favorite: boolean;
icon: WebsiteIconData;
+};
+
+export type CipherData = BaseCipherData & {
accountCreationFieldType?: string;
login?: {
username: string;
@@ -46,3 +45,9 @@ export type CipherData = {
username?: string;
};
};
+
+export type NotificationCipherData = BaseCipherData & {
+ login?: {
+ username: string;
+ };
+};
diff --git a/apps/browser/src/autofill/content/components/lit-stories/notification/body.lit-stories.ts b/apps/browser/src/autofill/content/components/lit-stories/notification/body.lit-stories.ts
index 90616647b0e..c4b32e8b0f1 100644
--- a/apps/browser/src/autofill/content/components/lit-stories/notification/body.lit-stories.ts
+++ b/apps/browser/src/autofill/content/components/lit-stories/notification/body.lit-stories.ts
@@ -5,11 +5,11 @@ import { CipherType } from "@bitwarden/common/vault/enums";
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
import { NotificationType } from "../../../../notification/abstractions/notification-bar";
-import { CipherData } from "../../cipher/types";
+import { NotificationCipherData } from "../../cipher/types";
import { NotificationBody } from "../../notification/body";
type Args = {
- ciphers: CipherData[];
+ ciphers: NotificationCipherData[];
notificationType: NotificationType;
theme: Theme;
};
@@ -38,7 +38,7 @@ export default {
fallbackImage: "https://example.com/fallback.png",
icon: "icon-class",
},
- login: { username: "user@example.com", passkey: null },
+ login: { username: "user@example.com" },
},
],
theme: ThemeTypes.Light,
diff --git a/apps/browser/src/autofill/content/components/notification/body.ts b/apps/browser/src/autofill/content/components/notification/body.ts
index 6a3ed2e5d1e..6dc957ab8b8 100644
--- a/apps/browser/src/autofill/content/components/notification/body.ts
+++ b/apps/browser/src/autofill/content/components/notification/body.ts
@@ -5,7 +5,7 @@ import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums";
import { NotificationType } from "../../../notification/abstractions/notification-bar";
import { CipherItem } from "../cipher";
-import { CipherData } from "../cipher/types";
+import { NotificationCipherData } from "../cipher/types";
import { scrollbarStyles, spacing, themes, typography } from "../constants/styles";
import { ItemRow } from "../rows/item-row";
@@ -20,7 +20,7 @@ export function NotificationBody({
notificationType,
theme = ThemeTypes.Light,
}: {
- ciphers: CipherData[];
+ ciphers: NotificationCipherData[];
customClasses?: string[];
notificationType?: NotificationType;
theme: Theme;
diff --git a/apps/browser/src/autofill/content/components/notification/container.ts b/apps/browser/src/autofill/content/components/notification/container.ts
index 8bd07ab8296..8d1b57c80cd 100644
--- a/apps/browser/src/autofill/content/components/notification/container.ts
+++ b/apps/browser/src/autofill/content/components/notification/container.ts
@@ -8,8 +8,7 @@ import {
NotificationTypes,
NotificationType,
} from "../../../notification/abstractions/notification-bar";
-import { createAutofillOverlayCipherDataMock } from "../../../spec/autofill-mocks";
-import { CipherData } from "../cipher/types";
+import { NotificationCipherData } from "../cipher/types";
import { themes, spacing } from "../constants/styles";
import { NotificationBody, componentClassPrefix as notificationBodyClassPrefix } from "./body";
@@ -24,23 +23,15 @@ export function NotificationContainer({
i18n,
theme = ThemeTypes.Light,
type,
+ ciphers,
}: NotificationBarIframeInitData & { handleCloseNotification: (e: Event) => void } & {
i18n: { [key: string]: string };
type: NotificationType; // @TODO typing override for generic `NotificationBarIframeInitData.type`
+ ciphers: NotificationCipherData[];
}) {
const headerMessage = getHeaderMessage(i18n, type);
const showBody = true;
- // @TODO remove mock ciphers for development
- const ciphers = [
- createAutofillOverlayCipherDataMock(1),
- { ...createAutofillOverlayCipherDataMock(2), icon: { imageEnabled: false } },
- {
- ...createAutofillOverlayCipherDataMock(3),
- icon: { imageEnabled: true, image: "https://localhost:8443/icons/webtests.dev/icon.png" },
- },
- ] as CipherData[];
-
return html`
${NotificationHeader({
diff --git a/apps/browser/src/autofill/notification/bar.ts b/apps/browser/src/autofill/notification/bar.ts
index 202b144258d..2316df19857 100644
--- a/apps/browser/src/autofill/notification/bar.ts
+++ b/apps/browser/src/autofill/notification/bar.ts
@@ -84,23 +84,25 @@ function initNotificationBar(message: NotificationBarWindowMessage) {
document.body.innerHTML = "";
// Current implementations utilize a require for scss files which creates the need to remove the node.
document.head.querySelectorAll('link[rel="stylesheet"]').forEach((node) => node.remove());
-
const themeType = getTheme(globalThis, theme);
// There are other possible passed theme values, but for now, resolve to dark or light
const resolvedTheme: Theme = themeType === ThemeTypes.Dark ? ThemeTypes.Dark : ThemeTypes.Light;
- // @TODO use context to avoid prop drilling
- return render(
- NotificationContainer({
- ...notificationBarIframeInitData,
- type: notificationBarIframeInitData.type as NotificationType,
- theme: resolvedTheme,
- handleCloseNotification,
- i18n,
- }),
- document.body,
- );
+ sendPlatformMessage({ command: "bgGetDecryptedCiphers" }, (cipherData) => {
+ // @TODO use context to avoid prop drilling
+ return render(
+ NotificationContainer({
+ ...notificationBarIframeInitData,
+ type: notificationBarIframeInitData.type as NotificationType,
+ theme: resolvedTheme,
+ handleCloseNotification,
+ i18n,
+ ciphers: cipherData,
+ }),
+ document.body,
+ );
+ });
}
setNotificationBarTheme();
From 1746046f1862ec35f427fd87fc2df480fa180631 Mon Sep 17 00:00:00 2001
From: SmithThe4th
Date: Thu, 6 Feb 2025 12:22:27 -0500
Subject: [PATCH 011/103] Updated cipher view to have the latest value of
organizationUseTotp from server response (#13223)
---
.../vault-item-dialog/vault-item-dialog.component.ts | 3 +++
.../components/custom-fields/custom-fields.component.ts | 2 +-
.../components/item-details/item-details-section.component.ts | 2 +-
3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/apps/web/src/app/vault/components/vault-item-dialog/vault-item-dialog.component.ts b/apps/web/src/app/vault/components/vault-item-dialog/vault-item-dialog.component.ts
index 0af0d720b0e..eb2289d7229 100644
--- a/apps/web/src/app/vault/components/vault-item-dialog/vault-item-dialog.component.ts
+++ b/apps/web/src/app/vault/components/vault-item-dialog/vault-item-dialog.component.ts
@@ -366,6 +366,9 @@ export class VaultItemDialogComponent implements OnInit, OnDestroy {
const cipherData = new CipherData(cipherResponse);
cipher = new Cipher(cipherData);
+
+ // Update organizationUseTotp from server response
+ this.cipher.organizationUseTotp = cipher.organizationUseTotp;
}
// Store the updated cipher so any following edits use the most up to date cipher
diff --git a/libs/vault/src/cipher-form/components/custom-fields/custom-fields.component.ts b/libs/vault/src/cipher-form/components/custom-fields/custom-fields.component.ts
index 1b3b9009946..fed92c45f24 100644
--- a/libs/vault/src/cipher-form/components/custom-fields/custom-fields.component.ts
+++ b/libs/vault/src/cipher-form/components/custom-fields/custom-fields.component.ts
@@ -151,7 +151,7 @@ export class CustomFieldsComponent implements OnInit, AfterViewInit {
const prefillCipher = this.cipherFormContainer.getInitialCipherView();
// When available, populate the form with the existing fields
- prefillCipher.fields?.forEach((field) => {
+ prefillCipher?.fields?.forEach((field) => {
let value: string | boolean = field.value;
if (field.type === FieldType.Boolean) {
diff --git a/libs/vault/src/cipher-form/components/item-details/item-details-section.component.ts b/libs/vault/src/cipher-form/components/item-details/item-details-section.component.ts
index ca778efac4b..85cd85bbf03 100644
--- a/libs/vault/src/cipher-form/components/item-details/item-details-section.component.ts
+++ b/libs/vault/src/cipher-form/components/item-details/item-details-section.component.ts
@@ -158,7 +158,7 @@ export class ItemDetailsSectionComponent implements OnInit {
get allowOwnershipChange() {
// Do not allow ownership change in edit mode and the cipher is owned by an organization
- if (this.config.mode === "edit" && this.originalCipherView.organizationId != null) {
+ if (this.config.mode === "edit" && this.originalCipherView?.organizationId != null) {
return false;
}
From 772f45aa6342abddf1bc9936a3f834de6b8f08ee Mon Sep 17 00:00:00 2001
From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com>
Date: Thu, 6 Feb 2025 09:28:53 -0800
Subject: [PATCH 012/103] [PM-14039] - [Defect] Desktop vault changes aren't
immediately taking effect (#13186)
* favor subscription over firstValueFrom in desktop cipher view
* add event handling for username generator
* Revert "add event handling for username generator"
This reverts commit 73cffbcc6bc4635968bbc355369ad3ce21753d2e.
* close out subscription on cleanup
---
.../src/vault/components/view.component.ts | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/libs/angular/src/vault/components/view.component.ts b/libs/angular/src/vault/components/view.component.ts
index 227bc14f1b1..bec4ae52206 100644
--- a/libs/angular/src/vault/components/view.component.ts
+++ b/libs/angular/src/vault/components/view.component.ts
@@ -11,7 +11,7 @@ import {
OnInit,
Output,
} from "@angular/core";
-import { filter, firstValueFrom, map, Observable } from "rxjs";
+import { filter, firstValueFrom, map, Observable, Subject, takeUntil } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
@@ -81,6 +81,7 @@ export class ViewComponent implements OnDestroy, OnInit {
private passwordReprompted = false;
private activeUserId$ = this.accountService.activeAccount$.pipe(map((a) => a?.id));
+ private destroyed$ = new Subject();
get fido2CredentialCreationDateValue(): string {
const dateCreated = this.i18nService.t("dateCreated");
@@ -146,12 +147,15 @@ export class ViewComponent implements OnDestroy, OnInit {
const activeUserId = await firstValueFrom(this.activeUserId$);
// Grab individual cipher from `cipherViews$` for the most up-to-date information
- this.cipher = await firstValueFrom(
- this.cipherService.cipherViews$.pipe(
- map((ciphers) => ciphers.find((c) => c.id === this.cipherId)),
+ this.cipherService.cipherViews$
+ .pipe(
+ map((ciphers) => ciphers?.find((c) => c.id === this.cipherId)),
filter((cipher) => !!cipher),
- ),
- );
+ takeUntil(this.destroyed$),
+ )
+ .subscribe((cipher) => {
+ this.cipher = cipher;
+ });
this.canAccessPremium = await firstValueFrom(
this.billingAccountProfileStateService.hasPremiumFromAnySource$(activeUserId),
@@ -524,6 +528,7 @@ export class ViewComponent implements OnDestroy, OnInit {
this.showCardNumber = false;
this.showCardCode = false;
this.passwordReprompted = false;
+ this.destroyed$.next();
if (this.totpInterval) {
clearInterval(this.totpInterval);
}
From fc62d80b705c9d163a3e2c2618482e1cb5bc3e0b Mon Sep 17 00:00:00 2001
From: Daniel James Smith <2670567+djsmith85@users.noreply.github.com>
Date: Thu, 6 Feb 2025 18:59:52 +0100
Subject: [PATCH 013/103] Rename @bitwarden/importer/ui to
@bitwarden/importer-ui (#13268)
Co-authored-by: Daniel James Smith
---
.../tools/popup/settings/import/import-browser-v2.component.ts | 2 +-
apps/browser/tsconfig.json | 2 +-
apps/desktop/src/app/tools/import/import-desktop.component.ts | 2 +-
apps/desktop/src/vault/app/vault/add-edit.component.ts | 2 +-
apps/desktop/tsconfig.json | 2 +-
.../organizations/settings/org-import.component.ts | 2 +-
apps/web/src/app/tools/import/import-web.component.ts | 2 +-
apps/web/tsconfig.json | 2 +-
bitwarden_license/bit-web/tsconfig.json | 2 +-
libs/shared/tsconfig.spec.json | 2 +-
tsconfig.eslint.json | 2 +-
tsconfig.json | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/apps/browser/src/tools/popup/settings/import/import-browser-v2.component.ts b/apps/browser/src/tools/popup/settings/import/import-browser-v2.component.ts
index 66cb5c62f48..1c5558bd90e 100644
--- a/apps/browser/src/tools/popup/settings/import/import-browser-v2.component.ts
+++ b/apps/browser/src/tools/popup/settings/import/import-browser-v2.component.ts
@@ -4,7 +4,7 @@ import { Router } from "@angular/router";
import { JslibModule } from "@bitwarden/angular/jslib.module";
import { AsyncActionsModule, ButtonModule, DialogModule } from "@bitwarden/components";
-import { ImportComponent } from "@bitwarden/importer/ui";
+import { ImportComponent } from "@bitwarden/importer-ui";
import { PopOutComponent } from "../../../../platform/popup/components/pop-out.component";
import { PopupFooterComponent } from "../../../../platform/popup/layout/popup-footer.component";
diff --git a/apps/browser/tsconfig.json b/apps/browser/tsconfig.json
index 81b9bc870c4..8055260db57 100644
--- a/apps/browser/tsconfig.json
+++ b/apps/browser/tsconfig.json
@@ -25,7 +25,7 @@
"@bitwarden/generator-legacy": ["../../libs/tools/generator/extensions/legacy/src"],
"@bitwarden/generator-navigation": ["../../libs/tools/generator/extensions/navigation/src"],
"@bitwarden/importer-core": ["../../libs/importer/src"],
- "@bitwarden/importer/ui": ["../../libs/importer/src/components"],
+ "@bitwarden/importer-ui": ["../../libs/importer/src/components"],
"@bitwarden/key-management": ["../../libs/key-management/src"],
"@bitwarden/key-management-ui": ["../../libs/key-management-ui/src"],
"@bitwarden/platform": ["../../libs/platform/src"],
diff --git a/apps/desktop/src/app/tools/import/import-desktop.component.ts b/apps/desktop/src/app/tools/import/import-desktop.component.ts
index 62fc007731d..72fe02b14fd 100644
--- a/apps/desktop/src/app/tools/import/import-desktop.component.ts
+++ b/apps/desktop/src/app/tools/import/import-desktop.component.ts
@@ -4,7 +4,7 @@ import { Component } from "@angular/core";
import { JslibModule } from "@bitwarden/angular/jslib.module";
import { AsyncActionsModule, ButtonModule, DialogModule } from "@bitwarden/components";
-import { ImportComponent } from "@bitwarden/importer/ui";
+import { ImportComponent } from "@bitwarden/importer-ui";
@Component({
templateUrl: "import-desktop.component.html",
diff --git a/apps/desktop/src/vault/app/vault/add-edit.component.ts b/apps/desktop/src/vault/app/vault/add-edit.component.ts
index f2ca05c9336..ae332c9723b 100644
--- a/apps/desktop/src/vault/app/vault/add-edit.component.ts
+++ b/apps/desktop/src/vault/app/vault/add-edit.component.ts
@@ -25,7 +25,7 @@ import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folde
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { CipherAuthorizationService } from "@bitwarden/common/vault/services/cipher-authorization.service";
import { DialogService, ToastService } from "@bitwarden/components";
-import { SshKeyPasswordPromptComponent } from "@bitwarden/importer/ui";
+import { SshKeyPasswordPromptComponent } from "@bitwarden/importer-ui";
import { PasswordRepromptService } from "@bitwarden/vault";
const BroadcasterSubscriptionId = "AddEditComponent";
diff --git a/apps/desktop/tsconfig.json b/apps/desktop/tsconfig.json
index 1bd97b0130f..0bef5a5564d 100644
--- a/apps/desktop/tsconfig.json
+++ b/apps/desktop/tsconfig.json
@@ -23,7 +23,7 @@
"@bitwarden/generator-legacy": ["../../libs/tools/generator/extensions/legacy/src"],
"@bitwarden/generator-navigation": ["../../libs/tools/generator/extensions/navigation/src"],
"@bitwarden/importer-core": ["../../libs/importer/src"],
- "@bitwarden/importer/ui": ["../../libs/importer/src/components"],
+ "@bitwarden/importer-ui": ["../../libs/importer/src/components"],
"@bitwarden/key-management": ["../../libs/key-management/src"],
"@bitwarden/key-management-ui": ["../../libs/key-management-ui/src"],
"@bitwarden/node/*": ["../../libs/node/src/*"],
diff --git a/apps/web/src/app/admin-console/organizations/settings/org-import.component.ts b/apps/web/src/app/admin-console/organizations/settings/org-import.component.ts
index 78784bdd3d2..e7a0051253f 100644
--- a/apps/web/src/app/admin-console/organizations/settings/org-import.component.ts
+++ b/apps/web/src/app/admin-console/organizations/settings/org-import.component.ts
@@ -11,8 +11,8 @@ import {
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { getUserId } from "@bitwarden/common/auth/services/account.service";
-import { ImportComponent } from "@bitwarden/importer/ui";
import { ImportCollectionServiceAbstraction } from "@bitwarden/importer-core";
+import { ImportComponent } from "@bitwarden/importer-ui";
import { LooseComponentsModule, SharedModule } from "../../../shared";
import { ImportCollectionAdminService } from "../../../tools/import/import-collection-admin.service";
diff --git a/apps/web/src/app/tools/import/import-web.component.ts b/apps/web/src/app/tools/import/import-web.component.ts
index 3f1d5155039..a527b9e71f4 100644
--- a/apps/web/src/app/tools/import/import-web.component.ts
+++ b/apps/web/src/app/tools/import/import-web.component.ts
@@ -1,7 +1,7 @@
import { Component } from "@angular/core";
import { Router } from "@angular/router";
-import { ImportComponent } from "@bitwarden/importer/ui";
+import { ImportComponent } from "@bitwarden/importer-ui";
import { HeaderModule } from "../../layouts/header/header.module";
import { SharedModule } from "../../shared";
diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json
index c05f24b9a8d..68ac8c80085 100644
--- a/apps/web/tsconfig.json
+++ b/apps/web/tsconfig.json
@@ -19,7 +19,7 @@
"@bitwarden/generator-legacy": ["../../libs/tools/generator/extensions/legacy/src"],
"@bitwarden/generator-navigation": ["../../libs/tools/generator/extensions/navigation/src"],
"@bitwarden/importer-core": ["../../libs/importer/src"],
- "@bitwarden/importer/ui": ["../../libs/importer/src/components"],
+ "@bitwarden/importer-ui": ["../../libs/importer/src/components"],
"@bitwarden/key-management": ["../../libs/key-management/src"],
"@bitwarden/key-management-ui": ["../../libs/key-management-ui/src"],
"@bitwarden/platform": ["../../libs/platform/src"],
diff --git a/bitwarden_license/bit-web/tsconfig.json b/bitwarden_license/bit-web/tsconfig.json
index 1c9a530d273..82e0b7f57fa 100644
--- a/bitwarden_license/bit-web/tsconfig.json
+++ b/bitwarden_license/bit-web/tsconfig.json
@@ -22,7 +22,7 @@
],
"@bitwarden/vault-export-ui": ["../../libs/tools/export/vault-export/vault-export-ui/src"],
"@bitwarden/importer-core": ["../../libs/importer/src"],
- "@bitwarden/importer/ui": ["../../libs/importer/src/components"],
+ "@bitwarden/importer-ui": ["../../libs/importer/src/components"],
"@bitwarden/key-management": ["../../libs/key-management/src"],
"@bitwarden/key-management-ui": ["../../libs/key-management-ui/src"],
"@bitwarden/platform": ["../../libs/platform/src"],
diff --git a/libs/shared/tsconfig.spec.json b/libs/shared/tsconfig.spec.json
index c0f082793e9..9c98378659e 100644
--- a/libs/shared/tsconfig.spec.json
+++ b/libs/shared/tsconfig.spec.json
@@ -16,7 +16,7 @@
"@bitwarden/generator-legacy": ["../tools/generator/extensions/legacy/src"],
"@bitwarden/generator-navigation": ["../tools/generator/extensions/navigation/src"],
"@bitwarden/importer-core": ["../importer/src"],
- "@bitwarden/importer/ui": ["../importer/src/components"],
+ "@bitwarden/importer-ui": ["../importer/src/components"],
"@bitwarden/key-management": ["../key-management/src"],
"@bitwarden/key-management-ui": ["../key-management-ui/src/index.ts"],
"@bitwarden/node/*": ["../node/src/*"],
diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json
index 91586ce1dd2..611b30a3bdb 100644
--- a/tsconfig.eslint.json
+++ b/tsconfig.eslint.json
@@ -29,7 +29,7 @@
"@bitwarden/generator-legacy": ["./libs/tools/generator/extensions/legacy/src"],
"@bitwarden/generator-navigation": ["./libs/tools/generator/extensions/navigation/src"],
"@bitwarden/importer-core": ["./libs/importer/src"],
- "@bitwarden/importer/ui": ["./libs/importer/src/components"],
+ "@bitwarden/importer-ui": ["./libs/importer/src/components"],
"@bitwarden/key-management": ["./libs/key-management/src"],
"@bitwarden/key-management-ui": ["./libs/key-management-ui/src/index,ts"],
"@bitwarden/node/*": ["./libs/node/src/*"],
diff --git a/tsconfig.json b/tsconfig.json
index 95f0dd154b8..e6e4c47096b 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -30,7 +30,7 @@
"@bitwarden/generator-legacy": ["./libs/tools/generator/extensions/legacy/src"],
"@bitwarden/generator-navigation": ["./libs/tools/generator/extensions/navigation/src"],
"@bitwarden/importer-core": ["./libs/importer/src"],
- "@bitwarden/importer/ui": ["./libs/importer/src/components"],
+ "@bitwarden/importer-ui": ["./libs/importer/src/components"],
"@bitwarden/key-management": ["./libs/key-management/src"],
"@bitwarden/key-management-ui": ["./libs/key-management-ui/src"],
"@bitwarden/node/*": ["./libs/node/src/*"],
From 0b5b1b347e214fb0d93ef958c0b3cf5079c55e9f Mon Sep 17 00:00:00 2001
From: Daniel James Smith <2670567+djsmith85@users.noreply.github.com>
Date: Thu, 6 Feb 2025 19:06:37 +0100
Subject: [PATCH 014/103] [PM-17165] Remove v1 generator UI from web (#13240)
* Remove v1 generator from web
Remove conditional routing based on `generator-tools-modernization`
Remove generatorSwap helper
Remove generator and password-generator-history components including the base ones in libs/angular
* Remove the feature flag `generator-tools-modernization`
* Remove unused keys from en/messages.json
* Remove unused css
---------
Co-authored-by: Daniel James Smith
---
apps/web/src/app/oss-routing.module.ts | 7 +-
.../src/app/shared/loose-components.module.ts | 6 -
.../src/app/tools/generator.component.html | 479 ------------------
apps/web/src/app/tools/generator.component.ts | 73 ---
.../password-generator-history.component.html | 47 --
.../password-generator-history.component.ts | 22 -
apps/web/src/locales/en/messages.json | 24 -
apps/web/src/scss/pages.scss | 34 --
.../components/generator.component.ts | 389 --------------
.../password-generator-history.component.ts | 40 --
.../src/tools/generator/generator-swap.ts | 32 --
libs/common/src/enums/feature-flag.enum.ts | 2 -
12 files changed, 3 insertions(+), 1152 deletions(-)
delete mode 100644 apps/web/src/app/tools/generator.component.html
delete mode 100644 apps/web/src/app/tools/generator.component.ts
delete mode 100644 apps/web/src/app/tools/password-generator-history.component.html
delete mode 100644 apps/web/src/app/tools/password-generator-history.component.ts
delete mode 100644 libs/angular/src/tools/generator/components/generator.component.ts
delete mode 100644 libs/angular/src/tools/generator/components/password-generator-history.component.ts
delete mode 100644 libs/angular/src/tools/generator/generator-swap.ts
diff --git a/apps/web/src/app/oss-routing.module.ts b/apps/web/src/app/oss-routing.module.ts
index 6863d6721e9..ac7e8cd8625 100644
--- a/apps/web/src/app/oss-routing.module.ts
+++ b/apps/web/src/app/oss-routing.module.ts
@@ -12,7 +12,6 @@ import {
activeAuthGuard,
} from "@bitwarden/angular/auth/guards";
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";
-import { generatorSwap } from "@bitwarden/angular/tools/generator/generator-swap";
import { twofactorRefactorSwap } from "@bitwarden/angular/utils/two-factor-component-refactor-route-swap";
import { NewDeviceVerificationNoticeGuard } from "@bitwarden/angular/vault/guards";
import {
@@ -90,7 +89,6 @@ import { SMLandingComponent } from "./secrets-manager/secrets-manager-landing/sm
import { DomainRulesComponent } from "./settings/domain-rules.component";
import { PreferencesComponent } from "./settings/preferences.component";
import { CredentialGeneratorComponent } from "./tools/credential-generator/credential-generator.component";
-import { GeneratorComponent } from "./tools/generator.component";
import { ReportsModule } from "./tools/reports";
import { AccessComponent } from "./tools/send/access.component";
import { SendAccessExplainerComponent } from "./tools/send/send-access-explainer.component";
@@ -831,10 +829,11 @@ const routes: Routes = [
titleId: "exportVault",
} satisfies RouteDataProperties,
},
- ...generatorSwap(GeneratorComponent, CredentialGeneratorComponent, {
+ {
path: "generator",
+ component: CredentialGeneratorComponent,
data: { titleId: "generator" } satisfies RouteDataProperties,
- }),
+ },
],
},
{
diff --git a/apps/web/src/app/shared/loose-components.module.ts b/apps/web/src/app/shared/loose-components.module.ts
index d6ba5a1990c..881b87e0819 100644
--- a/apps/web/src/app/shared/loose-components.module.ts
+++ b/apps/web/src/app/shared/loose-components.module.ts
@@ -66,8 +66,6 @@ import { ProductSwitcherModule } from "../layouts/product-switcher/product-switc
import { UserLayoutComponent } from "../layouts/user-layout.component";
import { DomainRulesComponent } from "../settings/domain-rules.component";
import { PreferencesComponent } from "../settings/preferences.component";
-import { GeneratorComponent } from "../tools/generator.component";
-import { PasswordGeneratorHistoryComponent } from "../tools/password-generator-history.component";
import { AddEditComponent as SendAddEditComponent } from "../tools/send/add-edit.component";
import { PremiumBadgeComponent } from "../vault/components/premium-badge.component";
import { AddEditCustomFieldsComponent } from "../vault/individual-vault/add-edit-custom-fields.component";
@@ -139,8 +137,6 @@ import { SharedModule } from "./shared.module";
OrgUnsecuredWebsitesReportComponent,
OrgUserConfirmComponent,
OrgWeakPasswordsReportComponent,
- GeneratorComponent,
- PasswordGeneratorHistoryComponent,
PreferencesComponent,
PremiumBadgeComponent,
ProfileComponent,
@@ -206,8 +202,6 @@ import { SharedModule } from "./shared.module";
OrgUnsecuredWebsitesReportComponent,
OrgUserConfirmComponent,
OrgWeakPasswordsReportComponent,
- GeneratorComponent,
- PasswordGeneratorHistoryComponent,
PreferencesComponent,
PremiumBadgeComponent,
ProfileComponent,
diff --git a/apps/web/src/app/tools/generator.component.html b/apps/web/src/app/tools/generator.component.html
deleted file mode 100644
index d73fe377011..00000000000
--- a/apps/web/src/app/tools/generator.component.html
+++ /dev/null
@@ -1,479 +0,0 @@
-
-
-
-
- {{ "passwordGeneratorPolicyInEffect" | i18n }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/web/src/app/tools/generator.component.ts b/apps/web/src/app/tools/generator.component.ts
deleted file mode 100644
index a11c0c4a97b..00000000000
--- a/apps/web/src/app/tools/generator.component.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-// FIXME: Update this file to be type safe and remove this and next line
-// @ts-strict-ignore
-import { Component, NgZone } from "@angular/core";
-import { ActivatedRoute } from "@angular/router";
-
-import { GeneratorComponent as BaseGeneratorComponent } from "@bitwarden/angular/tools/generator/components/generator.component";
-import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
-import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
-import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
-import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
-import { DialogService, ToastService } from "@bitwarden/components";
-import {
- PasswordGenerationServiceAbstraction,
- UsernameGenerationServiceAbstraction,
-} from "@bitwarden/generator-legacy";
-
-import { PasswordGeneratorHistoryComponent } from "./password-generator-history.component";
-
-@Component({
- selector: "app-generator",
- templateUrl: "generator.component.html",
-})
-export class GeneratorComponent extends BaseGeneratorComponent {
- constructor(
- passwordGenerationService: PasswordGenerationServiceAbstraction,
- usernameGenerationService: UsernameGenerationServiceAbstraction,
- accountService: AccountService,
- platformUtilsService: PlatformUtilsService,
- i18nService: I18nService,
- logService: LogService,
- route: ActivatedRoute,
- ngZone: NgZone,
- private dialogService: DialogService,
- toastService: ToastService,
- ) {
- super(
- passwordGenerationService,
- usernameGenerationService,
- platformUtilsService,
- accountService,
- i18nService,
- logService,
- route,
- ngZone,
- window,
- toastService,
- );
- if (platformUtilsService.isSelfHost()) {
- // Allow only valid email forwarders for self host
- this.forwardOptions = this.forwardOptions.filter((forwarder) => forwarder.validForSelfHosted);
- }
- }
-
- get isSelfHosted(): boolean {
- return this.platformUtilsService.isSelfHost();
- }
-
- async history() {
- this.dialogService.open(PasswordGeneratorHistoryComponent);
- }
-
- lengthChanged() {
- document.getElementById("length").focus();
- }
-
- minNumberChanged() {
- document.getElementById("min-number").focus();
- }
-
- minSpecialChanged() {
- document.getElementById("min-special").focus();
- }
-}
diff --git a/apps/web/src/app/tools/password-generator-history.component.html b/apps/web/src/app/tools/password-generator-history.component.html
deleted file mode 100644
index eabb45ece2d..00000000000
--- a/apps/web/src/app/tools/password-generator-history.component.html
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
- {{ "passwordHistory" | i18n }}
-
-
-
-
-
- |
-
-
- {{ h.date | date: "medium" }}
-
- |
-
-
- |
-
-
-
-
- {{ "noPasswordsInList" | i18n }}
-
-
-
-
-
-
-
diff --git a/apps/web/src/app/tools/password-generator-history.component.ts b/apps/web/src/app/tools/password-generator-history.component.ts
deleted file mode 100644
index 0c7c9c4e221..00000000000
--- a/apps/web/src/app/tools/password-generator-history.component.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { Component } from "@angular/core";
-
-import { PasswordGeneratorHistoryComponent as BasePasswordGeneratorHistoryComponent } from "@bitwarden/angular/tools/generator/components/password-generator-history.component";
-import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
-import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
-import { ToastService } from "@bitwarden/components";
-import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
-
-@Component({
- selector: "app-password-generator-history",
- templateUrl: "password-generator-history.component.html",
-})
-export class PasswordGeneratorHistoryComponent extends BasePasswordGeneratorHistoryComponent {
- constructor(
- passwordGenerationService: PasswordGenerationServiceAbstraction,
- platformUtilsService: PlatformUtilsService,
- i18nService: I18nService,
- toastService: ToastService,
- ) {
- super(passwordGenerationService, platformUtilsService, i18nService, window, toastService);
- }
-}
diff --git a/apps/web/src/locales/en/messages.json b/apps/web/src/locales/en/messages.json
index f663a4c6397..0f48595f09b 100644
--- a/apps/web/src/locales/en/messages.json
+++ b/apps/web/src/locales/en/messages.json
@@ -1718,9 +1718,6 @@
"message": "Avoid ambiguous characters",
"description": "Label for the avoid ambiguous characters checkbox."
},
- "regeneratePassword": {
- "message": "Regenerate password"
- },
"length": {
"message": "Length"
},
@@ -4773,9 +4770,6 @@
"passwordGeneratorPolicyDesc": {
"message": "Set requirements for password generator."
},
- "passwordGeneratorPolicyInEffect": {
- "message": "One or more organization policies are affecting your generator settings."
- },
"masterPasswordPolicyInEffect": {
"message": "One or more organization policies require your master password to meet the following requirements:"
},
@@ -6744,15 +6738,6 @@
"message": "Generator",
"description": "Short for 'credential generator'."
},
- "whatWouldYouLikeToGenerate": {
- "message": "What would you like to generate?"
- },
- "passwordType": {
- "message": "Password type"
- },
- "regenerateUsername": {
- "message": "Regenerate username"
- },
"generateUsername": {
"message": "Generate username"
},
@@ -6793,9 +6778,6 @@
}
}
},
- "usernameType": {
- "message": "Username type"
- },
"plusAddressedEmail": {
"message": "Plus addressed email",
"description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com"
@@ -7015,9 +6997,6 @@
"message": "Hostname",
"description": "Part of a URL."
},
- "apiAccessToken": {
- "message": "API access token"
- },
"deviceVerification": {
"message": "Device verification"
},
@@ -8728,9 +8707,6 @@
"message": "Self-host server URL",
"description": "Label for field requesting a self-hosted integration service URL"
},
- "aliasDomain": {
- "message": "Alias domain"
- },
"alreadyHaveAccount": {
"message": "Already have an account?"
},
diff --git a/apps/web/src/scss/pages.scss b/apps/web/src/scss/pages.scss
index 684d45a1a66..1e5c233e326 100644
--- a/apps/web/src/scss/pages.scss
+++ b/apps/web/src/scss/pages.scss
@@ -1,37 +1,3 @@
-app-generator {
- #lengthRange {
- width: 100%;
- }
-
- .card-generated {
- .card-body {
- @include themify($themes) {
- background: themed("foregroundColor");
- }
- align-items: center;
- display: flex;
- flex-wrap: wrap;
- font-family: $font-family-monospace;
- font-size: $font-size-lg;
- justify-content: center;
- text-align: center;
- }
- }
-}
-
-app-password-generator-history {
- .list-group-item {
- line-height: 1;
- @include themify($themes) {
- background: themed("backgroundColor");
- }
-
- .password {
- font-family: $font-family-monospace;
- }
- }
-}
-
tools-import {
textarea {
height: 150px;
diff --git a/libs/angular/src/tools/generator/components/generator.component.ts b/libs/angular/src/tools/generator/components/generator.component.ts
deleted file mode 100644
index 1f3c635e499..00000000000
--- a/libs/angular/src/tools/generator/components/generator.component.ts
+++ /dev/null
@@ -1,389 +0,0 @@
-// FIXME: Update this file to be type safe and remove this and next line
-// @ts-strict-ignore
-import { Directive, EventEmitter, Input, NgZone, OnDestroy, OnInit, Output } from "@angular/core";
-import { ActivatedRoute } from "@angular/router";
-import { BehaviorSubject, combineLatest, firstValueFrom, Subject } from "rxjs";
-import { debounceTime, first, map, skipWhile, takeUntil } from "rxjs/operators";
-
-import { PasswordGeneratorPolicyOptions } from "@bitwarden/common/admin-console/models/domain/password-generator-policy-options";
-import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
-import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
-import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
-import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
-import { ToastService } from "@bitwarden/components";
-import {
- GeneratorType,
- DefaultPasswordBoundaries as DefaultBoundaries,
-} from "@bitwarden/generator-core";
-import {
- PasswordGenerationServiceAbstraction,
- UsernameGenerationServiceAbstraction,
- UsernameGeneratorOptions,
- PasswordGeneratorOptions,
-} from "@bitwarden/generator-legacy";
-
-export class EmailForwarderOptions {
- name: string;
- value: string;
- validForSelfHosted: boolean;
-}
-
-@Directive()
-export class GeneratorComponent implements OnInit, OnDestroy {
- @Input() comingFromAddEdit = false;
- @Input() type: GeneratorType | "";
- @Output() onSelected = new EventEmitter();
-
- usernameGeneratingPromise: Promise;
- typeOptions: any[];
- usernameTypeOptions: any[];
- subaddressOptions: any[];
- catchallOptions: any[];
- forwardOptions: EmailForwarderOptions[];
- usernameOptions: UsernameGeneratorOptions = { website: null };
- passwordOptions: PasswordGeneratorOptions = {};
- username = "-";
- password = "-";
- showOptions = false;
- avoidAmbiguous = false;
- enforcedPasswordPolicyOptions: PasswordGeneratorPolicyOptions;
- usernameWebsite: string = null;
-
- get passTypeOptions() {
- return this._passTypeOptions.filter((o) => !o.disabled);
- }
- private _passTypeOptions: { name: string; value: GeneratorType; disabled: boolean }[];
-
- private destroy$ = new Subject();
- private isInitialized$ = new BehaviorSubject(false);
-
- // update screen reader minimum password length with 500ms debounce
- // so that the user isn't flooded with status updates
- private _passwordOptionsMinLengthForReader = new BehaviorSubject(
- DefaultBoundaries.length.min,
- );
- protected passwordOptionsMinLengthForReader$ = this._passwordOptionsMinLengthForReader.pipe(
- map((val) => val || DefaultBoundaries.length.min),
- debounceTime(500),
- );
-
- private _password = new BehaviorSubject("-");
-
- constructor(
- protected passwordGenerationService: PasswordGenerationServiceAbstraction,
- protected usernameGenerationService: UsernameGenerationServiceAbstraction,
- protected platformUtilsService: PlatformUtilsService,
- protected accountService: AccountService,
- protected i18nService: I18nService,
- protected logService: LogService,
- protected route: ActivatedRoute,
- protected ngZone: NgZone,
- private win: Window,
- protected toastService: ToastService,
- ) {
- this.typeOptions = [
- { name: i18nService.t("password"), value: "password" },
- { name: i18nService.t("username"), value: "username" },
- ];
- this._passTypeOptions = [
- { name: i18nService.t("password"), value: "password", disabled: false },
- { name: i18nService.t("passphrase"), value: "passphrase", disabled: false },
- ];
- this.usernameTypeOptions = [
- {
- name: i18nService.t("plusAddressedEmail"),
- value: "subaddress",
- desc: i18nService.t("plusAddressedEmailDesc"),
- },
- {
- name: i18nService.t("catchallEmail"),
- value: "catchall",
- desc: i18nService.t("catchallEmailDesc"),
- },
- {
- name: i18nService.t("forwardedEmail"),
- value: "forwarded",
- desc: i18nService.t("forwardedEmailDesc"),
- },
- { name: i18nService.t("randomWord"), value: "word" },
- ];
- this.subaddressOptions = [{ name: i18nService.t("random"), value: "random" }];
- this.catchallOptions = [{ name: i18nService.t("random"), value: "random" }];
-
- this.forwardOptions = [
- { name: "", value: "", validForSelfHosted: false },
- { name: "addy.io", value: "anonaddy", validForSelfHosted: true },
- { name: "DuckDuckGo", value: "duckduckgo", validForSelfHosted: false },
- { name: "Fastmail", value: "fastmail", validForSelfHosted: true },
- { name: "Firefox Relay", value: "firefoxrelay", validForSelfHosted: false },
- { name: "SimpleLogin", value: "simplelogin", validForSelfHosted: true },
- { name: "Forward Email", value: "forwardemail", validForSelfHosted: true },
- ].sort((a, b) => a.name.localeCompare(b.name));
-
- this._password.pipe(debounceTime(250)).subscribe((password) => {
- ngZone.run(() => {
- this.password = password;
- });
- this.passwordGenerationService.addHistory(this.password).catch((e) => {
- this.logService.error(e);
- });
- });
- }
-
- cascadeOptions(navigationType: GeneratorType = undefined, accountEmail: string) {
- this.avoidAmbiguous = !this.passwordOptions.ambiguous;
-
- if (!this.type) {
- if (navigationType) {
- this.type = navigationType;
- } else {
- this.type = this.passwordOptions.type === "username" ? "username" : "password";
- }
- }
-
- this.passwordOptions.type =
- this.passwordOptions.type === "passphrase" ? "passphrase" : "password";
-
- const overrideType = this.enforcedPasswordPolicyOptions.overridePasswordType ?? "";
- const isDisabled = overrideType.length
- ? (value: string, policyValue: string) => value !== policyValue
- : (_value: string, _policyValue: string) => false;
- for (const option of this._passTypeOptions) {
- option.disabled = isDisabled(option.value, overrideType);
- }
-
- if (this.usernameOptions.type == null) {
- this.usernameOptions.type = "word";
- }
- if (
- this.usernameOptions.subaddressEmail == null ||
- this.usernameOptions.subaddressEmail === ""
- ) {
- this.usernameOptions.subaddressEmail = accountEmail;
- }
- if (this.usernameWebsite == null) {
- this.usernameOptions.subaddressType = this.usernameOptions.catchallType = "random";
- } else {
- this.usernameOptions.website = this.usernameWebsite;
- }
- }
-
- async ngOnInit() {
- combineLatest([
- this.route.queryParams.pipe(first()),
- this.accountService.activeAccount$.pipe(first()),
- this.passwordGenerationService.getOptions$(),
- this.usernameGenerationService.getOptions$(),
- ])
- .pipe(
- map(([qParams, account, [passwordOptions, passwordPolicy], usernameOptions]) => ({
- navigationType: qParams.type as GeneratorType,
- accountEmail: account.email,
- passwordOptions,
- passwordPolicy,
- usernameOptions,
- })),
- takeUntil(this.destroy$),
- )
- .subscribe((options) => {
- this.passwordOptions = options.passwordOptions;
- this.enforcedPasswordPolicyOptions = options.passwordPolicy;
- this.usernameOptions = options.usernameOptions;
-
- this.cascadeOptions(options.navigationType, options.accountEmail);
- this._passwordOptionsMinLengthForReader.next(this.passwordOptions.minLength);
-
- if (this.regenerateWithoutButtonPress()) {
- this.regenerate().catch((e) => {
- this.logService.error(e);
- });
- }
-
- this.isInitialized$.next(true);
- });
-
- // once initialization is complete, `ngOnInit` should return.
- //
- // FIXME(#6944): if a sync is in progress, wait to complete until after
- // the sync completes.
- await firstValueFrom(
- this.isInitialized$.pipe(
- skipWhile((initialized) => !initialized),
- takeUntil(this.destroy$),
- ),
- );
-
- if (this.usernameWebsite !== null) {
- const websiteOption = { name: this.i18nService.t("websiteName"), value: "website-name" };
- this.subaddressOptions.push(websiteOption);
- this.catchallOptions.push(websiteOption);
- }
- }
-
- ngOnDestroy() {
- this.destroy$.next();
- this.destroy$.complete();
- this.isInitialized$.complete();
- this._passwordOptionsMinLengthForReader.complete();
- }
-
- async typeChanged() {
- await this.savePasswordOptions();
- }
-
- async regenerate() {
- if (this.type === "password") {
- await this.regeneratePassword();
- } else if (this.type === "username") {
- await this.regenerateUsername();
- }
- }
-
- async sliderChanged() {
- // 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.savePasswordOptions();
- await this.passwordGenerationService.addHistory(this.password);
- }
-
- async onPasswordOptionsMinNumberInput($event: Event) {
- // `savePasswordOptions()` replaces the null
- this.passwordOptions.number = null;
-
- await this.savePasswordOptions();
-
- // fixes UI desync that occurs when minNumber has a fixed value
- // that is reset through normalization
- ($event.target as HTMLInputElement).value = `${this.passwordOptions.minNumber}`;
- }
-
- async setPasswordOptionsNumber($event: boolean) {
- this.passwordOptions.number = $event;
- // `savePasswordOptions()` replaces the null
- this.passwordOptions.minNumber = null;
-
- await this.savePasswordOptions();
- }
-
- async onPasswordOptionsMinSpecialInput($event: Event) {
- // `savePasswordOptions()` replaces the null
- this.passwordOptions.special = null;
-
- await this.savePasswordOptions();
-
- // fixes UI desync that occurs when minSpecial has a fixed value
- // that is reset through normalization
- ($event.target as HTMLInputElement).value = `${this.passwordOptions.minSpecial}`;
- }
-
- async setPasswordOptionsSpecial($event: boolean) {
- this.passwordOptions.special = $event;
- // `savePasswordOptions()` replaces the null
- this.passwordOptions.minSpecial = null;
-
- await this.savePasswordOptions();
- }
-
- async sliderInput() {
- await this.normalizePasswordOptions();
- }
-
- async savePasswordOptions() {
- // map navigation state into generator type
- const restoreType = this.passwordOptions.type;
- if (this.type === "username") {
- this.passwordOptions.type = this.type;
- }
-
- // save options
- await this.normalizePasswordOptions();
- await this.passwordGenerationService.saveOptions(this.passwordOptions);
-
- // restore the original format
- this.passwordOptions.type = restoreType;
- }
-
- async saveUsernameOptions() {
- await this.usernameGenerationService.saveOptions(this.usernameOptions);
- if (this.usernameOptions.type === "forwarded") {
- this.username = "-";
- }
- }
-
- async regeneratePassword() {
- this._password.next(
- await this.passwordGenerationService.generatePassword(this.passwordOptions),
- );
- }
-
- regenerateUsername() {
- return this.generateUsername();
- }
-
- async generateUsername() {
- try {
- this.usernameGeneratingPromise = this.usernameGenerationService.generateUsername(
- this.usernameOptions,
- );
- this.username = await this.usernameGeneratingPromise;
- if (this.username === "" || this.username === null) {
- this.username = "-";
- }
- } catch (e) {
- this.logService.error(e);
- }
- }
-
- copy() {
- const password = this.type === "password";
- const copyOptions = this.win != null ? { window: this.win } : null;
- this.platformUtilsService.copyToClipboard(
- password ? this.password : this.username,
- copyOptions,
- );
- this.toastService.showToast({
- variant: "info",
- title: null,
- message: this.i18nService.t(
- "valueCopied",
- this.i18nService.t(password ? "password" : "username"),
- ),
- });
- }
-
- select() {
- this.onSelected.emit(this.type === "password" ? this.password : this.username);
- }
-
- toggleOptions() {
- this.showOptions = !this.showOptions;
- }
-
- regenerateWithoutButtonPress() {
- return this.type !== "username" || this.usernameOptions.type !== "forwarded";
- }
-
- private async normalizePasswordOptions() {
- // Application level normalize options dependent on class variables
- this.passwordOptions.ambiguous = !this.avoidAmbiguous;
-
- if (
- !this.passwordOptions.uppercase &&
- !this.passwordOptions.lowercase &&
- !this.passwordOptions.number &&
- !this.passwordOptions.special
- ) {
- this.passwordOptions.lowercase = true;
- if (this.win != null) {
- const lowercase = this.win.document.querySelector("#lowercase") as HTMLInputElement;
- if (lowercase) {
- lowercase.checked = true;
- }
- }
- }
-
- await this.passwordGenerationService.enforcePasswordGeneratorPoliciesOnOptions(
- this.passwordOptions,
- );
- }
-}
diff --git a/libs/angular/src/tools/generator/components/password-generator-history.component.ts b/libs/angular/src/tools/generator/components/password-generator-history.component.ts
deleted file mode 100644
index 2933163fce2..00000000000
--- a/libs/angular/src/tools/generator/components/password-generator-history.component.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-// FIXME: Update this file to be type safe and remove this and next line
-// @ts-strict-ignore
-import { Directive, OnInit } from "@angular/core";
-
-import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
-import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
-import { ToastService } from "@bitwarden/components";
-import { GeneratedPasswordHistory } from "@bitwarden/generator-history";
-import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
-
-@Directive()
-export class PasswordGeneratorHistoryComponent implements OnInit {
- history: GeneratedPasswordHistory[] = [];
-
- constructor(
- protected passwordGenerationService: PasswordGenerationServiceAbstraction,
- protected platformUtilsService: PlatformUtilsService,
- protected i18nService: I18nService,
- private win: Window,
- protected toastService: ToastService,
- ) {}
-
- async ngOnInit() {
- this.history = await this.passwordGenerationService.getHistory();
- }
-
- clear = async () => {
- this.history = await this.passwordGenerationService.clear();
- };
-
- copy(password: string) {
- const copyOptions = this.win != null ? { window: this.win } : null;
- this.platformUtilsService.copyToClipboard(password, copyOptions);
- this.toastService.showToast({
- variant: "info",
- title: null,
- message: this.i18nService.t("valueCopied", this.i18nService.t("password")),
- });
- }
-}
diff --git a/libs/angular/src/tools/generator/generator-swap.ts b/libs/angular/src/tools/generator/generator-swap.ts
deleted file mode 100644
index 16fafc67116..00000000000
--- a/libs/angular/src/tools/generator/generator-swap.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { Type, inject } from "@angular/core";
-import { Route, Routes } from "@angular/router";
-
-import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
-
-import { componentRouteSwap } from "../../utils/component-route-swap";
-
-/**
- * Helper function to swap between two components based on the GeneratorToolsModernization feature flag.
- * @param defaultComponent - The current non-refreshed component to render.
- * @param refreshedComponent - The new refreshed component to render.
- * @param options - The shared route options to apply to the default component, and to the alt component if altOptions is not provided.
- * @param altOptions - The alt route options to apply to the alt component.
- */
-export function generatorSwap(
- defaultComponent: Type,
- refreshedComponent: Type,
- options: Route,
- altOptions?: Route,
-): Routes {
- return componentRouteSwap(
- defaultComponent,
- refreshedComponent,
- async () => {
- const configService = inject(ConfigService);
- return configService.getFeatureFlag(FeatureFlag.GeneratorToolsModernization);
- },
- options,
- altOptions,
- );
-}
diff --git a/libs/common/src/enums/feature-flag.enum.ts b/libs/common/src/enums/feature-flag.enum.ts
index 550a8c07ff7..a8e036c82d6 100644
--- a/libs/common/src/enums/feature-flag.enum.ts
+++ b/libs/common/src/enums/feature-flag.enum.ts
@@ -26,7 +26,6 @@ export enum FeatureFlag {
/* Tools */
ItemShare = "item-share",
- GeneratorToolsModernization = "generator-tools-modernization",
CriticalApps = "pm-14466-risk-insights-critical-application",
EnableRiskInsightsNotifications = "enable-risk-insights-notifications",
@@ -88,7 +87,6 @@ export const DefaultFeatureFlagValue = {
/* Tools */
[FeatureFlag.ItemShare]: FALSE,
- [FeatureFlag.GeneratorToolsModernization]: FALSE,
[FeatureFlag.CriticalApps]: FALSE,
[FeatureFlag.EnableRiskInsightsNotifications]: FALSE,
From b9faf2c9c066866baf252bb778212dcc300a61c4 Mon Sep 17 00:00:00 2001
From: Vicki League
Date: Thu, 6 Feb 2025 13:33:07 -0500
Subject: [PATCH 015/103] [PM-15975] Prevent dialogs from overlapping
interactive top menu bars (#13251)
---
libs/components/src/dialog/dialog/dialog.component.ts | 3 ++-
.../src/credential-generator-history-dialog.component.html | 6 ------
.../src/credential-generator-history-dialog.component.ts | 7 -------
3 files changed, 2 insertions(+), 14 deletions(-)
diff --git a/libs/components/src/dialog/dialog/dialog.component.ts b/libs/components/src/dialog/dialog/dialog.component.ts
index e9e3e898257..504dbd3a1ea 100644
--- a/libs/components/src/dialog/dialog/dialog.component.ts
+++ b/libs/components/src/dialog/dialog/dialog.component.ts
@@ -63,7 +63,8 @@ export class DialogComponent {
@Input() loading = false;
@HostBinding("class") get classes() {
- return ["tw-flex", "tw-flex-col", "tw-max-h-screen", "tw-w-screen", "tw-p-4"].concat(
+ // `tw-max-h-[90vh]` is needed to prevent dialogs from overlapping the desktop header
+ return ["tw-flex", "tw-flex-col", "tw-w-screen", "tw-p-4", "tw-max-h-[90vh]"].concat(
this.width,
);
}
diff --git a/libs/tools/generator/components/src/credential-generator-history-dialog.component.html b/libs/tools/generator/components/src/credential-generator-history-dialog.component.html
index ad629601c34..b07eb62ae98 100644
--- a/libs/tools/generator/components/src/credential-generator-history-dialog.component.html
+++ b/libs/tools/generator/components/src/credential-generator-history-dialog.component.html
@@ -14,11 +14,5 @@
>
{{ "clearHistory" | i18n }}
-
-
diff --git a/libs/tools/generator/components/src/credential-generator-history-dialog.component.ts b/libs/tools/generator/components/src/credential-generator-history-dialog.component.ts
index 7bcffd92399..58da1157f7c 100644
--- a/libs/tools/generator/components/src/credential-generator-history-dialog.component.ts
+++ b/libs/tools/generator/components/src/credential-generator-history-dialog.component.ts
@@ -1,6 +1,5 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
-import { DialogRef } from "@angular/cdk/dialog";
import { CommonModule } from "@angular/common";
import { Component } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
@@ -35,7 +34,6 @@ export class CredentialGeneratorHistoryDialogComponent {
private accountService: AccountService,
private history: GeneratorHistoryService,
private dialogService: DialogService,
- private dialogRef: DialogRef,
) {
this.accountService.activeAccount$
.pipe(
@@ -54,11 +52,6 @@ export class CredentialGeneratorHistoryDialogComponent {
.subscribe(this.hasHistory$);
}
- /** closes the dialog */
- protected close() {
- this.dialogRef.close();
- }
-
/** Launches clear history flow */
protected async clear() {
const confirmed = await this.dialogService.openSimpleDialog({
From 1a001ff9a1e0b36ad867a91f86333409e5befb38 Mon Sep 17 00:00:00 2001
From: Brandon Treston
Date: Thu, 6 Feb 2025 13:53:23 -0500
Subject: [PATCH 016/103] [PM-18037] account deprovisioning banner (#13290)
* enable migration
---
libs/common/src/state-migrations/migrate.ts | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/libs/common/src/state-migrations/migrate.ts b/libs/common/src/state-migrations/migrate.ts
index 169de447f10..b409f52d936 100644
--- a/libs/common/src/state-migrations/migrate.ts
+++ b/libs/common/src/state-migrations/migrate.ts
@@ -68,12 +68,13 @@ import { RemoveUnassignedItemsBannerDismissed } from "./migrations/67-remove-una
import { MoveLastSyncDate } from "./migrations/68-move-last-sync-date";
import { MigrateIncorrectFolderKey } from "./migrations/69-migrate-incorrect-folder-key";
import { MoveBiometricAutoPromptToAccount } from "./migrations/7-move-biometric-auto-prompt-to-account";
+import { RemoveAcBannersDismissed } from "./migrations/70-remove-ac-banner-dismissed";
import { MoveStateVersionMigrator } from "./migrations/8-move-state-version";
import { MoveBrowserSettingsToGlobal } from "./migrations/9-move-browser-settings-to-global";
import { MinVersionMigrator } from "./migrations/min-version";
export const MIN_VERSION = 3;
-export const CURRENT_VERSION = 69;
+export const CURRENT_VERSION = 70;
export type MinVersion = typeof MIN_VERSION;
export function createMigrationBuilder() {
@@ -144,7 +145,8 @@ export function createMigrationBuilder() {
.with(MoveFinalDesktopSettingsMigrator, 65, 66)
.with(RemoveUnassignedItemsBannerDismissed, 66, 67)
.with(MoveLastSyncDate, 67, 68)
- .with(MigrateIncorrectFolderKey, 68, CURRENT_VERSION);
+ .with(MigrateIncorrectFolderKey, 68, 69)
+ .with(RemoveAcBannersDismissed, 69, CURRENT_VERSION);
}
export async function currentVersion(
From 3e988fae6f554fdb11d881eedfdd4058f619753d Mon Sep 17 00:00:00 2001
From: Todd Martin <106564991+trmartin4@users.noreply.github.com>
Date: Thu, 6 Feb 2025 14:37:08 -0500
Subject: [PATCH 017/103] Remove feature flag check from opt-out (#13130)
---
apps/web/src/app/auth/settings/account/account.component.html | 2 +-
apps/web/src/app/auth/settings/account/account.component.ts | 4 ----
2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/apps/web/src/app/auth/settings/account/account.component.html b/apps/web/src/app/auth/settings/account/account.component.html
index 9f405c65083..c5edc021614 100644
--- a/apps/web/src/app/auth/settings/account/account.component.html
+++ b/apps/web/src/app/auth/settings/account/account.component.html
@@ -9,7 +9,7 @@
-
+
|
-
+
|
{
+ showOrgAtRiskMembers = async (invokerId: string) => {
const dialogData = this.reportService.generateAtRiskMemberList(this.dataSource.data);
- this.dataService.setDrawerForOrgAtRiskMembers(dialogData);
+ this.dataService.setDrawerForOrgAtRiskMembers(dialogData, invokerId);
};
- showOrgAtRiskApps = async () => {
+ showOrgAtRiskApps = async (invokerId: string) => {
const data = this.reportService.generateAtRiskApplicationList(this.dataSource.data);
- this.dataService.setDrawerForOrgAtRiskApps(data);
+ this.dataService.setDrawerForOrgAtRiskApps(data, invokerId);
};
onCheckboxChange(applicationName: string, event: Event) {
diff --git a/bitwarden_license/bit-web/src/app/tools/access-intelligence/critical-applications.component.html b/bitwarden_license/bit-web/src/app/tools/access-intelligence/critical-applications.component.html
index 72e60c470b0..4dc4b7ffb1a 100644
--- a/bitwarden_license/bit-web/src/app/tools/access-intelligence/critical-applications.component.html
+++ b/bitwarden_license/bit-web/src/app/tools/access-intelligence/critical-applications.component.html
@@ -35,19 +35,27 @@
@@ -70,7 +78,11 @@
|
-
+
|
|
diff --git a/bitwarden_license/bit-web/src/app/tools/access-intelligence/critical-applications.component.ts b/bitwarden_license/bit-web/src/app/tools/access-intelligence/critical-applications.component.ts
index 4d820a3cc66..f1fa38dd28f 100644
--- a/bitwarden_license/bit-web/src/app/tools/access-intelligence/critical-applications.component.ts
+++ b/bitwarden_license/bit-web/src/app/tools/access-intelligence/critical-applications.component.ts
@@ -131,17 +131,17 @@ export class CriticalApplicationsComponent implements OnInit {
?.atRiskMemberDetails ?? [],
applicationName,
};
- this.dataService.setDrawerForAppAtRiskMembers(data);
+ this.dataService.setDrawerForAppAtRiskMembers(data, applicationName);
};
- showOrgAtRiskMembers = async () => {
+ showOrgAtRiskMembers = async (invokerId: string) => {
const data = this.reportService.generateAtRiskMemberList(this.dataSource.data);
- this.dataService.setDrawerForOrgAtRiskMembers(data);
+ this.dataService.setDrawerForOrgAtRiskMembers(data, invokerId);
};
- showOrgAtRiskApps = async () => {
+ showOrgAtRiskApps = async (invokerId: string) => {
const data = this.reportService.generateAtRiskApplicationList(this.dataSource.data);
- this.dataService.setDrawerForOrgAtRiskApps(data);
+ this.dataService.setDrawerForOrgAtRiskApps(data, invokerId);
};
trackByFunction(_: number, item: ApplicationHealthReportDetailWithCriticalFlag) {
diff --git a/bitwarden_license/bit-web/src/app/tools/access-intelligence/risk-insights.component.html b/bitwarden_license/bit-web/src/app/tools/access-intelligence/risk-insights.component.html
index a368f5c0c18..12082e888b0 100644
--- a/bitwarden_license/bit-web/src/app/tools/access-intelligence/risk-insights.component.html
+++ b/bitwarden_license/bit-web/src/app/tools/access-intelligence/risk-insights.component.html
@@ -56,7 +56,11 @@
-
+
Date: Fri, 7 Feb 2025 12:15:05 -0500
Subject: [PATCH 026/103] [PM-16792] add semantic logger facade (#13255)
---
.../tools/log/default-semantic-logger.spec.ts | 199 ++++++++++++++++++
.../src/tools/log/default-semantic-logger.ts | 65 ++++++
.../src/tools/log/disabled-semantic-logger.ts | 18 ++
libs/common/src/tools/log/factory.ts | 30 +++
libs/common/src/tools/log/index.ts | 2 +
.../tools/log/semantic-logger.abstraction.ts | 94 +++++++++
6 files changed, 408 insertions(+)
create mode 100644 libs/common/src/tools/log/default-semantic-logger.spec.ts
create mode 100644 libs/common/src/tools/log/default-semantic-logger.ts
create mode 100644 libs/common/src/tools/log/disabled-semantic-logger.ts
create mode 100644 libs/common/src/tools/log/factory.ts
create mode 100644 libs/common/src/tools/log/index.ts
create mode 100644 libs/common/src/tools/log/semantic-logger.abstraction.ts
diff --git a/libs/common/src/tools/log/default-semantic-logger.spec.ts b/libs/common/src/tools/log/default-semantic-logger.spec.ts
new file mode 100644
index 00000000000..8d1dadb66af
--- /dev/null
+++ b/libs/common/src/tools/log/default-semantic-logger.spec.ts
@@ -0,0 +1,199 @@
+import { mock } from "jest-mock-extended";
+
+import { LogService } from "../../platform/abstractions/log.service";
+import { LogLevelType } from "../../platform/enums";
+
+import { DefaultSemanticLogger } from "./default-semantic-logger";
+
+const logger = mock();
+
+describe("DefaultSemanticLogger", () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ describe("debug", () => {
+ it("writes structural log messages to console.log", () => {
+ const log = new DefaultSemanticLogger(logger, {});
+
+ log.debug("this is a debug message");
+
+ expect(logger.write).toHaveBeenCalledWith(LogLevelType.Debug, {
+ message: "this is a debug message",
+ level: LogLevelType.Debug,
+ });
+ });
+
+ it("writes structural content to console.log", () => {
+ const log = new DefaultSemanticLogger(logger, {});
+
+ log.debug({ example: "this is content" });
+
+ expect(logger.write).toHaveBeenCalledWith(LogLevelType.Debug, {
+ content: { example: "this is content" },
+ level: LogLevelType.Debug,
+ });
+ });
+
+ it("writes structural content to console.log with a message", () => {
+ const log = new DefaultSemanticLogger(logger, {});
+
+ log.info({ example: "this is content" }, "this is a message");
+
+ expect(logger.write).toHaveBeenCalledWith(LogLevelType.Info, {
+ content: { example: "this is content" },
+ message: "this is a message",
+ level: LogLevelType.Info,
+ });
+ });
+ });
+
+ describe("info", () => {
+ it("writes structural log messages to console.log", () => {
+ const log = new DefaultSemanticLogger(logger, {});
+
+ log.info("this is an info message");
+
+ expect(logger.write).toHaveBeenCalledWith(LogLevelType.Info, {
+ message: "this is an info message",
+ level: LogLevelType.Info,
+ });
+ });
+
+ it("writes structural content to console.log", () => {
+ const log = new DefaultSemanticLogger(logger, {});
+
+ log.info({ example: "this is content" });
+
+ expect(logger.write).toHaveBeenCalledWith(LogLevelType.Info, {
+ content: { example: "this is content" },
+ level: LogLevelType.Info,
+ });
+ });
+
+ it("writes structural content to console.log with a message", () => {
+ const log = new DefaultSemanticLogger(logger, {});
+
+ log.info({ example: "this is content" }, "this is a message");
+
+ expect(logger.write).toHaveBeenCalledWith(LogLevelType.Info, {
+ content: { example: "this is content" },
+ message: "this is a message",
+ level: LogLevelType.Info,
+ });
+ });
+ });
+
+ describe("warn", () => {
+ it("writes structural log messages to console.warn", () => {
+ const log = new DefaultSemanticLogger(logger, {});
+
+ log.warn("this is a warning message");
+
+ expect(logger.write).toHaveBeenCalledWith(LogLevelType.Warning, {
+ message: "this is a warning message",
+ level: LogLevelType.Warning,
+ });
+ });
+
+ it("writes structural content to console.warn", () => {
+ const log = new DefaultSemanticLogger(logger, {});
+
+ log.warn({ example: "this is content" });
+
+ expect(logger.write).toHaveBeenCalledWith(LogLevelType.Warning, {
+ content: { example: "this is content" },
+ level: LogLevelType.Warning,
+ });
+ });
+
+ it("writes structural content to console.warn with a message", () => {
+ const log = new DefaultSemanticLogger(logger, {});
+
+ log.warn({ example: "this is content" }, "this is a message");
+
+ expect(logger.write).toHaveBeenCalledWith(LogLevelType.Warning, {
+ content: { example: "this is content" },
+ message: "this is a message",
+ level: LogLevelType.Warning,
+ });
+ });
+ });
+
+ describe("error", () => {
+ it("writes structural log messages to console.error", () => {
+ const log = new DefaultSemanticLogger(logger, {});
+
+ log.error("this is an error message");
+
+ expect(logger.write).toHaveBeenCalledWith(LogLevelType.Error, {
+ message: "this is an error message",
+ level: LogLevelType.Error,
+ });
+ });
+
+ it("writes structural content to console.error", () => {
+ const log = new DefaultSemanticLogger(logger, {});
+
+ log.error({ example: "this is content" });
+
+ expect(logger.write).toHaveBeenCalledWith(LogLevelType.Error, {
+ content: { example: "this is content" },
+ level: LogLevelType.Error,
+ });
+ });
+
+ it("writes structural content to console.error with a message", () => {
+ const log = new DefaultSemanticLogger(logger, {});
+
+ log.error({ example: "this is content" }, "this is a message");
+
+ expect(logger.write).toHaveBeenCalledWith(LogLevelType.Error, {
+ content: { example: "this is content" },
+ message: "this is a message",
+ level: LogLevelType.Error,
+ });
+ });
+ });
+
+ describe("panic", () => {
+ it("writes structural log messages to console.error before throwing the message", () => {
+ const log = new DefaultSemanticLogger(logger, {});
+
+ expect(() => log.panic("this is an error message")).toThrow("this is an error message");
+
+ expect(logger.write).toHaveBeenCalledWith(LogLevelType.Error, {
+ message: "this is an error message",
+ level: LogLevelType.Error,
+ });
+ });
+
+ it("writes structural log messages to console.error with a message before throwing the message", () => {
+ const log = new DefaultSemanticLogger(logger, {});
+
+ expect(() => log.panic({ example: "this is content" }, "this is an error message")).toThrow(
+ "this is an error message",
+ );
+
+ expect(logger.write).toHaveBeenCalledWith(LogLevelType.Error, {
+ content: { example: "this is content" },
+ message: "this is an error message",
+ level: LogLevelType.Error,
+ });
+ });
+
+ it("writes structural log messages to console.error with a content before throwing the message", () => {
+ const log = new DefaultSemanticLogger(logger, {});
+
+ expect(() => log.panic("this is content", "this is an error message")).toThrow(
+ "this is an error message",
+ );
+
+ expect(logger.write).toHaveBeenCalledWith(LogLevelType.Error, {
+ content: "this is content",
+ message: "this is an error message",
+ level: LogLevelType.Error,
+ });
+ });
+ });
+});
diff --git a/libs/common/src/tools/log/default-semantic-logger.ts b/libs/common/src/tools/log/default-semantic-logger.ts
new file mode 100644
index 00000000000..1bd62baf126
--- /dev/null
+++ b/libs/common/src/tools/log/default-semantic-logger.ts
@@ -0,0 +1,65 @@
+import { Jsonify } from "type-fest";
+
+import { LogService } from "../../platform/abstractions/log.service";
+import { LogLevelType } from "../../platform/enums";
+
+import { SemanticLogger } from "./semantic-logger.abstraction";
+
+/** Sends semantic logs to the console.
+ * @remarks the behavior of this logger is based on `LogService`; it
+ * replaces dynamic messages (`%s`) with a JSON-formatted semantic log.
+ */
+export class DefaultSemanticLogger implements SemanticLogger {
+ /** Instantiates a console semantic logger
+ * @param context a static payload that is cloned when the logger
+ * logs a message. The `messages`, `level`, and `content` fields
+ * are reserved for use by loggers.
+ */
+ constructor(
+ private logger: LogService,
+ context: Jsonify,
+ ) {
+ this.context = context && typeof context === "object" ? context : {};
+ }
+
+ readonly context: object;
+
+ debug(content: Jsonify, message?: string): void {
+ this.log(content, LogLevelType.Debug, message);
+ }
+
+ info(content: Jsonify, message?: string): void {
+ this.log(content, LogLevelType.Info, message);
+ }
+
+ warn(content: Jsonify, message?: string): void {
+ this.log(content, LogLevelType.Warning, message);
+ }
+
+ error(content: Jsonify, message?: string): void {
+ this.log(content, LogLevelType.Error, message);
+ }
+
+ panic(content: Jsonify, message?: string): never {
+ this.log(content, LogLevelType.Error, message);
+ const panicMessage =
+ message ?? (typeof content === "string" ? content : "a fatal error occurred");
+ throw new Error(panicMessage);
+ }
+
+ private log(content: Jsonify, level: LogLevelType, message?: string) {
+ const log = {
+ ...this.context,
+ message,
+ content: content ?? undefined,
+ level,
+ };
+
+ if (typeof content === "string" && !message) {
+ log.message = content;
+ delete log.content;
+ }
+
+ this.logger.write(level, log);
+ }
+}
diff --git a/libs/common/src/tools/log/disabled-semantic-logger.ts b/libs/common/src/tools/log/disabled-semantic-logger.ts
new file mode 100644
index 00000000000..054c3ed390b
--- /dev/null
+++ b/libs/common/src/tools/log/disabled-semantic-logger.ts
@@ -0,0 +1,18 @@
+import { Jsonify } from "type-fest";
+
+import { SemanticLogger } from "./semantic-logger.abstraction";
+
+/** Disables semantic logs. Still panics. */
+export class DisabledSemanticLogger implements SemanticLogger {
+ debug(_content: Jsonify, _message?: string): void {}
+
+ info(_content: Jsonify, _message?: string): void {}
+
+ warn(_content: Jsonify, _message?: string): void {}
+
+ error(_content: Jsonify, _message?: string): void {}
+
+ panic(_content: Jsonify, message?: string): never {
+ throw new Error(message);
+ }
+}
diff --git a/libs/common/src/tools/log/factory.ts b/libs/common/src/tools/log/factory.ts
new file mode 100644
index 00000000000..d887c4e310a
--- /dev/null
+++ b/libs/common/src/tools/log/factory.ts
@@ -0,0 +1,30 @@
+import { Jsonify } from "type-fest";
+
+import { LogService } from "../../platform/abstractions/log.service";
+
+import { DefaultSemanticLogger } from "./default-semantic-logger";
+import { DisabledSemanticLogger } from "./disabled-semantic-logger";
+import { SemanticLogger } from "./semantic-logger.abstraction";
+
+/** Instantiates a semantic logger that emits nothing when a message
+ * is logged.
+ * @param _context a static payload that is cloned when the logger
+ * logs a message. The `messages`, `level`, and `content` fields
+ * are reserved for use by loggers.
+ */
+export function disabledSemanticLoggerProvider(
+ _context: Jsonify,
+): SemanticLogger {
+ return new DisabledSemanticLogger();
+}
+
+/** Instantiates a semantic logger that emits logs to the console.
+ * @param context a static payload that is cloned when the logger
+ * logs a message. The `messages`, `level`, and `content` fields
+ * are reserved for use by loggers.
+ * @param settings specializes how the semantic logger functions.
+ * If this is omitted, the logger suppresses debug messages.
+ */
+export function consoleSemanticLoggerProvider(logger: LogService): SemanticLogger {
+ return new DefaultSemanticLogger(logger, {});
+}
diff --git a/libs/common/src/tools/log/index.ts b/libs/common/src/tools/log/index.ts
new file mode 100644
index 00000000000..1f86ca4e4d7
--- /dev/null
+++ b/libs/common/src/tools/log/index.ts
@@ -0,0 +1,2 @@
+export { disabledSemanticLoggerProvider, consoleSemanticLoggerProvider } from "./factory";
+export { SemanticLogger } from "./semantic-logger.abstraction";
diff --git a/libs/common/src/tools/log/semantic-logger.abstraction.ts b/libs/common/src/tools/log/semantic-logger.abstraction.ts
new file mode 100644
index 00000000000..196d1f3f12c
--- /dev/null
+++ b/libs/common/src/tools/log/semantic-logger.abstraction.ts
@@ -0,0 +1,94 @@
+import { Jsonify } from "type-fest";
+
+/** Semantic/structural logging component */
+export interface SemanticLogger {
+ /** Logs a message at debug priority.
+ * Debug messages are used for diagnostics, and are typically disabled
+ * in production builds.
+ * @param message - a message to record in the log's `message` field.
+ */
+ debug(message: string): void;
+
+ /** Logs the content at debug priority.
+ * Debug messages are used for diagnostics, and are typically disabled
+ * in production builds.
+ * @param content - JSON content included in the log's `content` field.
+ * @param message - a message to record in the log's `message` field.
+ */
+ debug(content: Jsonify, message?: string): void;
+
+ /** combined signature for overloaded methods */
+ debug(content: Jsonify | string, message?: string): void;
+
+ /** Logs a message at informational priority.
+ * Information messages are used for status reports.
+ * @param message - a message to record in the log's `message` field.
+ */
+ info(message: string): void;
+
+ /** Logs the content at informational priority.
+ * Information messages are used for status reports.
+ * @param content - JSON content included in the log's `content` field.
+ * @param message - a message to record in the log's `message` field.
+ */
+ info(content: Jsonify, message?: string): void;
+
+ /** combined signature for overloaded methods */
+ info(content: Jsonify | string, message?: string): void;
+
+ /** Logs a message at warn priority.
+ * Warn messages are used to indicate a operation that may affect system
+ * stability occurred.
+ * @param message - a message to record in the log's `message` field.
+ */
+ warn(message: string): void;
+
+ /** Logs the content at warn priority.
+ * Warn messages are used to indicate a operation that may affect system
+ * stability occurred.
+ * @param content - JSON content included in the log's `content` field.
+ * @param message - a message to record in the log's `message` field.
+ */
+ warn(content: Jsonify, message?: string): void;
+
+ /** combined signature for overloaded methods */
+ warn(content: Jsonify | string, message?: string): void;
+
+ /** Logs a message at error priority.
+ * Error messages are used to indicate a operation that affects system
+ * stability occurred and the system was able to recover.
+ * @param message - a message to record in the log's `message` field.
+ */
+ error(message: string): void;
+
+ /** Logs the content at debug priority.
+ * Error messages are used to indicate a operation that affects system
+ * stability occurred and the system was able to recover.
+ * @param content - JSON content included in the log's `content` field.
+ * @param message - a message to record in the log's `message` field.
+ */
+ error(content: Jsonify, message?: string): void;
+
+ /** combined signature for overloaded methods */
+ error(content: Jsonify | string, message?: string): void;
+
+ /** Logs a message at panic priority and throws an error.
+ * Panic messages are used to indicate a operation that affects system
+ * stability occurred and the system cannot recover. Panic messages
+ * log an error and throw an `Error`.
+ * @param message - a message to record in the log's `message` field.
+ */
+ panic(message: string): never;
+
+ /** Logs the content at debug priority and throws an error.
+ * Panic messages are used to indicate a operation that affects system
+ * stability occurred and the system cannot recover. Panic messages
+ * log an error and throw an `Error`.
+ * @param content - JSON content included in the log's `content` field.
+ * @param message - a message to record in the log's `message` field.
+ */
+ panic(content: Jsonify, message?: string): never;
+
+ /** combined signature for overloaded methods */
+ panic(content: Jsonify | string, message?: string): never;
+}
From 95ef2f523cc5bffd75ecb5f68403ca7ba05dcf2d Mon Sep 17 00:00:00 2001
From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com>
Date: Fri, 7 Feb 2025 10:05:37 -0800
Subject: [PATCH 027/103] [PM-16707] - show password history for hidden field
types (#13199)
* don't limit password history to login types
* don't display password change date if it's not present
---
.../item-history/item-history-v2.component.html | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libs/vault/src/cipher-view/item-history/item-history-v2.component.html b/libs/vault/src/cipher-view/item-history/item-history-v2.component.html
index a207b8fa1ca..19d1cfe1744 100644
--- a/libs/vault/src/cipher-view/item-history/item-history-v2.component.html
+++ b/libs/vault/src/cipher-view/item-history/item-history-v2.component.html
@@ -10,15 +10,15 @@
{{ "dateCreated" | i18n }}:
{{ cipher.creationDate | date: "medium" }}
@@ -26,7 +26,7 @@
{{ cipher.passwordRevisionDisplayDate | date: "medium" }}
|