Compare commits

..

110 Commits

Author SHA1 Message Date
David Baker 76c675cd09 v0.14.1 2018-11-22 16:46:26 +00:00
David Baker 85a4a594c5 Prepare changelog for v0.14.1 2018-11-22 16:46:25 +00:00
David Baker f70746c50f Handle crypto db version upgrades 2018-11-22 16:38:10 +00:00
David Baker ae85c209ab v0.14.0 2018-11-19 15:09:43 +00:00
David Baker 2306caa62f Prepare changelog for v0.14.0 2018-11-19 15:09:42 +00:00
David Baker 3222b11346 v0.14.0-rc.1 2018-11-15 15:06:39 +00:00
David Baker fc9d6a6d47 Prepare changelog for v0.14.0-rc.1 2018-11-15 15:06:39 +00:00
Bruno Windels b233ab87bb Merge branch 'master' into develop 2018-11-14 18:21:01 +01:00
Bruno Windels 73c3a709de Merge branch 'release-v0.13.1' 2018-11-14 18:19:24 +01:00
Bruno Windels 6ce7b30b72 v0.13.1 2018-11-14 18:18:12 +01:00
Bruno Windels 980d55a2f3 Prepare changelog for v0.13.1 2018-11-14 18:18:11 +01:00
Richard Lewis 988be62804 Add function to get currently joined room members. 2018-11-14 18:15:14 +01:00
Richard Lewis 23efd0850d Add function to get currently joined rooms. 2018-11-14 18:15:08 +01:00
Bruno Windels c6ea976d7f Merge branch 'master' into develop 2018-11-14 10:55:13 +01:00
Bruno Windels 5f24915300 Merge branch 'release-v0.13.0' 2018-11-14 10:54:52 +01:00
Bruno Windels fbe174fb64 v0.13.0 2018-11-14 10:53:42 +01:00
Richard Lewis 977d5331c0 Update CHANGELOG. 2018-11-14 10:50:05 +01:00
Richard Lewis d40d7e18f5 Update CHANGELOG. 2018-11-14 10:49:54 +01:00
Richard Lewis 11be68ad49 Refactor code to base 'login' method. 2018-11-14 10:49:44 +01:00
Richard Lewis b0d0782a72 Linting. 2018-11-14 10:49:36 +01:00
Richard Lewis dbb6d8ac71 Set access_token and user_id after login in with username and password. 2018-11-14 10:49:25 +01:00
David Baker 2774bd238b Merge pull request #781 from matrix-org/travis/block-send-if-failed
Prevent messages from being sent if other messages have failed to send
2018-11-09 10:54:38 +00:00
Travis Ralston fed67192bc Fix test: Actually resend the event after unknown devices are found
This test didn't actually test that resending would work, despite its name.
2018-11-08 17:17:30 -07:00
Travis Ralston 16db970558 Appease the linter 2018-11-08 16:51:21 -07:00
Travis Ralston c9a79bf32e Prevent messages from being sent if other messages have failed to send
Fixes https://github.com/vector-im/riot-web/issues/5408
2018-11-08 16:46:03 -07:00
David Baker eafba9c7ef Merge pull request #777 from matrix-org/dbkr/olm_unit_test
A unit test for olm
2018-11-06 12:04:55 +00:00
Richard Lewis 610923af89 Merge pull request #778 from matrix-org/rxl881/loginWithPassword
Set access_token and user_id after login in with username and password.
2018-11-05 17:25:31 +00:00
Richard Lewis 23dfeb13df Update CHANGELOG. 2018-11-05 17:17:22 +00:00
Richard Lewis f4abd7d027 Update CHANGELOG. 2018-11-05 17:06:39 +00:00
Richard Lewis b716e71784 Refactor code to base 'login' method. 2018-11-05 16:40:11 +00:00
Richard Lewis 094598196a Linting. 2018-11-05 16:02:30 +00:00
David Baker db1d1c49a0 Merge pull request #779 from matrix-org/rxl881/getRooms
Add function to get currently joined rooms.
2018-11-05 12:14:12 +00:00
David Baker ff4125c11e Remove unused stuff & comments 2018-11-05 09:39:46 +00:00
Richard Lewis a0d51803ed Add function to get currently joined room members. 2018-11-05 00:08:04 +00:00
Richard Lewis 3aabd63975 Add function to get currently joined rooms. 2018-11-04 21:49:17 +00:00
Richard Lewis 394e37f9ea Set access_token and user_id after login in with username and password. 2018-11-04 19:43:18 +00:00
Travis Ralston 369b88d6f8 Merge pull request #775 from matrix-org/travis/cleanup-request
Remove the request-only stuff we don't need anymore
2018-11-02 09:39:23 -06:00
David Baker ec8b3ae515 Lint (and also name the test right) 2018-11-02 12:33:46 +00:00
David Baker c94382b46c A unit test for olm
Megolm has plenty but none for just the olm layer by itself. I
was playing with getting session re-establishment to work and a
unit test came out.
2018-11-02 12:05:13 +00:00
Travis Ralston e89879d8a6 Remove the request-only stuff we don't need anymore
This was introduced in https://github.com/matrix-org/matrix-react-sdk/pull/2250 but can be pulled out due to https://github.com/matrix-org/matrix-js-sdk/pull/770. See https://github.com/vector-im/riot-web/issues/7634 for more information about the future.
2018-10-31 13:07:31 -06:00
Travis Ralston 62b2c07be2 Merge pull request #770 from matrix-org/travis/fix-request
Manually construct query strings for browser-request instances
2018-10-30 15:18:33 -06:00
Travis Ralston 2fb29ae8fd Use the right query string lib 2018-10-30 14:59:57 -06:00
Travis Ralston b57e858ad1 We can't use arrow functions, apparently. 2018-10-30 14:27:51 -06:00
Travis Ralston 054aac17aa Just use the interface provided to us rather than hack in a flag 2018-10-30 14:25:25 -06:00
Travis Ralston 68b65dd357 Because uglify-js breaks everything 2018-10-30 14:12:46 -06:00
Travis Ralston f2881126cd Manually construct query strings for browser-request instances
Because `request` just doesn't work for us in the browser, but `browser-request` is fine despite us having to do our own query strings.

Fixes https://github.com/vector-im/riot-web/issues/7620
2018-10-30 13:59:29 -06:00
Bruno Windels 11968a5888 Merge pull request #769 from matrix-org/bwindels/initcryptoll
Fix: correctly check for crypto being present
2018-10-30 16:13:32 +00:00
Bruno Windels ad279dc566 correctly check for crypto being present 2018-10-30 16:05:44 +01:00
David Baker 604af1ac8c Merge branch 'master' into develop 2018-10-29 14:01:26 +00:00
David Baker 68c6393eb2 v0.12.1 2018-10-29 13:59:39 +00:00
David Baker 4cbf9c7f47 Prepare changelog for v0.12.1 2018-10-29 13:59:39 +00:00
Travis Ralston 8bb3b75b1d Merge pull request #768 from aaronraimist/lint
Update babel-eslint to 8.1.1
2018-10-26 21:13:04 -06:00
Aaron Raimist a76f0c7cb4 Update babel-eslint to 8.1.1
Signed-off-by: Aaron Raimist <aaron@raim.ist>
2018-10-26 22:07:40 -05:00
Travis Ralston 01e31afcbd Merge pull request #764 from matrix-org/travis/permalink-routing
Support `request` in the browser and support supplying servers to try in joinRoom()
2018-10-26 14:22:51 -06:00
Travis Ralston 64b83b3245 Merge branch 'develop' into travis/permalink-routing 2018-10-26 09:20:54 -06:00
David Baker e69f7dbc5f Merge pull request #767 from matrix-org/dbkr/loglevel_dep
loglevel should be a normal dependency
2018-10-26 11:26:15 +01:00
David Baker 4d0f6df89a alphabetical order 2018-10-26 11:23:05 +01:00
David Baker 6b184363a1 loglevel should be a normal dependency
rather than a dev dependency
2018-10-26 11:16:20 +01:00
David Baker b519069634 Merge pull request #766 from matrix-org/dbkr/stop_devicelist
Stop devicelist when client is stopped
2018-10-26 11:14:36 +01:00
Travis Ralston 1bd44a7427 Merge remote-tracking branch 'origin/develop' into travis/permalink-routing 2018-10-25 14:36:46 -06:00
Travis Ralston 568ff5a3f5 Appease the linter 2018-10-25 14:36:14 -06:00
David Baker 88b39f4b67 Stop devicelist when client is stopped
To avoid the devicelist trying to save after the client has been
stopped

Hopefully will fix random test failures on node 11.
2018-10-25 19:00:03 +01:00
David Baker 870e96a1df Merge pull request #743 from matrix-org/dbkr/wasm
Update to WebAssembly-powered Olm
2018-10-25 15:58:18 +01:00
David Baker 59070c2af6 Merge remote-tracking branch 'origin/develop' into dbkr/wasm 2018-10-25 15:29:41 +01:00
David Baker cec8936728 Merge pull request #763 from Ryuno-Ki/logging-lib
Logging lib. Fixes #332
2018-10-25 15:28:47 +01:00
David Baker 14071b0d31 Merge pull request #765 from matrix-org/dbkr/mock_request_stop
Use new stop() method on matrix-mock-request
2018-10-25 15:16:08 +01:00
David Baker 57173e4385 Use mock-request 1.2.2 2018-10-25 15:01:05 +01:00
David Baker 997caad985 jsdoc 2018-10-25 14:43:17 +01:00
David Baker 2b752c0c02 Use new stop() method on matrix-mock-request
To finish all pending flushes between tests. This stops the unit
tests from hanging on node 11 when run in certain combinations.

