diff --git a/package-lock.json b/package-lock.json index aee9f5d30..462fbc13a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,12 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@types/argon2-browser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@types/argon2-browser/-/argon2-browser-1.6.0.tgz", + "integrity": "sha512-218mScZ+/w4Quuo9cZnVO9Q3u9yhIBMnQz7NZDbSaFLDpA00aj6caCPsRvkcf3iJ8BjX1VqhE5335Of+2doMtA==", + "dev": true + }, "@types/chrome": { "version": "0.0.86", "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.86.tgz", @@ -266,15 +272,9 @@ "dev": true }, "acorn": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", - "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", - "dev": true - }, - "acorn-dynamic-import": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", - "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", + "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", "dev": true }, "ajv": { @@ -343,6 +343,11 @@ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, + "argon2-browser": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/argon2-browser/-/argon2-browser-1.8.0.tgz", + "integrity": "sha512-5jDXBnzI66PPkSAivtmF0kfCOhSwXJEk/8rYnGaDEy/hgFlp2EsP8qngmPNbttPalBI0vTAN2kq0zRzVE/WFeA==" + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -558,9 +563,15 @@ } }, "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "dev": true + }, + "base64-loader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64-loader/-/base64-loader-1.0.0.tgz", + "integrity": "sha1-5TC62I6QbdKh+tCvLZ5oP6i9kqg=", "dev": true }, "big.js": { @@ -739,31 +750,38 @@ "dev": true }, "cacache": { - "version": "11.3.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", - "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.2.tgz", + "integrity": "sha512-ifKgxH2CKhJEg6tNdAwziu6Q33EvuG26tYcda6PT3WKisZcYDXsnEdnRv67Po3yCzFfaSoMjGZzJyD2c3DT1dg==", "dev": true, "requires": { - "bluebird": "^3.5.3", + "bluebird": "^3.5.5", "chownr": "^1.1.1", "figgy-pudding": "^3.5.1", - "glob": "^7.1.3", + "glob": "^7.1.4", "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", "lru-cache": "^5.1.1", "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", + "rimraf": "^2.6.3", "ssri": "^6.0.1", "unique-filename": "^1.1.1", "y18n": "^4.0.0" }, "dependencies": { + "bluebird": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", + "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==", + "dev": true + }, "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", + "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", "dev": true }, "lru-cache": { @@ -832,9 +850,9 @@ } }, "chownr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz", + "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==", "dev": true }, "chrome-trace-event": { @@ -933,9 +951,9 @@ "dev": true }, "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", "dev": true }, "commondir": { @@ -1096,39 +1114,6 @@ "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz", "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=" }, - "css-loader": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.1.tgz", - "integrity": "sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w==", - "dev": true, - "requires": { - "camelcase": "^5.2.0", - "icss-utils": "^4.1.0", - "loader-utils": "^1.2.3", - "normalize-path": "^3.0.0", - "postcss": "^7.0.14", - "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^2.0.6", - "postcss-modules-scope": "^2.1.0", - "postcss-modules-values": "^2.0.0", - "postcss-value-parser": "^3.3.0", - "schema-utils": "^1.0.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - } - } - }, "css-select": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.2.tgz", @@ -1371,9 +1356,9 @@ } }, "elliptic": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", - "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", + "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -1483,9 +1468,9 @@ } }, "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true }, "esutils": { @@ -1690,30 +1675,6 @@ "commondir": "^1.0.1", "make-dir": "^2.0.0", "pkg-dir": "^3.0.0" - }, - "dependencies": { - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", - "dev": true - } } }, "findup-sync": { @@ -2383,9 +2344,9 @@ "dev": true }, "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -2575,21 +2536,6 @@ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "dev": true }, - "icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", - "dev": true - }, - "icss-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.0.tgz", - "integrity": "sha512-3DEun4VOeMvSczifM3F2cKQrDQ5Pj6WKhkOq6HD4QTnDUAq8MQRxy5TX6Sy1iY6WPBe4gQ3p5vTECjbIkglkkQ==", - "dev": true, - "requires": { - "postcss": "^7.0.14" - } - }, "ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", @@ -2624,10 +2570,10 @@ "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", "dev": true }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "dev": true }, "inflight": { @@ -2944,6 +2890,24 @@ "yallist": "^2.1.2" } }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "mamacro": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", @@ -3120,9 +3084,9 @@ } }, "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, "requires": { "for-in": "^1.0.2", @@ -3216,9 +3180,9 @@ "dev": true }, "node-libs-browser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz", - "integrity": "sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", "dev": true, "requires": { "assert": "^1.1.1", @@ -3231,7 +3195,7 @@ "events": "^3.0.0", "https-browserify": "^1.0.0", "os-browserify": "^0.3.0", - "path-browserify": "0.0.0", + "path-browserify": "0.0.1", "process": "^0.11.10", "punycode": "^1.2.4", "querystring-es3": "^0.2.0", @@ -3243,7 +3207,7 @@ "tty-browserify": "0.0.0", "url": "^0.11.0", "util": "^0.11.0", - "vm-browserify": "0.0.4" + "vm-browserify": "^1.0.1" }, "dependencies": { "punycode": { @@ -3494,9 +3458,9 @@ "dev": true }, "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", "dev": true }, "path-dirname": { @@ -3542,6 +3506,12 @@ "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==", "dev": true }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", @@ -3652,84 +3622,6 @@ } } }, - "postcss-modules-extract-imports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", - "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", - "dev": true, - "requires": { - "postcss": "^7.0.5" - } - }, - "postcss-modules-local-by-default": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz", - "integrity": "sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA==", - "dev": true, - "requires": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^6.0.0", - "postcss-value-parser": "^3.3.1" - }, - "dependencies": { - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "postcss-selector-parser": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", - "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } - } - }, - "postcss-modules-scope": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz", - "integrity": "sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A==", - "dev": true, - "requires": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^6.0.0" - }, - "dependencies": { - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "postcss-selector-parser": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", - "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } - } - }, - "postcss-modules-values": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz", - "integrity": "sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w==", - "dev": true, - "requires": { - "icss-replace-symbols": "^1.1.0", - "postcss": "^7.0.6" - } - }, "postcss-selector-parser": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", @@ -3741,12 +3633,6 @@ "uniq": "^1.0.1" } }, - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, "prettier": { "version": "1.18.2", "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz", @@ -3987,12 +3873,12 @@ "dev": true }, "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "requires": { - "glob": "^7.0.5" + "glob": "^7.1.3" } }, "ripemd160": { @@ -4074,9 +3960,9 @@ "dev": true }, "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "dev": true, "requires": { "extend-shallow": "^2.0.1", @@ -4266,9 +4152,9 @@ } }, "source-map-support": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", - "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -4460,14 +4346,14 @@ "dev": true }, "terser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.0.0.tgz", - "integrity": "sha512-dOapGTU0hETFl1tCo4t56FN+2jffoKyER9qBGoUFyZ6y7WLoKT0bF+lAYi6B6YsILcGF3q1C2FBh8QcKSCgkgA==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.1.4.tgz", + "integrity": "sha512-+ZwXJvdSwbd60jG0Illav0F06GDJF0R4ydZ21Q3wGAFKoBGyJGo34F63vzJHgvYxc1ukOtIjvwEvl9MkjzM6Pg==", "dev": true, "requires": { - "commander": "^2.19.0", + "commander": "^2.20.0", "source-map": "~0.6.1", - "source-map-support": "~0.5.10" + "source-map-support": "~0.5.12" }, "dependencies": { "source-map": { @@ -4479,20 +4365,19 @@ } }, "terser-webpack-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz", - "integrity": "sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz", + "integrity": "sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg==", "dev": true, "requires": { - "cacache": "^11.3.2", - "find-cache-dir": "^2.0.0", + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", "is-wsl": "^1.1.0", - "loader-utils": "^1.2.3", "schema-utils": "^1.0.0", "serialize-javascript": "^1.7.0", "source-map": "^0.6.1", - "terser": "^4.0.0", - "webpack-sources": "^1.3.0", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", "worker-farm": "^1.7.0" }, "dependencies": { @@ -4520,9 +4405,9 @@ "integrity": "sha1-t8+nHnaPHJAAxJe5FRswlHxQ5G0=" }, "timers-browserify": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", + "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", "dev": true, "requires": { "setimmediate": "^1.0.4" @@ -4641,9 +4526,9 @@ } }, "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", "dev": true }, "tty-browserify": { @@ -4665,38 +4550,15 @@ "dev": true }, "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", "dev": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } + "set-value": "^2.0.1" } }, "uniq": { @@ -4715,9 +4577,9 @@ } }, "unique-slug": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz", - "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", "dev": true, "requires": { "imurmurhash": "^0.1.4" @@ -4846,13 +4708,10 @@ "dev": true }, "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "0.0.1" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", + "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", + "dev": true }, "vue": { "version": "2.6.10", @@ -4939,35 +4798,54 @@ } }, "webpack": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.33.0.tgz", - "integrity": "sha512-ggWMb0B2QUuYso6FPZKUohOgfm+Z0sVFs8WwWuSH1IAvkWs428VDNmOlAxvHGTB9Dm/qOB/qtE5cRx5y01clxw==", + "version": "4.39.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.39.2.tgz", + "integrity": "sha512-AKgTfz3xPSsEibH00JfZ9sHXGUwIQ6eZ9tLN8+VLzachk1Cw2LVmy+4R7ZiwTa9cZZ15tzySjeMui/UnSCAZhA==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", "@webassemblyjs/helper-module-context": "1.8.5", "@webassemblyjs/wasm-edit": "1.8.5", "@webassemblyjs/wasm-parser": "1.8.5", - "acorn": "^6.0.5", - "acorn-dynamic-import": "^4.0.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chrome-trace-event": "^1.0.0", + "acorn": "^6.2.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^4.1.0", - "eslint-scope": "^4.0.0", + "eslint-scope": "^4.0.3", "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "micromatch": "^3.1.8", - "mkdirp": "~0.5.0", - "neo-async": "^2.5.0", - "node-libs-browser": "^2.0.0", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", "schema-utils": "^1.0.0", - "tapable": "^1.1.0", - "terser-webpack-plugin": "^1.1.0", - "watchpack": "^1.5.0", - "webpack-sources": "^1.3.0" + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.1", + "watchpack": "^1.6.0", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "dev": true + } } }, "webpack-cli": { @@ -5021,9 +4899,9 @@ } }, "webpack-sources": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", - "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", "dev": true, "requires": { "source-list-map": "^2.0.0", @@ -5125,9 +5003,9 @@ "dev": true }, "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, "y18n": { diff --git a/package.json b/package.json index 80b3a2329..656de3a86 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,11 @@ }, "homepage": "https://github.com/Authenticator-Extension/Authenticator#readme", "devDependencies": { + "@types/argon2-browser": "^1.6.0", "@types/chrome": "^0.0.86", "@types/crypto-js": "^3.1.43", "@types/jssha": "2.0.0", - "css-loader": "^2.1.1", + "base64-loader": "^1.0.0", "fork-ts-checker-webpack-plugin": "^1.3.5", "prettier": "1.18.2", "sass": "^1.21.0", @@ -32,11 +33,12 @@ "vue-loader": "^15.7.0", "vue-svg-loader": "^0.12.0", "vue-template-compiler": "^2.6.10", - "webpack": "^4.33.0", + "webpack": "^4.38.0", "webpack-cli": "^3.3.3", "webpack-merge": "^4.2.1" }, "dependencies": { + "argon2-browser": "^1.8.0", "crypto-js": "^3.1.9-1", "jssha": "^2.3.1", "qrcode-generator": "^1.4.3", diff --git a/sass/popup.scss b/sass/popup.scss index 949328672..094adbdee 100644 --- a/sass/popup.scss +++ b/sass/popup.scss @@ -650,6 +650,10 @@ svg { top: 110px; animation: fadeout 0.2s 1 ease-in; } + + &.show { + top: 10px; + } } // Menu diff --git a/src/background.ts b/src/background.ts index f52c2269f..8b6a200ee 100644 --- a/src/background.ts +++ b/src/background.ts @@ -1,5 +1,3 @@ -import * as CryptoJS from "crypto-js"; -// tslint:disable-next-line:ban-ts-ignore // @ts-ignore import QRCode from "qrcode-reader"; @@ -7,6 +5,7 @@ import { getCredentials } from "./models/credentials"; import { Encryption } from "./models/encryption"; import { EntryStorage, ManagedStorage } from "./models/storage"; import { Dropbox, Drive } from "./models/backup"; +import { argon } from "./models/argon"; let cachedPassphrase = ""; chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { @@ -167,7 +166,7 @@ async function getTotp(text: string) { chrome.tabs.sendMessage(id, { action: "secretqr", secret }); } else { const encryption = new Encryption(cachedPassphrase); - const hash = CryptoJS.MD5(secret).toString(); + const hash = await argon.hash(secret); if ( !/^[2-7a-z]+=*$/i.test(secret) && /^[0-9a-f]+$/i.test(secret) && diff --git a/src/components/Import/FileImport.vue b/src/components/Import/FileImport.vue index 5f52b01d8..02e80207b 100644 --- a/src/components/Import/FileImport.vue +++ b/src/components/Import/FileImport.vue @@ -56,7 +56,7 @@ export default Vue.extend({ try { importData = JSON.parse(reader.result as string); } catch (e) { - importData = getEntryDataFromOTPAuthPerLine( + importData = await getEntryDataFromOTPAuthPerLine( reader.result as string ); } diff --git a/src/components/Import/TextImport.vue b/src/components/Import/TextImport.vue index 67dab9e42..c98f71ad0 100644 --- a/src/components/Import/TextImport.vue +++ b/src/components/Import/TextImport.vue @@ -44,7 +44,7 @@ export default Vue.extend({ exportData = JSON.parse(this.importCode); } catch (error) { // Maybe one-otpauth-per line text - exportData = getEntryDataFromOTPAuthPerLine(this.importCode); + exportData = await getEntryDataFromOTPAuthPerLine(this.importCode); } try { diff --git a/src/components/Popup.vue b/src/components/Popup.vue index f77999845..3a6fcfeae 100644 --- a/src/components/Popup.vue +++ b/src/components/Popup.vue @@ -20,7 +20,11 @@ /> diff --git a/src/components/Popup/AddAccountPage.vue b/src/components/Popup/AddAccountPage.vue index 2f56c0c83..898f65b99 100644 --- a/src/components/Popup/AddAccountPage.vue +++ b/src/components/Popup/AddAccountPage.vue @@ -31,7 +31,7 @@ import Vue from "vue"; import { mapState } from "vuex"; import { OTPType, OTPEntry } from "../../models/otp"; -import * as CryptoJS from "crypto-js"; +import { argon } from "../../models/argon"; export default Vue.extend({ data: function(): { @@ -91,20 +91,23 @@ export default Vue.extend({ this.newAccount.period = undefined; } - const entry = new OTPEntry({ - type, - index: 0, - issuer: this.newAccount.issuer, - account: this.newAccount.account, - encrypted: false, - hash: CryptoJS.MD5(this.newAccount.secret).toString(), - secret: this.newAccount.secret, - counter: 0, - period: this.newAccount.period - }); + const entry = new OTPEntry( + { + type, + index: 0, + issuer: this.newAccount.issuer, + account: this.newAccount.account, + encrypted: false, + hash: await argon.hash(this.newAccount.secret), + secret: this.newAccount.secret, + counter: 0, + period: this.newAccount.period + }, + this.$store.state.accounts.encryption + ); - await entry.create(this.$store.state.accounts.encryption); - await this.$store.dispatch("accounts/updateEntries"); + await entry.create(); + await this.$store.dispatch("accounts/addCode", entry); this.$store.commit("style/hideInfo"); this.$store.commit("style/toggleEdit"); diff --git a/src/components/Popup/EntryComponent.vue b/src/components/Popup/EntryComponent.vue index 01381ead4..2a904a6f5 100644 --- a/src/components/Popup/EntryComponent.vue +++ b/src/components/Popup/EntryComponent.vue @@ -127,7 +127,7 @@ export default Vue.extend({ ) ) { await entry.delete(); - await this.$store.dispatch("accounts/updateEntries"); + await this.$store.dispatch("accounts/deleteCode", entry.hash); } return; }, @@ -141,7 +141,7 @@ export default Vue.extend({ return; } this.$store.commit("style/toggleHotpDisabled"); - await entry.next(this.$store.state.accounts.encryption); + await entry.next(); setTimeout(() => { this.$store.commit("style/toggleHotpDisabled"); }, 3000); diff --git a/src/components/Popup/LoadingPage.vue b/src/components/Popup/LoadingPage.vue new file mode 100644 index 000000000..ebcea1544 --- /dev/null +++ b/src/components/Popup/LoadingPage.vue @@ -0,0 +1,10 @@ + + diff --git a/src/components/Popup/MainBody.vue b/src/components/Popup/MainBody.vue index c997f5c01..1e9647086 100644 --- a/src/components/Popup/MainBody.vue +++ b/src/components/Popup/MainBody.vue @@ -114,10 +114,7 @@ export default Vue.extend({ from: dragIndex, to: dropIndex }); - await EntryStorage.set( - this.$store.state.accounts.encryption, - this.$store.state.accounts.entries - ); + await EntryStorage.set(this.$store.state.accounts.entries); } ); }, diff --git a/src/components/Popup/PageHandler.vue b/src/components/Popup/PageHandler.vue index c2cdfad9f..65ced06f6 100644 --- a/src/components/Popup/PageHandler.vue +++ b/src/components/Popup/PageHandler.vue @@ -2,7 +2,7 @@
@@ -25,6 +25,7 @@ import DropboxPage from "./DropboxPage.vue"; import DrivePage from "./DrivePage.vue"; import StorageSyncConfPage from "./StorageSyncConfPage.vue"; import PrefrencesPage from "./PrefrencesPage.vue"; +import LoadingPage from "./LoadingPage.vue"; export default Vue.extend({ computed: { @@ -48,7 +49,8 @@ export default Vue.extend({ DropboxPage, DrivePage, PrefrencesPage, - StorageSyncConfPage + StorageSyncConfPage, + LoadingPage } }); diff --git a/src/definitions/module-interface.d.ts b/src/definitions/module-interface.d.ts index 75b1dffeb..6d9322947 100644 --- a/src/definitions/module-interface.d.ts +++ b/src/definitions/module-interface.d.ts @@ -43,6 +43,7 @@ interface StyleState { slideout: Boolean; fadein: Boolean; fadeout: Boolean; + show: Boolean; qrfadein: Boolean; qrfadeout: Boolean; notificationFadein: Boolean; diff --git a/src/definitions/otp.d.ts b/src/definitions/otp.d.ts index bbabe91b5..0cdb96be6 100644 --- a/src/definitions/otp.d.ts +++ b/src/definitions/otp.d.ts @@ -9,18 +9,19 @@ interface IOTPEntry { counter: number; code: string; period: number; - create(encryption: IEncryption): Promise; - update(encryption: IEncryption): Promise; - next(encryption: IEncryption): Promise; - applyEncryption(encryption: IEncryption): void; + create(): Promise; + update(): Promise; + next(): Promise; + applyEncryption(encryption: IEncryption): Promise; + changeEncryption(encryption: IEncryption): Promise; delete(): Promise; generate(): void; + rehash(encryption: IEncryption): Promise; } interface IEncryption { - getEncryptedSecret(entry: IOTPEntry): string; getEncryptedString(data: string): string; - getDecryptedSecret(entry: OTPStorage): string | null; + getDecryptedSecret(entry: OTPStorage): Promise; getEncryptionStatus(): boolean; updateEncryptionPassword(password: string): void; } diff --git a/src/import.ts b/src/import.ts index 2fd827d72..f7feaa25e 100644 --- a/src/import.ts +++ b/src/import.ts @@ -5,6 +5,7 @@ import { loadI18nMessages } from "./store/i18n"; import { Encryption } from "./models/encryption"; import { EntryStorage } from "./models/storage"; import * as CryptoJS from "crypto-js"; +import { argon } from "./models/argon"; async function init() { // i18n @@ -12,7 +13,15 @@ async function init() { // Load entries to global const encryption = new Encryption(await getCachedPassphrase()); - Vue.prototype.$entries = await EntryStorage.get(encryption); + const entries = await EntryStorage.get(); + + if (encryption.getEncryptionStatus()) { + for (const entry of entries) { + await entry.applyEncryption(encryption); + } + } + + Vue.prototype.$entries = entries; Vue.prototype.$encryption = encryption; const instance = new Vue({ @@ -88,7 +97,7 @@ export function decryptBackupData( return decryptedbackupData; } -export function getEntryDataFromOTPAuthPerLine(importCode: string) { +export async function getEntryDataFromOTPAuthPerLine(importCode: string) { const lines = importCode.split("\n"); const exportData: { [hash: string]: OTPStorage } = {}; for (let item of lines) { @@ -153,7 +162,7 @@ export function getEntryDataFromOTPAuthPerLine(importCode: string) { ) { continue; } else { - const hash = CryptoJS.MD5(secret).toString(); + const hash = await argon.hash(secret); if ( !/^[2-7a-z]+=*$/i.test(secret) && /^[0-9a-f]+$/i.test(secret) && diff --git a/src/models/argon.ts b/src/models/argon.ts new file mode 100644 index 000000000..718cefac4 --- /dev/null +++ b/src/models/argon.ts @@ -0,0 +1,30 @@ +import * as argon2 from "argon2-browser"; + +export class argon { + static async hash(value: string) { + const salt = window.crypto.getRandomValues(new Uint8Array(16)); + const hash = await argon2.hash({ + pass: value, + salt, + mem: 1024 * 8, + type: argon2.ArgonType.Argon2id + }); + + return hash.encoded; + } + + static compareHash(hash: string, value: string) { + return new Promise((resolve: (value: boolean) => void) => { + argon2 + .verify({ + pass: value, + encoded: hash + }) + .then(() => resolve(true)) + .catch((e: { message: string; code: number }) => { + console.error("Error decoding hash", e); + resolve(false); + }); + }); + } +} diff --git a/src/models/backup.ts b/src/models/backup.ts index 8a9cefb44..b9ed7ba8c 100644 --- a/src/models/backup.ts +++ b/src/models/backup.ts @@ -12,7 +12,7 @@ export class Dropbox implements BackupProvider { // Encrypt by default if user hasn't set yet localStorage.dropboxEncrypted = "true"; } - const exportData = await EntryStorage.getExport( + const exportData = await EntryStorage.backupGetExport( encryption, localStorage.dropboxEncrypted === "true" ); @@ -335,7 +335,7 @@ export class Drive implements BackupProvider { if (localStorage.driveEncrypted === undefined) { localStorage.driveEncrypted = "true"; } - const exportData = await EntryStorage.getExport( + const exportData = await EntryStorage.backupGetExport( encryption, localStorage.driveEncrypted === "true" ); diff --git a/src/models/encryption.ts b/src/models/encryption.ts index 1ccc79472..37b3969af 100644 --- a/src/models/encryption.ts +++ b/src/models/encryption.ts @@ -1,4 +1,5 @@ import * as CryptoJS from "crypto-js"; +import { argon } from "./argon"; export class Encryption implements IEncryption { private password: string; @@ -7,23 +8,6 @@ export class Encryption implements IEncryption { this.password = password; } - getEncryptedSecret(entry: IOTPEntry): string { - if (entry.encSecret) { - return entry.encSecret; - } else if (entry.secret) { - if (!this.password) { - // Not encrypted, give unencrypted. - return entry.secret; - } else { - // Not encrypted and password is set, encrypt. - return CryptoJS.AES.encrypt(entry.secret, this.password).toString(); - } - } else { - console.error(entry); - throw new Error("Invalid entry"); - } - } - getEncryptedString(data: string): string { if (!this.password) { return data; @@ -32,13 +16,9 @@ export class Encryption implements IEncryption { } } - getDecryptedSecret(entry: { secret: string; hash: string }): string | null { + async getDecryptedSecret(entry: { secret: string; hash: string }) { try { - if (entry.hash === CryptoJS.MD5(entry.secret).toString()) { - return entry.secret; - } - - let decryptedSecret = CryptoJS.AES.decrypt( + const decryptedSecret = CryptoJS.AES.decrypt( entry.secret, this.password ).toString(CryptoJS.enc.Utf8); @@ -51,12 +31,6 @@ export class Encryption implements IEncryption { return null; } - if (entry.hash === CryptoJS.MD5(decryptedSecret).toString()) { - return decryptedSecret; - } - - decryptedSecret = decryptedSecret.replace(/ /g, ""); - if ( !/^[a-z2-7]+=*$/i.test(decryptedSecret) && !/^[0-9a-f]+$/i.test(decryptedSecret) && @@ -67,8 +41,23 @@ export class Encryption implements IEncryption { return null; } + if ( + /^\$argon2(?:d|i|di|id)\$v=(\d+)\$m=(\d+),t=(\d+),p=(\d+)\$([A-Za-z0-9+/=]+)\$([A-Za-z0-9+/=]*)$/.test( + entry.hash + ) + ) { + if (await argon.compareHash(entry.hash, decryptedSecret)) { + return decryptedSecret; + } + } else if (entry.hash === CryptoJS.MD5(decryptedSecret).toString()) { + return decryptedSecret; + } + console.warn( - `Account ${entry.hash} may have secret ${decryptedSecret}, but hash did not match.` + `Account ${entry.hash} may have secret ${decryptedSecret.replace( + / /g, + "" + )}, but hash did not match.` ); return null; } catch (error) { diff --git a/src/models/otp.ts b/src/models/otp.ts index bfacd5e75..12e73a880 100644 --- a/src/models/otp.ts +++ b/src/models/otp.ts @@ -1,6 +1,8 @@ import { Encryption } from "./encryption"; import { KeyUtilities } from "./key-utilities"; import { EntryStorage } from "./storage"; +import { argon } from "./argon"; +import * as CryptoJS from "crypto-js"; export enum OTPType { totp = 1, @@ -23,28 +25,34 @@ export class OTPEntry implements IOTPEntry { period: number; code = "••••••"; - constructor(entry: { - account: string; - encrypted: boolean; - hash: string; - index: number; - issuer: string; - secret: string; - type: OTPType; - counter: number; - period?: number; - }) { + constructor( + entry: { + account: string; + encrypted: boolean; + hash: string; + index: number; + issuer: string; + secret: string; + type: OTPType; + counter: number; + period?: number; + }, + encryption?: Encryption + ) { this.type = entry.type; this.index = entry.index; this.issuer = entry.issuer; + this.account = entry.account; if (entry.encrypted) { this.encSecret = entry.secret; this.secret = null; } else { this.secret = entry.secret; this.encSecret = null; + if (encryption && encryption.getEncryptionStatus()) { + this.encSecret = encryption.getEncryptedString(this.secret); + } } - this.account = entry.account; this.hash = entry.hash; this.counter = entry.counter; if (this.type === OTPType.totp && entry.period) { @@ -57,20 +65,38 @@ export class OTPEntry implements IOTPEntry { } } - async create(encryption: Encryption) { - await EntryStorage.add(encryption, this); + async create() { + await EntryStorage.add(this); return; } - async update(encryption: Encryption) { - await EntryStorage.update(encryption, this); + async update() { + await EntryStorage.update(this); return; } - applyEncryption(encryption: Encryption) { + async changeEncryption(encryption: Encryption) { + if (!this.secret) { + return; + } + + if (encryption.getEncryptionStatus()) { + this.encSecret = encryption.getEncryptedString(this.secret); + } else { + this.encSecret = null; + } + + await this.update(); + return; + } + + async applyEncryption(encryption: Encryption) { const secret = this.encSecret ? this.encSecret : null; if (secret) { - this.secret = encryption.getDecryptedSecret({ hash: this.hash, secret }); + this.secret = await encryption.getDecryptedSecret({ + hash: this.hash, + secret + }); if (this.type !== OTPType.hotp && this.type !== OTPType.hhex) { this.generate(); } @@ -83,18 +109,34 @@ export class OTPEntry implements IOTPEntry { return; } - async next(encryption: Encryption) { + async next() { if (this.type !== OTPType.hotp && this.type !== OTPType.hhex) { return; } this.generate(); if (this.secret !== null) { this.counter++; - await this.update(encryption); + await this.update(); } return; } + async rehash() { + const secret = this.secret; + if (!secret) { + return; + } + + if (this.hash !== CryptoJS.MD5(secret).toString()) { + return; + } + + const newHash = await argon.hash(secret); + await this.delete(); + this.hash = newHash; + await this.create(); + } + generate() { if (!this.secret && !this.encSecret) { this.code = "Invalid"; diff --git a/src/models/storage.ts b/src/models/storage.ts index 7e7a88730..931dd142d 100644 --- a/src/models/storage.ts +++ b/src/models/storage.ts @@ -1,7 +1,6 @@ -import * as CryptoJS from "crypto-js"; - import { Encryption } from "./encryption"; import { OTPEntry, OTPType } from "./otp"; +import { argon } from "./argon"; export class BrowserStorage { private static async getStorageLocation() { @@ -90,18 +89,32 @@ export class BrowserStorage { export class EntryStorage { private static getOTPStorageFromEntry( - encryption: Encryption, - entry: OTPEntry + entry: OTPEntry, + unencrypted?: boolean ): OTPStorage { + let secret: string; + if (entry.encSecret) { + secret = entry.encSecret; + } else if (entry.secret) { + secret = entry.secret; + } else { + secret = ""; + console.warn("Invalid entry", entry); + } + + if (unencrypted && entry.secret) { + secret = entry.secret; + } + const storageItem: OTPStorage = { account: entry.account, - encrypted: encryption.getEncryptionStatus(), + encrypted: Boolean(entry.encSecret), hash: entry.hash, index: entry.index, issuer: entry.issuer, type: OTPType[entry.type], counter: entry.counter, // TODO: Make this optional for non HOTP accounts - secret: encryption.getEncryptedSecret(entry) + secret }; if (entry.period && entry.period !== 30) { @@ -134,8 +147,11 @@ export class EntryStorage { return newData; } - /* tslint:disable-next-line:no-any */ - private static isOTPStorage(entry: any) { + private static isOTPStorage(entry: unknown) { + if (typeof entry !== "object") { + return false; + } + if (!entry || !entry.hasOwnProperty("secret")) { return false; } @@ -178,14 +194,39 @@ export class EntryStorage { ); } - static getExport(encryption: Encryption, encrypted?: boolean) { + static getExport(data: IOTPEntry[], encrypted?: boolean) { + try { + let exportData: { [hash: string]: OTPStorage } = {}; + for (const entry of data) { + if (!encrypted) { + if (!entry.secret) { + // Not unencrypted + } else { + exportData[entry.hash] = this.getOTPStorageFromEntry( + entry as OTPEntry, + true + ); + } + } else { + exportData[entry.hash] = this.getOTPStorageFromEntry( + entry as OTPEntry + ); + } + } + return exportData; + } catch (error) { + return error; + } + } + + static backupGetExport(encryption: Encryption, encrypted?: boolean) { return new Promise( ( resolve: (value: { [hash: string]: OTPStorage }) => void, reject: (reason: Error) => void ) => { try { - BrowserStorage.get((_data: { [hash: string]: OTPStorage }) => { + BrowserStorage.get(async (_data: { [hash: string]: OTPStorage }) => { for (const hash of Object.keys(_data)) { if (!this.isValidEntry(_data, hash)) { delete _data[hash]; @@ -194,7 +235,7 @@ export class EntryStorage { if (!encrypted) { // decrypt the data to export if (_data[hash].encrypted) { - const decryptedSecret = encryption.getDecryptedSecret( + const decryptedSecret = await encryption.getDecryptedSecret( _data[hash] ); if ( @@ -226,7 +267,7 @@ export class EntryStorage { return new Promise( (resolve: () => void, reject: (reason: Error) => void) => { try { - BrowserStorage.get((_data: { [hash: string]: OTPStorage }) => { + BrowserStorage.get(async (_data: { [hash: string]: OTPStorage }) => { for (const hash of Object.keys(data)) { // never trust data import from user // we do not support encrypted data import any longer @@ -284,9 +325,14 @@ export class EntryStorage { data[hash].type = OTPType[OTPType.hhex]; } - const _hash = CryptoJS.MD5(data[hash].secret).toString(); - // not a valid hash - if (!/^[0-9a-f]{32}$/.test(hash)) { + const _hash = await argon.hash(data[hash].secret); + + // not a valid / old hash + if ( + !/^\$argon2(?:d|i|di|id)\$v=(\d+)\$m=(\d+),t=(\d+),p=(\d+)\$([A-Za-z0-9+/=]+)\$([A-Za-z0-9+/=]*)$/.test( + hash + ) + ) { data[_hash] = data[hash]; data[_hash].hash = _hash; delete data[hash]; @@ -315,28 +361,22 @@ export class EntryStorage { ); } - static add(encryption: Encryption, entry: OTPEntry) { + static add(entry: OTPEntry) { return new Promise( (resolve: () => void, reject: (reason: Error) => void) => { try { - BrowserStorage.get((_data: { [hash: string]: OTPStorage }) => { - if (_data.hasOwnProperty(entry.hash)) { - throw new Error("The specific entry has already existed."); - } - const storageItem = this.getOTPStorageFromEntry(encryption, entry); - _data[entry.hash] = storageItem; - _data = this.ensureUniqueIndex(_data); - BrowserStorage.set(_data, resolve); - }); - return; + BrowserStorage.set( + { [entry.hash]: this.getOTPStorageFromEntry(entry) }, + resolve + ); } catch (error) { - return reject(error); + reject(error); } } ); } - static update(encryption: Encryption, entry: OTPEntry) { + static update(entry: OTPEntry) { return new Promise( (resolve: () => void, reject: (reason: Error) => void) => { try { @@ -344,7 +384,7 @@ export class EntryStorage { if (!_data.hasOwnProperty(entry.hash)) { throw new Error("Entry to change does not exist."); } - const storageItem = this.getOTPStorageFromEntry(encryption, entry); + const storageItem = this.getOTPStorageFromEntry(entry); _data[entry.hash] = storageItem; _data = this.ensureUniqueIndex(_data); BrowserStorage.set(_data, resolve); @@ -357,16 +397,13 @@ export class EntryStorage { ); } - static set(encryption: Encryption, entries: OTPEntry[]) { + static set(entries: OTPEntry[]) { return new Promise( (resolve: () => void, reject: (reason: Error) => void) => { try { BrowserStorage.get((_data: { [hash: string]: OTPStorage }) => { entries.forEach(entry => { - const storageItem = this.getOTPStorageFromEntry( - encryption, - entry - ); + const storageItem = this.getOTPStorageFromEntry(entry); _data[entry.hash] = storageItem; }); _data = this.ensureUniqueIndex(_data); @@ -380,7 +417,7 @@ export class EntryStorage { ); } - static get(encryption: Encryption) { + static get() { return new Promise( ( resolve: (value: OTPEntry[]) => void, @@ -389,21 +426,19 @@ export class EntryStorage { try { BrowserStorage.get(async (_data: { [hash: string]: OTPStorage }) => { const data: OTPEntry[] = []; + for (const hash of Object.keys(_data)) { if (!this.isValidEntry(_data, hash)) { continue; } const entryData = _data[hash]; - let needMigrate = false; if (!entryData.hash) { entryData.hash = hash; - needMigrate = true; } if (!entryData.type) { entryData.type = OTPType[OTPType.totp]; - needMigrate = true; } let type: OTPType; @@ -421,7 +456,6 @@ export class EntryStorage { // and save it type = OTPType.totp; entryData.type = OTPType[OTPType.totp]; - needMigrate = true; } let period = 30; @@ -444,26 +478,23 @@ export class EntryStorage { counter: entryData.counter, period }); - entry.applyEncryption(encryption); - data.push(entry); - if (entry.secret !== null && !/^[0-9a-f]{32}$/.test(hash)) { - const _hash = CryptoJS.MD5(entry.secret).toString(); - if (hash !== _hash) { - console.warn("Invalid hash:", entry); - } - } - } + data.push(entry); - data.sort((a, b) => { - return a.index - b.index; - }); + data.sort((a, b) => { + return a.index - b.index; + }); - for (let i = 0; i < data.length; i++) { - if (data[i].index !== i) { - const exportData = await this.getExport(encryption); - await this.import(encryption, exportData); - break; + if ( + entry.secret !== null && + !( + /^[0-9a-f]{32}$/.test(hash) || + /^\$argon2(?:d|i|di|id)\$v=(\d+)\$m=(\d+),t=(\d+),p=(\d+)\$([A-Za-z0-9+/=]+)\$([A-Za-z0-9+/=]*)$/.test( + hash + ) + ) + ) { + console.warn("Invalid hash:", entry); } } diff --git a/src/popup.ts b/src/popup.ts index 775d73210..0f92ab5df 100644 --- a/src/popup.ts +++ b/src/popup.ts @@ -16,6 +16,7 @@ import { Menu } from "./store/Menu"; import { Notification } from "./store/Notification"; import { Qr } from "./store/Qr"; import { Dropbox, Drive } from "./models/backup"; +import { EntryStorage } from "./models/storage"; async function init() { // Add globals @@ -53,8 +54,22 @@ async function init() { // Prompt for password if needed if (instance.$store.state.accounts.shouldShowPassphrase) { - instance.$store.commit("style/showInfo"); - instance.$store.commit("currentView/changeView", "EnterPasswordPage"); + instance.$store.commit("style/showInfo", true); + // If we have cached password, use that + if (instance.$store.state.accounts.encryption.getEncryptionStatus()) { + instance.$store.commit("currentView/changeView", "LoadingPage"); + for (const entry of instance.$store.state.accounts.entries) { + await entry.applyEncryption(instance.$store.state.accounts.encryption); + } + instance.$store.commit( + "accounts/updateExport", + await EntryStorage.getExport(instance.$store.state.accounts.entries) + ); + instance.$store.commit("accounts/updateCodes"); + instance.$store.commit("style/hideInfo", true); + } else { + instance.$store.commit("currentView/changeView", "EnterPasswordPage"); + } } // Set document title diff --git a/src/store/Accounts.ts b/src/store/Accounts.ts index dfff8d064..209c3f800 100644 --- a/src/store/Accounts.ts +++ b/src/store/Accounts.ts @@ -11,9 +11,7 @@ export class Accounts implements IModule { let shouldShowPassphrase = cachedPassphrase ? false : await EntryStorage.hasEncryptedEntry(); - const entries = shouldShowPassphrase - ? [] - : await this.getEntries(encryption); + const entries = shouldShowPassphrase ? [] : await this.getEntries(); for (let i = 0; i < entries.length; i++) { if (entries[i].code === "Encrypted") { @@ -34,8 +32,8 @@ export class Accounts implements IModule { filter: true, siteName: await this.getSiteName(), showSearch: false, - exportData: await EntryStorage.getExport(encryption), - exportEncData: await EntryStorage.getExport(encryption, true) + exportData: await EntryStorage.getExport(entries), + exportEncData: await EntryStorage.getExport(entries, true) }, getters: { shouldFilter( @@ -116,12 +114,6 @@ export class Accounts implements IModule { }, loadCodes(state: AccountsState, newCodes: IOTPEntry[]) { state.entries = newCodes; - - if (state.encryption.getEncryptionStatus()) { - for (const entry of state.entries) { - entry.applyEncryption(state.encryption); - } - } }, moveCode(state: AccountsState, opts: { from: number; to: number }) { state.entries.splice( @@ -150,6 +142,39 @@ export class Accounts implements IModule { } }, actions: { + deleteCode: async ( + state: ActionContext, + hash: string + ) => { + const index = state.state.entries.findIndex( + entry => entry.hash === hash + ); + if (index > -1) { + state.state.entries.splice(index, 1); + } + state.commit( + "updateExport", + await EntryStorage.getExport(state.state.entries) + ); + state.commit( + "updateEncExport", + await EntryStorage.getExport(state.state.entries, true) + ); + }, + addCode: async ( + state: ActionContext, + entry: IOTPEntry + ) => { + state.state.entries.unshift(entry); + state.commit( + "updateExport", + await EntryStorage.getExport(state.state.entries) + ); + state.commit( + "updateEncExport", + await EntryStorage.getExport(state.state.entries, true) + ); + }, applyPassphrase: async ( state: ActionContext, password: string @@ -158,9 +183,32 @@ export class Accounts implements IModule { return; } + state.commit("currentView/changeView", "LoadingPage", { root: true }); + state.state.encryption.updateEncryptionPassword(password); await state.dispatch("updateEntries"); - state.commit("style/hideInfo", null, { root: true }); + + // Migrate old hashes to argon2 + if (state.state.encryption.getEncryptionStatus()) { + let changedHash = false; + + for (const entry of state.state.entries) { + if ( + !/^\$argon2(?:d|i|di|id)\$v=(\d+)\$m=(\d+),t=(\d+),p=(\d+)\$([A-Za-z0-9+/=]+)\$([A-Za-z0-9+/=]*)$/.test( + entry.hash + ) + ) { + await entry.rehash(state.state.encryption); + changedHash = true; + } + } + + if (changedHash) { + await state.dispatch("updateEntries"); + } + } + + state.commit("style/hideInfo", true, { root: true }); if (!state.getters.currentlyEncrypted) { document.cookie = "passphrase=" + password; @@ -175,39 +223,41 @@ export class Accounts implements IModule { state: ActionContext, password: string ) => { - await EntryStorage.import( - new Encryption(password), - await EntryStorage.getExport(state.state.encryption as Encryption) - ); - state.state.encryption.updateEncryptionPassword(password); + document.cookie = "passphrase=" + password; chrome.runtime.sendMessage({ action: "cachePassphrase", value: password }); + for (const entry of state.state.entries) { + await entry.changeEncryption(state.state.encryption); + } + await state.dispatch("updateEntries"); // remove cached passphrase in old version localStorage.removeItem("encodedPhrase"); }, updateEntries: async (state: ActionContext) => { - state.commit( - "loadCodes", - await this.getEntries(state.state.encryption as Encryption) - ); + const entries = await this.getEntries(); + + if (state.state.encryption.getEncryptionStatus()) { + for (const entry of entries) { + await entry.applyEncryption(state.state.encryption as Encryption); + } + } + + state.commit("loadCodes", entries); state.commit("updateCodes"); state.commit( "updateExport", - await EntryStorage.getExport(state.state.encryption as Encryption) + await EntryStorage.getExport(state.state.entries) ); state.commit( "updateEncExport", - await EntryStorage.getExport( - state.state.encryption as Encryption, - true - ) + await EntryStorage.getExport(state.state.entries, true) ); return; }, @@ -379,8 +429,8 @@ export class Accounts implements IModule { ); } - private async getEntries(encryption: Encryption) { - const otpEntries = await EntryStorage.get(encryption); + private async getEntries() { + const otpEntries = await EntryStorage.get(); return otpEntries; } diff --git a/src/store/Style.ts b/src/store/Style.ts index 993bb3237..21a6002f8 100644 --- a/src/store/Style.ts +++ b/src/store/Style.ts @@ -9,6 +9,7 @@ export class Style implements IModule { slideout: false, // menu fadein: false, // info fadeout: false, // info + show: false, // info qrfadein: false, qrfadeout: false, notificationFadein: false, @@ -28,13 +29,21 @@ export class Style implements IModule { state.style.slideout = false; }, 200); }, - showInfo(state: StyleState) { - state.style.fadein = true; - state.style.fadeout = false; + showInfo(state: StyleState, noAnimate?: boolean) { + if (noAnimate) { + state.style.show = true; + } else { + state.style.fadein = true; + state.style.fadeout = false; + } }, - hideInfo(state: StyleState) { - state.style.fadein = false; - state.style.fadeout = true; + hideInfo(state: StyleState, noAnimate?: boolean) { + if (noAnimate) { + state.style.show = false; + } else { + state.style.fadein = false; + state.style.fadeout = true; + } setTimeout(() => { state.style.fadeout = false; }, 200); diff --git a/webpack.config.js b/webpack.config.js index 450109374..aaf0d809f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,25 +1,35 @@ -const path = require('path'); -const VueLoaderPlugin = require('vue-loader/lib/plugin'); -const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); +const path = require("path"); +const VueLoaderPlugin = require("vue-loader/lib/plugin"); +const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin"); module.exports = { - mode: 'development', - devtool: 'source-map', + mode: "development", + devtool: "source-map", entry: { - background: './src/background.ts', - content: './src/content.ts', - popup: './src/popup.ts', - import: './src/import.ts', - qr: './src/qr.ts', - qrdebug: './src/qrdebug.ts', - test: './src/test/test.ts' + background: "./src/background.ts", + content: "./src/content.ts", + popup: "./src/popup.ts", + import: "./src/import.ts", + qr: "./src/qr.ts", + qrdebug: "./src/qrdebug.ts", + test: "./src/test/test.ts" + }, + // For argon2-browser + node: { + fs: "empty" }, module: { rules: [ + { + // argon2-browser overrides + test: /\.wasm$/, + loader: "base64-loader", + type: "javascript/auto" + }, { test: /\.tsx?$/, - loader: 'ts-loader', - options: { + loader: "ts-loader", + options: { appendTsSuffixTo: [/\.vue$/], transpileOnly: true }, @@ -27,38 +37,35 @@ module.exports = { }, { test: /\.vue$/, - loader: 'vue-loader' + loader: "vue-loader" }, { test: /\.svg$/, - loader: 'vue-svg-loader' + loader: "vue-svg-loader" } ] }, plugins: [ new VueLoaderPlugin(), - new ForkTsCheckerWebpackPlugin( - { - vue: true - } - ) + new ForkTsCheckerWebpackPlugin({ + vue: true + }) ], resolve: { extensions: [ - '.mjs', - '.js', - '.jsx', - '.vue', - '.json', - '.wasm', - '.ts', - '.tsx' + ".mjs", + ".js", + ".jsx", + ".vue", + ".json", + ".wasm", + ".ts", + ".tsx" ], - modules: [ - 'node_modules' - ] + modules: ["node_modules"] }, output: { - path: path.resolve(__dirname, 'dist') + path: path.resolve(__dirname, "dist"), + publicPath: "/dist/" } };