Merge branch 'master' into artifacts/electron-builder-publisher-config
This commit is contained in:
commit
7a8b70da1d
11
README.md
11
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
|
||||
|
|
2
jslib
2
jslib
|
@ -1 +1 @@
|
|||
Subproject commit 6bcadc4f408db2c150753f53a07d6f8888b6e9ff
|
||||
Subproject commit c757cc7ab68d3e1f63b7a00ad50a7076a3248d87
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<b [hidden]="form.loading">{{ "submit" | i18n }}</b>
|
||||
<i class="bwi bwi-spinner bwi-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
<a routerLink="/login" class="btn block">{{ "cancel" | i18n }}</a>
|
||||
<a role="button" tabindex="0" routerLink="/login" class="btn block">{{ "cancel" | i18n }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -30,12 +30,11 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword()"
|
||||
|
@ -45,7 +44,7 @@
|
|||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div id="login-page">
|
||||
<div class="login-header">
|
||||
<a
|
||||
href="#"
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
(click)="settings()"
|
||||
class="environment-urls-settings-icon"
|
||||
|
@ -9,7 +9,7 @@
|
|||
>
|
||||
<i class="bwi bwi-cog bwi-lg" aria-hidden="true"></i>
|
||||
{{ "settings" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
<form
|
||||
id="login-page"
|
||||
|
@ -48,12 +48,11 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword()"
|
||||
|
@ -63,7 +62,7 @@
|
|||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -83,18 +82,22 @@
|
|||
>
|
||||
<i class="bwi bwi-spinner bwi-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
<a routerLink="/register" class="btn block">
|
||||
<a role="button" tabindex="0" routerLink="/register" class="btn block">
|
||||
<i class="bwi bwi-pencil-square" aria-hidden="true"></i> {{ "createAccount" | i18n }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="buttons-row">
|
||||
<a (click)="launchSsoBrowser('desktop', 'bitwarden://sso-callback')" class="btn block">
|
||||
<button
|
||||
type="button"
|
||||
(click)="launchSsoBrowser('desktop', 'bitwarden://sso-callback')"
|
||||
class="btn block"
|
||||
>
|
||||
<i class="bwi bwi-bank" aria-hidden="true"></i> {{ "enterpriseSingleSignOn" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sub-options">
|
||||
<a routerLink="/hint">{{ "getMasterPasswordHint" | i18n }}</a>
|
||||
<a role="button" tabindex="0" routerLink="/hint">{{ "getMasterPasswordHint" | i18n }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -40,12 +40,11 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword(false)"
|
||||
|
@ -55,7 +54,7 @@
|
|||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
|
@ -91,12 +90,11 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword(true)"
|
||||
|
@ -106,7 +104,7 @@
|
|||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
|
@ -146,7 +144,7 @@
|
|||
<b [hidden]="form.loading">{{ "submit" | i18n }}</b>
|
||||
<i class="bwi bwi-spinner bwi-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
<a routerLink="/login" class="btn block">{{ "cancel" | i18n }}</a>
|
||||
<a role="button" tabindex="0" routerLink="/login" class="btn block">{{ "cancel" | i18n }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -56,12 +56,11 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword(false)"
|
||||
|
@ -71,7 +70,7 @@
|
|||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
|
@ -109,12 +108,11 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword(true)"
|
||||
|
@ -124,7 +122,7 @@
|
|||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
{{ "twoStepOptions" | i18n }}
|
||||
</div>
|
||||
<div class="box-content">
|
||||
<a
|
||||
href="#"
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
*ngFor="let p of providers"
|
||||
class="box-content-row"
|
||||
|
@ -17,11 +17,11 @@
|
|||
<img [src]="'images/two-factor/' + p.type + '.png'" alt="" class="img-right" />
|
||||
<span class="text">{{ p.name }}</span>
|
||||
<span class="detail">{{ p.description }}</span>
|
||||
</a>
|
||||
<a href="#" appStopClick class="box-content-row" (click)="recover()">
|
||||
</button>
|
||||
<button type="button" appStopClick class="box-content-row" (click)="recover()">
|
||||
<span class="text">{{ "recoveryCodeTitle" | i18n }}</span>
|
||||
<span class="detail">{{ "recoveryCodeDesc" | i18n }}</span>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -124,22 +124,21 @@
|
|||
>
|
||||
<i class="bwi bwi-spinner bwi-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
<a routerLink="/login" class="btn block">{{ "cancel" | i18n }}</a>
|
||||
<a role="button" tabindex="0" routerLink="/login" class="btn block">{{ "cancel" | i18n }}</a>
|
||||
</div>
|
||||
<div class="sub-options">
|
||||
<a href="#" appStopClick (click)="anotherMethod()" role="button">{{
|
||||
"useAnotherTwoStepMethod" | i18n
|
||||
}}</a>
|
||||
<a
|
||||
href="#"
|
||||
<button type="button" appStopClick (click)="anotherMethod()">
|
||||
{{ "useAnotherTwoStepMethod" | i18n }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
(click)="sendEmail(true)"
|
||||
[appApiAction]="emailPromise"
|
||||
role="button"
|
||||
*ngIf="selectedProviderType === providerType.Email"
|
||||
>
|
||||
{{ "sendVerificationCodeEmailAgain" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -36,12 +36,11 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword(false)"
|
||||
|
@ -51,7 +50,7 @@
|
|||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
|
@ -84,12 +83,11 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword(true)"
|
||||
|
@ -99,7 +97,7 @@
|
|||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -120,7 +118,7 @@
|
|||
<b [hidden]="form.loading">{{ "submit" | i18n }}</b>
|
||||
<i class="bwi bwi-spinner bwi-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
<a (click)="logOut()" class="btn block">{{ "logOut" | i18n }}</a>
|
||||
<button type="button" (click)="logOut()" class="btn block">{{ "logOut" | i18n }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -19,12 +19,11 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword()"
|
||||
|
@ -34,7 +33,7 @@
|
|||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
|
@ -36,7 +36,7 @@
|
|||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPin, 'bwi-eye-slash': showPin }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
<button
|
||||
*ngFor="let a of accounts | keyvalue"
|
||||
class="account"
|
||||
[ngClass]="{ active: a.value.profile.authenticationStatus == 'active' }"
|
||||
(click)="switch(a.key)"
|
||||
appA11yTitle="{{ 'loggedInAsOn' | i18n: a.value.profile.email:a.value.serverUrl }}"
|
||||
attr.aria-label="{{ 'switchAccount' | i18n }}"
|
||||
|
@ -72,17 +71,17 @@
|
|||
<span class="server" aria-hidden="true" *ngIf="a.value.serverUrl != 'bitwarden.com'">{{
|
||||
a.value.serverUrl
|
||||
}}</span>
|
||||
<span class="status" aria-hidden="true">{{ a.value.profile.authenticationStatus }}</span>
|
||||
<span class="status" aria-hidden="true">{{
|
||||
(a.value.profile.authenticationStatus === authStatus.Unlocked ? "unlocked" : "locked")
|
||||
| i18n
|
||||
}}</span>
|
||||
</div>
|
||||
<i
|
||||
class="bwi bwi-unlock bwi-2x text-muted"
|
||||
class="bwi bwi-2x text-muted"
|
||||
[ngClass]="
|
||||
a.value.profile.authenticationStatus == authStatus.Unlocked ? 'bwi-unlock' : 'bwi-lock'
|
||||
"
|
||||
aria-hidden="true"
|
||||
*ngIf="a.value.profile.authenticationStatus == 'unlocked'"
|
||||
></i>
|
||||
<i
|
||||
class="bwi bwi-lock bwi-2x text-muted"
|
||||
aria-hidden="true"
|
||||
*ngIf="a.value.profile.authenticationStatus == 'locked'"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -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<void> {
|
||||
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(
|
||||
accounts[userId].profile.authenticationStatus = await this.authService.getAuthStatus(
|
||||
userId
|
||||
))
|
||||
? AuthenticationStatus.Locked
|
||||
: AuthenticationStatus.Unlocked;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
this.accounts = await this.createSwitcherAccounts(accounts);
|
||||
|
|
|
@ -93,21 +93,21 @@
|
|||
</div>
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
{{ "options" | i18n }}
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="toggle"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
(click)="toggleOptions()"
|
||||
[attr.aria-expanded]="showOptions"
|
||||
>
|
||||
{{ "options" | i18n }}
|
||||
<i
|
||||
class="bwi bwi-lg"
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-angle-down': !showOptions, 'bwi-chevron-up': showOptions }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div [hidden]="!showOptions">
|
||||
|
@ -157,12 +157,11 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePasswordVisible()"
|
||||
|
@ -173,7 +172,7 @@
|
|||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,26 +5,44 @@
|
|||
<h2 class="sr-only">{{ "filters" | i18n }}</h2>
|
||||
<ul>
|
||||
<li [ngClass]="{ active: selectedAll }">
|
||||
<a href="#" appStopClick appBlurClick (click)="selectAll()">
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
(click)="selectAll()"
|
||||
[attr.aria-pressed]="selectedAll"
|
||||
>
|
||||
<i class="bwi bwi-fw bwi-filter" aria-hidden="true"></i> {{ "allSends" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<h2>{{ "types" | i18n }}</h2>
|
||||
<ul>
|
||||
<li [ngClass]="{ active: selectedType === sendType.Text }">
|
||||
<a href="#" appStopClick appBlurClick (click)="selectType(sendType.Text)">
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
(click)="selectType(sendType.Text)"
|
||||
[attr.aria-pressed]="selectedType === sendType.Text"
|
||||
>
|
||||
<i class="bwi bwi-fw bwi-file-text" aria-hidden="true"></i> {{
|
||||
"sendTypeText" | i18n
|
||||
}}
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
<li [ngClass]="{ active: selectedType === sendType.File }">
|
||||
<a href="#" appStopClick appBlurClick (click)="selectType(sendType.File)">
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
(click)="selectType(sendType.File)"
|
||||
[attr.aria-pressed]="selectedType === sendType.File"
|
||||
>
|
||||
<i class="bwi bwi-fw bwi-file" aria-hidden="true"></i> {{
|
||||
"sendTypeFile" | i18n
|
||||
}}
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -36,20 +54,21 @@
|
|||
<div id="items" class="items">
|
||||
<div class="content">
|
||||
<div class="list" *ngIf="filteredSends.length">
|
||||
<a
|
||||
<button
|
||||
*ngFor="let s of filteredSends"
|
||||
appStopClick
|
||||
(click)="selectSend(s.id)"
|
||||
title="{{ 'viewItem' | i18n }}"
|
||||
(contextmenu)="viewSendMenu(s)"
|
||||
[ngClass]="{ active: s.id === sendId }"
|
||||
[attr.aria-pressed]="s.id === sendId"
|
||||
class="flex-list-item"
|
||||
>
|
||||
<div class="item-icon" aria-hidden="true">
|
||||
<span class="item-icon" aria-hidden="true">
|
||||
<i class="bwi bwi-fw bwi-lg" [ngClass]="s.type == 0 ? 'bwi-file-text' : 'bwi-file'"></i>
|
||||
</div>
|
||||
<div class="item-content">
|
||||
<div class="item-title">
|
||||
</span>
|
||||
<span class="item-content">
|
||||
<span class="item-title">
|
||||
{{ s.name }}
|
||||
<span class="title-badges">
|
||||
<ng-container *ngIf="s.disabled">
|
||||
|
@ -98,10 +117,10 @@
|
|||
<span class="sr-only">{{ "pendingDeletion" | i18n }}</span>
|
||||
</ng-container>
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
<span class="item-details">{{ s.deletionDate | date }}</span>
|
||||
</div>
|
||||
</a>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="no-items" *ngIf="!filteredSends.length">
|
||||
<i class="bwi bwi-spinner bwi-spin bwi-3x" *ngIf="!loaded" aria-hidden="true"></i>
|
||||
|
|
|
@ -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<void> {
|
||||
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 {}
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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 {}
|
|
@ -10,15 +10,14 @@
|
|||
*ngFor="let f of cipher.fields; let i = index; trackBy: trackByFunction"
|
||||
[ngClass]="{ 'box-content-row-checkbox': f.type === fieldType.Boolean }"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
(click)="removeField(f)"
|
||||
appA11yTitle="{{ 'remove' | i18n }}"
|
||||
role="button"
|
||||
>
|
||||
<i class="bwi bwi-minus-circle bwi-lg" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
<label for="fieldName{{ i }}" class="sr-only">{{ "name" | i18n }}</label>
|
||||
<label for="fieldValue{{ i }}" class="sr-only">{{ "value" | i18n }}</label>
|
||||
<div class="row-main">
|
||||
|
@ -78,12 +77,11 @@
|
|||
class="action-buttons"
|
||||
*ngIf="f.type === fieldType.Hidden && (cipher.viewPassword || f.newField)"
|
||||
>
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="f.showValue"
|
||||
(click)="toggleFieldValue(f)"
|
||||
|
@ -93,7 +91,7 @@
|
|||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !f.showValue, 'bwi-eye-slash': f.showValue }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
<div class="drag-handle" appA11yTitle="{{ 'dragToSort' | i18n }}" cdkDragHandle>
|
||||
<i class="bwi bwi-hamburger" aria-hidden="true"></i>
|
||||
|
@ -102,10 +100,10 @@
|
|||
</div>
|
||||
<!-- Add new custom field -->
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<a href="#" appStopClick (click)="addField()" role="button">
|
||||
<button type="button" appStopClick (click)="addField()">
|
||||
<i class="bwi bwi-plus-circle bwi-fw bwi-lg" aria-hidden="true"></i>
|
||||
{{ "newCustomField" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
<label for="addFieldType" class="sr-only">{{ "type" | i18n }}</label>
|
||||
<select id="addFieldType" name="AddFieldType" [(ngModel)]="addFieldType" class="field-type">
|
||||
<option *ngFor="let o of addFieldTypeOptions" [ngValue]="o.value">{{ o.name }}</option>
|
||||
|
|
|
@ -87,12 +87,11 @@
|
|||
aria-hidden="true"
|
||||
></i>
|
||||
</button>
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword()"
|
||||
|
@ -102,18 +101,17 @@
|
|||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
<a
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'generatePassword' | i18n }}"
|
||||
(click)="generatePassword()"
|
||||
>
|
||||
<i class="bwi bwi-lg bwi-generate" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
|
@ -153,12 +151,11 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showCardNumber"
|
||||
(click)="toggleCardNumber()"
|
||||
|
@ -168,7 +165,7 @@
|
|||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showCardNumber, 'bwi-eye-slash': showCardNumber }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
|
@ -208,12 +205,11 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showCardCode"
|
||||
(click)="toggleCardCode()"
|
||||
|
@ -223,7 +219,7 @@
|
|||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showCardCode, 'bwi-eye-slash': showCardCode }"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -406,9 +402,14 @@
|
|||
appBoxRow
|
||||
*ngFor="let u of cipher.login.uris; let i = index; trackBy: trackByFunction"
|
||||
>
|
||||
<a href="#" appStopClick (click)="removeUri(u)" appA11yTitle="{{ 'remove' | i18n }}">
|
||||
<i class="bwi bwi-minus-circle bwi-lg" aria-hidden="true" role="button"></i>
|
||||
</a>
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
(click)="removeUri(u)"
|
||||
appA11yTitle="{{ 'remove' | i18n }}"
|
||||
>
|
||||
<i class="bwi bwi-minus-circle bwi-lg" aria-hidden="true"></i>
|
||||
</button>
|
||||
<div class="row-main">
|
||||
<label for="loginUri{{ i }}">{{ "uriPosition" | i18n: i + 1 }}</label>
|
||||
<input
|
||||
|
@ -435,31 +436,29 @@
|
|||
</select>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleOptions' | i18n }}"
|
||||
(click)="toggleUriOptions(u)"
|
||||
>
|
||||
<i class="bwi bwi-lg bwi-cog" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<a
|
||||
href="#"
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
(click)="addUri()"
|
||||
class="box-content-row"
|
||||
role="button"
|
||||
>
|
||||
<i class="bwi bwi-plus-circle bwi-fw bwi-lg" aria-hidden="true"></i>
|
||||
{{ "newUri" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
|
@ -477,9 +476,13 @@
|
|||
<div class="box-content-row box-content-row-checkbox" appBoxRow *ngIf="canUseReprompt">
|
||||
<label for="passwordPrompt"
|
||||
>{{ "passwordPrompt" | i18n }}
|
||||
<a href="#" appA11yTitle="{{ 'learnMore' | i18n }}" (click)="openHelpReprompt()">
|
||||
<button
|
||||
type="button"
|
||||
appA11yTitle="{{ 'learnMore' | i18n }}"
|
||||
(click)="openHelpReprompt()"
|
||||
>
|
||||
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</label>
|
||||
<input
|
||||
id="passwordPrompt"
|
||||
|
@ -489,30 +492,28 @@
|
|||
(change)="repromptChanged()"
|
||||
/>
|
||||
</div>
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="box-content-row box-content-row-flex text-default"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
(click)="attachments()"
|
||||
*ngIf="editMode && !cloneMode"
|
||||
role="button"
|
||||
>
|
||||
<div class="row-main">{{ "attachments" | i18n }}</div>
|
||||
<i class="bwi bwi-angle-right row-sub-icon" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="box-content-row box-content-row-flex text-default"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
(click)="editCollections()"
|
||||
*ngIf="editMode && !cloneMode && cipher.organizationId"
|
||||
role="button"
|
||||
>
|
||||
<div class="row-main">{{ "collections" | i18n }}</div>
|
||||
<i class="bwi bwi-angle-right row-sub-icon" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
|
|
|
@ -6,14 +6,15 @@
|
|||
*ngIf="ciphers.length"
|
||||
>
|
||||
<div class="list">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
*cdkVirtualFor="let c of ciphers; trackBy: trackByFn"
|
||||
appStopClick
|
||||
(click)="selectCipher(c)"
|
||||
(contextmenu)="rightClickCipher(c)"
|
||||
href="#"
|
||||
title="{{ 'viewItem' | i18n }}"
|
||||
[ngClass]="{ active: c.id === activeCipherId }"
|
||||
[attr.aria-pressed]="c.id === activeCipherId"
|
||||
class="flex-list-item virtual-scroll-item"
|
||||
>
|
||||
<app-vault-icon [cipher]="c"></app-vault-icon>
|
||||
|
@ -39,7 +40,7 @@
|
|||
</span>
|
||||
<span *ngIf="c.subTitle" class="detail">{{ c.subTitle }}</span>
|
||||
</div>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
<div class="no-items" *ngIf="!ciphers.length">
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
</div>
|
||||
<div class="generated-block" *ngIf="type === 'username'">
|
||||
<div class="generated-wrapper" [innerHTML]="username | colorPassword" appSelectCopy></div>
|
||||
<div class="action-buttons">
|
||||
<div class="action-buttons" #form [appApiAction]="usernameGeneratingPromise">
|
||||
<button
|
||||
type="button"
|
||||
class="icon-btn primary"
|
||||
|
@ -57,8 +57,13 @@
|
|||
appStopClick
|
||||
appA11yTitle="{{ 'regenerateUsername' | i18n }}"
|
||||
(click)="regenerate()"
|
||||
[disabled]="form.loading"
|
||||
>
|
||||
<i class="bwi bwi-lg bwi-generate" aria-hidden="true"></i>
|
||||
<i
|
||||
class="bwi bwi-lg bwi-generate"
|
||||
[ngClass]="form.loading ? 'bwi-spin' : ''"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -371,6 +376,62 @@
|
|||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngIf="usernameOptions.forwardedService === 'simplelogin'">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="simplelogin-apikey">{{ "apiKey" | i18n }}</label>
|
||||
<input
|
||||
id="simplelogin-apikey"
|
||||
type="password"
|
||||
name="SimpleLoginApiKey"
|
||||
[(ngModel)]="usernameOptions.forwardedSimpleLoginApiKey"
|
||||
(blur)="saveUsernameOptions()"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="simplelogin-hostname">{{ "hostname" | i18n }}</label>
|
||||
<input
|
||||
id="simplelogin-hostname"
|
||||
type="text"
|
||||
name="SimpleLoginHostname"
|
||||
[(ngModel)]="usernameOptions.forwardedSimpleLoginHostname"
|
||||
(blur)="saveUsernameOptions()"
|
||||
/>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="usernameOptions.forwardedService === 'anonaddy'">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="anonaddy-accessToken">{{ "apiAccessToken" | i18n }}</label>
|
||||
<input
|
||||
id="anonaddy-accessToken"
|
||||
type="password"
|
||||
name="AnonAddyAccessToken"
|
||||
[(ngModel)]="usernameOptions.forwardedAnonAddyApiToken"
|
||||
(blur)="saveUsernameOptions()"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="anonaddy-domain">{{ "domainName" | i18n }}</label>
|
||||
<input
|
||||
id="anonaddy-domain"
|
||||
type="text"
|
||||
name="AnonAddyDomain"
|
||||
[(ngModel)]="usernameOptions.forwardedAnonAddyDomain"
|
||||
(blur)="saveUsernameOptions()"
|
||||
/>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="usernameOptions.forwardedService === 'firefoxrelay'">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="firefox-apikey">{{ "apiAccessToken" | i18n }}</label>
|
||||
<input
|
||||
id="firefox-apikey"
|
||||
type="password"
|
||||
name="FirefoxApiKey"
|
||||
[(ngModel)]="usernameOptions.forwardedFirefoxApiToken"
|
||||
(blur)="saveUsernameOptions()"
|
||||
/>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box" *ngIf="usernameOptions.type === 'subaddress'" [hidden]="!showOptions">
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -3,44 +3,86 @@
|
|||
<h2 class="sr-only">{{ "filters" | i18n }}</h2>
|
||||
<ul>
|
||||
<li [ngClass]="{ active: selectedAll }">
|
||||
<a href="#" appStopClick appBlurClick (click)="selectAll()">
|
||||
<button
|
||||
type="button"
|
||||
[attr.aria-pressed]="selectedAll"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
(click)="selectAll()"
|
||||
>
|
||||
<i class="bwi bwi-fw bwi-filter" aria-hidden="true"></i> {{ "allItems" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
<li [ngClass]="{ active: selectedFavorites }">
|
||||
<a href="#" appStopClick appBlurClick (click)="selectFavorites()">
|
||||
<button
|
||||
type="button"
|
||||
[attr.aria-pressed]="selectedFavorites"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
(click)="selectFavorites()"
|
||||
>
|
||||
<i class="bwi bwi-fw bwi-star" aria-hidden="true"></i> {{ "favorites" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
<li [ngClass]="{ active: selectedTrash }">
|
||||
<a href="#" appStopClick appBlurClick (click)="selectTrash()">
|
||||
<button
|
||||
type="button"
|
||||
[attr.aria-pressed]="selectedTrash"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
(click)="selectTrash()"
|
||||
>
|
||||
<i class="bwi bwi-fw bwi-trash" aria-hidden="true"></i> {{ "trash" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<h2>{{ "types" | i18n }}</h2>
|
||||
<ul>
|
||||
<li [ngClass]="{ active: selectedType === cipherType.Login }">
|
||||
<a href="#" appStopClick appBlurClick (click)="selectType(cipherType.Login)">
|
||||
<button
|
||||
type="button"
|
||||
[attr.aria-pressed]="selectedType === cipherType.Login"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
(click)="selectType(cipherType.Login)"
|
||||
>
|
||||
<i class="bwi bwi-fw bwi-globe" aria-hidden="true"></i> {{ "typeLogin" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
<li [ngClass]="{ active: selectedType === cipherType.Card }">
|
||||
<a href="#" appStopClick appBlurClick (click)="selectType(cipherType.Card)">
|
||||
<button
|
||||
type="button"
|
||||
[attr.aria-pressed]="selectedType === cipherType.Card"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
(click)="selectType(cipherType.Card)"
|
||||
>
|
||||
<i class="bwi bwi-fw bwi-credit-card" aria-hidden="true"></i> {{ "typeCard" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
<li [ngClass]="{ active: selectedType === cipherType.Identity }">
|
||||
<a href="#" appStopClick appBlurClick (click)="selectType(cipherType.Identity)">
|
||||
<button
|
||||
type="button"
|
||||
[attr.aria-pressed]="selectedType === cipherType.Identity"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
(click)="selectType(cipherType.Identity)"
|
||||
>
|
||||
<i class="bwi bwi-fw bwi-id-card" aria-hidden="true"></i> {{ "typeIdentity" | i18n }}
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
<li [ngClass]="{ active: selectedType === cipherType.SecureNote }">
|
||||
<a href="#" appStopClick appBlurClick (click)="selectType(cipherType.SecureNote)">
|
||||
<button
|
||||
type="button"
|
||||
[attr.aria-pressed]="selectedType === cipherType.SecureNote"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
(click)="selectType(cipherType.SecureNote)"
|
||||
>
|
||||
<i class="bwi bwi-fw bwi-sticky-note" aria-hidden="true"></i> {{
|
||||
"typeSecureNote" | i18n
|
||||
}}
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<p *ngIf="!loaded" class="text-muted">{{ "loading" | i18n }}</p>
|
||||
|
@ -57,7 +99,13 @@
|
|||
*ngFor="let f of folders"
|
||||
[ngClass]="{ active: selectedFolder && f.node.id === selectedFolderId }"
|
||||
>
|
||||
<a href="#" appStopClick appBlurClick (click)="selectFolder(f.node)">
|
||||
<button
|
||||
type="button"
|
||||
[attr.aria-pressed]="selectedFolder && f.node.id === selectedFolderId"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
(click)="selectFolder(f.node)"
|
||||
>
|
||||
<i
|
||||
*ngIf="f.children.length"
|
||||
class="bwi bwi-fw"
|
||||
|
@ -86,7 +134,7 @@
|
|||
>
|
||||
<i class="bwi bwi-pencil bwi-fw" aria-hidden="true"></i>
|
||||
</span>
|
||||
</a>
|
||||
</button>
|
||||
<ul class="bwi-ul" *ngIf="f.children.length && !isCollapsed(f.node)">
|
||||
<ng-container
|
||||
*ngTemplateOutlet="recursiveFolders; context: { $implicit: f.children }"
|
||||
|
@ -107,7 +155,14 @@
|
|||
*ngFor="let c of collections"
|
||||
[ngClass]="{ active: c.node.id === selectedCollectionId }"
|
||||
>
|
||||
<a href="#" appStopClick appBlurClick (click)="selectCollection(c.node)">
|
||||
<button
|
||||
*ngIf="c.children.length == 0"
|
||||
type="button"
|
||||
[attr.aria-pressed]="c.node.id === selectedCollectionId"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
(click)="selectCollection(c.node)"
|
||||
>
|
||||
<i
|
||||
*ngIf="c.children.length"
|
||||
class="bwi bwi-fw"
|
||||
|
@ -126,7 +181,7 @@
|
|||
aria-hidden="true"
|
||||
></i>
|
||||
{{ c.node.name }}
|
||||
</a>
|
||||
</button>
|
||||
<ul class="bwi-ul" *ngIf="c.children.length && !isCollapsed(c.node)">
|
||||
<ng-container
|
||||
*ngTemplateOutlet="recursiveCollections; context: { $implicit: c.children }"
|
||||
|
|
|
@ -17,16 +17,15 @@
|
|||
<span class="detail">{{ h.date | date: "medium" }}</span>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'copyPassword' | i18n }}"
|
||||
(click)="copy(h.password)"
|
||||
role="button"
|
||||
>
|
||||
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" *ngIf="!history.length">
|
||||
|
|
|
@ -15,16 +15,15 @@
|
|||
<span class="detail">{{ h.lastUsedDate | date: "medium" }}</span>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'copyPassword' | i18n }}"
|
||||
(click)="copy(h.password)"
|
||||
role="button"
|
||||
>
|
||||
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" *ngIf="!history.length">
|
||||
|
|
|
@ -35,24 +35,23 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
*ngIf="field.type === fieldType.Hidden && cipher.viewPassword"
|
||||
(click)="toggleFieldValue(field)"
|
||||
role="button"
|
||||
>
|
||||
<i
|
||||
class="bwi bwi-lg"
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !field.showValue, 'bwi-eye-slash': field.showValue }"
|
||||
></i>
|
||||
</a>
|
||||
<a
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'copyValue' | i18n }}"
|
||||
*ngIf="
|
||||
|
@ -64,10 +63,9 @@
|
|||
(click)="
|
||||
copy(field.value, 'value', field.type === fieldType.Hidden ? 'H_Field' : 'Field')
|
||||
"
|
||||
role="button"
|
||||
>
|
||||
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -22,16 +22,15 @@
|
|||
{{ cipher.login.username }}
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'copyUsername' | i18n }}"
|
||||
(click)="copy(cipher.login.username, 'username', 'Username')"
|
||||
role="button"
|
||||
>
|
||||
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-flex" *ngIf="cipher.login.password">
|
||||
|
@ -74,31 +73,29 @@
|
|||
aria-hidden="true"
|
||||
></i>
|
||||
</button>
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword()"
|
||||
role="button"
|
||||
>
|
||||
<i
|
||||
class="bwi bwi-lg"
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</a>
|
||||
<a
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'copyPassword' | i18n }}"
|
||||
(click)="copy(cipher.login.password, 'password', 'Password')"
|
||||
role="button"
|
||||
>
|
||||
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
@ -131,16 +128,15 @@
|
|||
</svg>
|
||||
</span>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'copyValue' | i18n }}"
|
||||
(click)="copy(totpCode, 'verificationCodeTotp', 'TOTP')"
|
||||
role="button"
|
||||
>
|
||||
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -153,35 +149,37 @@
|
|||
<div class="box-content-row box-content-row-flex" *ngIf="cipher.card.number">
|
||||
<div class="row-main">
|
||||
<span class="row-label">{{ "number" | i18n }}</span>
|
||||
<span *ngIf="!showCardNumber" class="monospaced">{{ cipher.card.maskedNumber }}</span>
|
||||
<span *ngIf="showCardNumber" class="monospaced">{{ cipher.card.number }}</span>
|
||||
<span *ngIf="!showCardNumber" class="monospaced">{{
|
||||
cipher.card.maskedNumber | creditCardNumber: cipher.card.brand
|
||||
}}</span>
|
||||
<span *ngIf="showCardNumber" class="monospaced">{{
|
||||
cipher.card.number | creditCardNumber: cipher.card.brand
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showCardNumber"
|
||||
(click)="toggleCardNumber()"
|
||||
role="button"
|
||||
>
|
||||
<i
|
||||
class="bwi bwi-lg"
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showCardNumber, 'bwi-eye-slash': showCardNumber }"
|
||||
></i>
|
||||
</a>
|
||||
<a
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'copyNumber' | i18n }}"
|
||||
(click)="copy(cipher.card.number, 'number', 'Card Number')"
|
||||
role="button"
|
||||
>
|
||||
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" *ngIf="cipher.card.brand">
|
||||
|
@ -199,31 +197,29 @@
|
|||
<span *ngIf="showCardCode" class="monospaced">{{ cipher.card.code }}</span>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showCardCode"
|
||||
(click)="toggleCardCode()"
|
||||
role="button"
|
||||
>
|
||||
<i
|
||||
class="bwi bwi-lg"
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showCardCode, 'bwi-eye-slash': showCardCode }"
|
||||
></i>
|
||||
</a>
|
||||
<a
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'copySecurityCode' | i18n }}"
|
||||
(click)="copy(cipher.card.code, 'securityCode', 'Security Code')"
|
||||
role="button"
|
||||
>
|
||||
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -289,27 +285,25 @@
|
|||
<span title="{{ u.uri }}">{{ u.hostOrUri }}</span>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'launch' | i18n }}"
|
||||
*ngIf="u.canLaunch"
|
||||
(click)="launch(u)"
|
||||
role="button"
|
||||
>
|
||||
<i class="bwi bwi-lg bwi-share-square" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
href="#"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'copyUri' | i18n }}"
|
||||
(click)="copy(u.uri, u.isWebsite ? 'website' : 'uri', 'URI')"
|
||||
role="button"
|
||||
>
|
||||
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -334,10 +328,10 @@
|
|||
{{ "attachments" | i18n }}
|
||||
</div>
|
||||
<div class="box-content">
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
class="box-content-row box-content-row-flex text-default"
|
||||
*ngFor="let attachment of cipher.attachments"
|
||||
href="#"
|
||||
appStopClick
|
||||
appBlurCLick
|
||||
(click)="downloadAttachment(attachment)"
|
||||
|
@ -354,7 +348,7 @@
|
|||
*ngIf="attachment.downloading"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
|
@ -369,15 +363,14 @@
|
|||
</div>
|
||||
<div *ngIf="cipher.hasPasswordHistory">
|
||||
<b class="font-weight-semibold">{{ "passwordHistory" | i18n }}:</b>
|
||||
<a
|
||||
href="#"
|
||||
<button
|
||||
type="button"
|
||||
(click)="viewHistory()"
|
||||
appStopClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'passwordHistory' | i18n }}, {{ cipher.passwordHistory.length }}"
|
||||
>
|
||||
<span aria-hidden="true">{{ cipher.passwordHistory.length }}</span>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<boolean> {
|
||||
if (this.biometricService) {
|
||||
return await this.biometricService.authenticateBiometric();
|
||||
|
|
|
@ -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=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,9 @@ button {
|
|||
}
|
||||
|
||||
button {
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue