diff --git a/README.md b/README.md
index d76e58db..189d3ab0 100644
--- a/README.md
+++ b/README.md
@@ -22,22 +22,11 @@ The Bitwarden desktop app is written using Electron and Angular. The application
- [Node.js](https://nodejs.org) v16.13.1 (LTS) or greater
- NPM v8
-- Rust (https://www.rust-lang.org/tools/install)
- Windows:
- To compile the native node modules used in the app you will need the _Visual C++ toolset_, available through the standard Visual Studio installer. You will also need to install the _Microsoft Build Tools 2015_ and _Windows 10 SDK 17134_ as additional dependencies in the Visual Studio installer.
- Linux:
- The following packages `build-essential libsecret-1-dev libglib2.0-dev`
-## Build native module
-
-The desktop application relies on native code written in rust, which needs to be compiled first.
-
-```bash
-cd desktop_native
-npm ci
-npm run build
-```
-
## Run the app
```bash
diff --git a/jslib b/jslib
index 6bcadc4f..c757cc7a 160000
--- a/jslib
+++ b/jslib
@@ -1 +1 @@
-Subproject commit 6bcadc4f408db2c150753f53a07d6f8888b6e9ff
+Subproject commit c757cc7ab68d3e1f63b7a00ad50a7076a3248d87
diff --git a/package-lock.json b/package-lock.json
index fe7887aa..44b5babf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,12 +19,12 @@
"@angular/platform-browser": "^12.2.13",
"@angular/platform-browser-dynamic": "^12.2.13",
"@angular/router": "^12.2.13",
- "@bitwarden/desktop-native": "file:desktop_native",
"@bitwarden/jslib-angular": "file:jslib/angular",
"@bitwarden/jslib-common": "file:jslib/common",
"@bitwarden/jslib-electron": "file:jslib/electron",
"@nodert-win10-rs4/windows.security.credentials.ui": "^0.4.4",
"forcefocus": "^1.1.0",
+ "keytar": "^7.9.0",
"ngx-toastr": "14.1.4",
"node-ipc": "^9.1.4",
"nord": "^0.2.1",
@@ -79,11 +79,10 @@
"desktop_native": {
"name": "@bitwarden/desktop_native",
"version": "0.1.0",
- "hasInstallScript": true,
+ "extraneous": true,
"license": "GPL-3.0",
"devDependencies": {
- "@napi-rs/cli": "^2.4.4",
- "cargo-cp-artifact": "^0.1"
+ "@napi-rs/cli": "^2.6.2"
}
},
"jslib/angular": {
@@ -654,10 +653,6 @@
"node": ">=6.9.0"
}
},
- "node_modules/@bitwarden/desktop-native": {
- "resolved": "desktop_native",
- "link": true
- },
"node_modules/@bitwarden/jslib-angular": {
"resolved": "jslib/angular",
"link": true
@@ -1093,22 +1088,6 @@
"msgpack5": "^4.5.0"
}
},
- "node_modules/@napi-rs/cli": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.6.2.tgz",
- "integrity": "sha512-EmH+DQDEBUIoqMim0cc+X96ImtcIZLFjgW5WWORpzYnA9Ug7zNPO7jCLMhIQRd/p5AdWaXrT4SVXc/aip09rKQ==",
- "dev": true,
- "bin": {
- "napi": "scripts/index.js"
- },
- "engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Brooooooklyn"
- }
- },
"node_modules/@ngtools/webpack": {
"version": "12.2.17",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-12.2.17.tgz",
@@ -2193,9 +2172,9 @@
}
},
"node_modules/async": {
- "version": "0.9.2",
- "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
- "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=",
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
+ "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==",
"dev": true
},
"node_modules/async-exit-hook": {
@@ -2772,15 +2751,6 @@
"integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==",
"dev": true
},
- "node_modules/cargo-cp-artifact": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.6.tgz",
- "integrity": "sha512-CQw0doK/aaF7j041666XzuilHxqMxaKkn+I5vmBsd8SAwS0cO5CqVEVp0xJwOKstyqWZ6WK4Ww3O6p26x/Goyg==",
- "dev": true,
- "bin": {
- "cargo-cp-artifact": "bin/cargo-cp-artifact.js"
- }
- },
"node_modules/chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -3600,7 +3570,6 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
- "dev": true,
"dependencies": {
"mimic-response": "^3.1.0"
},
@@ -3615,7 +3584,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
- "dev": true,
"engines": {
"node": ">=10"
},
@@ -4020,12 +3988,12 @@
}
},
"node_modules/ejs": {
- "version": "3.1.6",
- "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz",
- "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==",
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.7.tgz",
+ "integrity": "sha512-BIar7R6abbUxDA3bfXrO4DSgwo8I+fB5/1zgujl3HLLjwd6+9iOnrT+t3grn2qbk9vOgBubXOFwX2m9axoFaGw==",
"dev": true,
"dependencies": {
- "jake": "^10.6.1"
+ "jake": "^10.8.5"
},
"bin": {
"ejs": "bin/cli.js"
@@ -5303,12 +5271,33 @@
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
},
"node_modules/filelist": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz",
- "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.3.tgz",
+ "integrity": "sha512-LwjCsruLWQULGYKy7TX0OPtrL9kLpojOFKc5VCTxdFTV7w5zbsgqVKfnkKG7Qgjtq50gKfO56hJv88OfcGb70Q==",
"dev": true,
"dependencies": {
- "minimatch": "^3.0.4"
+ "minimatch": "^5.0.1"
+ }
+ },
+ "node_modules/filelist/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/filelist/node_modules/minimatch": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+ "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
}
},
"node_modules/fill-range": {
@@ -6563,12 +6552,12 @@
}
},
"node_modules/jake": {
- "version": "10.8.4",
- "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.4.tgz",
- "integrity": "sha512-MtWeTkl1qGsWUtbl/Jsca/8xSoK3x0UmS82sNbjqxxG/de/M/3b1DntdjHgPMC50enlTNwXOCRqPXLLt5cCfZA==",
+ "version": "10.8.5",
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
+ "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
"dev": true,
"dependencies": {
- "async": "0.9.x",
+ "async": "^3.2.3",
"chalk": "^4.0.2",
"filelist": "^1.0.1",
"minimatch": "^3.0.4"
@@ -6794,6 +6783,184 @@
"graceful-fs": "^4.1.6"
}
},
+ "node_modules/keytar": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz",
+ "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "node-addon-api": "^4.3.0",
+ "prebuild-install": "^7.0.1"
+ }
+ },
+ "node_modules/keytar/node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/keytar/node_modules/aproba": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+ },
+ "node_modules/keytar/node_modules/are-we-there-yet": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
+ "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
+ "dependencies": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "node_modules/keytar/node_modules/detect-libc": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
+ "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/keytar/node_modules/gauge": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+ "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+ "dependencies": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "node_modules/keytar/node_modules/is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "dependencies": {
+ "number-is-nan": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/keytar/node_modules/node-addon-api": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz",
+ "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ=="
+ },
+ "node_modules/keytar/node_modules/npmlog": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+ "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+ "dependencies": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "node_modules/keytar/node_modules/prebuild-install": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz",
+ "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==",
+ "dependencies": {
+ "detect-libc": "^2.0.0",
+ "expand-template": "^2.0.3",
+ "github-from-package": "0.0.0",
+ "minimist": "^1.2.3",
+ "mkdirp-classic": "^0.5.3",
+ "napi-build-utils": "^1.0.1",
+ "node-abi": "^3.3.0",
+ "npmlog": "^4.0.1",
+ "pump": "^3.0.0",
+ "rc": "^1.2.7",
+ "simple-get": "^4.0.0",
+ "tar-fs": "^2.0.0",
+ "tunnel-agent": "^0.6.0"
+ },
+ "bin": {
+ "prebuild-install": "bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/keytar/node_modules/readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/keytar/node_modules/simple-get": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+ "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ },
+ "node_modules/keytar/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/keytar/node_modules/string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dependencies": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/keytar/node_modules/strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/keyv": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.2.2.tgz",
@@ -7766,7 +7933,6 @@
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.8.0.tgz",
"integrity": "sha512-tzua9qWWi7iW4I42vUPKM+SfaF0vQSLAm4yO5J83mSwB7GeoWrDKC/K+8YCnYNwqP5duwazbw2X9l4m8SC2cUw==",
- "dev": true,
"dependencies": {
"semver": "^7.3.5"
},
@@ -11753,13 +11919,6 @@
"to-fast-properties": "^2.0.0"
}
},
- "@bitwarden/desktop-native": {
- "version": "file:desktop_native",
- "requires": {
- "@napi-rs/cli": "^2.4.4",
- "cargo-cp-artifact": "^0.1"
- }
- },
"@bitwarden/jslib-angular": {
"version": "file:jslib/angular",
"requires": {
@@ -12153,12 +12312,6 @@
"msgpack5": "^4.5.0"
}
},
- "@napi-rs/cli": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.6.2.tgz",
- "integrity": "sha512-EmH+DQDEBUIoqMim0cc+X96ImtcIZLFjgW5WWORpzYnA9Ug7zNPO7jCLMhIQRd/p5AdWaXrT4SVXc/aip09rKQ==",
- "dev": true
- },
"@ngtools/webpack": {
"version": "12.2.17",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-12.2.17.tgz",
@@ -13016,9 +13169,9 @@
"dev": true
},
"async": {
- "version": "0.9.2",
- "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
- "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=",
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
+ "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==",
"dev": true
},
"async-exit-hook": {
@@ -13436,12 +13589,6 @@
"integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==",
"dev": true
},
- "cargo-cp-artifact": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.6.tgz",
- "integrity": "sha512-CQw0doK/aaF7j041666XzuilHxqMxaKkn+I5vmBsd8SAwS0cO5CqVEVp0xJwOKstyqWZ6WK4Ww3O6p26x/Goyg==",
- "dev": true
- },
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -14040,7 +14187,6 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
- "dev": true,
"requires": {
"mimic-response": "^3.1.0"
},
@@ -14048,8 +14194,7 @@
"mimic-response": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
- "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
- "dev": true
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="
}
}
},
@@ -14364,12 +14509,12 @@
"integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w=="
},
"ejs": {
- "version": "3.1.6",
- "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz",
- "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==",
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.7.tgz",
+ "integrity": "sha512-BIar7R6abbUxDA3bfXrO4DSgwo8I+fB5/1zgujl3HLLjwd6+9iOnrT+t3grn2qbk9vOgBubXOFwX2m9axoFaGw==",
"dev": true,
"requires": {
- "jake": "^10.6.1"
+ "jake": "^10.8.5"
}
},
"electron": {
@@ -15354,12 +15499,32 @@
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
},
"filelist": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz",
- "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.3.tgz",
+ "integrity": "sha512-LwjCsruLWQULGYKy7TX0OPtrL9kLpojOFKc5VCTxdFTV7w5zbsgqVKfnkKG7Qgjtq50gKfO56hJv88OfcGb70Q==",
"dev": true,
"requires": {
- "minimatch": "^3.0.4"
+ "minimatch": "^5.0.1"
+ },
+ "dependencies": {
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+ "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ }
}
},
"fill-range": {
@@ -16246,12 +16411,12 @@
"dev": true
},
"jake": {
- "version": "10.8.4",
- "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.4.tgz",
- "integrity": "sha512-MtWeTkl1qGsWUtbl/Jsca/8xSoK3x0UmS82sNbjqxxG/de/M/3b1DntdjHgPMC50enlTNwXOCRqPXLLt5cCfZA==",
+ "version": "10.8.5",
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
+ "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
"dev": true,
"requires": {
- "async": "0.9.x",
+ "async": "^3.2.3",
"chalk": "^4.0.2",
"filelist": "^1.0.1",
"minimatch": "^3.0.4"
@@ -16419,6 +16584,150 @@
"universalify": "^2.0.0"
}
},
+ "keytar": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz",
+ "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==",
+ "requires": {
+ "node-addon-api": "^4.3.0",
+ "prebuild-install": "^7.0.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+ },
+ "are-we-there-yet": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
+ "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "detect-libc": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
+ "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w=="
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+ "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "node-addon-api": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz",
+ "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ=="
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+ "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "prebuild-install": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz",
+ "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==",
+ "requires": {
+ "detect-libc": "^2.0.0",
+ "expand-template": "^2.0.3",
+ "github-from-package": "0.0.0",
+ "minimist": "^1.2.3",
+ "mkdirp-classic": "^0.5.3",
+ "napi-build-utils": "^1.0.1",
+ "node-abi": "^3.3.0",
+ "npmlog": "^4.0.1",
+ "pump": "^3.0.0",
+ "rc": "^1.2.7",
+ "simple-get": "^4.0.0",
+ "tar-fs": "^2.0.0",
+ "tunnel-agent": "^0.6.0"
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "simple-get": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+ "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+ "requires": {
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ }
+ }
+ },
"keyv": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.2.2.tgz",
@@ -17141,7 +17450,6 @@
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.8.0.tgz",
"integrity": "sha512-tzua9qWWi7iW4I42vUPKM+SfaF0vQSLAm4yO5J83mSwB7GeoWrDKC/K+8YCnYNwqP5duwazbw2X9l4m8SC2cUw==",
- "dev": true,
"requires": {
"semver": "^7.3.5"
}
diff --git a/package.json b/package.json
index f735bd60..98506d67 100644
--- a/package.json
+++ b/package.json
@@ -111,12 +111,12 @@
"@angular/platform-browser": "^12.2.13",
"@angular/platform-browser-dynamic": "^12.2.13",
"@angular/router": "^12.2.13",
- "@bitwarden/desktop-native": "file:desktop_native",
"@bitwarden/jslib-angular": "file:jslib/angular",
"@bitwarden/jslib-common": "file:jslib/common",
"@bitwarden/jslib-electron": "file:jslib/electron",
"@nodert-win10-rs4/windows.security.credentials.ui": "^0.4.4",
"forcefocus": "^1.1.0",
+ "keytar": "^7.9.0",
"ngx-toastr": "14.1.4",
"node-ipc": "^9.1.4",
"nord": "^0.2.1",
diff --git a/src/app/accounts/hint.component.html b/src/app/accounts/hint.component.html
index 19ce6e77..55137081 100644
--- a/src/app/accounts/hint.component.html
+++ b/src/app/accounts/hint.component.html
@@ -25,7 +25,7 @@
{{ "submit" | i18n }}
- {{ "cancel" | i18n }}
+ {{ "cancel" | i18n }}
diff --git a/src/app/accounts/lock.component.html b/src/app/accounts/lock.component.html
index e503282c..71ac7594 100644
--- a/src/app/accounts/lock.component.html
+++ b/src/app/accounts/lock.component.html
@@ -30,12 +30,11 @@
/>
diff --git a/src/app/accounts/login.component.html b/src/app/accounts/login.component.html
index d4495781..bf7830e1 100644
--- a/src/app/accounts/login.component.html
+++ b/src/app/accounts/login.component.html
@@ -1,7 +1,7 @@
@@ -83,18 +82,22 @@
>
-
+
{{ "createAccount" | i18n }}
diff --git a/src/app/accounts/register.component.html b/src/app/accounts/register.component.html
index c0c3ce14..4136f5cf 100644
--- a/src/app/accounts/register.component.html
+++ b/src/app/accounts/register.component.html
@@ -40,12 +40,11 @@
/>
@@ -91,12 +90,11 @@
/>
@@ -146,7 +144,7 @@
{{ "submit" | i18n }}
-
{{ "cancel" | i18n }}
+
{{ "cancel" | i18n }}
diff --git a/src/app/accounts/set-password.component.html b/src/app/accounts/set-password.component.html
index d7afcda8..61e99105 100644
--- a/src/app/accounts/set-password.component.html
+++ b/src/app/accounts/set-password.component.html
@@ -56,12 +56,11 @@
/>
@@ -109,12 +108,11 @@
/>
diff --git a/src/app/accounts/two-factor-options.component.html b/src/app/accounts/two-factor-options.component.html
index 8dd875e9..778d2636 100644
--- a/src/app/accounts/two-factor-options.component.html
+++ b/src/app/accounts/two-factor-options.component.html
@@ -7,8 +7,8 @@
{{ "twoStepOptions" | i18n }}
diff --git a/src/app/accounts/two-factor.component.html b/src/app/accounts/two-factor.component.html
index aab55ab2..e2abd0f8 100644
--- a/src/app/accounts/two-factor.component.html
+++ b/src/app/accounts/two-factor.component.html
@@ -124,22 +124,21 @@
>
- {{ "cancel" | i18n }}
+ {{ "cancel" | i18n }}
diff --git a/src/app/accounts/two-factor.component.ts b/src/app/accounts/two-factor.component.ts
index db482230..acf8919f 100644
--- a/src/app/accounts/two-factor.component.ts
+++ b/src/app/accounts/two-factor.component.ts
@@ -4,6 +4,7 @@ import { ActivatedRoute, Router } from "@angular/router";
import { TwoFactorComponent as BaseTwoFactorComponent } from "jslib-angular/components/two-factor.component";
import { ModalService } from "jslib-angular/services/modal.service";
import { ApiService } from "jslib-common/abstractions/api.service";
+import { AppIdService } from "jslib-common/abstractions/appId.service";
import { AuthService } from "jslib-common/abstractions/auth.service";
import { EnvironmentService } from "jslib-common/abstractions/environment.service";
import { I18nService } from "jslib-common/abstractions/i18n.service";
@@ -38,7 +39,8 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
stateService: StateService,
route: ActivatedRoute,
logService: LogService,
- twoFactorService: TwoFactorService
+ twoFactorService: TwoFactorService,
+ appIdService: AppIdService
) {
super(
authService,
@@ -51,7 +53,8 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
stateService,
route,
logService,
- twoFactorService
+ twoFactorService,
+ appIdService
);
super.onSuccessfulLogin = () => {
return syncService.fullSync(true);
diff --git a/src/app/accounts/update-temp-password.component.html b/src/app/accounts/update-temp-password.component.html
index 26ee4672..084c3217 100644
--- a/src/app/accounts/update-temp-password.component.html
+++ b/src/app/accounts/update-temp-password.component.html
@@ -36,12 +36,11 @@
/>
@@ -84,12 +83,11 @@
/>
@@ -120,7 +118,7 @@
{{ "submit" | i18n }}
- {{ "logOut" | i18n }}
+
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 8923eb45..b824b5fe 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -35,6 +35,7 @@ import { SyncService } from "jslib-common/abstractions/sync.service";
import { SystemService } from "jslib-common/abstractions/system.service";
import { TokenService } from "jslib-common/abstractions/token.service";
import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service";
+import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus";
import { CipherType } from "jslib-common/enums/cipherType";
import { MenuUpdateRequest } from "../main/menu/menu.updater";
@@ -330,7 +331,9 @@ export class AppComponent implements OnInit {
if (message.userId != null) {
await this.stateService.setActiveUser(message.userId);
}
- const locked = await this.vaultTimeoutService.isLocked(message.userId);
+ const locked =
+ (await this.authService.getAuthStatus(message.userId)) ===
+ AuthenticationStatus.Locked;
if (locked) {
this.messagingService.send("locked", { userId: message.userId });
} else {
@@ -436,7 +439,8 @@ export class AppComponent implements OnInit {
isAuthenticated: await this.stateService.getIsAuthenticated({
userId: userId,
}),
- isLocked: await this.vaultTimeoutService.isLocked(userId),
+ isLocked:
+ (await this.authService.getAuthStatus(userId)) === AuthenticationStatus.Locked,
email: stateAccounts[i].profile.email,
userId: stateAccounts[i].profile.userId,
};
@@ -591,7 +595,7 @@ export class AppComponent implements OnInit {
const keys = Object.keys(accounts);
if (keys.length > 0) {
for (const userId of keys) {
- if (!(await this.vaultTimeoutService.isLocked(userId))) {
+ if ((await this.authService.getAuthStatus(userId)) === AuthenticationStatus.Unlocked) {
return;
}
}
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 3cd8197d..29e324cf 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -91,7 +91,7 @@ import { SearchComponent } from "./layout/search/search.component";
import { AddEditComponent as SendAddEditComponent } from "./send/add-edit.component";
import { EffluxDatesComponent as SendEffluxDatesComponent } from "./send/efflux-dates.component";
import { SendComponent } from "./send/send.component";
-import { ServicesModule } from "./services.module";
+import { ServicesModule } from "./services/services.module";
import { AddEditCustomFieldsComponent } from "./vault/add-edit-custom-fields.component";
import { AddEditComponent } from "./vault/add-edit.component";
import { AttachmentsComponent } from "./vault/attachments.component";
diff --git a/src/app/components/password-reprompt.component.html b/src/app/components/password-reprompt.component.html
index f2805761..078e983b 100644
--- a/src/app/components/password-reprompt.component.html
+++ b/src/app/components/password-reprompt.component.html
@@ -19,12 +19,11 @@
/>
diff --git a/src/app/components/set-pin.component.html b/src/app/components/set-pin.component.html
index 538eb0a2..78552942 100644
--- a/src/app/components/set-pin.component.html
+++ b/src/app/components/set-pin.component.html
@@ -22,9 +22,9 @@
/>
diff --git a/src/app/layout/account-switcher.component.html b/src/app/layout/account-switcher.component.html
index a01907f1..0d52b719 100644
--- a/src/app/layout/account-switcher.component.html
+++ b/src/app/layout/account-switcher.component.html
@@ -53,7 +53,6 @@
diff --git a/src/app/layout/account-switcher.component.ts b/src/app/layout/account-switcher.component.ts
index 6fb6c140..1958bed7 100644
--- a/src/app/layout/account-switcher.component.ts
+++ b/src/app/layout/account-switcher.component.ts
@@ -2,9 +2,9 @@ import { animate, state, style, transition, trigger } from "@angular/animations"
import { ConnectedPosition } from "@angular/cdk/overlay";
import { Component, OnInit } from "@angular/core";
+import { AuthService } from "jslib-common/abstractions/auth.service";
import { MessagingService } from "jslib-common/abstractions/messaging.service";
import { StateService } from "jslib-common/abstractions/state.service";
-import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service";
import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus";
import { Utils } from "jslib-common/misc/utils";
import { Account } from "jslib-common/models/domain/account";
@@ -53,6 +53,7 @@ export class AccountSwitcherComponent implements OnInit {
accounts: { [userId: string]: SwitcherAccount } = {};
activeAccountEmail: string;
serverUrl: string;
+ authStatus = AuthenticationStatus;
overlayPostition: ConnectedPosition[] = [
{
originX: "end",
@@ -78,22 +79,16 @@ export class AccountSwitcherComponent implements OnInit {
constructor(
private stateService: StateService,
- private vaultTimeoutService: VaultTimeoutService,
+ private authService: AuthService,
private messagingService: MessagingService
) {}
async ngOnInit(): Promise {
- this.stateService.accounts.subscribe(async (accounts) => {
+ this.stateService.accounts.subscribe(async (accounts: { [userId: string]: Account }) => {
for (const userId in accounts) {
- if (userId === (await this.stateService.getUserId())) {
- accounts[userId].profile.authenticationStatus = AuthenticationStatus.Active;
- } else {
- accounts[userId].profile.authenticationStatus = (await this.vaultTimeoutService.isLocked(
- userId
- ))
- ? AuthenticationStatus.Locked
- : AuthenticationStatus.Unlocked;
- }
+ accounts[userId].profile.authenticationStatus = await this.authService.getAuthStatus(
+ userId
+ );
}
this.accounts = await this.createSwitcherAccounts(accounts);
diff --git a/src/app/send/add-edit.component.html b/src/app/send/add-edit.component.html
index 7a43aacb..a91bfb6c 100644
--- a/src/app/send/add-edit.component.html
+++ b/src/app/send/add-edit.component.html
@@ -93,21 +93,21 @@
@@ -157,12 +157,11 @@
/>
diff --git a/src/app/send/send.component.html b/src/app/send/send.component.html
index fc52a836..853debb5 100644
--- a/src/app/send/send.component.html
+++ b/src/app/send/send.component.html
@@ -5,26 +5,44 @@
{{ "filters" | i18n }}
{{ "types" | i18n }}
@@ -36,20 +54,21 @@
diff --git a/src/app/services.module.ts b/src/app/services.module.ts
deleted file mode 100644
index 74acaabc..00000000
--- a/src/app/services.module.ts
+++ /dev/null
@@ -1,211 +0,0 @@
-import { APP_INITIALIZER, NgModule } from "@angular/core";
-
-import { JslibServicesModule } from "jslib-angular/services/jslib-services.module";
-import { BroadcasterService as BroadcasterServiceAbstraction } from "jslib-common/abstractions/broadcaster.service";
-import { CryptoService as CryptoServiceAbstraction } from "jslib-common/abstractions/crypto.service";
-import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "jslib-common/abstractions/cryptoFunction.service";
-import { EnvironmentService as EnvironmentServiceAbstraction } from "jslib-common/abstractions/environment.service";
-import { EventService as EventServiceAbstraction } from "jslib-common/abstractions/event.service";
-import { I18nService as I18nServiceAbstraction } from "jslib-common/abstractions/i18n.service";
-import { LogService as LogServiceAbstraction } from "jslib-common/abstractions/log.service";
-import { MessagingService as MessagingServiceAbstraction } from "jslib-common/abstractions/messaging.service";
-import { NotificationsService as NotificationsServiceAbstraction } from "jslib-common/abstractions/notifications.service";
-import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "jslib-common/abstractions/passwordReprompt.service";
-import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "jslib-common/abstractions/platformUtils.service";
-import { StateService as StateServiceAbstraction } from "jslib-common/abstractions/state.service";
-import { StateMigrationService as StateMigrationServiceAbstraction } from "jslib-common/abstractions/stateMigration.service";
-import { StorageService as StorageServiceAbstraction } from "jslib-common/abstractions/storage.service";
-import { SyncService as SyncServiceAbstraction } from "jslib-common/abstractions/sync.service";
-import { SystemService as SystemServiceAbstraction } from "jslib-common/abstractions/system.service";
-import { TwoFactorService as TwoFactorServiceAbstraction } from "jslib-common/abstractions/twoFactor.service";
-import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "jslib-common/abstractions/vaultTimeout.service";
-import { ThemeType } from "jslib-common/enums/themeType";
-import { StateFactory } from "jslib-common/factories/stateFactory";
-import { GlobalState } from "jslib-common/models/domain/globalState";
-import { ContainerService } from "jslib-common/services/container.service";
-import { EventService } from "jslib-common/services/event.service";
-import { StateMigrationService } from "jslib-common/services/stateMigration.service";
-import { SystemService } from "jslib-common/services/system.service";
-import { VaultTimeoutService } from "jslib-common/services/vaultTimeout.service";
-import { ElectronCryptoService } from "jslib-electron/services/electronCrypto.service";
-import { ElectronLogService } from "jslib-electron/services/electronLog.service";
-import { ElectronPlatformUtilsService } from "jslib-electron/services/electronPlatformUtils.service";
-import { ElectronRendererMessagingService } from "jslib-electron/services/electronRendererMessaging.service";
-import { ElectronRendererSecureStorageService } from "jslib-electron/services/electronRendererSecureStorage.service";
-import { ElectronRendererStorageService } from "jslib-electron/services/electronRendererStorage.service";
-
-import { Account } from "../models/account";
-import { I18nService } from "../services/i18n.service";
-import { LoginGuardService } from "../services/loginGuard.service";
-import { NativeMessagingService } from "../services/nativeMessaging.service";
-import { PasswordRepromptService } from "../services/passwordReprompt.service";
-import { StateService } from "../services/state.service";
-
-import { SearchBarService } from "./layout/search/search-bar.service";
-
-export function initFactory(
- window: Window,
- environmentService: EnvironmentServiceAbstraction,
- syncService: SyncServiceAbstraction,
- vaultTimeoutService: VaultTimeoutService,
- i18nService: I18nService,
- eventService: EventService,
- twoFactorService: TwoFactorServiceAbstraction,
- notificationsService: NotificationsServiceAbstraction,
- platformUtilsService: PlatformUtilsServiceAbstraction,
- stateService: StateServiceAbstraction,
- cryptoService: CryptoServiceAbstraction,
- nativeMessagingService: NativeMessagingService
-): () => Promise
{
- return async () => {
- nativeMessagingService.init();
- await stateService.init();
- await environmentService.setUrlsFromStorage();
- syncService.fullSync(true);
- await vaultTimeoutService.init(true);
- const locale = await stateService.getLocale();
- await i18nService.init(locale);
- eventService.init(true);
- twoFactorService.init();
- setTimeout(() => notificationsService.init(), 3000);
- const htmlEl = window.document.documentElement;
- htmlEl.classList.add("os_" + platformUtilsService.getDeviceString());
- htmlEl.classList.add("locale_" + i18nService.translationLocale);
- const theme = await platformUtilsService.getEffectiveTheme();
- htmlEl.classList.add("theme_" + theme);
- platformUtilsService.onDefaultSystemThemeChange(async (sysTheme) => {
- const bwTheme = await stateService.getTheme();
- if (bwTheme == null || bwTheme === ThemeType.System) {
- htmlEl.classList.remove("theme_" + ThemeType.Light, "theme_" + ThemeType.Dark);
- htmlEl.classList.add("theme_" + sysTheme);
- }
- });
-
- let installAction = null;
- const installedVersion = await stateService.getInstalledVersion();
- const currentVersion = await platformUtilsService.getApplicationVersion();
- if (installedVersion == null) {
- installAction = "install";
- } else if (installedVersion !== currentVersion) {
- installAction = "update";
- }
-
- if (installAction != null) {
- await stateService.setInstalledVersion(currentVersion);
- }
-
- const containerService = new ContainerService(cryptoService);
- containerService.attachToGlobal(window);
- };
-}
-
-@NgModule({
- imports: [JslibServicesModule],
- declarations: [],
- providers: [
- {
- provide: APP_INITIALIZER,
- useFactory: initFactory,
- deps: [
- "WINDOW",
- EnvironmentServiceAbstraction,
- SyncServiceAbstraction,
- VaultTimeoutServiceAbstraction,
- I18nServiceAbstraction,
- EventServiceAbstraction,
- TwoFactorServiceAbstraction,
- NotificationsServiceAbstraction,
- PlatformUtilsServiceAbstraction,
- StateServiceAbstraction,
- CryptoServiceAbstraction,
- NativeMessagingService,
- ],
- multi: true,
- },
- { provide: LogServiceAbstraction, useClass: ElectronLogService, deps: [] },
- {
- provide: PlatformUtilsServiceAbstraction,
- useFactory: (
- i18nService: I18nServiceAbstraction,
- messagingService: MessagingServiceAbstraction,
- stateService: StateServiceAbstraction
- ) => new ElectronPlatformUtilsService(i18nService, messagingService, true, stateService),
- deps: [I18nServiceAbstraction, MessagingServiceAbstraction, StateServiceAbstraction],
- },
- {
- provide: I18nServiceAbstraction,
- useFactory: (window: Window) => new I18nService(window.navigator.language, "./locales"),
- deps: ["WINDOW"],
- },
- {
- provide: MessagingServiceAbstraction,
- useClass: ElectronRendererMessagingService,
- deps: [BroadcasterServiceAbstraction],
- },
- { provide: StorageServiceAbstraction, useClass: ElectronRendererStorageService },
- { provide: "SECURE_STORAGE", useClass: ElectronRendererSecureStorageService },
- {
- provide: CryptoServiceAbstraction,
- useClass: ElectronCryptoService,
- deps: [
- CryptoFunctionServiceAbstraction,
- PlatformUtilsServiceAbstraction,
- LogServiceAbstraction,
- StateServiceAbstraction,
- ],
- },
- {
- provide: SystemServiceAbstraction,
- useFactory: (
- messagingService: MessagingServiceAbstraction,
- platformUtilsService: PlatformUtilsServiceAbstraction,
- stateService: StateServiceAbstraction
- ) => new SystemService(messagingService, platformUtilsService, null, stateService),
- deps: [MessagingServiceAbstraction, PlatformUtilsServiceAbstraction, StateServiceAbstraction],
- },
- { provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService },
- NativeMessagingService,
- SearchBarService,
- {
- provide: LoginGuardService,
- useClass: LoginGuardService,
- deps: [StateServiceAbstraction, PlatformUtilsServiceAbstraction, I18nServiceAbstraction],
- },
- {
- provide: StateServiceAbstraction,
- useFactory: (
- storageService: StorageServiceAbstraction,
- secureStorageService: StorageServiceAbstraction,
- logService: LogServiceAbstraction,
- stateMigrationService: StateMigrationServiceAbstraction
- ) =>
- new StateService(
- storageService,
- secureStorageService,
- logService,
- stateMigrationService,
- new StateFactory(GlobalState, Account)
- ),
- deps: [
- StorageServiceAbstraction,
- "SECURE_STORAGE",
- LogServiceAbstraction,
- StateMigrationServiceAbstraction,
- ],
- },
- {
- provide: StateMigrationServiceAbstraction,
- useFactory: (
- storageService: StorageServiceAbstraction,
- secureStorageService: StorageServiceAbstraction
- ) =>
- new StateMigrationService(
- storageService,
- secureStorageService,
- new StateFactory(GlobalState, Account)
- ),
- deps: [StorageServiceAbstraction, "SECURE_STORAGE"],
- },
- ],
-})
-export class ServicesModule {}
diff --git a/src/app/services/init.service.ts b/src/app/services/init.service.ts
new file mode 100644
index 00000000..3bc3d49a
--- /dev/null
+++ b/src/app/services/init.service.ts
@@ -0,0 +1,81 @@
+import { Inject, Injectable } from "@angular/core";
+
+import { WINDOW } from "jslib-angular/services/jslib-services.module";
+import { CryptoService as CryptoServiceAbstraction } from "jslib-common/abstractions/crypto.service";
+import { EnvironmentService as EnvironmentServiceAbstraction } from "jslib-common/abstractions/environment.service";
+import { EventService as EventServiceAbstraction } from "jslib-common/abstractions/event.service";
+import { I18nService as I18nServiceAbstraction } from "jslib-common/abstractions/i18n.service";
+import { NotificationsService as NotificationsServiceAbstraction } from "jslib-common/abstractions/notifications.service";
+import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "jslib-common/abstractions/platformUtils.service";
+import { StateService as StateServiceAbstraction } from "jslib-common/abstractions/state.service";
+import { SyncService as SyncServiceAbstraction } from "jslib-common/abstractions/sync.service";
+import { TwoFactorService as TwoFactorServiceAbstraction } from "jslib-common/abstractions/twoFactor.service";
+import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "jslib-common/abstractions/vaultTimeout.service";
+import { ThemeType } from "jslib-common/enums/themeType";
+import { ContainerService } from "jslib-common/services/container.service";
+import { EventService } from "jslib-common/services/event.service";
+import { VaultTimeoutService } from "jslib-common/services/vaultTimeout.service";
+
+import { I18nService } from "../../services/i18n.service";
+import { NativeMessagingService } from "../../services/nativeMessaging.service";
+
+@Injectable()
+export class InitService {
+ constructor(
+ @Inject(WINDOW) private win: Window,
+ private environmentService: EnvironmentServiceAbstraction,
+ private syncService: SyncServiceAbstraction,
+ private vaultTimeoutService: VaultTimeoutServiceAbstraction,
+ private i18nService: I18nServiceAbstraction,
+ private eventService: EventServiceAbstraction,
+ private twoFactorService: TwoFactorServiceAbstraction,
+ private notificationsService: NotificationsServiceAbstraction,
+ private platformUtilsService: PlatformUtilsServiceAbstraction,
+ private stateService: StateServiceAbstraction,
+ private cryptoService: CryptoServiceAbstraction,
+ private nativeMessagingService: NativeMessagingService
+ ) {}
+
+ init() {
+ return async () => {
+ this.nativeMessagingService.init();
+ await this.stateService.init();
+ await this.environmentService.setUrlsFromStorage();
+ this.syncService.fullSync(true);
+ (this.vaultTimeoutService as VaultTimeoutService).init(true);
+ const locale = await this.stateService.getLocale();
+ await (this.i18nService as I18nService).init(locale);
+ (this.eventService as EventService).init(true);
+ this.twoFactorService.init();
+ setTimeout(() => this.notificationsService.init(), 3000);
+ const htmlEl = this.win.document.documentElement;
+ htmlEl.classList.add("os_" + this.platformUtilsService.getDeviceString());
+
+ const theme = await this.platformUtilsService.getEffectiveTheme();
+ htmlEl.classList.add("theme_" + theme);
+ this.platformUtilsService.onDefaultSystemThemeChange(async (sysTheme) => {
+ const bwTheme = await this.stateService.getTheme();
+ if (bwTheme == null || bwTheme === ThemeType.System) {
+ htmlEl.classList.remove("theme_" + ThemeType.Light, "theme_" + ThemeType.Dark);
+ htmlEl.classList.add("theme_" + sysTheme);
+ }
+ });
+
+ let installAction = null;
+ const installedVersion = await this.stateService.getInstalledVersion();
+ const currentVersion = await this.platformUtilsService.getApplicationVersion();
+ if (installedVersion == null) {
+ installAction = "install";
+ } else if (installedVersion !== currentVersion) {
+ installAction = "update";
+ }
+
+ if (installAction != null) {
+ await this.stateService.setInstalledVersion(currentVersion);
+ }
+
+ const containerService = new ContainerService(this.cryptoService);
+ containerService.attachToGlobal(this.win);
+ };
+ }
+}
diff --git a/src/app/services/services.module.ts b/src/app/services/services.module.ts
new file mode 100644
index 00000000..694cc6de
--- /dev/null
+++ b/src/app/services/services.module.ts
@@ -0,0 +1,135 @@
+import { APP_INITIALIZER, InjectionToken, NgModule } from "@angular/core";
+
+import {
+ JslibServicesModule,
+ SECURE_STORAGE,
+ STATE_FACTORY,
+ STATE_SERVICE_USE_CACHE,
+ WINDOW,
+ CLIENT_TYPE,
+ LOCALES_DIRECTORY,
+ SYSTEM_LANGUAGE,
+} from "jslib-angular/services/jslib-services.module";
+import { BroadcasterService as BroadcasterServiceAbstraction } from "jslib-common/abstractions/broadcaster.service";
+import { CryptoService as CryptoServiceAbstraction } from "jslib-common/abstractions/crypto.service";
+import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "jslib-common/abstractions/cryptoFunction.service";
+import { I18nService as I18nServiceAbstraction } from "jslib-common/abstractions/i18n.service";
+import {
+ LogService,
+ LogService as LogServiceAbstraction,
+} from "jslib-common/abstractions/log.service";
+import { MessagingService as MessagingServiceAbstraction } from "jslib-common/abstractions/messaging.service";
+import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "jslib-common/abstractions/passwordReprompt.service";
+import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "jslib-common/abstractions/platformUtils.service";
+import { StateService as StateServiceAbstraction } from "jslib-common/abstractions/state.service";
+import { StateMigrationService as StateMigrationServiceAbstraction } from "jslib-common/abstractions/stateMigration.service";
+import { StorageService as StorageServiceAbstraction } from "jslib-common/abstractions/storage.service";
+import { SystemService as SystemServiceAbstraction } from "jslib-common/abstractions/system.service";
+import { ClientType } from "jslib-common/enums/clientType";
+import { StateFactory } from "jslib-common/factories/stateFactory";
+import { GlobalState } from "jslib-common/models/domain/globalState";
+import { SystemService } from "jslib-common/services/system.service";
+import { ElectronCryptoService } from "jslib-electron/services/electronCrypto.service";
+import { ElectronLogService } from "jslib-electron/services/electronLog.service";
+import { ElectronPlatformUtilsService } from "jslib-electron/services/electronPlatformUtils.service";
+import { ElectronRendererMessagingService } from "jslib-electron/services/electronRendererMessaging.service";
+import { ElectronRendererSecureStorageService } from "jslib-electron/services/electronRendererSecureStorage.service";
+import { ElectronRendererStorageService } from "jslib-electron/services/electronRendererStorage.service";
+
+import { Account } from "../../models/account";
+import { I18nService } from "../../services/i18n.service";
+import { LoginGuardService } from "../../services/loginGuard.service";
+import { NativeMessagingService } from "../../services/nativeMessaging.service";
+import { PasswordRepromptService } from "../../services/passwordReprompt.service";
+import { StateService } from "../../services/state.service";
+import { SearchBarService } from "../layout/search/search-bar.service";
+
+import { InitService } from "./init.service";
+
+const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
+
+@NgModule({
+ imports: [JslibServicesModule],
+ declarations: [],
+ providers: [
+ InitService,
+ NativeMessagingService,
+ SearchBarService,
+ LoginGuardService,
+ {
+ provide: APP_INITIALIZER,
+ useFactory: (initService: InitService) => initService.init(),
+ deps: [InitService],
+ multi: true,
+ },
+ {
+ provide: STATE_FACTORY,
+ useValue: new StateFactory(GlobalState, Account),
+ },
+ {
+ provide: CLIENT_TYPE,
+ useValue: ClientType.Desktop,
+ },
+ {
+ provide: RELOAD_CALLBACK,
+ useValue: null,
+ },
+ { provide: LogServiceAbstraction, useClass: ElectronLogService, deps: [] },
+ {
+ provide: PlatformUtilsServiceAbstraction,
+ useClass: ElectronPlatformUtilsService,
+ deps: [
+ I18nServiceAbstraction,
+ MessagingServiceAbstraction,
+ CLIENT_TYPE,
+ StateServiceAbstraction,
+ ],
+ },
+ {
+ provide: I18nServiceAbstraction,
+ useClass: I18nService,
+ deps: [SYSTEM_LANGUAGE, LOCALES_DIRECTORY],
+ },
+ {
+ provide: MessagingServiceAbstraction,
+ useClass: ElectronRendererMessagingService,
+ deps: [BroadcasterServiceAbstraction],
+ },
+ { provide: StorageServiceAbstraction, useClass: ElectronRendererStorageService },
+ { provide: SECURE_STORAGE, useClass: ElectronRendererSecureStorageService },
+ {
+ provide: CryptoServiceAbstraction,
+ useClass: ElectronCryptoService,
+ deps: [
+ CryptoFunctionServiceAbstraction,
+ PlatformUtilsServiceAbstraction,
+ LogServiceAbstraction,
+ StateServiceAbstraction,
+ ],
+ },
+ {
+ provide: SystemServiceAbstraction,
+ useClass: SystemService,
+ deps: [
+ MessagingServiceAbstraction,
+ PlatformUtilsServiceAbstraction,
+ RELOAD_CALLBACK,
+ StateServiceAbstraction,
+ ],
+ },
+ { provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService },
+ {
+ provide: StateServiceAbstraction,
+ useClass: StateService,
+ deps: [
+ StorageServiceAbstraction,
+ SECURE_STORAGE,
+ LogService,
+ StateMigrationServiceAbstraction,
+ STATE_FACTORY,
+ STATE_SERVICE_USE_CACHE,
+ ],
+ },
+ ],
+})
+export class ServicesModule {}
diff --git a/src/app/vault/add-edit-custom-fields.component.html b/src/app/vault/add-edit-custom-fields.component.html
index 9f5fc24a..0e5a8f6e 100644
--- a/src/app/vault/add-edit-custom-fields.component.html
+++ b/src/app/vault/add-edit-custom-fields.component.html
@@ -10,15 +10,14 @@
*ngFor="let f of cipher.fields; let i = index; trackBy: trackByFunction"
[ngClass]="{ 'box-content-row-checkbox': f.type === fieldType.Boolean }"
>
-
-
+
@@ -78,12 +77,11 @@
class="action-buttons"
*ngIf="f.type === fieldType.Hidden && (cipher.viewPassword || f.newField)"
>
-
-
+
@@ -102,10 +100,10 @@
-
+
+
@@ -153,12 +151,11 @@
/>
@@ -208,12 +205,11 @@
/>
@@ -406,9 +402,14 @@
appBoxRow
*ngFor="let u of cipher.login.uris; let i = index; trackBy: trackByFunction"
>
-
-
-
+
-
{{ "newUri" | i18n }}
-
+
diff --git a/src/app/vault/ciphers.component.html b/src/app/vault/ciphers.component.html
index 1dbbb89c..90a70360 100644
--- a/src/app/vault/ciphers.component.html
+++ b/src/app/vault/ciphers.component.html
@@ -6,14 +6,15 @@
*ngIf="ciphers.length"
>
-
+
diff --git a/src/app/vault/generator.component.html b/src/app/vault/generator.component.html
index fad3a231..79c9bf5b 100644
--- a/src/app/vault/generator.component.html
+++ b/src/app/vault/generator.component.html
@@ -41,7 +41,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/vault/generator.component.ts b/src/app/vault/generator.component.ts
index 553f53b2..471fd971 100644
--- a/src/app/vault/generator.component.ts
+++ b/src/app/vault/generator.component.ts
@@ -3,6 +3,7 @@ import { ActivatedRoute } from "@angular/router";
import { GeneratorComponent as BaseGeneratorComponent } from "jslib-angular/components/generator.component";
import { I18nService } from "jslib-common/abstractions/i18n.service";
+import { LogService } from "jslib-common/abstractions/log.service";
import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service";
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
import { StateService } from "jslib-common/abstractions/state.service";
@@ -19,7 +20,8 @@ export class GeneratorComponent extends BaseGeneratorComponent {
stateService: StateService,
platformUtilsService: PlatformUtilsService,
i18nService: I18nService,
- route: ActivatedRoute
+ route: ActivatedRoute,
+ logService: LogService
) {
super(
passwordGenerationService,
@@ -27,6 +29,7 @@ export class GeneratorComponent extends BaseGeneratorComponent {
platformUtilsService,
stateService,
i18nService,
+ logService,
route,
window
);
diff --git a/src/app/vault/groupings.component.html b/src/app/vault/groupings.component.html
index 276c7f57..148c21d1 100644
--- a/src/app/vault/groupings.component.html
+++ b/src/app/vault/groupings.component.html
@@ -3,44 +3,86 @@
{{ "filters" | i18n }}
{{ "types" | i18n }}
{{ "loading" | i18n }}
@@ -57,7 +99,13 @@
*ngFor="let f of folders"
[ngClass]="{ active: selectedFolder && f.node.id === selectedFolderId }"
>
-
+
+
diff --git a/src/app/vault/password-history.component.html b/src/app/vault/password-history.component.html
index 8ce5b059..633cee14 100644
--- a/src/app/vault/password-history.component.html
+++ b/src/app/vault/password-history.component.html
@@ -15,16 +15,15 @@
{{ h.lastUsedDate | date: "medium" }}
diff --git a/src/app/vault/view-custom-fields.component.html b/src/app/vault/view-custom-fields.component.html
index a180885f..d1980048 100644
--- a/src/app/vault/view-custom-fields.component.html
+++ b/src/app/vault/view-custom-fields.component.html
@@ -35,24 +35,23 @@
diff --git a/src/app/vault/view.component.html b/src/app/vault/view.component.html
index 3a2b12ef..255d0e76 100644
--- a/src/app/vault/view.component.html
+++ b/src/app/vault/view.component.html
@@ -22,16 +22,15 @@
{{ cipher.login.username }}
@@ -74,31 +73,29 @@
aria-hidden="true"
>
-
-
-
+
+
@@ -153,35 +149,37 @@
{{ "number" | i18n }}
- {{ cipher.card.maskedNumber }}
- {{ cipher.card.number }}
+ {{
+ cipher.card.maskedNumber | creditCardNumber: cipher.card.brand
+ }}
+ {{
+ cipher.card.number | creditCardNumber: cipher.card.brand
+ }}
@@ -199,31 +197,29 @@
{{ cipher.card.code }}
@@ -289,27 +285,25 @@
{{ u.hostOrUri }}
@@ -334,10 +328,10 @@
{{ "attachments" | i18n }}
@@ -369,15 +363,14 @@
diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json
index af873f0c..e204d4d5 100644
--- a/src/locales/en/messages.json
+++ b/src/locales/en/messages.json
@@ -1853,6 +1853,12 @@
}
}
},
+ "locked": {
+ "message": "Locked"
+ },
+ "unlocked": {
+ "message": "Unlocked"
+ },
"generator": {
"message": "Generator"
},
@@ -1895,5 +1901,21 @@
},
"service": {
"message": "Service"
+ },
+ "forwardedEmail": {
+ "message": "Forwarded Email Alias"
+ },
+ "forwardedEmailDesc": {
+ "message": "Generate an email alias with an external forwarding service."
+ },
+ "hostname": {
+ "message": "Hostname",
+ "description": "Part of a URL."
+ },
+ "apiAccessToken": {
+ "message": "API Access Token"
+ },
+ "apiKey": {
+ "message": "API Key"
}
}
diff --git a/src/main/desktopCredentialStorageListener.ts b/src/main/desktopCredentialStorageListener.ts
index 70c9c7c9..1c6d06b0 100644
--- a/src/main/desktopCredentialStorageListener.ts
+++ b/src/main/desktopCredentialStorageListener.ts
@@ -1,5 +1,5 @@
-import { passwords } from "@bitwarden/desktop-native";
import { ipcMain } from "electron";
+import { deletePassword, getPassword, setPassword } from "keytar";
import { BiometricMain } from "./biometric/biometric.main";
@@ -25,14 +25,14 @@ export class DesktopCredentialStorageListener {
let val: string | boolean = null;
if (authenticated && message.action && message.key) {
if (message.action === "getPassword") {
- val = await this.getPassword(serviceName, message.key);
+ val = await getPassword(serviceName, message.key);
} else if (message.action === "hasPassword") {
- const result = await this.getPassword(serviceName, message.key);
+ const result = await getPassword(serviceName, message.key);
val = result != null;
} else if (message.action === "setPassword" && message.value) {
- await passwords.setPassword(serviceName, message.key, message.value);
+ await setPassword(serviceName, message.key, message.value);
} else if (message.action === "deletePassword") {
- await passwords.deletePassword(serviceName, message.key);
+ await deletePassword(serviceName, message.key);
}
}
event.returnValue = val;
@@ -42,18 +42,6 @@ export class DesktopCredentialStorageListener {
});
}
- // Gracefully handle old keytar values, and if detected updated the entry to the proper format
- private async getPassword(serviceName: string, key: string) {
- let val = await passwords.getPassword(serviceName, key);
- try {
- JSON.parse(val);
- } catch (e) {
- val = await passwords.getPasswordKeytar(serviceName, key);
- await passwords.setPassword(serviceName, key, val);
- }
- return val;
- }
-
private async authenticateBiometric(): Promise {
if (this.biometricService) {
return await this.biometricService.authenticateBiometric();
diff --git a/src/package-lock.json b/src/package-lock.json
index a34fc70f..a8c141bc 100644
--- a/src/package-lock.json
+++ b/src/package-lock.json
@@ -1,33 +1,19 @@
{
"name": "@bitwarden/desktop",
- "version": "1.32.2",
+ "version": "1.33.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@bitwarden/desktop",
- "version": "1.32.2",
+ "version": "1.33.1",
"license": "GPL-3.0",
"dependencies": {
- "@bitwarden/desktop-native": "file:../desktop_native",
"@nodert-win10-rs4/windows.security.credentials.ui": "^0.4.4",
- "forcefocus": "^1.1.0"
+ "forcefocus": "^1.1.0",
+ "keytar": "^7.9.0"
}
},
- "../desktop_native": {
- "name": "@bitwarden/desktop_native",
- "version": "0.1.0",
- "hasInstallScript": true,
- "license": "GPL-3.0",
- "devDependencies": {
- "@napi-rs/cli": "^2.4.4",
- "cargo-cp-artifact": "^0.1"
- }
- },
- "node_modules/@bitwarden/desktop-native": {
- "resolved": "../desktop_native",
- "link": true
- },
"node_modules/@nodert-win10-rs4/windows.security.credentials.ui": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/@nodert-win10-rs4/windows.security.credentials.ui/-/windows.security.credentials.ui-0.4.4.tgz",
@@ -299,6 +285,135 @@
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
+ "node_modules/keytar": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz",
+ "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "node-addon-api": "^4.3.0",
+ "prebuild-install": "^7.0.1"
+ }
+ },
+ "node_modules/keytar/node_modules/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "dependencies": {
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/keytar/node_modules/detect-libc": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
+ "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/keytar/node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/keytar/node_modules/node-abi": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.15.0.tgz",
+ "integrity": "sha512-Ic6z/j6I9RLm4ov7npo1I48UQr2BEyFCqh6p7S1dhEx9jPO0GPGq/e2Rb7x7DroQrmiVMz/Bw1vJm9sPAl2nxA==",
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/keytar/node_modules/prebuild-install": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz",
+ "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==",
+ "dependencies": {
+ "detect-libc": "^2.0.0",
+ "expand-template": "^2.0.3",
+ "github-from-package": "0.0.0",
+ "minimist": "^1.2.3",
+ "mkdirp-classic": "^0.5.3",
+ "napi-build-utils": "^1.0.1",
+ "node-abi": "^3.3.0",
+ "npmlog": "^4.0.1",
+ "pump": "^3.0.0",
+ "rc": "^1.2.7",
+ "simple-get": "^4.0.0",
+ "tar-fs": "^2.0.0",
+ "tunnel-agent": "^0.6.0"
+ },
+ "bin": {
+ "prebuild-install": "bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/keytar/node_modules/semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/keytar/node_modules/simple-get": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+ "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/mimic-response": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
@@ -338,6 +453,11 @@
"semver": "^5.4.1"
}
},
+ "node_modules/node-addon-api": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz",
+ "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ=="
+ },
"node_modules/noop-logger": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
@@ -615,16 +735,14 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
}
},
"dependencies": {
- "@bitwarden/desktop-native": {
- "version": "file:../desktop_native",
- "requires": {
- "@napi-rs/cli": "^2.4.4",
- "cargo-cp-artifact": "^0.1"
- }
- },
"@nodert-win10-rs4/windows.security.credentials.ui": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/@nodert-win10-rs4/windows.security.credentials.ui/-/windows.security.credentials.ui-0.4.4.tgz",
@@ -824,6 +942,89 @@
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
+ "keytar": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz",
+ "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==",
+ "requires": {
+ "node-addon-api": "^4.3.0",
+ "prebuild-install": "^7.0.1"
+ },
+ "dependencies": {
+ "decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "requires": {
+ "mimic-response": "^3.1.0"
+ }
+ },
+ "detect-libc": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
+ "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w=="
+ },
+ "mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="
+ },
+ "node-abi": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.15.0.tgz",
+ "integrity": "sha512-Ic6z/j6I9RLm4ov7npo1I48UQr2BEyFCqh6p7S1dhEx9jPO0GPGq/e2Rb7x7DroQrmiVMz/Bw1vJm9sPAl2nxA==",
+ "requires": {
+ "semver": "^7.3.5"
+ }
+ },
+ "prebuild-install": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz",
+ "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==",
+ "requires": {
+ "detect-libc": "^2.0.0",
+ "expand-template": "^2.0.3",
+ "github-from-package": "0.0.0",
+ "minimist": "^1.2.3",
+ "mkdirp-classic": "^0.5.3",
+ "napi-build-utils": "^1.0.1",
+ "node-abi": "^3.3.0",
+ "npmlog": "^4.0.1",
+ "pump": "^3.0.0",
+ "rc": "^1.2.7",
+ "simple-get": "^4.0.0",
+ "tar-fs": "^2.0.0",
+ "tunnel-agent": "^0.6.0"
+ }
+ },
+ "semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "simple-get": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+ "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+ "requires": {
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ }
+ }
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
"mimic-response": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
@@ -857,6 +1058,11 @@
"semver": "^5.4.1"
}
},
+ "node-addon-api": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz",
+ "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ=="
+ },
"noop-logger": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
@@ -1083,6 +1289,11 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
}
}
}
diff --git a/src/package.json b/src/package.json
index 3e7ab7e0..1dc98451 100644
--- a/src/package.json
+++ b/src/package.json
@@ -12,8 +12,8 @@
"url": "https://github.com/bitwarden/desktop"
},
"dependencies": {
- "@bitwarden/desktop-native": "file:../desktop_native",
"@nodert-win10-rs4/windows.security.credentials.ui": "^0.4.4",
- "forcefocus": "^1.1.0"
+ "forcefocus": "^1.1.0",
+ "keytar": "^7.9.0"
}
}
diff --git a/src/scss/base.scss b/src/scss/base.scss
index 4c9445da..70889595 100644
--- a/src/scss/base.scss
+++ b/src/scss/base.scss
@@ -84,6 +84,9 @@ button {
}
button {
+ border: none;
+ background: transparent;
+ color: inherit;
white-space: nowrap;
cursor: pointer;
}
diff --git a/src/scss/box.scss b/src/scss/box.scss
index ddb7bcca..a955617f 100644
--- a/src/scss/box.scss
+++ b/src/scss/box.scss
@@ -105,9 +105,11 @@
.box-content-row {
display: block;
+ width: 100%;
padding: 10px 15px;
position: relative;
z-index: 1;
+ text-align: left;
&:before {
content: "";
@@ -232,7 +234,8 @@
margin-top: 5px;
}
- > a {
+ > a,
+ > button {
padding: 8px 8px 8px 4px;
margin: 0;
@@ -366,7 +369,7 @@
&:not(.box-draggable-row) {
.action-buttons .row-btn:last-child {
- padding-right: 2px !important;
+ margin-right: -6px !important;
}
}
diff --git a/src/scss/list.scss b/src/scss/list.scss
index fb6ddac3..45288e5e 100644
--- a/src/scss/list.scss
+++ b/src/scss/list.scss
@@ -1,10 +1,8 @@
@import "variables.scss";
-.list > a {
- display: block;
+.list > button {
padding: 3px 10px;
text-decoration: none;
- position: relative;
user-select: none;
z-index: 1;
@@ -105,11 +103,14 @@
}
}
-.list > a.flex-list-item {
+.list > button.flex-list-item {
display: flex;
align-items: center;
+ width: 100%;
+ text-align: left;
.item-icon {
+ display: block;
margin-left: -5px;
margin-right: 4px;
@include themify($themes) {
@@ -118,7 +119,9 @@
}
.item-content {
+ display: block;
.item-title {
+ display: block;
.title-badges {
@include themify($themes) {
color: themed("mutedColor");
@@ -135,12 +138,12 @@
}
.flex-cipher-list-item {
- flex-direction: column;
- flex-wrap: nowrap;
- justify-content: center;
- align-items: flex-start;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
+
+ > * {
+ text-align: left;
+ }
}
}
diff --git a/src/scss/vault.scss b/src/scss/vault.scss
index 168a23e9..adef1984 100644
--- a/src/scss/vault.scss
+++ b/src/scss/vault.scss
@@ -43,7 +43,7 @@ app-root {
order: 1;
width: 22%;
min-width: 175px;
- max-width: 250px;
+ max-width: 600px;
border-right: 1px solid #000000;
@include themify($themes) {
@@ -129,7 +129,7 @@ app-root {
ul.bwi-ul {
// Level 1
li {
- > a {
+ > button {
padding-left: 12px;
}
@@ -137,14 +137,14 @@ app-root {
left: -4px;
}
- &.active > a .bwi-li {
+ &.active > button .bwi-li {
left: 11px;
}
}
// Level 2
ul li {
- > a {
+ > button {
padding-left: 23px;
}
@@ -152,14 +152,14 @@ app-root {
left: 7px;
}
- &.active > a .bwi-li {
+ &.active > button .bwi-li {
left: 22px;
}
}
// Level 3
ul ul li {
- > a {
+ > button {
padding-left: 34px;
}
@@ -167,14 +167,14 @@ app-root {
left: 18px;
}
- &.active > a .bwi-li {
+ &.active > button .bwi-li {
left: 33px;
}
}
// Level 4
ul ul ul li {
- > a {
+ > button {
padding-left: 45px;
}
@@ -182,14 +182,14 @@ app-root {
left: 29px;
}
- &.active > a .bwi-li {
+ &.active > button .bwi-li {
left: 44px;
}
}
// Level 5
ul ul ul ul li {
- > a {
+ > button {
padding-left: 56px;
}
@@ -197,14 +197,14 @@ app-root {
left: 40px;
}
- &.active > a .bwi-li {
+ &.active > button .bwi-li {
left: 55px;
}
}
// Level 6
ul ul ul ul ul li {
- > a {
+ > button {
padding-left: 67px;
}
@@ -212,14 +212,14 @@ app-root {
left: 51px;
}
- &.active > a .bwi-li {
+ &.active > button .bwi-li {
left: 66px;
}
}
// Level 7
ul ul ul ul ul ul li {
- > a {
+ > button {
padding-left: 78px;
}
@@ -227,7 +227,7 @@ app-root {
left: 62px;
}
- &.active > a .bwi-li {
+ &.active > button .bwi-li {
left: 77px;
}
}
@@ -238,10 +238,11 @@ app-root {
margin: 0;
li {
- a {
+ button {
padding: 5px 0;
display: flex;
align-items: center;
+ width: 100%;
@include themify($themes) {
color: themed("textColor");