From 86b01131c37778e5f53bc9a25a2d220d2b646ca0 Mon Sep 17 00:00:00 2001 From: "Matthew A. Miller" Date: Thu, 8 Feb 2018 13:18:31 -0700 Subject: [PATCH] Publish 0.1.6-alpha (#533) --- README.md | 3 + docs/release-notes.md | 25 + package-lock.json | 931 +----------------- package.json | 6 +- src/webextension/background/accounts/index.js | 34 +- src/webextension/background/message-ports.js | 10 +- src/webextension/icons/account.svg | 3 + src/webextension/icons/arrowhead-down-16.svg | 3 + src/webextension/icons/default-avatar.svg | 1 + src/webextension/icons/options.svg | 3 + src/webextension/icons/signout.svg | 3 + src/webextension/list/actions.js | 45 + .../list/components/item-fields.js | 29 +- .../components/account-summary-label.js | 22 - .../manage/components/account-summary.css | 141 +++ .../list/manage/components/account-summary.js | 113 +++ .../list/manage/components/app.css | 2 + .../list/manage/components/app.js | 4 +- .../list/manage/containers/account-summary.js | 18 - .../containers/current-account-summary.js | 25 + src/webextension/locales/en-US/list.ftl | 8 +- src/webextension/locales/en-US/widgets.ftl | 9 +- src/webextension/widgets/button-stack.js | 19 +- src/webextension/widgets/button.css | 2 +- .../copy-to-clipboard-button.css} | 14 +- .../widgets/copy-to-clipboard-button.js | 67 ++ src/webextension/widgets/error-message.css | 8 - src/webextension/widgets/error-message.js | 23 - src/webextension/widgets/link.css | 41 +- src/webextension/widgets/link.js | 57 +- src/webextension/widgets/password-input.js | 16 +- src/webextension/widgets/toolbar.css | 2 +- test/unit/background/accounts-test.js | 54 +- test/unit/background/message-ports-test.js | 2 + test/unit/list/actions-test.js | 40 +- .../components/account-summary-label-test.js | 30 - .../manage/components/account-summary-test.js | 142 +++ .../manage/containers/account-summary-test.js | 48 - .../current-account-summary-test.js | 90 ++ .../components/item-details-panel-test.js | 2 +- test/unit/widgets/button-stack-test.js | 5 +- test/unit/widgets/button-test.js | 2 +- .../widgets/copy-to-clipboard-button-test.js | 83 ++ test/unit/widgets/link-test.js | 75 +- 44 files changed, 1055 insertions(+), 1205 deletions(-) create mode 100644 src/webextension/icons/account.svg create mode 100644 src/webextension/icons/arrowhead-down-16.svg create mode 100644 src/webextension/icons/default-avatar.svg create mode 100644 src/webextension/icons/options.svg create mode 100644 src/webextension/icons/signout.svg delete mode 100644 src/webextension/list/manage/components/account-summary-label.js create mode 100644 src/webextension/list/manage/components/account-summary.css create mode 100644 src/webextension/list/manage/components/account-summary.js delete mode 100644 src/webextension/list/manage/containers/account-summary.js create mode 100644 src/webextension/list/manage/containers/current-account-summary.js rename src/webextension/{list/manage/components/account-summary-label.css => widgets/copy-to-clipboard-button.css} (52%) create mode 100644 src/webextension/widgets/copy-to-clipboard-button.js delete mode 100644 src/webextension/widgets/error-message.css delete mode 100644 src/webextension/widgets/error-message.js delete mode 100644 test/unit/list/manage/components/account-summary-label-test.js create mode 100644 test/unit/list/manage/components/account-summary-test.js delete mode 100644 test/unit/list/manage/containers/account-summary-test.js create mode 100644 test/unit/list/manage/containers/current-account-summary-test.js create mode 100644 test/unit/widgets/copy-to-clipboard-button-test.js diff --git a/README.md b/README.md index fd1aa7a4..997172ce 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ [![Build Status][travis-image]][travis-link] [![Coverage Status][codecov-image]][codecov-link] [![Waffle Board][waffle-image]][waffle-link] +[![Greenkeeper badge][greenkeeper-image]][greenkeeper-link] # Lockbox for Firefox @@ -46,6 +47,8 @@ version 2.0][license-link]. [codecov-link]: https://codecov.io/gh/mozilla-lockbox/lockbox-extension [waffle-image]: https://badge.waffle.io/mozilla-lockbox/lockbox-extension.svg?columns=In%20Progress [waffle-link]: https://waffle.io/mozilla-lockbox/lockbox-extension +[greenkeeper-image]: https://badges.greenkeeper.io/mozilla-lockbox/lockbox-extension.svg +[greenkeeper-link]: https://greenkeeper.io/ [install-link]: /docs/install.md [org-website]: https://mozilla-lockbox.github.io/ [docs-link]: /docs diff --git a/docs/release-notes.md b/docs/release-notes.md index 4567d0c5..40192c23 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,5 +1,30 @@ # Lockbox Release Notes +## 0.1.6-alpha + +_Date: 2018-02-08_ + +### What's New + +* When you copy a username or password from the doorhanger to the clipboard, you now get confirmation of that action ([#318](https://github.com/mozilla-lockbox/lockbox-extension/issues/318)) +* When signed in with the full editor view open, it displays additional profile information you have set on Firefox Accounts to better personalize your experience ([#417](https://github.com/mozilla-lockbox/lockbox-extension/issues/417)) +* When signed in with the full editor view open, you can better manage your Firefox Account ([#442](https://github.com/mozilla-lockbox/lockbox-extension/issues/442)) +* You can now sign out of Lockbox, locking down your entries without quitting Firefox ([#149](https://github.com/mozilla-lockbox/lockbox-extension/issues/149)) + +### What's Fixed + +* Cleaned up obsolete or erroneous localization usage ([#240](https://github.com/mozilla-lockbox/lockbox-extension/issues/240)) +* Activated Greenkeeper to mitigate stale dependencies ([#276](https://github.com/mozilla-lockbox/lockbox-extension/issues/276)) + * Updated `style-loader` dependency ([#502](https://github.com/mozilla-lockbox/lockbox-extension/pull/502)) + +### Known Issues + +* Once you link a Firefox Account to Lockbox, you cannot unlink it from that account. +* Once you link a Firefox Account to Lockbox, signing in with a different account can render Lockbox unusable until you quit and restart Firefox. +* Once you link a Firefox Account to Lockbox, resetting your Firefox Account password through "forgot your password" will render all your logins inaccessible; the only recourse is to reset Lockbox and start over. +* Firefox's default prompt to save logins is only disabled on new installs of this extension; updating Lockbox will not change your current Firefox preferences. + + ## 0.1.5-alpha _Date: 2018-01-30_ diff --git a/package-lock.json b/package-lock.json index b81901f0..522d964b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "lockbox", - "version": "0.1.5-alpha", + "version": "0.1.6-alpha", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -3520,7 +3520,6 @@ "requires": { "anymatch": "1.3.0", "async-each": "1.0.1", - "fsevents": "1.1.2", "glob-parent": "2.0.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", @@ -7348,905 +7347,6 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "fsevents": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.2.tgz", - "integrity": "sha512-Sn44E5wQW4bTHXvQmvSHwqbuiXtduD6Rrjm2ZtUEGbyrig+nUH3t/QD4M4/ZXViY556TBpRgZkHLDx3JxPwxiw==", - "dev": true, - "optional": true, - "requires": { - "nan": "2.7.0", - "node-pre-gyp": "0.6.36" - }, - "dependencies": { - "abbrev": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "ajv": { - "version": "4.11.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.2.9" - } - }, - "asn1": { - "version": "0.2.3", - "bundled": true, - "dev": true, - "optional": true - }, - "assert-plus": { - "version": "0.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "asynckit": { - "version": "0.4.0", - "bundled": true, - "dev": true, - "optional": true - }, - "aws-sign2": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "aws4": { - "version": "1.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "balanced-match": { - "version": "0.4.2", - "bundled": true, - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "block-stream": { - "version": "0.0.9", - "bundled": true, - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "boom": { - "version": "2.10.1", - "bundled": true, - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "brace-expansion": { - "version": "1.1.7", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "0.4.2", - "concat-map": "0.0.1" - } - }, - "buffer-shims": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "caseless": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true - }, - "co": { - "version": "4.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "combined-stream": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "requires": { - "delayed-stream": "1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "cryptiles": { - "version": "2.0.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "boom": "2.10.1" - } - }, - "dashdash": { - "version": "1.14.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "debug": { - "version": "2.6.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.4.2", - "bundled": true, - "dev": true, - "optional": true - }, - "delayed-stream": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "ecc-jsbn": { - "version": "0.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "extend": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "extsprintf": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true, - "dev": true, - "optional": true - }, - "form-data": { - "version": "2.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.15" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "fstream": { - "version": "1.0.11", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.1" - } - }, - "fstream-ignore": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fstream": "1.0.11", - "inherits": "2.0.3", - "minimatch": "3.0.4" - } - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "1.1.1", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "getpass": { - "version": "0.1.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "bundled": true, - "dev": true - }, - "har-schema": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "optional": true - }, - "har-validator": { - "version": "4.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "hawk": { - "version": "3.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "hoek": { - "version": "2.16.3", - "bundled": true, - "dev": true - }, - "http-signature": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.0", - "sshpk": "1.13.0" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "ini": { - "version": "1.3.4", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "jodid25519": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "jsbn": { - "version": "0.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true, - "dev": true, - "optional": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "jsonify": "0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "jsonify": { - "version": "0.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "jsprim": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.0.2", - "json-schema": "0.2.3", - "verror": "1.3.6" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "mime-db": { - "version": "1.27.0", - "bundled": true, - "dev": true - }, - "mime-types": { - "version": "2.1.15", - "bundled": true, - "dev": true, - "requires": { - "mime-db": "1.27.0" - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "node-pre-gyp": { - "version": "0.6.36", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "mkdirp": "0.5.1", - "nopt": "4.0.1", - "npmlog": "4.1.0", - "rc": "1.2.1", - "request": "2.81.0", - "rimraf": "2.6.1", - "semver": "5.3.0", - "tar": "2.2.1", - "tar-pack": "3.4.0" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1.1.0", - "osenv": "0.1.4" - } - }, - "npmlog": { - "version": "4.1.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "oauth-sign": { - "version": "0.8.2", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "performance-now": { - "version": "0.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "1.0.7", - "bundled": true, - "dev": true - }, - "punycode": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true - }, - "qs": { - "version": "6.4.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.2.9", - "bundled": true, - "dev": true, - "requires": { - "buffer-shims": "1.0.0", - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "1.0.1", - "util-deprecate": "1.0.2" - } - }, - "request": { - "version": "2.81.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.15", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.0.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.2", - "tunnel-agent": "0.6.0", - "uuid": "3.0.1" - } - }, - "rimraf": { - "version": "2.6.1", - "bundled": true, - "dev": true, - "requires": { - "glob": "7.1.2" - } - }, - "safe-buffer": { - "version": "5.0.1", - "bundled": true, - "dev": true - }, - "semver": { - "version": "5.3.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sntp": { - "version": "1.0.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "hoek": "2.16.3" - } - }, - "sshpk": { - "version": "1.13.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jodid25519": "1.0.2", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string_decoder": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "stringstream": { - "version": "0.0.5", - "bundled": true, - "dev": true, - "optional": true - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "2.2.1", - "bundled": true, - "dev": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - }, - "tar-pack": { - "version": "3.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "2.6.8", - "fstream": "1.0.11", - "fstream-ignore": "1.0.5", - "once": "1.4.0", - "readable-stream": "2.2.9", - "rimraf": "2.6.1", - "tar": "2.2.1", - "uid-number": "0.0.6" - } - }, - "tough-cookie": { - "version": "2.3.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "punycode": "1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "bundled": true, - "dev": true, - "optional": true - }, - "uid-number": { - "version": "0.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "uuid": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "verror": { - "version": "1.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "extsprintf": "1.0.2" - } - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - } - } - }, "ftp": { "version": "0.3.10", "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", @@ -11949,13 +11049,6 @@ } } }, - "nan": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", - "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=", - "dev": true, - "optional": true - }, "nanomatch": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.7.tgz", @@ -12298,6 +11391,7 @@ "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz", "integrity": "sha1-hKZqJgF0QI/Ft3oY+IjszET7aXE=", "dev": true, + "optional": true, "requires": { "colors": "0.5.1", "underscore": "1.4.4" @@ -12948,6 +12042,17 @@ "readable-stream": "2.3.3" }, "dependencies": { + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8", + "isarray": "1.0.0" + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -13861,6 +12966,7 @@ "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", "dev": true, + "optional": true, "requires": { "postcss": "5.2.18", "postcss-value-parser": "3.3.0" @@ -14616,15 +13722,6 @@ } } }, - "react-copy-to-clipboard": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.1.tgz", - "integrity": "sha512-ELKq31/E3zjFs5rDWNCfFL4NvNFQvGRoJdAKReD/rUPA+xxiLPQmZBZBvy2vgH7V0GE9isIQpT9WXbwIVErYdA==", - "requires": { - "copy-to-clipboard": "3.0.8", - "prop-types": "15.6.0" - } - }, "react-document-title": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/react-document-title/-/react-document-title-2.0.3.tgz", diff --git a/package.json b/package.json index 147f2d28..2b198359 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "title": "Lockbox", "name": "lockbox", "id": "lockbox@mozilla.com", - "version": "0.1.5-alpha", + "version": "0.1.6-alpha", "main": "dist/bootstrap.js", "description": "The simple way to store, retrieve and manage website login info", "author": "Lockbox Team ", @@ -54,6 +54,7 @@ ] }, "dependencies": { + "copy-to-clipboard": "^3.0.8", "fluent": "^0.4.2", "fluent-intl-polyfill": "^0.1.0", "fluent-langneg": "^0.1.0", @@ -63,7 +64,6 @@ "node-jose": "^0.11.0", "prop-types": "^15.6.0", "react": "^16.2.0", - "react-copy-to-clipboard": "^5.0.1", "react-dom": "^16.2.0", "react-modal": "^3.1.11", "react-redux": "^5.0.6", @@ -127,7 +127,7 @@ "sinon": "^4.1.6", "sinon-chai": "^2.14.0", "source-map-support": "^0.5.1", - "style-loader": "^0.19.1", + "style-loader": "^0.20.1", "stylelint": "8.4.0", "stylelint-config-recommended": "2.0.1", "webpack": "^3.10.0", diff --git a/src/webextension/background/accounts/index.js b/src/webextension/background/accounts/index.js index 4477dedc..202f34ab 100644 --- a/src/webextension/background/accounts/index.js +++ b/src/webextension/background/accounts/index.js @@ -72,6 +72,8 @@ export const AUTHENTICATED = "authenticated"; export const APP_KEY_NAME = "https://identity.mozilla.com/apps/lockbox"; +export const DEFAULT_AVATAR_PATH = "icons/default-avatar.svg"; + export class Account { constructor({config = DEFAULT_CONFIG, info}) { // TODO: verify configuration (when there is one) @@ -112,6 +114,12 @@ export class Account { get uid() { return (this.info && this.info.uid) || undefined; } get email() { return (this.info && this.info.email) || undefined; } + get displayName() { return (this.info && this.info.displayName) || this.email; } + get avatar() { + return (this.info && this.info.avatar) || + browser.extension.getURL(DEFAULT_AVATAR_PATH); + } + get keys() { return (this.info && this.info.keys) || new Map(); } async signIn(action = "signin") { @@ -181,19 +189,33 @@ export class Account { this.info = { uid: userInfo.uid, email: userInfo.email, + displayName: userInfo.displayName, + avatar: userInfo.avatar, access_token: oauthInfo.access_token, expires_at: (Date.now() / 1000) + oauthInfo.expires_in, - refresh_token: oauthInfo.refresh_token, id_token: oauthInfo.id_token, + refresh_token: oauthInfo.refresh_token, keys, }; return this; } - async signOut() { - // TODO: implement a complete signout/forget - // TODO: something server side? - this.info = undefined; + async signOut(full = false) { + if (full) { + // forget everything + this.info = undefined; + } else if (this.info) { + // light touch -- whitelist + const info = this.info; + this.info = { + uid: info.uid, + access_token: info.access_token, + expires_at: info.expires_at, + id_token: info.id_token, + }; + } + // XXXX: something server side? + return this; } @@ -202,6 +224,8 @@ export class Account { mode: this.mode, uid: this.uid, email: this.email, + displayName: this.displayName, + avatar: this.avatar, }; } } diff --git a/src/webextension/background/message-ports.js b/src/webextension/background/message-ports.js index cff256a2..48cf7136 100644 --- a/src/webextension/background/message-ports.js +++ b/src/webextension/background/message-ports.js @@ -103,8 +103,8 @@ export default function initializeMessagePorts() { await closeView(); await datastore.reset(); - await account.signOut(); - // TODO: put other reset calls here + await account.signOut(true); + // XXXX: put other reset calls here await updateBrowserAction({datastore}); broadcast({type: "account_details_updated", account: account.details()}); @@ -143,9 +143,15 @@ export default function initializeMessagePorts() { case "signout": return openDataStore().then(async (datastore) => { // TODO: perform (light) signout from FxA + const account = getAccount(); + + await account.signOut(); await datastore.lock(); await updateBrowserAction({datastore}); + telemetry.recordEvent("fxaSignout", "accounts"); + broadcast({ type: "account_details_updated", account: account.details() }); + await closeView("manage"); return {}; }); diff --git a/src/webextension/icons/account.svg b/src/webextension/icons/account.svg new file mode 100644 index 00000000..0b032a1a --- /dev/null +++ b/src/webextension/icons/account.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/webextension/icons/arrowhead-down-16.svg b/src/webextension/icons/arrowhead-down-16.svg new file mode 100644 index 00000000..a56e6870 --- /dev/null +++ b/src/webextension/icons/arrowhead-down-16.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/webextension/icons/default-avatar.svg b/src/webextension/icons/default-avatar.svg new file mode 100644 index 00000000..e6dc3a5d --- /dev/null +++ b/src/webextension/icons/default-avatar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/webextension/icons/options.svg b/src/webextension/icons/options.svg new file mode 100644 index 00000000..01cf3b4f --- /dev/null +++ b/src/webextension/icons/options.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/webextension/icons/signout.svg b/src/webextension/icons/signout.svg new file mode 100644 index 00000000..73730be2 --- /dev/null +++ b/src/webextension/icons/signout.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/webextension/list/actions.js b/src/webextension/list/actions.js index 150e6ca3..bfed26a6 100644 --- a/src/webextension/list/actions.js +++ b/src/webextension/list/actions.js @@ -7,6 +7,12 @@ import { version } from "../../../package"; export const GET_ACCOUNT_DETAILS_STARTING = Symbol("GET_ACCOUNT_DETAILS_STARTING"); export const GET_ACCOUNT_DETAILS_COMPLETED = Symbol("GET_ACCOUNT_DETAILS_COMPLETED"); +export const OPEN_ACCOUNT_PAGE = Symbol("OPEN_ACCOUNT_PAGE"); +export const OPEN_OPTIONS = Symbol("OPEN_OPTIONS"); + +export const SIGNOUT_STARTING = Symbol("SIGNOUT_STARTING"); +export const SIGNOUT_COMPLETED = Symbol("SIGNOUT_COMPLETED"); + export const LIST_ITEMS_STARTING = Symbol("LIST_ITEMS_STARTING"); export const LIST_ITEMS_COMPLETED = Symbol("LIST_ITEMS_COMPLETED"); @@ -41,6 +47,7 @@ export const OPEN_FAQ = Symbol("OPEN_FAQ"); // other (i.e. FOO_STARTING and FOO_COMPLETED). let nextActionId = 0; +const ACCOUNT_URL = "https://accounts.firefox.com/settings"; const FEEDBACK_URL = "https://qsurvey.mozilla.com/s3/Lockbox-Input?ver=" + version; const FAQ_URL = "https://mozilla-lockbox.github.io/lockbox-extension/faqs/"; @@ -75,6 +82,44 @@ export function accountDetailsUpdated(account) { return getAccountDetailsCompleted(undefined, account); } +export function openAccountPage() { + window.open(ACCOUNT_URL, "_blank"); + return { + type: OPEN_ACCOUNT_PAGE, + }; +} + +export function openOptions() { + browser.runtime.openOptionsPage(); + return { + type: OPEN_OPTIONS, + }; +} + +export function signout() { + return async (dispatch) => { + const actionId = nextActionId++; + dispatch(signoutStarting(actionId)); + + await browser.runtime.sendMessage({type: "signout"}); + dispatch(signoutCompleted(actionId)); + }; +} + +function signoutStarting(actionId) { + return { + type: SIGNOUT_STARTING, + actionId, + }; +} + +function signoutCompleted(actionId) { + return { + type: SIGNOUT_COMPLETED, + actionId, + }; +} + export function listItems() { return async (dispatch) => { const actionId = nextActionId++; diff --git a/src/webextension/list/components/item-fields.js b/src/webextension/list/components/item-fields.js index 98f2da1b..df00ec0a 100644 --- a/src/webextension/list/components/item-fields.js +++ b/src/webextension/list/components/item-fields.js @@ -5,9 +5,8 @@ import { Localized } from "fluent-react"; import PropTypes from "prop-types"; import React from "react"; -import CopyToClipboard from "react-copy-to-clipboard"; -import Button from "../../widgets/button"; +import CopyToClipboardButton from "../../widgets/copy-to-clipboard-button"; import FieldText from "../../widgets/field-text"; import Input from "../../widgets/input"; import LabelText from "../../widgets/label-text"; @@ -18,20 +17,6 @@ import styles from "./item-fields.css"; const PASSWORD_DOT = "\u25cf"; -function CopyToClipboardButton({text, field, onCopy, ...props}) { - return ( - onCopy(field)}> - + ); +} + +AccountSummaryButton.propTypes = { + displayName: PropTypes.string, + avatar: PropTypes.string, + onClick: PropTypes.func, +}; + +export function AccountSummaryDropdown({isOpen, onClose, onClickAccount, + onClickOptions, onClickSignout}) { + return ( + +
    +
  • + + { onClickAccount(); onClose(); }}> + aCCOUNt + + +
  • +
  • + + { onClickOptions(); onClose(); }}> + oPTIONs + + +
  • +
  • + + { onClickSignout(); onClose(); }}> + sIGn oUt + + +
  • +
+
+ ); +} + +AccountSummaryDropdown.propTypes = { + isOpen: PropTypes.bool.isRequired, + onClose: PropTypes.func.isRequired, + onClickAccount: PropTypes.func.isRequired, + onClickOptions: PropTypes.func.isRequired, + onClickSignout: PropTypes.func.isRequired, +}; + +export default class AccountSummary extends React.Component { + static get propTypes() { + return { + displayName: PropTypes.string, + avatar: PropTypes.string, + }; + } + + constructor(props) { + super(props); + this.state = { + showDropdown: false, + }; + } + + openDropdown() { + this.setState({showDropdown: true}); + } + + closeDropdown() { + this.setState({showDropdown: false}); + } + + render() { + const {displayName, avatar, ...props} = this.props; + const {showDropdown} = this.state; + return ( +
+ this.openDropdown()}/> + this.closeDropdown()} + {...props}/> +
+ ); + } +} diff --git a/src/webextension/list/manage/components/app.css b/src/webextension/list/manage/components/app.css index 3d729607..91198db6 100644 --- a/src/webextension/list/manage/components/app.css +++ b/src/webextension/list/manage/components/app.css @@ -10,6 +10,7 @@ body { font: caption; font-size: 13px; -moz-user-select: none; + overflow: hidden; } html, @@ -44,6 +45,7 @@ body > main, grid-column: 2; background-color: #f9f9fa; border-top: 1px solid #d1d1d2; + overflow: auto; } .filter { diff --git a/src/webextension/list/manage/components/app.js b/src/webextension/list/manage/components/app.js index c381d838..2ebbe952 100644 --- a/src/webextension/list/manage/components/app.js +++ b/src/webextension/list/manage/components/app.js @@ -6,9 +6,9 @@ import { Localized } from "fluent-react"; import React from "react"; import DocumentTitle from "react-document-title"; -import AccountSummary from "../containers/account-summary"; import AddItem from "../containers/add-item"; import AllItems from "../containers/all-items"; +import CurrentAccountSummary from "../containers/current-account-summary"; import CurrentSelection from "../containers/current-selection"; import GoHome from "../containers/go-home"; import ItemFilter from "../../containers/item-filter"; @@ -31,7 +31,7 @@ export default function App() { - +