Requires https://github.com/matrix-org/matrix-mock-request/pull/6
(so will need a release of matrix-mock-request before merging)
2018-10-25 14:29:25 +01:00
Travis Ralston 2cccb8b450 Install memfs because webpack is made of fail 2018-10-24 16:57:36 -06:00
Travis Ralston 0c540ac8de Re-add the querystring options 2018-10-24 16:36:12 -06:00
Travis Ralston 6033b7b886 Update request and browserify; Use request in the browser 2018-10-24 16:36:00 -06:00
Travis Ralston b67f8d1389 Merge branch 'develop' into travis/permalink-routing 2018-10-24 16:22:18 -06:00
André Jaenisch ae645ad9f0 Use Node.js module export, since ES6 export breaks build.
Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
2018-10-24 21:52:50 +02:00
André Jaenisch 5b72509dac Fix broken build.
Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
2018-10-24 21:12:51 +02:00
André Jaenisch 3ce42a096b Add Apache license banner.
Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
2018-10-24 21:06:04 +02:00
André Jaenisch 8331c2f267 Use ES6 export instead of CommonJS.
Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
2018-10-24 21:05:21 +02:00
André Jaenisch b3c9570b0f Remove 'use strict'.
Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
2018-10-24 20:56:29 +02:00
André Jaenisch 9d5c877df9 Set loglevel to DEBUG to remain current behaviour.
Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
2018-10-24 20:55:54 +02:00
André Jaenisch a8e2727473 Set level of logger instead of all of them.
Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
2018-10-24 20:55:22 +02:00
David Baker 4b9c6e6bd2 Merge remote-tracking branch 'origin/develop' into dbkr/wasm 2018-10-24 19:15:04 +01:00
David Baker d29ac088c0 retest 2018-10-24 18:55:04 +01:00
David Baker 3a316de9ef Update to Olm 3 here too 2018-10-24 17:40:58 +01:00
David Baker 84b91d4575 Update to Olm 3 2018-10-24 16:58:48 +01:00
David Baker f5832423f4 v0.12.1-rc.1 2018-10-24 11:14:59 +01:00
David Baker 73dd07aadf Prepare changelog for v0.12.1-rc.1 2018-10-24 11:14:59 +01:00
André Jaenisch 0f39a45734 Fixing module export of logger. Refs #332
Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
2018-10-24 01:44:10 +02:00
André Jaenisch f41060c39a Replace console.log with loglevel logger. Fixes #332
Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
2018-10-24 00:48:57 +02:00
André Jaenisch bbb8e12bac Create logger module. Refs #332
Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
2018-10-24 00:48:57 +02:00
André Jaenisch d0e1471c91 Added loglevel library. Refs #332
Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
2018-10-24 00:48:52 +02:00
Travis Ralston 47cb97bc60 Merge pull request #762 from aaronraimist/valid-package-json
Add repository type to package.json to make it valid
2018-10-20 21:55:48 -06:00
Aaron Raimist 8d35bea830 Add repository type to package.json to make it valid
Signed-off-by: Aaron Raimist <aaron@raim.ist>
2018-10-20 21:38:04 -05:00
Travis Ralston d8bcc4e3f1 Initial support for specifying which servers to try in joinRoom
This has a bug when using browser-request where the query string for `server_name: [a, b]` comes out as `?server_name=a,b` instead of `?server_name=a&server_name=b`. This is due to browser-request not supporting the same qs options as request, so the qsStringifyOptions do nothing.
2018-10-19 13:34:22 -06:00
Travis Ralston 1061026f96 Merge pull request #761 from Half-Shot/hs/upload-limits
Add getMediaConfig()
2018-10-16 09:04:08 -06:00
Will Hunt e638c49160 Merge remote-tracking branch 'upstream/develop' into hs/upload-limits 2018-10-16 11:32:21 +01:00
David Baker 5d84db9fb7 Merge branch 'release-v0.12.0' 2018-10-16 10:49:14 +01:00
David Baker b9e198c172 Oops: remove debug logging 2018-10-15 11:39:39 +01:00
David Baker 5873db7331 Merge remote-tracking branch 'origin/develop' into dbkr/wasm 2018-10-09 10:47:11 +01:00
David Baker 35d584c67b Remove outdated comment 2018-10-04 13:05:45 +01:00
David Baker 9504cbcc4f Merge remote-tracking branch 'origin/develop' into dbkr/wasm 2018-10-04 11:19:37 +01:00
Bruno Windels 6790699279 Merge pull request #739 from matrix-org/ben/new-examples
add new examples, to be expanded into a post
2018-10-04 10:21:36 +02:00
Ben Parsons fbca7951fc improvements suggested by Bruno 2018-10-01 14:29:24 +01:00
David Baker 33ad65a105 Don't assume Olm will be available from start
By doing `Olm = global.Olm` on script load, we require that Olm is
available right from the start, which isn't really necessary. As
long as it appears some time before we actually want to use it,
this is fine (we can probably assume it's not going to go away
again..?)

