Compare commits
248 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7d07ab7c7e | |||
| f8ff3aac58 | |||
| 299a7728d1 | |||
| 39dc6a1742 | |||
| f21c5aa7f2 | |||
| e9bc3f26a5 | |||
| 23eaddd6ea | |||
| 8143ce8450 | |||
| 0a487ec43e | |||
| 0edb483802 | |||
| 06a32ce0a1 | |||
| a57ec87c67 | |||
| 4e62491ea4 | |||
| 5758029c1e | |||
| 8f08710c58 | |||
| 90f98105f0 | |||
| 90354aa330 | |||
| 06adc34fb3 | |||
| 87bf07f95e | |||
| ab512d087c | |||
| 6799c29921 | |||
| a3f1da1981 | |||
| 3b225651cc | |||
| aa8c2ca277 | |||
| 84509087ac | |||
| 2450d461fd | |||
| 50c590ae26 | |||
| 516dff06ee | |||
| 9a8af05bfb | |||
| c9bf61c387 | |||
| 4f0f2e8c16 | |||
| 6f042a2142 | |||
| 91416bdbb2 | |||
| 9b093f7569 | |||
| 6cca73b999 | |||
| fafd6df13e | |||
| 8f77870526 | |||
| eb0462e89b | |||
| 80748d7d85 | |||
| b694d53b73 | |||
| 8004e82c50 | |||
| 85b5849228 | |||
| 6b86777e96 | |||
| efe64a4817 | |||
| ad777f36b2 | |||
| de77ad867c | |||
| 9b35f86497 | |||
| 84fc8b1931 | |||
| 455c85fb69 | |||
| 2a2fed695b | |||
| c1f28bd410 | |||
| c74e0bb6b3 | |||
| 5b9e158035 | |||
| a8d200dd02 | |||
| 34ae967cb8 | |||
| a67f14825e | |||
| 50c14d0ab8 | |||
| 0edb6e6f6f | |||
| 36d0dacda1 | |||
| 83b74070aa | |||
| f80af68686 | |||
| fe4ac06f43 | |||
| eaaa3e980a | |||
| 07629bfb9a | |||
| 88fdeca2bf | |||
| a3c8eac38b | |||
| bd5380c0b4 | |||
| c3b5767999 | |||
| 9e5c2732c9 | |||
| b8957fa917 | |||
| 52c139dcdc | |||
| 39d4bf1494 | |||
| 4c713e3387 | |||
| bb486f5148 | |||
| 524fea1297 | |||
| e9528ebb98 | |||
| de18283c3b | |||
| cc1c7561a3 | |||
| 5d928f07a0 | |||
| 01b882480f | |||
| 21d52fdbdd | |||
| f9baff2a3a | |||
| 71eca4ffcc | |||
| bc8dca5105 | |||
| 3ae3dffff7 | |||
| 81c6023940 | |||
| 3a0f27fa7e | |||
| 60e339bac0 | |||
| ecb88f45b7 | |||
| 24a869d15b | |||
| 1d427a1ea8 | |||
| 90e25867ad | |||
| 2ae56e61cb | |||
| 56c0830328 | |||
| 093f139d34 | |||
| 1083efc212 | |||
| 69773c2619 | |||
| 2525b5a5d8 | |||
| ff9c84ff94 | |||
| 3aa2bf8a76 | |||
| a229ece693 | |||
| b435137332 | |||
| 2cdbc9f4db | |||
| aa6884e484 | |||
| 4f4d694687 | |||
| 1b47999e80 | |||
| 02427651dd | |||
| 8eeb088e50 | |||
| 3f62581556 | |||
| b53a7f6ee8 | |||
| a4591afba6 | |||
| 6ea4c77dd5 | |||
| dc3d90d696 | |||
| 00de919eb4 | |||
| fdacc2f7ab | |||
| 5a64c29228 | |||
| c5cddf1607 | |||
| 44c7844a4b | |||
| f293da5b34 | |||
| 4f044de79e | |||
| da116e6077 | |||
| 2489180c47 | |||
| 4ec4d330aa | |||
| c75ca1c2d6 | |||
| 67462e9fc4 | |||
| 424b6303ef | |||
| 59c4e2c354 | |||
| ecca8bc86e | |||
| 43ca920b10 | |||
| e1a3f8f053 | |||
| 6e7cb63e7d | |||
| ab1177d987 | |||
| ee0a1d281d | |||
| aef7b9a1dc | |||
| 7cb8de5b69 | |||
| 5c2fb1c42b | |||
| 553857583d | |||
| 6d0923153f | |||
| e34eb48914 | |||
| 05ab6ef3ab | |||
| 81eefc1377 | |||
| 895d854e1c | |||
| e432d4f808 | |||
| 56c0ae294b | |||
| 0b9d68b4f2 | |||
| e2e034f795 | |||
| bb5e3d51b8 | |||
| 70b23614b5 | |||
| 24a75e3765 | |||
| d694ee3ef3 | |||
| efbdf4e1a8 | |||
| 44bfc2e846 | |||
| 0121bdbb75 | |||
| b8ba77a7b5 | |||
| 65dd5cc6ad | |||
| 8aeb994839 | |||
| 64daa444dd | |||
| 26aab4f38d | |||
| 6059df1b67 | |||
| 2a0c85c772 | |||
| 3488fbe64c | |||
| 811a98ad19 | |||
| 4462f4b90e | |||
| 4143a79f7b | |||
| 3ed9b00398 | |||
| b005b75331 | |||
| a9f9e2cf35 | |||
| 5602b94dcb | |||
| 930de640ac | |||
| 6d9fba8191 | |||
| 624c6f0a6e | |||
| 7d2f7fae45 | |||
| 3f917b39c9 | |||
| f1336a5ce7 | |||
| 7a10d504b2 | |||
| 831aec6488 | |||
| 6eb229ac1e | |||
| c58db665dd | |||
| e222fb1783 | |||
| 31a0192c2d | |||
| 53f8091e3a | |||
| 012cbf7995 | |||
| ac26c91cba | |||
| c13162aada | |||
| 9fb6eea8b7 | |||
| 23c4f19cda | |||
| 3b34570749 | |||
| 0412ca5810 | |||
| c80518bf3e | |||
| 61ee6eb8af | |||
| 654e8b41fa | |||
| 7080458f7e | |||
| 08d236f5ec | |||
| e332a7d113 | |||
| 7879709f62 | |||
| 56e030762e | |||
| bac73150ca | |||
| 2e1fb15ada | |||
| ae9bcd6f6c | |||
| c18c679b9b | |||
| d014ee0b72 | |||
| a30ef7250b | |||
| 570ce4f4b7 | |||
| 3c7c9048eb | |||
| 41243757ee | |||
| 2af311bd7d | |||
| 1bc9ee7110 | |||
| 4e040f8e77 | |||
| 26c1c6db3b | |||
| d38da83656 | |||
| 58f163ed5c | |||
| c0c9f0122c | |||
| d33395e46d | |||
| b83c7d3929 | |||
| b5df016b1b | |||
| a8b6be3b38 | |||
| 78cf175f5a | |||
| 1b78856a7d | |||
| 8194287391 | |||
| 2eecea9a07 | |||
| 465032dd4f | |||
| e473315a89 | |||
| 9d34ad5287 | |||
| a532cc5cf9 | |||
| 60c6c5bc41 | |||
| 0cbbbe8503 | |||
| 47a8d3e50a | |||
| 304da09f3b | |||
| 137c6919f6 | |||
| 842ce30190 | |||
| a0456dc430 | |||
| 52ec831b16 | |||
| 9a2bf78a8e | |||
| cb16f7a60b | |||
| ad84631ddb | |||
| d78426d708 | |||
| 4ef970b4da | |||
| b199f133b3 | |||
| 7d1b183a1b | |||
| 49d119e92e | |||
| feed1da570 | |||
| a3ad835d84 | |||
| f8afee8ebd | |||
| 7e955fc312 | |||
| eebf92366f | |||
| 3c23e166a7 | |||
| de8063a43a | |||
| a73dabcb67 |
@@ -53,6 +53,7 @@ module.exports = {
|
||||
// rules we do not want from the google styleguide
|
||||
"object-curly-spacing": ["off"],
|
||||
"spaced-comment": ["off"],
|
||||
"guard-for-in": ["off"],
|
||||
|
||||
// in principle we prefer single quotes, but life is too short
|
||||
quotes: ["off"],
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
patreon: matrixdotorg
|
||||
liberapay: matrixdotorg
|
||||
+199
@@ -1,3 +1,202 @@
|
||||
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)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
Matrix Javascript SDK
|
||||
=====================
|
||||
[](http://matrix.org/jenkins/job/JavascriptSDK/)
|
||||
|
||||
This is the [Matrix](https://matrix.org) Client-Server v1/v2 alpha SDK for
|
||||
This is the [Matrix](https://matrix.org) Client-Server r0 SDK for
|
||||
JavaScript. This SDK can be run in a browser or in Node.js.
|
||||
|
||||
Quickstart
|
||||
@@ -297,7 +296,7 @@ Then visit ``http://localhost:8005`` to see the API docs.
|
||||
End-to-end encryption support
|
||||
=============================
|
||||
|
||||
The SDK supports end-to-end encryption via the and Megolm protocols, using
|
||||
The SDK supports end-to-end encryption via the Olm and Megolm protocols, using
|
||||
[libolm](https://gitlab.matrix.org/matrix-org/olm). It is left up to the
|
||||
application to make libolm available, via the ``Olm`` global.
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "matrix-js-sdk",
|
||||
"version": "2.0.0",
|
||||
"version": "2.3.2",
|
||||
"description": "Matrix Client-Server SDK for Javascript",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
+7
-6
@@ -27,6 +27,7 @@ import MockHttpBackend from 'matrix-mock-request';
|
||||
import expect from 'expect';
|
||||
import Promise from 'bluebird';
|
||||
import LocalStorageCryptoStore from '../lib/crypto/store/localStorage-crypto-store';
|
||||
import logger from '../src/logger';
|
||||
|
||||
/**
|
||||
* Wrapper for a MockStorageApi, MockHttpBackend and MatrixClient
|
||||
@@ -82,7 +83,7 @@ TestClient.prototype.toString = function() {
|
||||
* @return {Promise}
|
||||
*/
|
||||
TestClient.prototype.start = function() {
|
||||
console.log(this + ': starting');
|
||||
logger.log(this + ': starting');
|
||||
this.httpBackend.when("GET", "/pushrules").respond(200, {});
|
||||
this.httpBackend.when("POST", "/filter").respond(200, { filter_id: "fid" });
|
||||
this.expectDeviceKeyUpload();
|
||||
@@ -100,7 +101,7 @@ TestClient.prototype.start = function() {
|
||||
this.httpBackend.flushAllExpected(),
|
||||
testUtils.syncPromise(this.client),
|
||||
]).then(() => {
|
||||
console.log(this + ': started');
|
||||
logger.log(this + ': started');
|
||||
});
|
||||
};
|
||||
|
||||
@@ -122,7 +123,7 @@ TestClient.prototype.expectDeviceKeyUpload = function() {
|
||||
expect(content.one_time_keys).toBe(undefined);
|
||||
expect(content.device_keys).toBeTruthy();
|
||||
|
||||
console.log(self + ': received device keys');
|
||||
logger.log(self + ': received device keys');
|
||||
// we expect this to happen before any one-time keys are uploaded.
|
||||
expect(Object.keys(self.oneTimeKeys).length).toEqual(0);
|
||||
|
||||
@@ -159,7 +160,7 @@ TestClient.prototype.awaitOneTimeKeyUpload = function() {
|
||||
expect(content.device_keys).toBe(undefined);
|
||||
expect(content.one_time_keys).toBeTruthy();
|
||||
expect(content.one_time_keys).toNotEqual({});
|
||||
console.log('%s: received %i one-time keys', this,
|
||||
logger.log('%s: received %i one-time keys', this,
|
||||
Object.keys(content.one_time_keys).length);
|
||||
this.oneTimeKeys = content.one_time_keys;
|
||||
return {one_time_key_counts: {
|
||||
@@ -223,11 +224,11 @@ TestClient.prototype.getSigningKey = function() {
|
||||
* @returns {Promise} promise which completes once the sync has been flushed
|
||||
*/
|
||||
TestClient.prototype.flushSync = function() {
|
||||
console.log(`${this}: flushSync`);
|
||||
logger.log(`${this}: flushSync`);
|
||||
return Promise.all([
|
||||
this.httpBackend.flush('/sync', 1),
|
||||
testUtils.syncPromise(this.client),
|
||||
]).then(() => {
|
||||
console.log(`${this}: flushSync completed`);
|
||||
logger.log(`${this}: flushSync completed`);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@ import Promise from 'bluebird';
|
||||
|
||||
import TestClient from '../TestClient';
|
||||
import testUtils from '../test-utils';
|
||||
import logger from '../../src/logger';
|
||||
|
||||
const ROOM_ID = "!room:id";
|
||||
|
||||
@@ -71,7 +72,7 @@ function getSyncResponse(roomMembers) {
|
||||
|
||||
describe("DeviceList management:", function() {
|
||||
if (!global.Olm) {
|
||||
console.warn('not running deviceList tests: Olm not present');
|
||||
logger.warn('not running deviceList tests: Olm not present');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -108,7 +109,7 @@ describe("DeviceList management:", function() {
|
||||
|
||||
return aliceTestClient.flushSync();
|
||||
}).then(function() {
|
||||
console.log("Forcing alice to download our device keys");
|
||||
logger.log("Forcing alice to download our device keys");
|
||||
|
||||
aliceTestClient.httpBackend.when('POST', '/keys/query').respond(200, {
|
||||
device_keys: {
|
||||
@@ -121,7 +122,7 @@ describe("DeviceList management:", function() {
|
||||
aliceTestClient.httpBackend.flush('/keys/query', 1),
|
||||
]);
|
||||
}).then(function() {
|
||||
console.log("Telling alice to send a megolm message");
|
||||
logger.log("Telling alice to send a megolm message");
|
||||
|
||||
aliceTestClient.httpBackend.when(
|
||||
'PUT', '/send/',
|
||||
|
||||
@@ -36,6 +36,7 @@ import Promise from 'bluebird';
|
||||
const utils = require("../../lib/utils");
|
||||
const testUtils = require("../test-utils");
|
||||
const TestClient = require('../TestClient').default;
|
||||
import logger from '../../src/logger';
|
||||
|
||||
let aliTestClient;
|
||||
const roomId = "!room:localhost";
|
||||
@@ -95,7 +96,7 @@ function expectBobQueryKeys() {
|
||||
|
||||
const aliKeys = {};
|
||||
aliKeys[aliDeviceId] = aliTestClient.deviceKeys;
|
||||
console.log("query result will be", aliKeys);
|
||||
logger.log("query result will be", aliKeys);
|
||||
|
||||
bobTestClient.httpBackend.when(
|
||||
"POST", "/keys/query",
|
||||
@@ -334,7 +335,7 @@ function recvMessage(httpBackend, client, sender, message) {
|
||||
if (event.getType() == "m.room.member") {
|
||||
return;
|
||||
}
|
||||
console.log(client.credentials.userId + " received event",
|
||||
logger.log(client.credentials.userId + " received event",
|
||||
event);
|
||||
|
||||
client.removeListener("event", onEvent);
|
||||
@@ -607,7 +608,7 @@ describe("MatrixClient crypto", function() {
|
||||
|
||||
const eventPromise = new Promise((resolve, reject) => {
|
||||
const onEvent = function(event) {
|
||||
console.log(bobUserId + " received event",
|
||||
logger.log(bobUserId + " received event",
|
||||
event);
|
||||
resolve(event);
|
||||
};
|
||||
@@ -734,7 +735,7 @@ describe("MatrixClient crypto", function() {
|
||||
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
console.log(aliTestClient + ': starting');
|
||||
logger.log(aliTestClient + ': starting');
|
||||
httpBackend.when("GET", "/pushrules").respond(200, {});
|
||||
httpBackend.when("POST", "/filter").respond(200, { filter_id: "fid" });
|
||||
aliTestClient.expectDeviceKeyUpload();
|
||||
@@ -746,7 +747,7 @@ describe("MatrixClient crypto", function() {
|
||||
aliTestClient.client.startClient({});
|
||||
|
||||
return httpBackend.flushAllExpected().then(() => {
|
||||
console.log(aliTestClient + ': started');
|
||||
logger.log(aliTestClient + ': started');
|
||||
});
|
||||
})
|
||||
.then(() => httpBackend.when("POST", "/keys/upload")
|
||||
@@ -755,7 +756,7 @@ describe("MatrixClient crypto", function() {
|
||||
expect(content.one_time_keys).toNotEqual({});
|
||||
expect(Object.keys(content.one_time_keys).length)
|
||||
.toBeGreaterThanOrEqualTo(1);
|
||||
console.log('received %i one-time keys',
|
||||
logger.log('received %i one-time keys',
|
||||
Object.keys(content.one_time_keys).length);
|
||||
// cancel futher calls by telling the client
|
||||
// we have more than we need
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -5,6 +5,7 @@ const sdk = require("../..");
|
||||
const HttpBackend = require("matrix-mock-request");
|
||||
const utils = require("../test-utils");
|
||||
const EventTimeline = sdk.EventTimeline;
|
||||
import logger from '../../src/logger';
|
||||
|
||||
const baseUrl = "http://localhost.or.something";
|
||||
const userId = "@alice:localhost";
|
||||
@@ -84,7 +85,7 @@ function startClient(httpBackend, client) {
|
||||
// set up a promise which will resolve once the client is initialised
|
||||
const deferred = Promise.defer();
|
||||
client.on("sync", function(state) {
|
||||
console.log("sync", state);
|
||||
logger.log("sync", state);
|
||||
if (state != "SYNCING") {
|
||||
return;
|
||||
}
|
||||
@@ -669,11 +670,11 @@ describe("MatrixClient event timelines", function() {
|
||||
// initiate the send, and set up checks to be done when it completes
|
||||
// - but note that it won't complete until after the /sync does, below.
|
||||
client.sendTextMessage(roomId, "a body", TXN_ID).then(function(res) {
|
||||
console.log("sendTextMessage completed");
|
||||
logger.log("sendTextMessage completed");
|
||||
expect(res.event_id).toEqual(event.event_id);
|
||||
return client.getEventTimeline(timelineSet, event.event_id);
|
||||
}).then(function(tl) {
|
||||
console.log("getEventTimeline completed (2)");
|
||||
logger.log("getEventTimeline completed (2)");
|
||||
expect(tl.getEvents().length).toEqual(2);
|
||||
expect(tl.getEvents()[1].getContent().body).toEqual("a body");
|
||||
}),
|
||||
@@ -684,7 +685,7 @@ describe("MatrixClient event timelines", function() {
|
||||
]).then(function() {
|
||||
return client.getEventTimeline(timelineSet, event.event_id);
|
||||
}).then(function(tl) {
|
||||
console.log("getEventTimeline completed (1)");
|
||||
logger.log("getEventTimeline completed (1)");
|
||||
expect(tl.getEvents().length).toEqual(2);
|
||||
expect(tl.getEvents()[1].event).toEqual(event);
|
||||
|
||||
|
||||
@@ -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();
|
||||
@@ -355,9 +355,9 @@ describe("MatrixClient", function() {
|
||||
return client._crypto._olmDevice.sign(anotherjson.stringify(b));
|
||||
};
|
||||
|
||||
console.log("Ed25519: " + ed25519key);
|
||||
console.log("boris:", sign(borisKeys.dev1));
|
||||
console.log("chaz:", sign(chazKeys.dev2));
|
||||
logger.log("Ed25519: " + ed25519key);
|
||||
logger.log("boris:", sign(borisKeys.dev1));
|
||||
logger.log("chaz:", sign(chazKeys.dev2));
|
||||
*/
|
||||
|
||||
httpBackend.when("POST", "/keys/query").check(function(req) {
|
||||
@@ -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);
|
||||
|
||||
@@ -23,6 +23,7 @@ import expect from 'expect';
|
||||
const utils = require('../../lib/utils');
|
||||
const testUtils = require('../test-utils');
|
||||
const TestClient = require('../TestClient').default;
|
||||
import logger from '../../src/logger';
|
||||
|
||||
const ROOM_ID = "!room:id";
|
||||
|
||||
@@ -203,7 +204,7 @@ function getSyncResponse(roomMembers) {
|
||||
|
||||
describe("megolm", function() {
|
||||
if (!global.Olm) {
|
||||
console.warn('not running megolm tests: Olm not present');
|
||||
logger.warn('not running megolm tests: Olm not present');
|
||||
return;
|
||||
}
|
||||
const Olm = global.Olm;
|
||||
@@ -416,7 +417,7 @@ describe("megolm", function() {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
event.once('Event.decrypted', (ev) => {
|
||||
console.log(`${Date.now()} event ${event.getId()} now decrypted`);
|
||||
logger.log(`${Date.now()} event ${event.getId()} now decrypted`);
|
||||
resolve(ev);
|
||||
});
|
||||
});
|
||||
@@ -555,7 +556,7 @@ describe("megolm", function() {
|
||||
).respond(200, function(path, content) {
|
||||
const ct = content.ciphertext;
|
||||
const r = inboundGroupSession.decrypt(ct);
|
||||
console.log('Decrypted received megolm message', r);
|
||||
logger.log('Decrypted received megolm message', r);
|
||||
|
||||
expect(r.message_index).toEqual(0);
|
||||
const decrypted = JSON.parse(r.plaintext);
|
||||
@@ -600,7 +601,7 @@ describe("megolm", function() {
|
||||
|
||||
return aliceTestClient.flushSync();
|
||||
}).then(function() {
|
||||
console.log('Forcing alice to download our device keys');
|
||||
logger.log('Forcing alice to download our device keys');
|
||||
|
||||
aliceTestClient.httpBackend.when('POST', '/keys/query').respond(
|
||||
200, getTestKeysQueryResponse('@bob:xyz'),
|
||||
@@ -611,10 +612,10 @@ describe("megolm", function() {
|
||||
aliceTestClient.httpBackend.flush('/keys/query', 1),
|
||||
]);
|
||||
}).then(function() {
|
||||
console.log('Telling alice to block our device');
|
||||
logger.log('Telling alice to block our device');
|
||||
aliceTestClient.client.setDeviceBlocked('@bob:xyz', 'DEVICE_ID');
|
||||
|
||||
console.log('Telling alice to send a megolm message');
|
||||
logger.log('Telling alice to send a megolm message');
|
||||
aliceTestClient.httpBackend.when(
|
||||
'PUT', '/send/',
|
||||
).respond(200, {
|
||||
@@ -656,7 +657,7 @@ describe("megolm", function() {
|
||||
|
||||
return aliceTestClient.flushSync();
|
||||
}).then(function() {
|
||||
console.log("Fetching bob's devices and marking known");
|
||||
logger.log("Fetching bob's devices and marking known");
|
||||
|
||||
aliceTestClient.httpBackend.when('POST', '/keys/query').respond(
|
||||
200, getTestKeysQueryResponse('@bob:xyz'),
|
||||
@@ -669,17 +670,17 @@ describe("megolm", function() {
|
||||
aliceTestClient.client.setDeviceKnown('@bob:xyz', 'DEVICE_ID');
|
||||
});
|
||||
}).then(function() {
|
||||
console.log('Telling alice to send a megolm message');
|
||||
logger.log('Telling alice to send a megolm message');
|
||||
|
||||
aliceTestClient.httpBackend.when(
|
||||
'PUT', '/sendToDevice/m.room.encrypted/',
|
||||
).respond(200, function(path, content) {
|
||||
console.log('sendToDevice: ', content);
|
||||
logger.log('sendToDevice: ', content);
|
||||
const m = content.messages['@bob:xyz'].DEVICE_ID;
|
||||
const ct = m.ciphertext[testSenderKey];
|
||||
expect(ct.type).toEqual(1); // normal message
|
||||
const decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body));
|
||||
console.log('decrypted sendToDevice:', decrypted);
|
||||
logger.log('decrypted sendToDevice:', decrypted);
|
||||
expect(decrypted.type).toEqual('m.room_key');
|
||||
megolmSessionId = decrypted.content.session_id;
|
||||
return {};
|
||||
@@ -688,7 +689,7 @@ describe("megolm", function() {
|
||||
aliceTestClient.httpBackend.when(
|
||||
'PUT', '/send/',
|
||||
).respond(200, function(path, content) {
|
||||
console.log('/send:', content);
|
||||
logger.log('/send:', content);
|
||||
expect(content.session_id).toEqual(megolmSessionId);
|
||||
return {
|
||||
event_id: '$event_id',
|
||||
@@ -704,14 +705,14 @@ describe("megolm", function() {
|
||||
}),
|
||||
]);
|
||||
}).then(function() {
|
||||
console.log('Telling alice to block our device');
|
||||
logger.log('Telling alice to block our device');
|
||||
aliceTestClient.client.setDeviceBlocked('@bob:xyz', 'DEVICE_ID');
|
||||
|
||||
console.log('Telling alice to send another megolm message');
|
||||
logger.log('Telling alice to send another megolm message');
|
||||
aliceTestClient.httpBackend.when(
|
||||
'PUT', '/send/',
|
||||
).respond(200, function(path, content) {
|
||||
console.log('/send:', content);
|
||||
logger.log('/send:', content);
|
||||
expect(content.session_id).toNotEqual(megolmSessionId);
|
||||
return {
|
||||
event_id: '$event_id',
|
||||
@@ -792,7 +793,7 @@ describe("megolm", function() {
|
||||
aliceTestClient.httpBackend.when(
|
||||
'PUT', '/sendToDevice/m.room.encrypted/',
|
||||
).respond(200, function(path, content) {
|
||||
console.log("sendToDevice: ", content);
|
||||
logger.log("sendToDevice: ", content);
|
||||
const m = content.messages[aliceTestClient.userId].DEVICE_ID;
|
||||
const ct = m.ciphertext[testSenderKey];
|
||||
expect(ct.type).toEqual(0); // pre-key message
|
||||
@@ -812,7 +813,7 @@ describe("megolm", function() {
|
||||
).respond(200, function(path, content) {
|
||||
const ct = content.ciphertext;
|
||||
const r = inboundGroupSession.decrypt(ct);
|
||||
console.log('Decrypted received megolm message', r);
|
||||
logger.log('Decrypted received megolm message', r);
|
||||
decrypted = JSON.parse(r.plaintext);
|
||||
|
||||
return {
|
||||
@@ -865,7 +866,7 @@ describe("megolm", function() {
|
||||
return aliceTestClient.flushSync();
|
||||
}).then(function() {
|
||||
// this will block
|
||||
console.log('Forcing alice to download our device keys');
|
||||
logger.log('Forcing alice to download our device keys');
|
||||
downloadPromise = aliceTestClient.client.downloadKeys(['@bob:xyz']);
|
||||
|
||||
// so will this.
|
||||
|
||||
+4
-3
@@ -14,11 +14,12 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// try to load the olm library.
|
||||
import logger from '../src/logger';
|
||||
|
||||
// try to load the olm library.
|
||||
try {
|
||||
global.Olm = require('olm');
|
||||
console.log('loaded libolm');
|
||||
logger.log('loaded libolm');
|
||||
} catch (e) {
|
||||
console.warn("unable to run crypto tests: libolm not available");
|
||||
logger.warn("unable to run crypto tests: libolm not available");
|
||||
}
|
||||
|
||||
+6
-5
@@ -5,6 +5,7 @@ import Promise from 'bluebird';
|
||||
// load olm before the sdk if possible
|
||||
import './olm-loader';
|
||||
|
||||
import logger from '../src/logger';
|
||||
import sdk from '..';
|
||||
const MatrixEvent = sdk.MatrixEvent;
|
||||
|
||||
@@ -25,7 +26,7 @@ module.exports.syncPromise = function(client, count) {
|
||||
|
||||
const p = new Promise((resolve, reject) => {
|
||||
const cb = (state) => {
|
||||
console.log(`${Date.now()} syncPromise(${count}): ${state}`);
|
||||
logger.log(`${Date.now()} syncPromise(${count}): ${state}`);
|
||||
if (state == 'SYNCING') {
|
||||
resolve();
|
||||
} else {
|
||||
@@ -48,8 +49,8 @@ module.exports.syncPromise = function(client, count) {
|
||||
module.exports.beforeEach = function(context) {
|
||||
const desc = context.currentTest.fullTitle();
|
||||
|
||||
console.log(desc);
|
||||
console.log(new Array(1 + desc.length).join("="));
|
||||
logger.log(desc);
|
||||
logger.log(new Array(1 + desc.length).join("="));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -232,11 +233,11 @@ module.exports.awaitDecryption = function(event) {
|
||||
return Promise.resolve(event);
|
||||
}
|
||||
|
||||
console.log(`${Date.now()} event ${event.getId()} is being decrypted; waiting`);
|
||||
logger.log(`${Date.now()} event ${event.getId()} is being decrypted; waiting`);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
event.once('Event.decrypted', (ev) => {
|
||||
console.log(`${Date.now()} event ${event.getId()} now decrypted`);
|
||||
logger.log(`${Date.now()} event ${event.getId()} now decrypted`);
|
||||
resolve(ev);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -275,7 +275,7 @@ describe("AutoDiscovery", function() {
|
||||
"m.homeserver": {
|
||||
state: "FAIL_ERROR",
|
||||
error: AutoDiscovery.ERROR_INVALID_HOMESERVER,
|
||||
base_url: null,
|
||||
base_url: "https://example.org",
|
||||
},
|
||||
"m.identity_server": {
|
||||
state: "PROMPT",
|
||||
@@ -304,7 +304,7 @@ describe("AutoDiscovery", function() {
|
||||
"m.homeserver": {
|
||||
state: "FAIL_ERROR",
|
||||
error: AutoDiscovery.ERROR_INVALID_HOMESERVER,
|
||||
base_url: null,
|
||||
base_url: "https://example.org",
|
||||
},
|
||||
"m.identity_server": {
|
||||
state: "PROMPT",
|
||||
@@ -335,7 +335,7 @@ describe("AutoDiscovery", function() {
|
||||
"m.homeserver": {
|
||||
state: "FAIL_ERROR",
|
||||
error: AutoDiscovery.ERROR_INVALID_HOMESERVER,
|
||||
base_url: null,
|
||||
base_url: "https://example.org",
|
||||
},
|
||||
"m.identity_server": {
|
||||
state: "PROMPT",
|
||||
@@ -528,7 +528,7 @@ describe("AutoDiscovery", function() {
|
||||
"m.identity_server": {
|
||||
state: "FAIL_ERROR",
|
||||
error: AutoDiscovery.ERROR_INVALID_IDENTITY_SERVER,
|
||||
base_url: null,
|
||||
base_url: "https://identity.example.org",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -569,7 +569,7 @@ describe("AutoDiscovery", function() {
|
||||
"m.identity_server": {
|
||||
state: "FAIL_ERROR",
|
||||
error: AutoDiscovery.ERROR_INVALID_IDENTITY_SERVER,
|
||||
base_url: null,
|
||||
base_url: "https://identity.example.org",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -19,6 +19,7 @@ import DeviceList from '../../../lib/crypto/DeviceList';
|
||||
import MemoryCryptoStore from '../../../lib/crypto/store/memory-crypto-store.js';
|
||||
import testUtils from '../../test-utils';
|
||||
import utils from '../../../lib/utils';
|
||||
import logger from '../../../src/logger';
|
||||
|
||||
import expect from 'expect';
|
||||
import Promise from 'bluebird';
|
||||
@@ -134,7 +135,7 @@ describe('DeviceList', function() {
|
||||
}).then(() => {
|
||||
// uh-oh; user restarts before second request completes. The new instance
|
||||
// should know we never got a complete device list.
|
||||
console.log("Creating new devicelist to simulate app reload");
|
||||
logger.log("Creating new devicelist to simulate app reload");
|
||||
downloadSpy.reset();
|
||||
const dl2 = createTestDeviceList();
|
||||
const queryDefer3 = Promise.defer();
|
||||
|
||||
@@ -10,6 +10,7 @@ import MockStorageApi from '../../../MockStorageApi';
|
||||
import testUtils from '../../../test-utils';
|
||||
import OlmDevice from '../../../../lib/crypto/OlmDevice';
|
||||
import Crypto from '../../../../lib/crypto';
|
||||
import logger from '../../../../src/logger';
|
||||
|
||||
const MatrixEvent = sdk.MatrixEvent;
|
||||
const MegolmDecryption = algorithms.DECRYPTION_CLASSES['m.megolm.v1.aes-sha2'];
|
||||
@@ -21,7 +22,7 @@ const Olm = global.Olm;
|
||||
|
||||
describe("MegolmDecryption", function() {
|
||||
if (!global.Olm) {
|
||||
console.warn('Not running megolm unit tests: libolm not present');
|
||||
logger.warn('Not running megolm unit tests: libolm not present');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import expect from 'expect';
|
||||
import MemoryCryptoStore from '../../../../lib/crypto/store/memory-crypto-store.js';
|
||||
import MockStorageApi from '../../../MockStorageApi';
|
||||
import testUtils from '../../../test-utils';
|
||||
import logger from '../../../../src/logger';
|
||||
|
||||
import OlmDevice from '../../../../lib/crypto/OlmDevice';
|
||||
import olmlib from '../../../../lib/crypto/olmlib';
|
||||
@@ -45,7 +46,7 @@ async function setupSession(initiator, opponent) {
|
||||
|
||||
describe("OlmDecryption", function() {
|
||||
if (!global.Olm) {
|
||||
console.warn('Not running megolm unit tests: libolm not present');
|
||||
logger.warn('Not running megolm unit tests: libolm not present');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import testUtils from '../../test-utils';
|
||||
|
||||
import OlmDevice from '../../../lib/crypto/OlmDevice';
|
||||
import Crypto from '../../../lib/crypto';
|
||||
import logger from '../../../src/logger';
|
||||
|
||||
const Olm = global.Olm;
|
||||
|
||||
@@ -112,7 +113,7 @@ function makeTestClient(sessionStore, cryptoStore) {
|
||||
|
||||
describe("MegolmBackup", function() {
|
||||
if (!global.Olm) {
|
||||
console.warn('Not running megolm backup unit tests: libolm not present');
|
||||
logger.warn('Not running megolm backup unit tests: libolm not present');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,15 +13,15 @@ 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.
|
||||
*/
|
||||
import logger from '../../../../src/logger';
|
||||
|
||||
try {
|
||||
global.Olm = require('olm');
|
||||
} catch (e) {
|
||||
console.warn("unable to run device verification tests: libolm not available");
|
||||
logger.warn("unable to run device verification tests: libolm not available");
|
||||
}
|
||||
|
||||
import expect from 'expect';
|
||||
|
||||
import DeviceInfo from '../../../../lib/crypto/deviceinfo';
|
||||
|
||||
import {ShowQRCode, ScanQRCode} from '../../../../lib/crypto/verification/QRCode';
|
||||
@@ -30,7 +30,7 @@ const Olm = global.Olm;
|
||||
|
||||
describe("QR code verification", function() {
|
||||
if (!global.Olm) {
|
||||
console.warn('Not running device verification tests: libolm not present');
|
||||
logger.warn('Not running device verification tests: libolm not present');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,11 +13,12 @@ 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.
|
||||
*/
|
||||
import logger from '../../../../src/logger';
|
||||
|
||||
try {
|
||||
global.Olm = require('olm');
|
||||
} catch (e) {
|
||||
console.warn("unable to run device verification tests: libolm not available");
|
||||
logger.warn("unable to run device verification tests: libolm not available");
|
||||
}
|
||||
|
||||
import expect from 'expect';
|
||||
@@ -32,7 +33,7 @@ import {makeTestClients} from './util';
|
||||
|
||||
describe("verification request", function() {
|
||||
if (!global.Olm) {
|
||||
console.warn('Not running device verification unit tests: libolm not present');
|
||||
logger.warn('Not running device verification unit tests: libolm not present');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -68,8 +69,14 @@ describe("verification request", function() {
|
||||
bob.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.requestVerification("@bob:example.com");
|
||||
expect(aliceVerifier).toBeAn(SAS);
|
||||
|
||||
// XXX: Private function access (but it's a test, so we're okay)
|
||||
aliceVerifier._endTimer();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,11 +13,12 @@ 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.
|
||||
*/
|
||||
import logger from '../../../../src/logger';
|
||||
|
||||
try {
|
||||
global.Olm = require('olm');
|
||||
} catch (e) {
|
||||
console.warn("unable to run device verification tests: libolm not available");
|
||||
logger.warn("unable to run device verification tests: libolm not available");
|
||||
}
|
||||
|
||||
import expect from 'expect';
|
||||
@@ -37,7 +38,7 @@ import {makeTestClients} from './util';
|
||||
|
||||
describe("SAS verification", function() {
|
||||
if (!global.Olm) {
|
||||
console.warn('Not running device verification unit tests: libolm not present');
|
||||
logger.warn('Not running device verification unit tests: libolm not present');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -56,6 +57,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() {
|
||||
|
||||
@@ -21,6 +21,7 @@ import testUtils from '../test-utils';
|
||||
|
||||
import expect from 'expect';
|
||||
import Promise from 'bluebird';
|
||||
import logger from '../../src/logger';
|
||||
|
||||
describe("MatrixEvent", () => {
|
||||
beforeEach(function() {
|
||||
@@ -48,7 +49,7 @@ describe("MatrixEvent", () => {
|
||||
const crypto = {
|
||||
decryptEvent: function() {
|
||||
++callCount;
|
||||
console.log(`decrypt: ${callCount}`);
|
||||
logger.log(`decrypt: ${callCount}`);
|
||||
if (callCount == 1) {
|
||||
// schedule a second decryption attempt while
|
||||
// the first one is still running.
|
||||
|
||||
@@ -24,6 +24,7 @@ const InteractiveAuth = sdk.InteractiveAuth;
|
||||
const MatrixError = sdk.MatrixError;
|
||||
|
||||
import expect from 'expect';
|
||||
import logger from '../../src/logger';
|
||||
|
||||
// Trivial client object to test interactive auth
|
||||
// (we do not need TestClient here)
|
||||
@@ -64,7 +65,7 @@ describe("InteractiveAuth", function() {
|
||||
|
||||
// first we expect a call here
|
||||
stateUpdated.andCall(function(stage) {
|
||||
console.log('aaaa');
|
||||
logger.log('aaaa');
|
||||
expect(stage).toEqual("logintype");
|
||||
ia.submitAuthDict({
|
||||
type: "logintype",
|
||||
@@ -75,7 +76,7 @@ describe("InteractiveAuth", function() {
|
||||
// .. which should trigger a call here
|
||||
const requestRes = {"a": "b"};
|
||||
doRequest.andCall(function(authData) {
|
||||
console.log('cccc');
|
||||
logger.log('cccc');
|
||||
expect(authData).toEqual({
|
||||
session: "sessionId",
|
||||
type: "logintype",
|
||||
@@ -106,7 +107,7 @@ describe("InteractiveAuth", function() {
|
||||
|
||||
// first we expect a call to doRequest
|
||||
doRequest.andCall(function(authData) {
|
||||
console.log("request1", authData);
|
||||
logger.log("request1", authData);
|
||||
expect(authData).toEqual({});
|
||||
const err = new MatrixError({
|
||||
session: "sessionId",
|
||||
@@ -132,7 +133,7 @@ describe("InteractiveAuth", function() {
|
||||
|
||||
// submitAuthDict should trigger another call to doRequest
|
||||
doRequest.andCall(function(authData) {
|
||||
console.log("request2", authData);
|
||||
logger.log("request2", authData);
|
||||
expect(authData).toEqual({
|
||||
session: "sessionId",
|
||||
type: "logintype",
|
||||
|
||||
@@ -7,6 +7,7 @@ const utils = require("../test-utils");
|
||||
|
||||
import expect from 'expect';
|
||||
import lolex from 'lolex';
|
||||
import logger from '../../src/logger';
|
||||
|
||||
describe("MatrixClient", function() {
|
||||
const userId = "@alice:bar";
|
||||
@@ -69,7 +70,7 @@ describe("MatrixClient", function() {
|
||||
"MatrixClient[UT] RECV " + method + " " + path + " " +
|
||||
"EXPECT " + (next ? next.method : next) + " " + (next ? next.path : next)
|
||||
);
|
||||
console.log(logLine);
|
||||
logger.log(logLine);
|
||||
|
||||
if (!next) { // no more things to return
|
||||
if (pendingLookup) {
|
||||
@@ -91,7 +92,7 @@ describe("MatrixClient", function() {
|
||||
return pendingLookup.promise;
|
||||
}
|
||||
if (next.path === path && next.method === method) {
|
||||
console.log(
|
||||
logger.log(
|
||||
"MatrixClient[UT] Matched. Returning " +
|
||||
(next.error ? "BAD" : "GOOD") + " response",
|
||||
);
|
||||
@@ -353,7 +354,7 @@ describe("MatrixClient", function() {
|
||||
function syncChecker(expectedStates, done) {
|
||||
return function syncListener(state, old) {
|
||||
const expected = expectedStates.shift();
|
||||
console.log(
|
||||
logger.log(
|
||||
"'sync' curr=%s old=%s EXPECT=%s", state, old, expected,
|
||||
);
|
||||
if (!expected) {
|
||||
|
||||
@@ -104,7 +104,7 @@ describe("Room", function() {
|
||||
user_ids: [userA],
|
||||
},
|
||||
});
|
||||
room.addLiveEvents([typing]);
|
||||
room.addEphemeralEvents([typing]);
|
||||
expect(room.currentState.setTypingEvent).toHaveBeenCalledWith(typing);
|
||||
});
|
||||
|
||||
|
||||
+39
-27
@@ -48,7 +48,7 @@ describe("MatrixScheduler", function() {
|
||||
clock.uninstall();
|
||||
});
|
||||
|
||||
it("should process events in a queue in a FIFO manner", function(done) {
|
||||
it("should process events in a queue in a FIFO manner", async function() {
|
||||
retryFn = function() {
|
||||
return 0;
|
||||
};
|
||||
@@ -57,28 +57,30 @@ describe("MatrixScheduler", function() {
|
||||
};
|
||||
const deferA = Promise.defer();
|
||||
const deferB = Promise.defer();
|
||||
let resolvedA = false;
|
||||
let yieldedA = false;
|
||||
scheduler.setProcessFunction(function(event) {
|
||||
if (resolvedA) {
|
||||
if (yieldedA) {
|
||||
expect(event).toEqual(eventB);
|
||||
return deferB.promise;
|
||||
} else {
|
||||
yieldedA = true;
|
||||
expect(event).toEqual(eventA);
|
||||
return deferA.promise;
|
||||
}
|
||||
});
|
||||
scheduler.queueEvent(eventA);
|
||||
scheduler.queueEvent(eventB).done(function() {
|
||||
expect(resolvedA).toBe(true);
|
||||
done();
|
||||
});
|
||||
deferA.resolve({});
|
||||
resolvedA = true;
|
||||
deferB.resolve({});
|
||||
const abPromise = Promise.all([
|
||||
scheduler.queueEvent(eventA),
|
||||
scheduler.queueEvent(eventB),
|
||||
]);
|
||||
deferB.resolve({b: true});
|
||||
deferA.resolve({a: true});
|
||||
const [a, b] = await abPromise;
|
||||
expect(a.a).toEqual(true);
|
||||
expect(b.b).toEqual(true);
|
||||
});
|
||||
|
||||
it("should invoke the retryFn on failure and wait the amount of time specified",
|
||||
function(done) {
|
||||
async function() {
|
||||
const waitTimeMs = 1500;
|
||||
const retryDefer = Promise.defer();
|
||||
retryFn = function() {
|
||||
@@ -97,24 +99,26 @@ describe("MatrixScheduler", function() {
|
||||
return defer.promise;
|
||||
} else if (procCount === 2) {
|
||||
// don't care about this defer
|
||||
return Promise.defer().promise;
|
||||
return new Promise();
|
||||
}
|
||||
expect(procCount).toBeLessThan(3);
|
||||
});
|
||||
|
||||
scheduler.queueEvent(eventA);
|
||||
// as queueing doesn't start processing synchronously anymore (see commit bbdb5ac)
|
||||
// wait just long enough before it does
|
||||
await Promise.resolve();
|
||||
expect(procCount).toEqual(1);
|
||||
defer.reject({});
|
||||
retryDefer.promise.done(function() {
|
||||
expect(procCount).toEqual(1);
|
||||
clock.tick(waitTimeMs);
|
||||
expect(procCount).toEqual(2);
|
||||
done();
|
||||
});
|
||||
await retryDefer.promise;
|
||||
expect(procCount).toEqual(1);
|
||||
clock.tick(waitTimeMs);
|
||||
await Promise.resolve();
|
||||
expect(procCount).toEqual(2);
|
||||
});
|
||||
|
||||
it("should give up if the retryFn on failure returns -1 and try the next event",
|
||||
function(done) {
|
||||
async function() {
|
||||
// Queue A & B.
|
||||
// Reject A and return -1 on retry.
|
||||
// Expect B to be tried next and the promise for A to be rejected.
|
||||
@@ -122,8 +126,8 @@ describe("MatrixScheduler", function() {
|
||||
return -1;
|
||||
};
|
||||
queueFn = function() {
|
||||
return "yep";
|
||||
};
|
||||
return "yep";
|
||||
};
|
||||
|
||||
const deferA = Promise.defer();
|
||||
const deferB = Promise.defer();
|
||||
@@ -142,13 +146,17 @@ describe("MatrixScheduler", function() {
|
||||
|
||||
const globalA = scheduler.queueEvent(eventA);
|
||||
scheduler.queueEvent(eventB);
|
||||
|
||||
// as queueing doesn't start processing synchronously anymore (see commit bbdb5ac)
|
||||
// wait just long enough before it does
|
||||
await Promise.resolve();
|
||||
expect(procCount).toEqual(1);
|
||||
deferA.reject({});
|
||||
globalA.catch(function() {
|
||||
try {
|
||||
await globalA;
|
||||
} catch(err) {
|
||||
await Promise.resolve();
|
||||
expect(procCount).toEqual(2);
|
||||
done();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it("should treat each queue separately", function(done) {
|
||||
@@ -300,7 +308,11 @@ describe("MatrixScheduler", function() {
|
||||
expect(ev).toEqual(eventA);
|
||||
return defer.promise;
|
||||
});
|
||||
expect(procCount).toEqual(1);
|
||||
// as queueing doesn't start processing synchronously anymore (see commit bbdb5ac)
|
||||
// wait just long enough before it does
|
||||
Promise.resolve().then(() => {
|
||||
expect(procCount).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
it("should not call the processFn if there are no queued events", function() {
|
||||
|
||||
+7
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-1
@@ -17,7 +17,7 @@ limitations under the License.
|
||||
/** @module auto-discovery */
|
||||
|
||||
import Promise from 'bluebird';
|
||||
const logger = require("./logger");
|
||||
import logger from './logger';
|
||||
import { URL as NodeURL } from "url";
|
||||
|
||||
// Dev note: Auto discovery is part of the spec.
|
||||
@@ -256,6 +256,11 @@ export class AutoDiscovery {
|
||||
if (!hsVersions || !hsVersions.raw["versions"]) {
|
||||
logger.error("Invalid /versions response");
|
||||
clientConfig["m.homeserver"].error = AutoDiscovery.ERROR_INVALID_HOMESERVER;
|
||||
|
||||
// Supply the base_url to the caller because they may be ignoring liveliness
|
||||
// errors, like this one.
|
||||
clientConfig["m.homeserver"].base_url = hsUrl;
|
||||
|
||||
return Promise.resolve(clientConfig);
|
||||
}
|
||||
|
||||
@@ -311,6 +316,11 @@ export class AutoDiscovery {
|
||||
logger.error("Invalid /api/v1 response");
|
||||
failingClientConfig["m.identity_server"].error =
|
||||
AutoDiscovery.ERROR_INVALID_IDENTITY_SERVER;
|
||||
|
||||
// Supply the base_url to the caller because they may be ignoring
|
||||
// liveliness errors, like this one.
|
||||
failingClientConfig["m.identity_server"].base_url = isUrl;
|
||||
|
||||
return Promise.resolve(failingClientConfig);
|
||||
}
|
||||
}
|
||||
|
||||
+230
-98
@@ -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
|
||||
@@ -151,13 +168,14 @@ MatrixBaseApis.prototype.isUsernameAvailable = function(username) {
|
||||
* threepid uses during registration in the ID server. Set 'msisdn' to
|
||||
* true to bind msisdn.
|
||||
* @param {string} guestAccessToken
|
||||
* @param {string} inhibitLogin
|
||||
* @param {module:client.callback} callback Optional.
|
||||
* @return {module:client.Promise} Resolves: TODO
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
MatrixBaseApis.prototype.register = function(
|
||||
username, password,
|
||||
sessionId, auth, bindThreepids, guestAccessToken,
|
||||
sessionId, auth, bindThreepids, guestAccessToken, inhibitLogin,
|
||||
callback,
|
||||
) {
|
||||
// backwards compat
|
||||
@@ -166,6 +184,10 @@ MatrixBaseApis.prototype.register = function(
|
||||
} else if (bindThreepids === null || bindThreepids === undefined) {
|
||||
bindThreepids = {};
|
||||
}
|
||||
if (typeof inhibitLogin === 'function') {
|
||||
callback = inhibitLogin;
|
||||
inhibitLogin = undefined;
|
||||
}
|
||||
|
||||
if (auth === undefined || auth === null) {
|
||||
auth = {};
|
||||
@@ -192,6 +214,9 @@ MatrixBaseApis.prototype.register = function(
|
||||
if (guestAccessToken !== undefined && guestAccessToken !== null) {
|
||||
params.guest_access_token = guestAccessToken;
|
||||
}
|
||||
if (inhibitLogin !== undefined && inhibitLogin !== null) {
|
||||
params.inhibit_login = inhibitLogin;
|
||||
}
|
||||
// Temporary parameter added to make the register endpoint advertise
|
||||
// msisdn flows. This exists because there are clients that break
|
||||
// when given stages they don't recognise. This parameter will cease
|
||||
@@ -383,9 +408,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,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -430,6 +454,35 @@ 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.authedRequestWithPrefix(
|
||||
undefined, "GET", path, null, null, httpApi.PREFIX_UNSTABLE,
|
||||
);
|
||||
return response;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} roomId
|
||||
@@ -887,32 +940,6 @@ MatrixBaseApis.prototype.sendStateEvent = function(roomId, eventType, content, s
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} roomId
|
||||
* @param {string} eventId
|
||||
* @param {string} [txnId] transaction id. One will be made up if not
|
||||
* supplied.
|
||||
* @param {module:client.callback} callback Optional.
|
||||
* @return {module:client.Promise} Resolves: TODO
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
MatrixBaseApis.prototype.redactEvent = function(
|
||||
roomId, eventId, txnId, callback,
|
||||
) {
|
||||
if (arguments.length === 3) {
|
||||
callback = txnId;
|
||||
}
|
||||
|
||||
const path = utils.encodeUri("/rooms/$roomId/redact/$eventId/$txnId", {
|
||||
$roomId: roomId,
|
||||
$eventId: eventId,
|
||||
$txnId: txnId ? txnId : this.makeTxnId(),
|
||||
});
|
||||
|
||||
return this._http.authedRequest(callback, "PUT", path, undefined, {});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} roomId
|
||||
* @param {Number} limit
|
||||
@@ -1318,9 +1345,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);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1353,10 +1378,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,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1373,11 +1396,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);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1399,10 +1418,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);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1420,10 +1436,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);
|
||||
};
|
||||
|
||||
|
||||
@@ -1465,7 +1479,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);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1599,9 +1615,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);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1636,10 +1650,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);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1667,10 +1678,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);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1689,20 +1698,39 @@ 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);
|
||||
};
|
||||
|
||||
|
||||
// Identity Server Operations
|
||||
// ==========================
|
||||
|
||||
/**
|
||||
* 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 `/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) {
|
||||
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.
|
||||
*
|
||||
* Note that the Home Server offers APIs to proxy this API for specific
|
||||
* Note that the Homeserver offers APIs to proxy this API for specific
|
||||
* situations, allowing for better feedback to the user.
|
||||
*
|
||||
* @param {string} email The email address to request a token for
|
||||
@@ -1715,22 +1743,50 @@ MatrixBaseApis.prototype.getKeyChanges = function(oldToken, newToken) {
|
||||
* @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;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1744,44 +1800,94 @@ 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;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
MatrixBaseApis.prototype.lookupThreePid = async function(
|
||||
medium,
|
||||
address,
|
||||
callback,
|
||||
identityAccessToken,
|
||||
) {
|
||||
const params = {
|
||||
medium: medium,
|
||||
address: address,
|
||||
};
|
||||
return this._http.idServerRequest(
|
||||
callback, "GET", "/lookup",
|
||||
params, httpApi.PREFIX_IDENTITY_V1,
|
||||
);
|
||||
|
||||
try {
|
||||
const response = await this._http.idServerRequest(
|
||||
undefined, "GET", "/lookup",
|
||||
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, "GET", "/lookup",
|
||||
params, httpApi.PREFIX_IDENTITY_V1,
|
||||
);
|
||||
}
|
||||
if (callback) callback(err);
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1810,10 +1916,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
|
||||
@@ -1825,9 +1928,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') {
|
||||
@@ -1852,10 +1954,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);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1871,12 +1970,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
|
||||
*/
|
||||
|
||||
+302
-49
@@ -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,6 +46,7 @@ const olmlib = require("./crypto/olmlib");
|
||||
|
||||
import ReEmitter from './ReEmitter';
|
||||
import RoomList from './crypto/RoomList';
|
||||
import logger from '../src/logger';
|
||||
|
||||
import Crypto from './crypto';
|
||||
import { isCryptoAvailable } from './crypto';
|
||||
@@ -70,7 +72,7 @@ function keysFromRecoverySession(sessions, decryptionKey, roomId) {
|
||||
decrypted.room_id = roomId;
|
||||
keys.push(decrypted);
|
||||
} catch (e) {
|
||||
console.log("Failed to decrypt session from backup");
|
||||
logger.log("Failed to decrypt session from backup");
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
@@ -277,6 +279,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);
|
||||
@@ -447,15 +491,16 @@ MatrixClient.prototype.setNotifTimelineSet = function(notifTimelineSet) {
|
||||
/**
|
||||
* Gets the capabilities of the homeserver. Always returns an object of
|
||||
* capability keys and their options, which may be empty.
|
||||
* @param {boolean} fresh True to ignore any cached values.
|
||||
* @return {module:client.Promise} Resolves to the capabilities of the homeserver
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
MatrixClient.prototype.getCapabilities = function() {
|
||||
MatrixClient.prototype.getCapabilities = function(fresh=false) {
|
||||
const now = new Date().getTime();
|
||||
|
||||
if (this._cachedCapabilities) {
|
||||
if (this._cachedCapabilities && !fresh) {
|
||||
if (now < this._cachedCapabilities.expiration) {
|
||||
console.log("Returning cached capabilities");
|
||||
logger.log("Returning cached capabilities");
|
||||
return Promise.resolve(this._cachedCapabilities.capabilities);
|
||||
}
|
||||
}
|
||||
@@ -464,7 +509,7 @@ MatrixClient.prototype.getCapabilities = function() {
|
||||
return this._http.authedRequest(
|
||||
undefined, "GET", "/capabilities",
|
||||
).catch((e) => {
|
||||
console.error(e);
|
||||
logger.error(e);
|
||||
return null; // otherwise consume the error
|
||||
}).then((r) => {
|
||||
if (!r) r = {};
|
||||
@@ -481,7 +526,7 @@ MatrixClient.prototype.getCapabilities = function() {
|
||||
expiration: now + cacheMs,
|
||||
};
|
||||
|
||||
console.log("Caching capabilities: ", capabilities);
|
||||
logger.log("Caching capabilities: ", capabilities);
|
||||
return capabilities;
|
||||
});
|
||||
};
|
||||
@@ -507,7 +552,7 @@ MatrixClient.prototype.initCrypto = async function() {
|
||||
}
|
||||
|
||||
if (this._crypto) {
|
||||
console.warn("Attempt to re-initialise e2e encryption on MatrixClient");
|
||||
logger.warn("Attempt to re-initialise e2e encryption on MatrixClient");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -521,7 +566,7 @@ MatrixClient.prototype.initCrypto = async function() {
|
||||
}
|
||||
|
||||
// initialise the list of encrypted rooms (whether or not crypto is enabled)
|
||||
console.log("Crypto: initialising roomlist...");
|
||||
logger.log("Crypto: initialising roomlist...");
|
||||
await this._roomList.init();
|
||||
|
||||
const userId = this.getUserId();
|
||||
@@ -556,7 +601,7 @@ MatrixClient.prototype.initCrypto = async function() {
|
||||
"crypto.warning",
|
||||
]);
|
||||
|
||||
console.log("Crypto: initialising crypto object...");
|
||||
logger.log("Crypto: initialising crypto object...");
|
||||
await crypto.init();
|
||||
|
||||
this.olmVersion = Crypto.getOlmVersion();
|
||||
@@ -732,19 +777,19 @@ async function _setDeviceVerification(
|
||||
* Request a key verification from another user.
|
||||
*
|
||||
* @param {string} userId the user to request verification with
|
||||
* @param {Array} devices array of device IDs to send requests to. Defaults to
|
||||
* all devices owned by the user
|
||||
* @param {Array} methods array of verification methods to use. Defaults to
|
||||
* all known methods
|
||||
* @param {Array} devices array of device IDs to send requests to. Defaults to
|
||||
* all devices owned by the user
|
||||
*
|
||||
* @returns {Promise<module:crypto/verification/Base>} resolves to a verifier
|
||||
* when the request is accepted by the other user
|
||||
*/
|
||||
MatrixClient.prototype.requestVerification = function(userId, devices, methods) {
|
||||
MatrixClient.prototype.requestVerification = function(userId, methods, devices) {
|
||||
if (this._crypto === null) {
|
||||
throw new Error("End-to-end encryption disabled");
|
||||
}
|
||||
return this._crypto.requestVerification(userId, devices);
|
||||
return this._crypto.requestVerification(userId, methods, devices);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -934,7 +979,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;
|
||||
@@ -1078,6 +1124,7 @@ MatrixClient.prototype.createKeyBackupVersion = function(info) {
|
||||
return this._crypto._signObject(data.auth_data).then(() => {
|
||||
return this._http.authedRequest(
|
||||
undefined, "POST", "/room_keys/version", undefined, data,
|
||||
{prefix: httpApi.PREFIX_UNSTABLE},
|
||||
);
|
||||
}).then((res) => {
|
||||
this.enableKeyBackup({
|
||||
@@ -1107,6 +1154,7 @@ MatrixClient.prototype.deleteKeyBackupVersion = function(version) {
|
||||
|
||||
return this._http.authedRequest(
|
||||
undefined, "DELETE", path, undefined, undefined,
|
||||
{prefix: httpApi.PREFIX_UNSTABLE},
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1148,6 +1196,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},
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1163,6 +1212,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<int>} 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);
|
||||
@@ -1222,7 +1284,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)) {
|
||||
@@ -1250,7 +1313,7 @@ MatrixClient.prototype._restoreKeyBackup = function(
|
||||
key.session_id = targetSessionId;
|
||||
keys.push(key);
|
||||
} catch (e) {
|
||||
console.log("Failed to decrypt session from backup");
|
||||
logger.log("Failed to decrypt session from backup");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1271,7 +1334,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},
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1694,6 +1758,21 @@ MatrixClient.prototype.setPowerLevel = function(roomId, userId, powerLevel,
|
||||
*/
|
||||
MatrixClient.prototype.sendEvent = function(roomId, eventType, content, txnId,
|
||||
callback) {
|
||||
return this._sendCompleteEvent(roomId, {
|
||||
type: eventType,
|
||||
content: content,
|
||||
}, txnId, callback);
|
||||
};
|
||||
/**
|
||||
* @param {string} roomId
|
||||
* @param {object} eventObject An object with the partial structure of an event, to which event_id, user_id, room_id and origin_server_ts will be added.
|
||||
* @param {string} txnId the txnId.
|
||||
* @param {module:client.callback} callback Optional.
|
||||
* @return {module:client.Promise} Resolves: TODO
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
MatrixClient.prototype._sendCompleteEvent = function(roomId, eventObject, txnId,
|
||||
callback) {
|
||||
if (utils.isFunction(txnId)) {
|
||||
callback = txnId; txnId = undefined;
|
||||
}
|
||||
@@ -1702,20 +1781,33 @@ MatrixClient.prototype.sendEvent = function(roomId, eventType, content, txnId,
|
||||
txnId = this.makeTxnId();
|
||||
}
|
||||
|
||||
console.log(`sendEvent of type ${eventType} in ${roomId} with txnId ${txnId}`);
|
||||
|
||||
// we always construct a MatrixEvent when sending because the store and
|
||||
// scheduler use them. We'll extract the params back out if it turns out
|
||||
// the client has no scheduler or store.
|
||||
const room = this.getRoom(roomId);
|
||||
const localEvent = new MatrixEvent({
|
||||
const localEvent = new MatrixEvent(Object.assign(eventObject, {
|
||||
event_id: "~" + roomId + ":" + txnId,
|
||||
user_id: this.credentials.userId,
|
||||
room_id: roomId,
|
||||
type: eventType,
|
||||
origin_server_ts: new Date().getTime(),
|
||||
content: content,
|
||||
});
|
||||
}));
|
||||
|
||||
const room = this.getRoom(roomId);
|
||||
|
||||
// if this is a relation or redaction of an event
|
||||
// that hasn't been sent yet (e.g. with a local id starting with a ~)
|
||||
// then listen for the remote echo of that event so that by the time
|
||||
// this event does get sent, we have the correct event_id
|
||||
const targetId = localEvent.getAssociatedId();
|
||||
if (targetId && targetId.startsWith("~")) {
|
||||
const target = room.getPendingEvents().find(e => e.getId() === targetId);
|
||||
target.once("Event.localEventIdReplaced", () => {
|
||||
localEvent.updateAssociatedId(target.getId());
|
||||
});
|
||||
}
|
||||
|
||||
const type = localEvent.getType();
|
||||
logger.log(`sendEvent of type ${type} in ${roomId} with txnId ${txnId}`);
|
||||
|
||||
localEvent._txnId = txnId;
|
||||
localEvent.setStatus(EventStatus.SENDING);
|
||||
|
||||
@@ -1784,7 +1876,7 @@ function _sendEvent(client, room, event, callback) {
|
||||
return res;
|
||||
}, function(err) {
|
||||
// the request failed to send.
|
||||
console.error("Error sending event", err.stack || err);
|
||||
logger.error("Error sending event", err.stack || err);
|
||||
|
||||
try {
|
||||
// set the error on the event before we update the status:
|
||||
@@ -1800,7 +1892,7 @@ function _sendEvent(client, room, event, callback) {
|
||||
callback(err);
|
||||
}
|
||||
} catch (err2) {
|
||||
console.error("Exception in error handler!", err2.stack || err);
|
||||
logger.error("Exception in error handler!", err2.stack || err);
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
@@ -1833,6 +1925,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 " +
|
||||
@@ -1842,6 +1948,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) {
|
||||
@@ -1869,6 +1990,11 @@ function _sendEventHttpRequest(client, event) {
|
||||
pathTemplate = "/rooms/$roomId/state/$eventType/$stateKey";
|
||||
}
|
||||
path = utils.encodeUri(pathTemplate, pathParams);
|
||||
} else if (event.isRedaction()) {
|
||||
const pathTemplate = `/rooms/$roomId/redact/$redactsEventId/$txnId`;
|
||||
path = utils.encodeUri(pathTemplate, Object.assign({
|
||||
$redactsEventId: event.event.redacts,
|
||||
}, pathParams));
|
||||
} else {
|
||||
path = utils.encodeUri(
|
||||
"/rooms/$roomId/send/$eventType/$txnId", pathParams,
|
||||
@@ -1878,13 +2004,30 @@ function _sendEventHttpRequest(client, event) {
|
||||
return client._http.authedRequest(
|
||||
undefined, "PUT", path, undefined, event.getWireContent(),
|
||||
).then((res) => {
|
||||
console.log(
|
||||
logger.log(
|
||||
`Event sent to ${event.getRoomId()} with event id ${res.event_id}`,
|
||||
);
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomId
|
||||
* @param {string} eventId
|
||||
* @param {string} [txnId] transaction id. One will be made up if not
|
||||
* supplied.
|
||||
* @param {module:client.callback} callback Optional.
|
||||
* @return {module:client.Promise} Resolves: TODO
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
MatrixClient.prototype.redactEvent = function(roomId, eventId, txnId, callback) {
|
||||
return this._sendCompleteEvent(roomId, {
|
||||
type: "m.room.redaction",
|
||||
content: {},
|
||||
redacts: eventId,
|
||||
}, txnId, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} roomId
|
||||
* @param {Object} content
|
||||
@@ -2067,7 +2210,12 @@ MatrixClient.prototype.sendReceipt = function(event, receiptType, callback) {
|
||||
* @return {module:client.Promise} Resolves: TODO
|
||||
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||
*/
|
||||
MatrixClient.prototype.sendReadReceipt = function(event, callback) {
|
||||
MatrixClient.prototype.sendReadReceipt = async function(event, callback) {
|
||||
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})`);
|
||||
}
|
||||
return this.sendReceipt(event, "m.read", callback);
|
||||
};
|
||||
|
||||
@@ -2077,20 +2225,25 @@ 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.
|
||||
* @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) {
|
||||
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");
|
||||
}
|
||||
@@ -2185,10 +2338,10 @@ MatrixClient.prototype.getRoomUpgradeHistory = function(roomId, verifyLinks=fals
|
||||
// Work backwards first, looking at create events.
|
||||
let createEvent = currentRoom.currentState.getStateEvents("m.room.create", "");
|
||||
while (createEvent) {
|
||||
console.log(`Looking at ${createEvent.getId()}`);
|
||||
logger.log(`Looking at ${createEvent.getId()}`);
|
||||
const predecessor = createEvent.getContent()['predecessor'];
|
||||
if (predecessor && predecessor['room_id']) {
|
||||
console.log(`Looking at predecessor ${predecessor['room_id']}`);
|
||||
logger.log(`Looking at predecessor ${predecessor['room_id']}`);
|
||||
const refRoom = this.getRoom(predecessor['room_id']);
|
||||
if (!refRoom) break; // end of the chain
|
||||
|
||||
@@ -2216,6 +2369,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", "");
|
||||
@@ -2227,6 +2381,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;
|
||||
@@ -2918,9 +3078,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 = [];
|
||||
@@ -3553,7 +3712,7 @@ MatrixClient.prototype.syncLeftRooms = function() {
|
||||
|
||||
// cleanup locks
|
||||
this._syncLeftRoomsPromise.then(function(res) {
|
||||
console.log("Marking success of sync left room request");
|
||||
logger.log("Marking success of sync left room request");
|
||||
self._syncedLeftRooms = true; // flip the bit on success
|
||||
}).finally(function() {
|
||||
self._syncLeftRoomsPromise = null; // cleanup ongoing request state
|
||||
@@ -3727,6 +3886,55 @@ MatrixClient.prototype.getTurnServers = function() {
|
||||
return this._turnServers || [];
|
||||
};
|
||||
|
||||
// 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. <strong>This function is implementation specific and may change
|
||||
* as a result.</strong>
|
||||
* @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.
|
||||
* <strong>This function is implementation specific and may change as a
|
||||
* result.</strong>
|
||||
* @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. <strong>This
|
||||
* function is implementation specific and may change as a result.</strong>
|
||||
* @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
|
||||
// =================
|
||||
|
||||
@@ -3798,7 +4006,7 @@ MatrixClient.prototype.startClient = async function(opts) {
|
||||
|
||||
if (this._syncApi) {
|
||||
// This shouldn't happen since we thought the client was not running
|
||||
console.error("Still have sync object whilst not running: stopping old one");
|
||||
logger.error("Still have sync object whilst not running: stopping old one");
|
||||
this._syncApi.stop();
|
||||
}
|
||||
|
||||
@@ -3841,7 +4049,7 @@ MatrixClient.prototype._storeClientOptions = function() {
|
||||
* clean shutdown.
|
||||
*/
|
||||
MatrixClient.prototype.stopClient = function() {
|
||||
console.log('stopping MatrixClient');
|
||||
logger.log('stopping MatrixClient');
|
||||
|
||||
this.clientRunning = false;
|
||||
// TODO: f.e. Room => self.store.storeRoom(room) ?
|
||||
@@ -3873,9 +4081,13 @@ MatrixClient.prototype.doesServerSupportLazyLoading = async function() {
|
||||
prefix: '',
|
||||
},
|
||||
);
|
||||
|
||||
const versions = response["versions"];
|
||||
const unstableFeatures = response["unstable_features"];
|
||||
|
||||
this._serverSupportsLazyLoading =
|
||||
unstableFeatures && unstableFeatures["m.lazy_load_members"];
|
||||
(versions && versions.includes("r0.5.0"))
|
||||
|| (unstableFeatures && unstableFeatures["m.lazy_load_members"]);
|
||||
}
|
||||
return this._serverSupportsLazyLoading;
|
||||
};
|
||||
@@ -3909,6 +4121,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]
|
||||
@@ -3982,7 +4235,7 @@ function setupCallEventHandler(client) {
|
||||
return; // stale/old invite event
|
||||
}
|
||||
if (call) {
|
||||
console.log(
|
||||
logger.log(
|
||||
"WARN: Already have a MatrixCall with id %s but got an " +
|
||||
"invite. Clobbering.",
|
||||
content.call_id,
|
||||
@@ -3993,7 +4246,7 @@ function setupCallEventHandler(client) {
|
||||
forceTURN: client._forceTURN,
|
||||
});
|
||||
if (!call) {
|
||||
console.log(
|
||||
logger.log(
|
||||
"Incoming call ID " + content.call_id + " but this client " +
|
||||
"doesn't support WebRTC",
|
||||
);
|
||||
@@ -4038,14 +4291,14 @@ function setupCallEventHandler(client) {
|
||||
if (existingCall.state === 'wait_local_media' ||
|
||||
existingCall.state === 'create_offer' ||
|
||||
existingCall.callId > call.callId) {
|
||||
console.log(
|
||||
logger.log(
|
||||
"Glare detected: answering incoming call " + call.callId +
|
||||
" and canceling outgoing call " + existingCall.callId,
|
||||
);
|
||||
existingCall._replacedBy(call);
|
||||
call.answer();
|
||||
} else {
|
||||
console.log(
|
||||
logger.log(
|
||||
"Glare detected: rejecting incoming call " + call.callId +
|
||||
" and keeping outgoing call " + existingCall.callId,
|
||||
);
|
||||
@@ -4115,7 +4368,7 @@ function checkTurnServers(client) {
|
||||
|
||||
client.turnServer().done(function(res) {
|
||||
if (res.uris) {
|
||||
console.log("Got TURN URIs: " + res.uris + " refresh in " +
|
||||
logger.log("Got TURN URIs: " + res.uris + " refresh in " +
|
||||
res.ttl + " secs");
|
||||
// map the response to a format that can be fed to
|
||||
// RTCPeerConnection
|
||||
@@ -4131,7 +4384,7 @@ function checkTurnServers(client) {
|
||||
}, (res.ttl || (60 * 60)) * 1000 * 0.9);
|
||||
}
|
||||
}, function(err) {
|
||||
console.error("Failed to get TURN URIs");
|
||||
logger.error("Failed to get TURN URIs");
|
||||
client._checkTurnServersTimeoutID =
|
||||
setTimeout(function() {
|
||||
checkTurnServers(client);
|
||||
@@ -4395,7 +4648,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
|
||||
* });
|
||||
*/
|
||||
|
||||
+6
-5
@@ -47,14 +47,14 @@ 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) {
|
||||
params.width = width;
|
||||
params.width = Math.round(width);
|
||||
}
|
||||
if (height) {
|
||||
params.height = height;
|
||||
params.height = Math.round(height);
|
||||
}
|
||||
if (resizeMethod) {
|
||||
params.method = resizeMethod;
|
||||
@@ -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 +
|
||||
|
||||
@@ -462,7 +462,7 @@ OlmDevice.prototype.createInboundSession = async function(
|
||||
*/
|
||||
OlmDevice.prototype.getSessionIdsForDevice = async function(theirDeviceIdentityKey) {
|
||||
if (this._sessionsInProgress[theirDeviceIdentityKey]) {
|
||||
console.log("waiting for session to be created");
|
||||
logger.log("waiting for session to be created");
|
||||
try {
|
||||
await this._sessionsInProgress[theirDeviceIdentityKey];
|
||||
} catch (e) {
|
||||
|
||||
@@ -23,8 +23,8 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import Promise from 'bluebird';
|
||||
import logger from '../../../src/logger';
|
||||
|
||||
const logger = require("../../logger");
|
||||
const utils = require("../../utils");
|
||||
const olmlib = require("../olmlib");
|
||||
const base = require("./base");
|
||||
@@ -278,7 +278,7 @@ MegolmEncryption.prototype._prepareNewSession = async function() {
|
||||
).catch((e) => {
|
||||
// This throws if the upload failed, but this is fine
|
||||
// since it will have written it to the db and will retry.
|
||||
console.log("Failed to back up group session", e);
|
||||
logger.log("Failed to back up group session", e);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -955,7 +955,7 @@ MegolmDecryption.prototype.onRoomKeyEvent = function(event) {
|
||||
).catch((e) => {
|
||||
// This throws if the upload failed, but this is fine
|
||||
// since it will have written it to the db and will retry.
|
||||
console.log("Failed to back up group session", e);
|
||||
logger.log("Failed to back up group session", e);
|
||||
});
|
||||
}
|
||||
}).catch((e) => {
|
||||
@@ -1088,7 +1088,7 @@ MegolmDecryption.prototype.importRoomKey = function(session) {
|
||||
).catch((e) => {
|
||||
// This throws if the upload failed, but this is fine
|
||||
// since it will have written it to the db and will retry.
|
||||
console.log("Failed to back up group session", e);
|
||||
logger.log("Failed to back up group session", e);
|
||||
});
|
||||
}
|
||||
// have another go at decrypting events sent with this session.
|
||||
|
||||
@@ -22,7 +22,7 @@ limitations under the License.
|
||||
*/
|
||||
import Promise from 'bluebird';
|
||||
|
||||
const logger = require("../../logger");
|
||||
import logger from '../../logger';
|
||||
const utils = require("../../utils");
|
||||
const olmlib = require("../olmlib");
|
||||
const DeviceInfo = require("../deviceinfo");
|
||||
|
||||
+50
-23
@@ -25,7 +25,7 @@ const anotherjson = require('another-json');
|
||||
import Promise from 'bluebird';
|
||||
import {EventEmitter} from 'events';
|
||||
|
||||
const logger = require("../logger");
|
||||
import logger from '../logger';
|
||||
const utils = require("../utils");
|
||||
const OlmDevice = require("./OlmDevice");
|
||||
const olmlib = require("./olmlib");
|
||||
@@ -197,11 +197,11 @@ utils.inherits(Crypto, EventEmitter);
|
||||
* Returns a promise which resolves once the crypto module is ready for use.
|
||||
*/
|
||||
Crypto.prototype.init = async function() {
|
||||
console.log("Crypto: initialising Olm...");
|
||||
logger.log("Crypto: initialising Olm...");
|
||||
await global.Olm.init();
|
||||
console.log("Crypto: initialising Olm device...");
|
||||
logger.log("Crypto: initialising Olm device...");
|
||||
await this._olmDevice.init();
|
||||
console.log("Crypto: loading device list...");
|
||||
logger.log("Crypto: loading device list...");
|
||||
await this._deviceList.load();
|
||||
|
||||
// build our device keys: these will later be uploaded
|
||||
@@ -210,7 +210,7 @@ Crypto.prototype.init = async function() {
|
||||
this._deviceKeys["curve25519:" + this._deviceId] =
|
||||
this._olmDevice.deviceCurve25519Key;
|
||||
|
||||
console.log("Crypto: fetching own devices...");
|
||||
logger.log("Crypto: fetching own devices...");
|
||||
let myDevices = this._deviceList.getRawStoredDevicesForUser(
|
||||
this._userId,
|
||||
);
|
||||
@@ -221,7 +221,7 @@ Crypto.prototype.init = async function() {
|
||||
|
||||
if (!myDevices[this._deviceId]) {
|
||||
// add our own deviceinfo to the cryptoStore
|
||||
console.log("Crypto: adding this device to the store...");
|
||||
logger.log("Crypto: adding this device to the store...");
|
||||
const deviceInfo = {
|
||||
keys: this._deviceKeys,
|
||||
algorithms: this._supportedAlgorithms,
|
||||
@@ -236,7 +236,7 @@ Crypto.prototype.init = async function() {
|
||||
this._deviceList.saveIfDirty();
|
||||
}
|
||||
|
||||
console.log("Crypto: checking for key backup...");
|
||||
logger.log("Crypto: checking for key backup...");
|
||||
this._checkAndStartKeyBackup();
|
||||
};
|
||||
|
||||
@@ -247,9 +247,9 @@ Crypto.prototype.init = async function() {
|
||||
* to it.
|
||||
*/
|
||||
Crypto.prototype._checkAndStartKeyBackup = async function() {
|
||||
console.log("Checking key backup status...");
|
||||
logger.log("Checking key backup status...");
|
||||
if (this._baseApis.isGuest()) {
|
||||
console.log("Skipping key backup check since user is guest");
|
||||
logger.log("Skipping key backup check since user is guest");
|
||||
this._checkedForBackup = true;
|
||||
return null;
|
||||
}
|
||||
@@ -257,7 +257,7 @@ Crypto.prototype._checkAndStartKeyBackup = async function() {
|
||||
try {
|
||||
backupInfo = await this._baseApis.getKeyBackupVersion();
|
||||
} catch (e) {
|
||||
console.log("Error checking for active key backup", e);
|
||||
logger.log("Error checking for active key backup", e);
|
||||
if (e.httpStatus / 100 === 4) {
|
||||
// well that's told us. we won't try again.
|
||||
this._checkedForBackup = true;
|
||||
@@ -269,27 +269,27 @@ Crypto.prototype._checkAndStartKeyBackup = async function() {
|
||||
const trustInfo = await this.isKeyBackupTrusted(backupInfo);
|
||||
|
||||
if (trustInfo.usable && !this.backupInfo) {
|
||||
console.log(
|
||||
logger.log(
|
||||
"Found usable key backup v" + backupInfo.version +
|
||||
": enabling key backups",
|
||||
);
|
||||
this._baseApis.enableKeyBackup(backupInfo);
|
||||
} else if (!trustInfo.usable && this.backupInfo) {
|
||||
console.log("No usable key backup: disabling key backup");
|
||||
logger.log("No usable key backup: disabling key backup");
|
||||
this._baseApis.disableKeyBackup();
|
||||
} else if (!trustInfo.usable && !this.backupInfo) {
|
||||
console.log("No usable key backup: not enabling key backup");
|
||||
logger.log("No usable key backup: not enabling key backup");
|
||||
} else if (trustInfo.usable && this.backupInfo) {
|
||||
// may not be the same version: if not, we should switch
|
||||
if (backupInfo.version !== this.backupInfo.version) {
|
||||
console.log(
|
||||
logger.log(
|
||||
"On backup version " + this.backupInfo.version + " but found " +
|
||||
"version " + backupInfo.version + ": switching.",
|
||||
);
|
||||
this._baseApis.disableKeyBackup();
|
||||
this._baseApis.enableKeyBackup(backupInfo);
|
||||
} else {
|
||||
console.log("Backup version " + backupInfo.version + " still current");
|
||||
logger.log("Backup version " + backupInfo.version + " still current");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,7 +359,7 @@ Crypto.prototype.isKeyBackupTrusted = async function(backupInfo) {
|
||||
for (const keyId of Object.keys(mySigs)) {
|
||||
const keyIdParts = keyId.split(':');
|
||||
if (keyIdParts[0] !== 'ed25519') {
|
||||
console.log("Ignoring unknown signature type: " + keyIdParts[0]);
|
||||
logger.log("Ignoring unknown signature type: " + keyIdParts[0]);
|
||||
continue;
|
||||
}
|
||||
const sigInfo = { deviceId: keyIdParts[1] }; // XXX: is this how we're supposed to get the device ID?
|
||||
@@ -371,7 +371,9 @@ Crypto.prototype.isKeyBackupTrusted = async function(backupInfo) {
|
||||
try {
|
||||
await olmlib.verifySignature(
|
||||
this._olmDevice,
|
||||
backupInfo.auth_data,
|
||||
// verifySignature modifies the object so we need to copy
|
||||
// if we verify more than one sig
|
||||
Object.assign({}, backupInfo.auth_data),
|
||||
this._userId,
|
||||
device.deviceId,
|
||||
device.getFingerprint(),
|
||||
@@ -1176,7 +1178,7 @@ Crypto.prototype.scheduleKeyBackupSend = async function(maxDelay = 10000) {
|
||||
numFailures = 0;
|
||||
} catch (err) {
|
||||
numFailures++;
|
||||
console.log("Key backup request failed", err);
|
||||
logger.log("Key backup request failed", err);
|
||||
if (err.data) {
|
||||
if (
|
||||
err.data.errcode == 'M_NOT_FOUND' ||
|
||||
@@ -1286,6 +1288,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<int>} Resolves to the number of sessions requiring a backup.
|
||||
*/
|
||||
Crypto.prototype.flagAllGroupSessionsForBackup = async function() {
|
||||
await this._cryptoStore.doTxn(
|
||||
'readwrite',
|
||||
[
|
||||
@@ -1303,9 +1317,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
|
||||
@@ -1646,6 +1658,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"
|
||||
@@ -1665,6 +1682,11 @@ Crypto.prototype._onKeyVerificationRequest = function(event) {
|
||||
}
|
||||
|
||||
const sender = event.getSender();
|
||||
if (sender === this._userId && content.from_device === this._deviceId) {
|
||||
// ignore requests from ourselves, because it doesn't make sense for a
|
||||
// device to verify itself
|
||||
return;
|
||||
}
|
||||
if (this._verificationTransactions.has(sender)) {
|
||||
if (this._verificationTransactions.get(sender).has(content.transaction_id)) {
|
||||
// transaction already exists: cancel it and drop the existing
|
||||
@@ -1717,7 +1739,7 @@ Crypto.prototype._onKeyVerificationRequest = function(event) {
|
||||
},
|
||||
);
|
||||
} else {
|
||||
// notify the application that of the verification request, so it can
|
||||
// notify the application of the verification request, so it can
|
||||
// decide what to do with it
|
||||
const request = {
|
||||
event: event,
|
||||
@@ -1757,6 +1779,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;
|
||||
@@ -1882,7 +1909,7 @@ Crypto.prototype._onKeyVerificationMessage = function(event) {
|
||||
if (!handler) {
|
||||
return;
|
||||
} else if (event.getType() === "m.key.verification.cancel") {
|
||||
console.log(event);
|
||||
logger.log(event);
|
||||
if (handler.verifier) {
|
||||
handler.verifier.cancel(event);
|
||||
} else if (handler.request && handler.request.cancel) {
|
||||
|
||||
@@ -24,7 +24,7 @@ limitations under the License.
|
||||
import Promise from 'bluebird';
|
||||
const anotherjson = require('another-json');
|
||||
|
||||
const logger = require("../logger");
|
||||
import logger from '../logger';
|
||||
const utils = require("../utils");
|
||||
|
||||
/**
|
||||
|
||||
@@ -694,7 +694,7 @@ function promiseifyTxn(txn) {
|
||||
if (txn._mx_abortexception !== undefined) {
|
||||
reject(txn._mx_abortexception);
|
||||
} else {
|
||||
console.log("Error performing indexeddb txn", event);
|
||||
logger.log("Error performing indexeddb txn", event);
|
||||
reject(event.target.error);
|
||||
}
|
||||
};
|
||||
@@ -702,7 +702,7 @@ function promiseifyTxn(txn) {
|
||||
if (txn._mx_abortexception !== undefined) {
|
||||
reject(txn._mx_abortexception);
|
||||
} else {
|
||||
console.log("Error performing indexeddb txn", event);
|
||||
logger.log("Error performing indexeddb txn", event);
|
||||
reject(event.target.error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -90,7 +90,7 @@ export default class IndexedDBCryptoStore {
|
||||
};
|
||||
|
||||
req.onerror = (ev) => {
|
||||
console.log("Error connecting to indexeddb", ev);
|
||||
logger.log("Error connecting to indexeddb", ev);
|
||||
reject(ev.target.error);
|
||||
};
|
||||
|
||||
@@ -160,7 +160,7 @@ export default class IndexedDBCryptoStore {
|
||||
};
|
||||
|
||||
req.onerror = (ev) => {
|
||||
console.log("Error deleting data from indexeddb", ev);
|
||||
logger.log("Error deleting data from indexeddb", ev);
|
||||
reject(ev.target.error);
|
||||
};
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@ limitations under the License.
|
||||
|
||||
import {MatrixEvent} from '../../models/event';
|
||||
import {EventEmitter} from 'events';
|
||||
import logger from '../../logger';
|
||||
import {newTimeoutError} from "./Error";
|
||||
|
||||
const timeoutException = new Error("Verification timed out");
|
||||
|
||||
export default class VerificationBase extends EventEmitter {
|
||||
/**
|
||||
@@ -59,9 +63,34 @@ export default class VerificationBase extends EventEmitter {
|
||||
this.transactionId = transactionId;
|
||||
this.startEvent = startEvent;
|
||||
this.request = request;
|
||||
this.cancelled = false;
|
||||
this._parent = parent;
|
||||
this._done = false;
|
||||
this._promise = null;
|
||||
this._transactionTimeoutTimer = null;
|
||||
|
||||
// At this point, the verification request was received so start the timeout timer.
|
||||
this._resetTimer();
|
||||
}
|
||||
|
||||
_resetTimer() {
|
||||
console.log("Refreshing/starting the verification transaction timeout timer");
|
||||
if (this._transactionTimeoutTimer !== null) {
|
||||
clearTimeout(this._transactionTimeoutTimer);
|
||||
}
|
||||
this._transactionTimeoutTimer = setTimeout(() => {
|
||||
if (!this._done && !this.cancelled) {
|
||||
console.log("Triggering verification timeout");
|
||||
this.cancel(timeoutException);
|
||||
}
|
||||
}, 10 * 60 * 1000); // 10 minutes
|
||||
}
|
||||
|
||||
_endTimer() {
|
||||
if (this._transactionTimeoutTimer !== null) {
|
||||
clearTimeout(this._transactionTimeoutTimer);
|
||||
this._transactionTimeoutTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
_sendToDevice(type, content) {
|
||||
@@ -91,6 +120,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;
|
||||
@@ -108,17 +138,23 @@ export default class VerificationBase extends EventEmitter {
|
||||
}
|
||||
|
||||
done() {
|
||||
this._endTimer(); // always kill the activity timer
|
||||
if (!this._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._sendToDevice(timeoutEvent.getType(), timeoutEvent.getContent());
|
||||
} else if (e instanceof MatrixEvent) {
|
||||
const sender = e.getSender();
|
||||
if (sender !== this.userId) {
|
||||
const content = e.getContent();
|
||||
@@ -145,7 +181,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);
|
||||
}
|
||||
@@ -167,15 +205,18 @@ export default class VerificationBase extends EventEmitter {
|
||||
this._promise = new Promise((resolve, reject) => {
|
||||
this._resolve = (...args) => {
|
||||
this._done = true;
|
||||
this._endTimer();
|
||||
resolve(...args);
|
||||
};
|
||||
this._reject = (...args) => {
|
||||
this._done = true;
|
||||
this._endTimer();
|
||||
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));
|
||||
}
|
||||
@@ -183,17 +224,29 @@ export default class VerificationBase extends EventEmitter {
|
||||
}
|
||||
|
||||
async _verifyKeys(userId, keys, verifier) {
|
||||
// we try to verify all the keys that we're told about, but we might
|
||||
// not know about all of them, so keep track of the keys that we know
|
||||
// about, and ignore the rest
|
||||
const verifiedDevices = [];
|
||||
|
||||
for (const [keyId, keyInfo] of Object.entries(keys)) {
|
||||
const deviceId = keyId.split(':', 2)[1];
|
||||
const device = await this._baseApis.getStoredDevice(userId, deviceId);
|
||||
if (!device) {
|
||||
throw new Error(`Could not find device ${deviceId}`);
|
||||
logger.warn(`verification: Could not find device ${deviceId} to verify`);
|
||||
} else {
|
||||
await verifier(keyId, device, keyInfo);
|
||||
verifiedDevices.push(deviceId);
|
||||
}
|
||||
}
|
||||
for (const keyId of Object.keys(keys)) {
|
||||
const deviceId = keyId.split(':', 2)[1];
|
||||
|
||||
// if none of the keys could be verified, then error because the app
|
||||
// should be informed about that
|
||||
if (!verifiedDevices.length) {
|
||||
throw new Error("No devices could be verified");
|
||||
}
|
||||
|
||||
for (const deviceId of verifiedDevices) {
|
||||
await this._baseApis.setDeviceVerified(userId, deviceId);
|
||||
}
|
||||
}
|
||||
|
||||
+42
-11
@@ -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,6 +23,7 @@ import Promise from 'bluebird';
|
||||
const parseContentType = require('content-type').parse;
|
||||
|
||||
const utils = require("./utils");
|
||||
import logger from '../src/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
|
||||
@@ -45,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
|
||||
*/
|
||||
@@ -101,7 +108,7 @@ module.exports.MatrixHttpApi.prototype = {
|
||||
};
|
||||
return {
|
||||
base: this.opts.baseUrl,
|
||||
path: "/_matrix/media/v1/upload",
|
||||
path: "/_matrix/media/r0/upload",
|
||||
params: params,
|
||||
};
|
||||
},
|
||||
@@ -164,9 +171,21 @@ module.exports.MatrixHttpApi.prototype = {
|
||||
const contentType = opts.type || file.type || 'application/octet-stream';
|
||||
const fileName = opts.name || file.name;
|
||||
|
||||
// we used to recommend setting file.stream to the thing to upload on
|
||||
// nodejs.
|
||||
const body = file.stream ? file.stream : file;
|
||||
// We used to recommend setting file.stream to the thing to upload on
|
||||
// Node.js. As of 2019-06-11, this is still in widespread use in various
|
||||
// clients, so we should preserve this for simple objects used in
|
||||
// Node.js. File API objects (via either the File or Blob interfaces) in
|
||||
// the browser now define a `stream` method, which leads to trouble
|
||||
// here, so we also check the type of `stream`.
|
||||
let body = file;
|
||||
if (body.stream && typeof body.stream !== "function") {
|
||||
logger.warn(
|
||||
"Using `file.stream` as the content to upload. Future " +
|
||||
"versions of the js-sdk will change this to expect `file` to " +
|
||||
"be the content directly.",
|
||||
);
|
||||
body = body.stream;
|
||||
}
|
||||
|
||||
// backwards-compatibility hacks where we used to do different things
|
||||
// between browser and node.
|
||||
@@ -175,7 +194,7 @@ module.exports.MatrixHttpApi.prototype = {
|
||||
if (global.XMLHttpRequest) {
|
||||
rawResponse = false;
|
||||
} else {
|
||||
console.warn(
|
||||
logger.warn(
|
||||
"Returning the raw JSON from uploadContent(). Future " +
|
||||
"versions of the js-sdk will change this default, to " +
|
||||
"return the parsed object. Set opts.rawResponse=false " +
|
||||
@@ -188,7 +207,7 @@ module.exports.MatrixHttpApi.prototype = {
|
||||
let onlyContentUri = opts.onlyContentUri;
|
||||
if (!rawResponse && onlyContentUri === undefined) {
|
||||
if (global.XMLHttpRequest) {
|
||||
console.warn(
|
||||
logger.warn(
|
||||
"Returning only the content-uri from uploadContent(). " +
|
||||
"Future versions of the js-sdk will change this " +
|
||||
"default, to return the whole response object. Set " +
|
||||
@@ -278,7 +297,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 = [];
|
||||
|
||||
@@ -314,7 +333,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,
|
||||
@@ -355,7 +374,14 @@ module.exports.MatrixHttpApi.prototype = {
|
||||
return this.uploads;
|
||||
},
|
||||
|
||||
idServerRequest: function(callback, method, path, params, prefix) {
|
||||
idServerRequest: function(
|
||||
callback,
|
||||
method,
|
||||
path,
|
||||
params,
|
||||
prefix,
|
||||
accessToken,
|
||||
) {
|
||||
const fullUri = this.opts.idBaseUrl + prefix + path;
|
||||
|
||||
if (callback !== undefined && !utils.isFunction(callback)) {
|
||||
@@ -376,6 +402,11 @@ module.exports.MatrixHttpApi.prototype = {
|
||||
} else {
|
||||
opts.form = params;
|
||||
}
|
||||
if (accessToken) {
|
||||
opts.headers = {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
};
|
||||
}
|
||||
|
||||
const defer = Promise.defer();
|
||||
this.opts.request(
|
||||
@@ -457,7 +488,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",
|
||||
|
||||
+62
-12
@@ -22,6 +22,7 @@ import Promise from 'bluebird';
|
||||
const url = require("url");
|
||||
|
||||
const utils = require("./utils");
|
||||
import logger from '../src/logger';
|
||||
|
||||
const EMAIL_STAGE_TYPE = "m.login.email.identity";
|
||||
const MSISDN_STAGE_TYPE = "m.login.msisdn";
|
||||
@@ -48,11 +49,18 @@ const MSISDN_STAGE_TYPE = "m.login.msisdn";
|
||||
* @param {object?} opts.authData error response from the last request. If
|
||||
* null, a request will be made with no auth before starting.
|
||||
*
|
||||
* @param {function(object?, bool?): module:client.Promise} opts.doRequest
|
||||
* called with the new auth dict to submit the request and a flag set
|
||||
* to true if this request is a background request. Should return a
|
||||
* promise which resolves to the successful response or rejects with a
|
||||
* MatrixError.
|
||||
* @param {function(object?): module:client.Promise} opts.doRequest
|
||||
* called with the new auth dict to submit the request. Also passes a
|
||||
* second deprecated arg which is a flag set to true if this request
|
||||
* is a background request. The busyChanged callback should be used
|
||||
* instead of the backfround flag. Should return a promise which resolves
|
||||
* to the successful response or rejects with a MatrixError.
|
||||
*
|
||||
* @param {function(bool): module:client.Promise} opts.busyChanged
|
||||
* called whenever the interactive auth logic becomes busy submitting
|
||||
* information provided by the user or finsihes. After this has been
|
||||
* called with true the UI should indicate that a request is in progress
|
||||
* until it is called again with false.
|
||||
*
|
||||
* @param {function(string, object?)} opts.stateUpdated
|
||||
* called when the status of the UI auth changes, ie. when the state of
|
||||
@@ -100,6 +108,7 @@ function InteractiveAuth(opts) {
|
||||
this._matrixClient = opts.matrixClient;
|
||||
this._data = opts.authData || {};
|
||||
this._requestCallback = opts.doRequest;
|
||||
this._busyChangedCallback = opts.busyChanged;
|
||||
// startAuthStage included for backwards compat
|
||||
this._stateUpdatedCallback = opts.stateUpdated || opts.startAuthStage;
|
||||
this._resolveFunc = null;
|
||||
@@ -111,9 +120,14 @@ function InteractiveAuth(opts) {
|
||||
this._clientSecret = opts.clientSecret || this._matrixClient.generateClientSecret();
|
||||
this._emailSid = opts.emailSid;
|
||||
if (this._emailSid === undefined) this._emailSid = null;
|
||||
this._requestingEmailToken = false;
|
||||
|
||||
this._chosenFlow = null;
|
||||
this._currentStage = null;
|
||||
|
||||
// if we are currently trying to submit an auth dict (which includes polling)
|
||||
// the promise the will resolve/reject when it completes
|
||||
this._submitPromise = null;
|
||||
}
|
||||
|
||||
InteractiveAuth.prototype = {
|
||||
@@ -134,7 +148,10 @@ InteractiveAuth.prototype = {
|
||||
// if we have no flows, try a request (we'll have
|
||||
// just a session ID in _data if resuming)
|
||||
if (!this._data.flows) {
|
||||
this._doRequest(this._data);
|
||||
if (this._busyChangedCallback) this._busyChangedCallback(true);
|
||||
this._doRequest(this._data).finally(() => {
|
||||
if (this._busyChangedCallback) this._busyChangedCallback(false);
|
||||
});
|
||||
} else {
|
||||
this._startNextAuthStage();
|
||||
}
|
||||
@@ -146,8 +163,11 @@ InteractiveAuth.prototype = {
|
||||
* completed out-of-band. If so, the attemptAuth promise will
|
||||
* be resolved.
|
||||
*/
|
||||
poll: function() {
|
||||
poll: async function() {
|
||||
if (!this._data.session) return;
|
||||
// if we currently have a request in flight, there's no point making
|
||||
// another just to check what the status is
|
||||
if (this._submitPromise) return;
|
||||
|
||||
let authDict = {};
|
||||
if (this._currentStage == EMAIL_STAGE_TYPE) {
|
||||
@@ -220,18 +240,44 @@ InteractiveAuth.prototype = {
|
||||
* in the attemptAuth promise being rejected. This can be set to true
|
||||
* for requests that just poll to see if auth has been completed elsewhere.
|
||||
*/
|
||||
submitAuthDict: function(authData, background) {
|
||||
submitAuthDict: async function(authData, background) {
|
||||
if (!this._resolveFunc) {
|
||||
throw new Error("submitAuthDict() called before attemptAuth()");
|
||||
}
|
||||
|
||||
if (!background && this._busyChangedCallback) {
|
||||
this._busyChangedCallback(true);
|
||||
}
|
||||
|
||||
// if we're currently trying a request, wait for it to finish
|
||||
// as otherwise we can get multiple 200 responses which can mean
|
||||
// things like multiple logins for register requests.
|
||||
// (but discard any expections as we only care when its done,
|
||||
// not whether it worked or not)
|
||||
while (this._submitPromise) {
|
||||
try {
|
||||
await this._submitPromise;
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
// use the sessionid from the last request.
|
||||
const auth = {
|
||||
session: this._data.session,
|
||||
};
|
||||
utils.extend(auth, authData);
|
||||
|
||||
this._doRequest(auth, background);
|
||||
try {
|
||||
// NB. the 'background' flag is deprecated by the busyChanged
|
||||
// callback and is here for backwards compat
|
||||
this._submitPromise = this._doRequest(auth, background);
|
||||
await this._submitPromise;
|
||||
} finally {
|
||||
this._submitPromise = null;
|
||||
if (!background && this._busyChangedCallback) {
|
||||
this._busyChangedCallback(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -283,7 +329,7 @@ InteractiveAuth.prototype = {
|
||||
// We ignore all failures here (even non-UI auth related ones)
|
||||
// since we don't want to suddenly fail if the internet connection
|
||||
// had a blip whilst we were polling
|
||||
console.log(
|
||||
logger.log(
|
||||
"Background poll request failed doing UI auth: ignoring",
|
||||
error,
|
||||
);
|
||||
@@ -304,12 +350,14 @@ InteractiveAuth.prototype = {
|
||||
|
||||
if (
|
||||
!this._emailSid &&
|
||||
!this._requestingEmailToken &&
|
||||
this._chosenFlow.stages.includes('m.login.email.identity')
|
||||
) {
|
||||
// If we've picked a flow with email auth, we send the email
|
||||
// now because we want the request to fail as soon as possible
|
||||
// if the email address is not valid (ie. already taken or not
|
||||
// registered, depending on what the operation is).
|
||||
this._requestingEmailToken = true;
|
||||
try {
|
||||
const requestTokenResult = await this._requestEmailTokenCallback(
|
||||
this._inputs.emailAddress,
|
||||
@@ -332,6 +380,8 @@ InteractiveAuth.prototype = {
|
||||
// the failure up as the user can't complete auth if we can't
|
||||
// send the email, foe whatever reason.
|
||||
this._rejectFunc(e);
|
||||
} finally {
|
||||
this._requestingEmailToken = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -383,9 +433,9 @@ InteractiveAuth.prototype = {
|
||||
if (this._chosenFlow === null) {
|
||||
this._chosenFlow = this._chooseFlow();
|
||||
}
|
||||
console.log("Active flow => %s", JSON.stringify(this._chosenFlow));
|
||||
logger.log("Active flow => %s", JSON.stringify(this._chosenFlow));
|
||||
const nextStage = this._firstUncompletedStage(this._chosenFlow);
|
||||
console.log("Next stage: %s", nextStage);
|
||||
logger.log("Next stage: %s", nextStage);
|
||||
return nextStage;
|
||||
},
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -20,6 +20,8 @@ limitations under the License.
|
||||
const EventEmitter = require("events").EventEmitter;
|
||||
const utils = require("../utils");
|
||||
const EventTimeline = require("./event-timeline");
|
||||
import {EventStatus} from "./event";
|
||||
import logger from '../../src/logger';
|
||||
import Relations from './relations';
|
||||
|
||||
// var DEBUG = false;
|
||||
@@ -28,7 +30,7 @@ const DEBUG = true;
|
||||
let debuglog;
|
||||
if (DEBUG) {
|
||||
// using bind means that we get to keep useful line numbers in the console
|
||||
debuglog = console.log.bind(console);
|
||||
debuglog = logger.log.bind(logger);
|
||||
} else {
|
||||
debuglog = function() {};
|
||||
}
|
||||
@@ -422,7 +424,7 @@ EventTimelineSet.prototype.addEventsToTimeline = function(events, toStartOfTimel
|
||||
}
|
||||
|
||||
// time to join the timelines.
|
||||
console.info("Already have timeline for " + eventId +
|
||||
logger.info("Already have timeline for " + eventId +
|
||||
" - joining timeline " + timeline + " to " +
|
||||
existingTimeline);
|
||||
|
||||
@@ -436,15 +438,14 @@ 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.
|
||||
console.warn({backwardsIsLive, forwardsIsLive}); // debugging
|
||||
if (backwardsIsLive) {
|
||||
console.warn(
|
||||
logger.warn(
|
||||
"Refusing to set a preceding existingTimeLine on our " +
|
||||
"timeline as the existingTimeLine is live (" + existingTimeline + ")",
|
||||
);
|
||||
}
|
||||
if (forwardsIsLive) {
|
||||
console.warn(
|
||||
logger.warn(
|
||||
"Refusing to set our preceding timeline on a existingTimeLine " +
|
||||
"as our timeline is live (" + timeline + ")",
|
||||
);
|
||||
@@ -464,8 +465,8 @@ EventTimelineSet.prototype.addEventsToTimeline = function(events, toStartOfTimel
|
||||
// timeline we ended up on.
|
||||
if (lastEventWasNew || !didUpdate) {
|
||||
if (direction === EventTimeline.FORWARDS && timeline === this._liveTimeline) {
|
||||
console.warn({lastEventWasNew, didUpdate}); // for debugging
|
||||
console.warn(
|
||||
logger.warn({lastEventWasNew, didUpdate}); // for debugging
|
||||
logger.warn(
|
||||
`Refusing to set forwards pagination token of live timeline ` +
|
||||
`${timeline} to ${paginationToken}`,
|
||||
);
|
||||
@@ -748,6 +749,10 @@ EventTimelineSet.prototype.aggregateRelations = function(event) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.isRedacted() || event.status === EventStatus.CANCELLED) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the event is currently encrypted, wait until it has been decrypted.
|
||||
if (event.isBeingDecrypted()) {
|
||||
event.once("Event.decrypted", () => {
|
||||
|
||||
+186
-13
@@ -24,13 +24,14 @@ limitations under the License.
|
||||
import Promise from 'bluebird';
|
||||
import {EventEmitter} from 'events';
|
||||
import utils from '../utils.js';
|
||||
import logger from '../../src/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",
|
||||
|
||||
@@ -48,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) {
|
||||
@@ -123,6 +125,8 @@ module.exports.MatrixEvent = function MatrixEvent(
|
||||
this.forwardLooking = true;
|
||||
this._pushActions = null;
|
||||
this._replacingEvent = null;
|
||||
this._localRedactionEvent = null;
|
||||
this._isCancelled = false;
|
||||
|
||||
this._clearEvent = {};
|
||||
|
||||
@@ -227,6 +231,9 @@ utils.extend(module.exports.MatrixEvent.prototype, {
|
||||
* @return {Object} The event content JSON, or an empty object.
|
||||
*/
|
||||
getOriginalContent: function() {
|
||||
if (this._localRedactionEvent) {
|
||||
return {};
|
||||
}
|
||||
return this._clearEvent.content || this.event.content || {};
|
||||
},
|
||||
|
||||
@@ -238,7 +245,9 @@ utils.extend(module.exports.MatrixEvent.prototype, {
|
||||
* @return {Object} The event content JSON, or an empty object.
|
||||
*/
|
||||
getContent: function() {
|
||||
if (this._replacingEvent) {
|
||||
if (this._localRedactionEvent) {
|
||||
return {};
|
||||
} else if (this._replacingEvent) {
|
||||
return this._replacingEvent.getContent()["m.new_content"] || {};
|
||||
} else {
|
||||
return this.getOriginalContent();
|
||||
@@ -395,7 +404,7 @@ utils.extend(module.exports.MatrixEvent.prototype, {
|
||||
// new info.
|
||||
//
|
||||
if (this._decryptionPromise) {
|
||||
console.log(
|
||||
logger.log(
|
||||
`Event ${this.getId()} already being decrypted; queueing a retry`,
|
||||
);
|
||||
this._retryDecryption = true;
|
||||
@@ -469,7 +478,7 @@ utils.extend(module.exports.MatrixEvent.prototype, {
|
||||
if (e.name !== "DecryptionError") {
|
||||
// not a decryption error: log the whole exception as an error
|
||||
// (and don't bother with a retry)
|
||||
console.error(
|
||||
logger.error(
|
||||
`Error decrypting event (id=${this.getId()}): ${e.stack || e}`,
|
||||
);
|
||||
this._decryptionPromise = null;
|
||||
@@ -495,7 +504,7 @@ utils.extend(module.exports.MatrixEvent.prototype, {
|
||||
//
|
||||
if (this._retryDecryption) {
|
||||
// decryption error, but we have a retry queued.
|
||||
console.log(
|
||||
logger.log(
|
||||
`Got error decrypting event (id=${this.getId()}: ` +
|
||||
`${e}), but retrying`,
|
||||
);
|
||||
@@ -504,7 +513,7 @@ utils.extend(module.exports.MatrixEvent.prototype, {
|
||||
|
||||
// decryption error, no retries queued. Warn about the error and
|
||||
// set it to m.bad.encrypted.
|
||||
console.warn(
|
||||
logger.warn(
|
||||
`Error decrypting event (id=${this.getId()}): ${e.detailedString}`,
|
||||
);
|
||||
|
||||
@@ -665,6 +674,27 @@ utils.extend(module.exports.MatrixEvent.prototype, {
|
||||
return this.event.unsigned || {};
|
||||
},
|
||||
|
||||
unmarkLocallyRedacted: function() {
|
||||
const value = this._localRedactionEvent;
|
||||
this._localRedactionEvent = null;
|
||||
if (this.event.unsigned) {
|
||||
this.event.unsigned.redacted_because = null;
|
||||
}
|
||||
return !!value;
|
||||
},
|
||||
|
||||
markLocallyRedacted: function(redactionEvent) {
|
||||
if (this._localRedactionEvent) {
|
||||
return;
|
||||
}
|
||||
this.emit("Event.beforeRedaction", this, redactionEvent);
|
||||
this._localRedactionEvent = redactionEvent;
|
||||
if (!this.event.unsigned) {
|
||||
this.event.unsigned = {};
|
||||
}
|
||||
this.event.unsigned.redacted_because = redactionEvent.event;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the content of an event in the same way it would be by the server
|
||||
* if it were redacted before it was sent to us
|
||||
@@ -678,6 +708,8 @@ utils.extend(module.exports.MatrixEvent.prototype, {
|
||||
throw new Error("invalid redaction_event in makeRedacted");
|
||||
}
|
||||
|
||||
this._localRedactionEvent = null;
|
||||
|
||||
this.emit("Event.beforeRedaction", this, redaction_event);
|
||||
|
||||
this._replacingEvent = null;
|
||||
@@ -723,6 +755,15 @@ utils.extend(module.exports.MatrixEvent.prototype, {
|
||||
return Boolean(this.getUnsigned().redacted_because);
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if this event is a redaction of another event
|
||||
*
|
||||
* @return {boolean} True if this event is a redaction
|
||||
*/
|
||||
isRedaction: function() {
|
||||
return this.getType() === "m.room.redaction";
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the push actions, if known, for this event
|
||||
*
|
||||
@@ -746,9 +787,26 @@ utils.extend(module.exports.MatrixEvent.prototype, {
|
||||
* @param {Object} event the object to assign to the `event` property
|
||||
*/
|
||||
handleRemoteEcho: function(event) {
|
||||
const oldUnsigned = this.getUnsigned();
|
||||
const oldId = this.getId();
|
||||
this.event = event;
|
||||
// if this event was redacted before it was sent, it's locally marked as redacted.
|
||||
// At this point, we've received the remote echo for the event, but not yet for
|
||||
// the redaction that we are sending ourselves. Preserve the locally redacted
|
||||
// state by copying over redacted_because so we don't get a flash of
|
||||
// redacted, not-redacted, redacted as remote echos come in
|
||||
if (oldUnsigned.redacted_because) {
|
||||
if (!this.event.unsigned) {
|
||||
this.event.unsigned = {};
|
||||
}
|
||||
this.event.unsigned.redacted_because = oldUnsigned.redacted_because;
|
||||
}
|
||||
// successfully sent.
|
||||
this.setStatus(null);
|
||||
if (this.getId() !== oldId) {
|
||||
// emit the event if it changed
|
||||
this.emit("Event.localEventIdReplaced", this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -771,6 +829,11 @@ utils.extend(module.exports.MatrixEvent.prototype, {
|
||||
this.emit("Event.status", this, status);
|
||||
},
|
||||
|
||||
replaceLocalEventId(eventId) {
|
||||
this.event.event_id = eventId;
|
||||
this.emit("Event.localEventIdReplaced", this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get whether the event is a relation event, and of a given type if
|
||||
* `relType` is passed in.
|
||||
@@ -806,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) {
|
||||
@@ -816,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];
|
||||
}
|
||||
},
|
||||
|
||||
@@ -834,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?}
|
||||
*/
|
||||
@@ -846,6 +930,90 @@ 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.
|
||||
*
|
||||
* @return {string?}
|
||||
*/
|
||||
getAssociatedId() {
|
||||
const relation = this.getRelation();
|
||||
if (relation) {
|
||||
return relation.event_id;
|
||||
} else if (this.isRedaction()) {
|
||||
return this.event.redacts;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if this event is associated with another event. See `getAssociatedId`.
|
||||
*
|
||||
* @return {bool}
|
||||
*/
|
||||
hasAssocation() {
|
||||
return !!this.getAssociatedId();
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the related id with a new one.
|
||||
*
|
||||
* Used to replace a local id with remote one before sending
|
||||
* an event with a related id.
|
||||
*
|
||||
* @param {string} eventId the new event id
|
||||
*/
|
||||
updateAssociatedId(eventId) {
|
||||
const relation = this.getRelation();
|
||||
if (relation) {
|
||||
relation.event_id = eventId;
|
||||
} else if (this.isRedaction()) {
|
||||
this.event.redacts = eventId;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -865,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;
|
||||
}
|
||||
@@ -880,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
|
||||
|
||||
+11
-6
@@ -242,12 +242,7 @@ export default class Relations extends EventEmitter {
|
||||
|
||||
redactedEvent.removeListener("Event.beforeRedaction", this._onBeforeRedaction);
|
||||
|
||||
// Dispatch a redaction event on this collection. `setTimeout` is used
|
||||
// to wait until the next event loop iteration by which time the event
|
||||
// has actually been marked as redacted.
|
||||
setTimeout(() => {
|
||||
this.emit("Relations.redaction");
|
||||
}, 0);
|
||||
this.emit("Relations.redaction");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -306,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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -21,6 +21,7 @@ const EventEmitter = require("events").EventEmitter;
|
||||
|
||||
const utils = require("../utils");
|
||||
const RoomMember = require("./room-member");
|
||||
import logger from '../../src/logger';
|
||||
|
||||
// possible statuses for out-of-band member loading
|
||||
const OOB_STATUS_NOTSTARTED = 1;
|
||||
@@ -447,7 +448,7 @@ RoomState.prototype.clearOutOfBandMembers = function() {
|
||||
delete this.members[userId];
|
||||
}
|
||||
});
|
||||
console.log(`LL: RoomState removed ${count} members...`);
|
||||
logger.log(`LL: RoomState removed ${count} members...`);
|
||||
this._oobMemberFlags.status = OOB_STATUS_NOTSTARTED;
|
||||
};
|
||||
|
||||
@@ -456,11 +457,11 @@ RoomState.prototype.clearOutOfBandMembers = function() {
|
||||
* @param {MatrixEvent[]} stateEvents array of membership state events
|
||||
*/
|
||||
RoomState.prototype.setOutOfBandMembers = function(stateEvents) {
|
||||
console.log(`LL: RoomState about to set ${stateEvents.length} OOB members ...`);
|
||||
logger.log(`LL: RoomState about to set ${stateEvents.length} OOB members ...`);
|
||||
if (this._oobMemberFlags.status !== OOB_STATUS_INPROGRESS) {
|
||||
return;
|
||||
}
|
||||
console.log(`LL: RoomState put in OOB_STATUS_FINISHED state ...`);
|
||||
logger.log(`LL: RoomState put in OOB_STATUS_FINISHED state ...`);
|
||||
this._oobMemberFlags.status = OOB_STATUS_FINISHED;
|
||||
stateEvents.forEach((e) => this._setOutOfBandMember(e));
|
||||
};
|
||||
|
||||
+187
-66
@@ -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,6 +30,7 @@ const ContentRepo = require("../content-repo");
|
||||
const EventTimeline = require("./event-timeline");
|
||||
const EventTimelineSet = require("./event-timeline-set");
|
||||
|
||||
import logger from '../../src/logger';
|
||||
import ReEmitter from '../ReEmitter';
|
||||
|
||||
// These constants are used as sane defaults when the homeserver doesn't support
|
||||
@@ -37,8 +39,8 @@ 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 SAFE_ROOM_VERSIONS = ['1', '2', '3'];
|
||||
const KNOWN_SAFE_ROOM_VERSION = '4';
|
||||
const SAFE_ROOM_VERSIONS = ['1', '2', '3', '4'];
|
||||
|
||||
function synthesizeReceipt(userId, event, receiptType) {
|
||||
// console.log("synthesizing receipt for "+event.getId());
|
||||
@@ -209,7 +211,7 @@ utils.inherits(Room, EventEmitter);
|
||||
Room.prototype.getVersion = function() {
|
||||
const createEvent = this.currentState.getStateEvents("m.room.create", "");
|
||||
if (!createEvent) {
|
||||
console.warn("Room " + this.room_id + " does not have an m.room.create event");
|
||||
logger.warn("Room " + this.room_id + " does not have an m.room.create event");
|
||||
return '1';
|
||||
}
|
||||
const ver = createEvent.getContent()['room_version'];
|
||||
@@ -262,9 +264,36 @@ Room.prototype.getRecommendedVersion = async function() {
|
||||
}
|
||||
}
|
||||
|
||||
let result = this._checkVersionAgainstCapability(versionCap);
|
||||
if (result.urgent && result.needsUpgrade) {
|
||||
// Something doesn't feel right: we shouldn't need to update
|
||||
// because the version we're on should be in the protocol's
|
||||
// namespace. This usually means that the server was updated
|
||||
// before the client was, making us think the newest possible
|
||||
// room version is not stable. As a solution, we'll refresh
|
||||
// the capability we're using to determine this.
|
||||
logger.warn(
|
||||
"Refreshing room version capability because the server looks " +
|
||||
"to be supporting a newer room version we don't know about.",
|
||||
);
|
||||
|
||||
const caps = await this._client.getCapabilities(true);
|
||||
versionCap = caps["m.room_versions"];
|
||||
if (!versionCap) {
|
||||
logger.warn("No room version capability - assuming upgrade required.");
|
||||
return result;
|
||||
} else {
|
||||
result = this._checkVersionAgainstCapability(versionCap);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
Room.prototype._checkVersionAgainstCapability = function(versionCap) {
|
||||
const currentVersion = this.getVersion();
|
||||
console.log(`[${this.roomId}] Current version: ${currentVersion}`);
|
||||
console.log(`[${this.roomId}] Version capability: `, versionCap);
|
||||
logger.log(`[${this.roomId}] Current version: ${currentVersion}`);
|
||||
logger.log(`[${this.roomId}] Version capability: `, versionCap);
|
||||
|
||||
const result = {
|
||||
version: currentVersion,
|
||||
@@ -273,7 +302,7 @@ Room.prototype.getRecommendedVersion = async function() {
|
||||
};
|
||||
|
||||
// If the room is on the default version then nothing needs to change
|
||||
if (currentVersion === versionCap.default) return Promise.resolve(result);
|
||||
if (currentVersion === versionCap.default) return result;
|
||||
|
||||
const stableVersions = Object.keys(versionCap.available)
|
||||
.filter((v) => versionCap.available[v] === 'stable');
|
||||
@@ -286,16 +315,16 @@ Room.prototype.getRecommendedVersion = async function() {
|
||||
result.needsUpgrade = true;
|
||||
result.urgent = !!this.getVersion().match(/^[0-9]+[0-9.]*$/g);
|
||||
if (result.urgent) {
|
||||
console.warn(`URGENT upgrade required on ${this.roomId}`);
|
||||
logger.warn(`URGENT upgrade required on ${this.roomId}`);
|
||||
} else {
|
||||
console.warn(`Non-urgent upgrade required on ${this.roomId}`);
|
||||
logger.warn(`Non-urgent upgrade required on ${this.roomId}`);
|
||||
}
|
||||
return Promise.resolve(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// The room is on a stable, but non-default, version by this point.
|
||||
// No upgrade needed.
|
||||
return Promise.resolve(result);
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -318,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 <code>opts.pendingEventOrdering</code> 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.
|
||||
*
|
||||
@@ -471,7 +517,7 @@ Room.prototype._loadMembers = async function() {
|
||||
if (rawMembersEvents === null) {
|
||||
fromServer = true;
|
||||
rawMembersEvents = await this._loadMembersFromServer();
|
||||
console.log(`LL: got ${rawMembersEvents.length} ` +
|
||||
logger.log(`LL: got ${rawMembersEvents.length} ` +
|
||||
`members from server for room ${this.roomId}`);
|
||||
}
|
||||
const memberEvents = rawMembersEvents.map(this._client.getEventMapper());
|
||||
@@ -515,21 +561,21 @@ Room.prototype.loadMembersIfNeeded = function() {
|
||||
const oobMembers = this.currentState.getMembers()
|
||||
.filter((m) => m.isOutOfBand())
|
||||
.map((m) => m.events.member.event);
|
||||
console.log(`LL: telling store to write ${oobMembers.length}`
|
||||
logger.log(`LL: telling store to write ${oobMembers.length}`
|
||||
+ ` members for room ${this.roomId}`);
|
||||
const store = this._client.store;
|
||||
return store.setOutOfBandMembers(this.roomId, oobMembers)
|
||||
// swallow any IDB error as we don't want to fail
|
||||
// because of this
|
||||
.catch((err) => {
|
||||
console.log("LL: storing OOB room members failed, oh well",
|
||||
logger.log("LL: storing OOB room members failed, oh well",
|
||||
err);
|
||||
});
|
||||
}
|
||||
}).catch((err) => {
|
||||
// as this is not awaited anywhere,
|
||||
// at least show the error in the console
|
||||
console.error(err);
|
||||
logger.error(err);
|
||||
});
|
||||
|
||||
this._membersPromise = inMemoryUpdate;
|
||||
@@ -555,9 +601,9 @@ Room.prototype.clearLoadedMembersIfNeeded = async function() {
|
||||
*/
|
||||
Room.prototype._cleanupAfterLeaving = function() {
|
||||
this.clearLoadedMembersIfNeeded().catch((err) => {
|
||||
console.error(`error after clearing loaded members from ` +
|
||||
logger.error(`error after clearing loaded members from ` +
|
||||
`room ${this.roomId} after leaving`);
|
||||
console.dir(err);
|
||||
logger.log(err);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -735,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,
|
||||
@@ -769,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;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1004,13 +1050,25 @@ Room.prototype.removeFilteredTimelineSet = function(filter) {
|
||||
* @private
|
||||
*/
|
||||
Room.prototype._addLiveEvent = function(event, duplicateStrategy) {
|
||||
if (event.getType() === "m.room.redaction") {
|
||||
if (event.isRedaction()) {
|
||||
const redactId = event.event.redacts;
|
||||
|
||||
// if we know about this event, redact its contents now.
|
||||
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
|
||||
@@ -1101,7 +1159,7 @@ Room.prototype.addPendingEvent = function(event, txnId) {
|
||||
|
||||
if (this._opts.pendingEventOrdering == "detached") {
|
||||
if (this._pendingEventList.some((e) => e.status === EventStatus.NOT_SENT)) {
|
||||
console.warn("Setting event as NOT_SENT due to messages in the same state");
|
||||
logger.warn("Setting event as NOT_SENT due to messages in the same state");
|
||||
event.setStatus(EventStatus.NOT_SENT);
|
||||
}
|
||||
this._pendingEventList.push(event);
|
||||
@@ -1110,24 +1168,26 @@ Room.prototype.addPendingEvent = function(event, txnId) {
|
||||
// For pending events, add them to the relations collection immediately.
|
||||
// (The alternate case below already covers this as part of adding to
|
||||
// the timeline set.)
|
||||
// TODO: We should consider whether this means it would be a better
|
||||
// design to lift the relations handling up to the room instead.
|
||||
for (let i = 0; i < this._timelineSets.length; i++) {
|
||||
const timelineSet = this._timelineSets[i];
|
||||
if (timelineSet.getFilter()) {
|
||||
if (this._filter.filterRoomTimeline([event]).length) {
|
||||
timelineSet.aggregateRelations(event);
|
||||
}
|
||||
} else {
|
||||
timelineSet.aggregateRelations(event);
|
||||
}
|
||||
this._aggregateNonLiveRelation(event);
|
||||
}
|
||||
|
||||
if (event.isRedaction()) {
|
||||
const redactId = event.event.redacts;
|
||||
let redactedEvent = this._pendingEventList &&
|
||||
this._pendingEventList.find(e => e.getId() === redactId);
|
||||
if (!redactedEvent) {
|
||||
redactedEvent = this.getUnfilteredTimelineSet().findEventById(redactId);
|
||||
}
|
||||
if (redactedEvent) {
|
||||
redactedEvent.markLocallyRedacted(event);
|
||||
this.emit("Room.redaction", event, this);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
@@ -1140,6 +1200,30 @@ Room.prototype.addPendingEvent = function(event, txnId) {
|
||||
|
||||
this.emit("Room.localEchoUpdated", event, this, null, null);
|
||||
};
|
||||
/**
|
||||
* Used to aggregate the local echo for a relation, and also
|
||||
* for re-applying a relation after it's redaction has been cancelled,
|
||||
* as the local echo for the redaction of the relation would have
|
||||
* un-aggregated the relation. Note that this is different from regular messages,
|
||||
* which are just kept detached for their local echo.
|
||||
*
|
||||
* Also note that live events are aggregated in the live EventTimelineSet.
|
||||
* @param {module:models/event.MatrixEvent} event the relation event that needs to be aggregated.
|
||||
*/
|
||||
Room.prototype._aggregateNonLiveRelation = function(event) {
|
||||
// TODO: We should consider whether this means it would be a better
|
||||
// design to lift the relations handling up to the room instead.
|
||||
for (let i = 0; i < this._timelineSets.length; i++) {
|
||||
const timelineSet = this._timelineSets[i];
|
||||
if (timelineSet.getFilter()) {
|
||||
if (timelineSet.getFilter().filterRoomTimeline([event]).length) {
|
||||
timelineSet.aggregateRelations(event);
|
||||
}
|
||||
} else {
|
||||
timelineSet.aggregateRelations(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deal with the echo of a message we sent.
|
||||
@@ -1161,7 +1245,7 @@ Room.prototype._handleRemoteEcho = function(remoteEvent, localEvent) {
|
||||
const oldStatus = localEvent.status;
|
||||
|
||||
// no longer pending
|
||||
delete this._txnToEvent[remoteEvent.transaction_id];
|
||||
delete this._txnToEvent[remoteEvent.getUnsigned().transaction_id];
|
||||
|
||||
// if it's in the pending list, remove it
|
||||
if (this._pendingEventList) {
|
||||
@@ -1229,7 +1313,7 @@ ALLOWED_TRANSITIONS[EventStatus.CANCELLED] =
|
||||
* @fires module:client~MatrixClient#event:"Room.localEchoUpdated"
|
||||
*/
|
||||
Room.prototype.updatePendingEvent = function(event, newStatus, newEventId) {
|
||||
console.log(`setting pendingEvent status to ${newStatus} in ${event.getRoomId()}`);
|
||||
logger.log(`setting pendingEvent status to ${newStatus} in ${event.getRoomId()}`);
|
||||
|
||||
// if the message was sent, we expect an event id
|
||||
if (newStatus == EventStatus.SENT && !newEventId) {
|
||||
@@ -1265,7 +1349,7 @@ Room.prototype.updatePendingEvent = function(event, newStatus, newEventId) {
|
||||
|
||||
if (newStatus == EventStatus.SENT) {
|
||||
// update the event id
|
||||
event.event.event_id = newEventId;
|
||||
event.replaceLocalEventId(newEventId);
|
||||
|
||||
// if the event was already in the timeline (which will be the case if
|
||||
// opts.pendingEventOrdering==chronological), we need to update the
|
||||
@@ -1276,12 +1360,13 @@ Room.prototype.updatePendingEvent = function(event, newStatus, newEventId) {
|
||||
} else if (newStatus == EventStatus.CANCELLED) {
|
||||
// remove it from the pending event list, or the timeline.
|
||||
if (this._pendingEventList) {
|
||||
utils.removeElement(
|
||||
this._pendingEventList,
|
||||
function(ev) {
|
||||
return ev.getId() == oldEventId;
|
||||
}, false,
|
||||
);
|
||||
const idx = this._pendingEventList.findIndex(ev => ev.getId() === oldEventId);
|
||||
if (idx !== -1) {
|
||||
const [removedEvent] = this._pendingEventList.splice(idx, 1);
|
||||
if (removedEvent.isRedaction()) {
|
||||
this._revertRedactionLocalEcho(removedEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.removeEvent(oldEventId);
|
||||
}
|
||||
@@ -1289,6 +1374,23 @@ Room.prototype.updatePendingEvent = function(event, newStatus, newEventId) {
|
||||
this.emit("Room.localEchoUpdated", event, this, oldEventId, oldStatus);
|
||||
};
|
||||
|
||||
Room.prototype._revertRedactionLocalEcho = function(redactionEvent) {
|
||||
const redactId = redactionEvent.event.redacts;
|
||||
if (!redactId) {
|
||||
return;
|
||||
}
|
||||
const redactedEvent = this.getUnfilteredTimelineSet()
|
||||
.findEventById(redactId);
|
||||
if (redactedEvent) {
|
||||
redactedEvent.unmarkLocallyRedacted();
|
||||
// re-render after undoing redaction
|
||||
this.emit("Room.redactionCancelled", redactionEvent, this);
|
||||
// reapply relation now redaction failed
|
||||
if (redactedEvent.isRelation()) {
|
||||
this._aggregateNonLiveRelation(redactedEvent);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Add some events to this room. This can include state events, message
|
||||
@@ -1330,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]);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1367,6 +1474,9 @@ Room.prototype.removeEvent = function(eventId) {
|
||||
for (let i = 0; i < this._timelineSets.length; i++) {
|
||||
const removed = this._timelineSets[i].removeEvent(eventId);
|
||||
if (removed) {
|
||||
if (removed.isRedaction()) {
|
||||
this._revertRedactionLocalEcho(removed);
|
||||
}
|
||||
removedAny = true;
|
||||
}
|
||||
}
|
||||
@@ -1790,10 +1900,21 @@ module.exports = Room;
|
||||
* event).
|
||||
*
|
||||
* @event module:client~MatrixClient#"Room.redaction"
|
||||
* @param {MatrixEvent} event The matrix event which was redacted
|
||||
* @param {MatrixEvent} event The matrix redaction event
|
||||
* @param {Room} room The room containing the redacted event
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fires when an event that was previously redacted isn't anymore.
|
||||
* This happens when the redaction couldn't be sent and
|
||||
* was subsequently cancelled by the user. Redactions have a local echo
|
||||
* which is undone in this scenario.
|
||||
*
|
||||
* @event module:client~MatrixClient#"Room.redactionCancelled"
|
||||
* @param {MatrixEvent} event The matrix redaction event that was cancelled.
|
||||
* @param {Room} room The room containing the unredacted event
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fires whenever the name of a room is updated.
|
||||
* @event module:client~MatrixClient#"Room.name"
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -24,6 +24,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
import logger from '../src/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.
|
||||
@@ -39,7 +40,7 @@ let _realCallbackKey;
|
||||
// each is an object with keys [runAt, func, params, key].
|
||||
const _callbackList = [];
|
||||
|
||||
// var debuglog = console.log.bind(console);
|
||||
// var debuglog = logger.log.bind(logger);
|
||||
const debuglog = function() {};
|
||||
|
||||
/**
|
||||
@@ -170,7 +171,7 @@ function _runCallbacks() {
|
||||
try {
|
||||
cb.func.apply(global, cb.params);
|
||||
} catch (e) {
|
||||
console.error("Uncaught exception in callback function",
|
||||
logger.error("Uncaught exception in callback function",
|
||||
e.stack || e);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-3
@@ -21,6 +21,7 @@ limitations under the License.
|
||||
*/
|
||||
const utils = require("./utils");
|
||||
import Promise from 'bluebird';
|
||||
import logger from '../src/logger';
|
||||
|
||||
const DEBUG = false; // set true to enable console logging.
|
||||
|
||||
@@ -176,7 +177,8 @@ MatrixScheduler.RETRY_BACKOFF_RATELIMIT = function(event, attempts, err) {
|
||||
* @see module:scheduler~queueAlgorithm
|
||||
*/
|
||||
MatrixScheduler.QUEUE_MESSAGES = function(event) {
|
||||
if (event.getType() === "m.room.message") {
|
||||
// enqueue messages or events that associate with another event (redactions and relations)
|
||||
if (event.getType() === "m.room.message" || event.hasAssocation()) {
|
||||
// put these events in the 'message' queue.
|
||||
return "message";
|
||||
}
|
||||
@@ -219,7 +221,14 @@ function _processQueue(scheduler, queueName) {
|
||||
);
|
||||
// fire the process function and if it resolves, resolve the deferred. Else
|
||||
// invoke the retry algorithm.
|
||||
scheduler._procFn(obj.event).done(function(res) {
|
||||
|
||||
// First wait for a resolved promise, so the resolve handlers for
|
||||
// the deferred of the previously sent event can run.
|
||||
// This way enqueued relations/redactions to enqueued events can receive
|
||||
// the remove id of their target before being sent.
|
||||
Promise.resolve().then(() => {
|
||||
return scheduler._procFn(obj.event);
|
||||
}).then(function(res) {
|
||||
// remove this from the queue
|
||||
_removeNextEvent(scheduler, queueName);
|
||||
debuglog("Queue '%s' sent event %s", queueName, obj.event.getId());
|
||||
@@ -269,7 +278,7 @@ function _removeNextEvent(scheduler, queueName) {
|
||||
|
||||
function debuglog() {
|
||||
if (DEBUG) {
|
||||
console.log(...arguments);
|
||||
logger.log(...arguments);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
});
|
||||
@@ -19,6 +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';
|
||||
|
||||
const VERSION = 3;
|
||||
|
||||
@@ -146,7 +147,7 @@ LocalIndexedDBStoreBackend.prototype = {
|
||||
*/
|
||||
connect: function() {
|
||||
if (!this._disconnected) {
|
||||
console.log(
|
||||
logger.log(
|
||||
`LocalIndexedDBStoreBackend.connect: already connected or connecting`,
|
||||
);
|
||||
return Promise.resolve();
|
||||
@@ -154,14 +155,14 @@ LocalIndexedDBStoreBackend.prototype = {
|
||||
|
||||
this._disconnected = false;
|
||||
|
||||
console.log(
|
||||
logger.log(
|
||||
`LocalIndexedDBStoreBackend.connect: connecting...`,
|
||||
);
|
||||
const req = this.indexedDB.open(this._dbName, VERSION);
|
||||
req.onupgradeneeded = (ev) => {
|
||||
const db = ev.target.result;
|
||||
const oldVersion = ev.oldVersion;
|
||||
console.log(
|
||||
logger.log(
|
||||
`LocalIndexedDBStoreBackend.connect: upgrading from ${oldVersion}`,
|
||||
);
|
||||
if (oldVersion < 1) { // The database did not previously exist.
|
||||
@@ -178,16 +179,16 @@ LocalIndexedDBStoreBackend.prototype = {
|
||||
};
|
||||
|
||||
req.onblocked = () => {
|
||||
console.log(
|
||||
logger.log(
|
||||
`can't yet open LocalIndexedDBStoreBackend because it is open elsewhere`,
|
||||
);
|
||||
};
|
||||
|
||||
console.log(
|
||||
logger.log(
|
||||
`LocalIndexedDBStoreBackend.connect: awaiting connection...`,
|
||||
);
|
||||
return reqAsEventPromise(req).then((ev) => {
|
||||
console.log(
|
||||
logger.log(
|
||||
`LocalIndexedDBStoreBackend.connect: connected`,
|
||||
);
|
||||
this.db = ev.target.result;
|
||||
@@ -215,7 +216,7 @@ LocalIndexedDBStoreBackend.prototype = {
|
||||
this._loadAccountData(),
|
||||
this._loadSyncData(),
|
||||
]).then(([accountData, syncData]) => {
|
||||
console.log(
|
||||
logger.log(
|
||||
`LocalIndexedDBStoreBackend: loaded initial data`,
|
||||
);
|
||||
this._syncAccumulator.accumulate({
|
||||
@@ -273,7 +274,7 @@ LocalIndexedDBStoreBackend.prototype = {
|
||||
reject(err);
|
||||
};
|
||||
}).then((events) => {
|
||||
console.log(`LL: got ${events && events.length}` +
|
||||
logger.log(`LL: got ${events && events.length}` +
|
||||
` membershipEvents from storage for room ${roomId} ...`);
|
||||
return events;
|
||||
});
|
||||
@@ -287,7 +288,7 @@ LocalIndexedDBStoreBackend.prototype = {
|
||||
* @param {event[]} membershipEvents the membership events to store
|
||||
*/
|
||||
setOutOfBandMembers: async function(roomId, membershipEvents) {
|
||||
console.log(`LL: backend about to store ${membershipEvents.length}` +
|
||||
logger.log(`LL: backend about to store ${membershipEvents.length}` +
|
||||
` members for ${roomId}`);
|
||||
const tx = this.db.transaction(["oob_membership_events"], "readwrite");
|
||||
const store = tx.objectStore("oob_membership_events");
|
||||
@@ -306,7 +307,7 @@ LocalIndexedDBStoreBackend.prototype = {
|
||||
};
|
||||
store.put(markerObject);
|
||||
await txnAsPromise(tx);
|
||||
console.log(`LL: backend done storing for ${roomId}!`);
|
||||
logger.log(`LL: backend done storing for ${roomId}!`);
|
||||
},
|
||||
|
||||
clearOutOfBandMembers: async function(roomId) {
|
||||
@@ -341,7 +342,7 @@ LocalIndexedDBStoreBackend.prototype = {
|
||||
[roomId, maxStateKey],
|
||||
);
|
||||
|
||||
console.log(`LL: Deleting all users + marker in storage for ` +
|
||||
logger.log(`LL: Deleting all users + marker in storage for ` +
|
||||
`room ${roomId}, with key range:`,
|
||||
[roomId, minStateKey], [roomId, maxStateKey]);
|
||||
await reqAsPromise(writeStore.delete(membersKeyRange));
|
||||
@@ -354,11 +355,11 @@ LocalIndexedDBStoreBackend.prototype = {
|
||||
*/
|
||||
clearDatabase: function() {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log(`Removing indexeddb instance: ${this._dbName}`);
|
||||
logger.log(`Removing indexeddb instance: ${this._dbName}`);
|
||||
const req = this.indexedDB.deleteDatabase(this._dbName);
|
||||
|
||||
req.onblocked = () => {
|
||||
console.log(
|
||||
logger.log(
|
||||
`can't yet delete indexeddb ${this._dbName}` +
|
||||
` because it is open elsewhere`,
|
||||
);
|
||||
@@ -368,14 +369,14 @@ LocalIndexedDBStoreBackend.prototype = {
|
||||
// in firefox, with indexedDB disabled, this fails with a
|
||||
// DOMError. We treat this as non-fatal, so that we can still
|
||||
// use the app.
|
||||
console.warn(
|
||||
logger.warn(
|
||||
`unable to delete js-sdk store indexeddb: ${ev.target.error}`,
|
||||
);
|
||||
resolve();
|
||||
};
|
||||
|
||||
req.onsuccess = () => {
|
||||
console.log(`Removed indexeddb instance: ${this._dbName}`);
|
||||
logger.log(`Removed indexeddb instance: ${this._dbName}`);
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
@@ -434,7 +435,7 @@ LocalIndexedDBStoreBackend.prototype = {
|
||||
* @return {Promise} Resolves if the data was persisted.
|
||||
*/
|
||||
_persistSyncData: function(nextBatch, roomsData, groupsData) {
|
||||
console.log("Persisting sync data up to ", nextBatch);
|
||||
logger.log("Persisting sync data up to ", nextBatch);
|
||||
return Promise.try(() => {
|
||||
const txn = this.db.transaction(["sync"], "readwrite");
|
||||
const store = txn.objectStore("sync");
|
||||
@@ -508,7 +509,7 @@ LocalIndexedDBStoreBackend.prototype = {
|
||||
* @return {Promise<Object[]>} A list of raw global account events.
|
||||
*/
|
||||
_loadAccountData: function() {
|
||||
console.log(
|
||||
logger.log(
|
||||
`LocalIndexedDBStoreBackend: loading account data...`,
|
||||
);
|
||||
return Promise.try(() => {
|
||||
@@ -517,7 +518,7 @@ LocalIndexedDBStoreBackend.prototype = {
|
||||
return selectQuery(store, undefined, (cursor) => {
|
||||
return cursor.value;
|
||||
}).then((result) => {
|
||||
console.log(
|
||||
logger.log(
|
||||
`LocalIndexedDBStoreBackend: loaded account data`,
|
||||
);
|
||||
return result;
|
||||
@@ -530,7 +531,7 @@ LocalIndexedDBStoreBackend.prototype = {
|
||||
* @return {Promise<Object>} An object with "roomsData" and "nextBatch" keys.
|
||||
*/
|
||||
_loadSyncData: function() {
|
||||
console.log(
|
||||
logger.log(
|
||||
`LocalIndexedDBStoreBackend: loading sync data...`,
|
||||
);
|
||||
return Promise.try(() => {
|
||||
@@ -539,11 +540,11 @@ LocalIndexedDBStoreBackend.prototype = {
|
||||
return selectQuery(store, undefined, (cursor) => {
|
||||
return cursor.value;
|
||||
}).then((results) => {
|
||||
console.log(
|
||||
logger.log(
|
||||
`LocalIndexedDBStoreBackend: loaded sync data`,
|
||||
);
|
||||
if (results.length > 1) {
|
||||
console.warn("loadSyncData: More than 1 sync row found.");
|
||||
logger.warn("loadSyncData: More than 1 sync row found.");
|
||||
}
|
||||
return (results.length > 0 ? results[0] : {});
|
||||
});
|
||||
|
||||
@@ -16,6 +16,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import Promise from 'bluebird';
|
||||
import logger from '../../src/logger';
|
||||
|
||||
/**
|
||||
* An IndexedDB store backend where the actual backend sits in a web
|
||||
@@ -140,7 +141,7 @@ RemoteIndexedDBStoreBackend.prototype = {
|
||||
|
||||
// tell the worker the db name.
|
||||
this._startPromise = this._doCmd('_setupWorker', [this._dbName]).then(() => {
|
||||
console.log("IndexedDB worker is ready");
|
||||
logger.log("IndexedDB worker is ready");
|
||||
});
|
||||
}
|
||||
return this._startPromise;
|
||||
@@ -170,13 +171,13 @@ RemoteIndexedDBStoreBackend.prototype = {
|
||||
|
||||
if (msg.command == 'cmd_success' || msg.command == 'cmd_fail') {
|
||||
if (msg.seq === undefined) {
|
||||
console.error("Got reply from worker with no seq");
|
||||
logger.error("Got reply from worker with no seq");
|
||||
return;
|
||||
}
|
||||
|
||||
const def = this._inFlight[msg.seq];
|
||||
if (def === undefined) {
|
||||
console.error("Got reply for unknown seq " + msg.seq);
|
||||
logger.error("Got reply for unknown seq " + msg.seq);
|
||||
return;
|
||||
}
|
||||
delete this._inFlight[msg.seq];
|
||||
@@ -189,7 +190,7 @@ RemoteIndexedDBStoreBackend.prototype = {
|
||||
def.reject(error);
|
||||
}
|
||||
} else {
|
||||
console.warn("Unrecognised message from worker: " + msg);
|
||||
logger.warn("Unrecognised message from worker: " + msg);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
|
||||
import Promise from 'bluebird';
|
||||
import LocalIndexedDBStoreBackend from "./indexeddb-local-backend.js";
|
||||
import logger from '../../src/logger';
|
||||
|
||||
/**
|
||||
* This class lives in the webworker and drives a LocalIndexedDBStoreBackend
|
||||
@@ -129,8 +130,8 @@ class IndexedDBStoreWorker {
|
||||
result: ret,
|
||||
});
|
||||
}, (err) => {
|
||||
console.error("Error running command: "+msg.command);
|
||||
console.error(err);
|
||||
logger.error("Error running command: "+msg.command);
|
||||
logger.error(err);
|
||||
this.postMessage.call(null, {
|
||||
command: 'cmd_fail',
|
||||
seq: msg.seq,
|
||||
|
||||
+15
-12
@@ -25,6 +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';
|
||||
|
||||
/**
|
||||
* This is an internal module. See {@link IndexedDBStore} for the public class.
|
||||
@@ -124,16 +125,16 @@ IndexedDBStore.exists = function(indexedDB, dbName) {
|
||||
*/
|
||||
IndexedDBStore.prototype.startup = function() {
|
||||
if (this.startedUp) {
|
||||
console.log(`IndexedDBStore.startup: already started`);
|
||||
logger.log(`IndexedDBStore.startup: already started`);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
console.log(`IndexedDBStore.startup: connecting to backend`);
|
||||
logger.log(`IndexedDBStore.startup: connecting to backend`);
|
||||
return this.backend.connect().then(() => {
|
||||
console.log(`IndexedDBStore.startup: loading presence events`);
|
||||
logger.log(`IndexedDBStore.startup: loading presence events`);
|
||||
return this.backend.getUserPresenceEvents();
|
||||
}).then((userPresenceEvents) => {
|
||||
console.log(`IndexedDBStore.startup: processing presence events`);
|
||||
logger.log(`IndexedDBStore.startup: processing presence events`);
|
||||
userPresenceEvents.forEach(([userId, rawEvent]) => {
|
||||
const u = new User(userId);
|
||||
if (rawEvent) {
|
||||
@@ -174,9 +175,9 @@ IndexedDBStore.prototype.getSavedSyncToken = degradable(function() {
|
||||
IndexedDBStore.prototype.deleteAllData = degradable(function() {
|
||||
MemoryStore.prototype.deleteAllData.call(this);
|
||||
return this.backend.clearDatabase().then(() => {
|
||||
console.log("Deleted indexeddb data.");
|
||||
logger.log("Deleted indexeddb data.");
|
||||
}, (err) => {
|
||||
console.error(`Failed to delete indexeddb data: ${err}`);
|
||||
logger.error(`Failed to delete indexeddb data: ${err}`);
|
||||
throw err;
|
||||
});
|
||||
});
|
||||
@@ -197,11 +198,13 @@ IndexedDBStore.prototype.wantsSave = function() {
|
||||
|
||||
/**
|
||||
* Possibly write data to the database.
|
||||
*
|
||||
* @param {bool} force True to force a save to happen
|
||||
* @return {Promise} Promise resolves after the write completes
|
||||
* (or immediately if no write is performed)
|
||||
*/
|
||||
IndexedDBStore.prototype.save = function() {
|
||||
if (this.wantsSave()) {
|
||||
IndexedDBStore.prototype.save = function(force) {
|
||||
if (force || this.wantsSave()) {
|
||||
return this._reallySave();
|
||||
}
|
||||
return Promise.resolve();
|
||||
@@ -290,18 +293,18 @@ function degradable(func, fallback) {
|
||||
try {
|
||||
return await func.call(this, ...args);
|
||||
} catch (e) {
|
||||
console.error("IndexedDBStore failure, degrading to MemoryStore", e);
|
||||
logger.error("IndexedDBStore failure, degrading to MemoryStore", e);
|
||||
this.emit("degraded", e);
|
||||
try {
|
||||
// We try to delete IndexedDB after degrading since this store is only a
|
||||
// cache (the app will still function correctly without the data).
|
||||
// It's possible that deleting repair IndexedDB for the next app load,
|
||||
// potenially by making a little more space available.
|
||||
console.log("IndexedDBStore trying to delete degraded data");
|
||||
logger.log("IndexedDBStore trying to delete degraded data");
|
||||
await this.backend.clearDatabase();
|
||||
console.log("IndexedDBStore delete after degrading succeeeded");
|
||||
logger.log("IndexedDBStore delete after degrading succeeeded");
|
||||
} catch (e) {
|
||||
console.warn("IndexedDBStore delete after degrading failed", e);
|
||||
logger.warn("IndexedDBStore delete after degrading failed", e);
|
||||
}
|
||||
// Degrade the store from being an instance of `IndexedDBStore` to instead be
|
||||
// an instance of `MemoryStore` so that future API calls use the memory path
|
||||
|
||||
+3
-1
@@ -335,8 +335,10 @@ module.exports.MemoryStore.prototype = {
|
||||
|
||||
/**
|
||||
* Save does nothing as there is no backing data store.
|
||||
* @param {bool} force True to force a save (but the memory
|
||||
* store still can't save anything)
|
||||
*/
|
||||
save: function() {},
|
||||
save: function(force) {},
|
||||
|
||||
/**
|
||||
* Startup does nothing as this store doesn't require starting up.
|
||||
|
||||
@@ -22,6 +22,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
const utils = require("../../utils");
|
||||
import logger from '../../logger';
|
||||
|
||||
const DEBUG = false; // set true to enable console logging.
|
||||
const E2E_PREFIX = "session.e2e.";
|
||||
@@ -257,7 +258,7 @@ function removeByPrefix(store, prefix) {
|
||||
|
||||
function debuglog() {
|
||||
if (DEBUG) {
|
||||
console.log(...arguments);
|
||||
logger.log(...arguments);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import utils from "./utils";
|
||||
import logger from '../src/logger';
|
||||
|
||||
|
||||
/**
|
||||
@@ -168,7 +169,7 @@ class SyncAccumulator {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.error("Unknown cateogory: ", category);
|
||||
logger.error("Unknown cateogory: ", category);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+51
-22
@@ -32,6 +32,8 @@ const Group = require('./models/group');
|
||||
const utils = require("./utils");
|
||||
const Filter = require("./filter");
|
||||
const EventTimeline = require("./models/event-timeline");
|
||||
const PushProcessor = require("./pushprocessor");
|
||||
import logger from '../src/logger';
|
||||
|
||||
import {InvalidStoreError} from './errors';
|
||||
|
||||
@@ -58,7 +60,7 @@ function debuglog(...params) {
|
||||
if (!DEBUG) {
|
||||
return;
|
||||
}
|
||||
console.log(...params);
|
||||
logger.log(...params);
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +128,9 @@ SyncApi.prototype.createRoom = function(roomId) {
|
||||
timelineSupport,
|
||||
unstableClientRelationAggregation,
|
||||
});
|
||||
client.reEmitter.reEmit(room, ["Room.name", "Room.timeline", "Room.redaction",
|
||||
client.reEmitter.reEmit(room, ["Room.name", "Room.timeline",
|
||||
"Room.redaction",
|
||||
"Room.redactionCancelled",
|
||||
"Room.receipt", "Room.tags",
|
||||
"Room.timelineReset",
|
||||
"Room.localEchoUpdated",
|
||||
@@ -392,7 +396,7 @@ SyncApi.prototype._peekPoll = function(peekRoom, token) {
|
||||
peekRoom.addLiveEvents(events);
|
||||
self._peekPoll(peekRoom, res.end);
|
||||
}, function(err) {
|
||||
console.error("[%s] Peek poll failed: %s", peekRoom.roomId, err);
|
||||
logger.error("[%s] Peek poll failed: %s", peekRoom.roomId, err);
|
||||
setTimeout(function() {
|
||||
self._peekPoll(peekRoom, token);
|
||||
}, 30 * 1000);
|
||||
@@ -454,7 +458,7 @@ SyncApi.prototype._wasLazyLoadingToggled = async function(lazyLoadMembers) {
|
||||
SyncApi.prototype._shouldAbortSync = function(error) {
|
||||
if (error.errcode === "M_UNKNOWN_TOKEN") {
|
||||
// The logout already happened, we just need to stop.
|
||||
console.warn("Token no longer valid - assuming logout");
|
||||
logger.warn("Token no longer valid - assuming logout");
|
||||
this.stop();
|
||||
return true;
|
||||
}
|
||||
@@ -494,7 +498,7 @@ SyncApi.prototype.sync = function() {
|
||||
|
||||
client.pushRules = result;
|
||||
} catch (err) {
|
||||
console.error("Getting push rules failed", err);
|
||||
logger.error("Getting push rules failed", err);
|
||||
if (self._shouldAbortSync(err)) return;
|
||||
// wait for saved sync to complete before doing anything else,
|
||||
// otherwise the sync state will end up being incorrect
|
||||
@@ -522,7 +526,7 @@ SyncApi.prototype.sync = function() {
|
||||
);
|
||||
debuglog("Created and stored lazy load sync filter");
|
||||
} catch (err) {
|
||||
console.error(
|
||||
logger.error(
|
||||
"Creating and storing lazy load sync filter failed",
|
||||
err,
|
||||
);
|
||||
@@ -546,7 +550,7 @@ SyncApi.prototype.sync = function() {
|
||||
// we leave the state as 'ERROR' which isn't great since this normally means
|
||||
// we're retrying. The client must be stopped before clearing the stores anyway
|
||||
// so the app should stop the client, clear the store and start it again.
|
||||
console.warn("InvalidStoreError: store is not usable: stopping sync.");
|
||||
logger.warn("InvalidStoreError: store is not usable: stopping sync.");
|
||||
return;
|
||||
}
|
||||
if (this.opts.lazyLoadMembers && this.opts.crypto) {
|
||||
@@ -557,7 +561,7 @@ SyncApi.prototype.sync = function() {
|
||||
await this.client._storeClientOptions();
|
||||
debuglog("Stored client options");
|
||||
} catch (err) {
|
||||
console.error("Storing client options failed", err);
|
||||
logger.error("Storing client options failed", err);
|
||||
throw err;
|
||||
}
|
||||
|
||||
@@ -580,7 +584,7 @@ SyncApi.prototype.sync = function() {
|
||||
getFilterName(client.credentials.userId), filter,
|
||||
);
|
||||
} catch (err) {
|
||||
console.error("Getting filter failed", err);
|
||||
logger.error("Getting filter failed", err);
|
||||
if (self._shouldAbortSync(err)) return;
|
||||
// wait for saved sync to complete before doing anything else,
|
||||
// otherwise the sync state will end up being incorrect
|
||||
@@ -627,7 +631,7 @@ SyncApi.prototype.sync = function() {
|
||||
return self._syncFromCache(savedSync);
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error("Getting saved sync failed", err);
|
||||
logger.error("Getting saved sync failed", err);
|
||||
});
|
||||
// Now start the first incremental sync request: this can also
|
||||
// take a while so if we set it going now, we can wait for it
|
||||
@@ -699,7 +703,7 @@ SyncApi.prototype._syncFromCache = async function(savedSync) {
|
||||
try {
|
||||
await this._processSyncResponse(syncEventData, data);
|
||||
} catch(e) {
|
||||
console.error("Error processing cached sync", e.stack || e);
|
||||
logger.error("Error processing cached sync", e.stack || e);
|
||||
}
|
||||
|
||||
// Don't emit a prepared if we've bailed because the store is invalid:
|
||||
@@ -774,7 +778,7 @@ SyncApi.prototype._sync = async function(syncOptions) {
|
||||
} catch(e) {
|
||||
// log the exception with stack if we have it, else fall back
|
||||
// to the plain description
|
||||
console.error("Caught /sync error", e.stack || e);
|
||||
logger.error("Caught /sync error", e.stack || e);
|
||||
|
||||
// Emit the exception for client handling
|
||||
this.client.emit("sync.unexpectedError", e);
|
||||
@@ -888,15 +892,15 @@ SyncApi.prototype._onSyncError = function(err, syncOptions) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.error("/sync error %s", err);
|
||||
console.error(err);
|
||||
logger.error("/sync error %s", err);
|
||||
logger.error(err);
|
||||
|
||||
if(this._shouldAbortSync(err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._failedSyncCount++;
|
||||
console.log('Number of consecutive failed sync requests:', this._failedSyncCount);
|
||||
logger.log('Number of consecutive failed sync requests:', this._failedSyncCount);
|
||||
|
||||
debuglog("Starting keep-alive");
|
||||
// Note that we do *not* mark the sync connection as
|
||||
@@ -1027,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;
|
||||
@@ -1040,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();
|
||||
@@ -1050,13 +1073,21 @@ SyncApi.prototype._processSyncResponse = async function(
|
||||
content.msgtype == "m.bad.encrypted"
|
||||
) {
|
||||
// the mapper already logged a warning.
|
||||
console.log(
|
||||
logger.log(
|
||||
'Ignoring undecryptable to-device event from ' +
|
||||
toDeviceEvent.getSender(),
|
||||
);
|
||||
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);
|
||||
},
|
||||
);
|
||||
@@ -1216,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);
|
||||
|
||||
@@ -19,6 +19,7 @@ limitations under the License.
|
||||
|
||||
import Promise from 'bluebird';
|
||||
const EventTimeline = require("./models/event-timeline");
|
||||
import logger from '../src/logger';
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -28,7 +29,7 @@ const DEBUG = false;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
const debuglog = DEBUG ? console.log.bind(console) : function() {};
|
||||
const debuglog = DEBUG ? logger.log.bind(logger) : function() {};
|
||||
|
||||
/**
|
||||
* the number of times we ask the server for more events before giving up
|
||||
|
||||
+11
-10
@@ -21,6 +21,7 @@ limitations under the License.
|
||||
*/
|
||||
const utils = require("../utils");
|
||||
const EventEmitter = require("events").EventEmitter;
|
||||
import logger from '../../src/logger';
|
||||
const DEBUG = true; // set true to enable console logging.
|
||||
|
||||
// events: hangup, error(err), replaced(call), state(state, oldState)
|
||||
@@ -195,7 +196,7 @@ MatrixCall.prototype.placeScreenSharingCall =
|
||||
* @param {string} queueId Arbitrary ID to track the chain of promises to be used
|
||||
*/
|
||||
MatrixCall.prototype.playElement = function(element, queueId) {
|
||||
console.log("queuing play on " + queueId + " and element " + element);
|
||||
logger.log("queuing play on " + queueId + " and element " + element);
|
||||
// XXX: FIXME: Does this leak elements, given the old promises
|
||||
// may hang around and retain a reference to them?
|
||||
if (this.mediaPromises[queueId]) {
|
||||
@@ -206,10 +207,10 @@ MatrixCall.prototype.playElement = function(element, queueId) {
|
||||
// these failures may be non-fatal (as in the case of unmounts)
|
||||
this.mediaPromises[queueId] =
|
||||
this.mediaPromises[queueId].then(function() {
|
||||
console.log("previous promise completed for " + queueId);
|
||||
logger.log("previous promise completed for " + queueId);
|
||||
return element.play();
|
||||
}, function() {
|
||||
console.log("previous promise failed for " + queueId);
|
||||
logger.log("previous promise failed for " + queueId);
|
||||
return element.play();
|
||||
});
|
||||
} else {
|
||||
@@ -224,14 +225,14 @@ MatrixCall.prototype.playElement = function(element, queueId) {
|
||||
* @param {string} queueId Arbitrary ID to track the chain of promises to be used
|
||||
*/
|
||||
MatrixCall.prototype.pauseElement = function(element, queueId) {
|
||||
console.log("queuing pause on " + queueId + " and element " + element);
|
||||
logger.log("queuing pause on " + queueId + " and element " + element);
|
||||
if (this.mediaPromises[queueId]) {
|
||||
this.mediaPromises[queueId] =
|
||||
this.mediaPromises[queueId].then(function() {
|
||||
console.log("previous promise completed for " + queueId);
|
||||
logger.log("previous promise completed for " + queueId);
|
||||
return element.pause();
|
||||
}, function() {
|
||||
console.log("previous promise failed for " + queueId);
|
||||
logger.log("previous promise failed for " + queueId);
|
||||
return element.pause();
|
||||
});
|
||||
} else {
|
||||
@@ -250,15 +251,15 @@ MatrixCall.prototype.pauseElement = function(element, queueId) {
|
||||
* @param {string} queueId Arbitrary ID to track the chain of promises to be used
|
||||
*/
|
||||
MatrixCall.prototype.assignElement = function(element, srcObject, queueId) {
|
||||
console.log("queuing assign on " + queueId + " element " + element + " for " +
|
||||
logger.log("queuing assign on " + queueId + " element " + element + " for " +
|
||||
srcObject);
|
||||
if (this.mediaPromises[queueId]) {
|
||||
this.mediaPromises[queueId] =
|
||||
this.mediaPromises[queueId].then(function() {
|
||||
console.log("previous promise completed for " + queueId);
|
||||
logger.log("previous promise completed for " + queueId);
|
||||
element.srcObject = srcObject;
|
||||
}, function() {
|
||||
console.log("previous promise failed for " + queueId);
|
||||
logger.log("previous promise failed for " + queueId);
|
||||
element.srcObject = srcObject;
|
||||
});
|
||||
} else {
|
||||
@@ -1159,7 +1160,7 @@ const callError = function(code, msg) {
|
||||
|
||||
const debuglog = function() {
|
||||
if (DEBUG) {
|
||||
console.log(...arguments);
|
||||
logger.log(...arguments);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
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.5.0":
|
||||
version "7.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.5.0.tgz#f20e4b7a91750ee8b63656073d843d2a736dca4a"
|
||||
integrity sha512-1TTVrt7J9rcG5PMjvO7VEG3FrEoEJNHxumRq66GemPmzboLWtIjjcJgk8rokuAS7IiRSpgVSu5Vb9lc99iJkOA==
|
||||
dependencies:
|
||||
"@babel/types" "^7.4.4"
|
||||
"@babel/types" "^7.5.0"
|
||||
jsesc "^2.5.1"
|
||||
lodash "^4.17.11"
|
||||
source-map "^0.5.0"
|
||||
@@ -44,18 +44,23 @@
|
||||
"@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==
|
||||
version "7.4.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.5.tgz#04af8d5d5a2b044a2a1bffacc1e5e6673544e872"
|
||||
integrity sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==
|
||||
|
||||
"@babel/parser@^7.5.0":
|
||||
version "7.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.0.tgz#3e0713dff89ad6ae37faec3b29dcfc5c979770b7"
|
||||
integrity sha512-I5nW8AhGpOXGCCNYGc+p7ExQIBxRFnS2fd/d862bNOKvmoEPjYPcfIjsfdy0ujagYOIYPczKgD9l3FsgTkAzKA==
|
||||
|
||||
"@babel/template@^7.1.0":
|
||||
version "7.4.4"
|
||||
@@ -67,24 +72,24 @@
|
||||
"@babel/types" "^7.4.4"
|
||||
|
||||
"@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.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.5.0.tgz#4216d6586854ef5c3c4592dab56ec7eb78485485"
|
||||
integrity sha512-SnA9aLbyOCcnnbQEGwdfBggnc142h/rbqqsXcaATj2hZcegCl903pUD/lfpsNBlBSuWow/YDfRyJuWi2EPR5cg==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.0.0"
|
||||
"@babel/generator" "^7.4.4"
|
||||
"@babel/generator" "^7.5.0"
|
||||
"@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.5.0"
|
||||
"@babel/types" "^7.5.0"
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
lodash "^4.17.11"
|
||||
|
||||
"@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.5.0":
|
||||
version "7.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.0.tgz#e47d43840c2e7f9105bc4d3a2c371b4d0c7832ab"
|
||||
integrity sha512-UFpDVqRABKsW01bvw7/wSUe56uy6RXM5+VJibVVAybDGxEW25jdwiFJEf7ASvSaC7sN7rbE/l3cLp2izav+CtQ==
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
lodash "^4.17.11"
|
||||
@@ -128,29 +133,29 @@ acorn-jsx@^5.0.0:
|
||||
integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==
|
||||
|
||||
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.7.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.7.0.tgz#aac6a559d27af6176b076ab6fb13c5974c213e3b"
|
||||
integrity sha512-XhahLSsCB6X6CJbe+uNu3Mn9sJBNFxtBN9NLgAOQovfS6Kh0lDUtmlclhjn9CvEK7A7YyRU13PXlNcpSiLI9Yw==
|
||||
dependencies:
|
||||
acorn "^6.0.2"
|
||||
acorn "^6.1.1"
|
||||
acorn-dynamic-import "^4.0.0"
|
||||
acorn-walk "^6.1.0"
|
||||
acorn-walk "^6.1.1"
|
||||
xtend "^4.0.1"
|
||||
|
||||
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@^6.1.1:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
|
||||
integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
|
||||
|
||||
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, acorn@^6.1.1:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.0.tgz#67f0da2fc339d6cfb5d6fb244fd449f33cd8bbe3"
|
||||
integrity sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==
|
||||
|
||||
ajv@^6.5.5, ajv@^6.9.1:
|
||||
version "6.10.0"
|
||||
@@ -314,10 +319,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,9 +423,9 @@ 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.2"
|
||||
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.2.tgz#182d5ac204579ff0881684b040560fdcc1558456"
|
||||
integrity sha512-UdsurWPtgiPgpJ06ryUnuaSXC2s0WoSZnQmEpbAH65XZSdwowgN5MvyP7e88nW07FYXv72erVtpBkxyDVKhH1Q==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.0.0"
|
||||
"@babel/parser" "^7.0.0"
|
||||
@@ -894,9 +900,9 @@ 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.6"
|
||||
resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.6.tgz#de047ec95f5f7b99ae63d830a2a894c96538b2cd"
|
||||
integrity sha512-4PaF8u2+AlViJxRVjurkLTxpp7CaFRD/jo5rPT9ONnKxyhQ8f59yzamEvq7EkriG56yn5On4ONyaG75HLqr46w==
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
@@ -931,9 +937,9 @@ binary-extensions@^1.0.0:
|
||||
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==
|
||||
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"
|
||||
@@ -1176,7 +1182,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==
|
||||
@@ -1240,9 +1246,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.6"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.6.tgz#b6cad653a929e244ce8a834244164d241fa954c5"
|
||||
integrity sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==
|
||||
dependencies:
|
||||
anymatch "^2.0.0"
|
||||
async-each "^1.0.1"
|
||||
@@ -1259,9 +1265,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.2"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6"
|
||||
integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==
|
||||
|
||||
cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
|
||||
version "1.0.4"
|
||||
@@ -1329,9 +1335,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"
|
||||
|
||||
@@ -1405,9 +1411,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"
|
||||
@@ -1504,6 +1510,13 @@ debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
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@^4.0.1, debug@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
|
||||
@@ -1677,9 +1690,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.0"
|
||||
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.0.tgz#2b8ed4c891b7de3200e14412a5b8248c7af505ca"
|
||||
integrity sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==
|
||||
dependencies:
|
||||
bn.js "^4.4.0"
|
||||
brorand "^1.0.1"
|
||||
@@ -2109,9 +2122,9 @@ flat-cache@^2.0.1:
|
||||
write "1.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"
|
||||
@@ -2147,9 +2160,9 @@ 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.6"
|
||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07"
|
||||
integrity sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==
|
||||
dependencies:
|
||||
minipass "^2.2.1"
|
||||
|
||||
@@ -2259,9 +2272,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"
|
||||
@@ -2290,9 +2303,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.0"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b"
|
||||
integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==
|
||||
|
||||
growl@1.10.5:
|
||||
version "1.10.5"
|
||||
@@ -2477,9 +2490,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"
|
||||
@@ -2497,16 +2510,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"
|
||||
@@ -2520,9 +2538,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.4.1"
|
||||
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.4.1.tgz#7bd9e5ab0567cd23b41b0180b68e0cfa82fc3c0b"
|
||||
integrity sha512-/Jw+qPZx4EDYsaT6uz7F4GJRNFMRdKNeUZw3ZnKV8lyuUgz/YWRCSUAJMZSVhSq4Ec0R2oYnyi6b3d4JXcL5Nw==
|
||||
dependencies:
|
||||
ansi-escapes "^3.2.0"
|
||||
chalk "^2.4.2"
|
||||
@@ -2766,7 +2784,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==
|
||||
@@ -2827,11 +2845,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"
|
||||
@@ -3023,12 +3036,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:
|
||||
@@ -3052,9 +3064,9 @@ lodash.memoize@~3.0.3:
|
||||
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==
|
||||
version "4.17.14"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba"
|
||||
integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==
|
||||
|
||||
loglevel@1.6.1:
|
||||
version "1.6.1"
|
||||
@@ -3091,9 +3103,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"
|
||||
@@ -3107,9 +3119,9 @@ markdown-it@^8.4.2:
|
||||
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==
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/marked/-/marked-0.6.3.tgz#79babad78af638ba4d522a9e715cdfdd2429e946"
|
||||
integrity sha512-Fqa7eq+UaxfMriqzYLayfqAE40WN03jf+zHjT18/uXNuzjq3TY0XTbrAoPeqSJrAmPz11VuUA+kBPYOhHt9oOQ==
|
||||
|
||||
math-random@^1.0.1:
|
||||
version "1.0.4"
|
||||
@@ -3238,7 +3250,7 @@ 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:
|
||||
minipass@^2.2.1, minipass@^2.3.5:
|
||||
version "2.3.5"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848"
|
||||
integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==
|
||||
@@ -3246,7 +3258,7 @@ minipass@^2.2.1, minipass@^2.3.4:
|
||||
safe-buffer "^5.1.2"
|
||||
yallist "^3.0.0"
|
||||
|
||||
minizlib@^1.1.1:
|
||||
minizlib@^1.2.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==
|
||||
@@ -3254,9 +3266,9 @@ minizlib@^1.1.1:
|
||||
minipass "^2.2.1"
|
||||
|
||||
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"
|
||||
@@ -3296,13 +3308,13 @@ mocha@^5.2.0:
|
||||
supports-color "5.4.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"
|
||||
@@ -3337,9 +3349,9 @@ ms@2.0.0:
|
||||
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
||||
|
||||
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==
|
||||
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"
|
||||
@@ -3347,9 +3359,9 @@ mute-stream@0.0.7:
|
||||
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"
|
||||
@@ -3379,18 +3391,18 @@ nave@~0.5.1:
|
||||
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"
|
||||
@@ -3446,9 +3458,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"
|
||||
@@ -3473,7 +3485,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=
|
||||
@@ -3734,9 +3746,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"
|
||||
@@ -3749,9 +3761,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.2.0"
|
||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.2.0.tgz#df12b5b1b3a30f51c329eacbdef98f3a6e136dc6"
|
||||
integrity sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA==
|
||||
|
||||
public-encrypt@^4.0.0:
|
||||
version "4.0.3"
|
||||
@@ -4036,9 +4048,9 @@ resolve@1.1.7, resolve@1.1.x:
|
||||
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==
|
||||
version "1.11.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e"
|
||||
integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==
|
||||
dependencies:
|
||||
path-parse "^1.0.6"
|
||||
|
||||
@@ -4083,9 +4095,9 @@ 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.2"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.2.tgz#2e35ce815cd46d84d02a209fb4e5921e051dbec7"
|
||||
integrity sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
@@ -4121,20 +4133,10 @@ set-blocking@~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"
|
||||
@@ -4359,9 +4361,9 @@ stream-http@^2.0.0:
|
||||
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"
|
||||
@@ -4483,9 +4485,9 @@ 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.1"
|
||||
resolved "https://registry.yarnpkg.com/table/-/table-5.4.1.tgz#0691ae2ebe8259858efb63e550b6d5f9300171e8"
|
||||
integrity sha512-E6CK1/pZe2N75rGZQotFOdmzWQ1AILtgYbMAbAjvms0S1l5IDB47zG3nCnFGB/w+7nB3vKofbLXCH7HPBo864w==
|
||||
dependencies:
|
||||
ajv "^6.9.1"
|
||||
lodash "^4.17.11"
|
||||
@@ -4498,17 +4500,17 @@ 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.10"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1"
|
||||
integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==
|
||||
dependencies:
|
||||
chownr "^1.1.1"
|
||||
fs-minipass "^1.2.5"
|
||||
minipass "^2.3.4"
|
||||
minizlib "^1.1.1"
|
||||
minipass "^2.3.5"
|
||||
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"
|
||||
@@ -4516,9 +4518,9 @@ ternary@~1.0.0:
|
||||
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==
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-4.0.2.tgz#580cea06c4932f46a48ed13804c93bc93c275968"
|
||||
integrity sha512-IWLuJqTvx97KP3uTYkFVn93cXO+EtlzJu8TdJylq+H0VBDlPMIfQA9MBS5Vc5t3xTEUG1q0hIfHMpAP2R+gWTw==
|
||||
dependencies:
|
||||
commander "^2.19.0"
|
||||
source-map "~0.6.1"
|
||||
@@ -4635,9 +4637,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"
|
||||
@@ -4674,9 +4676,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"
|
||||
@@ -4708,14 +4710,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"
|
||||
@@ -4876,7 +4878,7 @@ xtend@~2.1.1:
|
||||
dependencies:
|
||||
object-keys "~0.4.0"
|
||||
|
||||
yallist@^3.0.0, yallist@^3.0.2:
|
||||
yallist@^3.0.0, yallist@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9"
|
||||
integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==
|
||||
|
||||
Reference in New Issue
Block a user