From 06b3c37f038e3f611b064522bf3407aaa6c9e2c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Van=C4=9Bk?= Date: Mon, 25 Nov 2024 16:46:17 +0100 Subject: [PATCH 01/13] [PM-15167] Fix password generator ascii ambiguous sets (#12143) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ✨ Audrey ✨ --- libs/tools/generator/core/src/engine/data.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/tools/generator/core/src/engine/data.ts b/libs/tools/generator/core/src/engine/data.ts index d0155a49b25..a46a3e668d5 100644 --- a/libs/tools/generator/core/src/engine/data.ts +++ b/libs/tools/generator/core/src/engine/data.ts @@ -13,7 +13,7 @@ export const Ascii = Object.freeze({ /** The full set of characters available to the generator */ Full: Object.freeze({ Uppercase: toCharacterSet("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), - Lowercase: toCharacterSet("abcdefghijkmnopqrstuvwxyz"), + Lowercase: toCharacterSet("abcdefghijklmnopqrstuvwxyz"), Digit: toCharacterSet("0123456789"), Special: SpecialCharacters, } as CharacterSets), @@ -21,7 +21,7 @@ export const Ascii = Object.freeze({ /** All characters available to the generator that are not ambiguous. */ Unmistakable: Object.freeze({ Uppercase: toCharacterSet("ABCDEFGHJKLMNPQRSTUVWXYZ"), - Lowercase: toCharacterSet("abcdefghijklmnopqrstuvwxyz"), + Lowercase: toCharacterSet("abcdefghijkmnopqrstuvwxyz"), Digit: toCharacterSet("23456789"), Special: SpecialCharacters, } as CharacterSets), From 12fa1af2c52bfcccef16289b2398892609933557 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 16:59:00 +0100 Subject: [PATCH 02/13] [deps] Platform: Pin Rust crate tokio-util to =0.7.11 (#12121) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- apps/desktop/desktop_native/core/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/desktop_native/core/Cargo.toml b/apps/desktop/desktop_native/core/Cargo.toml index 5fc64969b74..1b8a0a04675 100644 --- a/apps/desktop/desktop_native/core/Cargo.toml +++ b/apps/desktop/desktop_native/core/Cargo.toml @@ -53,7 +53,7 @@ ssh-key = { version = "=0.6.6", default-features = false, features = [ bitwarden-russh = { git = "https://github.com/bitwarden/bitwarden-russh.git", branch = "km/pm-10098/clean-russh-implementation" } tokio = { version = "=1.40.0", features = ["io-util", "sync", "macros", "net"] } tokio-stream = { version = "=0.1.15", features = ["net"] } -tokio-util = { version = "0.7.11", features = ["codec"] } +tokio-util = { version = "=0.7.11", features = ["codec"] } thiserror = "=1.0.69" typenum = "=1.17.0" rand_chacha = "=0.3.1" From 08ce0c863b851e88a9ad52e1f7067aaec964e128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 25 Nov 2024 17:14:53 +0100 Subject: [PATCH 03/13] Fix conflict with pinned dependency (#12147) # Conflicts: # apps/desktop/desktop_native/core/Cargo.toml --- apps/desktop/desktop_native/core/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/desktop_native/core/Cargo.toml b/apps/desktop/desktop_native/core/Cargo.toml index 1b8a0a04675..f4dcb608d2c 100644 --- a/apps/desktop/desktop_native/core/Cargo.toml +++ b/apps/desktop/desktop_native/core/Cargo.toml @@ -53,7 +53,7 @@ ssh-key = { version = "=0.6.6", default-features = false, features = [ bitwarden-russh = { git = "https://github.com/bitwarden/bitwarden-russh.git", branch = "km/pm-10098/clean-russh-implementation" } tokio = { version = "=1.40.0", features = ["io-util", "sync", "macros", "net"] } tokio-stream = { version = "=0.1.15", features = ["net"] } -tokio-util = { version = "=0.7.11", features = ["codec"] } +tokio-util = { version = "=0.7.12", features = ["codec"] } thiserror = "=1.0.69" typenum = "=1.17.0" rand_chacha = "=0.3.1" From 0be38c580c3d4b78400c6a5ba7e8af9a782ecf08 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 11:20:54 -0500 Subject: [PATCH 04/13] [deps] Autofill: Update tldts to v6.1.64 (#12123) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- apps/cli/package.json | 2 +- package-lock.json | 18 +++++++++--------- package.json | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/cli/package.json b/apps/cli/package.json index 8be8f9ca34a..617e1df6dca 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -80,7 +80,7 @@ "papaparse": "5.4.1", "proper-lockfile": "4.1.2", "rxjs": "7.8.1", - "tldts": "6.1.61", + "tldts": "6.1.64", "zxcvbn": "4.4.2" } } diff --git a/package-lock.json b/package-lock.json index d5b44a8caeb..f82995b4cc0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -68,7 +68,7 @@ "qrious": "4.0.2", "rxjs": "7.8.1", "tabbable": "6.2.0", - "tldts": "6.1.61", + "tldts": "6.1.64", "utf-8-validate": "6.0.5", "zone.js": "0.14.10", "zxcvbn": "4.4.2" @@ -220,7 +220,7 @@ "papaparse": "5.4.1", "proper-lockfile": "4.1.2", "rxjs": "7.8.1", - "tldts": "6.1.61", + "tldts": "6.1.64", "zxcvbn": "4.4.2" }, "bin": { @@ -31664,21 +31664,21 @@ } }, "node_modules/tldts": { - "version": "6.1.61", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.61.tgz", - "integrity": "sha512-rv8LUyez4Ygkopqn+M6OLItAOT9FF3REpPQDkdMx5ix8w4qkuE7Vo2o/vw1nxKQYmJDV8JpAMJQr1b+lTKf0FA==", + "version": "6.1.64", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.64.tgz", + "integrity": "sha512-ph4AE5BXWIOsSy9stpoeo7bYe/Cy7VfpciIH4RhVZUPItCJmhqWCN0EVzxd8BOHiyNb42vuJc6NWTjJkg91Tuw==", "license": "MIT", "dependencies": { - "tldts-core": "^6.1.61" + "tldts-core": "^6.1.64" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.61", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.61.tgz", - "integrity": "sha512-In7VffkDWUPgwa+c9picLUxvb0RltVwTkSgMNFgvlGSWveCzGBemBqTsgJCL4EDFWZ6WH0fKTsot6yNhzy3ZzQ==", + "version": "6.1.64", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.64.tgz", + "integrity": "sha512-uqnl8vGV16KsyflHOzqrYjjArjfXaU6rMPXYy2/ZWoRKCkXtghgB4VwTDXUG+t0OTGeSewNAG31/x1gCTfLt+Q==", "license": "MIT" }, "node_modules/tmp": { diff --git a/package.json b/package.json index 0968e4c6b06..aea2c792868 100644 --- a/package.json +++ b/package.json @@ -197,7 +197,7 @@ "qrious": "4.0.2", "rxjs": "7.8.1", "tabbable": "6.2.0", - "tldts": "6.1.61", + "tldts": "6.1.64", "utf-8-validate": "6.0.5", "zone.js": "0.14.10", "zxcvbn": "4.4.2" From f3e1124b346c4ac6cc5e3c3810c393438bedd83f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 11:21:29 -0500 Subject: [PATCH 05/13] [deps] Platform: Update @types/node to v22.9.3 (#12127) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .../native-messaging-test-runner/package-lock.json | 8 ++++---- apps/desktop/native-messaging-test-runner/package.json | 2 +- package-lock.json | 8 ++++---- package.json | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/desktop/native-messaging-test-runner/package-lock.json b/apps/desktop/native-messaging-test-runner/package-lock.json index f51c0a32d9d..8dd8204b69e 100644 --- a/apps/desktop/native-messaging-test-runner/package-lock.json +++ b/apps/desktop/native-messaging-test-runner/package-lock.json @@ -18,7 +18,7 @@ "yargs": "17.7.2" }, "devDependencies": { - "@types/node": "22.9.0", + "@types/node": "22.9.3", "@types/node-ipc": "9.2.3", "typescript": "4.7.4" } @@ -106,9 +106,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", - "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", + "version": "22.9.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.3.tgz", + "integrity": "sha512-F3u1fs/fce3FFk+DAxbxc78DF8x0cY09RRL8GnXLmkJ1jvx3TtPdWoTT5/NiYfI5ASqXBmfqJi9dZ3gxMx4lzw==", "license": "MIT", "dependencies": { "undici-types": "~6.19.8" diff --git a/apps/desktop/native-messaging-test-runner/package.json b/apps/desktop/native-messaging-test-runner/package.json index 23b1dbdafba..d2da248522e 100644 --- a/apps/desktop/native-messaging-test-runner/package.json +++ b/apps/desktop/native-messaging-test-runner/package.json @@ -23,7 +23,7 @@ "yargs": "17.7.2" }, "devDependencies": { - "@types/node": "22.9.0", + "@types/node": "22.9.3", "@types/node-ipc": "9.2.3", "typescript": "4.7.4" }, diff --git a/package-lock.json b/package-lock.json index f82995b4cc0..ff25cd26ce6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -111,7 +111,7 @@ "@types/koa-json": "2.0.23", "@types/lowdb": "1.0.15", "@types/lunr": "2.3.7", - "@types/node": "22.9.0", + "@types/node": "22.9.3", "@types/node-fetch": "2.6.4", "@types/node-forge": "1.3.11", "@types/node-ipc": "9.2.3", @@ -9751,9 +9751,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", - "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", + "version": "22.9.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.3.tgz", + "integrity": "sha512-F3u1fs/fce3FFk+DAxbxc78DF8x0cY09RRL8GnXLmkJ1jvx3TtPdWoTT5/NiYfI5ASqXBmfqJi9dZ3gxMx4lzw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index aea2c792868..1426c27c0c5 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "@types/koa-json": "2.0.23", "@types/lowdb": "1.0.15", "@types/lunr": "2.3.7", - "@types/node": "22.9.0", + "@types/node": "22.9.3", "@types/node-fetch": "2.6.4", "@types/node-forge": "1.3.11", "@types/node-ipc": "9.2.3", From 2e5a043f1a1a3d60bf41e3d4b5a358aab67f1c00 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 11:24:31 -0500 Subject: [PATCH 06/13] [deps] Autofill: Update prettier-plugin-tailwindcss to v0.6.9 (#12122) 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 ff25cd26ce6..59fb666d4ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -160,7 +160,7 @@ "postcss": "8.4.47", "postcss-loader": "8.1.1", "prettier": "3.3.3", - "prettier-plugin-tailwindcss": "0.6.8", + "prettier-plugin-tailwindcss": "0.6.9", "process": "0.11.10", "remark-gfm": "4.0.0", "rimraf": "6.0.1", @@ -27911,9 +27911,9 @@ } }, "node_modules/prettier-plugin-tailwindcss": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.8.tgz", - "integrity": "sha512-dGu3kdm7SXPkiW4nzeWKCl3uoImdd5CTZEJGxyypEPL37Wj0HT2pLqjrvSei1nTeuQfO4PUfjeW5cTUNRLZ4sA==", + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.9.tgz", + "integrity": "sha512-r0i3uhaZAXYP0At5xGfJH876W3HHGHDp+LCRUJrs57PBeQ6mYHMwr25KH8NPX44F2yGTvdnH7OqCshlQx183Eg==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 1426c27c0c5..62dea0111f4 100644 --- a/package.json +++ b/package.json @@ -121,7 +121,7 @@ "postcss": "8.4.47", "postcss-loader": "8.1.1", "prettier": "3.3.3", - "prettier-plugin-tailwindcss": "0.6.8", + "prettier-plugin-tailwindcss": "0.6.9", "process": "0.11.10", "remark-gfm": "4.0.0", "rimraf": "6.0.1", From cf52c6030eb6ebe88f604de3425b99201f4f9d07 Mon Sep 17 00:00:00 2001 From: Daniel James Smith <2670567+djsmith85@users.noreply.github.com> Date: Mon, 25 Nov 2024 17:51:24 +0100 Subject: [PATCH 07/13] Cleaning up after removing gulp from codebase (#12117) Co-authored-by: Daniel James Smith --- .eslintignore | 1 - .github/renovate.json | 5 ----- .github/workflows/build-web.yml | 1 - 3 files changed, 7 deletions(-) diff --git a/.eslintignore b/.eslintignore index b6c475d3326..c9a25670a90 100644 --- a/.eslintignore +++ b/.eslintignore @@ -8,7 +8,6 @@ storybook-static **/webpack.*.js **/jest.config.js -**/gulpfile.js apps/browser/config/config.js apps/browser/src/auth/scripts/duo.js diff --git a/.github/renovate.json b/.github/renovate.json index 0172403f0f1..446aa789ebf 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -75,11 +75,6 @@ "concurrently", "cross-env", "del", - "gulp", - "gulp-if", - "gulp-json-editor", - "gulp-replace", - "gulp-zip", "nord", "patch-package", "prettier", diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index 350835d0ec7..6e5e11c3361 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -120,7 +120,6 @@ jobs: whoami node --version npm --version - gulp --version docker --version echo "GitHub ref: $GITHUB_REF" echo "GitHub event: $GITHUB_EVENT" From f65a39d6d80a3fa1f166234da4c5a10c60eafb96 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Mon, 25 Nov 2024 11:57:49 -0500 Subject: [PATCH 08/13] validate proper duo hostnames (#12149) --- apps/web/src/connectors/duo-redirect.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/apps/web/src/connectors/duo-redirect.ts b/apps/web/src/connectors/duo-redirect.ts index 2b8a3de4de1..a113c6b9756 100644 --- a/apps/web/src/connectors/duo-redirect.ts +++ b/apps/web/src/connectors/duo-redirect.ts @@ -51,14 +51,12 @@ window.addEventListener("load", async () => { */ function redirectToDuoFrameless(redirectUrl: string) { const validateUrl = new URL(redirectUrl); + const validDuoUrl = + validateUrl.protocol === "https:" && + (validateUrl.hostname.endsWith(".duosecurity.com") || + validateUrl.hostname.endsWith(".duofederal.com")); - if ( - validateUrl.protocol !== "https:" || - !( - validateUrl.hostname.endsWith("duosecurity.com") || - validateUrl.hostname.endsWith("duofederal.com") - ) - ) { + if (!validDuoUrl) { throw new Error("Invalid redirect URL"); } From 1bfdfd937571d82c90e6885e56c9464a80318cae Mon Sep 17 00:00:00 2001 From: Daniel James Smith <2670567+djsmith85@users.noreply.github.com> Date: Mon, 25 Nov 2024 18:48:34 +0100 Subject: [PATCH 09/13] Move access intelligence feature under bitwarden_license (#12116) Co-authored-by: Daniel James Smith --- .../organizations/organization-routing.module.ts | 7 ------- .../organizations/organizations-routing.module.ts | 7 +++++++ .../access-intelligence-routing.module.ts | 0 .../access-intelligence/access-intelligence.module.ts | 0 .../all-applications.component.html | 0 .../access-intelligence/all-applications.component.ts | 7 +++---- .../access-intelligence/application-table.mock.ts | 0 .../critical-applications.component.html | 0 .../critical-applications.component.ts | 7 +++---- .../notified-members-table.component.html | 0 .../notified-members-table.component.ts | 0 .../password-health-members-uri.component.html | 0 .../password-health-members-uri.component.spec.ts | 6 ++---- .../password-health-members-uri.component.ts | 8 ++------ .../password-health-members.component.html | 0 .../password-health-members.component.ts | 10 +++------- .../password-health.component.html | 0 .../password-health.component.spec.ts | 6 ++---- .../access-intelligence/password-health.component.ts | 11 +++-------- .../access-intelligence/risk-insights.component.html | 0 .../access-intelligence/risk-insights.component.ts | 3 +-- 21 files changed, 26 insertions(+), 46 deletions(-) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/access-intelligence-routing.module.ts (100%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/access-intelligence.module.ts (100%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/all-applications.component.html (100%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/all-applications.component.ts (94%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/application-table.mock.ts (100%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/critical-applications.component.html (100%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/critical-applications.component.ts (90%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/notified-members-table.component.html (100%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/notified-members-table.component.ts (100%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/password-health-members-uri.component.html (100%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/password-health-members-uri.component.spec.ts (93%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/password-health-members-uri.component.ts (92%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/password-health-members.component.html (100%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/password-health-members.component.ts (92%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/password-health.component.html (100%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/password-health.component.spec.ts (93%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/password-health.component.ts (86%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/risk-insights.component.html (100%) rename {apps/web => bitwarden_license/bit-web}/src/app/tools/access-intelligence/risk-insights.component.ts (96%) diff --git a/apps/web/src/app/admin-console/organizations/organization-routing.module.ts b/apps/web/src/app/admin-console/organizations/organization-routing.module.ts index a36b267e2fe..538cc45ac63 100644 --- a/apps/web/src/app/admin-console/organizations/organization-routing.module.ts +++ b/apps/web/src/app/admin-console/organizations/organization-routing.module.ts @@ -62,13 +62,6 @@ const routes: Routes = [ (m) => m.OrganizationReportingModule, ), }, - { - path: "access-intelligence", - loadChildren: () => - import("../../tools/access-intelligence/access-intelligence.module").then( - (m) => m.AccessIntelligenceModule, - ), - }, { path: "billing", loadChildren: () => diff --git a/bitwarden_license/bit-web/src/app/admin-console/organizations/organizations-routing.module.ts b/bitwarden_license/bit-web/src/app/admin-console/organizations/organizations-routing.module.ts index 8e5860833c5..3a76b92cede 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/organizations/organizations-routing.module.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/organizations/organizations-routing.module.ts @@ -76,6 +76,13 @@ const routes: Routes = [ }, ], }, + { + path: "access-intelligence", + loadChildren: () => + import("../../tools/access-intelligence/access-intelligence.module").then( + (m) => m.AccessIntelligenceModule, + ), + }, ], }, ]; diff --git a/apps/web/src/app/tools/access-intelligence/access-intelligence-routing.module.ts b/bitwarden_license/bit-web/src/app/tools/access-intelligence/access-intelligence-routing.module.ts similarity index 100% rename from apps/web/src/app/tools/access-intelligence/access-intelligence-routing.module.ts rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/access-intelligence-routing.module.ts diff --git a/apps/web/src/app/tools/access-intelligence/access-intelligence.module.ts b/bitwarden_license/bit-web/src/app/tools/access-intelligence/access-intelligence.module.ts similarity index 100% rename from apps/web/src/app/tools/access-intelligence/access-intelligence.module.ts rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/access-intelligence.module.ts diff --git a/apps/web/src/app/tools/access-intelligence/all-applications.component.html b/bitwarden_license/bit-web/src/app/tools/access-intelligence/all-applications.component.html similarity index 100% rename from apps/web/src/app/tools/access-intelligence/all-applications.component.html rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/all-applications.component.html diff --git a/apps/web/src/app/tools/access-intelligence/all-applications.component.ts b/bitwarden_license/bit-web/src/app/tools/access-intelligence/all-applications.component.ts similarity index 94% rename from apps/web/src/app/tools/access-intelligence/all-applications.component.ts rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/all-applications.component.ts index 5d76403f46b..c755aa72598 100644 --- a/apps/web/src/app/tools/access-intelligence/all-applications.component.ts +++ b/bitwarden_license/bit-web/src/app/tools/access-intelligence/all-applications.component.ts @@ -21,10 +21,9 @@ import { ToastService, } from "@bitwarden/components"; import { CardComponent } from "@bitwarden/tools-card"; - -import { HeaderModule } from "../../layouts/header/header.module"; -import { SharedModule } from "../../shared"; -import { PipesModule } from "../../vault/individual-vault/pipes/pipes.module"; +import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.module"; +import { SharedModule } from "@bitwarden/web-vault/app/shared"; +import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module"; import { applicationTableMockData } from "./application-table.mock"; diff --git a/apps/web/src/app/tools/access-intelligence/application-table.mock.ts b/bitwarden_license/bit-web/src/app/tools/access-intelligence/application-table.mock.ts similarity index 100% rename from apps/web/src/app/tools/access-intelligence/application-table.mock.ts rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/application-table.mock.ts diff --git a/apps/web/src/app/tools/access-intelligence/critical-applications.component.html b/bitwarden_license/bit-web/src/app/tools/access-intelligence/critical-applications.component.html similarity index 100% rename from apps/web/src/app/tools/access-intelligence/critical-applications.component.html rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/critical-applications.component.html diff --git a/apps/web/src/app/tools/access-intelligence/critical-applications.component.ts b/bitwarden_license/bit-web/src/app/tools/access-intelligence/critical-applications.component.ts similarity index 90% rename from apps/web/src/app/tools/access-intelligence/critical-applications.component.ts rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/critical-applications.component.ts index 0779b2977e5..43ff3d458bc 100644 --- a/apps/web/src/app/tools/access-intelligence/critical-applications.component.ts +++ b/bitwarden_license/bit-web/src/app/tools/access-intelligence/critical-applications.component.ts @@ -7,10 +7,9 @@ import { debounceTime, map } from "rxjs"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { SearchModule, TableDataSource, NoItemsModule, Icons } from "@bitwarden/components"; import { CardComponent } from "@bitwarden/tools-card"; - -import { HeaderModule } from "../../layouts/header/header.module"; -import { SharedModule } from "../../shared"; -import { PipesModule } from "../../vault/individual-vault/pipes/pipes.module"; +import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.module"; +import { SharedModule } from "@bitwarden/web-vault/app/shared"; +import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module"; import { applicationTableMockData } from "./application-table.mock"; import { RiskInsightsTabType } from "./risk-insights.component"; diff --git a/apps/web/src/app/tools/access-intelligence/notified-members-table.component.html b/bitwarden_license/bit-web/src/app/tools/access-intelligence/notified-members-table.component.html similarity index 100% rename from apps/web/src/app/tools/access-intelligence/notified-members-table.component.html rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/notified-members-table.component.html diff --git a/apps/web/src/app/tools/access-intelligence/notified-members-table.component.ts b/bitwarden_license/bit-web/src/app/tools/access-intelligence/notified-members-table.component.ts similarity index 100% rename from apps/web/src/app/tools/access-intelligence/notified-members-table.component.ts rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/notified-members-table.component.ts diff --git a/apps/web/src/app/tools/access-intelligence/password-health-members-uri.component.html b/bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health-members-uri.component.html similarity index 100% rename from apps/web/src/app/tools/access-intelligence/password-health-members-uri.component.html rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health-members-uri.component.html diff --git a/apps/web/src/app/tools/access-intelligence/password-health-members-uri.component.spec.ts b/bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health-members-uri.component.spec.ts similarity index 93% rename from apps/web/src/app/tools/access-intelligence/password-health-members-uri.component.spec.ts rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health-members-uri.component.spec.ts index e3011604a45..1e9e4171bc3 100644 --- a/apps/web/src/app/tools/access-intelligence/password-health-members-uri.component.spec.ts +++ b/bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health-members-uri.component.spec.ts @@ -3,7 +3,6 @@ import { ActivatedRoute, convertToParamMap } from "@angular/router"; import { mock, MockProxy } from "jest-mock-extended"; import { of } from "rxjs"; -// eslint-disable-next-line no-restricted-imports import { MemberCipherDetailsApiService, PasswordHealthService, @@ -15,9 +14,8 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { TableModule } from "@bitwarden/components"; - -import { LooseComponentsModule } from "../../shared"; -import { PipesModule } from "../../vault/individual-vault/pipes/pipes.module"; +import { LooseComponentsModule } from "@bitwarden/web-vault/app/shared"; +import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module"; import { PasswordHealthMembersURIComponent } from "./password-health-members-uri.component"; diff --git a/apps/web/src/app/tools/access-intelligence/password-health-members-uri.component.ts b/bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health-members-uri.component.ts similarity index 92% rename from apps/web/src/app/tools/access-intelligence/password-health-members-uri.component.ts rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health-members-uri.component.ts index c8aea97ef77..ffc9a7911e5 100644 --- a/apps/web/src/app/tools/access-intelligence/password-health-members-uri.component.ts +++ b/bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health-members-uri.component.ts @@ -5,7 +5,6 @@ import { ActivatedRoute } from "@angular/router"; import { map } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; -// eslint-disable-next-line no-restricted-imports import { MemberCipherDetailsApiService, PasswordHealthService, @@ -24,11 +23,8 @@ import { TableDataSource, TableModule, } from "@bitwarden/components"; - -// eslint-disable-next-line no-restricted-imports -import { HeaderModule } from "../../layouts/header/header.module"; -// eslint-disable-next-line no-restricted-imports -import { PipesModule } from "../../vault/individual-vault/pipes/pipes.module"; +import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.module"; +import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module"; @Component({ standalone: true, diff --git a/apps/web/src/app/tools/access-intelligence/password-health-members.component.html b/bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health-members.component.html similarity index 100% rename from apps/web/src/app/tools/access-intelligence/password-health-members.component.html rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health-members.component.html diff --git a/apps/web/src/app/tools/access-intelligence/password-health-members.component.ts b/bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health-members.component.ts similarity index 92% rename from apps/web/src/app/tools/access-intelligence/password-health-members.component.ts rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health-members.component.ts index 66ff348e9f9..19eded0de64 100644 --- a/apps/web/src/app/tools/access-intelligence/password-health-members.component.ts +++ b/bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health-members.component.ts @@ -4,7 +4,6 @@ import { FormControl, FormsModule } from "@angular/forms"; import { ActivatedRoute } from "@angular/router"; import { debounceTime, map } from "rxjs"; -// eslint-disable-next-line no-restricted-imports import { MemberCipherDetailsApiService, PasswordHealthService, @@ -21,12 +20,9 @@ import { TableModule, ToastService, } from "@bitwarden/components"; - -import { HeaderModule } from "../../layouts/header/header.module"; -// eslint-disable-next-line no-restricted-imports -import { SharedModule } from "../../shared"; -// eslint-disable-next-line no-restricted-imports -import { PipesModule } from "../../vault/individual-vault/pipes/pipes.module"; +import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.module"; +import { SharedModule } from "@bitwarden/web-vault/app/shared"; +import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module"; @Component({ standalone: true, diff --git a/apps/web/src/app/tools/access-intelligence/password-health.component.html b/bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health.component.html similarity index 100% rename from apps/web/src/app/tools/access-intelligence/password-health.component.html rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health.component.html diff --git a/apps/web/src/app/tools/access-intelligence/password-health.component.spec.ts b/bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health.component.spec.ts similarity index 93% rename from apps/web/src/app/tools/access-intelligence/password-health.component.spec.ts rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health.component.spec.ts index 5e934e3edfc..98637d0decb 100644 --- a/apps/web/src/app/tools/access-intelligence/password-health.component.spec.ts +++ b/bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health.component.spec.ts @@ -3,7 +3,6 @@ import { ActivatedRoute, convertToParamMap } from "@angular/router"; import { mock } from "jest-mock-extended"; import { of } from "rxjs"; -// eslint-disable-next-line no-restricted-imports import { MemberCipherDetailsApiService, PasswordHealthService, @@ -15,9 +14,8 @@ import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/pass import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { TableModule } from "@bitwarden/components"; import { TableBodyDirective } from "@bitwarden/components/src/table/table.component"; - -import { LooseComponentsModule } from "../../shared"; -import { PipesModule } from "../../vault/individual-vault/pipes/pipes.module"; +import { LooseComponentsModule } from "@bitwarden/web-vault/app/shared"; +import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module"; import { PasswordHealthComponent } from "./password-health.component"; diff --git a/apps/web/src/app/tools/access-intelligence/password-health.component.ts b/bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health.component.ts similarity index 86% rename from apps/web/src/app/tools/access-intelligence/password-health.component.ts rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health.component.ts index 058cfb86dae..8ae14562f36 100644 --- a/apps/web/src/app/tools/access-intelligence/password-health.component.ts +++ b/bitwarden_license/bit-web/src/app/tools/access-intelligence/password-health.component.ts @@ -5,7 +5,6 @@ import { ActivatedRoute } from "@angular/router"; import { map } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; -// eslint-disable-next-line no-restricted-imports import { MemberCipherDetailsApiService, PasswordHealthService, @@ -22,13 +21,9 @@ import { TableDataSource, TableModule, } from "@bitwarden/components"; - -// eslint-disable-next-line no-restricted-imports -import { HeaderModule } from "../../layouts/header/header.module"; -// eslint-disable-next-line no-restricted-imports -import { OrganizationBadgeModule } from "../../vault/individual-vault/organization-badge/organization-badge.module"; -// eslint-disable-next-line no-restricted-imports -import { PipesModule } from "../../vault/individual-vault/pipes/pipes.module"; +import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.module"; +import { OrganizationBadgeModule } from "@bitwarden/web-vault/app/vault/individual-vault/organization-badge/organization-badge.module"; +import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module"; @Component({ standalone: true, diff --git a/apps/web/src/app/tools/access-intelligence/risk-insights.component.html b/bitwarden_license/bit-web/src/app/tools/access-intelligence/risk-insights.component.html similarity index 100% rename from apps/web/src/app/tools/access-intelligence/risk-insights.component.html rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/risk-insights.component.html diff --git a/apps/web/src/app/tools/access-intelligence/risk-insights.component.ts b/bitwarden_license/bit-web/src/app/tools/access-intelligence/risk-insights.component.ts similarity index 96% rename from apps/web/src/app/tools/access-intelligence/risk-insights.component.ts rename to bitwarden_license/bit-web/src/app/tools/access-intelligence/risk-insights.component.ts index 1c6a36b4454..2308de28735 100644 --- a/apps/web/src/app/tools/access-intelligence/risk-insights.component.ts +++ b/bitwarden_license/bit-web/src/app/tools/access-intelligence/risk-insights.component.ts @@ -7,8 +7,7 @@ import { JslibModule } from "@bitwarden/angular/jslib.module"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { AsyncActionsModule, ButtonModule, TabsModule } from "@bitwarden/components"; - -import { HeaderModule } from "../../layouts/header/header.module"; +import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.module"; import { AllApplicationsComponent } from "./all-applications.component"; import { CriticalApplicationsComponent } from "./critical-applications.component"; From d13bbf979f75617d6c2a00e4244eaa4eddf28226 Mon Sep 17 00:00:00 2001 From: Github Actions Date: Mon, 25 Nov 2024 18:00:19 +0000 Subject: [PATCH 10/13] Bumped client version(s) --- apps/web/package.json | 2 +- package-lock.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index 02ee6babe92..542a482780f 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/web-vault", - "version": "2024.11.1", + "version": "2024.11.2", "scripts": { "build:oss": "webpack", "build:bit": "webpack -c ../../bitwarden_license/bit-web/webpack.config.js", diff --git a/package-lock.json b/package-lock.json index 59fb666d4ae..eaff5aed5f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -243,7 +243,7 @@ }, "apps/web": { "name": "@bitwarden/web-vault", - "version": "2024.11.1" + "version": "2024.11.2" }, "libs/admin-console": { "name": "@bitwarden/admin-console", From 820b03dd49e3160d343970d6a96d4d6f4caead7e Mon Sep 17 00:00:00 2001 From: rr-bw <102181210+rr-bw@users.noreply.github.com> Date: Mon, 25 Nov 2024 11:34:53 -0800 Subject: [PATCH 11/13] fix(biometrics): [PM-13901] Bugfix for "Ask for biometrics on launch does not auto prompt biometrics" (#12144) This PR ensures that, on the Chrome browser extension, biometrics gets auto-prompted when the user selects "Ask for biometrics on launch" by resetting the `isInitialLockScreen` to `true` on active account change. Feature flag: `ExtensionRefresh` ON. --- libs/auth/src/angular/lock/lock.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/auth/src/angular/lock/lock.component.ts b/libs/auth/src/angular/lock/lock.component.ts index 94c226f3f67..d8a2853a046 100644 --- a/libs/auth/src/angular/lock/lock.component.ts +++ b/libs/auth/src/angular/lock/lock.component.ts @@ -228,6 +228,7 @@ export class LockV2Component implements OnInit, OnDestroy { this.unlockOptions = null; this.activeUnlockOption = null; this.formGroup = null; // new form group will be created based on new active unlock option + this.isInitialLockScreen = true; // Desktop properties: this.biometricAsked = false; From bb0912154dfcfc9e5d11f53c547aa87613c47ba7 Mon Sep 17 00:00:00 2001 From: Will Martin Date: Mon, 25 Nov 2024 14:43:31 -0500 Subject: [PATCH 12/13] [CL-508] extension width setting (#12040) --- apps/browser/src/_locales/en/messages.json | 9 +++ .../src/platform/popup/browser-popup-utils.ts | 3 +- .../popup/layout/popup-layout.stories.ts | 22 +++++++ .../popup/layout/popup-width.service.ts | 63 +++++++++++++++++++ apps/browser/src/popup/app.component.ts | 3 + apps/browser/src/popup/main.ts | 4 +- apps/browser/src/popup/scss/base.scss | 2 +- .../settings/appearance-v2.component.html | 5 ++ .../settings/appearance-v2.component.spec.ts | 11 ++++ .../popup/settings/appearance-v2.component.ts | 28 ++++++++- .../src/platform/state/state-definitions.ts | 4 ++ libs/components/src/select/index.ts | 1 + 12 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 apps/browser/src/platform/popup/layout/popup-width.service.ts diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index 316bb23c4f8..ab1c6377e6a 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -4888,5 +4888,14 @@ }, "beta": { "message": "Beta" + }, + "extensionWidth": { + "message": "Extension width" + }, + "wide": { + "message": "Wide" + }, + "extraWide": { + "message": "Extra wide" } } diff --git a/apps/browser/src/platform/popup/browser-popup-utils.ts b/apps/browser/src/platform/popup/browser-popup-utils.ts index fb53d3451f2..83fde24ac6f 100644 --- a/apps/browser/src/platform/popup/browser-popup-utils.ts +++ b/apps/browser/src/platform/popup/browser-popup-utils.ts @@ -1,6 +1,7 @@ import { BrowserApi } from "../browser/browser-api"; import { ScrollOptions } from "./abstractions/browser-popup-utils.abstractions"; +import { PopupWidthOptions } from "./layout/popup-width.service"; class BrowserPopupUtils { /** @@ -108,7 +109,7 @@ class BrowserPopupUtils { const defaultPopoutWindowOptions: chrome.windows.CreateData = { type: "popup", focused: true, - width: 380, + width: Math.max(PopupWidthOptions.default, document.body.clientWidth), height: 630, }; const offsetRight = 15; diff --git a/apps/browser/src/platform/popup/layout/popup-layout.stories.ts b/apps/browser/src/platform/popup/layout/popup-layout.stories.ts index e80ac249ac1..1aaea85e4a1 100644 --- a/apps/browser/src/platform/popup/layout/popup-layout.stories.ts +++ b/apps/browser/src/platform/popup/layout/popup-layout.stories.ts @@ -514,3 +514,25 @@ export const TransparentHeader: Story = { `, }), }; + +export const WidthOptions: Story = { + render: (args) => ({ + props: args, + template: /* HTML */ ` +
+
Default:
+
+ +
+
Wide:
+
+ +
+
Extra wide:
+
+ +
+
+ `, + }), +}; diff --git a/apps/browser/src/platform/popup/layout/popup-width.service.ts b/apps/browser/src/platform/popup/layout/popup-width.service.ts new file mode 100644 index 00000000000..cc41b1d9d4a --- /dev/null +++ b/apps/browser/src/platform/popup/layout/popup-width.service.ts @@ -0,0 +1,63 @@ +import { inject, Injectable } from "@angular/core"; +import { map, Observable } from "rxjs"; + +import { + GlobalStateProvider, + KeyDefinition, + POPUP_STYLE_DISK, +} from "@bitwarden/common/platform/state"; + +/** + * + * Value represents width in pixels + */ +export const PopupWidthOptions = Object.freeze({ + default: 380, + wide: 480, + "extra-wide": 600, +}); + +type PopupWidthOptions = typeof PopupWidthOptions; +export type PopupWidthOption = keyof PopupWidthOptions; + +const POPUP_WIDTH_KEY_DEF = new KeyDefinition(POPUP_STYLE_DISK, "popup-width", { + deserializer: (s) => s, +}); + +/** + * Updates the extension popup width based on a user setting + **/ +@Injectable({ providedIn: "root" }) +export class PopupWidthService { + private static readonly LocalStorageKey = "bw-popup-width"; + private readonly state = inject(GlobalStateProvider).get(POPUP_WIDTH_KEY_DEF); + + readonly width$: Observable = this.state.state$.pipe( + map((state) => state ?? "default"), + ); + + async setWidth(width: PopupWidthOption) { + await this.state.update(() => width); + } + + /** Begin listening for state changes */ + init() { + this.width$.subscribe((width: PopupWidthOption) => { + PopupWidthService.setStyle(width); + localStorage.setItem(PopupWidthService.LocalStorageKey, width); + }); + } + + private static setStyle(width: PopupWidthOption) { + const pxWidth = PopupWidthOptions[width] ?? PopupWidthOptions.default; + document.body.style.width = `${pxWidth}px`; + } + + /** + * To keep the popup size from flickering on bootstrap, we store the width in `localStorage` so we can quickly & synchronously reference it. + **/ + static initBodyWidthFromLocalStorage() { + const storedValue = localStorage.getItem(PopupWidthService.LocalStorageKey); + this.setStyle(storedValue as any); + } +} diff --git a/apps/browser/src/popup/app.component.ts b/apps/browser/src/popup/app.component.ts index c23da5ca7ce..31f610b7e74 100644 --- a/apps/browser/src/popup/app.component.ts +++ b/apps/browser/src/popup/app.component.ts @@ -25,6 +25,7 @@ import { import { flagEnabled } from "../platform/flags"; import { PopupCompactModeService } from "../platform/popup/layout/popup-compact-mode.service"; +import { PopupWidthService } from "../platform/popup/layout/popup-width.service"; import { PopupViewCacheService } from "../platform/popup/view-cache/popup-view-cache.service"; import { initPopupClosedListener } from "../platform/services/popup-view-cache-background.service"; import { BrowserSendStateService } from "../tools/popup/services/browser-send-state.service"; @@ -44,6 +45,7 @@ import { DesktopSyncVerificationDialogComponent } from "./components/desktop-syn export class AppComponent implements OnInit, OnDestroy { private viewCacheService = inject(PopupViewCacheService); private compactModeService = inject(PopupCompactModeService); + private widthService = inject(PopupWidthService); private lastActivity: Date; private activeUserId: UserId; @@ -99,6 +101,7 @@ export class AppComponent implements OnInit, OnDestroy { await this.viewCacheService.init(); this.compactModeService.init(); + this.widthService.init(); // Component states must not persist between closing and reopening the popup, otherwise they become dead objects // Clear them aggressively to make sure this doesn't occur diff --git a/apps/browser/src/popup/main.ts b/apps/browser/src/popup/main.ts index c98e30e6bca..db634ea2e2c 100644 --- a/apps/browser/src/popup/main.ts +++ b/apps/browser/src/popup/main.ts @@ -1,6 +1,7 @@ import { enableProdMode } from "@angular/core"; import { platformBrowserDynamic } from "@angular/platform-browser-dynamic"; +import { PopupWidthService } from "../platform/popup/layout/popup-width.service"; import { BrowserPlatformUtilsService } from "../platform/services/platform-utils/browser-platform-utils.service"; require("./scss/popup.scss"); @@ -8,7 +9,8 @@ require("./scss/tailwind.css"); import { AppModule } from "./app.module"; -// We put this first to minimize the delay in window changing. +// We put these first to minimize the delay in window changing. +PopupWidthService.initBodyWidthFromLocalStorage(); // Should be removed once we deprecate support for Safari 16.0 and older. See Jira ticket [PM-1861] if (BrowserPlatformUtilsService.shouldApplySafariHeightFix(window)) { document.documentElement.classList.add("safari_height_fix"); diff --git a/apps/browser/src/popup/scss/base.scss b/apps/browser/src/popup/scss/base.scss index 89b8816567d..9412b911ee2 100644 --- a/apps/browser/src/popup/scss/base.scss +++ b/apps/browser/src/popup/scss/base.scss @@ -19,7 +19,7 @@ body { } body { - width: 380px !important; + min-width: 380px !important; height: 600px !important; position: relative; min-height: 100vh; diff --git a/apps/browser/src/vault/popup/settings/appearance-v2.component.html b/apps/browser/src/vault/popup/settings/appearance-v2.component.html index 466cffa216a..0fc6297b503 100644 --- a/apps/browser/src/vault/popup/settings/appearance-v2.component.html +++ b/apps/browser/src/vault/popup/settings/appearance-v2.component.html @@ -18,6 +18,11 @@ + + {{ "extensionWidth" | i18n }} + + + { const setEnableRoutingAnimation = jest.fn().mockResolvedValue(undefined); const setEnableCompactMode = jest.fn().mockResolvedValue(undefined); + const mockWidthService: Partial = { + width$: new BehaviorSubject("default"), + setWidth: jest.fn().mockResolvedValue(undefined), + }; + beforeEach(async () => { setSelectedTheme.mockClear(); setShowFavicons.mockClear(); @@ -78,6 +84,10 @@ describe("AppearanceV2Component", () => { provide: PopupCompactModeService, useValue: { enabled$: enableCompactMode$, setEnabled: setEnableCompactMode }, }, + { + provide: PopupWidthService, + useValue: mockWidthService, + }, ], }) .overrideComponent(AppearanceV2Component, { @@ -102,6 +112,7 @@ describe("AppearanceV2Component", () => { enableBadgeCounter: true, theme: ThemeType.Nord, enableCompactMode: false, + width: "default", }); }); diff --git a/apps/browser/src/vault/popup/settings/appearance-v2.component.ts b/apps/browser/src/vault/popup/settings/appearance-v2.component.ts index c20bc48bfea..31f7f31148f 100644 --- a/apps/browser/src/vault/popup/settings/appearance-v2.component.ts +++ b/apps/browser/src/vault/popup/settings/appearance-v2.component.ts @@ -12,7 +12,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { ThemeType } from "@bitwarden/common/platform/enums"; import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service"; -import { BadgeModule, CheckboxModule } from "@bitwarden/components"; +import { BadgeModule, CheckboxModule, Option } from "@bitwarden/components"; import { CardComponent } from "../../../../../../libs/components/src/card/card.component"; import { FormFieldModule } from "../../../../../../libs/components/src/form-field/form-field.module"; @@ -21,6 +21,10 @@ import { PopOutComponent } from "../../../platform/popup/components/pop-out.comp import { PopupCompactModeService } from "../../../platform/popup/layout/popup-compact-mode.service"; import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component"; import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.component"; +import { + PopupWidthOption, + PopupWidthService, +} from "../../../platform/popup/layout/popup-width.service"; @Component({ standalone: true, @@ -41,6 +45,8 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co }) export class AppearanceV2Component implements OnInit { private compactModeService = inject(PopupCompactModeService); + private popupWidthService = inject(PopupWidthService); + private i18nService = inject(I18nService); appearanceForm = this.formBuilder.group({ enableFavicon: false, @@ -48,6 +54,7 @@ export class AppearanceV2Component implements OnInit { theme: ThemeType.System, enableAnimations: true, enableCompactMode: false, + width: "default" as PopupWidthOption, }); /** To avoid flashes of inaccurate values, only show the form after the entire form is populated. */ @@ -56,6 +63,13 @@ export class AppearanceV2Component implements OnInit { /** Available theme options */ themeOptions: { name: string; value: ThemeType }[]; + /** Available width options */ + protected readonly widthOptions: Option[] = [ + { label: this.i18nService.t("default"), value: "default" }, + { label: this.i18nService.t("wide"), value: "wide" }, + { label: this.i18nService.t("extraWide"), value: "extra-wide" }, + ]; + constructor( private messagingService: MessagingService, private domainSettingsService: DomainSettingsService, @@ -81,6 +95,7 @@ export class AppearanceV2Component implements OnInit { this.animationControlService.enableRoutingAnimation$, ); const enableCompactMode = await firstValueFrom(this.compactModeService.enabled$); + const width = await firstValueFrom(this.popupWidthService.width$); // Set initial values for the form this.appearanceForm.setValue({ @@ -89,6 +104,7 @@ export class AppearanceV2Component implements OnInit { theme, enableAnimations, enableCompactMode, + width, }); this.formLoading = false; @@ -122,6 +138,12 @@ export class AppearanceV2Component implements OnInit { .subscribe((enableCompactMode) => { void this.updateCompactMode(enableCompactMode); }); + + this.appearanceForm.controls.width.valueChanges + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((width) => { + void this.updateWidth(width); + }); } async updateFavicon(enableFavicon: boolean) { @@ -144,4 +166,8 @@ export class AppearanceV2Component implements OnInit { async updateCompactMode(enableCompactMode: boolean) { await this.compactModeService.setEnabled(enableCompactMode); } + + async updateWidth(width: PopupWidthOption) { + await this.popupWidthService.setWidth(width); + } } diff --git a/libs/common/src/platform/state/state-definitions.ts b/libs/common/src/platform/state/state-definitions.ts index 0779d80982b..a600901df4f 100644 --- a/libs/common/src/platform/state/state-definitions.ts +++ b/libs/common/src/platform/state/state-definitions.ts @@ -121,6 +121,10 @@ export const TRANSLATION_DISK = new StateDefinition("translation", "disk", { web export const ANIMATION_DISK = new StateDefinition("animation", "disk"); export const TASK_SCHEDULER_DISK = new StateDefinition("taskScheduler", "disk"); +// Design System + +export const POPUP_STYLE_DISK = new StateDefinition("popupStyle", "disk"); + // Secrets Manager export const SM_ONBOARDING_DISK = new StateDefinition("smOnboarding", "disk", { diff --git a/libs/components/src/select/index.ts b/libs/components/src/select/index.ts index faebfee9bb8..8ef9993efda 100644 --- a/libs/components/src/select/index.ts +++ b/libs/components/src/select/index.ts @@ -1,3 +1,4 @@ export * from "./select.module"; export * from "./select.component"; +export * from "./option"; export * from "./option.component"; From c52eeb1cb331e063a771247193981ef4044a425c Mon Sep 17 00:00:00 2001 From: cyprain-okeke <108260115+cyprain-okeke@users.noreply.github.com> Date: Mon, 25 Nov 2024 22:37:24 +0100 Subject: [PATCH 13/13] [PM-13348] Browser Extension impacts on Free Bitwarden Family Policy (#12073) * Add changes for enabled policy * Remove unused property * Refactor the changes * remove duplicated across multiple components * Add some test and documentations to service * Correct the comment free family sponsorship for isExemptFromPolicy --- .../services/families-policy.service.spec.ts | 83 +++++++++++++++++++ .../src/services/families-policy.service.ts | 54 ++++++++++++ ...more-from-bitwarden-page-v2.component.html | 7 +- .../more-from-bitwarden-page-v2.component.ts | 6 ++ .../more-from-bitwarden-page.component.html | 1 + .../more-from-bitwarden-page.component.ts | 6 ++ .../services/policy/policy.service.ts | 3 + 7 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 apps/browser/src/services/families-policy.service.spec.ts create mode 100644 apps/browser/src/services/families-policy.service.ts diff --git a/apps/browser/src/services/families-policy.service.spec.ts b/apps/browser/src/services/families-policy.service.spec.ts new file mode 100644 index 00000000000..19291bcd825 --- /dev/null +++ b/apps/browser/src/services/families-policy.service.spec.ts @@ -0,0 +1,83 @@ +import { TestBed } from "@angular/core/testing"; +import { mock, MockProxy } from "jest-mock-extended"; +import { firstValueFrom, of } from "rxjs"; + +import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; +import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; +import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; +import { Policy } from "@bitwarden/common/admin-console/models/domain/policy"; + +import { FamiliesPolicyService } from "./families-policy.service"; // Adjust the import as necessary + +describe("FamiliesPolicyService", () => { + let service: FamiliesPolicyService; + let organizationService: MockProxy; + let policyService: MockProxy; + + beforeEach(() => { + organizationService = mock(); + policyService = mock(); + + TestBed.configureTestingModule({ + providers: [ + FamiliesPolicyService, + { provide: OrganizationService, useValue: organizationService }, + { provide: PolicyService, useValue: policyService }, + ], + }); + + service = TestBed.inject(FamiliesPolicyService); + }); + + it("should return false when there are no enterprise organizations", async () => { + jest.spyOn(service, "hasSingleEnterpriseOrg$").mockReturnValue(of(false)); + + const result = await firstValueFrom(service.isFreeFamilyPolicyEnabled$()); + expect(result).toBe(false); + }); + + it("should return true when the policy is enabled for the one enterprise organization", async () => { + jest.spyOn(service, "hasSingleEnterpriseOrg$").mockReturnValue(of(true)); + + const organizations = [{ id: "org1", canManageSponsorships: true }] as Organization[]; + organizationService.getAll$.mockReturnValue(of(organizations)); + + const policies = [{ organizationId: "org1", enabled: true }] as Policy[]; + policyService.getAll$.mockReturnValue(of(policies)); + + const result = await firstValueFrom(service.isFreeFamilyPolicyEnabled$()); + expect(result).toBe(true); + }); + + it("should return false when the policy is not enabled for the one enterprise organization", async () => { + jest.spyOn(service, "hasSingleEnterpriseOrg$").mockReturnValue(of(true)); + + const organizations = [{ id: "org1", canManageSponsorships: true }] as Organization[]; + organizationService.getAll$.mockReturnValue(of(organizations)); + + const policies = [{ organizationId: "org1", enabled: false }] as Policy[]; + policyService.getAll$.mockReturnValue(of(policies)); + + const result = await firstValueFrom(service.isFreeFamilyPolicyEnabled$()); + expect(result).toBe(false); + }); + + it("should return true when there is exactly one enterprise organization that can manage sponsorships", async () => { + const organizations = [{ id: "org1", canManageSponsorships: true }] as Organization[]; + organizationService.getAll$.mockReturnValue(of(organizations)); + + const result = await firstValueFrom(service.hasSingleEnterpriseOrg$()); + expect(result).toBe(true); + }); + + it("should return false when there are multiple organizations that can manage sponsorships", async () => { + const organizations = [ + { id: "org1", canManageSponsorships: true }, + { id: "org2", canManageSponsorships: true }, + ] as Organization[]; + organizationService.getAll$.mockReturnValue(of(organizations)); + + const result = await firstValueFrom(service.hasSingleEnterpriseOrg$()); + expect(result).toBe(false); + }); +}); diff --git a/apps/browser/src/services/families-policy.service.ts b/apps/browser/src/services/families-policy.service.ts new file mode 100644 index 00000000000..426f39dcfd0 --- /dev/null +++ b/apps/browser/src/services/families-policy.service.ts @@ -0,0 +1,54 @@ +import { Injectable } from "@angular/core"; +import { map, Observable, of, switchMap } from "rxjs"; + +import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; +import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; +import { PolicyType } from "@bitwarden/common/admin-console/enums"; + +@Injectable({ providedIn: "root" }) +export class FamiliesPolicyService { + constructor( + private policyService: PolicyService, + private organizationService: OrganizationService, + ) {} + + hasSingleEnterpriseOrg$(): Observable { + // Retrieve all organizations the user is part of + return this.organizationService.getAll$().pipe( + map((organizations) => { + // Filter to only those organizations that can manage sponsorships + const sponsorshipOrgs = organizations.filter((org) => org.canManageSponsorships); + + // Check if there is exactly one organization that can manage sponsorships. + // This is important because users that are part of multiple organizations + // may always access free bitwarden family menu. We want to restrict access + // to the policy only when there is a single enterprise organization and the free family policy is turn. + return sponsorshipOrgs.length === 1; + }), + ); + } + + isFreeFamilyPolicyEnabled$(): Observable { + return this.hasSingleEnterpriseOrg$().pipe( + switchMap((hasSingleEnterpriseOrg) => { + if (!hasSingleEnterpriseOrg) { + return of(false); + } + return this.organizationService.getAll$().pipe( + map((organizations) => organizations.find((org) => org.canManageSponsorships)?.id), + switchMap((enterpriseOrgId) => + this.policyService + .getAll$(PolicyType.FreeFamiliesSponsorshipPolicy) + .pipe( + map( + (policies) => + policies.find((policy) => policy.organizationId === enterpriseOrgId)?.enabled ?? + false, + ), + ), + ), + ); + }), + ); + } +} diff --git a/apps/browser/src/tools/popup/settings/about-page/more-from-bitwarden-page-v2.component.html b/apps/browser/src/tools/popup/settings/about-page/more-from-bitwarden-page-v2.component.html index 9322ab5113e..a2d01ce752e 100644 --- a/apps/browser/src/tools/popup/settings/about-page/more-from-bitwarden-page-v2.component.html +++ b/apps/browser/src/tools/popup/settings/about-page/more-from-bitwarden-page-v2.component.html @@ -12,7 +12,12 @@ - +