This means Riot doesn't need to faff about making sure olm is
loaded before starting anything else.
2018-09-26 16:39:22 +01:00
David Baker 63cc3fd890 lint 2018-09-25 18:14:11 +01:00
David Baker c556ca40b1 Support Olm with WebAssembly
wasm Olm has a new interface: it now has an init method that needs
to be called and the promise it returns waited on before the Olm
module is used. Support that, and allow Crypto etc to be imported
whether Olm is enabled or not. Change whether olm is enabled to
be async since now it will be unavailable if the async module init
fails. Don't call getOlmVersion() until the Olm.init() is done.
2018-09-25 17:49:54 +01:00
Ben Parsons d28f829b1c add new examples, to be expanded into a post 2018-09-20 13:12:50 +01:00
Will Hunt aec7ef6f9c getMediaLimits -> getMediaConfig 2018-06-23 14:38:39 +01:00
Will Hunt 329f09ce0a Media/limits => /config 2018-06-23 14:38:39 +01:00
Will Hunt 68c23af5ae Remove extra return 2018-06-23 14:38:39 +01:00
Will Hunt a54f30c02f Add getMediaLimits to client 2018-06-23 14:38:39 +01:00
38 changed files with 611 additions and 196 deletions
+88
View File
@@ -1,3 +1,91 @@
Changes in [0.14.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v0.14.1) (2018-11-22)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v0.14.0...v0.14.1)
* Warning when crypto DB is too new to use.
Changes in [0.14.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v0.14.0) (2018-11-19)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v0.14.0-rc.1...v0.14.0)
* No changes since rc.1
Changes in [0.14.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v0.14.0-rc.1) (2018-11-15)
============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v0.13.1...v0.14.0-rc.1)
BREAKING CHANGE
----------------
* js-sdk now uses Olm 3.0. Apps using Olm must update to 3.0 to
continue using Olm with the js-sdk. The js-sdk will call Olm's
init() method when the client is started.
All Changes
-----------
* Prevent messages from being sent if other messages have failed to send
[\#781](https://github.com/matrix-org/matrix-js-sdk/pull/781)
* A unit test for olm
[\#777](https://github.com/matrix-org/matrix-js-sdk/pull/777)
* Set access_token and user_id after login in with username and password.
[\#778](https://github.com/matrix-org/matrix-js-sdk/pull/778)
* Add function to get currently joined rooms.
[\#779](https://github.com/matrix-org/matrix-js-sdk/pull/779)
* Remove the request-only stuff we don't need anymore
[\#775](https://github.com/matrix-org/matrix-js-sdk/pull/775)
* Manually construct query strings for browser-request instances
[\#770](https://github.com/matrix-org/matrix-js-sdk/pull/770)
* Fix: correctly check for crypto being present
[\#769](https://github.com/matrix-org/matrix-js-sdk/pull/769)
* Update babel-eslint to 8.1.1
[\#768](https://github.com/matrix-org/matrix-js-sdk/pull/768)
* Support `request` in the browser and support supplying servers to try in
joinRoom()
[\#764](https://github.com/matrix-org/matrix-js-sdk/pull/764)
* loglevel should be a normal dependency
[\#767](https://github.com/matrix-org/matrix-js-sdk/pull/767)
* Stop devicelist when client is stopped
[\#766](https://github.com/matrix-org/matrix-js-sdk/pull/766)
* Update to WebAssembly-powered Olm
[\#743](https://github.com/matrix-org/matrix-js-sdk/pull/743)
* Logging lib. Fixes #332
[\#763](https://github.com/matrix-org/matrix-js-sdk/pull/763)
* Use new stop() method on matrix-mock-request
[\#765](https://github.com/matrix-org/matrix-js-sdk/pull/765)
Changes in [0.13.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v0.13.1) (2018-11-14)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v0.13.0...v0.13.1)
* Add function to get currently joined rooms.
[\#779](https://github.com/matrix-org/matrix-js-sdk/pull/779)
Changes in [0.13.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v0.13.0) (2018-11-15)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v0.12.1...v0.13.0)
BREAKING CHANGE
----------------
* `MatrixClient::login` now sets client `access_token` and `user_id` following successful login with username and password.
Changes in [0.12.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v0.12.1) (2018-10-29)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v0.12.1-rc.1...v0.12.1)
* No changes since rc.1
Changes in [0.12.1-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v0.12.1-rc.1) (2018-10-24)
============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v0.12.0...v0.12.1-rc.1)
* Add repository type to package.json to make it valid
[\#762](https://github.com/matrix-org/matrix-js-sdk/pull/762)
* Add getMediaConfig()
[\#761](https://github.com/matrix-org/matrix-js-sdk/pull/761)
* add new examples, to be expanded into a post
[\#739](https://github.com/matrix-org/matrix-js-sdk/pull/739)
Changes in [0.12.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v0.12.0) (2018-10-16)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v0.12.0-rc.1...v0.12.0)
+54 -2
View File
@@ -30,9 +30,61 @@ In Node.js
console.log("Public Rooms: %s", JSON.stringify(data));
});
```
See below for how to include libolm to enable end-to-end-encryption. Please check
[the Node.js terminal app](examples/node) for a more complex example.
To start the client:
```javascript
await client.startClient({initialSyncLimit: 10});
```
You can perform a call to `/sync` to get the current state of the client:
```javascript
client.once('sync', function(state, prevState, res) {
if(state === 'PREPARED') {
console.log("prepared");
} else {
console.log(state);
process.exit(1);
}
});
```
To send a message:
```javascript
var content = {
"body": "message text",
"msgtype": "m.text"
};
client.sendEvent("roomId", "m.room.message", content, "", (err, res) => {
console.log(err);
});
```
To listen for message events:
```javascript
client.on("Room.timeline", function(event, room, toStartOfTimeline) {
if (event.getType() !== "m.room.message") {
return; // only use messages
}
console.log(event.event.content.body);
});
```
By default, the `matrix-js-sdk` client uses the `MatrixInMemoryStore` to store events as they are received. For example to iterate through the currently stored timeline for a room:
```javascript
Object.keys(client.store.rooms).forEach((roomId) => {
client.getRoom(roomId).timeline.forEach(t => {
console.log(t.event);
});
});
```
What does this SDK do?
----------------------
@@ -267,13 +319,13 @@ To provide the Olm library in a browser application:
To provide the Olm library in a node.js application:
* ``npm install https://matrix.org/packages/npm/olm/olm-2.2.2.tgz``
* ``npm install https://matrix.org/packages/npm/olm/olm-3.0.0.tgz``
(replace the URL with the latest version you want to use from
https://matrix.org/packages/npm/olm/)
* ``global.Olm = require('olm');`` *before* loading ``matrix-js-sdk``.
If you want to package Olm as dependency for your node.js application, you
can use ``npm install https://matrix.org/packages/npm/olm/olm-2.2.2.tgz
can use ``npm install https://matrix.org/packages/npm/olm/olm-3.0.0.tgz
--save-optional`` (if your application also works without e2e crypto enabled)
or ``--save`` (if it doesn't) to do so.
+13 -1
View File
@@ -1,5 +1,17 @@
var matrixcs = require("./lib/matrix");
matrixcs.request(require("browser-request"));
const request = require('browser-request');
const queryString = require('qs');
matrixcs.request(function(opts, fn) {
// We manually fix the query string for browser-request because
// it doesn't correctly handle cases like ?via=one&via=two. Instead
// we mimic `request`'s query string interface to make it all work
// as expected.
// browser-request will happily take the constructed string as the
// query string without trying to modify it further.
opts.qs = queryString.stringify(opts.qs || {}, opts.qsStringifyOptions);
return request(opts, fn);
});
// just *accessing* indexedDB throws an exception in firefox with
// indexeddb disabled.
+9 -6
View File
@@ -1,6 +1,6 @@
{
"name": "matrix-js-sdk",
"version": "0.12.0",
"version": "0.14.1",
"description": "Matrix Client-Server SDK for Javascript",
"main": "index.js",
"scripts": {
@@ -21,6 +21,7 @@
"prepublish": "npm run clean && npm run build && git rev-parse HEAD > git-revision.txt"
},
"repository": {
"type": "git",
"url": "https://github.com/matrix-org/matrix-js-sdk"
},
"keywords": [
@@ -56,15 +57,17 @@
"bluebird": "^3.5.0",
"browser-request": "^0.3.3",
"content-type": "^1.0.2",
"request": "^2.53.0"
"loglevel": "1.6.1",
"qs": "^6.5.2",
"request": "^2.88.0"
},
"devDependencies": {
"babel-cli": "^6.18.0",
"babel-eslint": "^7.1.1",
"babel-eslint": "^8.1.1",
"babel-plugin-transform-async-to-bluebird": "^1.1.1",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.18.0",
"browserify": "^14.0.0",
"browserify": "^16.2.3",
"browserify-shim": "^3.8.13",
"eslint": "^3.13.1",
"eslint-config-google": "^0.7.1",
@@ -73,14 +76,14 @@
"istanbul": "^0.4.5",
"jsdoc": "^3.5.5",
"lolex": "^1.5.2",
"matrix-mock-request": "^1.2.0",
"matrix-mock-request": "^1.2.2",
"mocha": "^5.2.0",
"mocha-jenkins-reporter": "^0.4.0",
"rimraf": "^2.5.4",
"source-map-support": "^0.4.11",
"sourceify": "^0.1.0",
"uglify-js": "^2.8.26",
"watchify": "^3.2.1"
"watchify": "^3.11.0"
},
"browserify": {
"transform": [
+2
View File
@@ -102,9 +102,11 @@ TestClient.prototype.start = function() {
/**
* stop the client
* @return {Promise} Resolves once the mock http backend has finished all pending flushes
*/
TestClient.prototype.stop = function() {
this.client.stopClient();
return this.httpBackend.stop();
};
/**
+1 -1
View File
@@ -97,7 +97,7 @@ describe("DeviceList management:", function() {
});
afterEach(function() {
aliceTestClient.stop();
return aliceTestClient.stop();
});
it("Alice shouldn't do a second /query for non-e2e-capable devices", function() {
+2 -2
View File
@@ -410,10 +410,10 @@ describe("MatrixClient crypto", function() {
});
afterEach(function() {
aliTestClient.stop();
aliTestClient.httpBackend.verifyNoOutstandingExpectation();
bobTestClient.stop();
bobTestClient.httpBackend.verifyNoOutstandingExpectation();
return Promise.all([aliTestClient.stop(), bobTestClient.stop()]);
});
it("Bob uploads device keys", function() {
@@ -30,6 +30,7 @@ describe("MatrixClient events", function() {
afterEach(function() {
httpBackend.verifyNoOutstandingExpectation();
client.stopClient();
return httpBackend.stop();
});
describe("emissions", function() {
@@ -111,6 +111,7 @@ describe("getEventTimeline support", function() {
if (client) {
client.stopClient();
}
return httpBackend.stop();
});
it("timeline support must be enabled to work", function(done) {
+1
View File
@@ -41,6 +41,7 @@ describe("MatrixClient", function() {
afterEach(function() {
httpBackend.verifyNoOutstandingExpectation();
return httpBackend.stop();
});
describe("uploadContent", function() {
+1
View File
@@ -64,6 +64,7 @@ describe("MatrixClient opts", function() {
afterEach(function() {
httpBackend.verifyNoOutstandingExpectation();
return httpBackend.stop();
});
describe("without opts.store", function() {
@@ -36,6 +36,7 @@ describe("MatrixClient retrying", function() {
afterEach(function() {
httpBackend.verifyNoOutstandingExpectation();
return httpBackend.stop();
});
xit("should retry according to MatrixScheduler.retryFn", function() {
@@ -130,6 +130,7 @@ describe("MatrixClient room timelines", function() {
afterEach(function() {
httpBackend.verifyNoOutstandingExpectation();
client.stopClient();
return httpBackend.stop();
});
describe("local echo events", function() {
+1
View File
@@ -38,6 +38,7 @@ describe("MatrixClient syncing", function() {
afterEach(function() {
httpBackend.verifyNoOutstandingExpectation();
client.stopClient();
return httpBackend.stop();
});
describe("startClient", function() {
+8 -2
View File
@@ -296,7 +296,7 @@ describe("megolm", function() {
});
afterEach(function() {
aliceTestClient.stop();
return aliceTestClient.stop();
});
it("Alice receives a megolm message", function() {
@@ -817,8 +817,14 @@ describe("megolm", function() {
};
});
// Grab the event that we'll need to resend
const room = aliceTestClient.client.getRoom(ROOM_ID);
const pendingEvents = room.getPendingEvents();
expect(pendingEvents.length).toEqual(1);
const unsentEvent = pendingEvents[0];
return Promise.all([
aliceTestClient.client.sendTextMessage(ROOM_ID, 'test'),
aliceTestClient.client.resendEvent(unsentEvent, room),
// the crypto stuff can take a while, so give the requests a whole second.
aliceTestClient.httpBackend.flushAllExpected({
+9 -6
View File
@@ -1,20 +1,23 @@
"use strict";
import 'source-map-support/register';
import Crypto from '../../lib/crypto';
import expect from 'expect';
const sdk = require("../..");
let Crypto;
if (sdk.CRYPTO_ENABLED) {
Crypto = require("../../lib/crypto");
}
import expect from 'expect';
const Olm = global.Olm;
describe("Crypto", function() {
if (!sdk.CRYPTO_ENABLED) {
return;
}
beforeEach(function(done) {
Olm.init().then(done);
});
it("Crypto exposes the correct olm library version", function() {
expect(Crypto.getOlmVersion()[0]).toEqual(2);
expect(Crypto.getOlmVersion()[0]).toEqual(3);
});
});
+12 -1
View File
@@ -59,16 +59,25 @@ describe('DeviceList', function() {
let downloadSpy;
let sessionStore;
let cryptoStore;
let deviceLists = [];
beforeEach(function() {
testUtils.beforeEach(this); // eslint-disable-line no-invalid-this
deviceLists = [];
downloadSpy = expect.createSpy();
const mockStorage = new MockStorageApi();
sessionStore = new WebStorageSessionStore(mockStorage);
cryptoStore = new MemoryCryptoStore();
});
afterEach(function() {
for (const dl of deviceLists) {
dl.stop();
}
});
function createTestDeviceList() {
const baseApis = {
downloadKeysForUsers: downloadSpy,
@@ -76,7 +85,9 @@ describe('DeviceList', function() {
const mockOlm = {
verifySignature: function(key, message, signature) {},
};
return new DeviceList(baseApis, cryptoStore, sessionStore, mockOlm);
const dl = new DeviceList(baseApis, cryptoStore, sessionStore, mockOlm);
deviceLists.push(dl);
return dl;
}
it("should successfully download and store device keys", function() {
+7 -10
View File
@@ -13,20 +13,16 @@ import WebStorageSessionStore from '../../../../lib/store/session/webstorage';
import MemoryCryptoStore from '../../../../lib/crypto/store/memory-crypto-store.js';
import MockStorageApi from '../../../MockStorageApi';
import testUtils from '../../../test-utils';
// Crypto and OlmDevice won't import unless we have global.Olm
let OlmDevice;
let Crypto;
if (global.Olm) {
OlmDevice = require('../../../../lib/crypto/OlmDevice');
Crypto = require('../../../../lib/crypto');
}
import OlmDevice from '../../../../lib/crypto/OlmDevice';
import Crypto from '../../../../lib/crypto';
const MatrixEvent = sdk.MatrixEvent;
const MegolmDecryption = algorithms.DECRYPTION_CLASSES['m.megolm.v1.aes-sha2'];
const ROOM_ID = '!ROOM:ID';
const Olm = global.Olm;
describe("MegolmDecryption", function() {
if (!global.Olm) {
console.warn('Not running megolm unit tests: libolm not present');
@@ -69,7 +65,8 @@ describe("MegolmDecryption", function() {
describe('receives some keys:', function() {
let groupSession;
beforeEach(function() {
beforeEach(async function() {
await Olm.init();
groupSession = new global.Olm.OutboundGroupSession();
groupSession.create();
@@ -98,7 +95,7 @@ describe("MegolmDecryption", function() {
},
};
return event.attemptDecryption(mockCrypto).then(() => {
await event.attemptDecryption(mockCrypto).then(() => {
megolmDecryption.onRoomKeyEvent(event);
});
});
+90
View File
@@ -0,0 +1,90 @@
/*
Copyright 2018 New Vector Ltd
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.
*/
try {
global.Olm = require('olm');
} catch (e) {
console.warn("unable to run megolm tests: libolm not available");
}
import expect from 'expect';
import WebStorageSessionStore from '../../../../lib/store/session/webstorage';
import MemoryCryptoStore from '../../../../lib/crypto/store/memory-crypto-store.js';
import MockStorageApi from '../../../MockStorageApi';
import testUtils from '../../../test-utils';
import OlmDevice from '../../../../lib/crypto/OlmDevice';
function makeOlmDevice() {
const mockStorage = new MockStorageApi();
const sessionStore = new WebStorageSessionStore(mockStorage);
const cryptoStore = new MemoryCryptoStore(mockStorage);
const olmDevice = new OlmDevice(sessionStore, cryptoStore);
return olmDevice;
}
async function setupSession(initiator, opponent) {
await opponent.generateOneTimeKeys(1);
const keys = await opponent.getOneTimeKeys();
const firstKey = Object.values(keys['curve25519'])[0];
const sid = await initiator.createOutboundSession(
opponent.deviceCurve25519Key, firstKey,
);
return sid;
}
describe("OlmDecryption", function() {
if (!global.Olm) {
console.warn('Not running megolm unit tests: libolm not present');
return;
}
let aliceOlmDevice;
let bobOlmDevice;
beforeEach(async function() {
testUtils.beforeEach(this); // eslint-disable-line no-invalid-this
await global.Olm.init();
aliceOlmDevice = makeOlmDevice();
bobOlmDevice = makeOlmDevice();
await aliceOlmDevice.init();
await bobOlmDevice.init();
});
describe('olm', function() {
it("can decrypt messages", async function() {
const sid = await setupSession(aliceOlmDevice, bobOlmDevice);
const ciphertext = await aliceOlmDevice.encryptMessage(
bobOlmDevice.deviceCurve25519Key,
sid,
"The olm or proteus is an aquatic salamander in the family Proteidae",
);
const result = await bobOlmDevice.createInboundSession(
aliceOlmDevice.deviceCurve25519Key,
ciphertext.type,
ciphertext.body,
);
expect(result.payload).toEqual(
"The olm or proteus is an aquatic salamander in the family Proteidae",
);
});
});
});
+35 -1
View File
@@ -262,7 +262,19 @@ MatrixBaseApis.prototype.login = function(loginType, data, callback) {
utils.extend(login_data, data);
return this._http.authedRequest(
callback, "POST", "/login", undefined, login_data,
(error, response) => {
if (loginType === "m.login.password" && response &&
response.access_token && response.user_id) {
this._http.opts.accessToken = response.access_token;
this.credentials = {
userId: response.user_id,
};
}
if (callback) {
callback(error, response);
}
}, "POST", "/login", undefined, login_data,
);
};
@@ -927,6 +939,28 @@ MatrixBaseApis.prototype.setRoomReadMarkersHttpRequest =
);
};
/**
* @return {module:client.Promise} Resolves: A list of the user's current rooms
* @return {module:http-api.MatrixError} Rejects: with an error response.
*/
MatrixBaseApis.prototype.getJoinedRooms = function() {
const path = utils.encodeUri("/joined_rooms");
return this._http.authedRequest(undefined, "GET", path);
};
/**
* Retrieve membership info. for a room.
* @param {string} roomId ID of the room to get membership for
* @return {module:client.Promise} Resolves: A list of currently joined users
* and their profile data.
* @return {module:http-api.MatrixError} Rejects: with an error response.
*/
MatrixBaseApis.prototype.getJoinedRoomMembers = function(roomId) {
const path = utils.encodeUri("/rooms/$roomId/joined_members", {
$roomId: roomId,
});
return this._http.authedRequest(undefined, "GET", path);
};
// Room Directory operations
// =========================
+45 -20
View File
@@ -45,20 +45,16 @@ const ContentHelpers = require("./content-helpers");
import ReEmitter from './ReEmitter';
import RoomList from './crypto/RoomList';
import Crypto from './crypto';
import { isCryptoAvailable } from './crypto';
// Disable warnings for now: we use deprecated bluebird functions
// and need to migrate, but they spam the console with warnings.
Promise.config({warnings: false});
const SCROLLBACK_DELAY_MS = 3000;
let CRYPTO_ENABLED = false;
try {
var Crypto = require("./crypto");
CRYPTO_ENABLED = true;
} catch (e) {
console.warn("Unable to load crypto module: crypto will be disabled: " + e);
}
const CRYPTO_ENABLED = isCryptoAvailable();
/**
* Construct a Matrix Client. Only directly construct this if you want to use
@@ -133,6 +129,8 @@ function MatrixClient(opts) {
MatrixBaseApis.call(this, opts);
this.olmVersion = null; // Populated after initCrypto is done
this.reEmitter = new ReEmitter(this);
this.store = opts.store || new StubStore();
@@ -185,10 +183,6 @@ function MatrixClient(opts) {
this._forceTURN = opts.forceTURN || false;
if (CRYPTO_ENABLED) {
this.olmVersion = Crypto.getOlmVersion();
}
// List of which rooms have encryption enabled: separate from crypto because
// we still want to know which rooms are encrypted even if crypto is disabled:
// we don't want to start sending unencrypted events to them.
@@ -378,6 +372,13 @@ MatrixClient.prototype.setNotifTimelineSet = function(notifTimelineSet) {
* successfully initialised.
*/
MatrixClient.prototype.initCrypto = async function() {
if (!isCryptoAvailable()) {
throw new Error(
`End-to-end encryption not supported in this js-sdk build: did ` +
`you remember to load the olm library?`,
);
}
if (this._crypto) {
console.warn("Attempt to re-initialise e2e encryption on MatrixClient");
return;
@@ -395,13 +396,6 @@ MatrixClient.prototype.initCrypto = async function() {
// initialise the list of encrypted rooms (whether or not crypto is enabled)
await this._roomList.init();
if (!CRYPTO_ENABLED) {
throw new Error(
`End-to-end encryption not supported in this js-sdk build: did ` +
`you remember to load the olm library?`,
);
}
const userId = this.getUserId();
if (userId === null) {
throw new Error(
@@ -433,6 +427,9 @@ MatrixClient.prototype.initCrypto = async function() {
await crypto.init();
this.olmVersion = Crypto.getOlmVersion();
// if crypto initialisation was successful, tell it to attach its event
// handlers.
crypto.registerEventHandlers(this);
@@ -764,6 +761,17 @@ MatrixClient.prototype.getGroups = function() {
return this.store.getGroups();
};
/**
* Get the config for the media repository.
* @param {module:client.callback} callback Optional.
* @return {module:client.Promise} Resolves with an object containing the config.
*/
MatrixClient.prototype.getMediaConfig = function(callback) {
return this._http.requestWithPrefix(
callback, "GET", "/config", undefined, undefined, httpApi.PREFIX_MEDIA_R0,
);
};
// Room ops
// ========
@@ -910,6 +918,8 @@ MatrixClient.prototype.isUserIgnored = function(userId) {
* </strong> Default: true.
* @param {boolean} opts.inviteSignUrl If the caller has a keypair 3pid invite,
* the signing URL is passed in this parameter.
* @param {string[]} opts.viaServers The server names to try and join through in
* addition to those that are automatically chosen.
* @param {module:client.callback} callback Optional.
* @return {module:client.Promise} Resolves: Room object.
* @return {module:http-api.MatrixError} Rejects: with an error response.
@@ -938,6 +948,13 @@ MatrixClient.prototype.joinRoom = function(roomIdOrAlias, opts, callback) {
);
}
const queryString = {};
if (opts.viaServers) {
queryString["server_name"] = opts.viaServers;
}
const reqOpts = {qsStringifyOptions: {arrayFormat: 'repeat'}};
const defer = Promise.defer();
const self = this;
@@ -948,7 +965,8 @@ MatrixClient.prototype.joinRoom = function(roomIdOrAlias, opts, callback) {
}
const path = utils.encodeUri("/join/$roomid", { $roomid: roomIdOrAlias});
return self._http.authedRequest(undefined, "POST", path, undefined, data);
return self._http.authedRequest(
undefined, "POST", path, queryString, data, reqOpts);
}).then(function(res) {
const roomId = res.room_id;
const syncApi = new SyncApi(self, self._clientOpts);
@@ -1168,6 +1186,13 @@ MatrixClient.prototype.sendEvent = function(roomId, eventType, content, txnId,
room.addPendingEvent(localEvent, txnId);
}
// addPendingEvent can change the state to NOT_SENT if it believes
// that there's other events that have failed. We won't bother to
// try sending the event if the state has changed as such.
if (localEvent.status === EventStatus.NOT_SENT) {
return Promise.reject(new Error("Event blocked by other events not yet sent"));
}
return _sendEvent(this, room, localEvent, callback);
};
+29 -22
View File
@@ -24,6 +24,7 @@ limitations under the License.
import Promise from 'bluebird';
import logger from '../logger';
import DeviceInfo from './deviceinfo';
import olmlib from './olmlib';
import IndexedDBCryptoStore from './store/indexeddb-crypto-store';
@@ -110,7 +111,7 @@ export default class DeviceList {
'readwrite', [IndexedDBCryptoStore.STORE_DEVICE_DATA], (txn) => {
this._cryptoStore.getEndToEndDeviceData(txn, (deviceData) => {
if (deviceData === null) {
console.log("Migrating e2e device data...");
logger.log("Migrating e2e device data...");
this._devices = this._sessionStore.getAllEndToEndDevices() || {};
this._deviceTrackingStatus = (
this._sessionStore.getEndToEndDeviceTrackingStatus() || {}
@@ -145,6 +146,12 @@ export default class DeviceList {
}
}
stop() {
if (this._saveTimer !== null) {
clearTimeout(this._saveTimer);
}
}
/**
* Save the device tracking state to storage, if any changes are
* pending other than updating the sync token
@@ -190,7 +197,7 @@ export default class DeviceList {
const resolveSavePromise = this._resolveSavePromise;
this._savePromiseTime = targetTime;
this._saveTimer = setTimeout(() => {
console.log('Saving device tracking data at token ' + this._syncToken);
logger.log('Saving device tracking data at token ' + this._syncToken);
// null out savePromise now (after the delay but before the write),
// otherwise we could return the existing promise when the save has
// actually already happened. Likewise for the dirty flag.
@@ -258,7 +265,7 @@ export default class DeviceList {
if (this._keyDownloadsInProgressByUser[u]) {
// already a key download in progress/queued for this user; its results
// will be good enough for us.
console.log(
logger.log(
`downloadKeys: already have a download in progress for ` +
`${u}: awaiting its result`,
);
@@ -269,13 +276,13 @@ export default class DeviceList {
});
if (usersToDownload.length != 0) {
console.log("downloadKeys: downloading for", usersToDownload);
logger.log("downloadKeys: downloading for", usersToDownload);
const downloadPromise = this._doKeyDownload(usersToDownload);
promises.push(downloadPromise);
}
if (promises.length === 0) {
console.log("downloadKeys: already have all necessary keys");
logger.log("downloadKeys: already have all necessary keys");
}
return Promise.all(promises).then(() => {
@@ -433,7 +440,7 @@ export default class DeviceList {
throw new Error('userId must be a string; was '+userId);
}
if (!this._deviceTrackingStatus[userId]) {
console.log('Now tracking device list for ' + userId);
logger.log('Now tracking device list for ' + userId);
this._deviceTrackingStatus[userId] = TRACKING_STATUS_PENDING_DOWNLOAD;
}
// we don't yet persist the tracking status, since there may be a lot
@@ -452,7 +459,7 @@ export default class DeviceList {
*/
stopTrackingDeviceList(userId) {
if (this._deviceTrackingStatus[userId]) {
console.log('No longer tracking device list for ' + userId);
logger.log('No longer tracking device list for ' + userId);
this._deviceTrackingStatus[userId] = TRACKING_STATUS_NOT_TRACKED;
// we don't yet persist the tracking status, since there may be a lot
@@ -487,7 +494,7 @@ export default class DeviceList {
*/
invalidateUserDeviceList(userId) {
if (this._deviceTrackingStatus[userId]) {
console.log("Marking device list outdated for", userId);
logger.log("Marking device list outdated for", userId);
this._deviceTrackingStatus[userId] = TRACKING_STATUS_PENDING_DOWNLOAD;
// we don't yet persist the tracking status, since there may be a lot
@@ -550,7 +557,7 @@ export default class DeviceList {
).then(() => {
finished(true);
}, (e) => {
console.error(
logger.error(
'Error downloading keys for ' + users + ":", e,
);
finished(false);
@@ -573,7 +580,7 @@ export default class DeviceList {
// since we started this request. If that happens, we should
// ignore the completion of the first one.
if (this._keyDownloadsInProgressByUser[u] !== prom) {
console.log('Another update in the queue for', u,
logger.log('Another update in the queue for', u,
'- not marking up-to-date');
return;
}
@@ -584,7 +591,7 @@ export default class DeviceList {
// we didn't get any new invalidations since this download started:
// this user's device list is now up to date.
this._deviceTrackingStatus[u] = TRACKING_STATUS_UP_TO_DATE;
console.log("Device list for", u, "now up to date");
logger.log("Device list for", u, "now up to date");
} else {
this._deviceTrackingStatus[u] = TRACKING_STATUS_PENDING_DOWNLOAD;
}
@@ -659,7 +666,7 @@ class DeviceListUpdateSerialiser {
if (this._downloadInProgress) {
// just queue up these users
console.log('Queued key download for', users);
logger.log('Queued key download for', users);
return this._queuedQueryDeferred.promise;
}
@@ -679,7 +686,7 @@ class DeviceListUpdateSerialiser {
const deferred = this._queuedQueryDeferred;
this._queuedQueryDeferred = null;
console.log('Starting key download for', downloadUsers);
logger.log('Starting key download for', downloadUsers);
this._downloadInProgress = true;
const opts = {};
@@ -706,7 +713,7 @@ class DeviceListUpdateSerialiser {
return prom;
}).done(() => {
console.log('Completed key download for ' + downloadUsers);
logger.log('Completed key download for ' + downloadUsers);
this._downloadInProgress = false;
deferred.resolve();
@@ -716,7 +723,7 @@ class DeviceListUpdateSerialiser {
this._doQueuedQueries();
}
}, (e) => {
console.warn('Error downloading keys for ' + downloadUsers + ':', e);
logger.warn('Error downloading keys for ' + downloadUsers + ':', e);
this._downloadInProgress = false;
deferred.reject(e);
});
@@ -725,7 +732,7 @@ class DeviceListUpdateSerialiser {
}
async _processQueryResponseForUser(userId, response) {
console.log('got keys for ' + userId + ':', response);
logger.log('got keys for ' + userId + ':', response);
// map from deviceid -> deviceinfo for this user
const userStore = {};
@@ -763,7 +770,7 @@ async function _updateStoredDeviceKeysForUser(_olmDevice, userId, userStore,
}
if (!(deviceId in userResult)) {
console.log("Device " + userId + ":" + deviceId +
logger.log("Device " + userId + ":" + deviceId +
" has been removed");
delete userStore[deviceId];
updated = true;
@@ -780,12 +787,12 @@ async function _updateStoredDeviceKeysForUser(_olmDevice, userId, userStore,
// check that the user_id and device_id in the response object are
// correct
if (deviceResult.user_id !== userId) {
console.warn("Mismatched user_id " + deviceResult.user_id +
logger.warn("Mismatched user_id " + deviceResult.user_id +
" in keys from " + userId + ":" + deviceId);
continue;
}
if (deviceResult.device_id !== deviceId) {
console.warn("Mismatched device_id " + deviceResult.device_id +
logger.warn("Mismatched device_id " + deviceResult.device_id +
" in keys from " + userId + ":" + deviceId);
continue;
}
@@ -815,7 +822,7 @@ async function _storeDeviceKeys(_olmDevice, userStore, deviceResult) {
const signKeyId = "ed25519:" + deviceId;
const signKey = deviceResult.keys[signKeyId];
if (!signKey) {
console.warn("Device " + userId + ":" + deviceId +
logger.warn("Device " + userId + ":" + deviceId +
" has no ed25519 key");
return false;
}
@@ -825,7 +832,7 @@ async function _storeDeviceKeys(_olmDevice, userStore, deviceResult) {
try {
await olmlib.verifySignature(_olmDevice, deviceResult, userId, deviceId, signKey);
} catch (e) {
console.warn("Unable to verify signature on device " +
logger.warn("Unable to verify signature on device " +
userId + ":" + deviceId + ":" + e);
return false;
}
@@ -842,7 +849,7 @@ async function _storeDeviceKeys(_olmDevice, userStore, deviceResult) {
// best off sticking with the original keys.
//
// Should we warn the user about it somehow?
console.warn("Ed25519 key for device " + userId + ":" +
logger.warn("Ed25519 key for device " + userId + ":" +
deviceId + " has changed");
return false;
}
+19 -29
View File
@@ -15,19 +15,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import logger from '../logger';
import IndexedDBCryptoStore from './store/indexeddb-crypto-store';
/**
* olm.js wrapper
*
* @module crypto/OlmDevice
*/
const Olm = global.Olm;
if (!Olm) {
throw new Error("global.Olm is not defined");
}
// The maximum size of an event is 65K, and we base64 the content, so this is a
// reasonable approximation to the biggest plaintext we can encrypt.
const MAX_PLAINTEXT_LENGTH = 65536 * 3 / 4;
@@ -127,7 +117,7 @@ OlmDevice.prototype.init = async function() {
await this._migrateFromSessionStore();
let e2eKeys;
const account = new Olm.Account();
const account = new global.Olm.Account();
try {
await _initialiseAccount(
this._sessionStore, this._cryptoStore, this._pickleKey, account,
@@ -161,7 +151,7 @@ async function _initialiseAccount(sessionStore, cryptoStore, pickleKey, account)
* @return {array} The version of Olm.
*/
OlmDevice.getOlmVersion = function() {
return Olm.get_library_version();
return global.Olm.get_library_version();
};
OlmDevice.prototype._migrateFromSessionStore = async function() {
@@ -173,7 +163,7 @@ OlmDevice.prototype._migrateFromSessionStore = async function() {
// Migrate from sessionStore
pickledAccount = this._sessionStore.getEndToEndAccount();
if (pickledAccount !== null) {
console.log("Migrating account from session store");
logger.log("Migrating account from session store");
this._cryptoStore.storeAccount(txn, pickledAccount);
}
}
@@ -195,7 +185,7 @@ OlmDevice.prototype._migrateFromSessionStore = async function() {
// has run against the same localstorage and created some spurious sessions.
this._cryptoStore.countEndToEndSessions(txn, (count) => {
if (count) {
console.log("Crypto store already has sessions: not migrating");
logger.log("Crypto store already has sessions: not migrating");
return;
}
let numSessions = 0;
@@ -207,7 +197,7 @@ OlmDevice.prototype._migrateFromSessionStore = async function() {
);
}
}
console.log(
logger.log(
"Migrating " + numSessions + " sessions from session store",
);
});
@@ -236,14 +226,14 @@ OlmDevice.prototype._migrateFromSessionStore = async function() {
), txn,
);
} catch (e) {
console.warn(
logger.warn(
"Failed to migrate session " + s.senderKey + "/" +
s.sessionId + ": " + e.stack || e,
);
}
++numIbSessions;
}
console.log(
logger.log(
"Migrated " + numIbSessions +
" inbound group sessions from session store",
);
@@ -268,7 +258,7 @@ OlmDevice.prototype._migrateFromSessionStore = async function() {
*/
OlmDevice.prototype._getAccount = function(txn, func) {
this._cryptoStore.getAccount(txn, (pickledAccount) => {
const account = new Olm.Account();
const account = new global.Olm.Account();
try {
account.unpickle(this._pickleKey, pickledAccount);
func(account);
@@ -321,7 +311,7 @@ OlmDevice.prototype._getSession = function(deviceKey, sessionId, txn, func) {
* @private
*/
OlmDevice.prototype._unpickleSession = function(pickledSession, func) {
const session = new Olm.Session();
const session = new global.Olm.Session();
try {
session.unpickle(this._pickleKey, pickledSession);
func(session);
@@ -354,7 +344,7 @@ OlmDevice.prototype._saveSession = function(deviceKey, session, txn) {
* @private
*/
OlmDevice.prototype._getUtility = function(func) {
const utility = new Olm.Utility();
const utility = new global.Olm.Utility();
try {
return func(utility);
} finally {
@@ -466,7 +456,7 @@ OlmDevice.prototype.createOutboundSession = async function(
],
(txn) => {
this._getAccount(txn, (account) => {
const session = new Olm.Session();
const session = new global.Olm.Session();
try {
session.create_outbound(account, theirIdentityKey, theirOneTimeKey);
newSessionId = session.session_id();
@@ -510,7 +500,7 @@ OlmDevice.prototype.createInboundSession = async function(
],
(txn) => {
this._getAccount(txn, (account) => {
const session = new Olm.Session();
const session = new global.Olm.Session();
try {
session.create_inbound_from(
account, theirDeviceIdentityKey, ciphertext,
@@ -728,7 +718,7 @@ OlmDevice.prototype._getOutboundGroupSession = function(sessionId, func) {
throw new Error("Unknown outbound group session " + sessionId);
}
const session = new Olm.OutboundGroupSession();
const session = new global.Olm.OutboundGroupSession();
try {
session.unpickle(this._pickleKey, pickled);
return func(session);
@@ -744,7 +734,7 @@ OlmDevice.prototype._getOutboundGroupSession = function(sessionId, func) {
* @return {string} sessionId for the outbound session.
*/
OlmDevice.prototype.createOutboundGroupSession = function() {
const session = new Olm.OutboundGroupSession();
const session = new global.Olm.OutboundGroupSession();
try {
session.create();
this._saveOutboundGroupSession(session);
@@ -816,7 +806,7 @@ OlmDevice.prototype.getOutboundGroupSessionKey = function(sessionId) {
* @return {*} result of func
*/
OlmDevice.prototype._unpickleInboundGroupSession = function(sessionData, func) {
const session = new Olm.InboundGroupSession();
const session = new global.Olm.InboundGroupSession();
try {
session.unpickle(this._pickleKey, sessionData.session);
return func(session);
@@ -889,7 +879,7 @@ OlmDevice.prototype.addInboundGroupSession = async function(
roomId, senderKey, sessionId, txn,
(existingSession, existingSessionData) => {
if (existingSession) {
console.log(
logger.log(
"Update for megolm session " + senderKey + "/" + sessionId,
);
// for now we just ignore updates. TODO: implement something here
@@ -897,7 +887,7 @@ OlmDevice.prototype.addInboundGroupSession = async function(
}
// new session.
const session = new Olm.InboundGroupSession();
const session = new global.Olm.InboundGroupSession();
try {
if (exportFormat) {
session.import_session(sessionKey);
@@ -1034,7 +1024,7 @@ OlmDevice.prototype.hasInboundSessionKeys = async function(roomId, senderKey, se
}
if (roomId !== sessionData.room_id) {
console.warn(
logger.warn(
`requested keys for inbound group session ${senderKey}|` +
`${sessionId}, with incorrect room_id ` +
`(expected ${sessionData.room_id}, ` +
+11 -10
View File
@@ -16,6 +16,7 @@ limitations under the License.
import Promise from 'bluebird';
import logger from '../logger';
import utils from '../utils';
/**
@@ -108,7 +109,7 @@ export default class OutgoingRoomKeyRequestManager {
* Called when the client is stopped. Stops any running background processes.
*/
stop() {
console.log('stopping OutgoingRoomKeyRequestManager');
logger.log('stopping OutgoingRoomKeyRequestManager');
// stop the timer on the next run
this._clientRunning = false;
}
@@ -173,7 +174,7 @@ export default class OutgoingRoomKeyRequestManager {
// may have seen it, so we still need to send a cancellation
// in that case :/
console.log(
logger.log(
'deleting unnecessary room key request for ' +
stringifyRequestBody(requestBody),
);
@@ -201,7 +202,7 @@ export default class OutgoingRoomKeyRequestManager {
// the request cancelled. There is no point in
// sending another cancellation since the other tab
// will do it.
console.log(
logger.log(
'Tried to cancel room key request for ' +
stringifyRequestBody(requestBody) +
' but it was already cancelled in another tab',
@@ -222,7 +223,7 @@ export default class OutgoingRoomKeyRequestManager {
updatedReq,
andResend,
).catch((e) => {
console.error(
logger.error(
"Error sending room key request cancellation;"
+ " will retry later.", e,
);
@@ -261,7 +262,7 @@ export default class OutgoingRoomKeyRequestManager {
}).catch((e) => {
// this should only happen if there is an indexeddb error,
// in which case we're a bit stuffed anyway.
console.warn(
logger.warn(
`error in OutgoingRoomKeyRequestManager: ${e}`,
);
}).done();
@@ -282,7 +283,7 @@ export default class OutgoingRoomKeyRequestManager {
return Promise.resolve();
}
console.log("Looking for queued outgoing room key requests");
logger.log("Looking for queued outgoing room key requests");
return this._cryptoStore.getOutgoingRoomKeyRequestByState([
ROOM_KEY_REQUEST_STATES.CANCELLATION_PENDING,
@@ -290,7 +291,7 @@ export default class OutgoingRoomKeyRequestManager {
ROOM_KEY_REQUEST_STATES.UNSENT,
]).then((req) => {
if (!req) {
console.log("No more outgoing room key requests");
logger.log("No more outgoing room key requests");
this._sendOutgoingRoomKeyRequestsTimer = null;
return;
}
@@ -312,7 +313,7 @@ export default class OutgoingRoomKeyRequestManager {
// go around the loop again
return this._sendOutgoingRoomKeyRequests();
}).catch((e) => {
console.error("Error sending room key request; will retry later.", e);
logger.error("Error sending room key request; will retry later.", e);
this._sendOutgoingRoomKeyRequestsTimer = null;
this._startTimer();
}).done();
@@ -321,7 +322,7 @@ export default class OutgoingRoomKeyRequestManager {
// given a RoomKeyRequest, send it and update the request record
_sendOutgoingRoomKeyRequest(req) {
console.log(
logger.log(
`Requesting keys for ${stringifyRequestBody(req.requestBody)}` +
` from ${stringifyRecipientList(req.recipients)}` +
`(id ${req.requestId})`,
@@ -347,7 +348,7 @@ export default class OutgoingRoomKeyRequestManager {
// Given a RoomKeyRequest, cancel it and delete the request record unless
// andResend is set, in which case transition to UNSENT.
_sendOutgoingRoomKeyRequestCancellation(req, andResend) {
console.log(
logger.log(
`Sending cancellation for key request for ` +
`${stringifyRequestBody(req.requestBody)} to ` +
`${stringifyRecipientList(req.recipients)} ` +
+17 -16
View File
@@ -24,6 +24,7 @@ limitations under the License.
import Promise from 'bluebird';
const logger = require("../../logger");
const utils = require("../../utils");
const olmlib = require("../olmlib");
const base = require("./base");
@@ -65,7 +66,7 @@ OutboundSessionInfo.prototype.needsRotation = function(
if (this.useCount >= rotationPeriodMsgs ||
sessionLifetime >= rotationPeriodMs
) {
console.log(
logger.log(
"Rotating megolm session after " + this.useCount +
" messages, " + sessionLifetime + "ms",
);
@@ -103,7 +104,7 @@ OutboundSessionInfo.prototype.sharedWithTooManyDevices = function(
}
if (!devicesInRoom.hasOwnProperty(userId)) {
console.log("Starting new session because we shared with " + userId);
logger.log("Starting new session because we shared with " + userId);
return true;
}
@@ -113,7 +114,7 @@ OutboundSessionInfo.prototype.sharedWithTooManyDevices = function(
}
if (!devicesInRoom[userId].hasOwnProperty(deviceId)) {
console.log(
logger.log(
"Starting new session because we shared with " +
userId + ":" + deviceId,
);
@@ -182,7 +183,7 @@ MegolmEncryption.prototype._ensureOutboundSession = function(devicesInRoom) {
if (session && session.needsRotation(self._sessionRotationPeriodMsgs,
self._sessionRotationPeriodMs)
) {
console.log("Starting new megolm session because we need to rotate.");
logger.log("Starting new megolm session because we need to rotate.");
session = null;
}
@@ -192,7 +193,7 @@ MegolmEncryption.prototype._ensureOutboundSession = function(devicesInRoom) {
}
if (!session) {
console.log(`Starting new megolm session for room ${self._roomId}`);
logger.log(`Starting new megolm session for room ${self._roomId}`);
session = await self._prepareNewSession();
}
@@ -319,7 +320,7 @@ MegolmEncryption.prototype._splitUserDeviceMap = function(
continue;
}
console.log(
logger.log(
"share keys with device " + userId + ":" + deviceId,
);
@@ -441,10 +442,10 @@ MegolmEncryption.prototype._shareKeyWithDevices = async function(session, device
await this._encryptAndSendKeysToDevices(
session, key.chain_index, userDeviceMaps[i], payload,
);
console.log(`Completed megolm keyshare in ${this._roomId} `
logger.log(`Completed megolm keyshare in ${this._roomId} `
+ `(slice ${i + 1}/${userDeviceMaps.length})`);
} catch (e) {
console.log(`megolm keyshare in ${this._roomId} `
logger.log(`megolm keyshare in ${this._roomId} `
+ `(slice ${i + 1}/${userDeviceMaps.length}) failed`);
throw e;
@@ -463,7 +464,7 @@ MegolmEncryption.prototype._shareKeyWithDevices = async function(session, device
*/
MegolmEncryption.prototype.encryptMessage = function(room, eventType, content) {
const self = this;
console.log(`Starting to encrypt event for ${this._roomId}`);
logger.log(`Starting to encrypt event for ${this._roomId}`);
return this._getDevicesInRoom(room).then(function(devicesInRoom) {
// check if any of these devices are not yet known to the user.
@@ -782,12 +783,12 @@ MegolmDecryption.prototype.onRoomKeyEvent = function(event) {
!sessionId ||
!content.session_key
) {
console.error("key event is missing fields");
logger.error("key event is missing fields");
return;
}
if (!senderKey) {
console.error("key event has no sender key (not encrypted?)");
logger.error("key event has no sender key (not encrypted?)");
return;
}
@@ -804,13 +805,13 @@ MegolmDecryption.prototype.onRoomKeyEvent = function(event) {
senderKey = content.sender_key;
if (!senderKey) {
console.error("forwarded_room_key event is missing sender_key field");
logger.error("forwarded_room_key event is missing sender_key field");
return;
}
const ed25519Key = content.sender_claimed_ed25519_key;
if (!ed25519Key) {
console.error(
logger.error(
`forwarded_room_key_event is missing sender_claimed_ed25519_key field`,
);
return;
@@ -823,7 +824,7 @@ MegolmDecryption.prototype.onRoomKeyEvent = function(event) {
keysClaimed = event.getKeysClaimed();
}
console.log(`Adding key for megolm session ${senderKey}|${sessionId}`);
logger.log(`Adding key for megolm session ${senderKey}|${sessionId}`);
this._olmDevice.addInboundGroupSession(
content.room_id, senderKey, forwardingKeyChain, sessionId,
content.session_key, keysClaimed,
@@ -840,7 +841,7 @@ MegolmDecryption.prototype.onRoomKeyEvent = function(event) {
// have another go at decrypting events sent with this session.
this._retryDecryption(senderKey, sessionId);
}).catch((e) => {
console.error(`Error handling m.room_key_event: ${e}`);
logger.error(`Error handling m.room_key_event: ${e}`);
});
};
@@ -882,7 +883,7 @@ MegolmDecryption.prototype.shareKeysWithDevice = function(keyRequest) {
return null;
}
console.log(
logger.log(
"sharing keys for session " + body.sender_key + "|"
+ body.session_id + " with device "
+ userId + ":" + deviceId,
+3 -2
View File
@@ -22,6 +22,7 @@ limitations under the License.
*/
import Promise from 'bluebird';
const logger = require("../../logger");
const utils = require("../../utils");
const olmlib = require("../olmlib");
const DeviceInfo = require("../deviceinfo");
@@ -273,7 +274,7 @@ OlmDecryption.prototype._decryptMessage = async function(
const payload = await this._olmDevice.decryptMessage(
theirDeviceIdentityKey, sessionId, message.type, message.body,
);
console.log(
logger.log(
"Decrypted Olm message from " + theirDeviceIdentityKey +
" with session " + sessionId,
);
@@ -328,7 +329,7 @@ OlmDecryption.prototype._decryptMessage = async function(
);
}
console.log(
logger.log(
"created new inbound Olm session ID " +
res.session_id + " with " + theirDeviceIdentityKey,
);
+34 -29
View File
@@ -25,6 +25,7 @@ const anotherjson = require('another-json');
import Promise from 'bluebird';
import {EventEmitter} from 'events';
const logger = require("../logger");
const utils = require("../utils");
const OlmDevice = require("./OlmDevice");
const olmlib = require("./olmlib");
@@ -36,6 +37,10 @@ const DeviceList = require('./DeviceList').default;
import OutgoingRoomKeyRequestManager from './OutgoingRoomKeyRequestManager';
import IndexedDBCryptoStore from './store/indexeddb-crypto-store';
export function isCryptoAvailable() {
return Boolean(global.Olm);
}
/**
* Cryptography bits
*
@@ -62,7 +67,7 @@ import IndexedDBCryptoStore from './store/indexeddb-crypto-store';
*
* @param {RoomList} roomList An initialised RoomList object
*/
function Crypto(baseApis, sessionStore, userId, deviceId,
export default function Crypto(baseApis, sessionStore, userId, deviceId,
clientStore, cryptoStore, roomList) {
this._baseApis = baseApis;
this._sessionStore = sessionStore;
@@ -124,6 +129,8 @@ utils.inherits(Crypto, EventEmitter);
* Returns a promise which resolves once the crypto module is ready for use.
*/
Crypto.prototype.init = async function() {
await global.Olm.init();
const sessionStoreHasAccount = Boolean(this._sessionStore.getEndToEndAccount());
let cryptoStoreHasAccount;
await this._cryptoStore.doTxn(
@@ -196,7 +203,7 @@ Crypto.prototype.registerEventHandlers = function(eventEmitter) {
try {
crypto._onRoomMembership(event, member, oldMembership);
} catch (e) {
console.error("Error handling membership change:", e);
logger.error("Error handling membership change:", e);
}
});
@@ -214,6 +221,7 @@ Crypto.prototype.start = function() {
/** Stop background processes related to crypto */
Crypto.prototype.stop = function() {
this._outgoingRoomKeyRequestManager.stop();
this._deviceList.stop();
};
/**
@@ -381,7 +389,7 @@ function _maybeUploadOneTimeKeys(crypto) {
// create any more keys.
return uploadLoop(keyCount);
}).catch((e) => {
console.error("Error uploading one-time keys", e.stack || e);
logger.error("Error uploading one-time keys", e.stack || e);
}).finally(() => {
// reset _oneTimeKeyCount to prevent start uploading based on old data.
// it will be set again on the next /sync-response
@@ -606,13 +614,13 @@ Crypto.prototype.getEventSenderDeviceInfo = function(event) {
const claimedKey = event.getClaimedEd25519Key();
if (!claimedKey) {
console.warn("Event " + event.getId() + " claims no ed25519 key: " +
logger.warn("Event " + event.getId() + " claims no ed25519 key: " +
"cannot verify sending device");
return null;
}
if (claimedKey !== device.getFingerprint()) {
console.warn(
logger.warn(
"Event " + event.getId() + " claims ed25519 key " + claimedKey +
"but sender device has key " + device.getFingerprint());
return null;
@@ -658,7 +666,7 @@ Crypto.prototype.setRoomEncryption = async function(roomId, config, inhibitDevic
const existingConfig = this._roomList.getRoomEncryption(roomId);
if (existingConfig) {
if (JSON.stringify(existingConfig) != JSON.stringify(config)) {
console.error("Ignoring m.room.encryption event which requests " +
logger.error("Ignoring m.room.encryption event which requests " +
"a change of config in " + roomId);
return;
}
@@ -705,7 +713,7 @@ Crypto.prototype.setRoomEncryption = async function(roomId, config, inhibitDevic
}
if (!this._lazyLoadMembers) {
console.log("Enabling encryption in " + roomId + "; " +
logger.log("Enabling encryption in " + roomId + "; " +
"starting to track device lists for all users therein");
await this.trackRoomDevices(roomId);
@@ -717,7 +725,7 @@ Crypto.prototype.setRoomEncryption = async function(roomId, config, inhibitDevic
this._deviceList.refreshOutdatedDeviceLists();
}
} else {
console.log("Enabling encryption in " + roomId);
logger.log("Enabling encryption in " + roomId);
}
};
@@ -738,7 +746,7 @@ Crypto.prototype.trackRoomDevices = function(roomId) {
if (!room) {
throw new Error(`Unable to start tracking devices in unknown room ${roomId}`);
}
console.log(`Starting to track devices for room ${roomId} ...`);
logger.log(`Starting to track devices for room ${roomId} ...`);
const members = await room.getEncryptionTargetMembers();
members.forEach((m) => {
this._deviceList.startTrackingDeviceList(m.userId);
@@ -834,7 +842,7 @@ Crypto.prototype.importRoomKeys = function(keys) {
return Promise.map(
keys, (key) => {
if (!key.room_id || !key.algorithm) {
console.warn("ignoring room key entry with missing fields", key);
logger.warn("ignoring room key entry with missing fields", key);
return null;
}
@@ -963,7 +971,7 @@ Crypto.prototype.requestRoomKey = function(requestBody, recipients) {
requestBody, recipients,
).catch((e) => {
// this normally means we couldn't talk to the store
console.error(
logger.error(
'Error requesting key for event', e,
);
}).done();
@@ -980,7 +988,7 @@ Crypto.prototype.requestRoomKey = function(requestBody, recipients) {
Crypto.prototype.cancelRoomKeyRequest = function(requestBody, andResend) {
this._outgoingRoomKeyRequestManager.cancelRoomKeyRequest(requestBody, andResend)
.catch((e) => {
console.warn("Error clearing pending room key requests", e);
logger.warn("Error clearing pending room key requests", e);
}).done();
};
@@ -998,7 +1006,7 @@ Crypto.prototype.onCryptoEvent = async function(event) {
// finished processing the sync, in onSyncCompleted.
await this.setRoomEncryption(roomId, content, true);
} catch (e) {
console.error("Error configuring encryption in room " + roomId +
logger.error("Error configuring encryption in room " + roomId +
":", e);
}
};
@@ -1014,7 +1022,7 @@ Crypto.prototype.onSyncWillProcess = async function(syncData) {
// scratch, so mark everything as untracked. onCryptoEvent will
// be called for all e2e rooms during the processing of the sync,
// at which point we'll start tracking all the users of that room.
console.log("Initial sync performed - resetting device tracking state");
logger.log("Initial sync performed - resetting device tracking state");
this._deviceList.stopTrackingAllDeviceLists();
this._roomDeviceTrackingState = {};
}
@@ -1132,7 +1140,7 @@ Crypto.prototype._onToDeviceEvent = function(event) {
});
}
} catch (e) {
console.error("Error handling toDeviceEvent:", e);
logger.error("Error handling toDeviceEvent:", e);
}
};
@@ -1146,7 +1154,7 @@ Crypto.prototype._onRoomKeyEvent = function(event) {
const content = event.getContent();
if (!content.room_id || !content.algorithm) {
console.error("key event is missing fields");
logger.error("key event is missing fields");
return;
}
@@ -1184,12 +1192,12 @@ Crypto.prototype._onRoomMembership = function(event, member, oldMembership) {
// by calling _trackRoomDevices
if (this._roomDeviceTrackingState[roomId]) {
if (member.membership == 'join') {
console.log('Join event for ' + member.userId + ' in ' + roomId);
logger.log('Join event for ' + member.userId + ' in ' + roomId);
// make sure we are tracking the deviceList for this user
this._deviceList.startTrackingDeviceList(member.userId);
} else if (member.membership == 'invite' &&
this._clientStore.getRoom(roomId).shouldEncryptForInvitedMembers()) {
console.log('Invite event for ' + member.userId + ' in ' + roomId);
logger.log('Invite event for ' + member.userId + ' in ' + roomId);
this._deviceList.startTrackingDeviceList(member.userId);
}
}
@@ -1256,7 +1264,7 @@ Crypto.prototype._processReceivedRoomKeyRequests = async function() {
this._processReceivedRoomKeyRequestCancellation(cancellation),
);
} catch (e) {
console.error(`Error processing room key requsts: ${e}`);
logger.error(`Error processing room key requsts: ${e}`);
} finally {
this._processingRoomKeyRequests = false;
}
@@ -1275,13 +1283,13 @@ Crypto.prototype._processReceivedRoomKeyRequest = async function(req) {
const roomId = body.room_id;
const alg = body.algorithm;
console.log(`m.room_key_request from ${userId}:${deviceId}` +
logger.log(`m.room_key_request from ${userId}:${deviceId}` +
` for ${roomId} / ${body.session_id} (id ${req.requestId})`);
if (userId !== this._userId) {
// TODO: determine if we sent this device the keys already: in
// which case we can do so again.
console.log("Ignoring room key request from other user for now");
logger.log("Ignoring room key request from other user for now");
return;
}
@@ -1291,18 +1299,18 @@ Crypto.prototype._processReceivedRoomKeyRequest = async function(req) {
// if we don't have a decryptor for this room/alg, we don't have
// the keys for the requested events, and can drop the requests.
if (!this._roomDecryptors[roomId]) {
console.log(`room key request for unencrypted room ${roomId}`);
logger.log(`room key request for unencrypted room ${roomId}`);
return;
}
const decryptor = this._roomDecryptors[roomId][alg];
if (!decryptor) {
console.log(`room key request for unknown alg ${alg} in room ${roomId}`);
logger.log(`room key request for unknown alg ${alg} in room ${roomId}`);
return;
}
if (!await decryptor.hasKeysForKeyRequest(req)) {
console.log(
logger.log(
`room key request for unknown session ${roomId} / ` +
body.session_id,
);
@@ -1316,7 +1324,7 @@ Crypto.prototype._processReceivedRoomKeyRequest = async function(req) {
// if the device is is verified already, share the keys
const device = this._deviceList.getStoredDevice(userId, deviceId);
if (device && device.isVerified()) {
console.log('device is already verified: sharing keys');
logger.log('device is already verified: sharing keys');
req.share();
return;
}
@@ -1333,7 +1341,7 @@ Crypto.prototype._processReceivedRoomKeyRequest = async function(req) {
Crypto.prototype._processReceivedRoomKeyRequestCancellation = async function(
cancellation,
) {
console.log(
logger.log(
`m.room_key_request cancellation for ${cancellation.userId}:` +
`${cancellation.deviceId} (id ${cancellation.requestId})`,
);
@@ -1518,6 +1526,3 @@ class IncomingRoomKeyRequestCancellation {
* @event module:client~MatrixClient#"crypto.warning"
* @param {string} type One of the strings listed above
*/
/** */
module.exports = Crypto;
+6 -5
View File
@@ -23,6 +23,7 @@ limitations under the License.
import Promise from 'bluebird';
const anotherjson = require('another-json');
const logger = require("../logger");
const utils = require("../utils");
/**
@@ -65,7 +66,7 @@ module.exports.encryptMessageForDevice = async function(
return;
}
console.log(
logger.log(
"Using sessionid " + sessionId + " for device " +
recipientUserId + ":" + recipientDevice.deviceId,
);
@@ -190,7 +191,7 @@ module.exports.ensureOlmSessionsForDevices = async function(
}
if (!oneTimeKey) {
console.warn(
logger.warn(
"No one-time keys (alg=" + oneTimeKeyAlgorithm +
") for device " + userId + ":" + deviceId,
);
@@ -219,7 +220,7 @@ async function _verifyKeyAndStartSession(olmDevice, oneTimeKey, userId, deviceIn
deviceInfo.getFingerprint(),
);
} catch (e) {
console.error(
logger.error(
"Unable to verify signature on one-time key for device " +
userId + ":" + deviceId + ":", e,
);
@@ -233,12 +234,12 @@ async function _verifyKeyAndStartSession(olmDevice, oneTimeKey, userId, deviceIn
);
} catch (e) {
// possibly a bad key
console.error("Error starting session with device " +
logger.error("Error starting session with device " +
userId + ":" + deviceId + ": " + e);
return null;
}
console.log("Started new sessionid " + sid +
logger.log("Started new sessionid " + sid +
" for device " + userId + ":" + deviceId);
return sid;
}
@@ -16,6 +16,8 @@ limitations under the License.
*/
import Promise from 'bluebird';
import logger from '../../logger';
import utils from '../../utils';
export const VERSION = 6;
@@ -38,7 +40,7 @@ export class Backend {
// attempts to delete the database will block (and subsequent
// attempts to re-create it will also block).
db.onversionchange = (ev) => {
console.log(`versionchange for indexeddb ${this._dbName}: closing`);
logger.log(`versionchange for indexeddb ${this._dbName}: closing`);
db.close();
};
}
@@ -64,7 +66,7 @@ export class Backend {
this._getOutgoingRoomKeyRequest(txn, requestBody, (existing) => {
if (existing) {
// this entry matches the request - return it.
console.log(
logger.log(
`already have key request outstanding for ` +
`${requestBody.room_id} / ${requestBody.session_id}: ` +
`not sending another`,
@@ -75,7 +77,7 @@ export class Backend {
// we got to the end of the list without finding a match
// - add the new request.
console.log(
logger.log(
`enqueueing key request for ${requestBody.room_id} / ` +
requestBody.session_id,
);
@@ -226,7 +228,7 @@ export class Backend {
}
const data = cursor.value;
if (data.state != expectedState) {
console.warn(
logger.warn(
`Cannot update room key request from ${expectedState} ` +
`as it was already updated to ${data.state}`,
);
@@ -264,7 +266,7 @@ export class Backend {
}
const data = cursor.value;
if (data.state != expectedState) {
console.warn(
logger.warn(
`Cannot delete room key request in state ${data.state} `
+ `(expected ${expectedState})`,
);
@@ -400,7 +402,7 @@ export class Backend {
ev.stopPropagation();
// ...and this stops it from aborting the transaction
ev.preventDefault();
console.log(
logger.log(
"Ignoring duplicate inbound group session: " +
senderCurve25519Key + " / " + sessionId,
);
@@ -471,7 +473,7 @@ export class Backend {
}
export function upgradeDatabase(db, oldVersion) {
console.log(
logger.log(
`Upgrading IndexedDBCryptoStore from version ${oldVersion}`
+ ` to ${VERSION}`,
);
+25 -14
View File
@@ -17,9 +17,11 @@ limitations under the License.
import Promise from 'bluebird';
import logger from '../../logger';
import LocalStorageCryptoStore from './localStorage-crypto-store';
import MemoryCryptoStore from './memory-crypto-store';
import * as IndexedDBCryptoStoreBackend from './indexeddb-crypto-store-backend';
import {InvalidCryptoStoreError} from '../../errors';
/**
* Internal module. indexeddb storage for e2e.
@@ -64,7 +66,7 @@ export default class IndexedDBCryptoStore {
return;
}
console.log(`connecting to indexeddb ${this._dbName}`);
logger.log(`connecting to indexeddb ${this._dbName}`);
const req = this._indexedDB.open(
this._dbName, IndexedDBCryptoStoreBackend.VERSION,
@@ -77,7 +79,7 @@ export default class IndexedDBCryptoStore {
};
req.onblocked = () => {
console.log(
logger.log(
`can't yet open IndexedDBCryptoStore because it is open elsewhere`,
);
};
@@ -89,7 +91,7 @@ export default class IndexedDBCryptoStore {
req.onsuccess = (r) => {
const db = r.target.result;
console.log(`connected to indexeddb ${this._dbName}`);
logger.log(`connected to indexeddb ${this._dbName}`);
resolve(new IndexedDBCryptoStoreBackend.Backend(db));
};
}).then((backend) => {
@@ -106,16 +108,25 @@ export default class IndexedDBCryptoStore {
},
);
}).catch((e) => {
console.warn(
if (e.name === 'VersionError') {
logger.warn("Crypto DB is too new for us to use!", e);
// don't fall back to a different store: the user has crypto data
// in this db so we should use it or nothing at all.
throw new InvalidCryptoStoreError(InvalidCryptoStoreError.TOO_NEW);
}
logger.warn(
`unable to connect to indexeddb ${this._dbName}` +
`: falling back to localStorage store: ${e}`,
);
return new LocalStorageCryptoStore(global.localStorage);
}).catch((e) => {
console.warn(
`unable to open localStorage: falling back to in-memory store: ${e}`,
);
return new MemoryCryptoStore();
try {
return new LocalStorageCryptoStore(global.localStorage);
} catch (e) {
logger.warn(
`unable to open localStorage: falling back to in-memory store: ${e}`,
);
return new MemoryCryptoStore();
}
});
return this._backendPromise;
@@ -133,11 +144,11 @@ export default class IndexedDBCryptoStore {
return;
}
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 IndexedDBCryptoStore because it is open elsewhere`,
);
};
@@ -147,14 +158,14 @@ export default class IndexedDBCryptoStore {
};
req.onsuccess = () => {
console.log(`Removed indexeddb instance: ${this._dbName}`);
logger.log(`Removed indexeddb instance: ${this._dbName}`);
resolve();
};
}).catch((e) => {
// in firefox, with indexedDB disabled, this fails with a
// DOMError. We treat this as non-fatal, so that people can
// still use the app.
console.warn(`unable to delete IndexedDBCryptoStore: ${e}`);
logger.warn(`unable to delete IndexedDBCryptoStore: ${e}`);
});
}
@@ -15,6 +15,8 @@ limitations under the License.
*/
import Promise from 'bluebird';
import logger from '../../logger';
import MemoryCryptoStore from './memory-crypto-store.js';
/**
@@ -199,8 +201,8 @@ function getJsonItem(store, key) {
// JSON.parse(null) === null, so this returns null.
return JSON.parse(store.getItem(key));
} catch (e) {
console.log("Error: Failed to get key %s: %s", key, e.stack || e);
console.log(e.stack);
logger.log("Error: Failed to get key %s: %s", key, e.stack || e);
logger.log(e.stack);
}
return null;
}
+5 -4
View File
@@ -17,6 +17,7 @@ limitations under the License.
import Promise from 'bluebird';
import logger from '../../logger';
import utils from '../../utils';
/**
@@ -71,7 +72,7 @@ export default class MemoryCryptoStore {
if (existing) {
// this entry matches the request - return it.
console.log(
logger.log(
`already have key request outstanding for ` +
`${requestBody.room_id} / ${requestBody.session_id}: ` +
`not sending another`,
@@ -81,7 +82,7 @@ export default class MemoryCryptoStore {
// we got to the end of the list without finding a match
// - add the new request.
console.log(
logger.log(
`enqueueing key request for ${requestBody.room_id} / ` +
requestBody.session_id,
);
@@ -163,7 +164,7 @@ export default class MemoryCryptoStore {
}
if (req.state != expectedState) {
console.warn(
logger.warn(
`Cannot update room key request from ${expectedState} ` +
`as it was already updated to ${req.state}`,
);
@@ -194,7 +195,7 @@ export default class MemoryCryptoStore {
}
if (req.state != expectedState) {
console.warn(
logger.warn(
`Cannot delete room key request in state ${req.state} `
+ `(expected ${expectedState})`,
);
+23 -2
View File
@@ -1,6 +1,6 @@
// can't just do InvalidStoreError extends Error
// because of http://babeljs.io/docs/usage/caveats/#classes
function InvalidStoreError(reason, value) {
export function InvalidStoreError(reason, value) {
const message = `Store is invalid because ${reason}, ` +
`please stop the client, delete all data and start the client again`;
const instance = Reflect.construct(Error, [message]);
@@ -22,4 +22,25 @@ InvalidStoreError.prototype = Object.create(Error.prototype, {
});
Reflect.setPrototypeOf(InvalidStoreError, Error);
module.exports.InvalidStoreError = InvalidStoreError;
export function InvalidCryptoStoreError(reason) {
const message = `Crypto store is invalid because ${reason}, ` +
`please stop the client, delete all data and start the client again`;
const instance = Reflect.construct(Error, [message]);
Reflect.setPrototypeOf(instance, Reflect.getPrototypeOf(this));
instance.reason = reason;
instance.name = 'InvalidCryptoStoreError';
return instance;
}
InvalidCryptoStoreError.TOO_NEW = "TOO_NEW";
InvalidCryptoStoreError.prototype = Object.create(Error.prototype, {
constructor: {
value: Error,
enumerable: false,
writable: true,
configurable: true,
},
});
Reflect.setPrototypeOf(InvalidCryptoStoreError, Error);
+2
View File
@@ -752,6 +752,8 @@ module.exports.MatrixHttpApi.prototype = {
method: method,
withCredentials: false,
qs: queryParams,
qsStringifyOptions: opts.qsStringifyOptions,
useQuerystring: true,
body: data,
json: false,
timeout: localTimeoutMs,
+36
View File
@@ -0,0 +1,36 @@
/*
Copyright 2018 André Jaenisch
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.
*/
/**
* @module logger
*/
const log = require("loglevel");
// This is to demonstrate, that you can use any namespace you want.
// Namespaces allow you to turn on/off the logging for specific parts of the
// application.
// An idea would be to control this via an environment variable (on Node.js).
// See https://www.npmjs.com/package/debug to see how this could be implemented
// Part of #332 is introducing a logging library in the first place.
const DEFAULT_NAME_SPACE = "matrix";
const logger = log.getLogger(DEFAULT_NAME_SPACE);
logger.setLevel(log.levels.DEBUG);
/**
* Drop-in replacement for <code>console</code> using {@link https://www.npmjs.com/package/loglevel|loglevel}.
* Can be tailored down to specific use cases if needed.
*/
module.exports = logger;
+4
View File
@@ -999,6 +999,10 @@ Room.prototype.addPendingEvent = function(event, txnId) {
this._txnToEvent[txnId] = event;
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");
event.status = EventStatus.NOT_SENT;
}
this._pendingEventList.push(event);
} else {
for (let i = 0; i < this._timelineSets.length; i++) {
+1 -1
View File
@@ -516,7 +516,7 @@ SyncApi.prototype.sync = function() {
console.warn("InvalidStoreError: store is not usable: stopping sync.");
return;
}
if (this.opts.lazyLoadMembers && this._crypto) {
if (this.opts.lazyLoadMembers && this.opts.crypto) {
this.opts.crypto.enableLazyLoading();
}
await this.client._storeClientOptions();
+1 -1
View File
@@ -5,7 +5,7 @@ set -ex
npm run lint
# install Olm so that we can run the crypto tests.
npm install https://matrix.org/packages/npm/olm/olm-2.2.2.tgz
npm install https://matrix.org/packages/npm/olm/olm-3.0.0.tgz
npm run test