diff --git a/CHANGELOG.md b/CHANGELOG.md index 847b3d1be..d95976903 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,298 @@ +Changes in [2.4.2](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.4.2) (2019-10-18) +================================================================================================ +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.4.2-rc.1...v2.4.2) + + * No changes since v2.4.2-rc.1 + +Changes in [2.4.2-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.4.2-rc.1) (2019-10-09) +========================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.4.1...v2.4.2-rc.1) + + * Log state of Olm sessions + [\#1047](https://github.com/matrix-org/matrix-js-sdk/pull/1047) + * Add method to get access to all timelines + [\#1048](https://github.com/matrix-org/matrix-js-sdk/pull/1048) + +Changes in [2.4.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.4.1) (2019-10-01) +================================================================================================ +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.4.0...v2.4.1) + + * Upgrade deps + [\#1046](https://github.com/matrix-org/matrix-js-sdk/pull/1046) + * Ignore crypto events with no content + [\#1043](https://github.com/matrix-org/matrix-js-sdk/pull/1043) + +Changes in [2.4.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.4.0) (2019-09-27) +================================================================================================ +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.4.0-rc.1...v2.4.0) + + * Clean Yarn cache during release + [\#1045](https://github.com/matrix-org/matrix-js-sdk/pull/1045) + +Changes in [2.4.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.4.0-rc.1) (2019-09-25) +========================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.3.2...v2.4.0-rc.1) + + * Remove id_server from creds for interactive auth + [\#1044](https://github.com/matrix-org/matrix-js-sdk/pull/1044) + * Remove IS details from requestToken to HS + [\#1041](https://github.com/matrix-org/matrix-js-sdk/pull/1041) + * Add support for sending MSISDN tokens to alternate URLs + [\#1040](https://github.com/matrix-org/matrix-js-sdk/pull/1040) + * Add separate 3PID add and bind APIs + [\#1038](https://github.com/matrix-org/matrix-js-sdk/pull/1038) + * Bump eslint-utils from 1.4.0 to 1.4.2 + [\#1037](https://github.com/matrix-org/matrix-js-sdk/pull/1037) + * Handle WebRTC security errors as non-fatal + [\#1036](https://github.com/matrix-org/matrix-js-sdk/pull/1036) + * Check for r0.6.0 support in addition to unstable feature flags + [\#1035](https://github.com/matrix-org/matrix-js-sdk/pull/1035) + * Update room members on member event redaction + [\#1030](https://github.com/matrix-org/matrix-js-sdk/pull/1030) + * Support hidden read receipts + [\#1028](https://github.com/matrix-org/matrix-js-sdk/pull/1028) + * Do 3pid lookups in lowercase + [\#1029](https://github.com/matrix-org/matrix-js-sdk/pull/1029) + * Add Synapse admin functions for deactivating a user + [\#1027](https://github.com/matrix-org/matrix-js-sdk/pull/1027) + * Fix addPendingEvent with pending event order == chronological + [\#1026](https://github.com/matrix-org/matrix-js-sdk/pull/1026) + * Add AutoDiscovery.getRawClientConfig() for easy .well-known lookups + [\#1024](https://github.com/matrix-org/matrix-js-sdk/pull/1024) + * Don't convert errors to JSON if they are JSON already + [\#1025](https://github.com/matrix-org/matrix-js-sdk/pull/1025) + * Send id_access_token to HS for use in proxied IS requests + [\#1022](https://github.com/matrix-org/matrix-js-sdk/pull/1022) + * Clean up JSON handling in identity server requests + [\#1023](https://github.com/matrix-org/matrix-js-sdk/pull/1023) + * Use the v2 (hashed) lookup for identity server queries + [\#1021](https://github.com/matrix-org/matrix-js-sdk/pull/1021) + * Add getIdServer() & doesServerRequireIdServerParam() + [\#1018](https://github.com/matrix-org/matrix-js-sdk/pull/1018) + * Make requestToken endpoints work without ID Server + [\#1019](https://github.com/matrix-org/matrix-js-sdk/pull/1019) + * Fix setIdentityServer + [\#1016](https://github.com/matrix-org/matrix-js-sdk/pull/1016) + * Change ICE fallback server and make fallback opt-in + [\#1015](https://github.com/matrix-org/matrix-js-sdk/pull/1015) + * Throw an exception if trying to do an ID server request with no ID server + [\#1014](https://github.com/matrix-org/matrix-js-sdk/pull/1014) + * Add setIdentityServerUrl + [\#1013](https://github.com/matrix-org/matrix-js-sdk/pull/1013) + * Add matrix base API to report an event + [\#1011](https://github.com/matrix-org/matrix-js-sdk/pull/1011) + * Fix POST body for v2 IS requests + [\#1010](https://github.com/matrix-org/matrix-js-sdk/pull/1010) + * Add API for bulk lookup on the Identity Server + [\#1009](https://github.com/matrix-org/matrix-js-sdk/pull/1009) + * Remove deprecated authedRequestWithPrefix and requestWithPrefix + [\#1000](https://github.com/matrix-org/matrix-js-sdk/pull/1000) + * Add API for checking IS account info + [\#1007](https://github.com/matrix-org/matrix-js-sdk/pull/1007) + * Support rewriting push rules when our internal defaults change + [\#1006](https://github.com/matrix-org/matrix-js-sdk/pull/1006) + * Upgrade dependencies + [\#1005](https://github.com/matrix-org/matrix-js-sdk/pull/1005) + +Changes in [2.3.2](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.3.2) (2019-09-16) +================================================================================================ +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.3.2-rc.1...v2.3.2) + + * [Release] Fix addPendingEvent with pending event order == chronological + [\#1034](https://github.com/matrix-org/matrix-js-sdk/pull/1034) + +Changes in [2.3.2-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.3.2-rc.1) (2019-09-13) +========================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.3.1...v2.3.2-rc.1) + + * Synapse admin functions to release + [\#1033](https://github.com/matrix-org/matrix-js-sdk/pull/1033) + * [To Release] Add matrix base API to report an event + [\#1032](https://github.com/matrix-org/matrix-js-sdk/pull/1032) + +Changes in [2.3.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.3.1) (2019-09-12) +================================================================================================ +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.3.1-rc.1...v2.3.1) + + * No changes since rc.1 + +Changes in [2.3.1-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.3.1-rc.1) (2019-09-11) +========================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.3.0...v2.3.1-rc.1) + + * Update room members on member event redaction + [\#1031](https://github.com/matrix-org/matrix-js-sdk/pull/1031) + +Changes in [2.3.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.3.0) (2019-08-05) +================================================================================================ +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.3.0-rc.1...v2.3.0) + + * [release] Support rewriting push rules when our internal defaults change + [\#1008](https://github.com/matrix-org/matrix-js-sdk/pull/1008) + +Changes in [2.3.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.3.0-rc.1) (2019-07-31) +========================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.2.0...v2.3.0-rc.1) + + * Add support for IS v2 API with authentication + [\#1002](https://github.com/matrix-org/matrix-js-sdk/pull/1002) + * Tombstone bugfixes + [\#1001](https://github.com/matrix-org/matrix-js-sdk/pull/1001) + * Support for MSC2140 (terms of service for IS/IM) + [\#988](https://github.com/matrix-org/matrix-js-sdk/pull/988) + * Add a request method to /devices + [\#994](https://github.com/matrix-org/matrix-js-sdk/pull/994) + +Changes in [2.2.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.2.0) (2019-07-18) +================================================================================================ +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.2.0-rc.2...v2.2.0) + + * Upgrade lodash dependencies + +Changes in [2.2.0-rc.2](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.2.0-rc.2) (2019-07-12) +========================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.2.0-rc.1...v2.2.0-rc.2) + + * Fix regression from 2.2.0-rc.1 in request to /devices + [\#995](https://github.com/matrix-org/matrix-js-sdk/pull/995) + +Changes in [2.2.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.2.0-rc.1) (2019-07-12) +========================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.1.1...v2.2.0-rc.1) + + * End the verification timer when verification is done + [\#993](https://github.com/matrix-org/matrix-js-sdk/pull/993) + * Stabilize usage of stably stable APIs (in a stable way) + [\#990](https://github.com/matrix-org/matrix-js-sdk/pull/990) + * Expose original_event for /relations + [\#987](https://github.com/matrix-org/matrix-js-sdk/pull/987) + * Process ephemeral events outside timeline handling + [\#989](https://github.com/matrix-org/matrix-js-sdk/pull/989) + * Don't accept any locally known edits earlier than the last known server-side + aggregated edit + [\#986](https://github.com/matrix-org/matrix-js-sdk/pull/986) + * Get edit date transparently from server aggregations or local echo + [\#984](https://github.com/matrix-org/matrix-js-sdk/pull/984) + * Add a function to flag keys for backup without scheduling a backup + [\#982](https://github.com/matrix-org/matrix-js-sdk/pull/982) + * Block read marker and read receipt from advancing into pending events + [\#981](https://github.com/matrix-org/matrix-js-sdk/pull/981) + * Upgrade dependencies + [\#977](https://github.com/matrix-org/matrix-js-sdk/pull/977) + * Add default push rule to ignore reactions + [\#976](https://github.com/matrix-org/matrix-js-sdk/pull/976) + * Fix exception whilst syncing + [\#979](https://github.com/matrix-org/matrix-js-sdk/pull/979) + * Include the error object when raising Session.logged_out + [\#975](https://github.com/matrix-org/matrix-js-sdk/pull/975) + +Changes in [2.1.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.1.1) (2019-07-11) +================================================================================================ +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.1.0...v2.1.1) + + * Process emphemeral events outside timeline handling + [\#989](https://github.com/matrix-org/matrix-js-sdk/pull/989) + +Changes in [2.1.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.1.0) (2019-07-08) +================================================================================================ +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.1.0-rc.1...v2.1.0) + + * Fix exception whilst syncing + [\#979](https://github.com/matrix-org/matrix-js-sdk/pull/979) + +Changes in [2.1.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.1.0-rc.1) (2019-07-03) +========================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.0.1...v2.1.0-rc.1) + + * Handle self read receipts for fixing e2e notification counts + [\#974](https://github.com/matrix-org/matrix-js-sdk/pull/974) + * Add redacts field to event.toJSON + [\#973](https://github.com/matrix-org/matrix-js-sdk/pull/973) + * Handle associated event send failures + [\#972](https://github.com/matrix-org/matrix-js-sdk/pull/972) + * Remove irrelevant debug line from timeline handling + [\#971](https://github.com/matrix-org/matrix-js-sdk/pull/971) + * Handle relations in encrypted rooms + [\#969](https://github.com/matrix-org/matrix-js-sdk/pull/969) + * Relations endpoint support + [\#967](https://github.com/matrix-org/matrix-js-sdk/pull/967) + * Disable event encryption for reactions + [\#968](https://github.com/matrix-org/matrix-js-sdk/pull/968) + * Change the known safe room version to version 4 + [\#966](https://github.com/matrix-org/matrix-js-sdk/pull/966) + * Check for lazy-loading support in the spec versions instead + [\#965](https://github.com/matrix-org/matrix-js-sdk/pull/965) + * Use camelCase instead of underscore + [\#963](https://github.com/matrix-org/matrix-js-sdk/pull/963) + * Time out verification attempts after 10 minutes of inactivity + [\#961](https://github.com/matrix-org/matrix-js-sdk/pull/961) + * Don't handle key verification requests which are immediately cancelled + [\#962](https://github.com/matrix-org/matrix-js-sdk/pull/962) + +Changes in [2.0.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.0.1) (2019-06-19) +================================================================================================ +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.0.1-rc.2...v2.0.1) + + No changes since rc.2 + +Changes in [2.0.1-rc.2](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.0.1-rc.2) (2019-06-18) +========================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.0.1-rc.1...v2.0.1-rc.2) + + * return 'sending' status for an event that is only locally redacted + [\#960](https://github.com/matrix-org/matrix-js-sdk/pull/960) + * Key verification request fixes + [\#954](https://github.com/matrix-org/matrix-js-sdk/pull/954) + * Add flag to force saving sync store + [\#956](https://github.com/matrix-org/matrix-js-sdk/pull/956) + * Expose the inhibit_login flag to register + [\#953](https://github.com/matrix-org/matrix-js-sdk/pull/953) + * Support redactions and relations of/with unsent events. + [\#947](https://github.com/matrix-org/matrix-js-sdk/pull/947) + +Changes in [2.0.1-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.0.1-rc.1) (2019-06-12) +========================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v2.0.0...v2.0.1-rc.1) + + * Fix content uploads for modern browsers + [\#952](https://github.com/matrix-org/matrix-js-sdk/pull/952) + * Don't overlap auth submissions with polls + [\#951](https://github.com/matrix-org/matrix-js-sdk/pull/951) + * Add funding details for GitHub sponsor button + [\#945](https://github.com/matrix-org/matrix-js-sdk/pull/945) + * Fix backup sig validation with multiple sigs + [\#944](https://github.com/matrix-org/matrix-js-sdk/pull/944) + * Don't send another token request while one's in flight + [\#943](https://github.com/matrix-org/matrix-js-sdk/pull/943) + * Don't poll UI auth again until current poll finishes + [\#942](https://github.com/matrix-org/matrix-js-sdk/pull/942) + * Provide the discovered URLs when a liveliness error occurs + [\#938](https://github.com/matrix-org/matrix-js-sdk/pull/938) + * Encode event IDs when redacting events + [\#941](https://github.com/matrix-org/matrix-js-sdk/pull/941) + * add missing logger + [\#940](https://github.com/matrix-org/matrix-js-sdk/pull/940) + * verification: don't error if we don't know about some keys + [\#939](https://github.com/matrix-org/matrix-js-sdk/pull/939) + * Local echo for redactions + [\#937](https://github.com/matrix-org/matrix-js-sdk/pull/937) + * Refresh safe room versions when the server looks more modern than us + [\#934](https://github.com/matrix-org/matrix-js-sdk/pull/934) + * Add v4 as a safe room version + [\#935](https://github.com/matrix-org/matrix-js-sdk/pull/935) + * Disable guard-for-in rule + [\#933](https://github.com/matrix-org/matrix-js-sdk/pull/933) + * Extend loglevel logging for the whole project + [\#924](https://github.com/matrix-org/matrix-js-sdk/pull/924) + * fix(login): saves access_token and user_id after login for all login types + [\#930](https://github.com/matrix-org/matrix-js-sdk/pull/930) + * Do not try to request thumbnails with non-integer sizes + [\#929](https://github.com/matrix-org/matrix-js-sdk/pull/929) + * Revert "Add a bunch of debugging to .well-known IS validation" + [\#928](https://github.com/matrix-org/matrix-js-sdk/pull/928) + * Add a bunch of debugging to .well-known IS validation + [\#927](https://github.com/matrix-org/matrix-js-sdk/pull/927) + Changes in [2.0.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v2.0.0) (2019-05-31) ================================================================================================ [Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v1.2.0...v2.0.0) diff --git a/README.md b/README.md index 0504eabcc..9081598dd 100644 --- a/README.md +++ b/README.md @@ -322,13 +322,13 @@ To provide the Olm library in a browser application: To provide the Olm library in a node.js application: - * ``yarn add https://packages.matrix.org/npm/olm/olm-3.0.0.tgz`` + * ``yarn add https://packages.matrix.org/npm/olm/olm-3.1.4.tgz`` (replace the URL with the latest version you want to use from https://packages.matrix.org/npm/olm/) * ``global.Olm = require('olm');`` *before* loading ``matrix-js-sdk``. If you want to package Olm as dependency for your node.js application, you can -use ``yarn add https://packages.matrix.org/npm/olm/olm-3.0.0.tgz``. If your +use ``yarn add https://packages.matrix.org/npm/olm/olm-3.1.4.tgz``. If your application also works without e2e crypto enabled, add ``--optional`` to mark it as an optional dependency. diff --git a/package.json b/package.json index f6dfca937..c0539baf1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-js-sdk", - "version": "2.0.0", + "version": "2.4.2", "description": "Matrix Client-Server SDK for Javascript", "main": "index.js", "scripts": { @@ -17,7 +17,7 @@ "build": "babel -s -d lib src && rimraf dist && mkdir dist && browserify -d browser-index.js | exorcist dist/browser-matrix.js.map > dist/browser-matrix.js && terser -c -m -o dist/browser-matrix.min.js --source-map \"content='dist/browser-matrix.js.map'\" dist/browser-matrix.js", "dist": "yarn build", "watch": "watchify -d browser-index.js -o 'exorcist dist/browser-matrix.js.map > dist/browser-matrix.js' -v", - "lint": "eslint --max-warnings 101 src spec", + "lint": "eslint --max-warnings 93 src spec", "prepare": "yarn clean && yarn build && git rev-parse HEAD > git-revision.txt" }, "repository": { @@ -54,11 +54,11 @@ "dependencies": { "another-json": "^0.2.0", "babel-runtime": "^6.26.0", - "bluebird": "^3.5.0", + "bluebird": "3.5.5", "browser-request": "^0.3.3", "bs58": "^4.0.1", "content-type": "^1.0.2", - "loglevel": "1.6.1", + "loglevel": "^1.6.4", "qs": "^6.5.2", "request": "^2.88.0", "unhomoglyph": "^1.0.2" @@ -76,19 +76,19 @@ "eslint": "^5.12.0", "eslint-config-google": "^0.7.1", "eslint-plugin-babel": "^5.3.0", - "exorcist": "^0.4.0", + "exorcist": "^1.0.1", "expect": "^1.20.2", "istanbul": "^0.4.5", "jsdoc": "^3.5.5", "lolex": "^1.5.2", "matrix-mock-request": "^1.2.3", - "mocha": "^5.2.0", + "mocha": "^6.2.1", "mocha-jenkins-reporter": "^0.4.0", - "olm": "https://packages.matrix.org/npm/olm/olm-3.1.0.tgz", - "rimraf": "^2.5.4", - "source-map-support": "^0.4.11", - "sourceify": "^0.1.0", - "terser": "^4.0.0", + "olm": "https://packages.matrix.org/npm/olm/olm-3.1.4.tgz", + "rimraf": "^3.0.0", + "source-map-support": "^0.5.13", + "sourceify": "^1.0.0", + "terser": "^4.3.8", "watchify": "^3.11.1" }, "browserify": { diff --git a/release.sh b/release.sh index 3ff018c67..702e88cc3 100755 --- a/release.sh +++ b/release.sh @@ -195,6 +195,11 @@ if [ $dodist -eq 0 ]; then pushd "$builddir" git clone "$projdir" . git checkout "$rel_branch" + # We use Git branch / commit dependencies for some packages, and Yarn seems + # to have a hard time getting that right. See also + # https://github.com/yarnpkg/yarn/issues/4734. As a workaround, we clean the + # global cache here to ensure we get the right thing. + yarn cache clean yarn install # We haven't tagged yet, so tell the dist script what version # it's building diff --git a/spec/integ/matrix-client-event-emitter.spec.js b/spec/integ/matrix-client-event-emitter.spec.js index 93f4fbce4..9f7b028eb 100644 --- a/spec/integ/matrix-client-event-emitter.spec.js +++ b/spec/integ/matrix-client-event-emitter.spec.js @@ -302,11 +302,32 @@ describe("MatrixClient events", function() { }); it("should emit Session.logged_out on M_UNKNOWN_TOKEN", function() { - httpBackend.when("GET", "/sync").respond(401, { errcode: 'M_UNKNOWN_TOKEN' }); + const error = { errcode: 'M_UNKNOWN_TOKEN' }; + httpBackend.when("GET", "/sync").respond(401, error); let sessionLoggedOutCount = 0; - client.on("Session.logged_out", function(event, member) { + client.on("Session.logged_out", function(errObj) { sessionLoggedOutCount++; + expect(errObj.data).toEqual(error); + }); + + client.startClient(); + + return httpBackend.flushAllExpected().then(function() { + expect(sessionLoggedOutCount).toEqual( + 1, "Session.logged_out fired wrong number of times", + ); + }); + }); + + it("should emit Session.logged_out on M_UNKNOWN_TOKEN (soft logout)", function() { + const error = { errcode: 'M_UNKNOWN_TOKEN', soft_logout: true }; + httpBackend.when("GET", "/sync").respond(401, error); + + let sessionLoggedOutCount = 0; + client.on("Session.logged_out", function(errObj) { + sessionLoggedOutCount++; + expect(errObj.data).toEqual(error); }); client.startClient(); diff --git a/spec/integ/matrix-client-methods.spec.js b/spec/integ/matrix-client-methods.spec.js index 4c2b3c058..55bf119f6 100644 --- a/spec/integ/matrix-client-methods.spec.js +++ b/spec/integ/matrix-client-methods.spec.js @@ -48,7 +48,7 @@ describe("MatrixClient", function() { const buf = new Buffer('hello world'); it("should upload the file", function(done) { httpBackend.when( - "POST", "/_matrix/media/v1/upload", + "POST", "/_matrix/media/r0/upload", ).check(function(req) { expect(req.rawData).toEqual(buf); expect(req.queryParams.filename).toEqual("hi.txt"); @@ -87,7 +87,7 @@ describe("MatrixClient", function() { it("should parse the response if rawResponse=false", function(done) { httpBackend.when( - "POST", "/_matrix/media/v1/upload", + "POST", "/_matrix/media/r0/upload", ).check(function(req) { expect(req.opts.json).toBeFalsy(); }).respond(200, { "content_uri": "uri" }); @@ -107,7 +107,7 @@ describe("MatrixClient", function() { it("should parse errors into a MatrixError", function(done) { httpBackend.when( - "POST", "/_matrix/media/v1/upload", + "POST", "/_matrix/media/r0/upload", ).check(function(req) { expect(req.rawData).toEqual(buf); expect(req.opts.json).toBeFalsy(); @@ -396,7 +396,7 @@ describe("MatrixClient", function() { const auth = {a: 1}; it("should pass through an auth dict", function(done) { httpBackend.when( - "DELETE", "/_matrix/client/unstable/devices/my_device", + "DELETE", "/_matrix/client/r0/devices/my_device", ).check(function(req) { expect(req.data).toEqual({auth: auth}); }).respond(200); diff --git a/spec/unit/content-repo.spec.js b/spec/unit/content-repo.spec.js index b1a97f681..61b6fceb1 100644 --- a/spec/unit/content-repo.spec.js +++ b/spec/unit/content-repo.spec.js @@ -31,7 +31,7 @@ describe("ContentRepo", function() { function() { const mxcUri = "mxc://server.name/resourceid"; expect(ContentRepo.getHttpUriForMxc(baseUrl, mxcUri)).toEqual( - baseUrl + "/_matrix/media/v1/download/server.name/resourceid", + baseUrl + "/_matrix/media/r0/download/server.name/resourceid", ); }); @@ -43,7 +43,7 @@ describe("ContentRepo", function() { function() { const mxcUri = "mxc://server.name/resourceid"; expect(ContentRepo.getHttpUriForMxc(baseUrl, mxcUri, 32, 64, "crop")).toEqual( - baseUrl + "/_matrix/media/v1/thumbnail/server.name/resourceid" + + baseUrl + "/_matrix/media/r0/thumbnail/server.name/resourceid" + "?width=32&height=64&method=crop", ); }); @@ -52,7 +52,7 @@ describe("ContentRepo", function() { function() { const mxcUri = "mxc://server.name/resourceid#automade"; expect(ContentRepo.getHttpUriForMxc(baseUrl, mxcUri, 32)).toEqual( - baseUrl + "/_matrix/media/v1/thumbnail/server.name/resourceid" + + baseUrl + "/_matrix/media/r0/thumbnail/server.name/resourceid" + "?width=32#automade", ); }); @@ -61,7 +61,7 @@ describe("ContentRepo", function() { function() { const mxcUri = "mxc://server.name/resourceid#automade"; expect(ContentRepo.getHttpUriForMxc(baseUrl, mxcUri)).toEqual( - baseUrl + "/_matrix/media/v1/download/server.name/resourceid#automade", + baseUrl + "/_matrix/media/r0/download/server.name/resourceid#automade", ); }); }); @@ -73,21 +73,21 @@ describe("ContentRepo", function() { it("should set w/h by default to 96", function() { expect(ContentRepo.getIdenticonUri(baseUrl, "foobar")).toEqual( - baseUrl + "/_matrix/media/v1/identicon/foobar" + + baseUrl + "/_matrix/media/unstable/identicon/foobar" + "?width=96&height=96", ); }); it("should be able to set custom w/h", function() { expect(ContentRepo.getIdenticonUri(baseUrl, "foobar", 32, 64)).toEqual( - baseUrl + "/_matrix/media/v1/identicon/foobar" + + baseUrl + "/_matrix/media/unstable/identicon/foobar" + "?width=32&height=64", ); }); it("should URL encode the identicon string", function() { expect(ContentRepo.getIdenticonUri(baseUrl, "foo#bar", 32, 64)).toEqual( - baseUrl + "/_matrix/media/v1/identicon/foo%23bar" + + baseUrl + "/_matrix/media/unstable/identicon/foo%23bar" + "?width=32&height=64", ); }); diff --git a/spec/unit/crypto/verification/request.spec.js b/spec/unit/crypto/verification/request.spec.js index a53d58002..355597d04 100644 --- a/spec/unit/crypto/verification/request.spec.js +++ b/spec/unit/crypto/verification/request.spec.js @@ -69,8 +69,14 @@ describe("verification request", function() { bob.client.on("crypto.verification.request", (request) => { const bobVerifier = request.beginKeyVerification(verificationMethods.SAS); bobVerifier.verify(); + + // XXX: Private function access (but it's a test, so we're okay) + bobVerifier._endTimer(); }); const aliceVerifier = await alice.client.requestVerification("@bob:example.com"); expect(aliceVerifier).toBeAn(SAS); + + // XXX: Private function access (but it's a test, so we're okay) + aliceVerifier._endTimer(); }); }); diff --git a/spec/unit/crypto/verification/sas.spec.js b/spec/unit/crypto/verification/sas.spec.js index 8f64304ef..d26ec3be2 100644 --- a/spec/unit/crypto/verification/sas.spec.js +++ b/spec/unit/crypto/verification/sas.spec.js @@ -60,6 +60,9 @@ describe("SAS verification", function() { await sas.verify() .catch(spy); expect(spy).toHaveBeenCalled(); + + // Cancel the SAS for cleanup (we started a verification, so abort) + sas.cancel(); }); describe("verification", function() { @@ -370,4 +373,127 @@ describe("SAS verification", function() { expect(bob.client.setDeviceVerified) .toNotHaveBeenCalled(); }); + + describe("verification in DM", function() { + let alice; + let bob; + let aliceSasEvent; + let bobSasEvent; + let aliceVerifier; + let bobPromise; + + beforeEach(async function() { + [alice, bob] = await makeTestClients( + [ + {userId: "@alice:example.com", deviceId: "Osborne2"}, + {userId: "@bob:example.com", deviceId: "Dynabook"}, + ], + { + verificationMethods: [verificationMethods.SAS], + }, + ); + + alice.setDeviceVerified = expect.createSpy(); + alice.getDeviceEd25519Key = () => { + return "alice+base64+ed25519+key"; + }; + alice.getStoredDevice = () => { + return DeviceInfo.fromStorage( + { + keys: { + "ed25519:Dynabook": "bob+base64+ed25519+key", + }, + }, + "Dynabook", + ); + }; + alice.downloadKeys = () => { + return Promise.resolve(); + }; + + bob.setDeviceVerified = expect.createSpy(); + bob.getStoredDevice = () => { + return DeviceInfo.fromStorage( + { + keys: { + "ed25519:Osborne2": "alice+base64+ed25519+key", + }, + }, + "Osborne2", + ); + }; + bob.getDeviceEd25519Key = () => { + return "bob+base64+ed25519+key"; + }; + bob.downloadKeys = () => { + return Promise.resolve(); + }; + + aliceSasEvent = null; + bobSasEvent = null; + + bobPromise = new Promise((resolve, reject) => { + bob.on("event", async (event) => { + const content = event.getContent(); + if (event.getType() === "m.room.message" + && content.msgtype === "m.key.verification.request") { + expect(content.methods).toInclude(SAS.NAME); + expect(content.to).toBe(bob.getUserId()); + const verifier = bob.acceptVerificationDM(event, SAS.NAME); + verifier.on("show_sas", (e) => { + if (!e.sas.emoji || !e.sas.decimal) { + e.cancel(); + } else if (!aliceSasEvent) { + bobSasEvent = e; + } else { + try { + expect(e.sas).toEqual(aliceSasEvent.sas); + e.confirm(); + aliceSasEvent.confirm(); + } catch (error) { + e.mismatch(); + aliceSasEvent.mismatch(); + } + } + }); + await verifier.verify(); + resolve(); + } + }); + }); + + aliceVerifier = await alice.requestVerificationDM( + bob.getUserId(), "!room_id", [verificationMethods.SAS], + ); + aliceVerifier.on("show_sas", (e) => { + if (!e.sas.emoji || !e.sas.decimal) { + e.cancel(); + } else if (!bobSasEvent) { + aliceSasEvent = e; + } else { + try { + expect(e.sas).toEqual(bobSasEvent.sas); + e.confirm(); + bobSasEvent.confirm(); + } catch (error) { + e.mismatch(); + bobSasEvent.mismatch(); + } + } + }); + }); + + it("should verify a key", async function() { + await Promise.all([ + aliceVerifier.verify(), + bobPromise, + ]); + + // make sure Alice and Bob verified each other + expect(alice.setDeviceVerified) + .toHaveBeenCalledWith(bob.getUserId(), bob.deviceId); + expect(bob.setDeviceVerified) + .toHaveBeenCalledWith(alice.getUserId(), alice.deviceId); + }); + }); }); diff --git a/spec/unit/crypto/verification/util.js b/spec/unit/crypto/verification/util.js index 79247dd1a..d12b0462a 100644 --- a/spec/unit/crypto/verification/util.js +++ b/spec/unit/crypto/verification/util.js @@ -48,6 +48,25 @@ export async function makeTestClients(userInfos, options) { } } }; + const sendEvent = function(room, type, content) { + // make up a unique ID as the event ID + const eventId = "$" + this.makeTxnId(); // eslint-disable-line babel/no-invalid-this + const event = new MatrixEvent({ + sender: this.getUserId(), // eslint-disable-line babel/no-invalid-this + type: type, + content: content, + room_id: room, + event_id: eventId, + }); + for (const client of clients) { + setTimeout( + () => client.emit("event", event), + 0, + ); + } + + return {event_id: eventId}; + }; for (const userInfo of userInfos) { const testClient = new TestClient( @@ -59,6 +78,7 @@ export async function makeTestClients(userInfos, options) { } clientMap[userInfo.userId][userInfo.deviceId] = testClient.client; testClient.client.sendToDevice = sendToDevice; + testClient.client.sendEvent = sendEvent; clients.push(testClient); } diff --git a/spec/unit/matrix-client.spec.js b/spec/unit/matrix-client.spec.js index 5d870754d..029ae1bb5 100644 --- a/spec/unit/matrix-client.spec.js +++ b/spec/unit/matrix-client.spec.js @@ -154,12 +154,9 @@ describe("MatrixClient", function() { }); // FIXME: We shouldn't be yanking _http like this. client._http = [ - "authedRequest", "authedRequestWithPrefix", "getContentUri", - "request", "requestWithPrefix", "uploadContent", + "authedRequest", "getContentUri", "request", "uploadContent", ].reduce((r, k) => { r[k] = expect.createSpy(); return r; }, {}); client._http.authedRequest.andCall(httpReq); - client._http.authedRequestWithPrefix.andCall(httpReq); - client._http.requestWithPrefix.andCall(httpReq); client._http.request.andCall(httpReq); // set reasonable working defaults @@ -181,9 +178,6 @@ describe("MatrixClient", function() { client._http.authedRequest.andCall(function() { return Promise.defer().promise; }); - client._http.authedRequestWithPrefix.andCall(function() { - return Promise.defer().promise; - }); }); it("should not POST /filter if a matching filter already exists", async function() { diff --git a/spec/unit/room.spec.js b/spec/unit/room.spec.js index a809dd6ee..b257ec637 100644 --- a/spec/unit/room.spec.js +++ b/spec/unit/room.spec.js @@ -104,7 +104,7 @@ describe("Room", function() { user_ids: [userA], }, }); - room.addLiveEvents([typing]); + room.addEphemeralEvents([typing]); expect(room.currentState.setTypingEvent).toHaveBeenCalledWith(typing); }); diff --git a/src/ReEmitter.js b/src/ReEmitter.js index 51a4ab3b2..4ddf3229a 100644 --- a/src/ReEmitter.js +++ b/src/ReEmitter.js @@ -34,12 +34,18 @@ export default class Reemitter { } reEmit(source, eventNames) { + // We include the source as the last argument for event handlers which may need it, + // such as read receipt listeners on the client class which won't have the context + // of the room. + const forSource = (handler, ...args) => { + handler(...args, source); + }; for (const eventName of eventNames) { if (this.boundHandlers[eventName] === undefined) { this.boundHandlers[eventName] = this._handleEvent.bind(this, eventName); } - const boundHandler = this.boundHandlers[eventName]; + const boundHandler = forSource.bind(this, this.boundHandlers[eventName]); source.on(eventName, boundHandler); } } diff --git a/src/autodiscovery.js b/src/autodiscovery.js index 900c01663..df52b368b 100644 --- a/src/autodiscovery.js +++ b/src/autodiscovery.js @@ -429,6 +429,26 @@ export class AutoDiscovery { return AutoDiscovery.fromDiscoveryConfig(wellknown.raw); } + /** + * Gets the raw discovery client configuration for the given domain name. + * Should only be used if there's no validation to be done on the resulting + * object, otherwise use findClientConfig(). + * @param {string} domain The domain to get the client config for. + * @returns {Promise} Resolves to the domain's client config. Can + * be an empty object. + */ + static async getRawClientConfig(domain) { + if (!domain || typeof(domain) !== "string" || domain.length === 0) { + throw new Error("'domain' must be a string of non-zero length"); + } + + const response = await this._fetchWellKnownObject( + `https://${domain}/.well-known/matrix/client`, + ); + if (!response) return {}; + return response.raw || {}; + } + /** * Sanitizes a given URL to ensure it is either an HTTP or HTTP URL and * is suitable for the requirements laid out by .well-known auto discovery. diff --git a/src/base-apis.js b/src/base-apis.js index fbae5efa1..0e34d5e70 100644 --- a/src/base-apis.js +++ b/src/base-apis.js @@ -1,6 +1,8 @@ /* Copyright 2015, 2016 OpenMarket Ltd Copyright 2017 Vector Creations Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -23,8 +25,23 @@ limitations under the License. * @module base-apis */ +import { SERVICE_TYPES } from './service-types'; +import logger from './logger'; + const httpApi = require("./http-api"); const utils = require("./utils"); +const PushProcessor = require("./pushprocessor"); + +function termsUrlForService(serviceType, baseUrl) { + switch (serviceType) { + case SERVICE_TYPES.IS: + return baseUrl + httpApi.PREFIX_IDENTITY_V2 + '/terms'; + case SERVICE_TYPES.IM: + return baseUrl + '/_matrix/integrations/v1/terms'; + default: + throw new Error('Unsupported service type'); + } +} /** * Low-level wrappers for the Matrix APIs @@ -46,6 +63,15 @@ const utils = require("./utils"); * * @param {string} opts.accessToken The access_token for this user. * + * @param {IdentityServerProvider} [opts.identityServer] + * Optional. A provider object with one function `getAccessToken`, which is a + * callback that returns a Promise of an identity access token to supply + * with identity requests. If the object is unset, no access token will be + * supplied. + * See also https://github.com/vector-im/riot-web/issues/10615 which seeks to + * replace the previous approach of manual access tokens params with this + * callback throughout the SDK. + * * @param {Number=} opts.localTimeoutMs Optional. The default maximum amount of * time to wait before timing out HTTP requests. If not specified, there is no * timeout. @@ -62,6 +88,7 @@ function MatrixBaseApis(opts) { this.baseUrl = opts.baseUrl; this.idBaseUrl = opts.idBaseUrl; + this.identityServer = opts.identityServer; const httpOpts = { baseUrl: opts.baseUrl, @@ -100,6 +127,15 @@ MatrixBaseApis.prototype.getIdentityServerUrl = function(stripProto=false) { return this.idBaseUrl; }; +/** + * Set the Identity Server URL of this client + * @param {string} url New Identity Server URL + */ +MatrixBaseApis.prototype.setIdentityServerUrl = function(url) { + this.idBaseUrl = utils.ensureNoTrailingSlash(url); + this._http.setIdBaseUrl(this.idBaseUrl); +}; + /** * Get the access token associated with this account. * @return {?String} The access_token or null @@ -391,9 +427,8 @@ MatrixBaseApis.prototype.deactivateAccount = function(auth, erase) { body.erase = erase; } - return this._http.authedRequestWithPrefix( + return this._http.authedRequest( undefined, "POST", '/account/deactivate', undefined, body, - httpApi.PREFIX_R0, ); }; @@ -438,6 +473,37 @@ MatrixBaseApis.prototype.createRoom = function(options, callback) { callback, "POST", "/createRoom", undefined, options, ); }; +/** + * Fetches relations for a given event + * @param {string} roomId the room of the event + * @param {string} eventId the id of the event + * @param {string} relationType the rel_type of the relations requested + * @param {string} eventType the event type of the relations requested + * @param {Object} opts options with optional values for the request. + * @param {Object} opts.from the pagination token returned from a previous request as `next_batch` to return following relations. + * @return {Object} the response, with chunk and next_batch. + */ +MatrixBaseApis.prototype.fetchRelations = + async function(roomId, eventId, relationType, eventType, opts) { + const queryParams = {}; + if (opts.from) { + queryParams.from = opts.from; + } + const queryString = utils.encodeParams(queryParams); + const path = utils.encodeUri( + "/rooms/$roomId/relations/$eventId/$relationType/$eventType?" + queryString, { + $roomId: roomId, + $eventId: eventId, + $relationType: relationType, + $eventType: eventType, + }); + const response = await this._http.authedRequest( + undefined, "GET", path, null, null, { + prefix: httpApi.PREFIX_UNSTABLE, + }, + ); + return response; +}; /** * @param {string} roomId @@ -927,10 +993,13 @@ MatrixBaseApis.prototype.roomInitialSync = function(roomId, limit, callback) { * @param {string} rrEventId ID of the event tracked by the read receipt. This is here * for convenience because the RR and the RM are commonly updated at the same time as * each other. Optional. + * @param {object} opts Options for the read markers. + * @param {object} opts.hidden True to hide the read receipt from other users. This + * property is currently unstable and may change in the future. * @return {module:client.Promise} Resolves: the empty object, {}. */ MatrixBaseApis.prototype.setRoomReadMarkersHttpRequest = - function(roomId, rmEventId, rrEventId) { + function(roomId, rmEventId, rrEventId, opts) { const path = utils.encodeUri("/rooms/$roomId/read_markers", { $roomId: roomId, }); @@ -938,6 +1007,7 @@ MatrixBaseApis.prototype.setRoomReadMarkersHttpRequest = const content = { "m.fully_read": rmEventId, "m.read": rrEventId, + "m.hidden": Boolean(opts ? opts.hidden : false), }; return this._http.authedRequest( @@ -1269,10 +1339,16 @@ MatrixBaseApis.prototype.getThreePids = function(callback) { }; /** + * Add a 3PID to your homeserver account and optionally bind it to an identity + * server as well. An identity server is required as part of the `creds` object. + * + * This API is deprecated, and you should instead use `addThreePidOnly` + * for homeservers that support it. + * * @param {Object} creds * @param {boolean} bind * @param {module:client.callback} callback Optional. - * @return {module:client.Promise} Resolves: TODO + * @return {module:client.Promise} Resolves: on success * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.addThreePid = function(creds, bind, callback) { @@ -1286,6 +1362,75 @@ MatrixBaseApis.prototype.addThreePid = function(creds, bind, callback) { ); }; +/** + * Add a 3PID to your homeserver account. This API does not use an identity + * server, as the homeserver is expected to handle 3PID ownership validation. + * + * You can check whether a homeserver supports this API via + * `doesServerSupportSeparateAddAndBind`. + * + * @param {Object} data A object with 3PID validation data from having called + * `account/3pid//requestToken` on the homeserver. + * @return {module:client.Promise} Resolves: on success + * @return {module:http-api.MatrixError} Rejects: with an error response. + */ +MatrixBaseApis.prototype.addThreePidOnly = function(data) { + const path = "/account/3pid/add"; + return this._http.authedRequest( + undefined, "POST", path, null, data, { + prefix: httpApi.PREFIX_UNSTABLE, + }, + ); +}; + +/** + * Bind a 3PID for discovery onto an identity server via the homeserver. The + * identity server handles 3PID ownership validation and the homeserver records + * the new binding to track where all 3PIDs for the account are bound. + * + * You can check whether a homeserver supports this API via + * `doesServerSupportSeparateAddAndBind`. + * + * @param {Object} data A object with 3PID validation data from having called + * `validate//requestToken` on the identity server. It should also + * contain `id_server` and `id_access_token` fields as well. + * @return {module:client.Promise} Resolves: on success + * @return {module:http-api.MatrixError} Rejects: with an error response. + */ +MatrixBaseApis.prototype.bindThreePid = function(data) { + const path = "/account/3pid/bind"; + return this._http.authedRequest( + undefined, "POST", path, null, data, { + prefix: httpApi.PREFIX_UNSTABLE, + }, + ); +}; + +/** + * Unbind a 3PID for discovery on an identity server via the homeserver. The + * homeserver removes its record of the binding to keep an updated record of + * where all 3PIDs for the account are bound. + * + * @param {string} medium The threepid medium (eg. 'email') + * @param {string} address The threepid address (eg. 'bob@example.com') + * this must be as returned by getThreePids. + * @return {module:client.Promise} Resolves: on success + * @return {module:http-api.MatrixError} Rejects: with an error response. + */ +MatrixBaseApis.prototype.unbindThreePid = function(medium, address) { + const path = "/account/3pid/unbind"; + const data = { + medium, + address, + id_server: this.getIdentityServerUrl(true), + }; + return this._http.authedRequest( + undefined, "POST", path, null, data, { + prefix: httpApi.PREFIX_UNSTABLE, + }, + ); +}; + /** * @param {string} medium The threepid medium (eg. 'email') * @param {string} address The threepid address (eg. 'bob@example.com') @@ -1300,9 +1445,7 @@ MatrixBaseApis.prototype.deleteThreePid = function(medium, address) { 'medium': medium, 'address': address, }; - return this._http.authedRequestWithPrefix( - undefined, "POST", path, null, data, httpApi.PREFIX_UNSTABLE, - ); + return this._http.authedRequest(undefined, "POST", path, null, data); }; /** @@ -1335,10 +1478,8 @@ MatrixBaseApis.prototype.setPassword = function(authDict, newPassword, callback) * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.getDevices = function() { - const path = "/devices"; - return this._http.authedRequestWithPrefix( - undefined, "GET", path, undefined, undefined, - httpApi.PREFIX_UNSTABLE, + return this._http.authedRequest( + undefined, 'GET', "/devices", undefined, undefined, ); }; @@ -1355,11 +1496,7 @@ MatrixBaseApis.prototype.setDeviceDetails = function(device_id, body) { $device_id: device_id, }); - - return this._http.authedRequestWithPrefix( - undefined, "PUT", path, undefined, body, - httpApi.PREFIX_UNSTABLE, - ); + return this._http.authedRequest(undefined, "PUT", path, undefined, body); }; /** @@ -1381,10 +1518,7 @@ MatrixBaseApis.prototype.deleteDevice = function(device_id, auth) { body.auth = auth; } - return this._http.authedRequestWithPrefix( - undefined, "DELETE", path, undefined, body, - httpApi.PREFIX_UNSTABLE, - ); + return this._http.authedRequest(undefined, "DELETE", path, undefined, body); }; /** @@ -1402,10 +1536,8 @@ MatrixBaseApis.prototype.deleteMultipleDevices = function(devices, auth) { body.auth = auth; } - return this._http.authedRequestWithPrefix( - undefined, "POST", "/delete_devices", undefined, body, - httpApi.PREFIX_UNSTABLE, - ); + const path = "/delete_devices"; + return this._http.authedRequest(undefined, "POST", path, undefined, body); }; @@ -1447,7 +1579,9 @@ MatrixBaseApis.prototype.setPusher = function(pusher, callback) { * @return {module:http-api.MatrixError} Rejects: with an error response. */ MatrixBaseApis.prototype.getPushRules = function(callback) { - return this._http.authedRequest(callback, "GET", "/pushrules/"); + return this._http.authedRequest(callback, "GET", "/pushrules/").then(rules => { + return PushProcessor.rewriteDefaultRules(rules); + }); }; /** @@ -1581,9 +1715,7 @@ MatrixBaseApis.prototype.uploadKeysRequest = function(content, opts, callback) { } else { path = "/keys/upload"; } - return this._http.authedRequestWithPrefix( - callback, "POST", path, undefined, content, httpApi.PREFIX_UNSTABLE, - ); + return this._http.authedRequest(callback, "POST", path, undefined, content); }; MatrixBaseApis.prototype.uploadKeySignatures = function(content) { @@ -1625,10 +1757,7 @@ MatrixBaseApis.prototype.downloadKeysForUsers = function(userIds, opts) { content.device_keys[u] = {}; }); - return this._http.authedRequestWithPrefix( - undefined, "POST", "/keys/query", undefined, content, - httpApi.PREFIX_UNSTABLE, - ); + return this._http.authedRequest(undefined, "POST", "/keys/query", undefined, content); }; /** @@ -1656,10 +1785,8 @@ MatrixBaseApis.prototype.claimOneTimeKeys = function(devices, key_algorithm) { query[deviceId] = key_algorithm; } const content = {one_time_keys: queries}; - return this._http.authedRequestWithPrefix( - undefined, "POST", "/keys/claim", undefined, content, - httpApi.PREFIX_UNSTABLE, - ); + const path = "/keys/claim"; + return this._http.authedRequest(undefined, "POST", path, undefined, content); }; /** @@ -1678,10 +1805,8 @@ MatrixBaseApis.prototype.getKeyChanges = function(oldToken, newToken) { to: newToken, }; - return this._http.authedRequestWithPrefix( - undefined, "GET", "/keys/changes", qps, undefined, - httpApi.PREFIX_UNSTABLE, - ); + const path = "/keys/changes"; + return this._http.authedRequest(undefined, "GET", path, qps, undefined); }; MatrixBaseApis.prototype.uploadDeviceSigningKeys = function(auth, keys) { @@ -1696,10 +1821,36 @@ MatrixBaseApis.prototype.uploadDeviceSigningKeys = function(auth, keys) { // ========================== /** - * Requests an email verification token directly from an Identity Server. + * Register with an Identity Server using the OpenID token from the user's + * Homeserver, which can be retrieved via + * {@link module:client~MatrixClient#getOpenIdToken}. * - * Note that the Home Server offers APIs to proxy this API for specific - * situations, allowing for better feedback to the user. + * Note that the `/account/register` endpoint (as well as IS authentication in + * general) was added as part of the v2 API version. + * + * @param {object} hsOpenIdToken + * @return {module:client.Promise} Resolves: with object containing an Identity + * Server access token. + * @return {module:http-api.MatrixError} Rejects: with an error response. + */ +MatrixBaseApis.prototype.registerWithIdentityServer = function(hsOpenIdToken) { + if (!this.idBaseUrl) { + throw new Error("No Identity Server base URL set"); + } + + const uri = this.idBaseUrl + httpApi.PREFIX_IDENTITY_V2 + "/account/register"; + return this._http.requestOtherUrl( + undefined, "POST", uri, + null, hsOpenIdToken, + ); +}; + +/** + * Requests an email verification token directly from an identity server. + * + * This API is used as part of binding an email for discovery on an identity + * server. The validation data that results should be passed to the + * `bindThreePid` method to complete the binding process. * * @param {string} email The email address to request a token for * @param {string} clientSecret A secret binary string generated by the client. @@ -1711,26 +1862,122 @@ MatrixBaseApis.prototype.uploadDeviceSigningKeys = function(auth, keys) { * @param {string} nextLink Optional If specified, the client will be redirected * to this link after validation. * @param {module:client.callback} callback Optional. + * @param {string} identityAccessToken The `access_token` field of the identity + * server `/account/register` response (see {@link registerWithIdentityServer}). + * * @return {module:client.Promise} Resolves: TODO * @return {module:http-api.MatrixError} Rejects: with an error response. - * @throws Error if No ID server is set + * @throws Error if no identity server is set */ -MatrixBaseApis.prototype.requestEmailToken = function(email, clientSecret, - sendAttempt, nextLink, callback) { +MatrixBaseApis.prototype.requestEmailToken = async function( + email, + clientSecret, + sendAttempt, + nextLink, + callback, + identityAccessToken, +) { const params = { client_secret: clientSecret, email: email, send_attempt: sendAttempt, next_link: nextLink, }; - return this._http.idServerRequest( - callback, "POST", "/validate/email/requestToken", - params, httpApi.PREFIX_IDENTITY_V1, - ); + + try { + const response = await this._http.idServerRequest( + undefined, "POST", "/validate/email/requestToken", + params, httpApi.PREFIX_IDENTITY_V2, identityAccessToken, + ); + // TODO: Fold callback into above call once v1 path below is removed + if (callback) callback(null, response); + return response; + } catch (err) { + if (err.cors === "rejected" || err.httpStatus === 404) { + // Fall back to deprecated v1 API for now + // TODO: Remove this path once v2 is only supported version + // See https://github.com/vector-im/riot-web/issues/10443 + logger.warn("IS doesn't support v2, falling back to deprecated v1"); + return await this._http.idServerRequest( + callback, "POST", "/validate/email/requestToken", + params, httpApi.PREFIX_IDENTITY_V1, + ); + } + if (callback) callback(err); + throw err; + } }; /** - * Submits an MSISDN token to the identity server + * Requests a MSISDN verification token directly from an identity server. + * + * This API is used as part of binding a MSISDN for discovery on an identity + * server. The validation data that results should be passed to the + * `bindThreePid` method to complete the binding process. + * + * @param {string} phoneCountry The ISO 3166-1 alpha-2 code for the country in + * which phoneNumber should be parsed relative to. + * @param {string} phoneNumber The phone number, in national or international + * format + * @param {string} clientSecret A secret binary string generated by the client. + * It is recommended this be around 16 ASCII characters. + * @param {number} sendAttempt If an identity server sees a duplicate request + * with the same sendAttempt, it will not send another SMS. + * To request another SMS to be sent, use a larger value for + * the sendAttempt param as was used in the previous request. + * @param {string} nextLink Optional If specified, the client will be redirected + * to this link after validation. + * @param {module:client.callback} callback Optional. + * @param {string} identityAccessToken The `access_token` field of the Identity + * Server `/account/register` response (see {@link registerWithIdentityServer}). + * + * @return {module:client.Promise} Resolves: TODO + * @return {module:http-api.MatrixError} Rejects: with an error response. + * @throws Error if no identity server is set + */ +MatrixBaseApis.prototype.requestMsisdnToken = async function( + phoneCountry, + phoneNumber, + clientSecret, + sendAttempt, + nextLink, + callback, + identityAccessToken, +) { + const params = { + client_secret: clientSecret, + country: phoneCountry, + phone_number: phoneNumber, + send_attempt: sendAttempt, + next_link: nextLink, + }; + + try { + const response = await this._http.idServerRequest( + undefined, "POST", "/validate/msisdn/requestToken", + params, httpApi.PREFIX_IDENTITY_V2, identityAccessToken, + ); + // TODO: Fold callback into above call once v1 path below is removed + if (callback) callback(null, response); + return response; + } catch (err) { + if (err.cors === "rejected" || err.httpStatus === 404) { + // Fall back to deprecated v1 API for now + // TODO: Remove this path once v2 is only supported version + // See https://github.com/vector-im/riot-web/issues/10443 + logger.warn("IS doesn't support v2, falling back to deprecated v1"); + return await this._http.idServerRequest( + callback, "POST", "/validate/msisdn/requestToken", + params, httpApi.PREFIX_IDENTITY_V1, + ); + } + if (callback) callback(err); + throw err; + } +}; + +/** + * Submits a MSISDN token to the identity server * * This is used when submitting the code sent by SMS to a phone number. * The ID server has an equivalent API for email but the js-sdk does @@ -1740,46 +1987,323 @@ MatrixBaseApis.prototype.requestEmailToken = function(email, clientSecret, * @param {string} sid The sid given in the response to requestToken * @param {string} clientSecret A secret binary string generated by the client. * This must be the same value submitted in the requestToken call. - * @param {string} token The token, as enetered by the user. + * @param {string} msisdnToken The MSISDN token, as enetered by the user. + * @param {string} identityAccessToken The `access_token` field of the Identity + * Server `/account/register` response (see {@link registerWithIdentityServer}). * * @return {module:client.Promise} Resolves: Object, currently with no parameters. * @return {module:http-api.MatrixError} Rejects: with an error response. * @throws Error if No ID server is set */ -MatrixBaseApis.prototype.submitMsisdnToken = function(sid, clientSecret, token) { +MatrixBaseApis.prototype.submitMsisdnToken = async function( + sid, + clientSecret, + msisdnToken, + identityAccessToken, +) { const params = { sid: sid, client_secret: clientSecret, - token: token, + token: msisdnToken, }; - return this._http.idServerRequest( - undefined, "POST", "/validate/msisdn/submitToken", - params, httpApi.PREFIX_IDENTITY_V1, + + try { + return await this._http.idServerRequest( + undefined, "POST", "/validate/msisdn/submitToken", + params, httpApi.PREFIX_IDENTITY_V2, identityAccessToken, + ); + } catch (err) { + if (err.cors === "rejected" || err.httpStatus === 404) { + // Fall back to deprecated v1 API for now + // TODO: Remove this path once v2 is only supported version + // See https://github.com/vector-im/riot-web/issues/10443 + logger.warn("IS doesn't support v2, falling back to deprecated v1"); + return await this._http.idServerRequest( + undefined, "POST", "/validate/msisdn/submitToken", + params, httpApi.PREFIX_IDENTITY_V1, + ); + } + throw err; + } +}; + +/** + * Submits a MSISDN token to an arbitrary URL. + * + * This is used when submitting the code sent by SMS to a phone number in the + * newer 3PID flow where the homeserver validates 3PID ownership (as part of + * `requestAdd3pidMsisdnToken`). The homeserver response may include a + * `submit_url` to specify where the token should be sent, and this helper can + * be used to pass the token to this URL. + * + * @param {string} url The URL to submit the token to + * @param {string} sid The sid given in the response to requestToken + * @param {string} clientSecret A secret binary string generated by the client. + * This must be the same value submitted in the requestToken call. + * @param {string} msisdnToken The MSISDN token, as enetered by the user. + * + * @return {module:client.Promise} Resolves: Object, currently with no parameters. + * @return {module:http-api.MatrixError} Rejects: with an error response. + */ +MatrixBaseApis.prototype.submitMsisdnTokenOtherUrl = function( + url, + sid, + clientSecret, + msisdnToken, +) { + const params = { + sid: sid, + client_secret: clientSecret, + token: msisdnToken, + }; + + return this._http.requestOtherUrl( + undefined, "POST", url, undefined, params, ); }; +/** + * Gets the V2 hashing information from the identity server. Primarily useful for + * lookups. + * @param {string} identityAccessToken The access token for the identity server. + * @returns {Promise} The hashing information for the identity server. + */ +MatrixBaseApis.prototype.getIdentityHashDetails = function(identityAccessToken) { + return this._http.idServerRequest( + undefined, "GET", "/hash_details", + null, httpApi.PREFIX_IDENTITY_V2, identityAccessToken, + ); +}; + +/** + * Performs a hashed lookup of addresses against the identity server. This is + * only supported on identity servers which have at least the version 2 API. + * @param {Array>} addressPairs An array of 2 element arrays. + * The first element of each pair is the address, the second is the 3PID medium. + * Eg: ["email@example.org", "email"] + * @param {string} identityAccessToken The access token for the identity server. + * @returns {Promise>} A collection of address mappings to + * found MXIDs. Results where no user could be found will not be listed. + */ +MatrixBaseApis.prototype.identityHashedLookup = async function( + addressPairs, // [["email@example.org", "email"], ["10005550000", "msisdn"]] + identityAccessToken, +) { + const params = { + // addresses: ["email@example.org", "10005550000"], + // algorithm: "sha256", + // pepper: "abc123" + }; + + // Get hash information first before trying to do a lookup + const hashes = await this.getIdentityHashDetails(identityAccessToken); + if (!hashes || !hashes['lookup_pepper'] || !hashes['algorithms']) { + throw new Error("Unsupported identity server: bad response"); + } + + params['pepper'] = hashes['lookup_pepper']; + + const localMapping = { + // hashed identifier => plain text address + // For use in this function's return format + }; + + // When picking an algorithm, we pick the hashed over no hashes + if (hashes['algorithms'].includes('sha256')) { + // Abuse the olm hashing + const olmutil = new global.Olm.Utility(); + params["addresses"] = addressPairs.map(p => { + const addr = p[0].toLowerCase(); // lowercase to get consistent hashes + const med = p[1].toLowerCase(); + const hashed = olmutil.sha256(`${addr} ${med} ${params['pepper']}`) + .replace(/\+/g, '-').replace(/\//g, '_'); // URL-safe base64 + // Map the hash to a known (case-sensitive) address. We use the case + // sensitive version because the caller might be expecting that. + localMapping[hashed] = p[0]; + return hashed; + }); + params["algorithm"] = "sha256"; + } else if (hashes['algorithms'].includes('none')) { + params["addresses"] = addressPairs.map(p => { + const addr = p[0].toLowerCase(); // lowercase to get consistent hashes + const med = p[1].toLowerCase(); + const unhashed = `${addr} ${med}`; + // Map the unhashed values to a known (case-sensitive) address. We use + // the case sensitive version because the caller might be expecting that. + localMapping[unhashed] = p[0]; + return unhashed; + }); + params["algorithm"] = "none"; + } else { + throw new Error("Unsupported identity server: unknown hash algorithm"); + } + + const response = await this._http.idServerRequest( + undefined, "POST", "/lookup", + params, httpApi.PREFIX_IDENTITY_V2, identityAccessToken, + ); + + if (!response || !response['mappings']) return []; // no results + + const foundAddresses = [/* {address: "plain@example.org", mxid} */]; + for (const hashed of Object.keys(response['mappings'])) { + const mxid = response['mappings'][hashed]; + const plainAddress = localMapping[hashed]; + if (!plainAddress) { + throw new Error("Identity server returned more results than expected"); + } + + foundAddresses.push({address: plainAddress, mxid}); + } + return foundAddresses; +}; + /** * Looks up the public Matrix ID mapping for a given 3rd party * identifier from the Identity Server + * * @param {string} medium The medium of the threepid, eg. 'email' * @param {string} address The textual address of the threepid * @param {module:client.callback} callback Optional. + * @param {string} identityAccessToken The `access_token` field of the Identity + * Server `/account/register` response (see {@link registerWithIdentityServer}). + * * @return {module:client.Promise} Resolves: A threepid mapping * object or the empty object if no mapping * exists * @return {module:http-api.MatrixError} Rejects: with an error response. */ -MatrixBaseApis.prototype.lookupThreePid = function(medium, address, callback) { - const params = { - medium: medium, - address: address, - }; - return this._http.idServerRequest( - callback, "GET", "/lookup", - params, httpApi.PREFIX_IDENTITY_V1, - ); +MatrixBaseApis.prototype.lookupThreePid = async function( + medium, + address, + callback, + identityAccessToken, +) { + try { + // Note: we're using the V2 API by calling this function, but our + // function contract requires a V1 response. We therefore have to + // convert it manually. + const response = await this.identityHashedLookup( + [[address, medium]], identityAccessToken, + ); + const result = response.find(p => p.address === address); + if (!result) { + // TODO: Fold callback into above call once v1 path below is removed + if (callback) callback(null, {}); + return {}; + } + + const mapping = { + address, + medium, + mxid: result.mxid, + + // We can't reasonably fill these parameters: + // not_before + // not_after + // ts + // signatures + }; + + // TODO: Fold callback into above call once v1 path below is removed + if (callback) callback(null, mapping); + return mapping; + } catch (err) { + if (err.cors === "rejected" || err.httpStatus === 404) { + // Fall back to deprecated v1 API for now + // TODO: Remove this path once v2 is only supported version + // See https://github.com/vector-im/riot-web/issues/10443 + const params = { + medium: medium, + address: address, + }; + logger.warn("IS doesn't support v2, falling back to deprecated v1"); + return await this._http.idServerRequest( + callback, "GET", "/lookup", + params, httpApi.PREFIX_IDENTITY_V1, + ); + } + if (callback) callback(err, undefined); + throw err; + } }; +/** + * Looks up the public Matrix ID mappings for multiple 3PIDs. + * + * @param {Array.>} query Array of arrays containing + * [medium, address] + * @param {string} identityAccessToken The `access_token` field of the Identity + * Server `/account/register` response (see {@link registerWithIdentityServer}). + * + * @return {module:client.Promise} Resolves: Lookup results from IS. + * @return {module:http-api.MatrixError} Rejects: with an error response. + */ +MatrixBaseApis.prototype.bulkLookupThreePids = async function( + query, + identityAccessToken, +) { + try { + // Note: we're using the V2 API by calling this function, but our + // function contract requires a V1 response. We therefore have to + // convert it manually. + const response = await this.identityHashedLookup( + // We have to reverse the query order to get [address, medium] pairs + query.map(p => [p[1], p[0]]), identityAccessToken, + ); + + const v1results = []; + for (const mapping of response) { + const originalQuery = query.find(p => p[1] === mapping.address); + if (!originalQuery) { + throw new Error("Identity sever returned unexpected results"); + } + + v1results.push([ + originalQuery[0], // medium + mapping.address, + mapping.mxid, + ]); + } + + return {threepids: v1results}; + } catch (err) { + if (err.cors === "rejected" || err.httpStatus === 404) { + // Fall back to deprecated v1 API for now + // TODO: Remove this path once v2 is only supported version + // See https://github.com/vector-im/riot-web/issues/10443 + const params = { + threepids: query, + }; + logger.warn("IS doesn't support v2, falling back to deprecated v1"); + return await this._http.idServerRequest( + undefined, "POST", "/bulk_lookup", params, + httpApi.PREFIX_IDENTITY_V1, identityAccessToken, + ); + } + throw err; + } +}; + +/** + * Get account info from the Identity Server. This is useful as a neutral check + * to verify that other APIs are likely to approve access by testing that the + * token is valid, terms have been agreed, etc. + * + * @param {string} identityAccessToken The `access_token` field of the Identity + * Server `/account/register` response (see {@link registerWithIdentityServer}). + * + * @return {module:client.Promise} Resolves: an object with account info. + * @return {module:http-api.MatrixError} Rejects: with an error response. + */ +MatrixBaseApis.prototype.getIdentityAccount = function( + identityAccessToken, +) { + return this._http.idServerRequest( + undefined, "GET", "/account", + undefined, httpApi.PREFIX_IDENTITY_V2, identityAccessToken, + ); +}; // Direct-to-device messaging // ========================== @@ -1806,10 +2330,7 @@ MatrixBaseApis.prototype.sendToDevice = function( messages: contentMap, }; - return this._http.authedRequestWithPrefix( - undefined, "PUT", path, undefined, body, - httpApi.PREFIX_UNSTABLE, - ); + return this._http.authedRequest(undefined, "PUT", path, undefined, body); }; // Third party Lookup API @@ -1821,9 +2342,8 @@ MatrixBaseApis.prototype.sendToDevice = function( * @return {module:client.Promise} Resolves to the result object */ MatrixBaseApis.prototype.getThirdpartyProtocols = function() { - return this._http.authedRequestWithPrefix( + return this._http.authedRequest( undefined, "GET", "/thirdparty/protocols", undefined, undefined, - httpApi.PREFIX_UNSTABLE, ).then((response) => { // sanity check if (!response || typeof(response) !== 'object') { @@ -1848,10 +2368,7 @@ MatrixBaseApis.prototype.getThirdpartyLocation = function(protocol, params) { $protocol: protocol, }); - return this._http.authedRequestWithPrefix( - undefined, "GET", path, params, undefined, - httpApi.PREFIX_UNSTABLE, - ); + return this._http.authedRequest(undefined, "GET", path, params, undefined); }; /** @@ -1867,12 +2384,45 @@ MatrixBaseApis.prototype.getThirdpartyUser = function(protocol, params) { $protocol: protocol, }); - return this._http.authedRequestWithPrefix( - undefined, "GET", path, params, undefined, - httpApi.PREFIX_UNSTABLE, + return this._http.authedRequest(undefined, "GET", path, params, undefined); +}; + +MatrixBaseApis.prototype.getTerms = function(serviceType, baseUrl) { + const url = termsUrlForService(serviceType, baseUrl); + return this._http.requestOtherUrl( + undefined, 'GET', url, ); }; +MatrixBaseApis.prototype.agreeToTerms = function( + serviceType, baseUrl, accessToken, termsUrls, +) { + const url = termsUrlForService(serviceType, baseUrl); + const headers = { + Authorization: "Bearer " + accessToken, + }; + return this._http.requestOtherUrl( + undefined, 'POST', url, null, { user_accepts: termsUrls }, { headers }, + ); +}; + +/** + * Reports an event as inappropriate to the server, which may then notify the appropriate people. + * @param {string} roomId The room in which the event being reported is located. + * @param {string} eventId The event to report. + * @param {number} score The score to rate this content as where -100 is most offensive and 0 is inoffensive. + * @param {string} reason The reason the content is being reported. May be blank. + * @returns {module:client.Promise} Resolves to an empty object if successful + */ +MatrixBaseApis.prototype.reportEvent = function(roomId, eventId, score, reason) { + const path = utils.encodeUri("/rooms/$roomId/report/$eventId", { + $roomId: roomId, + $eventId: eventId, + }); + + return this._http.authedRequest(undefined, "POST", path, null, {score, reason}); +}; + /** * MatrixBaseApis object */ diff --git a/src/client.js b/src/client.js index 8e8957221..84ec107bc 100644 --- a/src/client.js +++ b/src/client.js @@ -2,6 +2,7 @@ Copyright 2015, 2016 OpenMarket Ltd Copyright 2017 Vector Creations Ltd Copyright 2018-2019 New Vector Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -45,7 +46,7 @@ const olmlib = require("./crypto/olmlib"); import ReEmitter from './ReEmitter'; import RoomList from './crypto/RoomList'; -import logger from '../src/logger'; +import logger from './logger'; import Crypto from './crypto'; import { isCryptoAvailable } from './crypto'; @@ -107,6 +108,15 @@ function keyFromRecoverySession(session, decryptionKey) { * * @param {string} opts.userId The user ID for this user. * + * @param {IdentityServerProvider} [opts.identityServer] + * Optional. A provider object with one function `getAccessToken`, which is a + * callback that returns a Promise of an identity access token to supply + * with identity requests. If the object is unset, no access token will be + * supplied. + * See also https://github.com/vector-im/riot-web/issues/10615 which seeks to + * replace the previous approach of manual access tokens params with this + * callback throughout the SDK. + * * @param {Object=} opts.store * The data store used for sync data from the homeserver. If not specified, * this client will not store any HTTP responses. The `createClient` helper @@ -158,17 +168,17 @@ function keyFromRecoverySession(session, decryptionKey) { * that the application can handle. Each element should be an item from {@link * module:crypto~verificationMethods verificationMethods}, or a class that * implements the {$link module:crypto/verification/Base verifier interface}. + * + * @param {boolean} [opts.forceTURN] + * Optional. Whether relaying calls through a TURN server should be forced. + * + * @param {boolean} [opts.fallbackICEServerAllowed] + * Optional. Whether to allow a fallback ICE server should be used for negotiating a + * WebRTC connection if the homeserver doesn't provide any servers. Defaults to false. */ function MatrixClient(opts) { - // Allow trailing slash in HS url - if (opts.baseUrl && opts.baseUrl.endsWith("/")) { - opts.baseUrl = opts.baseUrl.substr(0, opts.baseUrl.length - 1); - } - - // Allow trailing slash in IS url - if (opts.idBaseUrl && opts.idBaseUrl.endsWith("/")) { - opts.idBaseUrl = opts.idBaseUrl.substr(0, opts.idBaseUrl.length - 1); - } + opts.baseUrl = utils.ensureNoTrailingSlash(opts.baseUrl); + opts.idBaseUrl = utils.ensureNoTrailingSlash(opts.idBaseUrl); MatrixBaseApis.call(this, opts); @@ -227,6 +237,7 @@ function MatrixClient(opts) { this._verificationMethods = opts.verificationMethods; this._forceTURN = opts.forceTURN || false; + this._fallbackICEServerAllowed = opts.fallbackICEServerAllowed || false; // List of which rooms have encryption enabled: separate from crypto because // we still want to know which rooms are encrypted even if crypto is disabled: @@ -236,7 +247,9 @@ function MatrixClient(opts) { // The pushprocessor caches useful things, so keep one and re-use it this._pushProcessor = new PushProcessor(this); - this._serverSupportsLazyLoading = null; + // Cache of the server's /versions response + // TODO: This should expire: https://github.com/matrix-org/matrix-js-sdk/issues/1020 + this._serverVersionsCache = null; this._cachedCapabilities = null; // { capabilities: {}, lastUpdated: timestamp } @@ -278,6 +291,48 @@ function MatrixClient(opts) { } } }); + + // Like above, we have to listen for read receipts from ourselves in order to + // correctly handle notification counts on encrypted rooms. + // This fixes https://github.com/vector-im/riot-web/issues/9421 + this.on("Room.receipt", (event, room) => { + if (room && this.isRoomEncrypted(room.roomId)) { + // Figure out if we've read something or if it's just informational + const content = event.getContent(); + const isSelf = Object.keys(content).filter(eid => { + return Object.keys(content[eid]['m.read']).includes(this.getUserId()); + }).length > 0; + + if (!isSelf) return; + + // Work backwards to determine how many events are unread. We also set + // a limit for how back we'll look to avoid spinning CPU for too long. + // If we hit the limit, we assume the count is unchanged. + const maxHistory = 20; + const events = room.getLiveTimeline().getEvents(); + + let highlightCount = 0; + + for (let i = events.length - 1; i >= 0; i--) { + if (i === events.length - maxHistory) return; // limit reached + + const event = events[i]; + + if (room.hasUserReadEvent(this.getUserId(), event.getId())) { + // If the user has read the event, then the counting is done. + break; + } + + highlightCount += this.getPushActionsForEvent( + event, + ).tweaks.highlight ? 1 : 0; + } + + // Note: we don't need to handle 'total' notifications because the counts + // will come from the server. + room.setUnreadNotificationCount("highlight", highlightCount); + } + }); } utils.inherits(MatrixClient, EventEmitter); utils.extend(MatrixClient.prototype, MatrixBaseApis.prototype); @@ -734,6 +789,40 @@ async function _setDeviceVerification( client.emit("deviceVerificationChanged", userId, deviceId, dev); } +/** + * Request a key verification from another user, using a DM. + * + * @param {string} userId the user to request verification with + * @param {string} roomId the room to use for verification + * @param {Array} methods array of verification methods to use. Defaults to + * all known methods + * + * @returns {Promise} resolves to a verifier + * when the request is accepted by the other user + */ +MatrixClient.prototype.requestVerificationDM = function(userId, roomId, methods) { + if (this._crypto === null) { + throw new Error("End-to-end encryption disabled"); + } + return this._crypto.requestVerificationDM(userId, roomId, methods); +}; + +/** + * Accept a key verification request from a DM. + * + * @param {module:models/event~MatrixEvent} event the verification request + * that is accepted + * @param {string} method the verification mmethod to use + * + * @returns {module:crypto/verification/Base} a verifier + */ +MatrixClient.prototype.acceptVerificationDM = function(event, method) { + if (this._crypto === null) { + throw new Error("End-to-end encryption disabled"); + } + return this._crypto.acceptVerificationDM(event, method); +}; + /** * Request a key verification from another user. * @@ -1107,7 +1196,8 @@ MatrixClient.prototype.checkKeyBackup = function() { */ MatrixClient.prototype.getKeyBackupVersion = function() { return this._http.authedRequest( - undefined, "GET", "/room_keys/version", + undefined, "GET", "/room_keys/version", undefined, undefined, + {prefix: httpApi.PREFIX_UNSTABLE}, ).then((res) => { if (res.algorithm !== olmlib.MEGOLM_BACKUP_ALGORITHM) { const err = "Unknown backup algorithm: " + res.algorithm; @@ -1262,6 +1352,7 @@ MatrixClient.prototype.createKeyBackupVersion = async function(info) { const res = await this._http.authedRequest( undefined, "POST", "/room_keys/version", undefined, data, + {prefix: httpApi.PREFIX_UNSTABLE}, ); this.enableKeyBackup({ algorithm: info.algorithm, @@ -1289,6 +1380,7 @@ MatrixClient.prototype.deleteKeyBackupVersion = function(version) { return this._http.authedRequest( undefined, "DELETE", path, undefined, undefined, + {prefix: httpApi.PREFIX_UNSTABLE}, ); }; @@ -1330,6 +1422,7 @@ MatrixClient.prototype.sendKeyBackup = function(roomId, sessionId, version, data const path = this._makeKeyBackupPath(roomId, sessionId, version); return this._http.authedRequest( undefined, "PUT", path.path, path.queryData, data, + {prefix: httpApi.PREFIX_UNSTABLE}, ); }; @@ -1345,6 +1438,19 @@ MatrixClient.prototype.scheduleAllGroupSessionsForBackup = async function() { await this._crypto.scheduleAllGroupSessionsForBackup(); }; +/** + * Marks all group sessions as needing to be backed up without scheduling + * them to upload in the background. + * @returns {Promise} Resolves to the number of sessions requiring a backup. + */ +MatrixClient.prototype.flagAllGroupSessionsForBackup = function() { + if (this._crypto === null) { + throw new Error("End-to-end encryption disabled"); + } + + return this._crypto.flagAllGroupSessionsForBackup(); +}; + MatrixClient.prototype.isValidRecoveryKey = function(recoveryKey) { try { decodeRecoveryKey(recoveryKey); @@ -1404,7 +1510,8 @@ MatrixClient.prototype._restoreKeyBackup = function( } return this._http.authedRequest( - undefined, "GET", path.path, path.queryData, + undefined, "GET", path.path, path.queryData, undefined, + {prefix: httpApi.PREFIX_UNSTABLE}, ).then((res) => { if (res.rooms) { for (const [roomId, roomData] of Object.entries(res.rooms)) { @@ -1453,7 +1560,8 @@ MatrixClient.prototype.deleteKeysFromBackup = function(roomId, sessionId, versio const path = this._makeKeyBackupPath(roomId, sessionId, version); return this._http.authedRequest( - undefined, "DELETE", path.path, path.queryData, + undefined, "DELETE", path.path, path.queryData, undefined, + {prefix: httpApi.PREFIX_UNSTABLE}, ); }; @@ -1487,8 +1595,10 @@ MatrixClient.prototype.getGroups = function() { * @return {module:client.Promise} Resolves with an object containing the config. */ MatrixClient.prototype.getMediaConfig = function(callback) { - return this._http.authedRequestWithPrefix( - callback, "GET", "/config", undefined, undefined, httpApi.PREFIX_MEDIA_R0, + return this._http.authedRequest( + callback, "GET", "/config", undefined, undefined, { + prefix: httpApi.PREFIX_MEDIA_R0, + }, ); }; @@ -2043,6 +2153,20 @@ function _encryptEventIfNeeded(client, event, room) { return null; } + if (event.getType() === "m.reaction") { + // For reactions, there is a very little gained by encrypting the entire + // event, as relation data is already kept in the clear. Event + // encryption for a reaction effectively only obscures the event type, + // but the purpose is still obvious from the relation data, so nothing + // is really gained. It also causes quite a few problems, such as: + // * triggers notifications via default push rules + // * prevents server-side bundling for reactions + // The reaction key / content / emoji value does warrant encrypting, but + // this will be handled separately by encrypting just this value. + // See https://github.com/matrix-org/matrix-doc/pull/1849#pullrequestreview-248763642 + return null; + } + if (!client._crypto) { throw new Error( "This room is configured to use encryption, but your client does " + @@ -2052,6 +2176,21 @@ function _encryptEventIfNeeded(client, event, room) { return client._crypto.encryptEvent(event, room); } +/** + * Returns the eventType that should be used taking encryption into account + * for a given eventType. + * @param {MatrixClient} client the client + * @param {string} roomId the room for the events `eventType` relates to + * @param {string} eventType the event type + * @return {string} the event type taking encryption into account + */ +function _getEncryptedIfNeededEventType(client, roomId, eventType) { + if (eventType === "m.reaction") { + return eventType; + } + const isEncrypted = client.isRoomEncrypted(roomId); + return isEncrypted ? "m.room.encrypted" : eventType; +} function _updatePendingEventStatus(room, event, newStatus) { if (room) { @@ -2267,11 +2406,17 @@ MatrixClient.prototype.sendHtmlEmote = function(roomId, body, htmlBody, callback * Send a receipt. * @param {Event} event The event being acknowledged * @param {string} receiptType The kind of receipt e.g. "m.read" + * @param {object} opts Additional content to send alongside the receipt. * @param {module:client.callback} callback Optional. * @return {module:client.Promise} Resolves: TODO * @return {module:http-api.MatrixError} Rejects: with an error response. */ -MatrixClient.prototype.sendReceipt = function(event, receiptType, callback) { +MatrixClient.prototype.sendReceipt = function(event, receiptType, opts, callback) { + if (typeof(opts) === 'function') { + callback = opts; + opts = {}; + } + if (this.isGuest()) { return Promise.resolve({}); // guests cannot send receipts so don't bother. } @@ -2282,7 +2427,7 @@ MatrixClient.prototype.sendReceipt = function(event, receiptType, callback) { $eventId: event.getId(), }); const promise = this._http.authedRequest( - callback, "POST", path, undefined, {}, + callback, "POST", path, undefined, opts || {}, ); const room = this.getRoom(event.getRoomId()); @@ -2295,12 +2440,32 @@ MatrixClient.prototype.sendReceipt = function(event, receiptType, callback) { /** * Send a read receipt. * @param {Event} event The event that has been read. + * @param {object} opts The options for the read receipt. + * @param {boolean} opts.hidden True to prevent the receipt from being sent to + * other users and homeservers. Default false (send to everyone). This + * property is unstable and may change in the future. * @param {module:client.callback} callback Optional. * @return {module:client.Promise} Resolves: TODO * @return {module:http-api.MatrixError} Rejects: with an error response. */ -MatrixClient.prototype.sendReadReceipt = function(event, callback) { - return this.sendReceipt(event, "m.read", callback); +MatrixClient.prototype.sendReadReceipt = async function(event, opts, callback) { + if (typeof(opts) === 'function') { + callback = opts; + opts = {}; + } + if (!opts) opts = {}; + + const eventId = event.getId(); + const room = this.getRoom(event.getRoomId()); + if (room && room.hasPendingEvent(eventId)) { + throw new Error(`Cannot set read receipt to a pending event (${eventId})`); + } + + const addlContent = { + "m.hidden": Boolean(opts.hidden), + }; + + return this.sendReceipt(event, "m.read", addlContent, callback); }; /** @@ -2309,26 +2474,36 @@ MatrixClient.prototype.sendReadReceipt = function(event, callback) { * and displayed as a horizontal line in the timeline that is visually distinct to the * position of the user's own read receipt. * @param {string} roomId ID of the room that has been read - * @param {string} eventId ID of the event that has been read + * @param {string} rmEventId ID of the event that has been read * @param {string} rrEvent the event tracked by the read receipt. This is here for * convenience because the RR and the RM are commonly updated at the same time as each * other. The local echo of this receipt will be done if set. Optional. + * @param {object} opts Options for the read markers + * @param {object} opts.hidden True to hide the receipt from other users and homeservers. + * This property is unstable and may change in the future. * @return {module:client.Promise} Resolves: the empty object, {}. */ -MatrixClient.prototype.setRoomReadMarkers = function(roomId, eventId, rrEvent) { - const rmEventId = eventId; - let rrEventId; +MatrixClient.prototype.setRoomReadMarkers = async function( + roomId, rmEventId, rrEvent, opts, +) { + const room = this.getRoom(roomId); + if (room && room.hasPendingEvent(rmEventId)) { + throw new Error(`Cannot set read marker to a pending event (${rmEventId})`); + } // Add the optional RR update, do local echo like `sendReceipt` + let rrEventId; if (rrEvent) { rrEventId = rrEvent.getId(); - const room = this.getRoom(roomId); + if (room && room.hasPendingEvent(rrEventId)) { + throw new Error(`Cannot set read receipt to a pending event (${rrEventId})`); + } if (room) { room._addLocalEchoReceipt(this.credentials.userId, rrEvent, "m.read"); } } - return this.setRoomReadMarkersHttpRequest(roomId, rmEventId, rrEventId); + return this.setRoomReadMarkersHttpRequest(roomId, rmEventId, rrEventId, opts); }; /** @@ -2354,11 +2529,13 @@ MatrixClient.prototype.getUrlPreview = function(url, ts, callback) { } const self = this; - return this._http.authedRequestWithPrefix( + return this._http.authedRequest( callback, "GET", "/preview_url", { url: url, ts: ts, - }, undefined, httpApi.PREFIX_MEDIA_R0, + }, undefined, { + prefix: httpApi.PREFIX_MEDIA_R0, + }, ).then(function(response) { // TODO: expire cache occasionally self.urlPreviewCache[key] = response; @@ -2448,6 +2625,7 @@ MatrixClient.prototype.getRoomUpgradeHistory = function(roomId, verifyLinks=fals while (tombstoneEvent) { const refRoom = this.getRoom(tombstoneEvent.getContent()['replacement_room']); if (!refRoom) break; // end of the chain + if (refRoom.roomId === currentRoom.roomId) break; // Tombstone is referencing it's own room if (verifyLinks) { createEvent = refRoom.currentState.getStateEvents("m.room.create", ""); @@ -2459,6 +2637,12 @@ MatrixClient.prototype.getRoomUpgradeHistory = function(roomId, verifyLinks=fals // Push to the end because we're looking forwards upgradeHistory.push(refRoom); + const roomIds = new Set(upgradeHistory.map((ref) => ref.roomId)); + if (roomIds.size < upgradeHistory.length) { + // The last room added to the list introduced a previous roomId + // To avoid recursion, return the last rooms - 1 + return upgradeHistory.slice(0, upgradeHistory.length - 1); + } // Set the current room to the reference room so we know where we're at currentRoom = refRoom; @@ -2503,7 +2687,12 @@ MatrixClient.prototype.inviteByEmail = function(roomId, email, callback) { * @return {module:client.Promise} Resolves: TODO * @return {module:http-api.MatrixError} Rejects: with an error response. */ -MatrixClient.prototype.inviteByThreePid = function(roomId, medium, address, callback) { +MatrixClient.prototype.inviteByThreePid = async function( + roomId, + medium, + address, + callback, +) { const path = utils.encodeUri( "/rooms/$roomId/invite", { $roomId: roomId }, @@ -2516,12 +2705,24 @@ MatrixClient.prototype.inviteByThreePid = function(roomId, medium, address, call errcode: "ORG.MATRIX.JSSDK_MISSING_PARAM", })); } - - return this._http.authedRequest(callback, "POST", path, undefined, { + const params = { id_server: identityServerUrl, medium: medium, address: address, - }); + }; + + if ( + this.identityServer && + this.identityServer.getAccessToken && + await this.doesServerAcceptIdentityAccessToken() + ) { + const identityAccessToken = await this.identityServer.getAccessToken(); + if (identityAccessToken) { + params.id_access_token = identityAccessToken; + } + } + + return this._http.authedRequest(callback, "POST", path, undefined, params); }; /** @@ -3150,9 +3351,8 @@ MatrixClient.prototype.paginateEventTimeline = function(eventTimeline, opts) { params.from = token; } - promise = - this._http.authedRequestWithPrefix(undefined, "GET", path, params, - undefined, httpApi.PREFIX_UNSTABLE, + promise = this._http.authedRequest( + undefined, "GET", path, params, undefined, ).then(function(res) { const token = res.next_token; const matrixEvents = []; @@ -3311,14 +3511,9 @@ MatrixClient.prototype.setGuestAccess = function(roomId, opts) { /** * Requests an email verification token for the purposes of registration. - * This API proxies the Identity Server /validate/email/requestToken API, - * adding registration-specific behaviour. Specifically, if an account with - * the given email address already exists, it will either send an email - * to the address informing them of this or return M_THREEPID_IN_USE - * (which one is up to the Home Server). - * - * requestEmailToken calls the equivalent API directly on the ID server, - * therefore bypassing the registration-specific logic. + * This API requests a token from the homeserver. + * The doesServerRequireIdServerParam() method can be used to determine if + * the server requires the id_server parameter to be provided. * * Parameters and return value are as for requestEmailToken @@ -3343,8 +3538,9 @@ MatrixClient.prototype.requestRegisterEmailToken = function(email, clientSecret, /** * Requests a text message verification token for the purposes of registration. - * This API proxies the Identity Server /validate/msisdn/requestToken API, - * adding registration-specific behaviour, as with requestRegisterEmailToken. + * This API requests a token from the homeserver. + * The doesServerRequireIdServerParam() method can be used to determine if + * the server requires the id_server parameter to be provided. * * @param {string} phoneCountry The ISO 3166-1 alpha-2 code for the country in which * phoneNumber should be parsed relative to. @@ -3371,15 +3567,13 @@ MatrixClient.prototype.requestRegisterMsisdnToken = function(phoneCountry, phone /** * Requests an email verification token for the purposes of adding a * third party identifier to an account. - * This API proxies the Identity Server /validate/email/requestToken API, - * adding specific behaviour for the addition of email addresses to an - * account. Specifically, if an account with - * the given email address already exists, it will either send an email - * to the address informing them of this or return M_THREEPID_IN_USE - * (which one is up to the Home Server). - * - * requestEmailToken calls the equivalent API directly on the ID server, - * therefore bypassing the email addition specific logic. + * This API requests a token from the homeserver. + * The doesServerRequireIdServerParam() method can be used to determine if + * the server requires the id_server parameter to be provided. + * If an account with the given email address already exists and is + * associated with an account other than the one the user is authed as, + * it will either send an email to the address informing them of this + * or return M_THREEPID_IN_USE (which one is up to the Home Server). * * @param {string} email As requestEmailToken * @param {string} clientSecret As requestEmailToken @@ -3495,15 +3689,30 @@ MatrixClient.prototype.requestPasswordMsisdnToken = function(phoneCountry, phone * @param {object} params Parameters for the POST request * @return {module:client.Promise} Resolves: As requestEmailToken */ -MatrixClient.prototype._requestTokenFromEndpoint = function(endpoint, params) { - const id_server_url = url.parse(this.idBaseUrl); - if (id_server_url.host === null) { - throw new Error("Invalid ID server URL: " + this.idBaseUrl); +MatrixClient.prototype._requestTokenFromEndpoint = async function(endpoint, params) { + const postParams = Object.assign({}, params); + + // If the HS supports separate add and bind, then requestToken endpoints + // don't need an IS as they are all validated by the HS directly. + if (!await this.doesServerSupportSeparateAddAndBind() && this.idBaseUrl) { + const idServerUrl = url.parse(this.idBaseUrl); + if (!idServerUrl.host) { + throw new Error("Invalid ID server URL: " + this.idBaseUrl); + } + postParams.id_server = idServerUrl.host; + + if ( + this.identityServer && + this.identityServer.getAccessToken && + await this.doesServerAcceptIdentityAccessToken() + ) { + const identityAccessToken = await this.identityServer.getAccessToken(); + if (identityAccessToken) { + postParams.id_access_token = identityAccessToken; + } + } } - const postParams = Object.assign({}, params, { - id_server: id_server_url.host, - }); return this._http.request( undefined, "POST", endpoint, undefined, postParams, @@ -3959,6 +4168,77 @@ MatrixClient.prototype.getTurnServers = function() { return this._turnServers || []; }; +/** + * Set whether to allow a fallback ICE server should be used for negotiating a + * WebRTC connection if the homeserver doesn't provide any servers. Defaults to + * false. + * + * @param {boolean} allow + */ +MatrixClient.prototype.setFallbackICEServerAllowed = function(allow) { + this._fallbackICEServerAllowed = allow; +}; + +/** + * Get whether to allow a fallback ICE server should be used for negotiating a + * WebRTC connection if the homeserver doesn't provide any servers. Defaults to + * false. + * + * @returns {boolean} + */ +MatrixClient.prototype.isFallbackICEServerAllowed = function() { + return this._fallbackICEServerAllowed; +}; + +// Synapse-specific APIs +// ===================== + +/** + * Determines if the current user is an administrator of the Synapse homeserver. + * Returns false if untrue or the homeserver does not appear to be a Synapse + * homeserver. This function is implementation specific and may change + * as a result. + * @return {boolean} true if the user appears to be a Synapse administrator. + */ +MatrixClient.prototype.isSynapseAdministrator = function() { + return this.whoisSynapseUser(this.getUserId()) + .then(() => true) + .catch(() => false); +}; + +/** + * Performs a whois lookup on a user using Synapse's administrator API. + * This function is implementation specific and may change as a + * result. + * @param {string} userId the User ID to look up. + * @return {object} the whois response - see Synapse docs for information. + */ +MatrixClient.prototype.whoisSynapseUser = function(userId) { + const path = utils.encodeUri( + "/_synapse/admin/v1/whois/$userId", + { $userId: userId }, + ); + return this._http.authedRequest( + undefined, 'GET', path, undefined, undefined, {prefix: ''}, + ); +}; + +/** + * Deactivates a user using Synapse's administrator API. This + * function is implementation specific and may change as a result. + * @param {string} userId the User ID to deactivate. + * @return {object} the deactivate response - see Synapse docs for information. + */ +MatrixClient.prototype.deactivateSynapseUser = function(userId) { + const path = utils.encodeUri( + "/_synapse/admin/v1/deactivate/$userId", + { $userId: userId }, + ); + return this._http.authedRequest( + undefined, 'POST', path, undefined, undefined, {prefix: ''}, + ); +}; + // Higher level APIs // ================= @@ -4090,13 +4370,14 @@ MatrixClient.prototype.stopClient = function() { global.clearTimeout(this._checkTurnServersTimeoutID); }; -/* - * Query the server to see if it support members lazy loading - * @return {Promise} true if server supports lazy loading +/** + * Get the API versions supported by the server, along with any + * unstable APIs it supports + * @return {Promise} The server /versions response */ -MatrixClient.prototype.doesServerSupportLazyLoading = async function() { - if (this._serverSupportsLazyLoading === null) { - const response = await this._http.request( +MatrixClient.prototype.getVersions = async function() { + if (this._serverVersionsCache === null) { + this._serverVersionsCache = await this._http.request( undefined, // callback "GET", "/_matrix/client/versions", undefined, // queryParams @@ -4105,14 +4386,80 @@ MatrixClient.prototype.doesServerSupportLazyLoading = async function() { prefix: '', }, ); - const unstableFeatures = response["unstable_features"]; - this._serverSupportsLazyLoading = - unstableFeatures && unstableFeatures["m.lazy_load_members"]; } - return this._serverSupportsLazyLoading; + return this._serverVersionsCache; }; -/* +/** + * Query the server to see if it support members lazy loading + * @return {Promise} true if server supports lazy loading + */ +MatrixClient.prototype.doesServerSupportLazyLoading = async function() { + const response = await this.getVersions(); + + const versions = response["versions"]; + const unstableFeatures = response["unstable_features"]; + + return (versions && versions.includes("r0.5.0")) + || (unstableFeatures && unstableFeatures["m.lazy_load_members"]); +}; + +/** + * Query the server to see if the `id_server` parameter is required + * when registering with an 3pid, adding a 3pid or resetting password. + * @return {Promise} true if id_server parameter is required + */ +MatrixClient.prototype.doesServerRequireIdServerParam = async function() { + const response = await this.getVersions(); + + const versions = response["versions"]; + + // Supporting r0.6.0 is the same as having the flag set to false + if (versions && versions.includes("r0.6.0")) { + return false; + } + + const unstableFeatures = response["unstable_features"]; + if (unstableFeatures["m.require_identity_server"] === undefined) { + return true; + } else { + return unstableFeatures["m.require_identity_server"]; + } +}; + +/** + * Query the server to see if the `id_access_token` parameter can be safely + * passed to the homeserver. Some homeservers may trigger errors if they are not + * prepared for the new parameter. + * @return {Promise} true if id_access_token can be sent + */ +MatrixClient.prototype.doesServerAcceptIdentityAccessToken = async function() { + const response = await this.getVersions(); + + const versions = response["versions"]; + const unstableFeatures = response["unstable_features"]; + + return (versions && versions.includes("r0.6.0")) + || (unstableFeatures && unstableFeatures["m.id_access_token"]); +}; + +/** + * Query the server to see if it supports separate 3PID add and bind functions. + * This affects the sequence of API calls clients should use for these operations, + * so it's helpful to be able to check for support. + * @return {Promise} true if separate functions are supported + */ +MatrixClient.prototype.doesServerSupportSeparateAddAndBind = async function() { + const response = await this.getVersions(); + + const versions = response["versions"]; + const unstableFeatures = response["unstable_features"]; + + return (versions && versions.includes("r0.6.0")) + || (unstableFeatures && unstableFeatures["m.separate_add_and_bind"]); +}; + +/** * Get if lazy loading members is being used. * @return {boolean} Whether or not members are lazy loaded by this client */ @@ -4120,7 +4467,7 @@ MatrixClient.prototype.hasLazyLoadMembersEnabled = function() { return !!this._clientOpts.lazyLoadMembers; }; -/* +/** * Set a function which is called when /sync returns a 'limited' response. * It is called with a room ID and returns a boolean. It should return 'true' if the SDK * can SAFELY remove events from this room. It may not be safe to remove events if there @@ -4141,6 +4488,47 @@ MatrixClient.prototype.getCanResetTimelineCallback = function() { return this._canResetTimelineCallback; }; +/** + * Returns relations for a given event. Handles encryption transparently, + * with the caveat that the amount of events returned might be 0, even though you get a nextBatch. + * When the returned promise resolves, all messages should have finished trying to decrypt. + * @param {string} roomId the room of the event + * @param {string} eventId the id of the event + * @param {string} relationType the rel_type of the relations requested + * @param {string} eventType the event type of the relations requested + * @param {Object} opts options with optional values for the request. + * @param {Object} opts.from the pagination token returned from a previous request as `nextBatch` to return following relations. + * @return {Object} an object with `events` as `MatrixEvent[]` and optionally `nextBatch` if more relations are available. + */ +MatrixClient.prototype.relations = +async function(roomId, eventId, relationType, eventType, opts = {}) { + const fetchedEventType = _getEncryptedIfNeededEventType(this, roomId, eventType); + const result = await this.fetchRelations( + roomId, + eventId, + relationType, + fetchedEventType, + opts); + const mapper = this.getEventMapper(); + let originalEvent; + if (result.original_event) { + originalEvent = mapper(result.original_event); + } + let events = result.chunk.map(mapper); + if (fetchedEventType === "m.room.encrypted") { + const allEvents = originalEvent ? events.concat(originalEvent) : events; + await Promise.all(allEvents.map(e => { + return new Promise(resolve => e.once("Event.decrypted", resolve)); + })); + events = events.filter(e => e.getType() === eventType); + } + return { + originalEvent, + events, + nextBatch: result.next_batch, + }; +}; + function setupCallEventHandler(client) { const candidatesByCall = { // callId: [Candidate] @@ -4364,10 +4752,9 @@ function checkTurnServers(client) { } }, function(err) { logger.error("Failed to get TURN URIs"); - client._checkTurnServersTimeoutID = - setTimeout(function() { - checkTurnServers(client); -}, 60000); + client._checkTurnServersTimeoutID = setTimeout(function() { + checkTurnServers(client); + }, 60000); }); } @@ -4627,7 +5014,7 @@ module.exports.CRYPTO_ENABLED = CRYPTO_ENABLED; * when then login session can be renewed by using a refresh token. * @event module:client~MatrixClient#"Session.logged_out" * @example - * matrixClient.on("Session.logged_out", function(call){ + * matrixClient.on("Session.logged_out", function(errorObj){ * // show the login screen * }); */ diff --git a/src/content-repo.js b/src/content-repo.js index 8a5f9f06b..9c0a3306b 100644 --- a/src/content-repo.js +++ b/src/content-repo.js @@ -47,7 +47,7 @@ module.exports = { } } let serverAndMediaId = mxc.slice(6); // strips mxc:// - let prefix = "/_matrix/media/v1/download/"; + let prefix = "/_matrix/media/r0/download/"; const params = {}; if (width) { @@ -62,7 +62,7 @@ module.exports = { if (utils.keys(params).length > 0) { // these are thumbnailing params so they probably want the // thumbnailing API... - prefix = "/_matrix/media/v1/thumbnail/"; + prefix = "/_matrix/media/r0/thumbnail/"; } const fragmentOffset = serverAndMediaId.indexOf("#"); @@ -83,6 +83,7 @@ module.exports = { * @param {Number} width The desired width of the image in pixels. Default: 96. * @param {Number} height The desired height of the image in pixels. Default: 96. * @return {string} The complete URL to the identicon. + * @deprecated This is no longer in the specification. */ getIdenticonUri: function(baseUrl, identiconString, width, height) { if (!identiconString) { @@ -99,7 +100,7 @@ module.exports = { height: height, }; - const path = utils.encodeUri("/_matrix/media/v1/identicon/$ident", { + const path = utils.encodeUri("/_matrix/media/unstable/identicon/$ident", { $ident: identiconString, }); return baseUrl + path + diff --git a/src/crypto/OlmDevice.js b/src/crypto/OlmDevice.js index d47f19baa..7060074a7 100644 --- a/src/crypto/OlmDevice.js +++ b/src/crypto/OlmDevice.js @@ -594,6 +594,11 @@ OlmDevice.prototype.encryptMessage = async function( 'readwrite', [IndexedDBCryptoStore.STORE_SESSIONS], (txn) => { this._getSession(theirDeviceIdentityKey, sessionId, txn, (sessionInfo) => { + const sessionDesc = sessionInfo.session.describe(); + console.log( + "Session ID " + sessionId + " to " + + theirDeviceIdentityKey + ": " + sessionDesc, + ); res = sessionInfo.session.encrypt(payloadString); this._saveSession(theirDeviceIdentityKey, sessionInfo, txn); }); @@ -621,6 +626,11 @@ OlmDevice.prototype.decryptMessage = async function( 'readwrite', [IndexedDBCryptoStore.STORE_SESSIONS], (txn) => { this._getSession(theirDeviceIdentityKey, sessionId, txn, (sessionInfo) => { + const sessionDesc = sessionInfo.session.describe(); + console.log( + "Session ID " + sessionId + " to " + + theirDeviceIdentityKey + ": " + sessionDesc, + ); payloadString = sessionInfo.session.decrypt(messageType, ciphertext); sessionInfo.lastReceivedMessageTs = Date.now(); this._saveSession(theirDeviceIdentityKey, sessionInfo, txn); diff --git a/src/crypto/algorithms/megolm.js b/src/crypto/algorithms/megolm.js index deeb865ec..4262c2cee 100644 --- a/src/crypto/algorithms/megolm.js +++ b/src/crypto/algorithms/megolm.js @@ -23,7 +23,7 @@ limitations under the License. */ import Promise from 'bluebird'; -import logger from '../../../src/logger'; +import logger from '../../logger'; const utils = require("../../utils"); const olmlib = require("../olmlib"); diff --git a/src/crypto/index.js b/src/crypto/index.js index 9379026c9..a96e224dc 100644 --- a/src/crypto/index.js +++ b/src/crypto/index.js @@ -1224,6 +1224,132 @@ Crypto.prototype.setDeviceVerification = async function( }; +function verificationEventHandler(target, userId, roomId, eventId) { + return function(event) { + // listen for events related to this verification + if (event.getRoomId() !== roomId + || event.getSender() !== userId) { + return; + } + const content = event.getContent(); + if (!content["m.relates_to"]) { + return; + } + const relatesTo + = content["m.relationship"] || content["m.relates_to"]; + if (!relatesTo.rel_type + || relatesTo.rel_type !== "m.reference" + || !relatesTo.event_id + || relatesTo.event_id !== eventId) { + return; + } + + // the event seems to be related to this verification, so pass it on to + // the verification handler + target.handleEvent(event); + }; +} + +Crypto.prototype.requestVerificationDM = async function(userId, roomId, methods) { + let methodMap; + if (methods) { + methodMap = new Map(); + for (const method of methods) { + if (typeof method === "string") { + methodMap.set(method, defaultVerificationMethods[method]); + } else if (method.NAME) { + methodMap.set(method.NAME, method); + } + } + } else { + methodMap = this._baseApis._crypto._verificationMethods; + } + + let eventId = undefined; + const listenPromise = new Promise((_resolve, _reject) => { + const listener = (event) => { + // listen for events related to this verification + if (event.getRoomId() !== roomId + || event.getSender() !== userId) { + return; + } + const relatesTo = event.getRelation(); + if (!relatesTo || !relatesTo.rel_type + || relatesTo.rel_type !== "m.reference" + || !relatesTo.event_id + || relatesTo.event_id !== eventId) { + return; + } + + const content = event.getContent(); + // the event seems to be related to this verification + switch (event.getType()) { + case "m.key.verification.start": { + const verifier = new (methodMap.get(content.method))( + this._baseApis, userId, content.from_device, eventId, + roomId, event, + ); + verifier.handler = verificationEventHandler( + verifier, userId, roomId, eventId, + ); + // this handler gets removed when the verification finishes + // (see the verify method of crypto/verification/Base.js) + this._baseApis.on("event", verifier.handler); + resolve(verifier); + break; + } + case "m.key.verification.cancel": { + reject(event); + break; + } + } + }; + this._baseApis.on("event", listener); + + const resolve = (...args) => { + this._baseApis.off("event", listener); + _resolve(...args); + }; + const reject = (...args) => { + this._baseApis.off("event", listener); + _reject(...args); + }; + }); + + const res = await this._baseApis.sendEvent( + roomId, "m.room.message", + { + body: this._baseApis.getUserId() + " is requesting to verify " + + "your key, but your client does not support in-chat key " + + "verification. You will need to use legacy key " + + "verification to verify keys.", + msgtype: "m.key.verification.request", + to: userId, + from_device: this._baseApis.getDeviceId(), + methods: [...methodMap.keys()], + }, + ); + eventId = res.event_id; + + return listenPromise; +}; + +Crypto.prototype.acceptVerificationDM = function(event, Method) { + if (typeof(Method) === "string") { + Method = defaultVerificationMethods[Method]; + } + const content = event.getContent(); + const verifier = new Method( + this._baseApis, event.getSender(), content.from_device, event.getId(), + event.getRoomId(), + ); + verifier.handler = verificationEventHandler( + verifier, event.getSender(), event.getRoomId(), event.getId(), + ); + this._baseApis.on("event", verifier.handler); + return verifier; +}; + Crypto.prototype.requestVerification = function(userId, methods, devices) { if (!methods) { // .keys() returns an iterator, so we need to explicitly turn it into an array @@ -1271,20 +1397,7 @@ Crypto.prototype.beginKeyVerification = function( this._verificationTransactions.set(userId, new Map()); } transactionId = transactionId || randomString(32); - if (method instanceof Array) { - if (method.length !== 2 - || !this._verificationMethods.has(method[0]) - || !this._verificationMethods.has(method[1])) { - throw newUnknownMethodError(); - } - /* - return new TwoPartVerification( - this._verificationMethods[method[0]], - this._verificationMethods[method[1]], - userId, deviceId, transactionId, - ); - */ - } else if (this._verificationMethods.has(method)) { + if (this._verificationMethods.has(method)) { const verifier = new (this._verificationMethods.get(method))( this._baseApis, userId, deviceId, transactionId, ); @@ -1419,6 +1532,15 @@ Crypto.prototype.forceDiscardSession = function(roomId) { * the device query is always inhibited as the members are not tracked. */ Crypto.prototype.setRoomEncryption = async function(roomId, config, inhibitDeviceQuery) { + // ignore crypto events with no algorithm defined + // This will happen if a crypto event is redacted before we fetch the room state + // It would otherwise just throw later as an unknown algorithm would, but we may + // as well catch this here + if (!config.algorithm) { + console.log("Ignoring setRoomEncryption with no algorithm"); + return; + } + // if state is being replayed from storage, we might already have a configuration // for this room as they are persisted as well. // We just need to make sure the algorithm is initialized in this case. @@ -1756,6 +1878,18 @@ Crypto.prototype.backupGroupSession = async function( * upload in the background as soon as possible. */ Crypto.prototype.scheduleAllGroupSessionsForBackup = async function() { + await this.flagAllGroupSessionsForBackup(); + + // Schedule keys to upload in the background as soon as possible. + this.scheduleKeyBackupSend(0 /* maxDelay */); +}; + +/** + * Marks all group sessions as needing to be backed up without scheduling + * them to upload in the background. + * @returns {Promise} Resolves to the number of sessions requiring a backup. + */ +Crypto.prototype.flagAllGroupSessionsForBackup = async function() { await this._cryptoStore.doTxn( 'readwrite', [ @@ -1773,9 +1907,7 @@ Crypto.prototype.scheduleAllGroupSessionsForBackup = async function() { const remaining = await this._cryptoStore.countSessionsNeedingBackup(); this.emit("crypto.keyBackupSessionsRemaining", remaining); - - // Schedule keys to upload in the background as soon as possible. - this.scheduleKeyBackupSend(0 /* maxDelay */); + return remaining; }; /* eslint-disable valid-jsdoc */ //https://github.com/eslint/eslint/issues/7307 @@ -2122,6 +2254,11 @@ Crypto.prototype._onRoomKeyEvent = function(event) { * @param {module:models/event.MatrixEvent} event verification request event */ Crypto.prototype._onKeyVerificationRequest = function(event) { + if (event.isCancelled()) { + logger.warn("Ignoring flagged verification request from " + event.getSender()); + return; + } + const content = event.getContent(); if (!("from_device" in content) || typeof content.from_device !== "string" || !("transaction_id" in content) || typeof content.from_device !== "string" @@ -2238,6 +2375,11 @@ Crypto.prototype._onKeyVerificationRequest = function(event) { * @param {module:models/event.MatrixEvent} event verification start event */ Crypto.prototype._onKeyVerificationStart = function(event) { + if (event.isCancelled()) { + logger.warn("Ignoring flagged verification start from " + event.getSender()); + return; + } + const sender = event.getSender(); const content = event.getContent(); const transactionId = content.transaction_id; @@ -2271,22 +2413,6 @@ Crypto.prototype._onKeyVerificationStart = function(event) { transaction_id: content.transactionId, })); return; - } else if (content.next_method) { - if (!this._verificationMethods.has(content.next_method)) { - cancel(newUnknownMethodError({ - transaction_id: content.transactionId, - })); - return; - } else { - /* TODO: - const verification = new TwoPartVerification( - this._verificationMethods[content.method], - this._verificationMethods[content.next_method], - userId, deviceId, - ); - this.emit(verification.event_type, verification); - this.emit(verification.first.event_type, verification);*/ - } } else { const verifier = new (this._verificationMethods.get(content.method))( this._baseApis, sender, deviceId, content.transaction_id, @@ -2341,8 +2467,6 @@ Crypto.prototype._onKeyVerificationStart = function(event) { handler.request.resolve(verifier); } - } else { - // FIXME: make sure we're in a two-part verification, and the start matches the second part } } this._baseApis.emit("crypto.verification.start", verifier); diff --git a/src/crypto/store/indexeddb-crypto-store-backend.js b/src/crypto/store/indexeddb-crypto-store-backend.js index 76f066887..98c5d8945 100644 --- a/src/crypto/store/indexeddb-crypto-store-backend.js +++ b/src/crypto/store/indexeddb-crypto-store-backend.js @@ -719,7 +719,7 @@ function promiseifyTxn(txn) { if (txn._mx_abortexception !== undefined) { reject(txn._mx_abortexception); } else { - localStorage.log("Error performing indexeddb txn", event); + logger.log("Error performing indexeddb txn", event); reject(event.target.error); } }; diff --git a/src/crypto/store/localStorage-crypto-store.js b/src/crypto/store/localStorage-crypto-store.js index fd7934bb1..88e664ba0 100644 --- a/src/crypto/store/localStorage-crypto-store.js +++ b/src/crypto/store/localStorage-crypto-store.js @@ -17,7 +17,7 @@ limitations under the License. import Promise from 'bluebird'; import logger from '../../logger'; -import MemoryCryptoStore from './memory-crypto-store.js'; +import MemoryCryptoStore from './memory-crypto-store'; /** * Internal module. Partial localStorage backed storage for e2e. diff --git a/src/crypto/verification/Base.js b/src/crypto/verification/Base.js index cee051c8d..cf65663c7 100644 --- a/src/crypto/verification/Base.js +++ b/src/crypto/verification/Base.js @@ -23,6 +23,9 @@ import {MatrixEvent} from '../../models/event'; import {EventEmitter} from 'events'; import logger from '../../logger'; import DeviceInfo from '../deviceinfo'; +import {newTimeoutError} from "./Error"; + +const timeoutException = new Error("Verification timed out"); export default class VerificationBase extends EventEmitter { /** @@ -45,27 +48,66 @@ export default class VerificationBase extends EventEmitter { * * @param {string} transactionId the transaction ID to be used when sending events * - * @param {object} startEvent the m.key.verification.start event that + * @param {string} [roomId] the room to use for verification + * + * @param {object} [startEvent] the m.key.verification.start event that * initiated this verification, if any * - * @param {object} request the key verification request object related to + * @param {object} [request] the key verification request object related to * this verification, if any - * - * @param {object} parent parent verification for this verification, if any */ - constructor(baseApis, userId, deviceId, transactionId, startEvent, request, parent) { + constructor(baseApis, userId, deviceId, transactionId, roomId, startEvent, request) { super(); this._baseApis = baseApis; this.userId = userId; this.deviceId = deviceId; this.transactionId = transactionId; - this.startEvent = startEvent; - this.request = request; - this._parent = parent; + if (typeof(roomId) === "string" || roomId instanceof String) { + this.roomId = roomId; + this.startEvent = startEvent; + this.request = request; + } else { + // if room ID was omitted, but start event and request were not + this.startEvent= roomId; + this.request = startEvent; + } + this.cancelled = false; this._done = false; this._promise = null; + this._transactionTimeoutTimer = null; + + // At this point, the verification request was received so start the timeout timer. + this._resetTimer(); + + if (this.roomId) { + this._send = this._sendMessage; + } else { + this._send = this._sendToDevice; + } } + _resetTimer() { + logger.info("Refreshing/starting the verification transaction timeout timer"); + if (this._transactionTimeoutTimer !== null) { + clearTimeout(this._transactionTimeoutTimer); + } + this._transactionTimeoutTimer = setTimeout(() => { + if (!this._done && !this.cancelled) { + logger.info("Triggering verification timeout"); + this.cancel(timeoutException); + } + }, 10 * 60 * 1000); // 10 minutes + } + + _endTimer() { + if (this._transactionTimeoutTimer !== null) { + clearTimeout(this._transactionTimeoutTimer); + this._transactionTimeoutTimer = null; + } + } + + /* send a message to the other participant, using to-device messages + */ _sendToDevice(type, content) { if (this._done) { return Promise.reject(new Error("Verification is already done")); @@ -76,6 +118,21 @@ export default class VerificationBase extends EventEmitter { }); } + /* send a message to the other participant, using in-roomm messages + */ + _sendMessage(type, content) { + if (this._done) { + return Promise.reject(new Error("Verification is already done")); + } + // FIXME: if MSC1849 decides to use m.relationship instead of + // m.relates_to, we should follow suit here + content["m.relates_to"] = { + rel_type: "m.reference", + event_id: this.transactionId, + }; + return this._baseApis.sendEvent(this.roomId, type, content); + } + _waitForEvent(type) { if (this._done) { return Promise.reject(new Error("Verification is already done")); @@ -93,6 +150,7 @@ export default class VerificationBase extends EventEmitter { } else if (e.getType() === this._expectedEvent) { this._expectedEvent = undefined; this._rejectEvent = undefined; + this._resetTimer(); this._resolveEvent(e); } else { this._expectedEvent = undefined; @@ -110,17 +168,27 @@ export default class VerificationBase extends EventEmitter { } done() { + this._endTimer(); // always kill the activity timer if (!this._done) { + if (this.roomId) { + // verification in DM requires a done message + this._send("m.key.verification.done", {}); + } this._resolve(); } } cancel(e) { + this._endTimer(); // always kill the activity timer if (!this._done) { + this.cancelled = true; if (this.userId && this.deviceId && this.transactionId) { // send a cancellation to the other user (if it wasn't // cancelled by the other user) - if (e instanceof MatrixEvent) { + if (e === timeoutException) { + const timeoutEvent = newTimeoutError(); + this._send(timeoutEvent.getType(), timeoutEvent.getContent()); + } else if (e instanceof MatrixEvent) { const sender = e.getSender(); if (sender !== this.userId) { const content = e.getContent(); @@ -129,9 +197,9 @@ export default class VerificationBase extends EventEmitter { content.reason = content.reason || content.body || "Unknown reason"; content.transaction_id = this.transactionId; - this._sendToDevice("m.key.verification.cancel", content); + this._send("m.key.verification.cancel", content); } else { - this._sendToDevice("m.key.verification.cancel", { + this._send("m.key.verification.cancel", { code: "m.unknown", reason: content.body || "Unknown reason", transaction_id: this.transactionId, @@ -139,7 +207,7 @@ export default class VerificationBase extends EventEmitter { } } } else { - this._sendToDevice("m.key.verification.cancel", { + this._send("m.key.verification.cancel", { code: "m.unknown", reason: e.toString(), transaction_id: this.transactionId, @@ -147,7 +215,9 @@ export default class VerificationBase extends EventEmitter { } } if (this._promise !== null) { - this._reject(e); + // when we cancel without a promise, we end up with a promise + // but no reject function. If cancel is called again, we'd error. + if (this._reject) this._reject(e); } else { this._promise = Promise.reject(e); } @@ -169,15 +239,24 @@ export default class VerificationBase extends EventEmitter { this._promise = new Promise((resolve, reject) => { this._resolve = (...args) => { this._done = true; + this._endTimer(); + if (this.handler) { + this._baseApis.off("event", this.handler); + } resolve(...args); }; this._reject = (...args) => { this._done = true; + this._endTimer(); + if (this.handler) { + this._baseApis.off("event", this.handler); + } reject(...args); }; }); if (this._doVerification && !this._started) { this._started = true; + this._resetTimer(); // restart the timeout Promise.resolve(this._doVerification()) .then(this.done.bind(this), this.cancel.bind(this)); } diff --git a/src/crypto/verification/SAS.js b/src/crypto/verification/SAS.js index 363597704..d1cb0efe1 100644 --- a/src/crypto/verification/SAS.js +++ b/src/crypto/verification/SAS.js @@ -213,9 +213,10 @@ export default class SAS extends Base { message_authentication_codes: MAC_LIST, // FIXME: allow app to specify what SAS methods can be used short_authentication_string: SAS_LIST, - transaction_id: this.transactionId, }; - this._sendToDevice("m.key.verification.start", initialMessage); + // NOTE: this._send will modify initialMessage to include the + // transaction_id field, or the m.relationship/m.relates_to field + this._send("m.key.verification.start", initialMessage); let e = await this._waitForEvent("m.key.verification.accept"); @@ -235,7 +236,7 @@ export default class SAS extends Base { const hashCommitment = content.commitment; const olmSAS = new global.Olm.SAS(); try { - this._sendToDevice("m.key.verification.key", { + this._send("m.key.verification.key", { key: olmSAS.get_pubkey(), }); @@ -306,7 +307,7 @@ export default class SAS extends Base { const olmSAS = new global.Olm.SAS(); try { const commitmentStr = olmSAS.get_pubkey() + anotherjson.stringify(content); - this._sendToDevice("m.key.verification.accept", { + this._send("m.key.verification.accept", { key_agreement_protocol: keyAgreement, hash: hashMethod, message_authentication_code: macMethod, @@ -320,7 +321,7 @@ export default class SAS extends Base { // FIXME: make sure event is properly formed content = e.getContent(); olmSAS.set_their_key(content.key); - this._sendToDevice("m.key.verification.key", { + this._send("m.key.verification.key", { key: olmSAS.get_pubkey(), }); @@ -382,7 +383,7 @@ export default class SAS extends Base { keyList.sort().join(","), baseInfo + "KEY_IDS", ); - this._sendToDevice("m.key.verification.mac", { mac, keys }); + this._send("m.key.verification.mac", { mac, keys }); } async _checkMAC(olmSAS, content, method) { diff --git a/src/http-api.js b/src/http-api.js index 0c42f765e..4babe9f51 100644 --- a/src/http-api.js +++ b/src/http-api.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -22,7 +23,7 @@ import Promise from 'bluebird'; const parseContentType = require('content-type').parse; const utils = require("./utils"); -import logger from '../src/logger'; +import logger from './logger'; // we use our own implementation of setTimeout, so that if we get suspended in // the middle of a /sync, we cancel the sync as soon as we awake, rather than @@ -46,10 +47,15 @@ module.exports.PREFIX_R0 = "/_matrix/client/r0"; module.exports.PREFIX_UNSTABLE = "/_matrix/client/unstable"; /** - * URI path for the identity API + * URI path for v1 of the the identity API */ module.exports.PREFIX_IDENTITY_V1 = "/_matrix/identity/api/v1"; +/** + * URI path for the v2 identity API + */ +module.exports.PREFIX_IDENTITY_V2 = "/_matrix/identity/v2"; + /** * URI path for the media repo API */ @@ -90,6 +96,13 @@ module.exports.MatrixHttpApi = function MatrixHttpApi(event_emitter, opts) { }; module.exports.MatrixHttpApi.prototype = { + /** + * Sets the baase URL for the identity server + * @param {string} url The new base url + */ + setIdBaseUrl: function(url) { + this.opts.idBaseUrl = url; + }, /** * Get the content repository url with query parameters. @@ -102,7 +115,7 @@ module.exports.MatrixHttpApi.prototype = { }; return { base: this.opts.baseUrl, - path: "/_matrix/media/v1/upload", + path: "/_matrix/media/r0/upload", params: params, }; }, @@ -291,7 +304,7 @@ module.exports.MatrixHttpApi.prototype = { }); } }); - let url = this.opts.baseUrl + "/_matrix/media/v1/upload"; + let url = this.opts.baseUrl + "/_matrix/media/r0/upload"; const queryArgs = []; @@ -327,7 +340,7 @@ module.exports.MatrixHttpApi.prototype = { promise = this.authedRequest( opts.callback, "POST", "/upload", queryParams, body, { - prefix: "/_matrix/media/v1", + prefix: "/_matrix/media/r0", headers: {"Content-Type": contentType}, json: false, bodyParser: bodyParser, @@ -368,7 +381,18 @@ module.exports.MatrixHttpApi.prototype = { return this.uploads; }, - idServerRequest: function(callback, method, path, params, prefix) { + idServerRequest: function( + callback, + method, + path, + params, + prefix, + accessToken, + ) { + if (!this.opts.idBaseUrl) { + throw new Error("No Identity Server base URL set"); + } + const fullUri = this.opts.idBaseUrl + prefix + path; if (callback !== undefined && !utils.isFunction(callback)) { @@ -381,13 +405,17 @@ module.exports.MatrixHttpApi.prototype = { uri: fullUri, method: method, withCredentials: false, - json: false, + json: true, // we want a JSON response if we can _matrix_opts: this.opts, + headers: {}, }; - if (method == 'GET') { + if (method === 'GET') { opts.qs = params; - } else { - opts.form = params; + } else if (typeof params === "object") { + opts.json = params; + } + if (accessToken) { + opts.headers['Authorization'] = `Bearer ${accessToken}`; } const defer = Promise.defer(); @@ -395,12 +423,7 @@ module.exports.MatrixHttpApi.prototype = { opts, requestCallback(defer, callback, this.opts.onlyData), ); - // ID server does not always take JSON, so we can't use requests' 'json' - // option as we do with the home server, but it does return JSON, so - // parse it manually - return defer.promise.then(function(response) { - return JSON.parse(response); - }); + return defer.promise; }, /** @@ -470,7 +493,7 @@ module.exports.MatrixHttpApi.prototype = { const self = this; requestPromise.catch(function(err) { if (err.errcode == 'M_UNKNOWN_TOKEN') { - self.event_emitter.emit("Session.logged_out"); + self.event_emitter.emit("Session.logged_out", err); } else if (err.errcode == 'M_CONSENT_NOT_GIVEN') { self.event_emitter.emit( "no_consent", @@ -525,76 +548,6 @@ module.exports.MatrixHttpApi.prototype = { ); }, - /** - * Perform an authorised request to the homeserver with a specific path - * prefix which overrides the default for this call only. Useful for hitting - * different Matrix Client-Server versions. - * @param {Function} callback Optional. The callback to invoke on - * success/failure. See the promise return values for more information. - * @param {string} method The HTTP method e.g. "GET". - * @param {string} path The HTTP path after the supplied prefix e.g. - * "/createRoom". - * @param {Object} queryParams A dict of query params (these will NOT be - * urlencoded). - * @param {Object} data The HTTP JSON body. - * @param {string} prefix The full prefix to use e.g. - * "/_matrix/client/v2_alpha". - * @param {Number=} localTimeoutMs The maximum amount of time to wait before - * timing out the request. If not specified, there is no timeout. - * @return {module:client.Promise} Resolves to {data: {Object}, - * headers: {Object}, code: {Number}}. - * If onlyData is set, this will resolve to the data - * object only. - * @return {module:http-api.MatrixError} Rejects with an error if a problem - * occurred. This includes network problems and Matrix-specific error JSON. - * - * @deprecated prefer authedRequest with opts.prefix - */ - authedRequestWithPrefix: function(callback, method, path, queryParams, data, - prefix, localTimeoutMs) { - return this.authedRequest( - callback, method, path, queryParams, data, { - localTimeoutMs: localTimeoutMs, - prefix: prefix, - }, - ); - }, - - /** - * Perform a request to the homeserver without any credentials but with a - * specific path prefix which overrides the default for this call only. - * Useful for hitting different Matrix Client-Server versions. - * @param {Function} callback Optional. The callback to invoke on - * success/failure. See the promise return values for more information. - * @param {string} method The HTTP method e.g. "GET". - * @param {string} path The HTTP path after the supplied prefix e.g. - * "/createRoom". - * @param {Object} queryParams A dict of query params (these will NOT be - * urlencoded). - * @param {Object} data The HTTP JSON body. - * @param {string} prefix The full prefix to use e.g. - * "/_matrix/client/v2_alpha". - * @param {Number=} localTimeoutMs The maximum amount of time to wait before - * timing out the request. If not specified, there is no timeout. - * @return {module:client.Promise} Resolves to {data: {Object}, - * headers: {Object}, code: {Number}}. - * If onlyData is set, this will resolve to the data - * object only. - * @return {module:http-api.MatrixError} Rejects with an error if a problem - * occurred. This includes network problems and Matrix-specific error JSON. - * - * @deprecated prefer request with opts.prefix - */ - requestWithPrefix: function(callback, method, path, queryParams, data, prefix, - localTimeoutMs) { - return this.request( - callback, method, path, queryParams, data, { - localTimeoutMs: localTimeoutMs, - prefix: prefix, - }, - ); - }, - /** * Perform a request to an arbitrary URL. * @param {Function} callback Optional. The callback to invoke on @@ -883,7 +836,8 @@ function parseErrorResponse(response, body) { let err; if (contentType) { if (contentType.type === 'application/json') { - err = new module.exports.MatrixError(JSON.parse(body)); + const jsonBody = typeof(body) === 'object' ? body : JSON.parse(body); + err = new module.exports.MatrixError(jsonBody); } else if (contentType.type === 'text/plain') { err = new Error(`Server returned ${httpStatus} error: ${body}`); } diff --git a/src/interactive-auth.js b/src/interactive-auth.js index 57f164bd1..756756a2e 100644 --- a/src/interactive-auth.js +++ b/src/interactive-auth.js @@ -22,7 +22,7 @@ import Promise from 'bluebird'; const url = require("url"); const utils = require("./utils"); -import logger from '../src/logger'; +import logger from './logger'; const EMAIL_STAGE_TYPE = "m.login.email.identity"; const MSISDN_STAGE_TYPE = "m.login.msisdn"; @@ -174,16 +174,19 @@ InteractiveAuth.prototype = { // The email can be validated out-of-band, but we need to provide the // creds so the HS can go & check it. if (this._emailSid) { - const idServerParsedUrl = url.parse( - this._matrixClient.getIdentityServerUrl(), - ); + const creds = { + sid: this._emailSid, + client_secret: this._clientSecret, + }; + if (await this._matrixClient.doesServerRequireIdServerParam()) { + const idServerParsedUrl = url.parse( + this._matrixClient.getIdentityServerUrl(), + ); + creds.id_server = idServerParsedUrl.host; + } authDict = { type: EMAIL_STAGE_TYPE, - threepid_creds: { - sid: this._emailSid, - client_secret: this._clientSecret, - id_server: idServerParsedUrl.host, - }, + threepid_creds: creds, }; } } diff --git a/src/matrix.js b/src/matrix.js index 0460927ff..244b10f24 100644 --- a/src/matrix.js +++ b/src/matrix.js @@ -1,6 +1,7 @@ /* Copyright 2015, 2016 OpenMarket Ltd Copyright 2017 Vector Creations Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -76,6 +77,7 @@ module.exports.InteractiveAuth = require("./interactive-auth"); /** The {@link module:auto-discovery|AutoDiscovery} class. */ module.exports.AutoDiscovery = require("./autodiscovery").AutoDiscovery; +module.exports.SERVICE_TYPES = require('./service-types').SERVICE_TYPES; module.exports.MemoryCryptoStore = require("./crypto/store/memory-crypto-store").default; diff --git a/src/models/event-timeline-set.js b/src/models/event-timeline-set.js index 8f2fad30e..0a8602458 100644 --- a/src/models/event-timeline-set.js +++ b/src/models/event-timeline-set.js @@ -21,7 +21,7 @@ const EventEmitter = require("events").EventEmitter; const utils = require("../utils"); const EventTimeline = require("./event-timeline"); import {EventStatus} from "./event"; -import logger from '../../src/logger'; +import logger from '../logger'; import Relations from './relations'; // var DEBUG = false; @@ -92,6 +92,13 @@ function EventTimelineSet(room, opts) { } utils.inherits(EventTimelineSet, EventEmitter); +/** + * Get all the timelines in this set + * @return {module:models/event-timeline~EventTimeline[]} the timelines in this set + */ +EventTimelineSet.prototype.getTimelines = function() { + return this._timelines; +}; /** * Get the filter object this timeline set is filtered on, if any * @return {?Filter} the optional filter for this timelineSet @@ -438,7 +445,6 @@ EventTimelineSet.prototype.addEventsToTimeline = function(events, toStartOfTimel if (backwardsIsLive || forwardsIsLive) { // The live timeline should never be spliced into a non-live position. // We use independent logging to better discover the problem at a glance. - logger.warn({backwardsIsLive, forwardsIsLive}); // debugging if (backwardsIsLive) { logger.warn( "Refusing to set a preceding existingTimeLine on our " + @@ -689,9 +695,12 @@ EventTimelineSet.prototype.compareEventOrdering = function(eventId1, eventId2) { * The type of relation involved, such as "m.annotation", "m.reference", "m.replace", etc. * @param {String} eventType * The relation event's type, such as "m.reaction", etc. + * @throws If eventId, relationType or eventType + * are not valid. * - * @returns {Relations} - * A container for relation events. + * @returns {?Relations} + * A container for relation events or undefined if there are no relation events for + * the relationType. */ EventTimelineSet.prototype.getRelationsForEvent = function( eventId, relationType, eventType, diff --git a/src/models/event.js b/src/models/event.js index 50adc34a8..6aa39c943 100644 --- a/src/models/event.js +++ b/src/models/event.js @@ -24,14 +24,14 @@ limitations under the License. import Promise from 'bluebird'; import {EventEmitter} from 'events'; import utils from '../utils.js'; -import logger from '../../src/logger'; +import logger from '../logger'; /** * Enum for event statuses. * @readonly * @enum {string} */ -module.exports.EventStatus = { +const EventStatus = { /** The event was not sent and will no longer be retried. */ NOT_SENT: "not_sent", @@ -49,6 +49,7 @@ module.exports.EventStatus = { /** The event was cancelled before it was successfully sent. */ CANCELLED: "cancelled", }; +module.exports.EventStatus = EventStatus; const interns = {}; function intern(str) { @@ -124,7 +125,8 @@ module.exports.MatrixEvent = function MatrixEvent( this.forwardLooking = true; this._pushActions = null; this._replacingEvent = null; - this._locallyRedacted = false; + this._localRedactionEvent = null; + this._isCancelled = false; this._clearEvent = {}; @@ -229,7 +231,7 @@ utils.extend(module.exports.MatrixEvent.prototype, { * @return {Object} The event content JSON, or an empty object. */ getOriginalContent: function() { - if (this._locallyRedacted) { + if (this._localRedactionEvent) { return {}; } return this._clearEvent.content || this.event.content || {}; @@ -243,7 +245,7 @@ utils.extend(module.exports.MatrixEvent.prototype, { * @return {Object} The event content JSON, or an empty object. */ getContent: function() { - if (this._locallyRedacted) { + if (this._localRedactionEvent) { return {}; } else if (this._replacingEvent) { return this._replacingEvent.getContent()["m.new_content"] || {}; @@ -673,20 +675,20 @@ utils.extend(module.exports.MatrixEvent.prototype, { }, unmarkLocallyRedacted: function() { - const value = this._locallyRedacted; - this._locallyRedacted = false; + const value = this._localRedactionEvent; + this._localRedactionEvent = null; if (this.event.unsigned) { this.event.unsigned.redacted_because = null; } - return value; + return !!value; }, markLocallyRedacted: function(redactionEvent) { - if (this._locallyRedacted) { + if (this._localRedactionEvent) { return; } this.emit("Event.beforeRedaction", this, redactionEvent); - this._locallyRedacted = true; + this._localRedactionEvent = redactionEvent; if (!this.event.unsigned) { this.event.unsigned = {}; } @@ -706,7 +708,7 @@ utils.extend(module.exports.MatrixEvent.prototype, { throw new Error("invalid redaction_event in makeRedacted"); } - this._locallyRedacted = false; + this._localRedactionEvent = null; this.emit("Event.beforeRedaction", this, redaction_event); @@ -867,7 +869,11 @@ utils.extend(module.exports.MatrixEvent.prototype, { * @param {MatrixEvent?} newEvent the event with the replacing content, if any. */ makeReplaced(newEvent) { - if (this.isRedacted()) { + // don't allow redacted events to be replaced. + // if newEvent is null we allow to go through though, + // as with local redaction, the replacing event might get + // cancelled, which should be reflected on the target event. + if (this.isRedacted() && newEvent) { return; } if (this._replacingEvent !== newEvent) { @@ -877,15 +883,25 @@ utils.extend(module.exports.MatrixEvent.prototype, { }, /** - * Returns the status of the event, or the replacing event in case `makeReplace` has been called. + * Returns the status of any associated edit or redaction + * (not for reactions/annotations as their local echo doesn't affect the orignal event), + * or else the status of the event. * * @return {EventStatus} */ - replacementOrOwnStatus() { + getAssociatedStatus() { if (this._replacingEvent) { return this._replacingEvent.status; - } else { - return this.status; + } else if (this._localRedactionEvent) { + return this._localRedactionEvent.status; + } + return this.status; + }, + + getServerAggregatedRelation(relType) { + const relations = this.getUnsigned()["m.relations"]; + if (relations) { + return relations[relType]; } }, @@ -895,11 +911,18 @@ utils.extend(module.exports.MatrixEvent.prototype, { * @return {string?} */ replacingEventId() { - return this._replacingEvent && this._replacingEvent.getId(); + const replaceRelation = this.getServerAggregatedRelation("m.replace"); + if (replaceRelation) { + return replaceRelation.event_id; + } else if (this._replacingEvent) { + return this._replacingEvent.getId(); + } }, /** * Returns the event replacing the content of this event, if any. + * Replacements are aggregated on the server, so this would only + * return an event in case it came down the sync, or for local echo of edits. * * @return {MatrixEvent?} */ @@ -907,6 +930,31 @@ utils.extend(module.exports.MatrixEvent.prototype, { return this._replacingEvent; }, + /** + * Returns the origin_server_ts of the event replacing the content of this event, if any. + * + * @return {Date?} + */ + replacingEventDate() { + const replaceRelation = this.getServerAggregatedRelation("m.replace"); + if (replaceRelation) { + const ts = replaceRelation.origin_server_ts; + if (Number.isFinite(ts)) { + return new Date(ts); + } + } else if (this._replacingEvent) { + return this._replacingEvent.getDate(); + } + }, + + /** + * Returns the event that wants to redact this event, but hasn't been sent yet. + * @return {MatrixEvent} the event + */ + localRedactionEvent() { + return this._localRedactionEvent; + }, + /** * For relations and redactions, returns the event_id this event is referring to. * @@ -947,6 +995,25 @@ utils.extend(module.exports.MatrixEvent.prototype, { } }, + /** + * Flags an event as cancelled due to future conditions. For example, a verification + * request event in the same sync transaction may be flagged as cancelled to warn + * listeners that a cancellation event is coming down the same pipe shortly. + * @param {boolean} cancelled Whether the event is to be cancelled or not. + */ + flagCancelled(cancelled = true) { + this._isCancelled = cancelled; + }, + + /** + * Gets whether or not the event is flagged as cancelled. See flagCancelled() for + * more information. + * @returns {boolean} True if the event is cancelled, false otherwise. + */ + isCancelled() { + return this._isCancelled; + }, + /** * Summarise the event as JSON for debugging. If encrypted, include both the * decrypted and encrypted view of the event. This is named `toJSON` for use @@ -966,6 +1033,11 @@ utils.extend(module.exports.MatrixEvent.prototype, { room_id: this.getRoomId(), }; + // if this is a redaction then attach the redacts key + if (this.isRedaction()) { + event.redacts = this.event.redacts; + } + if (!this.isEncrypted()) { return event; } @@ -981,7 +1053,7 @@ utils.extend(module.exports.MatrixEvent.prototype, { /* _REDACT_KEEP_KEY_MAP gives the keys we keep when an event is redacted * * This is specified here: - * http://matrix.org/speculator/spec/HEAD/client_server/unstable.html#redactions + * http://matrix.org/speculator/spec/HEAD/client_server/latest.html#redactions * * Also: * - We keep 'unsigned' since that is created by the local server diff --git a/src/models/relations.js b/src/models/relations.js index 22ed41669..5b2045a45 100644 --- a/src/models/relations.js +++ b/src/models/relations.js @@ -301,10 +301,20 @@ export default class Relations extends EventEmitter { // event is known anyway. return null; } + + // the all-knowning server tells us that the event at some point had + // this timestamp for its replacement, so any following replacement should definitely not be less + const replaceRelation = + this._targetEvent.getServerAggregatedRelation("m.replace"); + const minTs = replaceRelation && replaceRelation.origin_server_ts; + return this.getRelations().reduce((last, event) => { if (event.getSender() !== this._targetEvent.getSender()) { return last; } + if (minTs && minTs > event.getTs()) { + return last; + } if (last && last.getTs() > event.getTs()) { return last; } diff --git a/src/models/room-member.js b/src/models/room-member.js index bbc7b5e23..d92267720 100644 --- a/src/models/room-member.js +++ b/src/models/room-member.js @@ -249,7 +249,7 @@ RoomMember.prototype.getDMInviter = function() { * "crop" or "scale". * @param {Boolean} allowDefault (optional) Passing false causes this method to * return null if the user has no avatar image. Otherwise, a default image URL - * will be returned. Default: true. + * will be returned. Default: true. (Deprecated) * @param {Boolean} allowDirectLinks (optional) If true, the avatar URL will be * returned even if it is a direct hyperlink rather than a matrix content URL. * If false, any non-matrix content URLs will be ignored. Setting this option to diff --git a/src/models/room-state.js b/src/models/room-state.js index 280b50a8a..cb1579f46 100644 --- a/src/models/room-state.js +++ b/src/models/room-state.js @@ -21,7 +21,7 @@ const EventEmitter = require("events").EventEmitter; const utils = require("../utils"); const RoomMember = require("./room-member"); -import logger from '../../src/logger'; +import logger from '../logger'; // possible statuses for out-of-band member loading const OOB_STATUS_NOTSTARTED = 1; diff --git a/src/models/room.js b/src/models/room.js index a77aaa24f..44968771a 100644 --- a/src/models/room.js +++ b/src/models/room.js @@ -1,6 +1,7 @@ /* Copyright 2015, 2016 OpenMarket Ltd Copyright 2018, 2019 New Vector Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -29,7 +30,7 @@ const ContentRepo = require("../content-repo"); const EventTimeline = require("./event-timeline"); const EventTimelineSet = require("./event-timeline-set"); -import logger from '../../src/logger'; +import logger from '../logger'; import ReEmitter from '../ReEmitter'; // These constants are used as sane defaults when the homeserver doesn't support @@ -38,7 +39,7 @@ import ReEmitter from '../ReEmitter'; // room versions which are considered okay for people to run without being asked // to upgrade (ie: "stable"). Eventually, we should remove these when all homeservers // return an m.room_versions capability. -const KNOWN_SAFE_ROOM_VERSION = '1'; +const KNOWN_SAFE_ROOM_VERSION = '4'; const SAFE_ROOM_VERSIONS = ['1', '2', '3', '4']; function synthesizeReceipt(userId, event, receiptType) { @@ -346,13 +347,30 @@ Room.prototype.userMayUpgradeRoom = function(userId) { Room.prototype.getPendingEvents = function() { if (this._opts.pendingEventOrdering !== "detached") { throw new Error( - "Cannot call getPendingEventList with pendingEventOrdering == " + + "Cannot call getPendingEvents with pendingEventOrdering == " + this._opts.pendingEventOrdering); } return this._pendingEventList; }; +/** + * Check whether the pending event list contains a given event by ID. + * + * @param {string} eventId The event ID to check for. + * @return {boolean} + * @throws If opts.pendingEventOrdering was not 'detached' + */ +Room.prototype.hasPendingEvent = function(eventId) { + if (this._opts.pendingEventOrdering !== "detached") { + throw new Error( + "Cannot call hasPendingEvent with pendingEventOrdering == " + + this._opts.pendingEventOrdering); + } + + return this._pendingEventList.some(event => event.getId() === eventId); +}; + /** * Get the live unfiltered timeline for this room. * @@ -763,7 +781,7 @@ Room.prototype.getBlacklistUnverifiedDevices = function() { * @param {string} resizeMethod The thumbnail resize method to use, either * "crop" or "scale". * @param {boolean} allowDefault True to allow an identicon for this room if an - * avatar URL wasn't explicitly set. Default: true. + * avatar URL wasn't explicitly set. Default: true. (Deprecated) * @return {?string} the avatar URL or null. */ Room.prototype.getAvatarUrl = function(baseUrl, width, height, resizeMethod, @@ -797,20 +815,20 @@ Room.prototype.getAvatarUrl = function(baseUrl, width, height, resizeMethod, * @return {array} The room's alias as an array of strings */ Room.prototype.getAliases = function() { - const alias_strings = []; + const aliasStrings = []; - const alias_events = this.currentState.getStateEvents("m.room.aliases"); - if (alias_events) { - for (let i = 0; i < alias_events.length; ++i) { - const alias_event = alias_events[i]; - if (utils.isArray(alias_event.getContent().aliases)) { + const aliasEvents = this.currentState.getStateEvents("m.room.aliases"); + if (aliasEvents) { + for (let i = 0; i < aliasEvents.length; ++i) { + const aliasEvent = aliasEvents[i]; + if (utils.isArray(aliasEvent.getContent().aliases)) { Array.prototype.push.apply( - alias_strings, alias_event.getContent().aliases, + aliasStrings, aliasEvent.getContent().aliases, ); } } } - return alias_strings; + return aliasStrings; }; /** @@ -1039,6 +1057,18 @@ Room.prototype._addLiveEvent = function(event, duplicateStrategy) { const redactedEvent = this.getUnfilteredTimelineSet().findEventById(redactId); if (redactedEvent) { redactedEvent.makeRedacted(event); + + // If this is in the current state, replace it with the redacted version + if (redactedEvent.getStateKey()) { + const currentStateEvent = this.currentState.getStateEvents( + redactedEvent.getType(), + redactedEvent.getStateKey(), + ); + if (currentStateEvent.getId() === redactedEvent.getId()) { + this.currentState.setStateEvents([redactedEvent]); + } + } + this.emit("Room.redaction", event, this); // TODO: we stash user displaynames (among other things) in @@ -1157,7 +1187,7 @@ Room.prototype.addPendingEvent = function(event, txnId) { for (let i = 0; i < this._timelineSets.length; i++) { const timelineSet = this._timelineSets[i]; if (timelineSet.getFilter()) { - if (this._filter.filterRoomTimeline([event]).length) { + if (timelineSet.getFilter().filterRoomTimeline([event]).length) { timelineSet.addEventToTimeline(event, timelineSet.getLiveTimeline(), false); } @@ -1186,7 +1216,7 @@ Room.prototype._aggregateNonLiveRelation = function(event) { for (let i = 0; i < this._timelineSets.length; i++) { const timelineSet = this._timelineSets[i]; if (timelineSet.getFilter()) { - if (this._filter.filterRoomTimeline([event]).length) { + if (timelineSet.getFilter().filterRoomTimeline([event]).length) { timelineSet.aggregateRelations(event); } } else { @@ -1402,28 +1432,33 @@ Room.prototype.addLiveEvents = function(events, duplicateStrategy) { } for (i = 0; i < events.length; i++) { - if (events[i].getType() === "m.typing") { - this.currentState.setTypingEvent(events[i]); - } else if (events[i].getType() === "m.receipt") { - this.addReceipt(events[i]); - } - // N.B. account_data is added directly by /sync to avoid - // having to maintain an event.isAccountData() here - else { - // TODO: We should have a filter to say "only add state event - // types X Y Z to the timeline". - this._addLiveEvent(events[i], duplicateStrategy); - } + // TODO: We should have a filter to say "only add state event + // types X Y Z to the timeline". + this._addLiveEvent(events[i], duplicateStrategy); + } +}; + +/** + * Adds/handles ephemeral events such as typing notifications and read receipts. + * @param {MatrixEvent[]} events A list of events to process + */ +Room.prototype.addEphemeralEvents = function(events) { + for (const event of events) { + if (event.getType() === 'm.typing') { + this.currentState.setTypingEvent(event); + } else if (event.getType() === 'm.receipt') { + this.addReceipt(event); + } // else ignore - life is too short for us to care about these events } }; /** * Removes events from this room. - * @param {String[]} event_ids A list of event_ids to remove. + * @param {String[]} eventIds A list of eventIds to remove. */ -Room.prototype.removeEvents = function(event_ids) { - for (let i = 0; i < event_ids.length; ++i) { - this.removeEvent(event_ids[i]); +Room.prototype.removeEvents = function(eventIds) { + for (let i = 0; i < eventIds.length; ++i) { + this.removeEvent(eventIds[i]); } }; diff --git a/src/pushprocessor.js b/src/pushprocessor.js index 544fdabd1..0cf05cacf 100644 --- a/src/pushprocessor.js +++ b/src/pushprocessor.js @@ -43,6 +43,11 @@ const DEFAULT_OVERRIDE_RULES = [ key: "type", pattern: "m.room.tombstone", }, + { + kind: "event_match", + key: "state_key", + pattern: "", + }, ], actions: [ "notify", @@ -52,6 +57,22 @@ const DEFAULT_OVERRIDE_RULES = [ }, ], }, + { + // For homeservers which don't support MSC2153 yet + rule_id: ".m.rule.reaction", + default: true, + enabled: true, + conditions: [ + { + kind: "event_match", + key: "type", + pattern: "m.reaction", + }, + ], + actions: [ + "dont_notify", + ], + }, ]; /** @@ -439,6 +460,38 @@ PushProcessor.actionListToActionsObject = function(actionlist) { return actionobj; }; +/** + * Rewrites conditions on a client's push rules to match the defaults + * where applicable. Useful for upgrading push rules to more strict + * conditions when the server is falling behind on defaults. + * @param {object} incomingRules The client's existing push rules + * @returns {object} The rewritten rules + */ +PushProcessor.rewriteDefaultRules = function(incomingRules) { + let newRules = JSON.parse(JSON.stringify(incomingRules)); // deep clone + + // These lines are mostly to make the tests happy. We shouldn't run into these + // properties missing in practice. + if (!newRules) newRules = {}; + if (!newRules.global) newRules.global = {}; + if (!newRules.global.override) newRules.global.override = []; + + // Fix default override rules + newRules.global.override = newRules.global.override.map(r => { + const defaultRule = DEFAULT_OVERRIDE_RULES.find(d => d.rule_id === r.rule_id); + if (!defaultRule) return r; + + // Copy over the actions, default, and conditions. Don't touch the user's + // preference. + r.default = defaultRule.default; + r.conditions = defaultRule.conditions; + r.actions = defaultRule.actions; + return r; + }); + + return newRules; +}; + /** * @typedef {Object} PushAction * @type {Object} diff --git a/src/realtime-callbacks.js b/src/realtime-callbacks.js index 6e0e88910..ee2faa1e5 100644 --- a/src/realtime-callbacks.js +++ b/src/realtime-callbacks.js @@ -24,7 +24,7 @@ limitations under the License. */ "use strict"; -import logger from '../src/logger'; +import logger from './logger'; // we schedule a callback at least this often, to check if we've missed out on // some wall-clock time due to being suspended. diff --git a/src/scheduler.js b/src/scheduler.js index a799597b9..1b8d46f67 100644 --- a/src/scheduler.js +++ b/src/scheduler.js @@ -21,7 +21,7 @@ limitations under the License. */ const utils = require("./utils"); import Promise from 'bluebird'; -import logger from '../src/logger'; +import logger from './logger'; const DEBUG = false; // set true to enable console logging. diff --git a/src/service-types.js b/src/service-types.js new file mode 100644 index 000000000..0803b9247 --- /dev/null +++ b/src/service-types.js @@ -0,0 +1,20 @@ +/* +Copyright 2019 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +export const SERVICE_TYPES = Object.freeze({ + IS: 'SERVICE_TYPE_IS', // An Identity Service + IM: 'SERVICE_TYPE_IM', // An Integration Manager +}); diff --git a/src/store/indexeddb-local-backend.js b/src/store/indexeddb-local-backend.js index 7d6662794..b1ddb144d 100644 --- a/src/store/indexeddb-local-backend.js +++ b/src/store/indexeddb-local-backend.js @@ -19,7 +19,7 @@ import Promise from 'bluebird'; import SyncAccumulator from "../sync-accumulator"; import utils from "../utils"; import * as IndexedDBHelpers from "../indexeddb-helpers"; -import logger from '../../src/logger'; +import logger from '../logger'; const VERSION = 3; diff --git a/src/store/indexeddb-remote-backend.js b/src/store/indexeddb-remote-backend.js index 896d53b74..920739b6e 100644 --- a/src/store/indexeddb-remote-backend.js +++ b/src/store/indexeddb-remote-backend.js @@ -16,7 +16,7 @@ limitations under the License. */ import Promise from 'bluebird'; -import logger from '../../src/logger'; +import logger from '../logger'; /** * An IndexedDB store backend where the actual backend sits in a web diff --git a/src/store/indexeddb-store-worker.js b/src/store/indexeddb-store-worker.js index 93d374d2f..c47fcc176 100644 --- a/src/store/indexeddb-store-worker.js +++ b/src/store/indexeddb-store-worker.js @@ -17,7 +17,7 @@ limitations under the License. import Promise from 'bluebird'; import LocalIndexedDBStoreBackend from "./indexeddb-local-backend.js"; -import logger from '../../src/logger'; +import logger from '../logger'; /** * This class lives in the webworker and drives a LocalIndexedDBStoreBackend diff --git a/src/store/indexeddb.js b/src/store/indexeddb.js index dd8978b76..f2f759de8 100644 --- a/src/store/indexeddb.js +++ b/src/store/indexeddb.js @@ -25,7 +25,7 @@ import LocalIndexedDBStoreBackend from "./indexeddb-local-backend.js"; import RemoteIndexedDBStoreBackend from "./indexeddb-remote-backend.js"; import User from "../models/user"; import {MatrixEvent} from "../models/event"; -import logger from '../../src/logger'; +import logger from '../logger'; /** * This is an internal module. See {@link IndexedDBStore} for the public class. diff --git a/src/sync-accumulator.js b/src/sync-accumulator.js index 1810429df..8d9b3b787 100644 --- a/src/sync-accumulator.js +++ b/src/sync-accumulator.js @@ -21,7 +21,7 @@ limitations under the License. */ import utils from "./utils"; -import logger from '../src/logger'; +import logger from './logger'; /** diff --git a/src/sync.js b/src/sync.js index 7d9e2e3ff..590cc16b4 100644 --- a/src/sync.js +++ b/src/sync.js @@ -32,7 +32,8 @@ const Group = require('./models/group'); const utils = require("./utils"); const Filter = require("./filter"); const EventTimeline = require("./models/event-timeline"); -import logger from '../src/logger'; +const PushProcessor = require("./pushprocessor"); +import logger from './logger'; import {InvalidStoreError} from './errors'; @@ -1030,8 +1031,9 @@ SyncApi.prototype._processSyncResponse = async function( // honour push rules that were previously cached. Base rules // will be updated when we recieve push rules via getPushRules // (see SyncApi.prototype.sync) before syncing over the network. - if (accountDataEvent.getType() == 'm.push_rules') { - client.pushRules = accountDataEvent.getContent(); + if (accountDataEvent.getType() === 'm.push_rules') { + const rules = accountDataEvent.getContent(); + client.pushRules = PushProcessor.rewriteDefaultRules(rules); } client.emit("accountData", accountDataEvent); return accountDataEvent; @@ -1043,8 +1045,26 @@ SyncApi.prototype._processSyncResponse = async function( if (data.to_device && utils.isArray(data.to_device.events) && data.to_device.events.length > 0 ) { + const cancelledKeyVerificationTxns = []; data.to_device.events .map(client.getEventMapper()) + .map((toDeviceEvent) => { // map is a cheap inline forEach + // We want to flag m.key.verification.start events as cancelled + // if there's an accompanying m.key.verification.cancel event, so + // we pull out the transaction IDs from the cancellation events + // so we can flag the verification events as cancelled in the loop + // below. + if (toDeviceEvent.getType() === "m.key.verification.cancel") { + const txnId = toDeviceEvent.getContent()['transaction_id']; + if (txnId) { + cancelledKeyVerificationTxns.push(txnId); + } + } + + // as mentioned above, .map is a cheap inline forEach, so return + // the unmodified event. + return toDeviceEvent; + }) .forEach( function(toDeviceEvent) { const content = toDeviceEvent.getContent(); @@ -1060,6 +1080,14 @@ SyncApi.prototype._processSyncResponse = async function( return; } + if (toDeviceEvent.getType() === "m.key.verification.start" + || toDeviceEvent.getType() === "m.key.verification.request") { + const txnId = content['transaction_id']; + if (cancelledKeyVerificationTxns.includes(txnId)) { + toDeviceEvent.flagCancelled(); + } + } + client.emit("toDeviceEvent", toDeviceEvent); }, ); @@ -1219,10 +1247,8 @@ SyncApi.prototype._processSyncResponse = async function( room.setSummary(joinObj.summary); } - // XXX: should we be adding ephemeralEvents to the timeline? - // It feels like that for symmetry with room.addAccountData() - // there should be a room.addEphemeralEvents() or similar. - room.addLiveEvents(ephemeralEvents); + // we deliberately don't add ephemeral events to the timeline + room.addEphemeralEvents(ephemeralEvents); // we deliberately don't add accountData to the timeline room.addAccountData(accountDataEvents); diff --git a/src/timeline-window.js b/src/timeline-window.js index d2ec174d2..a3edabcd0 100644 --- a/src/timeline-window.js +++ b/src/timeline-window.js @@ -19,7 +19,7 @@ limitations under the License. import Promise from 'bluebird'; const EventTimeline = require("./models/event-timeline"); -import logger from '../src/logger'; +import logger from './logger'; /** * @private diff --git a/src/utils.js b/src/utils.js index d05697f19..b752299f0 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -699,3 +700,11 @@ module.exports.globToRegexp = function(glob, extended) { } return pat; }; + +module.exports.ensureNoTrailingSlash = function(url) { + if (url && url.endsWith("/")) { + return url.substr(0, url.length - 1); + } else { + return url; + } +}; diff --git a/src/webrtc/call.js b/src/webrtc/call.js index 97ab3844e..f5819c746 100644 --- a/src/webrtc/call.js +++ b/src/webrtc/call.js @@ -21,7 +21,7 @@ limitations under the License. */ const utils = require("../utils"); const EventEmitter = require("events").EventEmitter; -import logger from '../../src/logger'; +import logger from '../logger'; const DEBUG = true; // set true to enable console logging. // events: hangup, error(err), replaced(call), state(state, oldState) @@ -61,9 +61,9 @@ function MatrixCall(opts) { this.URL = opts.URL; // Array of Objects with urls, username, credential keys this.turnServers = opts.turnServers || []; - if (this.turnServers.length === 0) { + if (this.turnServers.length === 0 && this.client.isFallbackICEServerAllowed()) { this.turnServers.push({ - urls: [MatrixCall.FALLBACK_STUN_SERVER], + urls: [MatrixCall.FALLBACK_ICE_SERVER], }); } utils.forEach(this.turnServers, function(server) { @@ -92,8 +92,8 @@ function MatrixCall(opts) { } /** The length of time a call can be ringing for. */ MatrixCall.CALL_TIMEOUT_MS = 60000; -/** The fallback server to use for STUN. */ -MatrixCall.FALLBACK_STUN_SERVER = 'stun:stun.l.google.com:19302'; +/** The fallback ICE server to use for STUN or TURN protocols. */ +MatrixCall.FALLBACK_ICE_SERVER = 'stun:turn.matrix.org'; /** An error code when the local client failed to create an offer. */ MatrixCall.ERR_LOCAL_OFFER_FAILED = "local_offer_failed"; /** @@ -665,7 +665,7 @@ MatrixCall.prototype._maybeGotUserMediaForAnswer = function(stream) { }, }; self.peerConn.createAnswer(function(description) { - debuglog("Created answer: " + description); + debuglog("Created answer: ", description); self.peerConn.setLocalDescription(description, function() { self._answerContent = { version: 0, @@ -754,7 +754,7 @@ MatrixCall.prototype._receivedAnswer = function(msg) { */ MatrixCall.prototype._gotLocalOffer = function(description) { const self = this; - debuglog("Created offer: " + description); + debuglog("Created offer: ", description); if (self.state == 'ended') { debuglog("Ignoring newly created offer on call ID " + self.callId + @@ -1217,24 +1217,9 @@ const _placeCallWithConstraints = function(self, constraints) { }; const _createPeerConnection = function(self) { - let servers = self.turnServers; - if (self.webRtc.vendor === "mozilla") { - // modify turnServers struct to match what mozilla expects. - servers = []; - for (let i = 0; i < self.turnServers.length; i++) { - for (let j = 0; j < self.turnServers[i].urls.length; j++) { - servers.push({ - url: self.turnServers[i].urls[j], - username: self.turnServers[i].username, - credential: self.turnServers[i].credential, - }); - } - } - } - const pc = new self.webRtc.RtcPeerConnection({ iceTransportPolicy: self.forceTURN ? 'relay' : undefined, - iceServers: servers, + iceServers: self.turnServers, }); pc.oniceconnectionstatechange = hookCallback(self, self._onIceConnectionStateChanged); pc.onsignalingstatechange = hookCallback(self, self._onSignallingStateChanged); @@ -1352,7 +1337,9 @@ module.exports.setVideoInput = function(deviceId) { videoInput = deviceId; }; * @param {MatrixClient} client The client instance to use. * @param {string} roomId The room the call is in. * @param {Object?} options DEPRECATED optional options map. - * @param {boolean} options.forceTURN DEPRECATED whether relay through TURN should be forced. This option is deprecated - use opts.forceTURN when creating the matrix client since it's only possible to set this option on outbound calls. + * @param {boolean} options.forceTURN DEPRECATED whether relay through TURN should be + * forced. This option is deprecated - use opts.forceTURN when creating the matrix client + * since it's only possible to set this option on outbound calls. * @return {MatrixCall} the call or null if the browser doesn't support calling. */ module.exports.createNewMatrixCall = function(client, roomId, options) { @@ -1383,24 +1370,36 @@ module.exports.createNewMatrixCall = function(client, roomId, options) { return getUserMedia.apply(w.navigator, arguments); }; } - webRtc.RtcPeerConnection = ( - w.RTCPeerConnection || w.webkitRTCPeerConnection || w.mozRTCPeerConnection - ); - webRtc.RtcSessionDescription = ( - w.RTCSessionDescription || w.webkitRTCSessionDescription || - w.mozRTCSessionDescription - ); - webRtc.RtcIceCandidate = ( - w.RTCIceCandidate || w.webkitRTCIceCandidate || w.mozRTCIceCandidate - ); - webRtc.vendor = null; - if (w.mozRTCPeerConnection) { - webRtc.vendor = "mozilla"; - } else if (w.webkitRTCPeerConnection) { - webRtc.vendor = "webkit"; - } else if (w.RTCPeerConnection) { - webRtc.vendor = "generic"; + + // Firefox throws on so little as accessing the RTCPeerConnection when operating in + // a secure mode. There's some information at https://bugzilla.mozilla.org/show_bug.cgi?id=1542616 + // though the concern is that the browser throwing a SecurityError will brick the + // client creation process. + try { + webRtc.RtcPeerConnection = ( + w.RTCPeerConnection || w.webkitRTCPeerConnection || w.mozRTCPeerConnection + ); + webRtc.RtcSessionDescription = ( + w.RTCSessionDescription || w.webkitRTCSessionDescription || + w.mozRTCSessionDescription + ); + webRtc.RtcIceCandidate = ( + w.RTCIceCandidate || w.webkitRTCIceCandidate || w.mozRTCIceCandidate + ); + webRtc.vendor = null; + if (w.mozRTCPeerConnection) { + webRtc.vendor = "mozilla"; + } else if (w.webkitRTCPeerConnection) { + webRtc.vendor = "webkit"; + } else if (w.RTCPeerConnection) { + webRtc.vendor = "generic"; + } + } catch (e) { + logger.error("Failed to set up WebRTC object: possible browser interference?"); + logger.error(e); + return null; } + if (!webRtc.RtcIceCandidate || !webRtc.RtcSessionDescription || !webRtc.RtcPeerConnection || !webRtc.getUserMedia) { return null; // WebRTC is not supported. diff --git a/yarn.lock b/yarn.lock index 3cd381ed3..4e8e5a558 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,23 +2,22 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" - integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== dependencies: "@babel/highlight" "^7.0.0" -"@babel/generator@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.4.4.tgz#174a215eb843fc392c7edcaabeaa873de6e8f041" - integrity sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ== +"@babel/generator@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.2.tgz#dac8a3c2df118334c2a29ff3446da1636a8f8c03" + integrity sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ== dependencies: - "@babel/types" "^7.4.4" + "@babel/types" "^7.6.0" jsesc "^2.5.1" - lodash "^4.17.11" + lodash "^4.17.13" source-map "^0.5.0" - trim-right "^1.0.1" "@babel/helper-function-name@^7.1.0": version "7.1.0" @@ -44,50 +43,50 @@ "@babel/types" "^7.4.4" "@babel/highlight@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" - integrity sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw== + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== dependencies: chalk "^2.0.0" esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.4.tgz#5977129431b8fe33471730d255ce8654ae1250b6" - integrity sha512-5pCS4mOsL+ANsFZGdvNLybx4wtqAZJ0MJjMHxvzI3bvIsz6sQvzW8XX92EYIkiPtIvcfG3Aj+Ir5VNyjnZhP7w== +"@babel/parser@^7.0.0", "@babel/parser@^7.4.4", "@babel/parser@^7.6.0", "@babel/parser@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.2.tgz#205e9c95e16ba3b8b96090677a67c9d6075b70a1" + integrity sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg== "@babel/template@^7.1.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237" - integrity sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw== + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.6.0.tgz#7f0159c7f5012230dad64cca42ec9bdb5c9536e6" + integrity sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.4.4" - "@babel/types" "^7.4.4" + "@babel/parser" "^7.6.0" + "@babel/types" "^7.6.0" "@babel/traverse@^7.0.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.4.4.tgz#0776f038f6d78361860b6823887d4f3937133fe8" - integrity sha512-Gw6qqkw/e6AGzlyj9KnkabJX7VcubqPtkUQVAwkc0wUMldr3A/hezNB3Rc5eIvId95iSGkGIOe5hh1kMKf951A== + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.2.tgz#b0e2bfd401d339ce0e6c05690206d1e11502ce2c" + integrity sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ== dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.4.4" + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.6.2" "@babel/helper-function-name" "^7.1.0" "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.4.4" - "@babel/types" "^7.4.4" + "@babel/parser" "^7.6.2" + "@babel/types" "^7.6.0" debug "^4.1.0" globals "^11.1.0" - lodash "^4.17.11" + lodash "^4.17.13" -"@babel/types@^7.0.0", "@babel/types@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.4.tgz#8db9e9a629bb7c29370009b4b779ed93fe57d5f0" - integrity sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ== +"@babel/types@^7.0.0", "@babel/types@^7.4.4", "@babel/types@^7.6.0": + version "7.6.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.1.tgz#53abf3308add3ac2a2884d539151c57c4b3ac648" + integrity sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g== dependencies: esutils "^2.0.2" - lodash "^4.17.11" + lodash "^4.17.13" to-fast-properties "^2.0.0" JSONStream@^1.0.3: @@ -117,45 +116,44 @@ accessory@~1.1.0: balanced-match "~0.2.0" dot-parts "~1.0.0" -acorn-dynamic-import@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" - integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== - acorn-jsx@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" - integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== + version "5.0.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.2.tgz#84b68ea44b373c4f8686023a551f61a21b7c4a4f" + integrity sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw== acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2, acorn-node@^1.6.1: - version "1.6.2" - resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.6.2.tgz#b7d7ceca6f22e6417af933a62cad4de01048d5d2" - integrity sha512-rIhNEZuNI8ibQcL7ANm/mGyPukIaZsRNX9psFNQURyJW0nu6k8wjSDld20z6v2mDBWqX13pIEnk9gGZJHIlEXg== + version "1.8.2" + resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8" + integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A== dependencies: - acorn "^6.0.2" - acorn-dynamic-import "^4.0.0" - acorn-walk "^6.1.0" - xtend "^4.0.1" + acorn "^7.0.0" + acorn-walk "^7.0.0" + xtend "^4.0.2" -acorn-walk@^6.1.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.1.1.tgz#d363b66f5fac5f018ff9c3a1e7b6f8e310cc3913" - integrity sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw== +acorn-walk@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.0.0.tgz#c8ba6f0f1aac4b0a9e32d1f0af12be769528f36b" + integrity sha512-7Bv1We7ZGuU79zZbb6rRqcpxo3OY+zrdtloZWoyD8fmGX+FeXRjE+iuGkZjSXLVovLzrsvMGMy0EkwA0E0umxg== acorn@^5.2.1: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== -acorn@^6.0.2, acorn@^6.0.7: - version "6.1.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" - integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== +acorn@^6.0.7: + version "6.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" + integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== -ajv@^6.5.5, ajv@^6.9.1: - version "6.10.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" - integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== +acorn@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" + integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== + +ajv@^6.10.2, ajv@^6.5.5, ajv@^6.9.1: + version "6.10.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" + integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" @@ -172,6 +170,11 @@ another-json@^0.2.0: resolved "https://registry.yarnpkg.com/another-json/-/another-json-0.2.0.tgz#b5f4019c973b6dd5c6506a2d93469cb6d32aeedc" integrity sha1-tfQBnJc7bdXGUGotk0acttMq7tw= +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" @@ -267,21 +270,6 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= -array-filter@~0.0.0: - version "0.0.1" - resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" - integrity sha1-fajPLiZijtcygDWB/SH2fKzS7uw= - -array-map@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" - integrity sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI= - -array-reduce@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" - integrity sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys= - array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" @@ -314,10 +302,11 @@ assert-plus@1.0.0, assert-plus@^1.0.0: integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= assert@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" - integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE= + version "1.5.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== dependencies: + object-assign "^4.1.1" util "0.10.3" assign-symbols@^1.0.0: @@ -417,16 +406,16 @@ babel-core@^6.26.0: source-map "^0.5.7" babel-eslint@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.1.tgz#919681dc099614cd7d31d45c8908695092a1faed" - integrity sha512-z7OT1iNV+TjOwHNLLyJk+HN+YVWX+CLE6fPD2SymJZOZQBs+QIexFjhm4keGTm8MW9xr4EC9Q0PbaLB24V5GoQ== + version "10.0.3" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.3.tgz#81a2c669be0f205e19462fed2482d33e4687a88a" + integrity sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA== dependencies: "@babel/code-frame" "^7.0.0" "@babel/parser" "^7.0.0" "@babel/traverse" "^7.0.0" "@babel/types" "^7.0.0" - eslint-scope "3.7.1" eslint-visitor-keys "^1.0.0" + resolve "^1.12.0" babel-generator@^6.26.0: version "6.26.1" @@ -928,16 +917,16 @@ balanced-match@~0.2.0: integrity sha1-e8ZYtL7WHu5CStdPdfXD4sTfPMc= base-x@^3.0.2: - version "3.0.5" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.5.tgz#d3ada59afed05b921ab581ec3112e6444ba0795a" - integrity sha512-C3picSgzPSLE+jW3tcBzJoGwitOtazb5B+5YmAxZm2ybmTi9LNgAtDO/jjVEBZwHoXmDBZ9m/IELj3elJVRBcA== + version "3.0.7" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.7.tgz#1c5a7fafe8f66b4114063e8da102799d4e7c408f" + integrity sha512-zAKJGuQPihXW22fkrfOclUUZXM2g92z5GzlSMHxhO6r6Qj+Nm0ccaGNBzDZojzwOMkpjAv4J0fOv1U4go+a4iw== dependencies: safe-buffer "^5.0.1" base64-js@^1.0.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" - integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== + version "1.3.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" + integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== base@^0.11.1: version "0.11.2" @@ -964,10 +953,10 @@ binary-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== -bluebird@^3.5.0, bluebird@^3.5.4: - version "3.5.4" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.4.tgz#d6cc661595de30d5b3af5fcedd3c0b3ef6ec5714" - integrity sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw== +bluebird@3.5.5, bluebird@^3.5.0, bluebird@^3.5.4: + version "3.5.5" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f" + integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w== bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: version "4.11.8" @@ -1112,9 +1101,9 @@ browserify-zlib@~0.2.0: pako "~1.0.5" browserify@^16.1.0, browserify@^16.2.3: - version "16.2.3" - resolved "https://registry.yarnpkg.com/browserify/-/browserify-16.2.3.tgz#7ee6e654ba4f92bce6ab3599c3485b1cc7a0ad0b" - integrity sha512-zQt/Gd1+W+IY+h/xX2NYMW4orQWhqSwyV+xsblycTtpOuB27h1fZhhNQuipJ4t79ohw4P4mMem0jp/ZkISQtjQ== + version "16.5.0" + resolved "https://registry.yarnpkg.com/browserify/-/browserify-16.5.0.tgz#a1c2bc0431bec11fd29151941582e3f645ede881" + integrity sha512-6bfI3cl76YLAnCZ75AGu/XPOsqUhRyc0F/olGIJeCxtfxF2HvPKEcmjU9M8oAPxl4uBY1U7Nry33Q6koV3f2iw== dependencies: JSONStream "^1.0.3" assert "^1.4.0" @@ -1153,7 +1142,7 @@ browserify@^16.1.0, browserify@^16.2.3: shasum "^1.0.0" shell-quote "^1.6.1" stream-browserify "^2.0.0" - stream-http "^2.0.0" + stream-http "^3.0.0" string_decoder "^1.1.1" subarg "^1.0.0" syntax-error "^1.1.1" @@ -1183,9 +1172,9 @@ buffer-xor@^1.0.3: integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= buffer@^5.0.2: - version "5.2.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" - integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== + version "5.4.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.4.3.tgz#3fbc9c69eb713d323e3fc1a895eee0710c072115" + integrity sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -1210,7 +1199,7 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" -cached-path-relative@^1.0.0: +cached-path-relative@^1.0.0, cached-path-relative@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.2.tgz#a13df4196d26776220cc3356eb147a52dba2c6db" integrity sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg== @@ -1220,17 +1209,22 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -catharsis@^0.8.10: - version "0.8.10" - resolved "https://registry.yarnpkg.com/catharsis/-/catharsis-0.8.10.tgz#364198c1fbf084ae17028ee33ec7db53ca942ee6" - integrity sha512-l2OUaz/3PU3MZylspVFJvwHCVfWyvcduPq4lv3AzZ2pJzZCo7kNKFNyatwujD7XgvGkNAE/Jhhbh2uARNwNkfw== +catharsis@^0.8.11: + version "0.8.11" + resolved "https://registry.yarnpkg.com/catharsis/-/catharsis-0.8.11.tgz#d0eb3d2b82b7da7a3ce2efb1a7b00becc6643468" + integrity sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g== dependencies: - lodash "^4.17.11" + lodash "^4.17.14" chalk@^1.1.3: version "1.1.3" @@ -1243,7 +1237,7 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1274,9 +1268,9 @@ chokidar@^1.6.1: fsevents "^1.0.0" chokidar@^2.1.1: - version "2.1.5" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.5.tgz#0ae8434d962281a5f56c72869e79cb6d9d86ad4d" - integrity sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A== + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== dependencies: anymatch "^2.0.0" async-each "^1.0.1" @@ -1293,9 +1287,9 @@ chokidar@^2.1.1: fsevents "^1.2.7" chownr@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" - integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== + version "1.1.3" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" + integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" @@ -1327,6 +1321,15 @@ cli-width@^2.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -1363,9 +1366,9 @@ combine-source-map@^0.8.0, combine-source-map@~0.8.0: source-map "~0.5.3" combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" - integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: delayed-stream "~1.0.0" @@ -1374,7 +1377,7 @@ commander@2.15.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== -commander@^2.11.0, commander@^2.19.0, commander@~2.20.0: +commander@^2.11.0, commander@^2.20.0, commander@~2.20.0: version "2.20.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== @@ -1439,9 +1442,9 @@ copy-descriptor@^0.1.0: integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js@^2.4.0, core-js@^2.5.0: - version "2.6.5" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.5.tgz#44bc8d249e7fb2ff5d00e0341a7ffb94fbf67895" - integrity sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A== + version "2.6.9" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" + integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -1531,6 +1534,13 @@ debug@3.1.0: dependencies: ms "2.0.0" +debug@3.2.6, debug@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -1545,6 +1555,11 @@ debug@^4.0.1, debug@^4.1.0: dependencies: ms "^2.1.1" +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -1560,7 +1575,7 @@ deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= -define-properties@^1.1.3, define-properties@~1.1.2: +define-properties@^1.1.2, define-properties@^1.1.3, define-properties@~1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== @@ -1659,16 +1674,16 @@ detective@~3.1.0: escodegen "~1.1.0" esprima-fb "3001.1.0-dev-harmony-fb" -diff@1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/diff/-/diff-1.0.7.tgz#24bbb001c4a7d5522169e7cabdb2c2814ed91cf4" - integrity sha1-JLuwAcSn1VIhaefKvbLCgU7ZHPQ= - diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== +diff@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff" + integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -1711,9 +1726,9 @@ ecc-jsbn@~0.1.1: safer-buffer "^2.1.0" elliptic@^6.0.0: - version "6.4.1" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" - integrity sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ== + version "6.5.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.1.tgz#c380f5f909bf1b9b4428d028cd18d3b0efd6b52b" + integrity sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -1734,16 +1749,36 @@ entities@~1.1.1: integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== es-abstract@^1.12.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" - integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== + version "1.14.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.14.2.tgz#7ce108fad83068c8783c3cdf62e504e084d8c497" + integrity sha512-DgoQmbpFNOofkjJtKwr87Ma5EW4Dc8fWhD0R+ndq7Oc456ivUfGOOP6oAZTTKl5/CcNMP+EN+e3/iUzgE0veZg== dependencies: es-to-primitive "^1.2.0" function-bind "^1.1.1" has "^1.0.3" + has-symbols "^1.0.0" is-callable "^1.1.4" is-regex "^1.0.4" - object-keys "^1.0.12" + object-inspect "^1.6.0" + object-keys "^1.1.1" + string.prototype.trimleft "^2.0.0" + string.prototype.trimright "^2.0.0" + +es-abstract@^1.5.1: + version "1.15.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.15.0.tgz#8884928ec7e40a79e3c9bc812d37d10c8b24cc57" + integrity sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ== + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.0" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-inspect "^1.6.0" + object-keys "^1.1.1" + string.prototype.trimleft "^2.1.0" + string.prototype.trimright "^2.1.0" es-to-primitive@^1.2.0: version "1.2.0" @@ -1804,14 +1839,6 @@ eslint-rule-composer@^0.3.0: resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg== -eslint-scope@3.7.1: - version "3.7.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" - integrity sha1-PWPD7f2gLgbgGkUq2IyqzHzctug= - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - eslint-scope@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" @@ -1821,14 +1848,16 @@ eslint-scope@^4.0.3: estraverse "^4.1.1" eslint-utils@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512" - integrity sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q== + version "1.4.2" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab" + integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q== + dependencies: + eslint-visitor-keys "^1.0.0" eslint-visitor-keys@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" - integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== + version "1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" + integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== eslint@^5.12.0: version "5.16.0" @@ -1921,9 +1950,9 @@ estraverse@^1.9.1: integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== estraverse@~1.5.0: version "1.5.1" @@ -1931,9 +1960,9 @@ estraverse@~1.5.0: integrity sha1-hno+jlip+EYYr7bC3bzZFrfLr3E= esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== esutils@~1.0.0: version "1.0.0" @@ -1953,14 +1982,15 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -exorcist@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/exorcist/-/exorcist-0.4.0.tgz#1230ffdedd9248f42fbccf8b4a44d4cab29e3c64" - integrity sha1-EjD/3t2SSPQvvM+LSkTUyrKePGQ= +exorcist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/exorcist/-/exorcist-1.0.1.tgz#79316e3c4885845490f7bb405c0e5b5db1167c52" + integrity sha1-eTFuPEiFhFSQ97tAXA5bXbEWfFI= dependencies: + is-stream "~1.1.0" minimist "0.0.5" + mkdirp "~0.5.1" mold-source-map "~0.4.0" - nave "~0.5.1" expand-brackets@^0.1.4: version "0.1.5" @@ -2034,9 +2064,9 @@ extend@~3.0.2: integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== external-editor@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" - integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== dependencies: chardet "^0.7.0" iconv-lite "^0.4.24" @@ -2133,6 +2163,13 @@ find-parent-dir@~0.3.0: resolved "https://registry.yarnpkg.com/find-parent-dir/-/find-parent-dir-0.3.0.tgz#33c44b429ab2b2f0646299c5f9f718f376ff8d54" integrity sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ= +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + flat-cache@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" @@ -2142,10 +2179,17 @@ flat-cache@^2.0.1: rimraf "2.6.3" write "1.0.3" +flat@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" + integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== + dependencies: + is-buffer "~2.0.3" + flatted@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" - integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== + version "2.0.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" + integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" @@ -2181,11 +2225,11 @@ fragment-cache@^0.2.1: map-cache "^0.2.2" fs-minipass@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" - integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== dependencies: - minipass "^2.2.1" + minipass "^2.6.0" fs-readdir-recursive@^1.0.0: version "1.1.0" @@ -2234,6 +2278,11 @@ get-assigned-identifiers@^1.2.0: resolved "https://registry.yarnpkg.com/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz#6dbf411de648cbaf8d9169ebb0d2d576191e2ff1" integrity sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ== +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -2281,6 +2330,18 @@ glob@7.1.2: once "^1.3.0" path-is-absolute "^1.0.0" +glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^5.0.15: version "5.0.15" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" @@ -2293,9 +2354,9 @@ glob@^5.0.15: path-is-absolute "^1.0.0" glob@^7.1.0, glob@^7.1.2, glob@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + version "7.1.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" + integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -2324,9 +2385,9 @@ globo@~1.1.0: ternary "~1.0.0" graceful-fs@^4.1.11, graceful-fs@^4.1.4, graceful-fs@^4.1.9: - version "4.1.15" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" - integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== + version "4.2.2" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" + integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== growl@1.10.5: version "1.10.5" @@ -2334,9 +2395,9 @@ growl@1.10.5: integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== handlebars@^4.0.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67" - integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw== + version "4.3.3" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.3.3.tgz#56dd05fe33d6bd8a7d797351c39a0cdcfd576be5" + integrity sha512-VupOxR91xcGojfINrzMqrvlyYbBs39sXIrWa7YdaQWeBudOlvKEGvCczMfJPgnuwHE/zyH1M6J+IUP6cgDVyxg== dependencies: neo-async "^2.6.0" optimist "^0.6.1" @@ -2450,6 +2511,11 @@ he@1.1.1: resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -2499,9 +2565,9 @@ ieee754@^1.1.4: integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== ignore-walk@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== + version "3.0.2" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.2.tgz#99d83a246c196ea5c93ef9315ad7b0819c35069b" + integrity sha512-EXyErtpHbn75ZTsOADsfx6J/FPo6/5cjev46PXrcTpd8z3BoRkXgYu9/JVqrI7tusjmwCZutGeRJeU0Wo1e4Cw== dependencies: minimatch "^3.0.4" @@ -2511,9 +2577,9 @@ ignore@^4.0.6: integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== import-fresh@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390" - integrity sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ== + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118" + integrity sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" @@ -2531,16 +2597,21 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== inherits@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" @@ -2554,9 +2625,9 @@ inline-source-map@~0.6.0: source-map "~0.5.3" inquirer@^6.2.2: - version "6.3.1" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.3.1.tgz#7a413b5e7950811013a3db491c61d1f3b776e8e7" - integrity sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA== + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== dependencies: ansi-escapes "^3.2.0" chalk "^2.4.2" @@ -2564,7 +2635,7 @@ inquirer@^6.2.2: cli-width "^2.0.0" external-editor "^3.0.3" figures "^2.0.0" - lodash "^4.17.11" + lodash "^4.17.12" mute-stream "0.0.7" run-async "^2.2.0" rxjs "^6.4.0" @@ -2633,6 +2704,11 @@ is-buffer@^1.1.0, is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-buffer@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" + integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== + is-callable@^1.0.4, is-callable@^1.1.3, is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" @@ -2800,7 +2876,7 @@ is-number@^4.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== -is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: +is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== @@ -2829,6 +2905,11 @@ is-regex@^1.0.3, is-regex@^1.0.4: dependencies: has "^1.0.1" +is-stream@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + is-string@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.4.tgz#cc3a9b69857d621e963725a24caeec873b826e64" @@ -2861,11 +2942,6 @@ isarray@1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= -isarray@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.4.tgz#38e7bcbb0f3ba1b7933c86ba1894ddfc3781bbb7" - integrity sha512-GMxXOiUirWg1xTKRipM0Ek07rX+ubx4nNVElTJdNLYmNO/2YrDkgJGw9CljXn+r4EWiDQg/8lsRdHyg2PJuUaA== - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -2918,7 +2994,7 @@ js-tokens@^3.0.2: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= -js-yaml@3.x, js-yaml@^3.13.0: +js-yaml@3.13.1, js-yaml@3.x, js-yaml@^3.13.0: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -2939,21 +3015,21 @@ jsbn@~0.1.0: integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= jsdoc@^3.5.5: - version "3.6.2" - resolved "https://registry.yarnpkg.com/jsdoc/-/jsdoc-3.6.2.tgz#ee289fc6ba9263b7e4eceb99921179fe1c31489a" - integrity sha512-S2vzg99C5+gb7FWlrK4TVdyzVPGGkdvpDkCEJH1JABi2PKzPeLu5/zZffcJUifgWUJqXWl41Hoc+MmuM2GukIg== + version "3.6.3" + resolved "https://registry.yarnpkg.com/jsdoc/-/jsdoc-3.6.3.tgz#dccea97d0e62d63d306b8b3ed1527173b5e2190d" + integrity sha512-Yf1ZKA3r9nvtMWHO1kEuMZTlHOF8uoQ0vyo5eH7SQy5YeIiHM+B0DgKnn+X6y6KDYZcF7G2SPkKF+JORCXWE/A== dependencies: "@babel/parser" "^7.4.4" bluebird "^3.5.4" - catharsis "^0.8.10" + catharsis "^0.8.11" escape-string-regexp "^2.0.0" js2xmlparser "^4.0.0" klaw "^3.0.0" markdown-it "^8.4.2" markdown-it-anchor "^5.0.2" - marked "^0.6.2" + marked "^0.7.0" mkdirp "^0.5.1" - requizzle "^0.2.2" + requizzle "^0.2.3" strip-json-comments "^3.0.1" taffydb "2.6.2" underscore "~1.9.1" @@ -3057,12 +3133,11 @@ klaw@^3.0.0: graceful-fs "^4.1.9" labeled-stream-splicer@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz#9cffa32fd99e1612fd1d86a8db962416d5292926" - integrity sha512-MC94mHZRvJ3LfykJlTUipBqenZz1pacOZEMhhQ8dMGcDHs0SBE5GbsavUXV7YtP3icBW17W0Zy1I0lfASmo9Pg== + version "2.0.2" + resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz#42a41a16abcd46fd046306cf4f2c3576fffb1c21" + integrity sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw== dependencies: inherits "^2.0.1" - isarray "^2.0.4" stream-splicer "^2.0.0" levn@^0.3.0, levn@~0.3.0: @@ -3074,26 +3149,41 @@ levn@^0.3.0, levn@~0.3.0: type-check "~0.3.2" linkify-it@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.1.0.tgz#c4caf38a6cd7ac2212ef3c7d2bde30a91561f9db" - integrity sha512-4REs8/062kV2DSHxNfq5183zrqXMl7WP0WzABH9IeJI+NLm429FgE1PDecltYfnOoFDFlZGh2T8PfZn0r+GTRg== + version "2.2.0" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" + integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== dependencies: uc.micro "^1.0.1" +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + lodash.memoize@~3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" integrity sha1-LcvSwofLwKVcxCMovQxzYVDVPj8= -lodash@^4.17.11, lodash@^4.17.4: - version "4.17.11" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" - integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== +lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -loglevel@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" - integrity sha1-4PyVEztu8nbNyIh82vJKpvFW+Po= +log-symbols@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== + dependencies: + chalk "^2.0.1" + +loglevel@^1.6.4: + version "1.6.4" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.4.tgz#f408f4f006db8354d0577dcf6d33485b3cb90d56" + integrity sha512-p0b6mOGKcGa+7nnmKbpzR6qloPbrgLcnio++E+14Vo/XffOGwZtRpUhr8dTH/x2oCMmEoIU0Zwm3ZauhvYD17g== lolex@^1.5.2: version "1.6.0" @@ -3125,9 +3215,9 @@ map-visit@^1.0.0: object-visit "^1.0.0" markdown-it-anchor@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/markdown-it-anchor/-/markdown-it-anchor-5.0.2.tgz#cdd917a05b7bf92fb736a6dae3385c6d0d0fa552" - integrity sha512-AFM/woBI8QDJMS/9+MmsBMT5/AR+ImfOsunQZTZhzcTmna3rIzAzbOh5E0l6mlFM/i9666BpUtkqQ9bS7WApCg== + version "5.2.4" + resolved "https://registry.yarnpkg.com/markdown-it-anchor/-/markdown-it-anchor-5.2.4.tgz#d39306fe4c199705b4479d3036842cf34dcba24f" + integrity sha512-n8zCGjxA3T+Mx1pG8HEgbJbkB8JFUuRkeTZQuIM8iPY6oQ8sWOPRZJDFC9a/pNg2QkHEjjGkhBEl/RSyzaDZ3A== markdown-it@^8.4.2: version "8.4.2" @@ -3140,10 +3230,10 @@ markdown-it@^8.4.2: mdurl "^1.0.1" uc.micro "^1.0.5" -marked@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/marked/-/marked-0.6.2.tgz#c574be8b545a8b48641456ca1dbe0e37b6dccc1a" - integrity sha512-LqxwVH3P/rqKX4EKGz7+c2G9r98WeM/SW34ybhgNGhUQNKtf1GmmSkJ6cDGJ/t6tiyae49qRkpyTw2B9HOrgUA== +marked@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-0.7.0.tgz#b64201f051d271b1edc10a04d1ae9b74bb8e5c0e" + integrity sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg== math-random@^1.0.1: version "1.0.4" @@ -3272,30 +3362,38 @@ minimist@~0.0.1: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= -minipass@^2.2.1, minipass@^2.3.4: - version "2.3.5" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" - integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== +minipass@^2.6.0, minipass@^2.8.6: + version "2.8.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.8.6.tgz#620d889ace26356391d010ecb9458749df9b6db5" + integrity sha512-lFG7d6g3+/UaFDCOtqPiKAC9zngWWsQZl1g5q6gaONqrjq61SX2xFqXMleQiFVyDpYwa018E9hmlAFY22PCb+A== dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" -minizlib@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" - integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== +minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== dependencies: - minipass "^2.2.1" + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.2.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.2.tgz#5d24764998f98112586f7e566bd4c0999769dad4" + integrity sha512-lsNFqSHdJ21EwKzCp12HHJGxSMtHkCW1EMA9cceG3MkMNARjuWotZnMe3NKNshAvFXpm4loZqmYsCmRwhS2JMw== + dependencies: + minipass "^2.9.0" mixin-deep@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" - integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== dependencies: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -3303,11 +3401,11 @@ mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1: minimist "0.0.8" mocha-jenkins-reporter@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/mocha-jenkins-reporter/-/mocha-jenkins-reporter-0.4.1.tgz#d944ce5f7fb157f4bbcea8de8d535db50ade2823" - integrity sha512-IqnIylrkKJG0lxeoawRkhv/uiYojMEw3o9TQOpDFarPYKVq4ymngVPwsyfMB0XMDqtDbOTOCviFg8xOLHb80/Q== + version "0.4.2" + resolved "https://registry.yarnpkg.com/mocha-jenkins-reporter/-/mocha-jenkins-reporter-0.4.2.tgz#122023651b13b9b99b915940950608f833655540" + integrity sha512-ofQ41SUX5Uh3eHLn/ki4UTsh/7Yuk6p8N3RbxB275TLPErjkJGXuiT5i0haJ51UdJ+bkUhdyIpcCOHS3XSNVsg== dependencies: - diff "1.0.7" + diff "4.0.1" mkdirp "0.5.1" mocha "^5.2.0" xml "^1.0.1" @@ -3329,14 +3427,43 @@ mocha@^5.2.0: mkdirp "0.5.1" supports-color "5.4.0" +mocha@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.1.tgz#da941c99437da9bac412097859ff99543969f94c" + integrity sha512-VCcWkLHwk79NYQc8cxhkmI8IigTIhsCwZ6RTxQsqK6go4UvEhzJkYuHm8B2YtlSxcYq2fY+ucr4JBwoD6ci80A== + dependencies: + ansi-colors "3.2.3" + browser-stdout "1.3.1" + debug "3.2.6" + diff "3.5.0" + escape-string-regexp "1.0.5" + find-up "3.0.0" + glob "7.1.3" + growl "1.10.5" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "2.2.0" + minimatch "3.0.4" + mkdirp "0.5.1" + ms "2.1.1" + node-environment-flags "1.0.5" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.0" + yargs-parser "13.1.1" + yargs-unparser "1.6.0" + module-deps@^6.0.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-6.2.0.tgz#d41a2e790245ce319171e4e7c4d8c73993ba3cd5" - integrity sha512-hKPmO06so6bL/ZvqVNVqdTVO8UAYsi3tQWlCa+z9KuWhoN4KDQtb5hcqQQv58qYiDE21wIvnttZEPiDgEbpwbA== + version "6.2.1" + resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-6.2.1.tgz#cfe558784060e926824f474b4e647287837cda50" + integrity sha512-UnEn6Ah36Tu4jFiBbJVUtt0h+iXqxpLqDvPS8nllbw5RZFmNJ1+Mz5BjYnM9ieH80zyxHkARGLnMIHlPK5bu6A== dependencies: JSONStream "^1.0.3" browser-resolve "^1.7.0" - cached-path-relative "^1.0.0" + cached-path-relative "^1.0.2" concat-stream "~1.6.0" defined "^1.0.0" detective "^5.0.2" @@ -3370,20 +3497,25 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@^2.1.1: +ms@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= nan@^2.12.1: - version "2.13.2" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7" - integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw== + version "2.14.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" + integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== nanomatch@^1.2.9: version "1.2.13" @@ -3407,30 +3539,33 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -nave@~0.5.1: - version "0.5.3" - resolved "https://registry.yarnpkg.com/nave/-/nave-0.5.3.tgz#5acec72375856e5c76c83bd21a68d713eb5f1ba4" - integrity sha1-Ws7HI3WFblx2yDvSGmjXE+tfG6Q= - needle@^2.2.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.3.1.tgz#d272f2f4034afb9c4c9ab1379aabc17fc85c9388" - integrity sha512-CaLXV3W8Vnbps8ZANqDGz7j4x7Yj1LW4TWF/TQuDfj7Cfx4nAPTvw98qgTevtto1oHDrh3pQkaODbqupXlsWTg== + version "2.4.0" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" + integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== dependencies: - debug "^4.1.0" + debug "^3.2.6" iconv-lite "^0.4.4" sax "^1.2.4" neo-async@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835" - integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA== + version "2.6.1" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" + integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-environment-flags@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" + integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + node-pre-gyp@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" @@ -3480,9 +3615,9 @@ npm-bundled@^1.0.1: integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== npm-packlist@^1.1.6: - version "1.4.1" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.1.tgz#19064cdf988da80ea3cee45533879d90192bbfbc" - integrity sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw== + version "1.4.4" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" + integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -3507,7 +3642,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.1.0: +object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -3521,12 +3656,12 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.1.0: +object-inspect@^1.1.0, object-inspect@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== -object-keys@^1.0.12, object-keys@^1.0.9: +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.0.9, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -3543,6 +3678,16 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" +object.assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + object.entries@^1.0.4: version "1.1.0" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.0.tgz#2024fc6d6ba246aee38bdb0ffd5cfbcf371b7519" @@ -3553,6 +3698,14 @@ object.entries@^1.0.4: function-bind "^1.1.1" has "^1.0.3" +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -3568,9 +3721,9 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -"olm@https://packages.matrix.org/npm/olm/olm-3.1.0.tgz": - version "3.1.0" - resolved "https://packages.matrix.org/npm/olm/olm-3.1.0.tgz#2c8fc2a42b7ea12febc31baa73ec03d9b601da16" +"olm@https://packages.matrix.org/npm/olm/olm-3.1.4.tgz": + version "3.1.4" + resolved "https://packages.matrix.org/npm/olm/olm-3.1.4.tgz#0f03128b7d3b2f614d2216409a1dfccca765fdb3" once@1.x, once@^1.3.0: version "1.4.0" @@ -3645,6 +3798,25 @@ output-file-sync@^1.1.2: mkdirp "^0.5.1" object-assign "^4.1.0" +p-limit@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" + integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== + dependencies: + p-try "^2.0.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + pako@~1.0.5: version "1.0.10" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" @@ -3665,9 +3837,9 @@ parents@^1.0.0, parents@^1.0.1: path-platform "~0.11.15" parse-asn1@^5.0.0: - version "5.1.4" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.4.tgz#37f6628f823fbdeb2273b4d540434a22f3ef1fcc" - integrity sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw== + version "5.1.5" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" + integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" @@ -3706,6 +3878,11 @@ path-dirname@^1.0.0: resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -3768,9 +3945,9 @@ private@^0.1.6, private@^0.1.8: integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== process@~0.11.0: version "0.11.10" @@ -3783,9 +3960,9 @@ progress@^2.0.0: integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== psl@^1.1.24: - version "1.1.31" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" - integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw== + version "1.4.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" + integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== public-encrypt@^4.0.0: version "4.0.3" @@ -3815,9 +3992,9 @@ punycode@^2.1.0: integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== qs@^6.5.2: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + version "6.9.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.0.tgz#d1297e2a049c53119cb49cca366adbbacc80b409" + integrity sha512-27RP4UotQORTpmNQDX8BHPukOnBP3p1uUJY5UnDhaJB+rMt9iMsok724XL+UHU23bEFOHRMQ2ZhI99qOWUMGFA== qs@~6.5.2: version "6.5.2" @@ -3875,7 +4052,7 @@ read-only-stream@^2.0.0: dependencies: readable-stream "^2.0.2" -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.6, readable-stream@~2.3.6: +readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -3888,6 +4065,15 @@ readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^3.0.6: + version "3.4.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" + integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@~1.0.17: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" @@ -4047,12 +4233,22 @@ request@^2.88.0: tunnel-agent "^0.6.0" uuid "^3.3.2" -requizzle@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/requizzle/-/requizzle-0.2.2.tgz#df991c0cffbbbdde721504c1455f68f53f7c7bd1" - integrity sha512-oJ6y7JcUJkblRGhMByGNcszeLgU0qDxNKFCiUZR1XyzHyVsev+Mxb1tyygxLd1ORsKee1SA5BInFdUwY64GE/A== +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +requizzle@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/requizzle/-/requizzle-0.2.3.tgz#4675c90aacafb2c036bd39ba2daa4a1cb777fded" + integrity sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ== dependencies: - lodash "^4.17.11" + lodash "^4.17.14" resolve-from@^4.0.0: version "4.0.0" @@ -4069,10 +4265,10 @@ resolve@1.1.7, resolve@1.1.x: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@^1.1.4, resolve@^1.4.0: - version "1.10.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.1.tgz#664842ac960795bbe758221cdccda61fb64b5f18" - integrity sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA== +resolve@^1.1.4, resolve@^1.12.0, resolve@^1.4.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" + integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== dependencies: path-parse "^1.0.6" @@ -4094,13 +4290,27 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== -rimraf@2.6.3, rimraf@^2.5.4, rimraf@^2.6.1: +rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: glob "^7.1.3" +rimraf@^2.6.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.0.tgz#614176d4b3010b75e5c390eb0ee96f6dc0cebb9b" + integrity sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -4117,13 +4327,18 @@ run-async@^2.2.0: is-promise "^2.1.0" rxjs@^6.4.0: - version "6.5.1" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.1.tgz#f7a005a9386361921b8524f38f54cbf80e5d08f4" - integrity sha512-y0j31WJc83wPu31vS1VlAFW5JGrnGC+j+TtGAa1fRQphy48+fDYiDmX8tjGloToEsMkxnouOg/1IzXGKkJnZMg== + version "6.5.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" + integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== dependencies: tslib "^1.9.0" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== @@ -4145,30 +4360,20 @@ sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -semver@^5.3.0, semver@^5.5.0, semver@^5.5.1: - version "5.7.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" - integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== +semver@^5.3.0, semver@^5.5.0, semver@^5.5.1, semver@^5.7.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -set-blocking@~2.0.0: +set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -set-value@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= - dependencies: - 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.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" - integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -4204,14 +4409,9 @@ shebang-regex@^1.0.0: integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= shell-quote@^1.4.2, shell-quote@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" - integrity sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c= - dependencies: - array-filter "~0.0.0" - array-map "~0.0.0" - array-reduce "~0.0.0" - jsonify "~0.0.0" + version "1.7.2" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" + integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" @@ -4278,17 +4478,17 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.4.11, source-map-support@^0.4.15: +source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== dependencies: source-map "^0.5.6" -source-map-support@~0.5.10: - version "0.5.12" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" - integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== +source-map-support@^0.5.13, source-map-support@~0.5.12: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -4322,10 +4522,10 @@ source-map@~0.2.0: dependencies: amdefine ">=0.0.4" -sourceify@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/sourceify/-/sourceify-0.1.0.tgz#0b56fe57f9457350d92658810aafda7c0f44034c" - integrity sha1-C1b+V/lFc1DZJliBCq/afA9EA0w= +sourceify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/sourceify/-/sourceify-1.0.0.tgz#428da9a97fcbac6c250e03e58ea7aeb980c9e242" + integrity sha512-dA8NM9+02fcz693ou7x6hRaWbgWpfP+lAWsCPaOXR1z6HEyFBexRaQf9f/uRlTLNhenPo3knpj4hGf54RGoMjw== dependencies: convert-source-map "^1.1.3" through2 "^2.0.0" @@ -4381,21 +4581,20 @@ stream-combiner2@^1.1.1: duplexer2 "~0.1.0" readable-stream "^2.0.2" -stream-http@^2.0.0: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== +stream-http@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.1.0.tgz#22fb33fe9b4056b4eccf58bd8f400c4b993ffe57" + integrity sha512-cuB6RgO7BqC4FBYzmnvhob5Do3wIdIsXAgGycHJnW+981gHqoYcYz9lqjJrk8WXRddbwPuqPYRl+bag6mYv4lw== dependencies: builtin-status-codes "^3.0.0" inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" + readable-stream "^3.0.6" xtend "^4.0.0" stream-splicer@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/stream-splicer/-/stream-splicer-2.0.0.tgz#1b63be438a133e4b671cc1935197600175910d83" - integrity sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM= + version "2.0.1" + resolved "https://registry.yarnpkg.com/stream-splicer/-/stream-splicer-2.0.1.tgz#0b13b7ee2b5ac7e0609a7463d83899589a363fcd" + integrity sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg== dependencies: inherits "^2.0.1" readable-stream "^2.0.2" @@ -4417,7 +4616,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^3.0.0: +string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== @@ -4426,12 +4625,28 @@ string-width@^3.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string_decoder@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" - integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== +string.prototype.trimleft@^2.0.0, string.prototype.trimleft@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" + integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== dependencies: - safe-buffer "~5.1.0" + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.0.0, string.prototype.trimright@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" + integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" string_decoder@~0.10.x: version "0.10.31" @@ -4459,14 +4674,14 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.1.0: +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== dependencies: ansi-regex "^4.1.0" -strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: +strip-json-comments@2.0.1, strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= @@ -4490,6 +4705,13 @@ supports-color@5.4.0: dependencies: has-flag "^3.0.0" +supports-color@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== + dependencies: + has-flag "^3.0.0" + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -4517,12 +4739,12 @@ syntax-error@^1.1.1: acorn-node "^1.2.0" table@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/table/-/table-5.2.3.tgz#cde0cc6eb06751c009efab27e8c820ca5b67b7f2" - integrity sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ== + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== dependencies: - ajv "^6.9.1" - lodash "^4.17.11" + ajv "^6.10.2" + lodash "^4.17.14" slice-ansi "^2.1.0" string-width "^3.0.0" @@ -4532,31 +4754,31 @@ taffydb@2.6.2: integrity sha1-fLy2S1oUG2ou/CxdLGe04VCyomg= tar@^4: - version "4.4.8" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" - integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ== + version "4.4.13" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" + integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== dependencies: chownr "^1.1.1" fs-minipass "^1.2.5" - minipass "^2.3.4" - minizlib "^1.1.1" + minipass "^2.8.6" + minizlib "^1.2.1" mkdirp "^0.5.0" safe-buffer "^5.1.2" - yallist "^3.0.2" + yallist "^3.0.3" ternary@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/ternary/-/ternary-1.0.0.tgz#45702725608c9499d46a9610e9b0e49ff26f789e" integrity sha1-RXAnJWCMlJnUapYQ6bDkn/JveJ4= -terser@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.0.0.tgz#ef356f6f359a963e2cc675517f21c1c382877374" - integrity sha512-dOapGTU0hETFl1tCo4t56FN+2jffoKyER9qBGoUFyZ6y7WLoKT0bF+lAYi6B6YsILcGF3q1C2FBh8QcKSCgkgA== +terser@^4.3.8: + version "4.3.8" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.8.tgz#707f05f3f4c1c70c840e626addfdb1c158a17136" + integrity sha512-otmIRlRVmLChAWsnSFNO0Bfk6YySuBp6G9qrHiJwlLDd4mxe2ta4sjI7TzIR+W1nBMjilzrMcPOz9pSusgx3hQ== dependencies: - 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" text-table@^0.2.0: version "0.2.0" @@ -4608,11 +4830,6 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= - to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" @@ -4669,9 +4886,9 @@ trim-right@^1.0.1: integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= tslib@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" - integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== tty-browserify@0.0.1: version "0.0.1" @@ -4708,9 +4925,9 @@ uc.micro@^1.0.1, uc.micro@^1.0.5: integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== uglify-js@^3.1.4: - version "3.5.10" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.5.10.tgz#652bef39f86d9dbfd6674407ee05a5e2d372cf2d" - integrity sha512-/GTF0nosyPLbdJBd+AwYiZ+Hu5z8KXWnO0WCGt1BQ/u9Iamhejykqmz5o1OHJ53+VAk6xVxychonnApDjuqGsw== + version "3.6.0" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.0.tgz#704681345c53a8b2079fb6cec294b05ead242ff5" + integrity sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg== dependencies: commander "~2.20.0" source-map "~0.6.1" @@ -4742,14 +4959,14 @@ unhomoglyph@^1.0.2: integrity sha1-1p5fWmocayEZQaCIm4HrqGWVwlM= union-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" - integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== dependencies: arr-union "^3.1.0" get-value "^2.0.6" is-extendable "^0.1.1" - set-value "^0.4.3" + set-value "^2.0.1" unset-value@^1.0.0: version "1.0.0" @@ -4760,9 +4977,9 @@ unset-value@^1.0.0: isobject "^3.0.0" upath@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068" - integrity sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q== + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== uri-js@^4.2.2: version "4.2.2" @@ -4794,7 +5011,7 @@ user-home@^1.1.1: resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" integrity sha1-K1viOjK2Onyd640PKNSFcko98ZA= -util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= @@ -4814,9 +5031,9 @@ util@~0.10.1: inherits "2.0.3" uuid@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + version "3.3.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" + integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== v8flags@^2.1.1: version "2.1.1" @@ -4852,14 +5069,19 @@ watchify@^3.11.1: through2 "^2.0.0" xtend "^4.0.0" -which@^1.1.1, which@^1.2.9: +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@1.3.1, which@^1.1.1, which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" -wide-align@^1.1.0: +wide-align@1.1.3, wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== @@ -4876,6 +5098,15 @@ wordwrap@~0.0.2: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -4898,10 +5129,10 @@ xmlcreate@^2.0.0: resolved "https://registry.yarnpkg.com/xmlcreate/-/xmlcreate-2.0.1.tgz#2ec38bd7b708d213fd1a90e2431c4af9c09f6a52" integrity sha512-MjGsXhKG8YjTKrDCXseFo3ClbMGvUD4en29H2Cev1dv4P/chlpw6KdYmlCWDkhosBVKRDjM836+3e3pm1cBNJA== -xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= +xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== xtend@~2.1.1: version "2.1.2" @@ -4910,7 +5141,45 @@ xtend@~2.1.1: dependencies: object-keys "~0.4.0" -yallist@^3.0.0, yallist@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" - integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yallist@^3.0.0, yallist@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.0.tgz#906cc2100972dc2625ae78f566a2577230a1d6f7" + integrity sha512-6gpP93MR+VOOehKbCPchro3wFZNSNmek8A2kbkOAZLIZAYx1KP/zAqwO0sOHi3xJEb+UBz8NaYt/17UNit1Q9w== + +yargs-parser@13.1.1, yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== + dependencies: + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" + +yargs@13.3.0, yargs@^13.3.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.1"