Compare commits

...

1484 Commits

Author SHA1 Message Date
RiotRobot 1a0bdb0f98 v15.3.0 2021-12-20 13:58:07 +00:00
RiotRobot e870bebd3d Prepare changelog for v15.3.0 2021-12-20 13:58:07 +00:00
RiotRobot 22a98b3e4f v15.3.0-rc.1 2021-12-14 14:37:58 +00:00
RiotRobot 934a0e8943 Prepare changelog for v15.3.0-rc.1 2021-12-14 14:37:58 +00:00
Michael Telatynski aeec4aa4a8 Update typescript-eslint plugin & parser (#2064) 2021-12-13 23:28:54 +00:00
Michael Telatynski 169b6b5572 Filter out falsey opts in /relations API hits (#2059) 2021-12-13 15:38:03 +00:00
RiotRobot 6244d77d44 Merge branch 'master' into develop 2021-12-13 15:22:07 +00:00
RiotRobot f4839a3b4f v15.2.1 2021-12-13 15:17:37 +00:00
RiotRobot 4b21b67a45 Prepare changelog for v15.2.1 2021-12-13 15:17:37 +00:00
David Baker 799a83a115 Update olm to 3.2.8 (#2062) 2021-12-13 14:59:03 +00:00
Michael Telatynski f3ebb2a314 Update Typescript to 4.5 (#2060) 2021-12-13 11:22:50 +00:00
Michael Telatynski c0fbed914e Update olm in yarn.lock (#2058) 2021-12-10 10:49:35 +00:00
Hubert Chathi dd8c157bb9 Improve fallback key behaviour (#2037) 2021-12-09 19:00:23 -05:00
Travis Ralston 8bd2d640f2 Update eslint 2021-12-09 16:01:07 -07:00
Aaron R 80aaa6c32b Fix imports to work with new lint rules (#2003)
* Add eslint-plugin-import

Signed-off-by: Aaron Raimist <aaron@raim.ist>

* Autofix

Signed-off-by: Aaron Raimist <aaron@raim.ist>

* Manual fix

Signed-off-by: Aaron Raimist <aaron@raim.ist>
2021-12-09 15:57:43 -07:00
Michael Telatynski 4e9fe8f53f Fix types (#2056) 2021-12-09 15:44:07 +00:00
Ajay Bura f926a2f777 Fix paginateEventTimeline resolve to boolean (#2054)
* Fix paginateEventTimeline resolve to boolean

Earlier paginateEventTimeline used to resolve to  chunk instead of returning boolean. Now it return boolean as specified in doc.

* added type
2021-12-09 20:00:55 +05:30
Michael Telatynski f8097221e6 Improve typing (#2055) 2021-12-09 14:22:58 +00:00
Callum Brown 95e7a76ba9 Finish adding registration token UIAA type (#2048)
Signed-off-by: Callum Brown <callum@calcuode.com>
2021-12-08 19:38:22 -07:00
Germain 72bc13eb39 Allow to omit optional params for /relations calls (#2053) 2021-12-08 08:23:53 +00:00
Germain 2206b80e65 Threads notifications after app startup (#2043) 2021-12-07 10:58:34 +00:00
Germain 39a8399977 Add new room event filter fields (#2051) 2021-12-07 09:42:52 +00:00
RiotRobot b7247fcedc Resetting package fields for development 2021-12-06 15:14:16 +00:00
RiotRobot e4494707fa Merge branch 'master' into develop 2021-12-06 15:14:16 +00:00
RiotRobot 45b7cab203 v15.2.0 2021-12-06 15:10:51 +00:00
RiotRobot 4dfc3b9dbb Prepare changelog for v15.2.0 2021-12-06 15:10:50 +00:00
Hugh Nimmo-Smith 15d05cd92f Fix incorrect MSC3089 typings and add null checks (#2049)
* Fix MSC3089TreeSpace typings to match actual code

* Implement strict null checks to resolve TS strictNullChecks=true issues
2021-12-06 10:54:43 +00:00
skyka13711 ba1b1cc6fa fix exports (#2047) 2021-12-02 19:40:10 -07:00
Michael Telatynski b716cde9b5 Add method to fetch /account/whoami (#2046) 2021-12-02 13:43:15 +00:00
RiotRobot 46a0645865 v15.2.0-rc.1 2021-11-30 18:16:24 +00:00
RiotRobot 2b30f45f60 Prepare changelog for v15.2.0-rc.1 2021-11-30 18:16:23 +00:00
J. Ryan Stinnett 87b920698f Upgrade allchange to 1.0.6 (#2042) 2021-11-30 17:55:38 +00:00
Germain 4f4811e1d9 Emit thread update after event decryption (#2040) 2021-11-30 14:40:59 +00:00
Hugh Nimmo-Smith db9936e07c Standardise content type handling in MSC3089 createFile() and createNewVersion() (#2014)
* Provide cross platform compatible versions of createFile() and createNewVersion()

The exist implementations are deprecated as they only work in a browser and support a different type of contents from MatrixClient.uploadContent()

* Fix MSC3089 content upload meta data in NodeJS runtime

* Break unstable createFile() and createNewVersion() instead of deprecating

Test using NodeJS types instead of mocked browser Blob

* chore: remove incorrect comment
2021-11-30 09:02:41 +00:00
Hugh Nimmo-Smith 7dcee2eb40 Implementation of deriveKey() for NodeJS (#2021)
Based on approach used by aes.ts
2021-11-30 09:02:26 +00:00
skyka13711 6b34ea6fe5 Exporting missing types (#2023)
* fix types export

* fix lint

* index.ts fix exports

* revert yarn.lock

Co-authored-by: Alexey Avramenko <2822698@gmail.com>
Co-authored-by: nikita <nikita@42px.ru>
2021-11-29 19:54:08 -07:00
Germain b33b01df0f Handle remote echo when creating a thread (#2038) 2021-11-25 08:27:13 +00:00
Germain 1c895432ed Fix backwards compatibility for redactEvent (#2039) 2021-11-24 15:42:10 +00:00
Germain ddd6a05198 Make local echo work for threads (#2026) 2021-11-24 08:19:17 +00:00
Germain 0ccde7807f Comprehensive events emitter typing (#2034) 2021-11-23 15:16:35 +00:00
Will Hunt 9f97992196 getStateEvent should return any (#2032)
* getStateEvent returns any

getStateEvent returns the content of an event, not the whole state event as per https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-state-eventtype-statekey

* Make the return type Record<string, any>

Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>

Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2021-11-23 13:54:54 +00:00
Germain 67b8da719f Add a flag to track user participation in a thread (#2030) 2021-11-23 08:20:27 +00:00
Šimon Brandner 04fad564f7 Fix call upgrades (#2024)
* Init call feeds with non-muted state

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>

* Improve CallFeed docs

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-11-22 18:17:35 -07:00
Germain aee698c285 Add KeyVerificationRequest msgType (#2033) 2021-11-22 17:08:24 +00:00
RiotRobot 55b489b17a Resetting package fields for development 2021-11-22 13:32:08 +00:00
RiotRobot c5d188c30a Merge branch 'master' into develop 2021-11-22 13:32:08 +00:00
RiotRobot 6fff3d6db5 v15.1.1 2021-11-22 13:28:39 +00:00
RiotRobot 8043d83921 Prepare changelog for v15.1.1 2021-11-22 13:28:39 +00:00
Michael Telatynski b2d83c1f80 Iterate type definitions (#2029) 2021-11-19 17:35:09 +00:00
Travis Ralston 1b91cd7037 Add optional force parameter when ensuring Olm sessions (#2027)
This is useful for debugging crypto where Element's `/discardsession` doesn't reset the Olm session.
2021-11-19 07:33:45 -07:00
skyka13711 0baf926c84 TimelineWindow fix load function signature (#2028) 2021-11-19 09:00:08 +00:00
Robert Long 763e25e031 Update sync state to error when aborting (#2025) 2021-11-18 12:16:57 -08:00
RiotRobot 861023b3f6 v15.1.1-rc.1 2021-11-17 13:52:47 +00:00
RiotRobot 1f5a83994b Prepare changelog for v15.1.1-rc.1 2021-11-17 13:52:47 +00:00
Dariusz Niemczyk af523522de Add LocalStorageErrorEventListener (#2019)
Add a way to listen to LocalStorage error events from element-web
and matrix-react-sdk in the same manner.

Related: https://github.com/vector-im/element-web/issues/18423
2021-11-15 18:08:20 +00:00
Dariusz Niemczyk c3a266b3e7 Implement TypedEventEmitter for better TS support (#2018)
We're using stringly typed events everywhere, this is the first step for
better typescript support with our event emitters before we replace it
with something much better for React support.
2021-11-15 14:47:21 +00:00
Callum Brown f41d815aa6 Add registration token UIA type (#2020) 2021-11-15 09:16:23 +00:00
Germain ad8a93dde8 Fix check supportExperimentalThreads (#2017) 2021-11-10 10:54:13 +00:00
Germain b07d44a6c0 Getter for last thread reply (#2015) 2021-11-09 14:46:48 +00:00
RiotRobot 1dc899ba6e Resetting package fields for development 2021-11-08 17:37:26 +00:00
RiotRobot 0b1e3edaff Merge branch 'master' into develop 2021-11-08 17:37:25 +00:00
RiotRobot 9fb4fed044 v15.1.0 2021-11-08 17:34:08 +00:00
RiotRobot 730b0b121d Prepare changelog for v15.1.0 2021-11-08 17:34:07 +00:00
Aaron R 9d9d9e2cfa Fix edit history being broken after editing an unencrypted event with an encrypted event (#2013) 2021-11-08 08:55:41 +00:00
Germain 43bc09f392 Copy relations to thread root in the thread timeline (#2012) 2021-11-05 14:16:45 +00:00
Germain 195498e9db Make events pagination responses parse threads (#2011) 2021-11-04 11:29:14 +00:00
Faye Duxovni 50332c4999 End authentication attempt immediately if we couldn't find an appropriate flow (#2008)
If `doRequest()` in `interactive-auth.ts` fails to obtain an appropriate authentication flow, it should return immediately after rejecting the promise.  If it continues, it'll attempt to check `chosenFlow.stages`, which will cause an error because `chosenFlow` is `null`.  This was breaking the interactive auth spec tests with Node 16.
2021-11-02 10:40:46 -04:00
RiotRobot 9e46646b16 v15.1.0-rc.1 2021-11-02 14:09:01 +00:00
RiotRobot a74a03e414 Prepare changelog for v15.1.0-rc.1 2021-11-02 14:09:00 +00:00
David Baker fe8b9eca8e Update allchange to 1.0.5 (#2010) 2021-11-02 13:30:49 +00:00
Germain a7cc1ae630 Fetch thread root event if it's missing from the sync (#2009) 2021-11-02 11:56:43 +00:00
Šimon Brandner 14e008bbad Don't emit CallError when we fail to get screen-sharing stream (#2005)
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-10-28 16:23:06 +01:00
Travis Ralston 6a12c265cf PSFD-455: Try to set a sender on search result events if possible (#2004)
This is to ensure that search results have aesthetic information such as display name and avatar. Though the membership event won't be in context for when the event was sent, it'll at least be something better than a bare user ID.
2021-10-28 07:48:27 -06:00
Šimon Brandner c35cb57a79 Port some changes from group calls branch to develop (#2001)
* Add some useful getters

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>

Co-authored-by: Robert Long <robert@robertlong.me>

* Add removeLocalFeed()

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>

Co-authored-by: Robert Long <robert@robertlong.me>

* Don't updateStream() if they're the same

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>

Co-authored-by: Robert Long <robert@robertlong.me>

* Add isSpeaking()

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>

Co-authored-by: Robert Long <robert@robertlong.me>

* Improve speaking detection using history

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>

Co-authored-by: Robert Long <robert@robertlong.me>

* Make code for placing and answering calls more flexible

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>

Co-authored-by: Robert Long <robert@robertlong.me>

* Correctly log stream id

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>

* Remove mistaken parameter

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>

* Add a unit

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>

Co-authored-by: Robert Long <robert@robertlong.me>
2021-10-26 11:59:15 -07:00
Christian Paul 51c776f51e Correct TypeScript signature of client.sendCompleteEvent (#1997)
* Correct TypeScript signature of client.sendCompleteEvent

* Revert renaming txnId to txnIdOrCallback
2021-10-25 14:25:38 -06:00
Hubert Chathi 7ce0eb26d4 Fetch room membership from server rather than relying on stored data (#1998)
To work around the possibility that the persisted sync data may be out of date.
2021-10-25 10:29:46 -04:00
RiotRobot f0091fa811 Resetting package fields for development 2021-10-25 11:25:30 +01:00
RiotRobot 25c88bc986 Merge branch 'master' into develop 2021-10-25 11:25:29 +01:00
RiotRobot ab06f57965 v15.0.0 2021-10-25 11:22:22 +01:00
RiotRobot c46209a159 Prepare changelog for v15.0.0 2021-10-25 11:22:21 +01:00
Germain 0c47e27f9f Add explicit options to disable pending events (#1993) 2021-10-22 09:23:12 +01:00
Hubert Chathi 0385f265e8 Mark old verification methods as deprecated (#1994)
The old verification methods start a verification by sending an
`m.key.verification.start` message, rather than an `m.key.verification.request`
message.  This behaviour is deprecated in the
spec (https://github.com/matrix-org/matrix-doc/pull/3122), so these functions
should be deprecated too.
2021-10-21 16:10:13 -04:00
David Baker 59b3960a42 Strip direction override characters from display names (#1992)
Strip RLO and LRO characters from name and rawDisplayName so they
can safely be embedded into other text without messing up the text
ordering.

Fixes https://github.com/vector-im/element-web/issues/1712
2021-10-20 17:08:40 +01:00
Germain d5ab4ba2ef Update thread replies count to only include m.thread (#1991) 2021-10-20 16:49:54 +01:00
Travis Ralston f59b81f46b Update allchange (#1989) 2021-10-19 18:21:52 +01:00
Michael Telatynski 4c39ce8c96 Add method to fetch the MSC3266 Room Summary of a Room (#1988) 2021-10-19 16:13:29 +01:00
Germain Souquet 94ff0ea4cd Upgrade yarn dependencies 2021-10-19 11:24:53 +01:00
RiotRobot 526758a07f v15.0.0-rc.1 2021-10-19 10:50:42 +01:00
RiotRobot 9686fba81e Prepare changelog for v15.0.0-rc.1 2021-10-19 10:50:41 +01:00
Germain bbc547fd7f Merge pull request #1982 from matrix-org/gsouquet/thread-event-new 2021-10-15 14:32:19 +01:00
Germain 7d5dbeaf2d Merge pull request #1981 from matrix-org/gsouquet/threads-root-guard 2021-10-15 14:32:13 +01:00
Germain Souquet 8c19cf45e2 Dispatch a Thread.New event 2021-10-15 11:09:14 +01:00
Germain Souquet c9277de8ee Remove console statement 2021-10-15 10:31:43 +01:00
Germain Souquet b5baca51a6 Null-guard for thread root event not loaded yet 2021-10-15 10:22:32 +01:00
Germain fc800821f9 Merge pull request #1980 from matrix-org/gsouquet/threads-relations 2021-10-15 08:53:42 +01:00
Germain Souquet efbc46937f Null-guard for event that do not have a thread 2021-10-14 17:37:33 +01:00
Germain Souquet 9ceeb2d220 Delete UnstableValue and use hardcoded value for m.thread 2021-10-14 17:09:00 +01:00
Germain Souquet 7b89862ed0 Make threads use 'm.thread' relation 2021-10-14 16:56:48 +01:00
David Baker 6804e4290a Merge pull request #1972 from SimonBrandner/feature/answer-no-cam
Try to answer a call without video if we can't access the camera
2021-10-14 12:15:35 +01:00
David Baker 0a3d820fda Merge pull request #1943 from freaktechnik/develop
Fix `requestVerificationDM` with chronological `pendingEventOrdering`
2021-10-14 12:14:20 +01:00
Michael Telatynski e2a9c95ea8 Merge pull request #1974 from SimonBrandner/task/security-ts 2021-10-14 10:02:14 +01:00
Šimon Brandner 3aefc9f02e Add tests for falling back to answering with no video
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-10-14 08:46:36 +02:00
Šimon Brandner 0042cb5292 Fix importRoomKeys() definition
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-10-13 16:50:27 +02:00
Denis Kasak b288c97372 Merge pull request #1975 from matrix-org/dkasak/more-detailed-room-key-sharing-logging
More detailed logging when sharing room keys
2021-10-12 13:26:43 +00:00
Denis Kasak a0de1740a4 Add comma per review
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2021-10-12 13:23:22 +00:00
Denis Kasak 8e2e3018d8 Log device objects for existing/new devices when sharing room keys. 2021-10-12 13:48:41 +02:00
Denis Kasak 60e93024e7 Fix comment regarding marking blocked devices as notified. 2021-10-12 13:43:28 +02:00
Denis Kasak d89aa365f9 More detailed logging of blocked devices.
Separately log how many blocked devices there are in total and list them
out.

Then, log how many devices were notified because they were newly
blocked and list those out too.
2021-10-12 13:43:28 +02:00
Denis Kasak 4241263f2c Make log message regarding notifying unnotified failed devices clearer. 2021-10-12 13:43:26 +02:00
Denis Kasak b009f9c21b Log more clearly when we're sharing room keys with *new* Olm sessions. 2021-10-12 13:41:04 +02:00
Denis Kasak 04ccec6de3 Log which devices room keys were shared with. 2021-10-12 13:41:04 +02:00
RiotRobot e7b41fadd0 Merge branch 'master' into develop 2021-10-12 08:50:43 +01:00
RiotRobot 2dc1acef2e Resetting package fields for development 2021-10-12 08:36:13 +01:00
RiotRobot b977b629f4 Merge branch 'release-v14.0.1' 2021-10-12 08:35:42 +01:00
RiotRobot 6bbd493e20 v14.0.1 2021-10-12 08:29:30 +01:00
RiotRobot 38ad435af5 Prepare changelog for v14.0.1 2021-10-12 08:29:30 +01:00
RiotRobot 8f245af317 Merge branch 'master' into develop 2021-10-11 11:48:22 +01:00
RiotRobot 9b2bfbe7d0 v14.0.0 2021-10-11 11:44:54 +01:00
RiotRobot f69ea85e55 Prepare changelog for v14.0.0 2021-10-11 11:44:53 +01:00
Šimon Brandner 7559a10526 Make opts in importRoomKeys optional
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-10-10 08:36:11 +02:00
Šimon Brandner 68dbe959bb Add a logline
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-10-10 08:19:29 +02:00
Šimon Brandner 74a875aa23 Add MockMediaDeviceInfo
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-10-10 08:19:29 +02:00
Šimon Brandner 4b679c5056 Try to answer without video if we can't access it
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-10-10 08:19:22 +02:00
Šimon Brandner cb8a260b9c Improve handling when we don't have a camera
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-10-09 08:36:19 +02:00
Robert Long 7d7975b8bb Fix connecting to a call without a webcam
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-10-09 08:05:59 +02:00
Travis Ralston f12513da96 Merge pull request #1971 from matrix-org/travis/spam-log
Remove excess logging from getRoomUpgradeHistory()
2021-10-08 10:33:07 -06:00
Travis Ralston 785a3e3381 Remove excess logging from getRoomUpgradeHistory()
On large accounts this can now cause a massive amount of spam. It's not really providing any value in day-to-day debugging either.
2021-10-08 10:28:20 -06:00
RiotRobot f5fcc20840 v14.0.0-rc.2 2021-10-07 17:42:40 +01:00
RiotRobot 17e20c17b3 Prepare changelog for v14.0.0-rc.2 2021-10-07 17:42:40 +01:00
Michael Telatynski 39fd350ffe Merge pull request #1969 from matrix-org/t3chguy/cp/space-hierarchy 2021-10-06 16:51:32 +01:00
Michael Telatynski b4d100baff Tweak Room Hierarchy root visibility and add loading getter 2021-10-06 13:29:13 +01:00
Michael Telatynski 29bc83f4a7 Merge pull request #1968 from matrix-org/t3chguy/fix/19276 2021-10-06 13:27:12 +01:00
Michael Telatynski 13c8774d45 Tweak Room Hierarchy root visibility and add loading getter 2021-10-06 10:25:27 +01:00
Travis Ralston c9212e770d Merge pull request #1966 from Alexendoo/declaration-map
Enable TypeScript declaration maps
2021-10-05 13:39:47 -06:00
Germain 08aa7803e3 Merge pull request #1964 from SimonBrandner/feature/call-feed-opts 2021-10-04 15:02:49 +01:00
Alex Macleod 770858c255 Enable TypeScript declaration maps
This allows go-to-definition to reach the original .ts files for
consumers of the package. It emits .d.ts.map files alongside the regular
.d.ts files

e.g. in sdk.createClient go-to-definition on createClient will place the
cursor at the function in src/matrix.ts rather than inside a definition
file lib/matrix.d.ts

Signed-off-by: Alex Macleod <alex@macleod.io>
2021-10-04 14:36:50 +01:00
Germain Souquet c73bb7d408 Update dependencies 2021-10-04 12:30:14 +01:00
RiotRobot 15cd675354 v14.0.0-rc.1 2021-10-04 11:55:19 +01:00
RiotRobot e8137d3f88 Prepare changelog for v14.0.0-rc.1 2021-10-04 11:55:19 +01:00
Šimon Brandner c63abe9988 Use ICallFeedOpts in the CallFeed constructor
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-10-02 08:12:43 +02:00
Germain a7a08fd760 Merge pull request #1962 from matrix-org/gsouquet/fix-19229 2021-10-01 15:46:30 +01:00
Germain df51f95fbd Merge pull request #1963 from matrix-org/gsouquet/fix-19225 2021-10-01 12:11:35 +01:00
Germain Souquet a14cf1a339 Remove unused DuplicateStrategy 2021-10-01 12:07:16 +01:00
Germain Souquet 30758600f0 Prepend events to thread when fetching the reply chain 2021-10-01 10:49:46 +01:00
Germain 823242a93c Merge pull request #1959 from psrpinto/fix/joined-rooms-response 2021-09-30 17:54:53 +01:00
Martin Giger 482e3c4cb7 Skip waiting if already sent and abort on cancel 2021-09-30 16:58:08 +02:00
Germain Souquet 1dbd7158ad Prevent redactions to be sent as pending events
Co-authored-by: Dariusz Niemczyk <Palid@users.noreply.github.com>
2021-09-30 13:56:52 +01:00
Michael Telatynski 46b3f0babd Merge pull request #1958 from SimonBrandner/fix/call-length 2021-09-29 15:04:02 +01:00
Šimon Brandner b4bc554d7a Make sure to callLengthInterval only once
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-29 15:46:22 +02:00
Paulo Pinto 1485969493 Return IJoinedRoomsResponse from getJoinedRooms(), instead of string[]
Signed-off-by: Paulo Pinto <paulo.pinto@automattic.com>
2021-09-29 11:45:01 +01:00
Travis Ralston 92f7ddcf3e Merge pull request #1954 from SimonBrandner/task/src-ts
Changes for TS migration
2021-09-27 13:45:06 -06:00
Travis Ralston 90d480b4cf Merge pull request #1952 from matrix-org/travis/fsdk/versions
Implement file versioning for tree spaces
2021-09-27 10:04:22 -06:00
RiotRobot 2515d07c8f Resetting package fields for development 2021-09-27 14:23:47 +01:00
RiotRobot 7acb9416c2 Merge branch 'master' into develop 2021-09-27 14:23:47 +01:00
RiotRobot 095e3a8a88 v13.0.0 2021-09-27 14:20:00 +01:00
RiotRobot 92623a246a Prepare changelog for v13.0.0 2021-09-27 14:20:00 +01:00
Michael Telatynski 0c4212ca90 Merge pull request #1935 from matrix-org/t3chguy/fix/18969 2021-09-27 11:08:07 +01:00
Germain 9a06a05a75 Merge pull request #1953 from SimonBrandner/fix/audio-upgrade 2021-09-27 10:18:13 +01:00
Šimon Brandner f05a0615f7 Export IRequestMsisdnTokenResponse
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-27 09:45:07 +02:00
Šimon Brandner 6b93687ff0 Pass correct params to upgradeCall() to upgrade audio
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-26 13:10:00 +02:00
Travis Ralston 8d910d5e26 Merge pull request #1950 from SimonBrandner/feature/flexible-answer
Allow answering calls without audio/video
2021-09-25 23:39:20 -06:00
Šimon Brandner 9264050f41 Update src/webrtc/call.ts
Co-authored-by: Travis Ralston <travpc@gmail.com>
2021-09-26 07:26:08 +02:00
Travis Ralston eab0c54663 Appease the linter 2021-09-25 20:47:59 -06:00
Travis Ralston 82a254b7bd Implement file versioning for tree spaces
The diff isn't super clear on how this works, but the general idea is that the MSC3089Branches (files) now know which directory they came from, and the directories (MSC3089TreeSpace) can tell when files are triggering uploads referencing themselves so it can add all the replacement metadata onto the event.

There's a few challenges with how relations work in the js-sdk which has shaped the API surface exposed by this change. Specifically, there is a `getVersionHistory()` function instead of a function to get a certain prior version: the js-sdk doesn't track parent events in the relation structures so cannot determine what the event could have replaced. 

In order to trigger the built-in relations structures, we must trigger decryption with `emit: true`. This is so an internal listener in the relations system can pick up `Event.decrypted`.
2021-09-25 20:44:17 -06:00
Šimon Brandner 0f6a59ed98 Allow answering calls without audio/video
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-25 10:00:51 +02:00
Travis Ralston afb4682987 Merge pull request #1949 from SimonBrandner/fix/mic-state
Fix not returning new mic mute state
2021-09-25 01:14:11 -06:00
Šimon Brandner a18326519b Add missing return statement
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-25 08:26:13 +02:00
Germain b033540f95 Merge pull request #1948 from matrix-org/gsouquet/fix-sync-partitioning 2021-09-24 15:43:27 +01:00
Germain Souquet ff529d733d Fix event partitioning from non threading ready clients 2021-09-24 14:54:40 +01:00
Germain 5951958c05 Merge pull request #1945 from matrix-org/gsouquet/thread-serialise-18720 2021-09-24 11:17:39 +01:00
David Baker 886f2fb95d Merge pull request #1947 from matrix-org/dbkr/we_like_tests
Add tests requirements to CONTRIBUTING
2021-09-23 18:15:32 +01:00
David Baker f6ce0c581e Add tests requirements to CONTRIBUTING
Fixes https://github.com/vector-im/element-web/issues/19136
2021-09-23 14:09:01 +01:00
Germain 5ce68b6c12 Merge pull request #1944 from matrix-org/gsouquet/thread-state-events-18719 2021-09-23 09:17:02 +01:00
Germain Souquet c748aebfc5 Add context to explain why we fetch roomstate in threads 2021-09-22 17:36:12 +01:00
Germain Souquet f8ec445ff0 Fix addLiveEvent with 'replace' strategy 2021-09-22 17:14:18 +01:00
Germain Souquet 5d4f347eaa Add thread serialisation helper 2021-09-22 11:35:19 +01:00
Germain Souquet 1359c0574e Share room state events with thread's timelines 2021-09-22 11:19:08 +01:00
Travis Ralston b1d239b292 Merge pull request #1934 from aaronraimist/kick-api
Switch to /kick API
2021-09-21 23:30:23 -06:00
Travis Ralston 70031415e8 Merge pull request #1938 from matrix-org/travis/fix-widgets-relations
Ensure unencrypted fields get exposed by getEffectiveEvent()
2021-09-21 23:16:18 -06:00
Martin Giger 3c97d17770 Fix requestVerificationDM with chronological pendingEventOrdering
Signed-off-by: Martin Giger <martin@humanoids.be>
2021-09-21 20:04:07 +02:00
Travis Ralston 5a73a9758a Merge pull request #1941 from SimonBrandner/feature/bound
Add `bound` to `IThreepid`
2021-09-21 11:36:36 -06:00
Travis Ralston 6848e96244 Merge pull request #1942 from SimonBrandner/feature/trusted_locally
Add `trusted_locally` to `TrustInfo`
2021-09-21 11:26:35 -06:00
Travis Ralston b53566e074 Merge pull request #1827 from SimonBrandner/feature/call-upgrades
Support for call upgrades
2021-09-21 09:10:02 -06:00
Šimon Brandner 012b914a97 Add trusted_locally to TrustInfo
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-21 16:20:39 +02:00
Šimon Brandner 3c6eed0135 Add bound to IThreepid
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-21 14:56:33 +02:00
RiotRobot f2a2e7f5dd v13.0.0-rc.1 2021-09-21 09:24:22 +01:00
RiotRobot 15b6a9a257 Prepare changelog for v13.0.0-rc.1 2021-09-21 09:24:21 +01:00
Šimon Brandner b83977e72f Add @param docs
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-20 16:40:46 +02:00
Travis Ralston 8f5082cd2f Merge pull request #1940 from SimonBrandner/feature/getHistoryVisibility
Add `getHistoryVisibility()` and `getGuestAccess()`
2021-09-20 08:34:14 -06:00
David Baker 50c877cb60 Merge pull request #1939 from SimonBrandner/fix/stream-stopping
Fix stream stopping and improve logging
2021-09-20 11:56:36 +01:00
Šimon Brandner e3e7fd5900 Add getGuestAccess()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-19 10:47:18 +02:00
Šimon Brandner 69823f9cae Add getHistoryVisibility()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-19 10:36:45 +02:00
Šimon Brandner e5dcdf109a Fix stream stopping and improve logging
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-19 09:29:16 +02:00
Šimon Brandner 5c6a643436 Merge branch 'feature/call-upgrades' of https://github.com/SimonBrandner/matrix-js-sdk into feature/call-upgrades 2021-09-19 07:44:40 +02:00
Šimon Brandner 1ca1a69eb8 Fix docs
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-19 07:44:28 +02:00
Šimon Brandner 76ea1ba192 Improve log
Co-authored-by: Travis Ralston <travpc@gmail.com>
2021-09-19 07:43:09 +02:00
Šimon Brandner 8cd8ec134e Merge remote-tracking branch 'upstream/develop' into feature/call-upgrades 2021-09-19 07:42:04 +02:00
Travis Ralston 6c649e2bfe Merge pull request #1937 from SimonBrandner/fix/getUserMediaStream
Fix `getUserMediaStream()` not being able to handle streams of different track combinations
2021-09-18 16:29:15 -06:00
Travis Ralston 9f42647a75 Ensure unencrypted fields get exposed by getEffectiveEvent()
Fixes https://github.com/vector-im/element-web/issues/19062
2021-09-18 16:26:08 -06:00
Šimon Brandner 9747e5e0d5 Fix getUserMediaStream() not being able to handle streams of different track combinations
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-18 13:18:28 +02:00
Šimon Brandner a4cacbc73a Add call upgrade support
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-18 12:32:13 +02:00
Šimon Brandner f24840d09c Make CallFeed handle addTrack events
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-18 12:31:54 +02:00
Šimon Brandner acb7991cc5 Fix getUserMediaStream() not being able to handle streams of different track combinations
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-18 12:27:24 +02:00
Šimon Brandner 6addc7dd3d Add MockMediaStream
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-18 12:27:08 +02:00
Eric Eastwood 2bd60f4160 Merge pull request #1933 from matrix-org/madlittlemods/more-better-pr-descriptions
Update PR guidelines for easier review
2021-09-17 11:54:13 -05:00
David Baker e71362a6df Merge pull request #1936 from matrix-org/dbkr/await_save_backup_key
Fix race on automatic backup restore
2021-09-17 17:06:43 +01:00
David Baker 673c09cd77 Fix race on automatic backup restore
We forgot to await the saving of the backup key, so there was a race
where it would fail to get the backup key because it hadn't been saved
yet, so the backup wouldn't be restored automatically.

Fixes https://github.com/vector-im/element-web/issues/17781
2021-09-17 15:53:14 +01:00
Michael Telatynski 4606422e57 Make RoomState::hasSufficientPowerLevelFor public 2021-09-17 15:35:03 +01:00
Dariusz Niemczyk 4bc8f968e0 Merge pull request #1932 from matrix-org/palid/threads-typescriptify
Fix PR comments
2021-09-17 08:11:36 +02:00
Aaron Raimist 35ee58dfe1 Switch to /kick API
Signed-off-by: Aaron Raimist <aaron@raim.ist>
2021-09-17 01:05:21 -05:00
Eric Eastwood 3705426b6d Make PR's easier to review 2021-09-16 16:05:49 -05:00
Dariusz Niemczyk 5813aea27f Properly rename ThreadEvents to ThreadEvent 2021-09-16 17:49:31 +02:00
Dariusz Niemczyk 5ba836a31b Fix PR comments 2021-09-16 17:12:57 +02:00
Dariusz Niemczyk 4f387d15b9 Merge pull request #1930 from matrix-org/palid/threads-typescriptify
Typescriptify thread events a bit
2021-09-16 17:12:02 +02:00
Dariusz Niemczyk 8ab0246ca2 Fix PR comments 2021-09-16 16:03:47 +02:00
Dariusz Niemczyk ed68bd4108 Typescriptify thread events a bit 2021-09-16 15:59:41 +02:00
Dariusz Niemczyk 3d39e8ec26 Merge pull request #1880 from matrix-org/palid/fix/dont-persist-log-level
Palid/fix/dont persist log level
2021-09-16 14:52:52 +02:00
Robert Long 53bdab7cc8 Merge pull request #1929 from matrix-org/robertlong/datachannels
Add WebRTC DataChannels to MatrixCall
2021-09-15 14:25:13 -07:00
Robert Long fafa55ba1d Merge pull request #1928 from matrix-org/robertlong/clone-streams
Clone and stop local media streams from mediaHandler
2021-09-15 14:25:00 -07:00
Travis Ralston 3a818c1419 Merge pull request #1927 from SimonBrandner/feature/getBuffer
Add `getBuffer()` to `QRCodeData`
2021-09-15 14:42:11 -06:00
Robert Long 422853298c Reset media stream arrays 2021-09-15 13:20:52 -07:00
Robert Long f3a2bd6b40 Clean up stopAllMedia 2021-09-15 12:38:12 -07:00
Robert Long 6834137f50 Add datachannels to MatrixCall 2021-09-15 12:28:09 -07:00
Robert Long c4d7fef0cd Clone and stop local media streams from mediaHandler 2021-09-15 12:08:28 -07:00
Šimon Brandner 556b5ff628 Add getBuffer() to QRCodeData
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-15 20:27:13 +02:00
David Baker 2daa1ec4ce Merge pull request #1916 from matrix-org/dbkr/verify_key_share_tests
Tests for key sharing security fix
2021-09-15 18:38:03 +01:00
Travis Ralston 348ea72b70 Merge pull request #1925 from SimonBrandner/task/setCodecPreferences
Add `setCodecPreferences()` to `global.d.ts`
2021-09-15 09:48:27 -06:00
Šimon Brandner 4e14d810c5 Add setCodecPreferences()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-15 17:44:16 +02:00
Travis Ralston f84905b003 Merge pull request #1924 from SimonBrandner/revert-1923-task/die-rtx-hack
Revert "Remove RTX codec hack "
2021-09-15 09:23:27 -06:00
Šimon Brandner 9bb87145f6 Revert "Remove RTX codec hack " 2021-09-15 17:17:56 +02:00
Travis Ralston c7675570aa Merge pull request #1923 from SimonBrandner/task/die-rtx-hack
Remove RTX codec hack
2021-09-15 09:16:55 -06:00
Šimon Brandner be942fd66a Remove RTX codec hack as the issue is no longer present on Chromium 90
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-15 16:38:59 +02:00
James Salter 8544aca362 Merge pull request #1922 from matrix-org/revert-errors-ts
Revert "Migrate errors to TypeScript"
2021-09-15 12:08:32 +01:00
James Salter c3308e1de9 Revert "Migrate errors to TypeScript"
This reverts commit ab906faa17.
2021-09-15 12:01:34 +01:00
David Baker 047d7125a1 Merge pull request #1920 from matrix-org/dbkr/fix_autodiscovery_types
Fix types
2021-09-15 11:29:10 +01:00
David Baker cf4d3117c1 Fix types
This is 'any' (defined as any by IWellKnownConfig.raw) rather than
string (which the jsdoc claimed). We were calling this method ourselves
but with an object that was also 'any', so it was fine, but react-sdk
calls it with an object literal, which typescript knows it not a string.
2021-09-15 10:29:14 +01:00
David Baker 88c2844e48 Merge pull request #1919 from matrix-org/dbkr/yarnupgrade_20210914
yarn upgrade
2021-09-15 10:01:18 +01:00
Germain 6ca4694fe6 Merge pull request #1907 from matrix-org/gsouquet/ts-last-push 2021-09-15 08:30:52 +01:00
Germain 062287e270 Merge pull request #1913 from matrix-org/gsouquet/ts-security 2021-09-15 08:27:29 +01:00
Germain Souquet 50e0d76f10 remove erroneous comment related to typings 2021-09-15 09:26:25 +02:00
Travis Ralston df039d3d8c Merge pull request #1911 from SimonBrandner/feature/media-handling
Improve `MatrixCall` media handling and internally remove `CallType`s
2021-09-14 14:40:45 -06:00
Travis Ralston 799606b73c Merge pull request #1909 from matrix-org/travis/fsdk/locking
Add file locking to MSC3089 branches
2021-09-14 12:39:41 -06:00
Travis Ralston c048f5d357 Merge pull request #1910 from matrix-org/travis/fsdk/tests
Add missing tests for MSC3089 implementation
2021-09-14 12:37:54 -06:00
Robert Long f712a8cecb Merge pull request #1903 from matrix-org/robertlong/fix-register-types
Add types for the MatrixClient register method
2021-09-14 10:56:12 -07:00
David Baker e1d8d6bf4e Not typescript again
because this time they just removed setCodecPreferences from webrtc?
2021-09-14 18:52:35 +01:00
Robert Long 14ed8a110c Update src/client.ts
Co-authored-by: Travis Ralston <travisr@matrix.org>
2021-09-14 10:50:50 -07:00
David Baker cb6700f21b yarn upgrade 2021-09-14 18:41:14 +01:00
Travis Ralston d4f35bf07a fix main package? 2021-09-14 10:03:23 -06:00
RiotRobot b4eb29138b Resetting package fields for development 2021-09-14 15:52:38 +01:00
RiotRobot 8ca3a071f9 Merge branch 'master' into develop 2021-09-14 15:51:45 +01:00
RiotRobot 5abd211436 Merge branch 'release-v12.5.0' 2021-09-14 15:51:13 +01:00
RiotRobot 99f428e091 v12.5.0 2021-09-14 15:46:09 +01:00
RiotRobot a734fdf9b0 Prepare changelog for v12.5.0 2021-09-14 15:46:08 +01:00
David Baker 6f91b2bc80 Merge pull request #1917 from matrix-org/dbkr/verify_keyshare_tests_125rel
Tests for key sharing security fix
2021-09-14 15:33:05 +01:00
David Baker 32d7272939 Tests for key sharing security fix
Tests for 894c24880d
2021-09-14 15:24:15 +01:00
David Baker c8d85452bf Merge remote-tracking branch 'origin/develop' into dbkr/verify_key_share_tests 2021-09-14 15:16:49 +01:00
RiotRobot 557f800919 Verify target device key on reshare 2021-09-14 15:14:46 +01:00
David Baker 2119e88c78 Tests for key sharing security fix
Tests for 894c24880d
2021-09-14 13:11:18 +01:00
Travis Ralston 24e7a7e6bf Merge pull request #1915 from SimonBrandner/feature/has-been-cancelled
Add `hasBeenCancelled` to `VerificationBase`
2021-09-13 20:54:03 -06:00
Šimon Brandner 4e5847f356 Add hasBeenCancelled to VerificationBase
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-13 18:01:24 +02:00
RiotRobot 72d580edfd Merge branch 'master' into develop 2021-09-13 12:50:02 +01:00
RiotRobot e878b7683b v12.4.1 2021-09-13 12:47:04 +01:00
RiotRobot fac700bf4d Changelog for 12.4.1 2021-09-13 12:43:13 +01:00
RiotRobot 894c24880d Verify target device key on reshare 2021-09-13 12:34:48 +01:00
Germain d742249fd1 Merge pull request #1914 from matrix-org/gsouquet/ts-misc
Types adjustment for TS migration
2021-09-13 10:00:26 +01:00
Germain Souquet 9c100fea48 Types update for UserView TS migration 2021-09-12 10:12:59 +02:00
Germain Souquet 7daab62850 Types fixes for CreateKeyBackupDialog TS migration 2021-09-12 09:21:04 +02:00
Germain Souquet fed0ced89d Type fixes for CreateSecretStorageDialog TS migration 2021-09-12 08:56:31 +02:00
Germain Souquet df9cfaed1d Merge branch 'develop' into gsouquet/ts-last-push 2021-09-11 16:18:25 +01:00
Germain Souquet edd614dd0c fix cyclic dependencies for AutoDiscoveryActionEnum 2021-09-11 16:17:40 +01:00
Germain Souquet 375b228bb2 fix missing types and linting errors 2021-09-11 16:06:29 +01:00
Šimon Brandner 7143ef8a32 Internally remove call types
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-11 08:21:58 +02:00
Šimon Brandner 1bd7de5a18 Use MediaHandler
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-11 08:21:57 +02:00
Šimon Brandner a1f73eee86 Add MediaHandler
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-11 08:21:51 +02:00
Travis Ralston d9f8710758 Add missing tests for MSC3089 implementation
Fixes https://github.com/vector-im/element-web/issues/18461
2021-09-10 14:44:50 -06:00
Travis Ralston 3a9d5439a2 Add tests 2021-09-10 14:18:11 -06:00
Travis Ralston 5d1be6e8be Add file locking to MSC3089 branches
This isn't hooked up to versioning, yet, but will be eventually.
2021-09-10 14:15:32 -06:00
Germain 775e85a2e8 Merge pull request #1906 from matrix-org/gsouquet/threads-relations-18721 2021-09-10 19:22:41 +01:00
Travis Ralston dc8f403c44 Merge pull request #1908 from SimonBrandner/task/dialogs-ts
Add `ISasEvent`
2021-09-10 12:17:41 -06:00
Šimon Brandner cf9fa991d1 Add ISasEvent
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-10 19:18:19 +02:00
Robert Long d26dc49755 Merge pull request #1904 from matrix-org/robertlong/callfeed-dispose
Properly dispose of CallFeeds
2021-09-10 10:07:10 -07:00
Germain be04559a66 Merge pull request #1878 from SimonBrandner/task/i-hate-my-code 2021-09-10 16:16:51 +01:00
Germain Souquet 0722dafe58 Migrate AutoDiscovery to TypeScript 2021-09-10 16:04:55 +01:00
Germain Souquet ab906faa17 Migrate errors to TypeScript 2021-09-10 15:39:36 +01:00
Germain Souquet 9d63a12469 Migrate realtime-callbacks to TypeScript 2021-09-10 15:31:21 +01:00
Germain Souquet f40d0d24c7 Move relations and redactions to thread timeline 2021-09-10 09:21:25 +01:00
Germain Souquet 2cdea36abf Merge branch 'develop' into gsouquet/threads-relations-18721 2021-09-10 08:18:03 +01:00
Travis Ralston 8d4f4c8832 Merge pull request #1901 from matrix-org/travis/rl/perf-metrics
[Release] Exclude opt-in Element performance metrics from encryption
2021-09-09 18:27:25 -06:00
Robert Long 3b4dcbb01d Properly dispose of CallFeeds 2021-09-09 17:15:41 -07:00
Robert Long b52f3b1c57 Add types for the MatrixClient register method 2021-09-09 17:00:45 -07:00
Germain 2cdf5629e5 Merge pull request #1900 from matrix-org/gsouquet/thread-disable-echo 2021-09-09 18:56:02 +01:00
Germain Souquet 97b4f0e369 restore correct local echo 2021-09-09 18:51:12 +01:00
Germain Souquet a508c8d236 Make supportsExperimentalThreads calls more resilient 2021-09-09 18:40:15 +01:00
Travis Ralston 7911e6371a Exclude opt-in Element performance metrics from encryption
This is needed for the system which is meant to be monitoring this metadata. See https://github.com/matrix-org/matrix-react-sdk/pull/6766
2021-09-09 10:41:09 -06:00
Travis Ralston bbace01e9a Merge pull request #1897 from matrix-org/travis/measure-encryption-perf
Exclude opt-in Element performance metrics from encryption
2021-09-09 10:38:18 -06:00
Germain Souquet 87469fea63 Disable pending events for threads
There's a fair few things to update to make them work with Threads
Will get back to it when the plan is to build a more polished UI ready for production
2021-09-09 17:24:55 +01:00
Germain Souquet 48a9db0315 Add helper to check threads support 2021-09-09 17:24:34 +01:00
Germain Souquet 33c9471112 Make timelineSet public readonly 2021-09-09 17:23:45 +01:00
Travis Ralston 04fdcbb672 Exclude opt-in Element performance metrics from encryption
This is needed for the system which is meant to be monitoring this metadata. See https://github.com/matrix-org/matrix-react-sdk/pull/6766
2021-09-08 11:34:01 -06:00
Michael Telatynski 4d2286c5be Merge pull request #1888 from matrix-org/t3chguy/ts1234 2021-09-08 16:59:17 +01:00
Michael Telatynski 620e45e4dc fix typing mishap 2021-09-08 16:56:19 +01:00
Michael Telatynski fb97e74344 iterate PR based on feedback 2021-09-08 16:49:17 +01:00
Michael Telatynski 3bbb7df72d fix tests private field access 2021-09-08 12:57:12 +01:00
Michael Telatynski 58b08821bf Fix bugs identified by TS 2021-09-08 12:49:30 +01:00
Michael Telatynski 19bdfd5b84 Add missing interface 2021-09-08 12:49:22 +01:00
Michael Telatynski b6c857e2a2 Convert crypto/verification/* to Typescript 2021-09-08 12:34:44 +01:00
Michael Telatynski 0991626e85 Merge pull request #1884 from matrix-org/t3chguy/ts/123 2021-09-08 10:03:25 +01:00
Germain 7b10d4fac0 Merge pull request #1886 from janpawellek/janpawellek-fix-removeEventListener
Fix calling removeEventListener if it does not exist
2021-09-08 09:13:27 +01:00
Jan Pawellek 980dacaa87 Add explaination why the check for global.window.removeEventListener is necessary 2021-09-08 09:59:09 +02:00
Travis Ralston 3790e8abb4 Merge pull request #1887 from matrix-org/revert-1872-fix/call-notifs
Revert "Count notifications in encrypted rooms client-side"
2021-09-07 14:15:15 -06:00
Travis Ralston 14ba851daf Revert "Count notifications in encrypted rooms client-side" 2021-09-07 14:15:01 -06:00
Travis Ralston 95d80772d7 Merge pull request #1872 from SimonBrandner/fix/call-notifs
Count notifications in encrypted rooms client-side
2021-09-07 12:31:49 -06:00
RiotRobot 341e936082 v12.5.0-rc.1 2021-09-07 18:20:07 +01:00
RiotRobot e87399c4a1 Prepare changelog for v12.5.0-rc.1 2021-09-07 18:20:06 +01:00
Jan Pawellek a7678ea1e0 Fix calling removeEventListener if it does not exist 2021-09-07 17:12:21 +02:00
Germain 0388bd3b48 Merge pull request #1885 from matrix-org/gsouquet/improve-threads-dedupe 2021-09-07 15:31:56 +01:00
Germain Souquet f27327164b Merge branch 'develop' into gsouquet/improve-threads-dedupe 2021-09-07 15:28:05 +01:00
Germain a0f85075c1 Merge pull request #1882 from matrix-org/gsouquet/fix-replyinthread 2021-09-07 15:26:35 +01:00
Germain Souquet e97d18a03b Improve thread deduplication thread process
Some threads were still holding a reference to the original thread models they were assigned to, leading to some unexpected timeline rendering
2021-09-07 15:05:45 +01:00
Michael Telatynski f07cdb43b1 Fix dehydration Crypto type 2021-09-07 14:39:49 +01:00
Michael Telatynski da8c8f166d Improve jsdoc 2021-09-07 14:36:20 +01:00
Michael Telatynski 0830a30498 Fix tests 2021-09-07 14:36:10 +01:00
Michael Telatynski 68a2762b75 fix forwarding_curve25519_key_chain in OlmDevice::exportInboundGroupSession 2021-09-07 13:29:42 +01:00
Michael Telatynski 666e471369 Convert OlmDevice to Typescript 2021-09-07 13:22:27 +01:00
Germain Souquet d89f4a74f9 Fix replyInThread getter to match event m.in_reply_to structure 2021-09-07 10:20:01 +01:00
Germain Souquet 191535d01a Fix replyInThread getter to match event m.in_reply_to structure 2021-09-07 10:17:24 +01:00
Šimon Brandner 241203f804 Merge remote-tracking branch 'upstream/develop' into fix/call-notifs 2021-09-03 18:28:34 +02:00
Šimon Brandner 26cc7a0f64 Return a TODO
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-03 18:24:37 +02:00
Travis Ralston 324f9e58ea Merge pull request #1873 from SimonBrandner/feature/call-timer/18566
Give `MatrixCall` the capability to emit `LengthChanged` events
2021-09-02 22:12:31 -06:00
Dariusz Niemczyk e71519c638 Remove persisted log levels 2021-09-02 20:17:32 +02:00
Šimon Brandner 9b6cee0cab Merge remote-tracking branch 'upstream/develop' into fix/call-notifs 2021-09-02 16:32:26 +02:00
Germain Souquet 2a5f6a7b3d Move all relations event in thread timeline
If an event is related to another event who's in a thread, we want to make sure to move that event to the thread's timeline
2021-09-02 14:14:30 +01:00
Šimon Brandner cae03817cb Use source id directly
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-02 14:10:43 +02:00
Germain 37736184a0 Merge pull request #1876 from matrix-org/gsouquet/replies-fix-18717
Add reply events rendering hint
2021-09-02 08:37:11 +01:00
Šimon Brandner 9431a52abe Move DesktopCapturerSource out of global.d.ts
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-01 18:22:51 +02:00
Šimon Brandner 13c664ad34 Remove Element-specifc screen-sharing code out of the js-sdk
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-01 18:22:45 +02:00
Šimon Brandner d7640d9e15 Don't use a callback in setScreensharingEnabled()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-09-01 18:08:59 +02:00
Michael Telatynski 3c36be9839 Merge pull request #1877 from matrix-org/t3chguy/fix/18798 2021-09-01 16:08:37 +01:00
Michael Telatynski 9dce7bbb97 Improve typing around join rules 2021-09-01 15:54:04 +01:00
Germain Souquet fa44300abc Add reply events rendering hint
Adds an unstable hint for clients to know whether to render an event in the room timeline or in a thread

There are currently no MSC associated with that unstable "io.element.in_thread" property as I am only experimenting before settling on a specific approach
2021-09-01 12:12:01 +01:00
RiotRobot 2783d162b7 Resetting package fields for development 2021-08-31 13:32:29 +01:00
RiotRobot 39566dbd4f Merge branch 'master' into develop 2021-08-31 13:32:28 +01:00
RiotRobot f8186add92 v12.4.0 2021-08-31 13:29:19 +01:00
RiotRobot c15f22e81d Prepare changelog for v12.4.0 2021-08-31 13:29:18 +01:00
Michael Telatynski 052ac8f95b Merge pull request #1874 from SimonBrandner/task/call-types
Improve TypeScript in `MatrixCall`
2021-08-31 13:06:23 +01:00
Šimon Brandner c37f8ba4c7 Make placeCalls public
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-31 14:00:37 +02:00
Germain 7e2458d5b5 Merge pull request #1828 from matrix-org/gsouquet/threaded-messaging-2349 2021-08-31 09:19:48 +01:00
Germain fe989177bb Merge pull request #1875 from psrpinto/fix/browser-example 2021-08-31 09:15:39 +01:00
Paulo Pinto 412645f025 Use HTTPS
Signed-off-by: Paulo Pinto <paulo.pinto@automattic.com>
2021-08-30 13:32:30 +01:00
Paulo Pinto e527c46f34 Add empty favicon
Signed-off-by: Paulo Pinto <paulo.pinto@automattic.com>
2021-08-30 13:32:30 +01:00
Paulo Pinto da471b57ad Define document encoding
Signed-off-by: Paulo Pinto <paulo.pinto@automattic.com>
2021-08-30 13:32:30 +01:00
Paulo Pinto a4ff97c8df Add required lang attribute
Signed-off-by: Paulo Pinto <paulo.pinto@automattic.com>
2021-08-30 13:32:30 +01:00
Šimon Brandner 411fc47f28 Improve TypeScript in MatrixCall
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-28 09:27:47 +02:00
Šimon Brandner b97e3113d1 Add/improve call event content types
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-28 09:27:34 +02:00
Šimon Brandner f107d63fab Give MatrixCall the capability to emit LengthChanged events
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-27 15:06:55 +02:00
Šimon Brandner a65ac5a82b Count notifications in encrypted rooms client-side
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-27 08:38:59 +02:00
Šimon Brandner c7c1db00e8 Use getWirePushActions()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-26 20:01:40 +02:00
Šimon Brandner 824f93daa3 Add wirePushRules
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-26 20:01:39 +02:00
Šimon Brandner 9fec2f8c58 Simplifie some code
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-26 20:01:39 +02:00
Šimon Brandner 0b46389176 currentCount -> currentHighlightCount
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-26 20:01:38 +02:00
Šimon Brandner db03f16b8e Add a type
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-26 20:01:37 +02:00
David Baker f83fcb1a18 Merge pull request #1870 from matrix-org/dbkr/allchange102
Update changelog generator
2021-08-26 09:42:37 +01:00
David Baker ba0f1f86b9 Merge pull request #1871 from matrix-org/dbkr/verification_request_cancel
Fix verification request cancellation
2021-08-26 09:40:53 +01:00
David Baker 81d349d993 Clarify operator precedence 2021-08-25 20:55:03 +01:00
David Baker d65d2b94b9 Fix verification request cancellation
If you started trying to verify against your other devices and
then cancelled the dialog, the device destination in the cancellation
to-device message would be 'null', so the cancellation wouldn't go
anywhere.

If we haven't yet picked a specific device to talk to, send the
cancellation to all devices (like we did the request).
2021-08-25 18:37:45 +01:00
David Baker acd52bc070 Update changelog generator 2021-08-25 17:19:25 +01:00
David Baker a64339763f Merge pull request #1869 from matrix-org/dbkr/yarn_upgrade_20210824
yarn upgrade
2021-08-25 16:39:45 +01:00
David Baker 4f21b95bbf Merge pull request #1865 from SimonBrandner/feature/voice-activity
Give `CallFeed` the capability to emit on volume changes
2021-08-25 14:40:24 +01:00
David Baker 03e4dcf1ed yarn upgrade 2021-08-25 10:57:37 +01:00
Germain Souquet 3c56d1372d Appease the linter 2021-08-25 09:15:07 +01:00
Germain Souquet 27ecdef09b Merge branch 'develop' into gsouquet/threaded-messaging-2349 2021-08-25 08:53:29 +01:00
RiotRobot 121e8a51c1 v12.4.0-rc.1 2021-08-24 17:04:11 +01:00
RiotRobot 88e3ada701 Prepare changelog for v12.4.0-rc.1 2021-08-24 17:04:10 +01:00
Dariusz Niemczyk 92d822d494 Merge pull request #1847 from matrix-org/jaller94-patch-2
SSSSCryptoCallbacks.getSecretStorageKey: Test if delegateCryptoCallbacks has getSecretStorageKey
2021-08-24 15:24:54 +02:00
Travis Ralston 62c93f54cc Merge pull request #1818 from matrix-org/t3chguy/fix/18089
Add support for /hierarchy API and fall back to /spaces API if needed
2021-08-23 15:51:28 -06:00
Germain Souquet 500c2ed4f2 Remove thread spec 2021-08-23 15:03:10 +01:00
Šimon Brandner 425362edfe Emit Speaking events from CallFeed
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-19 14:48:26 +02:00
Germain Souquet 9c554f9b3d Add experimentalThreadSupport flag 2021-08-19 11:18:46 +01:00
Germain Souquet b7a5f81f95 Add experimental indicators for all threading related features 2021-08-19 11:10:20 +01:00
Šimon Brandner 0746a64c83 Add some docs
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-19 12:03:57 +02:00
Šimon Brandner 22cd475d22 Add missing types
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-19 11:49:26 +02:00
Šimon Brandner 6904f6b36f Emit volume changes
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-19 11:49:19 +02:00
Šimon Brandner e25a649e1a Add webkitAudioContext to window
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-19 11:49:18 +02:00
Germain Souquet 0eb8cbee4d Merge branch 'develop' into gsouquet/threaded-messaging-2349 2021-08-19 10:45:23 +01:00
Dariusz Niemczyk 96e8f65af7 Merge pull request #1864 from matrix-org/palid/dx/typescriptify-password-reset
Add necessary changes for PasswordReset migration
2021-08-19 10:42:59 +02:00
Dariusz Niemczyk 8fb036ba2d Make eslint happy 2021-08-19 09:46:54 +02:00
Dariusz Niemczyk 0a10fa12ef Add necessary changes for PasswordReset migration 2021-08-19 08:59:55 +02:00
David Baker e30dad7913 Merge pull request #1859 from SimonBrandner/task/revert-quick-voip-fix
Revert quick VoIP fix
2021-08-18 18:50:37 +01:00
Travis Ralston c2a0c02898 Merge pull request #1850 from matrix-org/travis/fsdk/filemeta
Add method for including extra fields when uploading to a tree space
2021-08-18 07:29:49 -06:00
Dariusz Niemczyk 7c1e89f86a Merge pull request #1849 from matrix-org/jaller94-patch-3
Make delegateCryptoCallbacks an optional parameter of EncryptionSetupBuilder and SSSSCryptoCallbacks
2021-08-18 14:01:44 +02:00
Germain 29f8a4cba2 Merge pull request #1853 from matrix-org/gsouquet/ts-components-migration
Expose IMyDevice interface
2021-08-18 12:35:57 +01:00
Germain Souquet b884accc99 Dispatch thread events 2021-08-17 17:43:00 +01:00
Germain Souquet d56540320e Merge branch 'develop' into gsouquet/threaded-messaging-2349 2021-08-17 11:14:10 +01:00
Germain Souquet 526fe7e9a4 use timeline set instead of an array of events 2021-08-17 11:10:20 +01:00
Germain Souquet aa696c4c15 Move threading logic to the Sync API 2021-08-17 10:37:34 +01:00
RiotRobot 3216d7e5a7 Merge branch 'master' into develop 2021-08-17 09:27:42 +01:00
RiotRobot b68f649414 v12.3.1 2021-08-17 09:24:43 +01:00
RiotRobot 543f35d9a8 Prepare changelog for v12.3.1 2021-08-17 09:24:42 +01:00
David Baker 03d42a98cd Merge pull request #1862 from matrix-org/dbkr/release_script_handle_no_signing_id_rel_take_2
Fix release script to handle no signing ID
2021-08-17 09:19:30 +01:00
David Baker 4f48554cd2 Merge pull request #1861 from matrix-org/dbkr/release_script_handle_no_signing_id_rel
Fix release script to handle no signing ID
2021-08-17 09:13:59 +01:00
David Baker 85d9c0f403 Merge pull request #1860 from matrix-org/dbkr/1858_rel
Fix multiple VoIP regressions
2021-08-17 09:11:36 +01:00
David Baker 66b4279dd8 Fix release script to handle no signing ID
We now use the file for stuff other than just the signing ID, so
the file may be present but with no signing ID: handle this case.
2021-08-17 09:10:11 +01:00
Šimon Brandner 1ee84fbeca Fix regressions
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-17 09:06:53 +01:00
Šimon Brandner c0e15b206a Revert "Fix regressions"
This reverts commit bd8690de57.
2021-08-17 10:03:46 +02:00
David Baker 290575ba65 Merge pull request #1858 from SimonBrandner/fix/voip
Fix broken voice calls, no ringing and broken call notifications
2021-08-17 08:54:11 +01:00
Šimon Brandner bd8690de57 Fix regressions
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-17 08:09:14 +02:00
Šimon Brandner 0d09f87777 Revert "Revert "Fix glare related regressions""
This reverts commit 4c552cc350.
2021-08-17 07:33:40 +02:00
David Baker 0f45b7e516 Merge pull request #1857 from matrix-org/revert-1851-fix/glare/18538
Revert "Fix glare related regressions"
2021-08-16 23:18:13 +01:00
David Baker 4c552cc350 Revert "Fix glare related regressions" 2021-08-16 23:06:57 +01:00
David Baker 6a87f54292 Merge pull request #1856 from matrix-org/dbkr/release_script_handle_no_signing_id
Fix release script to handle no signing ID
2021-08-16 15:32:09 +01:00
David Baker bfb2c5aad0 Fix release script to handle no signing ID
We now use the file for stuff other than just the signing ID, so
the file may be present but with no signing ID: handle this case.
2021-08-16 14:38:42 +01:00
RiotRobot db898e7bcf Resetting package fields for development 2021-08-16 13:55:37 +01:00
RiotRobot dbebbe3a19 Merge branch 'master' into develop 2021-08-16 13:55:37 +01:00
RiotRobot 10e8aff46a v12.3.0 2021-08-16 13:52:36 +01:00
RiotRobot 81e2ea6a61 Prepare changelog for v12.3.0 2021-08-16 13:52:35 +01:00
David Baker 2594c59250 Merge pull request #1855 from matrix-org/dbkr/update_allchange
Update changelog generator
2021-08-16 13:31:28 +01:00
David Baker b56a4ee6ec Fix dates 2021-08-16 13:24:11 +01:00
David Baker ab524ad3b4 Update changelog generator 2021-08-16 13:18:06 +01:00
David Baker 83bf80feec Merge pull request #1854 from SimonBrandner/release/fix/glare/18538
[Release] Fix glare related regressions
2021-08-16 12:40:08 +01:00
Šimon Brandner b9e5417218 Await handleCallEvent()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-16 13:30:22 +02:00
Šimon Brandner 082169a756 Fix glare
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-16 13:30:21 +02:00
Šimon Brandner cdc87d371c Reformat some code
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-16 13:30:21 +02:00
Šimon Brandner f8ec3bc591 Remove weird method call
If we can get localUsermediaStream gotUserMediaForAnswer() has alredy been called before

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-16 13:30:21 +02:00
Šimon Brandner 85f4651e9b Simplifie some code
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-16 13:30:20 +02:00
Šimon Brandner da53241c48 Remove unnecessary logs
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-16 13:30:20 +02:00
Šimon Brandner fa265296e8 Add a comment
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-16 13:30:19 +02:00
David Baker ccf296ea92 Merge pull request #1851 from SimonBrandner/fix/glare/18538
Fix glare related regressions
2021-08-16 12:27:51 +01:00
Šimon Brandner d65b48204b Await handleCallEvent()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-16 13:14:04 +02:00
J. Ryan Stinnett 977720cee4 Merge pull request #1852 from matrix-org/jryans/comment-to-json
Clarify usages of event's toJSON
2021-08-16 10:30:50 +01:00
Christian Paul 3c7cdb1da8 Update src/crypto/EncryptionSetup.ts 2021-08-16 10:36:21 +02:00
Germain Souquet dd80e744ff Expose IMyDevice interface 2021-08-16 09:06:52 +01:00
J. Ryan Stinnett 0b12e37459 Clarify usages of event's toJSON 2021-08-16 09:04:14 +01:00
Šimon Brandner 51e815f0cb Fix glare
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-15 13:03:18 +02:00
Šimon Brandner f3856d569d Reformat some code
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-15 13:03:08 +02:00
Šimon Brandner e6d1909f0b Remove weird method call
If we can get localUsermediaStream gotUserMediaForAnswer() has alredy been called before

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-15 13:02:39 +02:00
Šimon Brandner 408976a199 Simplifie some code
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-15 12:58:38 +02:00
Šimon Brandner 4da49d926b Remove unnecessary logs
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-15 12:57:27 +02:00
Šimon Brandner 75750ed760 Add a comment
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-15 12:56:48 +02:00
Travis Ralston 2f74779bf1 Merge pull request #1772 from matrix-org/t3chguy/ts/12
Convert SearchResult, InteractiveAuth, PushProcessor and Scheduler to TS
2021-08-13 10:08:54 -06:00
Michael Telatynski 7b038393b1 Merge pull request #1792 from matrix-org/t3chguy/kill-groups
Deprecate groups APIs
2021-08-13 16:39:47 +01:00
Travis Ralston 768c0e7f77 Add method for including extra fields when uploading to a tree space
We ultimately need this to include things like `info` and other metadata in a specific environment.
2021-08-13 09:25:19 -06:00
Christian Paul c6009b1056 Make delegateCryptoCallbacks parameter optional on EncryptionSetupBuilder 2021-08-13 16:04:47 +02:00
Christian Paul 2a280afa88 Make SSSSCryptoCallbacks.delegateCryptoCallbacks optional 2021-08-13 15:58:44 +02:00
Christian Paul be980f4bc9 Update src/crypto/EncryptionSetup.ts 2021-08-13 15:38:22 +02:00
Dariusz Niemczyk 78118e9442 Merge pull request #1846 from matrix-org/jaller94-patch-1
SSSSCryptoCallbacks.getSecretStorageKey return Promise<null> if no key was found
2021-08-13 15:36:53 +02:00
Christian Paul a2c10a7913 SSSSCryptoCallbacks.getSecretStorageKey: Test if delegateCryptoCallbacks has getSecretStorageKey 2021-08-13 15:28:01 +02:00
Christian Paul 7c4f7c9dad SSSSCryptoCallbacks.getSecretStorageKey: Return null, if no key found 2021-08-13 15:23:47 +02:00
Christian Paul 62058e6d48 SSSSCryptoCallbacks.getSecretStorageKey may return Promise<void>
If no result is found, the function may reach the last line without `return` ever being called.
2021-08-13 15:15:20 +02:00
Dariusz Niemczyk a2f514b544 Merge pull request #1834 from matrix-org/palid/fix/signaling-state-errors
Fix temporary call messages being handled without call
2021-08-13 14:17:30 +02:00
RiotRobot 67434bc5d4 v12.3.0-rc.2 2021-08-12 15:11:35 +01:00
RiotRobot 167183775e Prepare changelog for v12.3.0-rc.2 2021-08-12 15:11:35 +01:00
David Baker 4ce6313126 Merge pull request #1840 from matrix-org/dbkr/allchange_npm
Use changelog generator from npm
2021-08-12 15:02:12 +01:00
David Baker 1298ed61b6 Merge pull request #1842 from matrix-org/dbkr/fix_types_build
Fix the types in shipped package
2021-08-12 14:33:01 +01:00
Michael Telatynski 14b424ee94 Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/fix/18089 2021-08-12 11:55:04 +01:00
David Baker 2bc1f2fe21 Apparently target matters when not emitting 2021-08-12 11:54:19 +01:00
David Baker b392dbf6f8 Fix the types building
1829 added the spec files to 'src', presumably because they just
were't type checked otherwise, but this chaqnged the implicit rootDir
so the lib directory we shipped has types in src/ and spec/ which
meant lib/index.d.ts was at lib/src/index.d.ts.

Specify the rootDir on the build tsconfig to put it back in the
right place, and also try to make the base tsconfig never emit
to avoid it ever generating .d.ts files in silly places. Move all
the optoins related to emitting to -build since they aren't relevant
in the main one.

Is this a sensible way to do this? It doesn't feel terribly elegant.

Fixes https://github.com/vector-im/element-web/issues/18503
Regressed in https://github.com/matrix-org/matrix-js-sdk/pull/1829
2021-08-12 11:46:49 +01:00
Travis Ralston 696b3ef1ce Merge pull request #1841 from matrix-org/travis/fsdk/fix-delete
Fix conditional on returning file tree spaces
2021-08-11 15:21:20 -06:00
Travis Ralston 4e2ee3b3a8 It helps to fix the other tests too 2021-08-11 15:18:24 -06:00
Travis Ralston 1f9fab9a0c Fix conditional on returning file tree spaces
If a tree space was deleted then it'll still hold a Room object for us, which is not much help if we're effectively trying to get the joined trees.
2021-08-11 15:11:13 -06:00
David Baker 6170796ed8 Use changelog generator from npm 2021-08-11 21:50:13 +01:00
Michael Telatynski d91d1cea34 Apply suggestions from code review
Co-authored-by: Travis Ralston <travisr@matrix.org>
2021-08-11 21:47:51 +01:00
Michael Telatynski 69ba32683c Iterate PR based on feedback 2021-08-11 21:45:51 +01:00
Michael Telatynski fc78e63ad1 Fix RoomHierarchy comments 2021-08-11 20:57:40 +01:00
Michael Telatynski db212a555d Update to latest version of MSC2946 API s/next_token/next_batch/ 2021-08-11 20:49:23 +01:00
RiotRobot 429f32dacb v12.3.0-rc.1 2021-08-11 15:41:40 +01:00
David Baker ad036104e6 Changelog 2021-08-11 15:41:00 +01:00
Dariusz Niemczyk 4607f0177c Fix invalid string quotes 2021-08-11 14:39:00 +02:00
Dariusz Niemczyk d7dbaeba46 Update src/webrtc/callEventHandler.ts
Co-authored-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-11 14:38:20 +02:00
Dariusz Niemczyk 3e94db1837 Update src/webrtc/call.ts
Co-authored-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-11 14:38:13 +02:00
Dariusz Niemczyk 4fd77c2f05 Update src/webrtc/callEventHandler.ts
Co-authored-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-11 14:38:08 +02:00
Dariusz Niemczyk 9fe05e7d40 Fix temporary call messages being handled without call
In cases where a rogue client, or just a simple bug, sends a temporary
call message, like CallNegotiate the messages should just be discarded
if there's no actual p2p connection created.
2021-08-11 14:28:10 +02:00
Matthew Hodgson 946dcd0301 Merge pull request #1838 from matrix-org/matthew/fix-turn
fix TURN by fixing regression preventing multiple ICE candidates from sending.
2021-08-11 11:35:36 +01:00
Matthew Hodgson 97d718e850 tab->space 2021-08-11 11:31:40 +01:00
Matthew Hodgson 913b2d148c clarify blank candidate comment 2021-08-11 11:30:42 +01:00
Matthew Hodgson 916f6a6126 fix TURN by fixing regression preventing multiple candidates from sending
In https://github.com/matrix-org/matrix-js-sdk/commit/eafecd36bc860e79d9aa280a7e60455dbd7c6f67#diff-df33fb6c18a9b5896cd500875824d6c10980d42c92b21cedac6d8f570a8d52b7L1639
the candidateSendTries reset was accidentally lost, meaning that we never send more than one m.call.candidates, breaking trickle ICE.

Also, we leak blank candidates out in m.call.candidates on Safari and FF, so fix that too.
2021-08-11 04:42:32 +01:00
David Baker 7dbee19456 Merge pull request #1837 from matrix-org/dbkr/fix_blank_membership_events
Fix blank profile in join events
2021-08-10 22:13:16 +01:00
David Baker 2375b00b52 more null checking 2021-08-10 22:09:01 +01:00
David Baker 13cdca028f Fix blank profile in join events
This definitely needs explanation, but hopefully the comment is sufficient.

Type: defect
Fixes https://github.com/vector-im/element-web/issues/18321
Regressed in https://github.com/matrix-org/matrix-js-sdk/pull/1765
2021-08-10 21:59:40 +01:00
Germain Souquet e5a67500e4 Stop checking for event type as it is sometimes encrypted 2021-08-10 16:21:59 +02:00
David Baker 264636c879 Merge pull request #1835 from matrix-org/travis/fsdk/get-perm
Add support for reading permissions from tree spaces
2021-08-10 11:08:51 +01:00
Michael Telatynski 9b50455049 Iterate PR, merge types with @types/PushRules 2021-08-10 11:03:05 +01:00
Michael Telatynski a531446396 tidy a bit more 2021-08-10 10:46:13 +01:00
Michael Telatynski f876c35283 Fix some bad conversion artifacts 2021-08-10 10:34:05 +01:00
Michael Telatynski 1bcec53c6b delint 2021-08-10 10:22:40 +01:00
Michael Telatynski 0ad5ef4e9b Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/ts/12 2021-08-10 10:21:13 +01:00
David Baker 94726aa1d5 Merge pull request #1832 from matrix-org/dbkr/preview_changelog
Add changelog preview action
2021-08-09 20:21:22 +01:00
Travis Ralston 8da2f91e22 Add support for reading permissions from tree spaces
This was originally thought to be able to be performed in another way, but unfortunately isn't as easy as originally predicted.
2021-08-09 08:43:46 -06:00
Dariusz Niemczyk b03555a50b Merge pull request #1833 from SimonBrandner/fix/screensharingc-crash
Fix error on turning off screensharing
2021-08-08 21:08:52 +02:00
Šimon Brandner b61312feca Fix screensharing crash
We have to first stop the track and only then delete the feed as stopping the tracks depends on the feed being defined

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-08 11:10:08 +02:00
David Baker ea9459d330 Add changelog preview action 2021-08-06 23:05:00 +01:00
Travis Ralston 3edfe70a7b Merge pull request #1831 from matrix-org/travis/fsdk/expose-get-file
Expose a getFileEvent() function off a MSC3089Branch
2021-08-06 09:15:24 -06:00
Travis Ralston 5482a19979 Expose a getFileEvent() function off a MSC3089Branch 2021-08-06 09:09:03 -06:00
Michael Telatynski e1678aaf11 Merge pull request #1830 from matrix-org/t3chguy/js-docfix
Fix type documentation on MatrixClient::setRoomMutePushRule
2021-08-06 14:48:05 +01:00
Michael Telatynski 2bdb570f3c Fix type documentation on MatrixClient::setRoomMutePushRule 2021-08-06 09:38:50 +01:00
Germain 3723b2da39 Merge pull request #1829 from matrix-org/gsouquet/jest-typescript 2021-08-05 11:00:40 +01:00
Germain Souquet b63af00579 Exclude tests when building browserify package 2021-08-05 11:56:26 +02:00
David Baker 4ed6fbe5fe Merge pull request #1820 from SimonBrandner/fix/hangup-reason/18219
Send `user_hangup` reason if the opponent supports it
2021-08-05 10:41:28 +01:00
Germain Souquet 026260502b Fix linting issues in TypeScript test files 2021-08-05 11:37:27 +02:00
Germain Souquet c45bc91389 Include all TypeScript @types listed in project dependency
Fixes vector-im/element-web#17743

The package @types/jest was not discovered because if types is specified, only packages listed will be included in the global scope.
2021-08-05 11:16:28 +02:00
Germain Souquet 18113900fe Implementation of event threading 2021-08-04 17:28:08 +02:00
David Baker 69358f8372 Merge pull request #1825 from matrix-org/dbkr/codeowners
Add CODEOWNERS
2021-08-04 13:21:37 +01:00
David Baker 8800c6d2e0 Add CODEOWNERS
This should make github auto review request from the element-web team
2021-08-04 13:16:15 +01:00
David Baker b63de6a902 Merge pull request #1823 from matrix-org/dbkr/argh_the_linting
Update eslint plugin & fix silly indenting
2021-08-04 10:03:20 +01:00
David Baker b1cec7d6a5 Merge pull request #1824 from matrix-org/dbkr/allchange
Switch to new changelog generator
2021-08-04 10:03:08 +01:00
David Baker 08821e499c Switch to new changelog generator 2021-08-03 17:51:42 +01:00
David Baker 3ca84cfc49 Update eslint plugin & fix silly indenting
As per matrix-org/eslint-plugin-matrix-org#15
this caused a bunch of silly indenting to creep in, so this fixes it
back to the previous style.
2021-08-03 17:15:25 +01:00
David Baker be8ecce995 Merge pull request #1821 from SimonBrandner/task/cleanup
Clean-up some VoIP code
2021-08-03 13:18:47 +01:00
Šimon Brandner 775c3465bb Rename so that VS Code spell checker shutsup
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-03 10:05:05 +02:00
Šimon Brandner 7484e3c032 Improve wording
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-03 09:48:23 +02:00
Šimon Brandner b93e79274f Move for better organization
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-03 09:45:27 +02:00
Šimon Brandner fee6a96350 Rename for consistency
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-03 09:44:44 +02:00
Šimon Brandner ac2c09108f Improve styling a bit
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-03 09:42:20 +02:00
Šimon Brandner 5b13785115 Make a few things into one liners
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-03 09:40:04 +02:00
Šimon Brandner dd3c53edac Extract weSentTheEvent into a variable
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-03 09:37:41 +02:00
Šimon Brandner 904071ebe6 Extract type into a variable
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-03 09:33:40 +02:00
Šimon Brandner 7e0aeb425d Move things we can into a switch statement
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-03 09:31:06 +02:00
Šimon Brandner f4e985b5cc Fix typos
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-02 21:38:05 +02:00
Šimon Brandner 03134832e9 Standardise screensharing casing
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-02 21:30:33 +02:00
Šimon Brandner dbb0f66094 Remove unused mute state stuff
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-02 21:29:09 +02:00
Šimon Brandner 4631cd1fe3 Make localUsermediaStream into a getter
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-02 21:28:49 +02:00
Šimon Brandner bc07ad5909 Make localScreenSharingStream into a getter
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-02 21:25:55 +02:00
Šimon Brandner 8b0c4a0efb Merge remote-tracking branch 'upstream/develop' into task/cleanup
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-02 21:17:14 +02:00
Šimon Brandner eac77a6695 Remove config as it wasn't used
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-02 21:15:36 +02:00
Šimon Brandner aae8f1c706 screenSharingStream -> localScreenSharingStream
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-02 21:14:59 +02:00
Šimon Brandner 1e281f6838 localAVStream -> localUsermediaStream
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-08-02 21:02:09 +02:00
David Baker aef89e4a26 Merge pull request #1812 from SimonBrandner/feature/muting
Support for MSC3291: Muting in VoIP calls
2021-08-02 17:20:42 +01:00
RiotRobot 8a1bc98d4e Resetting package fields for development 2021-08-02 13:03:59 +01:00
RiotRobot 8b2d5959ec Merge branch 'master' into develop 2021-08-02 13:03:59 +01:00
RiotRobot 4891446dc3 v12.2.0 2021-08-02 13:00:06 +01:00
David Baker cace8f232f Changelog for v12.2.0 2021-08-02 12:45:25 +01:00
Michael Telatynski 88b8b24629 Merge room hierarchy pages 2021-07-30 11:01:08 +01:00
Šimon Brandner b15ba8c5e3 Send hangup reason if the opponent supports it
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-30 08:54:39 +02:00
Michael Telatynski 58c60d85e7 Refactor Space Hierarchy stuff in preparation for pagination 2021-07-29 17:35:17 +01:00
Hubert Chathi 529fe93ab1 Merge pull request #1819 from uhoreg/fix_aes_iv
Only clear bit 63 when we create the IV
2021-07-29 12:07:54 -04:00
Hubert Chathi 600438d02e only clear bit 63 when we create the IV
If we got the IV from somewhere else, we should just use it as-is, rather than
trying to re-clear the bit.
2021-07-29 11:58:08 -04:00
Michael Telatynski 21a357c433 fix typo 2021-07-29 15:00:39 +01:00
Michael Telatynski 9c05077c26 Merge pull request #1816 from matrix-org/t3chguy/hidden-names 2021-07-29 12:55:40 +01:00
Michael Telatynski d49d6936a5 Add support for /children API and fall back to /spaces API if M_UNRECOGNIZED 2021-07-29 12:16:34 +01:00
Šimon Brandner e6696f78f4 Allow recieving unprefixed version of m.call.sdp_stream_metadata_changed
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-29 13:00:48 +02:00
Michael Telatynski f2da3ba6ae Apply hidden char check to rawDisplayName too 2021-07-29 11:00:30 +01:00
Šimon Brandner db5de4c6e4 Merge remote-tracking branch 'upstream/develop' into feature/muting 2021-07-29 09:10:38 +02:00
Šimon Brandner ca042b3647 Fix handling when remoteSDPStreamMetadata is null
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-28 20:12:21 +02:00
Šimon Brandner 87fd3521ea Fix types
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-28 20:11:51 +02:00
Šimon Brandner b3c66848e2 Handle missing params
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-28 19:06:24 +02:00
Šimon Brandner 606aa29381 Use recursivelyAssign
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-28 18:37:48 +02:00
Šimon Brandner 2d25150a21 Write tests for recursivelyAssign()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-28 17:57:16 +02:00
Šimon Brandner ca7a457094 Add recursivelyAssign()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-28 17:56:51 +02:00
Šimon Brandner 23ab3e3ec0 Test mute metadata gets mapped onto feeds
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-28 15:29:28 +02:00
Šimon Brandner b11a8459d8 Add a method for setting remoteSDPStreamMetadata
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-28 15:16:24 +02:00
Šimon Brandner 057eb0f2a5 Make mute state props mandetory
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-28 15:00:21 +02:00
Šimon Brandner 8de6c5aad1 Fix typo which caused all feeds to be muted by default
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-28 14:59:57 +02:00
Šimon Brandner 6fda2a0c57 Handle purpose changes
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-28 14:15:00 +02:00
David Baker efeeba265f Merge pull request #1813 from SimonBrandner/fix/call-view/18221
Handle DTMF support
2021-07-28 11:27:09 +01:00
Šimon Brandner 35ca7fdc48 Fix call transfer support
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-28 08:15:50 +02:00
Šimon Brandner 959e3f68a4 Handle DTMF support
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-27 17:51:13 +02:00
RiotRobot f20b3211e6 v12.2.0-rc.1 2021-07-27 15:43:44 +01:00
RiotRobot 9b5302ebf2 Prepare changelog for v12.2.0-rc.1 2021-07-27 15:43:43 +01:00
Šimon Brandner 19f90f56be Merge remote-tracking branch 'upstream/develop' into feature/muting 2021-07-27 16:40:07 +02:00
David Baker a69d9a9f20 Merge pull request #1685 from SimonBrandner/fix/12652/screen-share
Support for screen-sharing using multi-stream VoIP (MSC3077)
2021-07-27 15:36:40 +01:00
Michael Telatynski c5e113d0ca Merge pull request #1808 from matrix-org/t3chguy/ts/13 2021-07-27 15:36:21 +01:00
Šimon Brandner 1df90f8fc7 Basic implementation of MSC3291
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-27 14:31:13 +02:00
Šimon Brandner 8e6040ad6f Give CallFeed a mute state
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-27 14:23:58 +02:00
Šimon Brandner 21f107d734 Add types for MSC3291
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-27 14:19:54 +02:00
Dariusz Niemczyk e6d40f0c17 Merge pull request #1810 from matrix-org/fix/update-eslint-config
Update ESLint config
2021-07-27 09:51:58 +02:00
Dariusz Niemczyk 6b8bb46790 Update ESLint config 2021-07-26 16:37:47 +02:00
Michael Telatynski 05c3236e50 Merge pull request #1807 from bradtgmurray/improve-event-clear-event-state 2021-07-26 12:55:49 +01:00
Brad Murray 4f8c20ddae Fix reattempting decryption check 2021-07-26 07:49:42 -04:00
Brad Murray 8aa283d994 Fix lint in tests 2021-07-25 11:45:09 -04:00
Brad Murray e85b3b6a8d Fix the tests and add a test 2021-07-25 11:41:08 -04:00
Brad Murray 04cd9b55f7 Merge remote-tracking branch 'upstream/develop' into improve-event-clear-event-state 2021-07-25 11:23:11 -04:00
Brad Murray faf237e588 Respect the comment in getClearContent 2021-07-25 11:19:36 -04:00
Šimon Brandner 019abc7ad8 Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share 2021-07-25 08:13:23 +02:00
Michael Telatynski db4b6fe2af Update to beta better-docs to fix the gendocs issue 2021-07-24 12:10:45 +01:00
Michael Telatynski c340e6f1ba delint and fix tests 2021-07-24 12:01:23 +01:00
Michael Telatynski f227a307c1 Fix some confused signatures/types 2021-07-24 11:40:30 +01:00
Michael Telatynski 011a2acfd2 Convert crypto/store/* to Typescript 2021-07-24 11:35:30 +01:00
Michael Telatynski c2b5b14d26 Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/ts/12
 Conflicts:
	src/client.ts
	src/interactive-auth.ts
	src/models/search-result.ts
2021-07-23 23:46:15 +01:00
Brad Murray ad79a64f1c Address review feedback 2021-07-23 16:25:39 -04:00
Brad Murray 91f5df1e48 Fix incorrect indentation 2021-07-23 16:16:39 -04:00
Brad Murray 980d6fc2ae Differentiate between an undefined clearEvent and a falsey property of the clearEvent 2021-07-23 16:13:46 -04:00
Brad Murray 5aa60b8056 Clean up Event.clearEvent handling 2021-07-23 15:56:24 -04:00
Michael Telatynski dc154a00a8 Merge pull request #1806 from matrix-org/t3chguy/eslint1 2021-07-23 16:24:58 +01:00
Michael Telatynski a087acf65d Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/eslint1 2021-07-23 16:08:31 +01:00
Michael Telatynski 05d0755b6a Update matrix-org-eslint-plugin and tighten max warning limit
Whilst it is down, make the most of it!
2021-07-23 16:07:49 +01:00
Michael Telatynski cd86aa7d9e Merge pull request #1745 from matrix-org/t3chguy/fix/17686 2021-07-23 09:09:15 +01:00
Šimon Brandner fcbbcc0398 Always return true for voice calls
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-22 09:24:59 +02:00
Travis Ralston 2bd99b5cb0 Merge pull request #1771 from matrix-org/j94/functional-members
Functional members
2021-07-21 18:25:14 -06:00
David Baker 82d248cb8e Merge pull request #1802 from matrix-org/dbkr/yarn_upgrade_210721
yarn upgrade
2021-07-21 16:58:49 +01:00
David Baker ce2803ebaa yarn upgrade 2021-07-21 15:37:19 +01:00
Germain e85038e888 Merge pull request #1801 from matrix-org/gsouquet/localecompare-perf
Improve calculateRoomName performances by using Intl.Collator
2021-07-21 15:28:22 +01:00
Šimon Brandner ceafb1c5d0 Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share 2021-07-21 15:58:46 +02:00
Michael Telatynski a87858840b Merge pull request #1798 from matrix-org/t3chguy/eslint 2021-07-21 14:53:12 +01:00
Germain Souquet f708c47385 Improve calculateRoomName performances by using Intl.Collator 2021-07-21 14:18:22 +02:00
Michael Telatynski 9eb918f701 Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/fix/17686 2021-07-21 10:56:21 +01:00
Christian Paul b4bffd2700 Merge remote-tracking branch 'origin/develop' into j94/functional-members 2021-07-21 11:23:22 +02:00
Šimon Brandner 80d7c88b40 Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share 2021-07-20 15:47:36 +02:00
Travis Ralston fb315ac75b Merge pull request #1799 from matrix-org/travis/error1
Actually print IndexedDB command error if there is one
2021-07-20 07:38:43 -06:00
Šimon Brandner bee840ce16 Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share 2021-07-20 13:30:01 +02:00
Christian Paul afa67688f8 Add test for service member who is not a room member 2021-07-20 12:51:08 +02:00
Michael Telatynski 0c06e47782 Update eslint-plugin-matrix-org 2021-07-20 09:15:26 +01:00
Travis Ralston ea646c673b Actually print idb command error if there is one 2021-07-19 23:31:39 -06:00
Michael Telatynski 5cf6684129 Conform to new typescript eslint rules 2021-07-19 22:47:32 +01:00
Christian Paul cb2b9619ab Replace .indexOf() !== -1 with .includes() for readability 2021-07-19 18:22:29 +02:00
Christian Paul b8c2a57829 Add test with multiple service_members 2021-07-19 18:17:39 +02:00
Christian Paul 718a22f574 Merge branch 'j94/functional-members' of github.com:matrix-org/matrix-js-sdk into j94/functional-members 2021-07-19 18:01:05 +02:00
Christian Paul 324cd886a2 Merge remote-tracking branch 'origin/develop' into j94/functional-members 2021-07-19 18:00:59 +02:00
Christian Paul 4cf655785e Add tests 2021-07-19 17:59:11 +02:00
Michael Telatynski f686d70157 Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/fix/17686 2021-07-19 16:47:39 +01:00
RiotRobot b936b4a2ce Resetting package fields for development 2021-07-19 15:52:47 +01:00
RiotRobot 026839d7e7 Merge branch 'master' into develop 2021-07-19 15:52:46 +01:00
RiotRobot 830a4a741e v12.1.0 2021-07-19 15:49:55 +01:00
RiotRobot a3d9ed19a4 Prepare changelog for v12.1.0 2021-07-19 15:49:54 +01:00
David Baker 8f9f5fd5b0 Merge pull request #1796 from matrix-org/dbkr/upgrade_eslint_plugin_matrix_org
Update eslint-plugin-matrix-org
2021-07-19 15:33:45 +01:00
David Baker 805267f97f Update eslint-plugin-matrix-org 2021-07-19 15:23:20 +01:00
Christian Paul 4a1cd159a4 Update event.ts 2021-07-19 11:53:43 +02:00
Christian Paul 7129c7c7af Update src/models/room.ts
Co-authored-by: Travis Ralston <travisr@matrix.org>
2021-07-19 10:56:15 +02:00
Travis Ralston ecc9fda28b Merge pull request #1778 from matrix-org/travis/notifications-2
Add minimal types for "notification settings" UI
2021-07-16 23:53:13 -06:00
Travis Ralston 7f7c3cbea5 Fix exclusion types 2021-07-16 23:48:41 -06:00
Travis Ralston fc8cd39d1a Optionalize opts 2021-07-16 16:32:49 -06:00
Travis Ralston 589c66bb12 Re-appease linter 2021-07-16 16:30:06 -06:00
Travis Ralston 16fe5a91d5 Consolidate types 2021-07-16 16:27:50 -06:00
Travis Ralston b57b7a65ee Merge branch 'develop' into travis/notifications-2 2021-07-16 16:26:05 -06:00
Šimon Brandner 019e93e76c Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share 2021-07-16 21:38:10 +02:00
Michael Telatynski 69415ba2c3 Merge pull request #1791 from matrix-org/t3chguy/querystring 2021-07-16 19:57:22 +01:00
Šimon Brandner 1607ad2111 Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share 2021-07-16 20:11:39 +02:00
Michael Telatynski f1a0c46a29 Deprecate groups APIs 2021-07-16 17:45:07 +01:00
Michael Telatynski 9b81b805be create utility to decode qs into objects 2021-07-16 13:07:01 +01:00
Michael Telatynski 8379bb818e Switch from url to URL constructor 2021-07-16 13:01:27 +01:00
Michael Telatynski c62f2a0965 Merge pull request #1789 from matrix-org/t3chguy/fix/18008 2021-07-16 11:06:56 +01:00
Michael Telatynski d383e71aca Switch callEventHandler from listening on event to Room.timeline
so that it doesn't end up processing ephemerals, account data, remote echoes, etc etc
2021-07-15 17:44:17 +01:00
David Baker dbe93f598a Merge pull request #1787 from matrix-org/dbkr/new_changelogs
Contributing guidelines for new changelog generation
2021-07-15 14:12:20 +01:00
David Baker 2bc5f7132d Merge remote-tracking branch 'origin/develop' into dbkr/new_changelogs 2021-07-15 14:07:51 +01:00
David Baker b17f339011 Merge pull request #1786 from matrix-org/dbkr/fix_contributing_link
Fix link to CONTRIBUTING.md
2021-07-15 14:06:20 +01:00
Michael Telatynski e2b04d543a Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/fix/17686
 Conflicts:
	src/@types/partials.ts
	src/client.ts
2021-07-15 10:03:05 +01:00
Michael Telatynski 0601f98265 Merge pull request #1788 from SimonBrandner/feature/hidden-rrs
Use an unstable prefix for MSC2885: Hidden read receipts
2021-07-15 08:46:54 +01:00
Šimon Brandner bae5650e7a Fix MSC number
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2021-07-15 09:41:40 +02:00
Šimon Brandner ff40b4dc4a Fix MSC number
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2021-07-15 09:41:35 +02:00
Germain 6098f74d8f Merge pull request #1782 from psrpinto/fix/naming 2021-07-15 08:07:05 +01:00
David Baker 45c153321c Use X-Breaking-Change
Apparently we already have this label in react SDK (for some reason)
so let's use it. Plus, it's clearer that it's for changes rather than
issues that cause things to break.
2021-07-14 22:46:22 +01:00
David Baker 19aedebff1 Update other label mentions 2021-07-14 22:16:00 +01:00
David Baker 5392f616b4 Use existing issues labels / scheme
Co-authored-by: J. Ryan Stinnett <jryans@gmail.com>
2021-07-14 22:15:18 +01:00
David Baker c4ccb9d493 Use a real-life example which should hopefully be clearer 2021-07-14 22:00:42 +01:00
David Baker b0726b5008 On brand ourself
Co-authored-by: J. Ryan Stinnett <jryans@gmail.com>
2021-07-14 21:57:48 +01:00
David Baker 9c221419ef On-brand
Co-authored-by: J. Ryan Stinnett <jryans@gmail.com>
2021-07-14 21:57:29 +01:00
David Baker fddf0c47fb Fix formatting
Co-authored-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-14 21:57:04 +01:00
David Baker b17862e212 s/tag/label/
Also make breaking change notation clearer.
2021-07-14 19:55:58 +01:00
David Baker e133898554 Fix link to CONTRIBUTING.md 2021-07-14 19:48:47 +01:00
David Baker ee5a0e7edf Internal PRs shouldn't have changelog entries by default 2021-07-14 19:47:46 +01:00
David Baker b538c06fcb Update contributing guidelines to for new changelog stuff 2021-07-14 19:45:42 +01:00
David Baker 49cbaa579f Merge pull request #1785 from matrix-org/dbkr/contributing-to-md
Convert CONTRIBUTING to markdown
2021-07-14 19:05:26 +01:00
David Baker 20bd9b525b Convert CONTRIBUTING to markdown
Because everything else is
2021-07-14 19:02:03 +01:00
Michael Telatynski 3038fc523c Merge pull request #1780 from matrix-org/t3chguy/ts/c3
Use webpack worker-loader instead of homegrown hack
2021-07-14 18:25:21 +01:00
Michael Telatynski 52a85e3f82 Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/ts/c3 2021-07-14 17:52:42 +01:00
Michael Telatynski 3df1c4b507 Merge pull request #1779 from matrix-org/t3chguy/ts/c2 2021-07-14 17:44:35 +01:00
Travis Ralston 6ada02e245 Merge pull request #1784 from matrix-org/travis/widgets/fix-enc
Expose MatrixEvent's internal clearEvent as a function
2021-07-14 10:33:45 -06:00
Šimon Brandner 9184a0d902 Use MSC2885 unstable prefix
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-14 18:27:38 +02:00
Travis Ralston 4bc4e1b76f remove useless code 2021-07-14 10:22:36 -06:00
Michael Telatynski cb192d3c74 Merge pull request #1777 from matrix-org/t3chguy/ts/c1 2021-07-14 17:19:03 +01:00
Travis Ralston 11dabf9a68 rename 2021-07-14 10:18:12 -06:00
Travis Ralston ea4dfd003f It's not a partial anymore 2021-07-14 10:09:23 -06:00
Travis Ralston 326b14402f Return a properly shaped event 2021-07-14 10:07:43 -06:00
RiotRobot d71ca8a9e0 v12.1.0-rc.1 2021-07-14 16:16:04 +01:00
RiotRobot 45259f0773 Prepare changelog for v12.1.0-rc.1 2021-07-14 16:16:03 +01:00
Travis Ralston 83337eee57 Expose MatrixEvent's internal clearEvent as a function 2021-07-13 23:09:37 -06:00
Michael Telatynski aed861036b Merge pull request #1783 from SimonBrandner/ignore-vscode 2021-07-13 19:19:58 +01:00
Šimon Brandner 3ff05c0947 Ignore vscode
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-13 20:11:58 +02:00
Paulo Pinto 5b2a53a2b4 Undo changes to the CHANGELOG
Signed-off-by: Paulo Pinto <paulo.pinto@automattic.com>
2021-07-13 18:30:57 +01:00
Paulo Pinto 3f6aee1443 Use correct term for identity server
Signed-off-by: Paulo Pinto <paulo.pinto@automattic.com>
2021-07-13 16:27:40 +01:00
Paulo Pinto dba70d4ce2 Standardise casing of integration manager
Signed-off-by: Paulo Pinto <paulo.pinto@automattic.com>
2021-07-13 16:27:40 +01:00
Paulo Pinto ab3dfd48ae Standardise spelling of identity server
Signed-off-by: Paulo Pinto <paulo.pinto@automattic.com>
2021-07-13 16:27:40 +01:00
Paulo Pinto ab59e9134b Standardise casing of identity server
Signed-off-by: Paulo Pinto <paulo.pinto@automattic.com>
2021-07-13 16:27:40 +01:00
Paulo Pinto 56921f0961 Standardise spelling and casing of homeserver
Signed-off-by: Paulo Pinto <paulo.pinto@automattic.com>
2021-07-13 16:27:40 +01:00
Michael Telatynski f9005c33e9 Fix casing of IIndexedDBBackend 2021-07-13 11:29:32 +01:00
Michael Telatynski b7c5b36556 Merge pull request #1781 from matrix-org/t3chguy/dt1
Make `Crypto::inRoomVerificationRequests` public
2021-07-13 11:12:23 +01:00
Michael Telatynski 33deef9f2c Rework devtools and get rid of flippy tgl button 2021-07-13 10:33:33 +01:00
Travis Ralston d5c3cb1b7f More minimal types for pushers & push rules 2021-07-12 21:50:27 -06:00
Michael Telatynski 19d8f2bbac Use webpack worker-loader to load the IndexedDB worker instead of homegrown hack 2021-07-12 18:43:21 +01:00
Michael Telatynski 1aa103d8d2 Fix spurious argument appearing on the interface and TODO 2021-07-12 18:41:26 +01:00
Michael Telatynski 75f630e45d Add missing interface 2021-07-12 18:39:29 +01:00
Michael Telatynski 1defde0f5e Convert IndexedDB store & worker to Typescript 2021-07-12 18:36:47 +01:00
Michael Telatynski e38595e735 remove unused import 2021-07-12 09:14:44 +01:00
Michael Telatynski c0e16ac98c Update some more 2021-07-12 09:10:27 +01:00
Michael Telatynski b33429317c Fix setTimeout/setInterval typing 2021-07-12 09:02:47 +01:00
Michael Telatynski e3f7c848d7 iterate types based on PR review 2021-07-12 08:44:34 +01:00
Travis Ralston 5f2ed4450e -- 2021-07-11 21:04:10 -06:00
Travis Ralston 11e25ea9a2 Appease linter 2021-07-11 21:02:33 -06:00
Travis Ralston fb7184e6fb Reorganize types a bit 2021-07-11 20:56:52 -06:00
Travis Ralston 3c77a8772a Add minimal types for "notification settings" UI
For https://github.com/vector-im/element-web/issues/17782
2021-07-11 20:54:51 -06:00
Travis Ralston 5ce787c6ea Merge pull request #1765 from SimonBrandner/fix/add-event-meta-for-filtered/5692
Call `setEventMetadata()` for filtered `timelineSet`s
2021-07-11 02:51:51 -06:00
Šimon Brandner 67189ad323 Use an enum
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-11 10:47:42 +02:00
Michael Telatynski 3bff5430f6 delint 2021-07-10 15:55:19 +01:00
Michael Telatynski 17efcad6fe Improve and consolidate typing 2021-07-10 15:50:40 +01:00
Christian Paul d7e6cee19c Update room.ts 2021-07-10 03:44:03 +02:00
Christian Paul 116085e927 Fix linter error 2021-07-10 03:08:51 +02:00
Christian Paul 96e6e7b1e8 Update event.ts 2021-07-09 16:44:39 +02:00
Hubert Chathi 061199ec3c Merge pull request #1775 from uhoreg/symmetric_backup
Symmetric backup
2021-07-09 10:31:43 -04:00
David Baker 2d67a35af5 Merge pull request #1776 from matrix-org/dbkr/rescue_lost_megolm_key
Attempt to fix megolm key not being in SSSS
2021-07-09 14:30:55 +01:00
Michael Telatynski 4cb6ad9e70 Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/fix/17686 2021-07-09 08:53:24 +01:00
Hubert Chathi d639a29501 more type improvements 2021-07-08 18:47:22 -04:00
Hubert Chathi ac02f30dc8 improve types 2021-07-08 18:10:37 -04:00
David Baker 05a20ab56f Fix up keys even if key backup isn't enabled
Mostly because that's what the test tests, so let's keep that
behaviour the same.
2021-07-08 21:30:50 +01:00
David Baker 964aa6d94a Update comment 2021-07-08 21:20:34 +01:00
David Baker 1a17b138ce Attempt to fix megolm key not being in SSSS
If the account has both a key backup and SSSS enabled but the key
backup key isn't stored in SSSS, try to save it there by getting
it from either the cache or the user (if perhaps it's the same as
their security passphrase but lost a passthrough entry).

Fixes https://github.com/vector-im/element-web/issues/17886
2021-07-08 21:12:45 +01:00
Hubert Chathi 2e27e247f3 Merge branch 'develop' into symmetric_backup 2021-07-08 15:16:07 -04:00
Hubert Chathi ef8e4d6d35 fix the tests that got broken by the last commit 2021-07-08 11:19:46 -04:00
Hubert Chathi 8bee38367a use the MSC number 2021-07-08 10:14:53 -04:00
Šimon Brandner 0318c65847 Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share 2021-07-08 13:22:34 +02:00
David Baker ab5b69bbdb Merge pull request #1774 from matrix-org/dbkr/tsify_secretstorage
Convert SecretStorage to TypeScript
2021-07-08 09:18:23 +01:00
Hubert Chathi 9f4c5af665 fix test 2021-07-07 20:19:23 -04:00
Hubert Chathi e275301e8b lint 2021-07-07 19:50:16 -04:00
Hubert Chathi c8a7820cb3 fix types 2021-07-07 19:46:01 -04:00
Hubert Chathi 17dc1bda19 Merge branch 'develop' into symmetric_backup 2021-07-07 19:19:56 -04:00
David Baker 8d9de37099 type for reason 2021-07-07 21:21:22 +01:00
David Baker 29b403da45 visibility 2021-07-07 21:20:48 +01:00
David Baker 1fd1ba2ada de-underscore 2021-07-07 21:19:51 +01:00
David Baker 5fbce3b928 Consistent values between various account data interfaces 2021-07-07 21:18:14 +01:00
Hubert Chathi 9019bce843 mark session as untrusted when the session data has the untrusted flag 2021-07-07 16:16:07 -04:00
David Baker fd2d106f2a extract SecretStorageKeyObject 2021-07-07 21:14:34 +01:00
David Baker 64a1c83acc param names 2021-07-07 21:11:11 +01:00
David Baker 8cc250e19d param names 2021-07-07 21:10:51 +01:00
David Baker dbd737c87d param names & comment any 2021-07-07 21:10:13 +01:00
David Baker 33398e78cd Fix duplicate inlined / explicit members 2021-07-07 21:05:45 +01:00
David Baker 79c6d0180c remove TODO 2021-07-07 21:04:07 +01:00
David Baker e7a198dc0c Line breaks
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2021-07-07 21:00:02 +01:00
David Baker ef08c35c6f Line break
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2021-07-07 20:59:32 +01:00
David Baker 41b816538e Line break
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2021-07-07 20:58:47 +01:00
David Baker 87d9fe24f5 Shorthand
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2021-07-07 20:58:08 +01:00
David Baker d11c95a23f Add type
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2021-07-07 20:57:40 +01:00
David Baker 3c9b846116 Shorthand
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2021-07-07 20:56:55 +01:00
David Baker c701e2e6d3 Inline members in ctor
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2021-07-07 20:55:23 +01:00
David Baker 11b490c77f Line breaks
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2021-07-07 20:54:48 +01:00
David Baker 0544ab2617 Add return type
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2021-07-07 20:52:07 +01:00
David Baker 5c6d3724b0 Move some interfaces around 2021-07-07 20:21:44 +01:00
David Baker c34d4e777f Convert SecretStorage to TypeScript 2021-07-07 19:37:22 +01:00
Michael Telatynski 588d783a55 Merge pull request #1721 from matrix-org/t3chguy/fix/17494 2021-07-07 18:10:35 +01:00
Michael Telatynski 79f74fdff4 Improve return type for getUrlPreview 2021-07-07 17:54:46 +01:00
Germain 6f5dbb782e Merge pull request #1773 from matrix-org/gsouquet/ci-pure-lockfile
Do not generate a lockfile when running in CI
2021-07-07 15:23:25 +01:00
Germain Souquet f0ae9b0100 Do not generate a lockfile when running in CI 2021-07-07 16:11:14 +02:00
Michael Telatynski fd260a023c Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/fix/17494
 Conflicts:
	src/client.js
2021-07-07 14:03:12 +01:00
Michael Telatynski e775bcac3c Convert SearchResult, InteractiveAuth, PushProcessor and Scheduler to Typescript 2021-07-07 11:08:54 +01:00
Šimon Brandner 641c852ee2 Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share 2021-07-07 10:43:23 +02:00
Christian Paul ab679c2216 Update src/@types/event.ts 2021-07-07 00:39:26 +02:00
Christian Paul 96420a75ab room.ts: Use UNSTABLE_ELEMENT_FUNCTIONAL_USERS 2021-07-06 19:35:56 +02:00
Christian Paul c4263692f0 Update event.ts 2021-07-06 19:34:44 +02:00
Christian Paul 0074b71cbf Fix object-curly-spacing linting errors 2021-07-06 19:10:25 +02:00
Christian Paul d219c2f462 Fix mistakes 2021-07-06 19:07:20 +02:00
Christian Paul 4700dc0375 Remove trailing spaces 2021-07-06 18:59:02 +02:00
Christian Paul a248bbc46b Update src/models/room.ts
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2021-07-06 18:58:07 +02:00
Christian Paul d60affc1b8 room.calculateRoomName: Exclude service members 2021-07-06 18:35:34 +02:00
Christian Paul 8c0f5b4e31 Update event.ts: Add io.element.functional_members 2021-07-06 16:48:57 +02:00
Michael Telatynski a617f6cc55 Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/fix/17686 2021-07-06 10:12:18 +01:00
Michael Telatynski 9e66026bdc Export MSC3244 type 2021-07-06 10:08:40 +01:00
RiotRobot dc90115a1b Resetting package fields for development 2021-07-05 14:57:15 +01:00
RiotRobot 13b250d291 Merge branch 'master' into develop 2021-07-05 14:57:15 +01:00
RiotRobot 834ab22923 v12.0.1 2021-07-05 14:54:21 +01:00
RiotRobot 17be68a39d Prepare changelog for v12.0.1 2021-07-05 14:54:21 +01:00
Michael Telatynski 48ee03e278 Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/fix/17686 2021-07-05 13:45:56 +01:00
David Baker 5b86d8b837 Merge pull request #1766 from matrix-org/dbkr/secretrequest_nopromise
Tidy up secret requesting code
2021-07-02 14:50:50 +01:00
David Baker 521fce59ea Tidy up secret requesting code
Use a plain async function rather than a promise, so we don't
have to squelch the lint warning.
2021-07-02 14:46:30 +01:00
Michael Telatynski bbe1ba7328 Improve typing 2021-07-02 14:38:17 +01:00
Michael Telatynski ce7f20219f Merge pull request #1763 from matrix-org/t3chguy/ts/11
Convert Sync and SyncAccumulator to Typescript
2021-07-02 11:03:27 +01:00
Šimon Brandner aad33bd1b7 Formatting
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-02 11:04:54 +02:00
Šimon Brandner 9923c7e577 Merge remote-tracking branch 'upstream/develop' into fix/add-event-meta-for-filtered/5692
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-02 11:03:54 +02:00
Michael Telatynski ae870b1cc1 Merge pull request #1762 from matrix-org/t3chguy/ts/10 2021-07-02 09:51:56 +01:00
Michael Telatynski e3cb199540 Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/fix/17686 2021-07-02 09:06:15 +01:00
Šimon Brandner d9d19fdc63 delint
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-02 09:51:26 +02:00
Šimon Brandner f506882bf8 Call setEventMetadata() for filtered timelineSets
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-07-02 09:47:47 +02:00
David Baker e782183a49 Merge pull request #1764 from matrix-org/dbkr/ts_semicolons
Comply with new member-delimiter-style rule
2021-07-01 23:54:07 +01:00
David Baker 6699c4d8af Revert e0012d9b81
Accidentally comitted to develop
2021-07-01 23:49:13 +01:00
David Baker f027cbf170 Bump eslint plugin version
Also yarn has decided that other line is going away too
2021-07-01 23:48:56 +01:00
David Baker e0012d9b81 Bump eslint plugin version
Also yarn has decided that other line is going away too
2021-07-01 23:46:13 +01:00
David Baker b2ad957d29 Comply with new member-delimiter-style rule
Just `eslint --fix` with rule from
https://github.com/matrix-org/eslint-plugin-matrix-org/pull/9 in place
2021-07-01 23:28:18 +01:00
Michael Telatynski cab334ed73 Convert Sync and SyncAccumulator to Typescript 2021-07-01 22:47:50 +01:00
Michael Telatynski a99c1e96d6 fix field accesses in tests and default params 2021-07-01 21:05:58 +01:00
Michael Telatynski 261ac8b2d6 Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/fix/17686 2021-07-01 20:49:20 +01:00
Michael Telatynski 399237e781 use better types 2021-07-01 10:01:49 +01:00
Michael Telatynski 4b29f02f1c Convert EventTimeline, EventTimelineSet and TimelineWindow to TS 2021-07-01 09:53:55 +01:00
Hubert Chathi 558da5528b fix validity checks for backup info 2021-06-30 21:53:11 -04:00
J. Ryan Stinnett e3a00c2cb4 Merge pull request #1754 from aaronraimist/string-pl
Do not honor string power levels
2021-06-30 16:39:44 +01:00
Michael Telatynski 12deaa80a6 Merge pull request #1508 from matrix-org/t3chguy/ts/4 2021-06-29 22:24:18 +01:00
Germain a6507768bc Merge pull request #1760 from matrix-org/gsouquet/filepanel-typescript
Make filterId read/write and optional
2021-06-29 15:15:10 +01:00
RiotRobot 8f19ab066c v12.0.1-rc.1 2021-06-29 14:30:59 +01:00
RiotRobot 17decea576 Prepare changelog for v12.0.1-rc.1 2021-06-29 14:30:58 +01:00
Germain Souquet a2442add5b Make filterId read/write and optional 2021-06-29 13:46:42 +01:00
Michael Telatynski 7dbe95fa92 Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/fix/17686
 Conflicts:
	src/@types/partials.ts
	src/client.ts
2021-06-29 12:28:38 +01:00
Michael Telatynski 3339a2874d Merge pull request #1759 from matrix-org/t3chguy/fix/17753
Fix broken /messages filtering due to internal field changes in FilterComponent
2021-06-29 11:47:23 +01:00
Michael Telatynski 393047dec5 Fix broken /messages filtering due to internal field changes in FilterComponent 2021-06-29 11:34:59 +01:00
Aaron Raimist 55fb3d4e8e Also prevent sending unless safe integer
Synapse enforces this but I guess it doesn't hurt to also check here

Signed-off-by: Aaron Raimist <aaron@raim.ist>
2021-06-28 22:32:27 -05:00
Aaron Raimist 047180edc9 Merge branch 'develop' into string-pl 2021-06-28 22:17:55 -05:00
Michael Telatynski 1b0a388eb3 delint import 2021-06-25 10:27:55 +01:00
Michael Telatynski d50e559f97 MegolmDecryption::deviceId is not a valid field, sub it out for undefined as it isn't used meaningfully anyhow 2021-06-25 10:21:28 +01:00
Michael Telatynski 835aafcb17 Type the rest of algorithms because tests are unhappy otherwise 2021-06-25 10:18:46 +01:00
Michael Telatynski 48ad9ba3d7 Some more types 2021-06-24 21:48:55 +01:00
Michael Telatynski 3675e95970 fix the upset CI 2021-06-24 21:22:56 +01:00
Michael Telatynski 1ca13f4ce9 delint 2021-06-24 19:28:04 +01:00
Michael Telatynski 40aa6ba96a Even moar typescriptification 2021-06-24 19:19:41 +01:00
Michael Telatynski b4dc1e1555 Moar typescriptification 2021-06-24 17:41:52 +01:00
Michael Telatynski 3effeb7dc4 Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/ts/4
 Conflicts:
	package.json
	src/@types/global.d.ts
	src/crypto/key_passphrase.ts
	src/crypto/olmlib.ts
	src/utils.ts
2021-06-24 17:04:45 +01:00
Michael Telatynski 8c11839e4d Merge pull request #1749 from matrix-org/t3chguy/ts/5.1 2021-06-24 15:23:55 +01:00
Michael Telatynski 41817995bd Merge pull request #1739 from matrix-org/t3chguy/fix/15051 2021-06-24 11:20:10 +01:00
Hubert Chathi 8c9799d64c add tests and some fixes 2021-06-23 18:20:00 -04:00
Michael Telatynski 3a5e4ffa91 Fix yet more underscored accesses 2021-06-23 15:54:48 +01:00
Michael Telatynski 02afcc7d4b delint 2021-06-23 15:48:21 +01:00
Michael Telatynski e9007429dd fix more underscored accesses 2021-06-23 15:02:01 +01:00
Michael Telatynski 664d920dd1 Fix issues identified by Typescriptification 2021-06-23 14:51:40 +01:00
Michael Telatynski 5a8299f1a5 Convert more of js-sdk crypto and fix underscored field accesses 2021-06-23 14:47:25 +01:00
Michael Telatynski 6017fead19 Fix imports 2021-06-23 13:33:56 +01:00
Michael Telatynski 69050ed338 Fix import cycle 2021-06-23 13:12:26 +01:00
Michael Telatynski 2664848545 Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/ts/5.1 2021-06-23 13:05:34 +01:00
Aaron Raimist b18f0ff738 Do not honor string power levels
Signed-off-by: Aaron Raimist <aaron@raim.ist>
2021-06-22 22:34:34 -05:00
Michael Telatynski 1171c33f7a Merge pull request #1753 from matrix-org/t3chguy/ts/8 2021-06-22 22:04:22 +01:00
Michael Telatynski 6deb2bc7a9 Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/fix/15051
 Conflicts:
	src/models/MSC3089TreeSpace.ts
2021-06-22 22:03:44 +01:00
Michael Telatynski 7bda13aba6 Fix types of MatrixEvent sender & target 2021-06-22 20:37:50 +01:00
Travis Ralston 75719c3e0f Merge pull request #1744 from matrix-org/travis/keyshare-file-trees
Add keysharing on invites to File Tree Spaces
2021-06-22 10:48:57 -06:00
Michael Telatynski 2fb033b5ba Merge pull request #1746 from matrix-org/t3chguy/ts/5 2021-06-22 17:41:26 +01:00
Michael Telatynski 9f1db7a707 Merge pull request #1752 from matrix-org/t3chguy/ts/7
Improve type of IContent msgtype
2021-06-22 17:36:53 +01:00
Michael Telatynski a93de99d42 Improve type of IContent msgtype 2021-06-22 17:18:54 +01:00
Michael Telatynski 3d5774ac9e Update early MSC3083 support 2021-06-22 16:07:05 +01:00
Travis Ralston 1d8e0398e9 Merge pull request #1747 from SimonBrandner/feature/pr-template
Add PR template
2021-06-21 14:06:50 -06:00
Michael Telatynski cf76375ce0 Move Promise::allSettled typing from react-sdk to js-sdk 2021-06-21 21:04:29 +01:00
RiotRobot 284e2bb911 Resetting package fields for development 2021-06-21 16:28:40 +01:00
RiotRobot ecb790c179 Merge branch 'master' into develop 2021-06-21 16:28:40 +01:00
RiotRobot 467b75f2dc v12.0.0 2021-06-21 16:20:26 +01:00
RiotRobot 1f728cab92 Prepare changelog for v12.0.0 2021-06-21 16:20:25 +01:00
Michael Telatynski 66b17aa019 Add type for another-json dep 2021-06-19 19:45:29 +01:00
Michael Telatynski 27a6d1f878 Fix missing await identified by TS conversion 2021-06-19 19:44:47 +01:00
Michael Telatynski fc67dc6497 Convert crypto index to TS 2021-06-19 19:41:45 +01:00
Travis Ralston fedd9a981a Merge pull request #1738 from matrix-org/travis/event-fixes
Add functions to assist in immutability of Event objects
2021-06-18 11:23:08 -06:00
Travis Ralston 47e972a66c Incorporate merge conflict resolution 2021-06-18 11:18:29 -06:00
Travis Ralston 36bd4b5408 Merge remote-tracking branch 'origin/develop' into travis/event-fixes 2021-06-18 11:15:00 -06:00
Travis Ralston f502233ddc try to add more docs 2021-06-18 11:14:43 -06:00
Michael Telatynski 59c1edb623 fix tests 2021-06-18 17:56:51 +01:00
Michael Telatynski 9dd00c7731 Fix tests and tweak some optional types 2021-06-18 17:40:04 +01:00
Šimon Brandner 311edb4e4c Add PR template
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-06-18 17:30:50 +02:00
Michael Telatynski 924b8629d8 Updates around the use of private fields out of class 2021-06-18 16:29:10 +01:00
Michael Telatynski 9e11da1fa5 Fix typing 2021-06-18 16:11:11 +01:00
Michael Telatynski b760fa0ff5 Switch typescript target to es2020 as we use new things like Promise.allSettled and it needs it 2021-06-18 15:30:53 +01:00
Michael Telatynski cbce2f46c3 Fix position of invite_room_state on the event 2021-06-18 15:30:30 +01:00
Michael Telatynski 7aa5a79c86 Convert Room and RoomState to Typescript 2021-06-18 15:29:45 +01:00
Michael Telatynski fc029a9b9e Add MSC3244 types 2021-06-18 11:39:43 +01:00
Michael Telatynski 86ef80ae9a Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/fix/17686 2021-06-18 10:06:05 +01:00
Michael Telatynski e5b475ad89 Create Typescript types for JoinRule, GuestAccess, HistoryVisibility, including join_rule=restricted 2021-06-18 10:05:29 +01:00
Michael Telatynski 2c6858f149 Merge pull request #1742 from matrix-org/t3chguy/ts/5 2021-06-18 09:49:00 +01:00
Travis Ralston c1bff0b2ea delint 2021-06-17 17:38:57 -06:00
Travis Ralston 39892c98f9 Add keysharing on invites to File Tree Spaces 2021-06-17 17:36:49 -06:00
Travis Ralston b15487ec03 Misc lint 2021-06-17 14:24:39 -06:00
Travis Ralston 303119e113 Merge pull request #1743 from matrix-org/dependabot/npm_and_yarn/lodash-4.17.21
Bump lodash from 4.17.20 to 4.17.21
2021-06-17 11:08:33 -06:00
dependabot[bot] 09b729beb5 Bump lodash from 4.17.20 to 4.17.21
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21)

---
updated-dependencies:
- dependency-name: lodash
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-17 17:07:56 +00:00
Travis Ralston 6b73a77b2d Merge pull request #1740 from matrix-org/travis/invite-retry
Add invite retries to file trees
2021-06-17 11:07:06 -06:00
Michael Telatynski a2449ff6a7 Fix typos 2021-06-17 15:23:40 +01:00
Michael Telatynski b1b7522b80 Fix tests by updating private field names and spies 2021-06-17 15:18:52 +01:00
Michael Telatynski 608b0e7b93 Fix up some more type defs 2021-06-17 14:49:27 +01:00
Michael Telatynski 7c61b9cf7e Fix more type definitions 2021-06-17 14:24:53 +01:00
Michael Telatynski 50a973409a Typescript fixes due to MatrixEvent being TSified 2021-06-17 14:06:03 +01:00
Michael Telatynski bfea882416 Convert MatrixEvent to TS 2021-06-17 14:04:04 +01:00
Michael Telatynski f5e8fe836e Convert Room Member and User to TS 2021-06-17 14:03:52 +01:00
Michael Telatynski c4664a185f Convert Event Context to TS 2021-06-17 14:03:34 +01:00
Michael Telatynski c5f093c42f Merge pull request #1741 from matrix-org/t3chguy/ts/5
Convert IndexedDBStore to TS
2021-06-17 12:15:10 +01:00
Michael Telatynski 64f369b5de Fix IndexedDBStore ts-ification 2021-06-17 12:10:48 +01:00
Michael Telatynski 4b5653c09b Convert IndexedDBStore to TS 2021-06-17 11:37:41 +01:00
Michael Telatynski 837e739ec6 Merge pull request #1736 from matrix-org/t3chguy/ts4 2021-06-17 10:51:11 +01:00
Michael Telatynski b780ee8373 Update src/models/relations.ts
Co-authored-by: J. Ryan Stinnett <jryans@gmail.com>
2021-06-17 10:23:09 +01:00
Travis Ralston fe5bfbf76f The linter needed appeasing 2021-06-16 20:27:03 -06:00
Travis Ralston d924617672 Add invite retries to file trees 2021-06-16 20:24:48 -06:00
Michael Telatynski c545c7ca70 fix MSC3089TreeSpace incorrect type assumption 2021-06-16 20:32:46 +01:00
Michael Telatynski 9eb9f3a117 also do same update on the 3pid invite paths 2021-06-16 20:26:50 +01:00
Michael Telatynski 7862fd9679 just update jsdoc/ts return types due to contention. 2021-06-16 20:24:57 +01:00
Travis Ralston 17402e8475 Work around docgen 2021-06-15 14:32:53 -06:00
Travis Ralston aac77440db work around docgen? 2021-06-15 14:29:26 -06:00
Travis Ralston 13c9c4bea5 Add functions to assist in immutability of Event objects 2021-06-15 14:23:27 -06:00
RiotRobot 68c1171294 v12.0.0-rc.1 2021-06-15 16:10:48 +01:00
RiotRobot f4f01913fe Prepare changelog for v12.0.0-rc.1 2021-06-15 16:10:48 +01:00
Michael Telatynski eb5908d5d2 fix tests 2021-06-15 10:15:43 +01:00
Michael Telatynski e0c36498e6 delint 2021-06-15 10:06:30 +01:00
Michael Telatynski 913710dd99 Convert filter classes to typescript 2021-06-15 10:02:05 +01:00
Michael Telatynski 2f0d96d030 Convert some utils to typescript 2021-06-15 10:01:51 +01:00
Michael Telatynski 265802acb1 Convert some models to typescript 2021-06-15 10:01:38 +01:00
Michael Telatynski 045f31a0dc Convert some stores to typescript 2021-06-15 10:01:22 +01:00
Travis Ralston 9f6ed4fb33 Merge pull request #1730 from SimonBrandner/show-username
Rework how disambiguation is handled
2021-06-15 00:24:06 -06:00
Michael Telatynski 434117c771 Merge pull request #1735 from matrix-org/t3chguy/fix/17282 2021-06-14 22:15:12 +01:00
Michael Telatynski cd95b8724a Merge branch 'develop' of github.com:matrix-org/matrix-js-sdk into t3chguy/fix/17282 2021-06-14 21:46:31 +01:00
Michael Telatynski ec2a4d473e Iterate algorithm, base it on new js-sdk string lib 2021-06-14 21:28:33 +01:00
Travis Ralston 47eaf3cd58 Merge pull request #1734 from matrix-org/travis/fix-types
Move various types from the react-sdk to the js-sdk
2021-06-14 13:48:07 -06:00
Travis Ralston d7b23a8634 liiiinttteeerrrr 2021-06-14 13:37:19 -06:00
Travis Ralston 6db7972f04 preset 2021-06-14 13:35:20 -06:00
Travis Ralston 6840ee077c Appease the linter forever 2021-06-14 13:34:37 -06:00
Travis Ralston 3c85bcc3c9 Move various types from the react-sdk to the js-sdk 2021-06-14 13:32:28 -06:00
Travis Ralston 759eca6479 Merge pull request #1732 from matrix-org/travis/file-trees
Unstable implementation of MSC3089: File Trees
2021-06-14 12:04:09 -06:00
Travis Ralston 4488f174aa const 2021-06-14 12:00:59 -06:00
Travis Ralston 991a255041 Fix average on .5 2021-06-14 11:55:41 -06:00
Travis Ralston cfef635e1b Appease the linter 2021-06-14 10:41:32 -06:00
Travis Ralston d3027e1fe8 Offset the alphabet by 1 2021-06-14 10:28:26 -06:00
Travis Ralston d99ea1c6b4 Update src/utils.ts
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2021-06-14 08:21:09 -06:00
Travis Ralston 9af214007e APPEASE. THE. LINTER. 2021-06-11 11:37:44 -06:00
Travis Ralston 0541b7f3c5 Remove a layer of indirection 2021-06-11 11:36:52 -06:00
Travis Ralston 63fa774af7 Another round of appeasement 2021-06-11 11:34:37 -06:00
Travis Ralston 4b19b36de1 Crude JS->TS conversion on utils test because of linter and BigInt 2021-06-11 11:27:46 -06:00
Travis Ralston 5715df6b18 BigInt, rollover, and developer lint 2021-06-11 11:18:18 -06:00
Michael Telatynski 22bcacc715 Merge pull request #1729 from matrix-org/t3chguy/fix/17282
Add MSC3230 event type to enum
2021-06-11 12:40:23 +01:00
Travis Ralston f1e270ca9d appease the linter 2021-06-10 15:54:56 -06:00
Travis Ralston f535e7535c Update string averaging utils 2021-06-10 15:38:49 -06:00
David Baker 912c5e13e1 Merge pull request #1731 from matrix-org/dbkr/transferred_reason_code
Add separate reason code for transferred calls
2021-06-10 13:21:41 +01:00
Travis Ralston 4eb44ee2ea de-lint 2 2021-06-09 22:14:11 -06:00
Travis Ralston e41a2beb65 de-lint 2021-06-09 22:09:26 -06:00
Travis Ralston 1f6ba31a3f Use a sane padStart instead 2021-06-09 21:56:46 -06:00
Travis Ralston bcccc909c5 Pre-lint format 2021-06-09 21:55:06 -06:00
Travis Ralston b3a11030f2 Early file management APIs 2021-06-09 21:54:17 -06:00
Travis Ralston baaf76668f Early directory management 2021-06-09 21:54:17 -06:00
Šimon Brandner ca37ae6794 Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-06-09 19:20:21 +02:00
Hubert Chathi cf21d64aa8 allow backup algorithm to determine whether restored keys should be trusted 2021-06-09 13:02:47 -04:00
David Baker 36e2533164 Add separate reason code for transferred calls
'Replaced' is special cased so the media isn't torn down, but we
were passing Replaced for calls we transferred off elsewhere which
meant we never closed the media capture. Calls transferred elsewhere
aren't really replaced: they may as well have their own code.
2021-06-09 16:52:58 +01:00
Hubert Chathi c04d79d9a0 initial work on symmetric algorithm for key backups 2021-06-08 21:39:37 -04:00
Travis Ralston 9084b4e7aa Early implementation of MSC3089 (file trees)
MSC: https://github.com/matrix-org/matrix-doc/pull/3089
Includes part of MSC3088 (room subtyping): https://github.com/matrix-org/matrix-doc/pull/3088

The NamespacedValue stuff is borrowed from the Extensible Events implementation PR in the react-sdk as a useful thing to put here. When/if the MSCs become stable, we'd convert the values to enums and drop the constants (or keep them for migration purposes, but switch to stable). 

This flags the whole thing as unstable because it's highly subject to change.
2021-06-08 14:43:20 -06:00
Šimon Brandner f724da7e84 Merge remote-tracking branch 'upstream/develop' into disambiguate-prop 2021-06-08 11:30:50 +02:00
David Baker 4b8f47e2b4 Merge pull request #1728 from matrix-org/dbkr/hold_with_sendonly
Use sendonly for call hold
2021-06-08 09:26:57 +01:00
RiotRobot 35ecbed29d Resetting package fields for development 2021-06-07 17:00:30 +01:00
RiotRobot 30ed153ad1 Merge branch 'master' into develop 2021-06-07 17:00:30 +01:00
RiotRobot a1098989ff v11.2.0 2021-06-07 16:57:42 +01:00
RiotRobot 42bb63e07d Prepare changelog for v11.2.0 2021-06-07 16:57:42 +01:00
Michael Telatynski 683aae5ed5 Add MSC3230 event type to enum 2021-06-07 09:00:08 +01:00
David Baker 49ef274a83 Use sendonly for call hold
Instead of inactive. Remove the logic for trying to remember who
had who on hold, which is now unnecesasary. Appears to work fine
with element android & ios too.
2021-06-04 17:22:14 +01:00
J. Ryan Stinnett af16bba1ec Merge pull request #1727 from matrix-org/t3chguy/arg
Stop breeding sync listeners
2021-06-04 14:09:45 +01:00
Michael Telatynski 781086608e Stop breeding sync listeners 2021-06-04 13:58:19 +01:00
Šimon Brandner c1625e5c27 More styling :(
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-06-04 11:44:31 +02:00
Šimon Brandner 0e05f9fd73 Styling
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-06-04 11:41:35 +02:00
Šimon Brandner ef7595bb06 Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-06-04 11:38:13 +02:00
J. Ryan Stinnett e9c98b03b0 Merge pull request #1724 from matrix-org/jryans/semi-linting
Fix semicolons in TS files
2021-06-04 10:31:56 +01:00
J. Ryan Stinnett 75370f7855 Reduce allowable warning count 2021-06-04 10:24:55 +01:00
J. Ryan Stinnett 4a79e13410 Auto-fix more errors 2021-06-04 10:24:09 +01:00
J. Ryan Stinnett 220061f022 Merge remote-tracking branch 'origin/develop' into jryans/semi-linting 2021-06-04 10:22:06 +01:00
Šimon Brandner 090c2c0891 Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share 2021-06-04 08:27:46 +02:00
Travis Ralston 6c317b7f28 Fix types on checkOwnCrossSigningTrust 2021-06-04 00:10:33 -06:00
Travis Ralston 3788fbf607 Merge pull request #1718 from matrix-org/travis/ts-mtxcli
[BREAKING] Convert MatrixClient to TypeScript
2021-06-03 19:09:23 -06:00
Travis Ralston 382854c04c Appease linter 2021-06-03 19:04:49 -06:00
Travis Ralston c2fae3bad8 Fix missed conversion fallout 2021-06-03 19:02:46 -06:00
Travis Ralston 92ebd39391 Reincorporate crypto changes
https://github.com/matrix-org/matrix-js-sdk/pull/1697
2021-06-03 18:59:01 -06:00
Travis Ralston f53a32a6b4 Merge branch 'develop' into travis/ts-mtxcli 2021-06-03 18:49:08 -06:00
Hubert Chathi 6c882e6605 Merge pull request #1697 from uhoreg/backup_refactor
Factor out backup management to a separate module
2021-06-03 18:56:19 -04:00
Hubert Chathi ca85dfc6ff re-lint 2021-06-03 18:52:06 -04:00
Hubert Chathi e22ecc6b6d Merge branch 'develop' into backup_refactor 2021-06-03 18:43:46 -04:00
Hubert Chathi 2608dd2d64 mark members as public 2021-06-03 18:15:05 -04:00
J. Ryan Stinnett 7d20d24249 Convert small blocks to inline expressions 2021-06-03 15:51:33 +01:00
Travis Ralston a3ac3692af private->protected 2021-06-02 22:05:53 -06:00
Travis Ralston 0070c8f843 Merge pull request #1723 from schmop/power-levels-unknown-state-key
Ignore power_levels events with unknown state_key on room-state initialization
2021-06-02 19:04:13 -06:00
Travis Ralston b360fc8308 Fix test failure 2021-06-02 18:42:52 -06:00
Travis Ralston bf9ba65ac4 Fix olmVersion types 2021-06-02 13:42:20 -06:00
Travis Ralston 43abfbc537 Upstream build pass 2 2021-06-02 13:42:20 -06:00
Travis Ralston 2700f0acf6 Upstream build pass 1 2021-06-02 13:42:20 -06:00
Travis Ralston 9156bed961 Tests pass 2 2021-06-02 13:42:20 -06:00
Travis Ralston 71dc0bac56 Tests pass 1 2021-06-02 13:42:20 -06:00
Travis Ralston 40f55b2964 Lint pass 4 2021-06-02 13:42:20 -06:00
Travis Ralston 9307f9f345 Build pass 2 2021-06-02 13:42:20 -06:00
Travis Ralston dfb918adc3 Lint pass 3 2021-06-02 13:42:20 -06:00
Travis Ralston 2f87a4859e Lint pass 2 2021-06-02 13:42:20 -06:00
Travis Ralston 191f73e0d0 Appease typescript 2021-06-02 13:42:20 -06:00
Travis Ralston 263e55f25d Build pass 1 2021-06-02 13:42:20 -06:00
Travis Ralston 5c55dce13e Lint pass 1 2021-06-02 13:42:20 -06:00
Travis Ralston a1a6ec6dfa Fix remaining hot paths 2021-06-02 13:42:20 -06:00
Travis Ralston e1edd84700 Early pass to fix runtime/build errors 2021-06-02 13:42:20 -06:00
Travis Ralston 07ee256756 Incorporate https://github.com/matrix-org/matrix-js-sdk/pull/1720 2021-06-02 13:42:20 -06:00
Travis Ralston 48888e530e Defer types 2021-06-02 13:42:20 -06:00
Travis Ralston 4ef50bef55 define this.identityServer 2021-06-02 13:42:20 -06:00
Travis Ralston 486369e97c Clean up "base-apis" find&replace 2021-06-02 13:42:20 -06:00
Travis Ralston 67994f7a53 Move new MatrixClient into place 2021-06-02 13:42:20 -06:00
Travis Ralston f027ddaf35 Autoformat 2021-06-02 13:42:20 -06:00
Travis Ralston f3b27d1e06 Cleanup 2021-06-02 13:42:20 -06:00
Travis Ralston 92e18b32dc Import MatrixError 2021-06-02 13:42:20 -06:00
Travis Ralston 4030ec9c8b Fix easy typing errors 2021-06-02 13:42:20 -06:00
Travis Ralston 497c2dc8df Bring in BaseApis to MatrixClient 2021-06-02 13:42:20 -06:00
Travis Ralston 8a1d34c419 [Combined] First pass of JS->TS for MatrixClient 2021-06-02 13:42:20 -06:00
Travis Ralston caab5befaa Rename client.js -> 1client.ts for future commits 2021-06-02 13:42:20 -06:00
Travis Ralston 0d316e3d3e Move useful docs to ICreateClientOpts 2021-06-02 13:42:20 -06:00
Šimon Brandner d8fd12103a Merge branch 'develop' into fix/12652/screen-share
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-06-02 16:09:11 +02:00
David Baker 8f9a682d34 Merge pull request #1725 from matrix-org/dbkr/revert_1579
Revert 1579 (Fix extra negotiate message in Firefox)
2021-06-02 15:04:17 +01:00
David Baker 102d5acf09 Revert 1579
This is causing all sorts of problems, like
https://github.com/vector-im/element-web/issues/17450
and also issues where we fail to respond to negotiates because
we can't adjust a direction of a stopped transceiver. Until
s/inactive/sendonly/ let's live with the minor firefox bug rather
than all this brokenness.
2021-06-02 14:41:55 +01:00
J. Ryan Stinnett e2ec8952e3 Fix semicolons in TS files
This updates the linting config to include the semi fix in
https://github.com/matrix-org/eslint-plugin-matrix-org/pull/8. The various semi
errors have been auto-fixed.
2021-06-02 11:49:39 +01:00
Lars Richard b4eff9b996 Ignore m.room.power_levels events with unknown state_key on room-state initialization
Signed-off-by: Lars Richard <lars.richard@iserv.eu>
2021-06-02 11:42:50 +02:00
RiotRobot d050261fa9 v11.2.0-rc.1 2021-06-01 16:09:49 +01:00
RiotRobot d29330815e Prepare changelog for v11.2.0-rc.1 2021-06-01 16:09:48 +01:00
Michael Telatynski 801b4022de Merge pull request #1720 from matrix-org/t3chguy/fix/17521
Switch to stable endpoint/fields for MSC2858
2021-06-01 12:07:25 +01:00
Michael Telatynski bcb4071993 Strip hash from urls being previewed to de-duplicate 2021-06-01 11:17:30 +01:00
Michael Telatynski e78fbd1dff Switch to stable endpoint/fields for MSC2858 2021-06-01 11:01:10 +01:00
Hubert Chathi c543358826 add unit test and minor fixes 2021-05-31 21:52:20 -04:00
Travis Ralston ff2954839b Merge pull request #1715 from matrix-org/dependabot/npm_and_yarn/ws-7.4.6
Bump ws from 7.4.2 to 7.4.6
2021-05-29 21:44:48 -06:00
dependabot[bot] 1a91b88968 Bump ws from 7.4.2 to 7.4.6
Bumps [ws](https://github.com/websockets/ws) from 7.4.2 to 7.4.6.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/7.4.2...7.4.6)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-29 21:09:19 +00:00
Šimon Brandner 5724462c2c Delint
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-28 17:45:52 +02:00
Šimon Brandner 0a0489750c Add missing space
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-28 17:37:55 +02:00
Šimon Brandner f46190509a Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-28 17:37:17 +02:00
Germain 25ec81b6c7 Merge pull request #1712 from matrix-org/gsouquet/fix/17393
Make consistent call event type checks
2021-05-28 13:09:35 +01:00
J. Ryan Stinnett a50802a63f Merge pull request #1714 from matrix-org/jryans/babel-config
Apply new Babel linting config
2021-05-28 13:04:06 +01:00
J. Ryan Stinnett ce1d374a82 Merge pull request #1709 from matrix-org/dependabot/npm_and_yarn/browserslist-4.16.6
Bump browserslist from 4.16.1 to 4.16.6
2021-05-28 11:41:38 +01:00
J. Ryan Stinnett 6dca8ac460 Switch to new Babel lint config
This also adjusts the TypeScript project lint config to cover *.ts test files
too.
2021-05-28 11:39:06 +01:00
J. Ryan Stinnett 4dc21674d5 Fix log usage 2021-05-28 11:30:20 +01:00
J. Ryan Stinnett 8805dd8c01 Auto-fix lint errors 2021-05-28 11:15:10 +01:00
David Baker 73b624e761 Merge pull request #1713 from matrix-org/dbkr/user_busy
Add user_busy call hangup reason
2021-05-28 09:42:56 +01:00
David Baker c44fd972b6 Add user_busy call hangup reason
And fix hangup reasons in reject events
2021-05-27 18:56:27 +01:00
J. Ryan Stinnett ff344bc110 Switch lint parsers 2021-05-27 17:51:03 +01:00
J. Ryan Stinnett b0e2a38325 Auto-fix lint errors 2021-05-27 17:50:16 +01:00
J. Ryan Stinnett fbb741ab10 Switch to new Babel linting config 2021-05-27 17:49:35 +01:00
Šimon Brandner 75321220fd Simplifie code - don't be an idiot
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-27 18:49:02 +02:00
Šimon Brandner 43198b0425 Disable RTX only for screen-sharing transceivers
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-27 18:41:48 +02:00
Šimon Brandner 4aa2c03ff0 Merge branch 'develop' into fix/12652/screen-share 2021-05-27 18:23:22 +02:00
Germain 3a3be36f4c Merge pull request #1688 from matrix-org/gsouquet/pr-review-linting-rules 2021-05-27 16:03:36 +01:00
Germain Souquet cb91c4292c Merge branch 'develop' into gsouquet/pr-review-linting-rules 2021-05-27 16:00:12 +01:00
Germain Souquet 80722ce145 make consistent call event type checks 2021-05-27 09:55:50 +01:00
Hubert Chathi 07bfa5532e fix more unit tests 2021-05-26 18:18:30 -04:00
J. Ryan Stinnett cea1a3ff91 Merge pull request #1710 from matrix-org/jryans/hidden-events-reactions
Emit relations created when target event added later
2021-05-26 17:34:47 +01:00
J. Ryan Stinnett 270be2df7a Emit relations created when target event added later
This changes the "relations created" event to ensure it is properly emitted even
if the target event is added to the timeline after the relation event. There was
perhaps always a risk of this happening in the past, but is seems more likely to
bite now with delayed decryption.

Part of https://github.com/vector-im/element-web/issues/17461
2021-05-26 16:35:49 +01:00
Hubert Chathi e73b969066 lint 2021-05-25 22:10:15 -04:00
Hubert Chathi 98e2154f0f fix unit tests 2021-05-25 21:59:08 -04:00
dependabot[bot] 2c0549a772 Bump browserslist from 4.16.1 to 4.16.6
Bumps [browserslist](https://github.com/browserslist/browserslist) from 4.16.1 to 4.16.6.
- [Release notes](https://github.com/browserslist/browserslist/releases)
- [Changelog](https://github.com/browserslist/browserslist/blob/main/CHANGELOG.md)
- [Commits](https://github.com/browserslist/browserslist/compare/4.16.1...4.16.6)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-25 21:59:49 +00:00
RiotRobot acb9bc8cc5 Resetting package fields for development 2021-05-24 17:14:02 +01:00
RiotRobot 6f44aa39e8 Merge branch 'master' into develop 2021-05-24 17:13:42 +01:00
RiotRobot c706618229 v11.1.0 2021-05-24 17:09:09 +01:00
RiotRobot c26b571b1c Prepare changelog for v11.1.0 2021-05-24 17:09:08 +01:00
J. Ryan Stinnett cb3075b084 Merge pull request #1707 from matrix-org/jryans/olm-3.2.3-release
[Release] Bump libolm version and update package name
2021-05-24 16:49:25 +01:00
Hubert Chathi 66fb21bd0b bump olm to 3.2.3 2021-05-24 16:27:56 +01:00
Hubert Chathi 498109bd53 update test too 2021-05-24 16:27:56 +01:00
Hubert Chathi 6711ab5f9a Bump libolm version and update package name. 2021-05-24 16:27:56 +01:00
J. Ryan Stinnett ac8fa58845 Merge pull request #1705 from uhoreg/olm_3.2.2
Bump libolm version and update package name.
2021-05-24 16:22:15 +01:00
Hubert Chathi 095f656998 bump olm to 3.2.3 2021-05-24 11:10:52 -04:00
Hubert Chathi 9e30c4f7dd update test too 2021-05-21 16:28:37 -04:00
Hubert Chathi 56a2eeac77 Bump libolm version and update package name. 2021-05-21 16:04:54 -04:00
Michael Telatynski d104f2f4a7 Merge pull request #1703 from matrix-org/t3chguy/uploadContent
Fix uploadContent not rejecting promise when http status code >= 400
2021-05-20 18:43:12 +01:00
Michael Telatynski e8367ad241 fix httpStatus being resolved when response is undefined 2021-05-20 18:33:17 +01:00
Michael Telatynski f17cd142d5 Fix uploadContent not rejecting promise when http status code >= 400 2021-05-20 15:43:22 +01:00
Šimon Brandner db4c6af472 Fix an odd mistake
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-20 15:54:08 +02:00
Šimon Brandner 87689ca733 Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share 2021-05-20 15:50:15 +02:00
Šimon Brandner a1a5d85979 Stop tracks only if disabling screen-sharing
The other thing lead to usermedia tracks being stopped when on hold

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-20 15:49:56 +02:00
Šimon Brandner b1459a43ef Also put getRidOfRTXCodecs() before createAnswer()
Just to be sure

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-20 15:11:23 +02:00
J. Ryan Stinnett e8edc554a6 Merge pull request #1702 from matrix-org/jryans/test-noise
Reduce noise in tests
2021-05-20 13:42:31 +01:00
J. Ryan Stinnett bd8aca83ac Reduce noise in tests
This disables a common log message to cut down the test log size and make it
easier to read messages specific to each test.
2021-05-20 13:41:54 +01:00
J. Ryan Stinnett 7ebc1cfac5 Merge pull request #1700 from matrix-org/matthew/kill-invite-logspam
Only log once if a Room lacks an m.room.create event
2021-05-20 12:02:32 +01:00
Germain 2422204d6a Merge pull request #1701 from matrix-org/gsouquet/cache-normalized-name
Cache normalized room name
2021-05-20 11:12:00 +01:00
Germain Souquet 6c98c3c662 Remove reference to room name in utils 2021-05-20 10:58:20 +01:00
Germain Souquet 1d1310f034 Cache normalized room name 2021-05-20 10:44:47 +01:00
J. Ryan Stinnett 841888c480 Merge pull request #1699 from matrix-org/jryans/call-enc-release
[Release] Change call event handlers to adapt to undecrypted events
2021-05-19 21:28:19 +01:00
Šimon Brandner 8797381f44 Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share 2021-05-19 21:07:04 +02:00
Šimon Brandner 92e89ffbcf Add getRidOfRTXCodecs() method
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-19 21:06:35 +02:00
Matthew Hodgson 52c031f160 Only log once if a Room lacks an m.room.create event
Currently my account is logging ~20,000 warnings a minute about getType() being called
on invites which have no m.room.create events, which crashes my inspector and makes
my console unusable.  We still want the logline though, as it helps diagnose
space invite problems.  So instead, log this only once.  (Untested).
2021-05-19 19:02:31 +01:00
Germain Souquet 155113b75d move startEventCallHandler to MatrixClient prototype 2021-05-19 18:16:20 +01:00
Germain Souquet 2a863025c6 listen to call event handlers when sync is prepared 2021-05-19 18:15:39 +01:00
Germain Souquet b6763ce89f Change call event handlers to adapt to undecrypted events 2021-05-19 18:14:28 +01:00
Germain f346cd6b8d Merge pull request #1698 from matrix-org/gsouquet/fix-call-handlers 2021-05-19 17:23:51 +01:00
Germain Souquet 0c47412c75 move startEventCallHandler to MatrixClient prototype 2021-05-19 17:15:44 +01:00
Germain Souquet ea1ef3dbec listen to call event handlers when sync is prepared 2021-05-19 17:05:20 +01:00
Germain Souquet 61fd62ff81 Merge branch 'develop' into gsouquet/fix-call-handlers 2021-05-19 16:51:29 +01:00
Germain Souquet 32197ea903 Change call event handlers to adapt to undecrypted events 2021-05-19 15:45:21 +01:00
RiotRobot 65de184d88 v11.1.0-rc.1 2021-05-19 14:29:51 +01:00
RiotRobot 52764045ce Prepare changelog for v11.1.0-rc.1 2021-05-19 14:29:50 +01:00
Šimon Brandner c2da4376e0 Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share 2021-05-19 15:21:00 +02:00
J. Ryan Stinnett 4b0db6c472 Guard against duplicates in Relations model
The `Relations` model was relying on object reference equality to prevent
duplicates, which breaks down if we ever have two objects that represent the
same event.

This fixes things to additionally track event IDs we've seen before and discard
any attempts to add them twice.

Fixes https://github.com/vector-im/element-web/issues/11161
2021-05-19 13:20:40 +01:00
Šimon Brandner 78ebf8f117 Merge remote-tracking branch 'upstream/develop' into fix/12652/screen-share 2021-05-19 08:46:54 +02:00
Hubert Chathi 3ec89a89df fix some types 2021-05-18 18:40:36 -04:00
Hubert Chathi 9e6b72bf38 some linting 2021-05-18 18:31:19 -04:00
Hubert Chathi 747723c8fb factor out backup management to a separate module 2021-05-18 18:15:22 -04:00
Germain 40cd4629db Decrypt relations before applying them to target event (#1696) 2021-05-18 17:21:06 +01:00
RiotRobot 52a893a811 Resetting package fields for development 2021-05-17 13:32:49 +01:00
RiotRobot 7cc94e1e1e Merge branch 'master' into develop 2021-05-17 13:32:48 +01:00
RiotRobot 88945a6d6d v11.0.0 2021-05-17 13:30:08 +01:00
RiotRobot 7203c5aaf0 Prepare changelog for v11.0.0 2021-05-17 13:30:07 +01:00
J. Ryan Stinnett c305058c46 Merge pull request #1695 from matrix-org/jryans/glare-streams-release
[Release] Fix regressed glare
2021-05-17 11:55:25 +01:00
Šimon Brandner 91bbf7d1a8 Fix glare
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-17 11:20:14 +01:00
J. Ryan Stinnett 2d5857f145 Merge pull request #1690 from SimonBrandner/fix/glare/17250
Fix regressed glare
2021-05-17 11:11:39 +01:00
Šimon Brandner 5de189bfa3 Improve logging in pushRemoteFeed()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-15 11:06:04 +02:00
Travis Ralston 91af9a411d Null-guard power level object usage (#1694) 2021-05-14 08:36:44 +01:00
Germain 9a9ed124f5 Use native Object and Array methods (#1693) 2021-05-13 17:20:09 +01:00
Šimon Brandner 44fc820f99 Make feed pushing methods more verbose
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-13 18:12:48 +02:00
Michael Telatynski 4e5442d972 Merge pull request #1692 from matrix-org/t3chguy/fix/i80
Add m.reaction to EventType enum
2021-05-13 12:44:42 +01:00
Šimon Brandner 5a8e5a9785 Log local SDPStreamMetadata
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-13 13:43:44 +02:00
Šimon Brandner 960c5da3b2 Merge branch 'develop' into fix/12652/screen-share 2021-05-13 13:39:51 +02:00
Michael Telatynski b5fa54f91e Add m.reaction to EventType enum 2021-05-13 10:57:02 +01:00
Germain 2246aede4b Merge pull request #1684 from matrix-org/gsouquet/cache-decrypt 2021-05-12 12:19:59 +01:00
Šimon Brandner 4b2d409c69 Fix glare
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-12 07:47:48 +02:00
RiotRobot 684511ff06 v11.0.0-rc.1 2021-05-11 15:03:04 +01:00
RiotRobot 88b328df7e Prepare changelog for v11.0.0-rc.1 2021-05-11 15:03:03 +01:00
Michael Telatynski e3583dd04e Merge pull request #1679 from matrix-org/t3chguy/spaces-stable
Switch from MSC1772 unstable prefixes to stable
2021-05-11 13:39:47 +01:00
Germain Souquet e484a2ebb5 add missing coma to appease linter 2021-05-11 13:02:42 +01:00
Germain Souquet 5caf05cfa1 Apply new linting rules 2021-05-11 11:25:43 +01:00
Germain Souquet 72f86258d0 Add explainer for awaitDecryption 2021-05-11 10:05:24 +01:00
Germain Souquet 874cb3b779 make attemptDecryption backwards compatible 2021-05-11 10:02:32 +01:00
Germain f21e0228b4 Update documentation wording
Co-authored-by: Travis Ralston <travpc@gmail.com>
2021-05-11 09:20:14 +01:00
Šimon Brandner 00a28e743d Move track.stop() to deleteFeedByStream()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-10 19:18:39 +02:00
Šimon Brandner 2596c25ccc Add missing semicolon
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-10 19:17:07 +02:00
Germain Souquet 01cd82bc6a undo test timeout 2021-05-10 18:12:47 +01:00
Šimon Brandner 582aafa552 Simpler naming
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-10 19:12:33 +02:00
Germain Souquet d2a6a8b283 Merge branch 'develop' into gsouquet/cache-decrypt 2021-05-10 17:35:05 +01:00
Germain Souquet f242e460ed fix tests 2021-05-10 17:28:00 +01:00
Šimon Brandner 61e7d4f807 Remove some leftovers from placeScreensharingCall()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-10 18:22:06 +02:00
Germain Souquet 95e08253a6 Appease linter 2021-05-10 16:59:54 +01:00
Germain Souquet 202a4fa6f1 Better document new room methods 2021-05-10 15:55:16 +01:00
Germain Souquet 576f46cb88 Add flag to prevent emitting event.decrypted 2021-05-10 15:25:07 +01:00
J. Ryan Stinnett 2d73805ca3 Merge pull request #1680 from SimonBrandner/feed-example
Update the VoIP example to work with the new changes
2021-05-10 14:50:18 +01:00
J. Ryan Stinnett eedfa550a6 Merge pull request #1687 from matrix-org/dependabot/npm_and_yarn/hosted-git-info-2.8.9
Bump hosted-git-info from 2.8.8 to 2.8.9
2021-05-10 14:48:34 +01:00
dependabot[bot] 4ca718adc4 Bump hosted-git-info from 2.8.8 to 2.8.9
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-10 13:46:58 +00:00
RiotRobot 7c4ced8f46 Resetting package fields for development 2021-05-10 14:46:14 +01:00
RiotRobot 7018f4ab25 Merge branch 'master' into develop 2021-05-10 14:46:13 +01:00
RiotRobot fda13875ef v10.1.0 2021-05-10 14:43:18 +01:00
RiotRobot 8005917452 Prepare changelog for v10.1.0 2021-05-10 14:43:17 +01:00
Šimon Brandner f2c215311f If we can't get constraints don't error
We do this because it could mean the user just hasn't selected a window/screen

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-10 13:01:06 +02:00
Šimon Brandner a13cf0e1e0 Remove placeScreenSharingCall()
This method is quite problematic and doesn't have any benefits

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-10 12:27:21 +02:00
Šimon Brandner ff60bbac9d Remove import that was a mistake
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-10 07:35:25 +02:00
Šimon Brandner 16f569136b Simplifie and avoid repetation
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-09 18:48:08 +02:00
Šimon Brandner 27c172361f Add a log line to pushLocalFeed()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-08 20:03:47 +02:00
Šimon Brandner 1e0d6b9d4a Jest: should fallback to replaceTrack() if the other side doesn't support SPDStreamMetadata
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-08 15:50:20 +02:00
Šimon Brandner b67cd94ee2 Jest: should map SDPStreamMetadata to feeds
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-08 15:39:11 +02:00
Šimon Brandner c6764490c6 Use for loop
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-08 14:17:10 +02:00
Šimon Brandner 18580624e6 Use opponentSupportsSDPStreamMetadata()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-08 14:16:43 +02:00
Šimon Brandner 7b333a34b5 Warn level
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-08 14:16:30 +02:00
Šimon Brandner d0707e183d Make shift-click work again
This is VERY ugly but it works

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-08 10:02:27 +02:00
Šimon Brandner fa3b246de5 Add addToPeerConnection param
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-08 10:00:59 +02:00
Šimon Brandner df28d87d25 Remove log line
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-08 09:29:41 +02:00
Šimon Brandner fc68bb3ae0 Add ()!!!
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-08 09:29:31 +02:00
Šimon Brandner 82c530da95 Add setScreensharingEnabledWithoutMetadataSupport as a fallback()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-08 09:08:06 +02:00
Šimon Brandner d250e7387c Merge screenshare track into usermedia stream
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-08 09:02:01 +02:00
Šimon Brandner cbc74815d8 Use getScreensharingStream()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-08 08:46:29 +02:00
Šimon Brandner e9b802deb3 Use getScreensharingStream() in setScreensharingEnabled()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-08 08:03:45 +02:00
Šimon Brandner 377ca0c678 Add getScreensharingStream()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-08 08:01:56 +02:00
Šimon Brandner 972aef7a9d Merge feed delete methods and add sender arrays
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-08 07:40:46 +02:00
Šimon Brandner a35559be65 Add a method to start screensharing
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-07 21:33:05 +02:00
Šimon Brandner 0e6b43a769 Hook up methods to delete feeds
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-07 21:02:56 +02:00
Šimon Brandner 8c8a68d3ae Add methods to delete feeds
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-07 21:01:56 +02:00
Šimon Brandner 4d74b5cdad Send SDPStreamMetadata in negotiation response
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-07 20:57:45 +02:00
Šimon Brandner b1ace49f9a Add methods useful for screensharing
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-07 20:53:19 +02:00
Germain Souquet 91eee8587e extract shouldAttemptDecryption to event model 2021-05-07 15:16:04 +01:00
Germain Souquet e9132abc25 Do not attempt to decrypt already clear events 2021-05-07 12:58:53 +01:00
Šimon Brandner 640d13af99 Set remoteSDPStreamMetadata in onNegotiateReceived()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-07 13:20:36 +02:00
Šimon Brandner 50e0f6353a Move adding tracks into pushLocalFeed()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-07 13:15:09 +02:00
Germain Souquet 444eac5c6e consolidate critical event decryption implementation 2021-05-07 11:23:59 +01:00
Šimon Brandner 30f2263443 Rework pushing of remote feeds for MSC3077
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-07 11:18:25 +02:00
Šimon Brandner 25eb6de220 Send SDPStreamMetadata in answer
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-07 11:17:08 +02:00
Šimon Brandner cebdc44689 Set remoteSDPStreamMetadata from answer
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-07 11:11:31 +02:00
Šimon Brandner 23f5c2e03f Add a separate method to push local feed
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-07 10:43:36 +02:00
Šimon Brandner 4d4a6ede21 Use somicolons instead
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-07 10:41:59 +02:00
Šimon Brandner 6a920fe623 Get sdpStreamMetadata from invite
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-07 07:56:27 +02:00
Šimon Brandner 631faa2046 Send SDPStreamMetadata
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-06 17:18:30 +02:00
Šimon Brandner a4e853e1d4 Add types for MSC3077
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-05-06 17:15:04 +02:00
Šimon Brandner a449c5f8c2 Merge branch 'develop' into feed-example 2021-05-06 16:44:29 +02:00
Germain Souquet 19d6dbaa52 Use read receipt instead of read marker 2021-05-06 14:07:38 +01:00
Germain Souquet 8820619e82 Pass decrypt flag to event mapper 2021-05-06 12:34:21 +01:00
Germain Souquet fb33bc7e07 Lazily decrypt event on room view 2021-05-06 11:46:14 +01:00
J. Ryan Stinnett 57d1fa8410 Merge pull request #1660 from SimonBrandner/feed
Support for multiple streams (not MSC3077)
2021-05-06 11:19:52 +01:00
Michael Telatynski 838e38d84c Merge pull request #1683 from matrix-org/t3chguy/spaces-logs
Tweak missing m.room.create errors to describe their source
2021-05-06 00:06:38 +01:00
Michael Telatynski fc29056530 Tweak missing m.room.create errors to describe their source 2021-05-05 23:58:40 +01:00
RiotRobot 4e967c979c v10.1.0-rc.1 2021-05-04 15:37:55 +01:00
RiotRobot 62a34848c7 Prepare changelog for v10.1.0-rc.1 2021-05-04 15:37:54 +01:00
Travis Ralston 01fe6cc542 Merge pull request #1681 from matrix-org/revert-1678-travis/event-logging
Revert "Raise logging dramatically to chase pending event errors"
2021-05-02 19:11:06 -06:00
Travis Ralston 3fdc25777d Revert "Raise logging dramatically to chase pending event errors" 2021-05-02 19:10:47 -06:00
Šimon Brandner 3b7d6f8334 This check doesn't seem to be necessary
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-30 14:43:00 +02:00
Šimon Brandner 4b3c8b2969 Update the example to work with the new feed code
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-30 14:18:20 +02:00
Šimon Brandner ad80d69369 Add some basic styling
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-30 14:17:30 +02:00
Michael Telatynski e2d2249686 Switch from MSC1772 unstable prefixes to stable 2021-04-30 11:33:45 +01:00
J. Ryan Stinnett dc64c34ccb Merge pull request #1677 from matrix-org/jryans/coverage
Add test coverage collection script
2021-04-28 17:18:07 +01:00
Travis Ralston 0bf50659ab Merge pull request #1678 from matrix-org/travis/event-logging
Raise logging dramatically to chase pending event errors
2021-04-28 09:30:04 -06:00
Travis Ralston ec26b16ddf Raise logging dramatically to chase pending event errors
For https://github.com/vector-im/element-web/issues/17090 and similar issues

This logging is expected to exist no longer than a day.
2021-04-28 09:24:19 -06:00
J. Ryan Stinnett a044b74a1d Add test coverage collection script
This makes it clear to how collect basic test coverage when desired.
2021-04-28 14:17:08 +01:00
J. Ryan Stinnett 1e7a1dce90 Move Jest options into config block 2021-04-28 12:58:39 +01:00
Šimon Brandner 41c2772cff Merge branch 'develop' into feed
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-28 10:57:59 +02:00
David Baker 1bba2bc0ed Merge pull request #1674 from matrix-org/dbkr/asserted_identity
Support MSC3086 asserted identity
2021-04-28 09:47:30 +01:00
Šimon Brandner e11c523a75 Add getLocalFeeds() and getRemoteFeeds()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-27 10:06:21 +02:00
RiotRobot b911a890cf Add breaking notice 2021-04-26 18:03:19 +01:00
RiotRobot c8f69c0b79 Resetting package fields for development 2021-04-26 17:37:06 +01:00
RiotRobot 8a6248f120 Merge branch 'master' into develop 2021-04-26 17:37:06 +01:00
RiotRobot 340fa6c63e v10.0.0 2021-04-26 17:34:17 +01:00
RiotRobot 1177bf39a2 Prepare changelog for v10.0.0 2021-04-26 17:34:16 +01:00
Šimon Brandner 88b310c394 Rename stuff to make it easy to read
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-26 16:00:17 +02:00
Šimon Brandner 973de2db55 stopAllMedia() before deleteAllFeeds()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-24 12:56:28 +02:00
Šimon Brandner 1fe92f10c1 Delint
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-24 12:26:54 +02:00
Šimon Brandner 0e2e906b24 Remove remoteStream prop
This is done in order to be more generic

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-24 12:24:15 +02:00
Šimon Brandner 4667f8be03 Use feeds in stopAllMedia()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-24 12:08:45 +02:00
David Baker 4a51ac7a74 Move createNewMatrixCall to the client object
So we can mock it out it tests (and also I'm not sure why it was
like this in the first place: we passed the client in anyway...)

Deprecate createNewMatrixCall
2021-04-23 14:36:56 +01:00
J. Ryan Stinnett 6099efe41a Merge pull request #1670 from timokoesters/fix-undefined-results
Fix `/search` with no results field work again
2021-04-23 13:02:52 +01:00
Germain 4254d595fc Merge pull request #1672 from hannojg/patch-5 2021-04-22 09:27:22 +01:00
Šimon Brandner e4fbbd56a9 Improve wording
Co-authored-by: Travis Ralston <travpc@gmail.com>
2021-04-22 07:36:53 +02:00
Timo Kösters 069ca4a89d fix: make /search with no results field work again 2021-04-21 22:56:36 +02:00
Šimon Brandner 4290e8e56b Merge branch 'develop' into disambiguate-prop 2021-04-21 18:07:50 +02:00
RiotRobot e3ba08fbbc v10.0.0-rc.1 2021-04-21 16:40:23 +01:00
RiotRobot dd84e51161 Prepare changelog for v10.0.0-rc.1 2021-04-21 16:40:22 +01:00
David Baker bca8568d64 missing semicolon 2021-04-20 12:58:33 +01:00
David Baker 5407717534 Assert event emitted 2021-04-20 12:57:11 +01:00
David Baker 74ef760591 Tests: They find bugs 2021-04-20 12:48:54 +01:00
Germain b435b582bd Merge pull request #1675 from matrix-org/gsouquet-powerlevels-perf
Restrict event emit for room members that had power levels changed
2021-04-20 11:57:18 +01:00
Germain Souquet d46021a05e Restrict event emit for room members that had power levels changed 2021-04-20 11:22:16 +01:00
David Baker 1b31d0622e Unit test for asserted identity messages 2021-04-20 11:08:06 +01:00
Šimon Brandner a416fd562b Oops - remove log
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-20 11:11:33 +02:00
Šimon Brandner 323a096dd7 Merge branch 'disambiguate-prop' of https://github.com/SimonBrandner/matrix-js-sdk into disambiguate-prop 2021-04-20 11:01:20 +02:00
Šimon Brandner 628dd7bf41 Return false by default
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-20 11:01:13 +02:00
Šimon Brandner 71c6d71cae Fix docs
Co-authored-by: Jonathan de Jong <jonathandejong02@gmail.com>
2021-04-20 10:53:39 +02:00
Šimon Brandner e049edd449 Add docs
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-20 10:44:17 +02:00
Michael Telatynski 68206a6e19 Merge pull request #1669 from hannojg/patch-3
Fix sync with misconfigured push rules
2021-04-20 08:57:16 +01:00
David Baker 56797948af lint 2021-04-19 20:36:00 +01:00
David Baker c0af2f25a1 Support MSC3086 asserted identity 2021-04-19 20:28:42 +01:00
Šimon Brandner 0fdfc3ff53 Rework how disambiguation is handled
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-18 21:01:53 +02:00
Hanno J. Gödecke dc12b1df00 feat: room.getMembers
Signed-off-by: Hanno Gödecke <hgoedecke@cuvent.com>
2021-04-18 16:01:51 +02:00
Hanno J. Gödecke b13f5aebfd lint 2021-04-17 09:42:44 +02:00
Hanno J. Gödecke 338301bb5d fix: failure during sync 2021-04-17 09:34:31 +02:00
Šimon Brandner 72a0931663 Remove comment: // Fix when client is TSified
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-16 11:38:01 +02:00
Šimon Brandner 67584b9cc3 Merge branch 'feed' of https://github.com/SimonBrandner/matrix-js-sdk into feed 2021-04-16 11:10:22 +02:00
Šimon Brandner 1bfaa28f9c Fix missing types
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-16 11:09:28 +02:00
Hubert Chathi cbe9b59222 Merge pull request #1665 from uhoreg/dehydrated_device_missing_await
Add missing await
2021-04-14 10:47:09 -04:00
Hubert Chathi 276b52f0fe add missing await 2021-04-14 10:29:39 -04:00
Šimon Brandner 07f49bcc37 Merge branch 'develop' into feed 2021-04-13 12:33:23 +02:00
J. Ryan Stinnett 09fac77ce0 Merge pull request #1642 from matrix-org/jryans/rework-linting
Migrate to `eslint-plugin-matrix-org`
2021-04-13 11:12:39 +01:00
J. Ryan Stinnett 102704e91a Migrate to eslint-plugin-matrix-org
This migrates to the new plugin form of our custom ESLint configs. As part of
this, some packages are de-duplicated, configs streamlined, etc.
2021-04-13 11:00:41 +01:00
Michael Telatynski c5fb351baa Merge pull request #1664 from matrix-org/t3chguy/fix/8665
Add missing event type enum for key verification done
2021-04-13 10:05:00 +01:00
Michael Telatynski 98f8d4414d Add missing event type enum for key verification done 2021-04-13 09:41:53 +01:00
Germain 1dddcd4925 Merge pull request #1663 from matrix-org/gsouquet-timeline-jumpiness 2021-04-12 15:00:49 +01:00
Germain Souquet 2666a271a5 fix tests when pendingEventsList does not exist 2021-04-12 14:51:45 +01:00
RiotRobot e277de6e3d Resetting package fields for development 2021-04-12 14:42:29 +01:00
RiotRobot daa17b3287 Merge branch 'master' into develop 2021-04-12 14:42:29 +01:00
RiotRobot c7f887131e v9.11.0 2021-04-12 14:39:33 +01:00
RiotRobot 58546b80d0 Prepare changelog for v9.11.0 2021-04-12 14:39:32 +01:00
Germain Souquet 466f749b71 fix typo 2021-04-12 14:38:27 +01:00
Germain Souquet 4c2a83c470 Add explanation for events persistence 2021-04-12 14:29:10 +01:00
Germain Souquet d534ab18c7 fix event filtering logic 2021-04-12 13:07:57 +01:00
Germain Souquet 64aaed833b Only persist encrypted events for encrypted rooms 2021-04-12 12:53:27 +01:00
Germain Souquet 2f05be599c undo changes to event#toJSON and persist encrypted events 2021-04-12 12:26:27 +01:00
Germain Souquet 7371f8dd3a Persist txnId to ensure idempotency 2021-04-12 09:55:01 +01:00
Germain Souquet 79aefe9707 Fix timeline jumpiness by setting correct txnId 2021-04-12 09:37:19 +01:00
Michael Telatynski 6bc80577ee Merge pull request #1661 from janpawellek/janpawellek-fix-addEventListener
Fix calling addEventListener if it does not exist
2021-04-12 09:15:19 +01:00
Germain 837764190f Merge pull request #1655 from matrix-org/gsouquet-persist-unsent-messages 2021-04-09 17:48:01 +01:00
Germain Souquet 61948d70e3 Merge branch 'develop' into gsouquet-persist-unsent-messages 2021-04-09 17:05:19 +01:00
Jan Pawellek 9fb0385694 Fix calling addEventListener if it does not exist
Some platforms (e.g. React Native) register global.window, but do not have global.window.addEventListener. In this case, this function should not be called.
2021-04-09 10:18:47 +02:00
Šimon Brandner 193de8d3a9 Merge branch 'feed' of https://github.com/SimonBrandner/matrix-js-sdk into feed 2021-04-08 11:15:07 +02:00
Šimon Brandner 1f2b3512c1 Move SDPStreamMetadataPurpose into callEventTypes.ts
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-08 11:14:42 +02:00
Šimon Brandner ddc5bd3b36 Add prefixes to SDPStreamMetadataPurpose
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-08 11:07:53 +02:00
Šimon Brandner ee828d454a Rename CallFeedPurpose to SDPStreamMetadataPurpose
This is to match MSC3077

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-08 11:07:22 +02:00
Šimon Brandner 2916a73f4c Make selectDesktopCapturerSource optional 2021-04-08 11:01:17 +02:00
Šimon Brandner ae69af7e70 Merge branch 'develop' into feed 2021-04-07 19:14:17 +02:00
RiotRobot 1c6459fe65 v9.11.0-rc.1 2021-04-07 12:55:25 +01:00
RiotRobot adaeb42416 Prepare changelog for v9.11.0-rc.1 2021-04-07 12:55:24 +01:00
J. Ryan Stinnett f1e1daa194 Merge pull request #1657 from matrix-org/jryans/cs-keys-test
Only try to cache private keys we know exist
2021-04-06 10:09:04 +01:00
J. Ryan Stinnett 401e89ef78 Only try to cache private keys we know exist
This tweaks https://github.com/matrix-org/matrix-js-sdk/pull/1649 to only try
caching private keys locally once we've confirmed they exist first. This is most
likely only an issue in tests, where we sometimes create only some but not all
keys.
2021-04-06 09:49:20 +01:00
Travis Ralston 59e0bd467c Merge pull request #1654 from SimonBrandner/terminate-screen-share
Properly terminate screen-share calls if NoUserMedia
2021-04-05 10:55:02 -06:00
Šimon Brandner 7f4397f8ca Use getAudioTracks() and getVideoTracks()
This is much nicer. Before I hadn't realized this was possible

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-05 10:31:27 +02:00
Šimon Brandner 32830b93f1 Rename audioOnly to videoMuted
This makes more sense and will match a possible mute events MSC

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-04 08:50:27 +02:00
Šimon Brandner cdc0d5623b Rename to match MSC3077
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-04 08:37:09 +02:00
Šimon Brandner e78b415832 Add getMember() to CallFeed
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-04-04 08:33:51 +02:00
Šimon Brandner ff1379fd29 Merge branch 'develop' into feed 2021-04-03 08:35:05 +02:00
David Baker 3820c15ecf Merge pull request #1652 from matrix-org/dbkr/attended_transfer
Attended transfer
2021-04-01 17:34:18 +01:00
Germain Souquet 26ef33e4f3 No this assign 2021-04-01 17:29:21 +01:00
Germain Souquet 0534a4ed1b prevent removePendingEvent being called when not in detached mode 2021-04-01 17:23:55 +01:00
Germain Souquet f29a24a915 specify TestClient when testing room model 2021-04-01 15:22:13 +01:00
Germain Souquet cecbcd941e Persist unsent messages for subsequent sessions 2021-04-01 10:59:16 +01:00
David Baker 6be99d6397 Terminate the other call too 2021-03-30 12:13:28 +01:00
J. Ryan Stinnett 4e5947af51 Merge pull request #1653 from matrix-org/jryans/cancel-security-key
Remove catch handlers in private key retrieval
2021-03-29 17:58:07 +01:00
RiotRobot 4204b2170a Resetting package fields for development 2021-03-29 13:28:09 +01:00
RiotRobot 0a5ad489b6 Merge branch 'master' into develop 2021-03-29 13:28:08 +01:00
RiotRobot 5de34a5c99 v9.10.0 2021-03-29 13:25:27 +01:00
RiotRobot 08da6b8800 Prepare changelog for v9.10.0 2021-03-29 13:25:27 +01:00
Šimon Brandner 02b283be78 Properly terminate screenshare calls if NoUserMedia
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-03-27 09:13:44 +01:00
J. Ryan Stinnett 10c49c0fd1 Remove catch handlers in private key retrieval
This removes some catch blocks originally added by
https://github.com/matrix-org/matrix-js-sdk/pull/1472 so that higher level
operations can handle them as needed.

Part of https://github.com/vector-im/element-web/issues/15584
2021-03-26 17:57:23 +00:00
David Baker 9ecc0f5d95 Terminate calls once we've replaced them 2021-03-26 13:52:23 +00:00
Travis Ralston 972b59b99e Merge pull request #1651 from DantrazTrev/CallErrorFix
Fixed the media fail error on caller's side
2021-03-25 19:05:36 -06:00
David Baker 34bb05bd88 WIP attended transfer 2021-03-25 19:57:20 +00:00
Hubert Chathi 37fb21f726 Merge pull request #1640 from uhoreg/room-history-key-sharing2
Add function to share megolm keys for historical messages.
2021-03-25 14:18:12 -04:00
Ayush PS b42efa4a07 Fixed lint errors 2021-03-25 23:38:18 +05:30
Ayush PS 20b20738a7 Fixed a slight error back to orignal in ScreenShareCall 2021-03-25 23:02:44 +05:30
Ayush PS b28a191c4e Fixed the media fail error on caller's side 2021-03-25 22:43:18 +05:30
Hubert Chathi f92b620434 Merge branch 'develop' into room-history-key-sharing2 2021-03-25 12:24:42 -04:00
RiotRobot ae6e2cca27 v9.10.0-rc.1 2021-03-25 12:06:34 +00:00
RiotRobot bd920eef1f Prepare changelog for v9.10.0-rc.1 2021-03-25 12:06:34 +00:00
J. Ryan Stinnett bf25cb68da Merge pull request #1649 from matrix-org/jryans/get-keys-bootstrap-only
Cache cross-signing private keys if needed on bootstrap
2021-03-24 15:56:15 +00:00
J. Ryan Stinnett 0b063f6b8b Cache cross-signing private keys if needed on bootstrap
This is a revised version of
https://github.com/matrix-org/matrix-js-sdk/pull/1472 which was previously
reverted for causing security prompts to appear on device list sync. In this
version, we only allow private key requests (which are likely to trigger user
dialogs) if we are coming from the bootstrap path.

This allows sessions that have already synced cross-signing public keys but
never got the private keys for some reason to make forward progress when e.g.
the user triggers bootstrap from security settings.
2021-03-24 11:48:45 +00:00
Travis Ralston ed6d4e5f6c Merge pull request #1647 from SimonBrandner/dont-send-hangup
Don't send m.call.hangup if m.call.invite wasn't sent either
2021-03-22 00:42:04 -06:00
Travis Ralston accfa325b5 Merge pull request #1641 from NicolaiSoeborg/fix-registerGuest
docs: registerGuest()
2021-03-21 20:37:49 -06:00
Šimon Brandner b6ef8d95cd Don't send hangup if invite wasn't sent
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-03-21 21:29:00 +01:00
Travis Ralston c1144e3810 Merge pull request #1639 from Johennes/feature/chunk-device-keys
Download device keys in chunks of 250
2021-03-18 13:17:15 -06:00
Johannes Marbach 8663fd402b Download device keys in chunks of 250
Depending on the number of users in the request, the server might
overload. To prevent this, the download is broken into chunks of
250 users each. Additionally, no more than 3 requests are kicked off
at the same time to avoid running into rate limiting. Responses are
processed once all chunks have been downloaded.

Fixes: #1619

Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
2021-03-17 20:56:25 +01:00
Šimon Brandner d8134aa168 Merge branch 'feed' into feed-audio 2021-03-17 16:16:33 +01:00
Šimon Brandner 702b3e8473 Merge branch 'develop' into feed
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-03-17 16:16:07 +01:00
David Baker f34052fd31 Merge pull request #1646 from matrix-org/dbkr/more_call_fixes
More VoIP connectivity fixes
2021-03-17 15:00:09 +00:00
David Baker 27d75a269f unintentional comment 2021-03-16 19:18:45 +00:00
David Baker d208a7fc5f Remove unintentionally committed stuff 2021-03-16 19:17:04 +00:00
David Baker 702e16e3df More VoIP connectivity fixes
* Don't ignore other candidates when we see a null one (continue
   rather than return)
 * await on addICECandidate()
 * Don't add ice candidates until we've set a remote description
 * More & better logging
2021-03-16 19:13:03 +00:00
Hubert Chathi 6381018658 add jsdoc and implementation for memory crypto store 2021-03-16 13:52:05 -04:00
Travis Ralston 12050b14f0 Merge pull request #1644 from SimonBrandner/fix-optional
Make selectDesktopCapturerSource param optional
2021-03-15 21:12:03 -06:00
Hubert Chathi 1c191b2278 use new terminology and field name from MSC 2021-03-15 22:49:43 -04:00
Nicolai Søborg 2d4a4f1736 docs: registerGuest 2021-03-15 22:46:43 +00:00
RiotRobot cd38fb9b4c Resetting package fields for development 2021-03-15 14:34:56 +00:00
RiotRobot 7941b16ec4 Merge branch 'master' into develop 2021-03-15 14:34:56 +00:00
RiotRobot 3ff517e76e v9.9.0 2021-03-15 14:31:58 +00:00
RiotRobot 9559b26310 Prepare changelog for v9.9.0 2021-03-15 14:31:57 +00:00
Šimon Brandner 56ea4b8741 Make selectDesktopCapturerSource param optional
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-03-13 15:03:36 +01:00
Hubert Chathi a489691151 various fixes 2021-03-11 17:30:05 -05:00
Nicolai Søborg 6dabfcda6f setGuest(true) when registerGuest()
Signed-off-by: Nicolai Søborg <git@xn--sb-lka.org>
2021-03-11 22:39:51 +01:00
J. Ryan Stinnett 0b7b35f800 Merge pull request #1632 from matrix-org/matthew/rework-cross-signing-login
Expose APIs needed for reworked cross-signing login flow
2021-03-11 12:54:18 +00:00
Hubert Chathi 0bfcb5071d fix test, lint 2021-03-10 20:04:34 -05:00
Hubert Chathi ceb162eb01 initial work on room history key sharing, take 2 2021-03-10 19:51:22 -05:00
RiotRobot 0ffdf7c0f1 v9.9.0-rc.1 2021-03-10 17:21:50 +00:00
RiotRobot 13b6db8eb4 Prepare changelog for v9.9.0-rc.1 2021-03-10 17:21:49 +00:00
J. Ryan Stinnett 481acb2a1a Merge pull request #1638 from matrix-org/jryans/rm-olm-profiling
Remove detailed Olm session logging
2021-03-10 12:44:22 +00:00
J. Ryan Stinnett 683092140d Remove OTK claim timeout logging 2021-03-10 12:43:45 +00:00
J. Ryan Stinnett 1bb8c2d1a5 Remove detailed Olm session logging
Now that we understand the Olm session deadlock, we shouldn't need this detailed
per-session logging.

Fixes https://github.com/vector-im/element-web/issues/16647
2021-03-10 12:43:45 +00:00
J. Ryan Stinnett 60fd3b0786 Remove extra space in log message 2021-03-10 11:25:44 +00:00
Šimon Brandner b307a177f4 Remove handling of audio from MatrixCall
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-03-10 12:24:48 +01:00
Šimon Brandner 059430bd0a Doc public methods
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-03-10 12:21:15 +01:00
Šimon Brandner 530b60cbc2 Make MatrixCall use CallFeed
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-03-10 12:21:07 +01:00
J. Ryan Stinnett cd4abc4e9b Disable crypto transaction profiling 2021-03-10 11:05:17 +00:00
Michael Telatynski e6a21cc487 Merge pull request #1637 from matrix-org/t3chguy/spaces4.5
Add space summary suggested only param
2021-03-10 10:55:27 +00:00
Šimon Brandner ba8577f268 Add CallFeed class
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-03-10 08:43:01 +01:00
David Baker 6c5fc153bf Merge pull request #1634 from matrix-org/dbkr/check_turn_interval
Check TURN servers periodically, and at start of calls
2021-03-09 17:06:02 +00:00
David Baker 07f15b41a2 Don't start the timer if voip not supported 2021-03-09 14:39:21 +00:00
David Baker 8375638d76 Fix tests
Bit of a re-organisation so a peerconnection exists when the tests
go to mock things out. placeCall methods return promises to make this
possible.
2021-03-09 14:09:55 +00:00
J. Ryan Stinnett bed7543b46 Merge pull request #1624 from robintown/invite-reasons
Support sending invite reasons
2021-03-09 11:44:04 +00:00
Travis Ralston dc55236263 Merge pull request #1636 from matrix-org/dependabot/npm_and_yarn/elliptic-6.5.4
Bump elliptic from 6.5.3 to 6.5.4
2021-03-08 18:23:50 -07:00
dependabot[bot] 5f3427c5d1 Bump elliptic from 6.5.3 to 6.5.4
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.3 to 6.5.4.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.3...v6.5.4)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-09 01:23:08 +00:00
Travis Ralston 66e5af185d Merge pull request #1635 from matrix-org/travis/media-customization
Add a function to get a room's MXC URI
2021-03-08 18:23:00 -07:00
Travis Ralston 0ff611e033 Enum and linter 2021-03-08 18:16:39 -07:00
Travis Ralston 737cadaabc Add a function to get a room's MXC URI
This matches the RoomMember function of the same name.
2021-03-08 18:13:14 -07:00
Matthew Hodgson 9fb2fbaeec factor out getDehydratedDevice 2021-03-09 00:09:22 +00:00
David Baker 51e817a3a2 This is in ms, not seconds 2021-03-08 18:54:50 +00:00
David Baker 59c93b59bf Check TURN servers periodically, and at start of calls
Hopefully this should make our turn-credential checking code a bit
more robust (and possibly fix a seconds / ms mismatch).
2021-03-08 18:49:25 +00:00
David Baker c18ef051fc Merge pull request #1633 from matrix-org/dbkr/stop_streams_if_call_ended
Stop streams if the call has ended
2021-03-08 17:01:31 +00:00
David Baker 1ac5c9acbd Stop streams if the call has ended
When we get user media, don't forget to close the streams if the
call's ended by the time we got media.
2021-03-08 16:55:48 +00:00
J. Ryan Stinnett a034ca171e Merge pull request #1631 from SimonBrandner/remove-export
Remove export keyword from global.d.ts
2021-03-08 14:11:37 +00:00
Matthew Hodgson 977682d37f fix lint 2021-03-08 09:24:25 +00:00
Matthew Hodgson 0bafe263d7 fix lint 2021-03-08 05:05:14 +00:00
Matthew Hodgson 1a8fced80e Merge branch 'develop' into matthew/rework-cross-signing-login 2021-03-08 04:59:40 +00:00
Matthew Hodgson 1c4d0b5e99 expose getDevice API 2021-03-08 04:59:29 +00:00
Matthew Hodgson 844a2b457c expose getDehydratedDevice API 2021-03-08 04:59:19 +00:00
Matthew Hodgson ccf06f2216 don't cancel ourselves when selecting a self-verification partner 2021-03-08 04:58:55 +00:00
Šimon Brandner f630a9f297 Remove export
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-03-06 16:14:12 +01:00
Michael Telatynski 2f71c93b53 Add space summary suggested only param 2021-03-05 16:12:39 +00:00
J. Ryan Stinnett 92032a17a8 Merge pull request #1445 from florianjacob/patch-1
Fix IndexedDB store creation example
2021-03-04 16:28:05 +00:00
David Baker e531456d42 Merge pull request #1613 from SimonBrandner/constraint-cleanup
An attempt to  cleanup how constraints are handled in calls
2021-03-03 15:03:53 +00:00
Šimon Brandner f0b2d2fe4d Null-check screenshareConstraints
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-03-03 15:38:49 +01:00
Šimon Brandner 427500220d Remove AudioVideo ConstraintsType
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-03-03 15:35:02 +01:00
Šimon Brandner 32e19ead74 Merge branch 'develop' into constraint-cleanup 2021-03-03 15:30:46 +01:00
J. Ryan Stinnett d11adb6f43 Merge pull request #1628 from matrix-org/jryans/opt-display-name
Extract display name patterns to constants
2021-03-03 11:44:30 +00:00
Travis Ralston f6155a50f6 Merge pull request #1630 from matrix-org/dependabot/npm_and_yarn/pug-code-gen-2.0.3
Bump pug-code-gen from 2.0.2 to 2.0.3
2021-03-02 21:55:39 -07:00
dependabot[bot] 4efee9445d Bump pug-code-gen from 2.0.2 to 2.0.3
Bumps [pug-code-gen](https://github.com/pugjs/pug) from 2.0.2 to 2.0.3.
- [Release notes](https://github.com/pugjs/pug/releases)
- [Commits](https://github.com/pugjs/pug/compare/pug-code-gen@2.0.2...pug@2.0.3)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-03 03:35:37 +00:00
J. Ryan Stinnett 20746a433f Extract display name patterns to constants
This changes to constant patterns for calculating display names, which cuts out
~18% of the time spent and reduces GC pressure as well.
2021-03-02 17:52:57 +00:00
J. Ryan Stinnett 31dacc4206 Merge pull request #1627 from matrix-org/jryans/olm-session-deadlock
Avoid deadlocks when ensuring Olm sessions for devices
2021-03-02 14:35:04 +00:00
J. Ryan Stinnett 88e5c59a85 Fix lint warning on OTK result variable 2021-03-02 13:03:12 +00:00
J. Ryan Stinnett cf74920b36 Remove redundant Olm session in progress deletion
This removes extra steps that duplicated deletion of an in progress Olm session.
Resolving the promise handles removing the session from the in progress set, so
there's no need to do it again. There's also no need to delete from
`resolveSession`, as it's okay to resolve a promise multiple times.
2021-03-02 12:58:09 +00:00
J. Ryan Stinnett 972c900b58 Remove unused support for rejecting in progress Olm sessions
This removes the unused `reject` path for in progress Olm sessions to simplify
understanding the code.
2021-03-02 12:55:43 +00:00
J. Ryan Stinnett 12d5fd79f7 Avoid deadlocks when ensuring Olm sessions for devices
This reworks tracking the Olm sessions a particular task is updating to avoid
deadlocks. By ensuring we synchronously mark all sessions a task cares about as
in progress from the start, we know that no other tasks will own updating a
session in common, which avoids deadlocks across multiple tasks that might be
working on a shared set of devices.

Fixes https://github.com/vector-im/element-web/issues/16194
2021-03-02 12:50:49 +00:00
J. Ryan Stinnett a29f6979b2 Merge pull request #1626 from matrix-org/jryans/replacement-senders
Filter out edits from other senders in history
2021-03-02 12:33:21 +00:00
J. Ryan Stinnett 3a7146c77b Only log claim timeouts when a time was provided
This avoids logging immediately on various code paths (including tests) where no
timeout value is supplied.
2021-03-02 12:22:58 +00:00
J. Ryan Stinnett b178d8f629 Filter out edits from other senders in history
We currently don't support edits from other senders, but the server may not
filter them, so we filter them here on the client.
2021-03-02 12:15:27 +00:00
Šimon Brandner 0c94ee62a3 Pass in selectDesktopCapturerSource()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-03-02 13:00:57 +01:00
Šimon Brandner e7562898cd Add getScreenshareContraints()
This is nicer since we avoid some async functions

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-03-02 12:58:45 +01:00
RiotRobot fb73ab6878 Resetting package fields for development 2021-03-01 12:48:30 +00:00
RiotRobot 38f978791d Merge branch 'master' into develop 2021-03-01 12:48:30 +00:00
RiotRobot 5dd60de57d v9.8.0 2021-03-01 12:44:55 +00:00
RiotRobot 5efbfc2dba Prepare changelog for v9.8.0 2021-03-01 12:44:54 +00:00
J. Ryan Stinnett fcd1dbad89 Merge pull request #1618 from robintown/fix-content-helpers-export
Fix ContentHelpers export
2021-03-01 11:13:10 +00:00
J. Ryan Stinnett ad521bf4c2 Merge pull request #1621 from matrix-org/jryans/megolm-logs-2021-02-26
Add logging to in progress Olm sessions
2021-02-28 17:52:24 +00:00
J. Ryan Stinnett 8152fa44e0 Add more logging scopes to session IDs
This uses prefix chaining to correlate several scopes together.
2021-02-28 17:15:07 +00:00
J. Ryan Stinnett e217bf9e37 Enable prefixed loggers to chain 2021-02-28 17:15:07 +00:00
David Baker bfad21f811 Merge pull request #1623 from matrix-org/dbkr/ice_candidate_buffer
Don't ignore ICE candidates received before offer/answer
2021-02-27 15:11:26 +00:00
David Baker 81e68abce3 Merge pull request #1622 from matrix-org/dbkr/candidate_retries
Better handling of send failures on VoIP events
2021-02-27 15:11:00 +00:00
David Baker 7963bb352d Merge pull request #1620 from matrix-org/dbkr/log_turn_cred_expiry
Log when turn creds expire
2021-02-27 15:09:54 +00:00
Michael Telatynski 14d3882059 Merge pull request #1563 from matrix-org/t3chguy/spaces
Initial Spaces [MSC1772] support
2021-02-26 22:08:09 +00:00
Robin Townsend dede508e89 Support sending invite reasons
Added as the final argument to `invite` in order to keep backwards
compatibility.

Signed-off-by: Robin Townsend <robin@robin.town>
2021-02-26 16:46:18 -05:00
David Baker ea39b69f65 Don't ignore ICE candidates received before offer/answer
The main bug here was a race on the callee side because we await-ed
on setRemoteDescription before setting the opponent party ID, and
while we were await-ing, the callEventHandler could give us candidate
events which we'd duly ignore because we thought the party ID didn't
match.

This also meant that any candidates that arrived before the answer
would have been ignored. Save these up by party ID and then add the
ones from the party ID that we pick once the answer comes in.

Also fix the confusion on party IDs where we weren't sure whether
we hadn't picked an opponent or we'd picked an opponent without a
party ID. It's now undefined for the former and null for the latter,
as it claims to be in the comment.
2021-02-26 21:25:52 +00:00
David Baker eafecd36bc Better handling of send failures on VoIP events
Don't leave candidate message sin the queue, abort if we fail to
send the invite.
2021-02-26 18:42:05 +00:00
J. Ryan Stinnett 198c9a2507 Add logging to in progress Olm sessions
It seems like this might be where
https://github.com/vector-im/element-web/issues/16194 is deadlocking.
2021-02-26 17:27:06 +00:00
David Baker d07563013b Log when turn creds expire 2021-02-26 14:47:27 +00:00
Michael Telatynski 9e967832cd Update space summary API unstable prefix 2021-02-26 10:37:09 +00:00
Michael Telatynski bfe1987cd9 Add Spaces event types from MSC1772 2021-02-26 10:35:02 +00:00
Robin Townsend 1045538f1f Fix ContentHelpers export
This was previously exporting a promise, since it called the import
function manually but didn't await the result. However, since we have
Babel we can just use the new export … as … from syntax instead.

Signed-off-by: Robin Townsend <robin@robin.town>
2021-02-25 14:41:48 -05:00
J. Ryan Stinnett fccf08edcf Merge pull request #1617 from matrix-org/jryans/crypto-store-logging
Add logging to crypto store transactions
2021-02-25 16:58:45 +00:00
J. Ryan Stinnett f43fe366b5 Add logging to crypto store transactions
We churn through a huge number of crypto store transactions during startup,
which may be the cause of the symptoms in
https://github.com/vector-im/element-web/issues/16194.
2021-02-25 16:49:49 +00:00
Michael Telatynski 0f75f2ef9c Add base API for Space Summary MSC2946 2021-02-25 13:12:22 +00:00
Michael Telatynski 2cdc68f9c3 Merge pull request #1610 from matrix-org/t3chguy/spaces2
Room helper for getting type and checking if it is a space room
2021-02-25 11:30:49 +00:00
RiotRobot 6a7d58e22e v9.8.0-rc.1 2021-02-24 17:24:17 +00:00
RiotRobot 203829c1cd Prepare changelog for v9.8.0-rc.1 2021-02-24 17:24:16 +00:00
J. Ryan Stinnett b55e6c4ef0 Merge pull request #1615 from matrix-org/jryans/megolm-logs-2021-02-22
Optimise prefixed logger
2021-02-23 17:46:57 +00:00
J. Ryan Stinnett 8d779e8aec Optimise prefixed logger
Tweak the prefixed logger to only do the setup work the first time.
2021-02-23 16:32:10 +00:00
J. Ryan Stinnett dd1d48f688 Merge pull request #1614 from matrix-org/jryans/megolm-logs-2021-02-22
Add debug logs to encryption prep, take 3
2021-02-23 16:07:39 +00:00
J. Ryan Stinnett 8d14dc9ee3 Add debug logs to encryption prep, take 3
This continues adding more logs to work out the root cause of
https://github.com/vector-im/element-web/issues/16194.

Somehow, we're getting stuck while sharing keys with new sessions.
2021-02-23 14:22:44 +00:00
Šimon Brandner 5849ea8e63 Add AudioVideo constraint type
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-02-23 12:25:20 +01:00
Šimon Brandner 20afebf339 Set video to true
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-02-23 12:23:49 +01:00
Šimon Brandner 20eaba191e Simplifie placeScreenSharingCall()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-02-23 11:12:16 +01:00
Šimon Brandner ba58d3c544 Add screenshare type to getUserMediaContraints()
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-02-23 10:47:43 +01:00
David Baker a8b9d8e3ae Merge pull request #1612 from matrix-org/dbkr/jitsi_conference_captialised
Add functions for upper & lowercase random strings
2021-02-22 17:33:35 +00:00
David Baker 83d1e61b2f Add functions for upper & lowercase random strings 2021-02-22 16:47:16 +00:00
Michael Telatynski 8e0fc8d460 Room helper for getting type and checking if it is a space room 2021-02-19 14:21:22 +00:00
Michael Telatynski f547fa732f Merge pull request #1609 from matrix-org/t3chguy/spaces1
Room helpers for invite permissions and join rules
2021-02-18 18:02:31 +00:00
Michael Telatynski e24b1519a4 Merge pull request #1606 from SimonBrandner/fix-log
Fixed wording in "Adding video track with id" log
2021-02-18 18:00:28 +00:00
Michael Telatynski 3028fe9c87 Improve room documentation 2021-02-18 14:52:32 +00:00
Michael Telatynski 0b970b05b6 Wire up helpers for checking if a user can invite to a room and getting its join rule 2021-02-18 14:52:23 +00:00
Šimon Brandner f7bfb1e49e Fixed log (audio -> video)
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-02-17 20:51:43 +01:00
J. Ryan Stinnett 371ca009e9 Merge pull request #1605 from matrix-org/jryans/more-megolm-logging
Add more debug logs to encryption prep
2021-02-17 13:56:46 +00:00
J. Ryan Stinnett 4a0f848551 Add more debug logs to encryption prep
This continues work from https://github.com/matrix-org/matrix-js-sdk/pull/1580
and adds more logging, including specialised logging for a potential cause of
https://github.com/vector-im/element-web/issues/16194.

So far, it seems clear that something's going wrong in the "sharing keys with
new Olm session" step.
2021-02-17 13:45:26 +00:00
David Baker 5e8b7b2a62 Merge pull request #1604 from matrix-org/dbkr/ice_candidate_pool_size
Add option to set ice candidate pool size
2021-02-16 16:01:53 +00:00
David Baker 0f27b703bd Should be optional 2021-02-16 15:51:10 +00:00
David Baker 61e19c30cb Add option to set ice candidate pool size 2021-02-16 15:47:48 +00:00
RiotRobot c82bc35202 Resetting package fields for development 2021-02-16 10:58:15 +00:00
RiotRobot 65934227c3 Merge branch 'master' into develop 2021-02-16 10:58:15 +00:00
RiotRobot 7519becd43 v9.7.0 2021-02-16 10:55:42 +00:00
RiotRobot fe83c15bc6 Prepare changelog for v9.7.0 2021-02-16 10:55:41 +00:00
J. Ryan Stinnett 07e6b47fa7 Merge pull request #1601 from SimonBrandner/cancel-call-if-no-source
Cancel call if no source was selected
2021-02-11 12:29:57 +00:00
RiotRobot b026e1c2f7 v9.7.0-rc.1 2021-02-10 15:54:02 +00:00
RiotRobot f8194d9418 Prepare changelog for v9.7.0-rc.1 2021-02-10 15:54:01 +00:00
Šimon Brandner 1ecd7f274f Cancel call if no source was selected
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-02-10 07:49:03 +01:00
David Baker 66bf0ec7af Merge pull request #1600 from SimonBrandner/handle-undefined-peerconn
Handle undefined peerconn
2021-02-09 16:29:46 +00:00
Šimon Brandner 1b22df2b7b Handle undefined peerconn
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-02-09 14:42:34 +01:00
David Baker 9f993f1f67 Merge pull request #1599 from matrix-org/dbkr/reemitter_dont_throw_if_no_error_handler
ReEmitter: Don't throw if no error handler is attached
2021-02-08 19:44:03 +00:00
David Baker 975518bd88 ReEmitter: Don't throw if no error handler is attached
As hopefully explained by lengthy comment

Fixes https://github.com/matrix-org/matrix-js-sdk/issues/1569
2021-02-08 19:37:17 +00:00
David Baker 66a863456c Merge pull request #1598 from matrix-org/dbkr/reemitter_ts
Convert ReEmitter to TS
2021-02-08 19:15:08 +00:00
David Baker 91290c0d25 Actually add the test 2021-02-08 19:09:32 +00:00
David Baker 8a23e89c87 Convert ReEmitter to TS
And also add a test so I can be confident it's actually doing the
same thing.

NB. There was some logic there previously to reduce the number of
bound functions that had to be kept around, but it subsequently
started adding the source object as the last arg, at which point
there's now one bound function in memory per re-emitted event name
(plus the previous per-event-name handlers). This reduces it so it's
just one per re-emitted event name, so still could be quite a few,
but fewer than before.
2021-02-08 19:04:23 +00:00
Michael Telatynski 9e9cf85ba1 Merge pull request #1597 from rherrmann/patch-1
Fix typo in main readme
2021-02-08 17:18:29 +00:00
David Baker 3dd365bbea Merge pull request #1596 from matrix-org/dbkr/rogue_plus
Remove rogue plus character
2021-02-08 16:49:47 +00:00
Rüdiger Herrmann 33a824b980 Fix typo in main readme
Signed-off-by: Rüdiger Herrmann <ruediger.herrmann@gmx.de>
2021-02-08 17:41:48 +01:00
David Baker 8571884304 Remove rogue plus character
Apparently this is perfectly valid javascript and somehow casts
this.callId to a number... possibly it's ignoring the whitespace
and trating it as `++this.callId`?
2021-02-08 16:27:38 +00:00
David Baker 4f1067e66c Merge pull request #1595 from matrix-org/dbkr/call_id_nan
Fix call ID NaN
2021-02-08 16:18:01 +00:00
David Baker 7b5b851db0 Fix call ID NaN
We were seeing call IDs of NaN in the wild somehow... hopefully this
should make sure they're all actually strings.
2021-02-08 16:12:39 +00:00
J. Ryan Stinnett ed0be0cf84 Merge pull request #1594 from matrix-org/jryans/electron-type-merge
Fix Electron type merging
2021-02-08 15:25:14 +00:00
J. Ryan Stinnett d3775e5cb1 Fix Electron type merging
This changes to an interface for Electron types so that other layers can merge
in further APIs as needed.
2021-02-08 15:13:00 +00:00
J. Ryan Stinnett 2c8f658810 Merge pull request #1593 from SimonBrandner/fix-browser-screens-share
Fix browser screen share
2021-02-08 14:56:57 +00:00
Šimon Brandner 5c52f5f579 Fix browser screen share
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-02-08 15:48:30 +01:00
David Baker 0a81bb3fdc Merge pull request #1570 from SimonBrandner/fix-screen-sharing
Fix desktop Matrix screen sharing
2021-02-08 13:54:38 +00:00
J. Ryan Stinnett f33196bc51 Merge pull request #1591 from matrix-org/jryans/pos-wait
Guard against confused server retry times
2021-02-05 17:42:19 +00:00
J. Ryan Stinnett 6beb90a835 Guard against confused server retry times
If a server happens to give a negative retry time, this would be passed to
`setTimeout`, and browsers interpret negative values as `0`, meaning "as soon as
possible", so we then start looping infinitely with no delay.
2021-02-05 17:37:40 +00:00
J. Ryan Stinnett 9d45e6acd6 Merge pull request #1589 from SimonBrandner/decrypt-redaction-reason
Decrypt redaction events
2021-02-04 16:10:59 +00:00
Šimon Brandner 516c464458 Call decryptEvent recursively
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-02-04 16:59:26 +01:00
RiotRobot 6ad3fb16b3 Resetting package fields for development 2021-02-03 12:01:13 +00:00
RiotRobot 277fdd9b8c Merge branch 'master' into develop 2021-02-03 12:01:13 +00:00
RiotRobot 7d56993b39 v9.6.0 2021-02-03 11:58:27 +00:00
RiotRobot 4e1442fcf6 Prepare changelog for v9.6.0 2021-02-03 11:58:27 +00:00
Michael Telatynski 4777bf3e75 Merge pull request #1588 from matrix-org/t3chguy/cherrypick/1587
[Release] Fix edge cases with peeking where a room is re-peeked
2021-02-01 13:01:01 +00:00
Šimon Brandner 14cd37ec56 Decrypt redaction events
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-02-01 13:52:56 +01:00
Michael Telatynski 8bcdfd50c9 Fix edge cases with peeking where a room is re-peeked
but two Room instances are created and things get duplicated
2021-02-01 12:30:04 +00:00
Michael Telatynski 6776df8e80 Merge pull request #1587 from matrix-org/t3chguy/peeking
Fix edge cases with peeking where a room is re-peeked
2021-02-01 12:26:35 +00:00
Michael Telatynski fbec079c9b Fix edge cases with peeking where a room is re-peeked
but two Room instances are created and things get duplicated
2021-01-31 16:08:03 +00:00
RiotRobot 93f6bc3780 v9.6.0-rc.1 2021-01-29 17:20:04 +00:00
RiotRobot dde8f23cc3 Prepare changelog for v9.6.0-rc.1 2021-01-29 17:20:03 +00:00
RiotRobot 7cfbd0da95 Merge branch 'master' into develop 2021-01-26 11:42:21 +00:00
RiotRobot a27ddfaaaf v9.5.1 2021-01-26 11:39:39 +00:00
RiotRobot b53f616015 Prepare changelog for v9.5.1 2021-01-26 11:39:38 +00:00
J. Ryan Stinnett 22dc175879 Merge pull request #1585 from matrix-org/dbkr/voip-v0-release
[Release] Fix compatibility with v0 calls
2021-01-26 11:24:07 +00:00
David Baker 5f23e4699c We were using undefined here too 2021-01-26 11:17:44 +00:00
David Baker a1bd258a7b Remove unintentional commit 2021-01-26 11:17:44 +00:00
David Baker 39a9c54589 Fix compatability with v0 calls
https://github.com/matrix-org/matrix-js-sdk/pull/1567 introduced a
bug where we'd leave opponentPartyId undefined, but we compared it
to null later when testing for its presence.

Fixes https://github.com/vector-im/element-web/issues/16239
2021-01-26 11:17:44 +00:00
David Baker 5f68370e07 Merge pull request #1584 from matrix-org/dbkr/callstats
Add support for getting call stats
2021-01-26 10:53:53 +00:00
David Baker dae2de703d Add support for getting call stats
Also add a few 'public' annotations
2021-01-26 09:40:20 +00:00
David Baker fa19c40868 Merge pull request #1583 from matrix-org/dbkr/fix_v0_compat
Fix compatibility with v0 calls
2021-01-25 17:29:59 +00:00
David Baker 1df69d259a We were using undefined here too 2021-01-25 16:34:28 +00:00
David Baker 90dda0ca68 Remove unintentional commit 2021-01-25 16:13:13 +00:00
David Baker e2d138cac6 Fix compatability with v0 calls
https://github.com/matrix-org/matrix-js-sdk/pull/1567 introduced a
bug where we'd leave opponentPartyId undefined, but we compared it
to null later when testing for its presence.

Fixes https://github.com/vector-im/element-web/issues/16239
2021-01-25 16:09:39 +00:00
J. Ryan Stinnett 15f968d5f8 Merge pull request #1582 from matrix-org/jryans/upgrade-deps-2021-01
Upgrade deps 2021-01
2021-01-22 10:16:41 +00:00
Šimon Brandner 4a3b68de8f Merge branch 'develop' into fix-screen-sharing 2021-01-21 19:15:33 +01:00
David Baker f6aec7f763 Merge pull request #1581 from matrix-org/dbkr/log_the_call_id
Log the call ID when logging that we've received VoIP events
2021-01-21 17:59:49 +00:00
J. Ryan Stinnett 212b6c3a0f Resolve linting errors after upgrades 2021-01-20 13:54:45 +00:00
J. Ryan Stinnett 820256d451 Nested upgrades via yarn upgrade 2021-01-20 11:07:11 +00:00
J. Ryan Stinnett 3aba538db3 Update to latest deps 2021-01-20 11:05:17 +00:00
David Baker 4820cf8cac Log call ID here too 2021-01-19 19:28:08 +00:00
David Baker c289effba0 Log the call ID when logging that we've received VoIP events
Should make the logs a bit clearer
2021-01-19 18:11:41 +00:00
David Baker 3edccf496a Merge pull request #1579 from matrix-org/dbkr/foxes_dont_like_to_be_held
Fix extra negotiate message in Firefox
2021-01-19 17:51:35 +00:00
J. Ryan Stinnett 97b4171b3e Merge pull request #1580 from matrix-org/jryans/debug-encryption-prep
Add debug logs to encryption prep
2021-01-19 15:47:34 +00:00
J. Ryan Stinnett 4a073a7ba5 Fix lint 2021-01-19 15:36:08 +00:00
J. Ryan Stinnett 9f275d57a9 Add debug logs to encryption prep
This extra debug logs may help isolate the cause of
https://github.com/vector-im/element-web/issues/16194.

These changes also fix a related (but most likely different) failure mode: if a
failure occurred in the `encryptionPreparation` async task, we would skip trying
to prepare in all future attempts for that room. This change ensures prep
failures are logged and we resume prep attempts on the next call from the
application.
2021-01-19 15:28:28 +00:00
David Baker d23bbaeb06 Fix extra negotiate message in Firefox
Hopefully explained by the comments: Firefox sees that it's been
put on hold and tries to negotiate itself off hold again.

Fixes https://github.com/vector-im/element-web/issues/16190
2021-01-19 12:25:36 +00:00
J. Ryan Stinnett c64f7a9ec4 Merge pull request #1578 from tzyl/tzyl/get-presence-endpoint
Expose getPresence endpoint
2021-01-19 11:03:02 +00:00
RiotRobot 214a9df382 Resetting package fields for development 2021-01-18 15:06:36 +00:00
RiotRobot 90f6620f1e Merge branch 'master' into develop 2021-01-18 15:06:36 +00:00
tzyl f6e8048d9e Expose getPresence endpoint 2021-01-18 10:17:46 +00:00
Hubert Chathi 5afca17d27 Merge pull request #1577 from uhoreg/always_queue_backup
Queue keys for backup even if backup isn't enabled yet
2021-01-15 12:28:06 -05:00
J. Ryan Stinnett 2d7f5ae279 Merge pull request #1576 from matrix-org/jryans/forbidden-turn
Stop retrying TURN access when forbidden
2021-01-15 10:06:18 +00:00
Hubert Chathi 458384d658 queue keys for backup even if backup isn't enabled yet
We may not have managed to set up the backup yet when we get keys.  So we should
unconditionally queue up the keys for backup, so that when the backup is set up,
they will be sent instead of dropped.
2021-01-14 19:55:02 -05:00
J. Ryan Stinnett 159b98132d Stop retrying TURN access when forbidden
If we're not allowed to have TURN access, there's no reason to ask in a loop.
2021-01-14 17:49:15 +00:00
Šimon Brandner 349bb2730a Update thumbnails
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-01-14 12:44:50 +01:00
Šimon Brandner c13813348d Merge branch 'develop' into fix-screen-sharing 2021-01-14 08:35:58 +01:00
Šimon Brandner 26e70d6b30 Use contextBridge
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2021-01-14 08:34:46 +01:00
David Baker f6d3b50b08 Merge pull request #1573 from matrix-org/dbkr/dtmf
Add DTMF sending support
2021-01-13 13:07:18 +00:00
David Baker 5b1fdb7b37 Typo
Co-authored-by: J. Ryan Stinnett <jryans@gmail.com>
2021-01-13 11:37:30 +00:00
Šimon Brandner c701bf279f Merge branch 'develop' into fix-screen-sharing 2021-01-05 20:48:34 +01:00
David Baker f8f76f6806 Add DTMF sending support 2021-01-04 19:58:12 +00:00
Šimon Brandner c4e7c149a4 Type cleanup
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2020-12-26 18:09:38 +01:00
Šimon Brandner f91edfabbb Change formatting
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2020-12-26 16:58:08 +01:00
Šimon Brandner f410004d45 Clean up
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2020-12-26 08:50:46 +01:00
Šimon Brandner 49e238d580 Get screen-sharing working, somehow
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
2020-12-26 08:32:50 +01:00
Michael Telatynski 54a03b234a Merge branch 'develop' into t3chguy/ts/4 2020-10-22 16:46:06 +01:00
Michael Telatynski ad2f537887 Merge remote-tracking branch 'origin/t3chguy/ts/4' into t3chguy/ts/4 2020-10-13 22:34:22 +01:00
Michael Telatynski df36f0dab4 fix couple more errors
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2020-10-13 22:34:06 +01:00
Hubert Chathi 608d7faa29 fix some typescript errors 2020-10-13 17:25:58 -04:00
Michael Telatynski 7845957d0d fix Olm types import
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2020-10-13 19:43:31 +01:00
Michael Telatynski 13c5c4e4f5 Use utf8 instead of utf-8
as per https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2020-10-13 19:36:03 +01:00
Michael Telatynski 62114028d5 Convert aes, key_passphrase, olmlib, and recoverykey to TS
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2020-10-13 19:28:16 +01:00
florianjacob 22713d8f89 correct IndexedDB store creation example 2020-08-26 14:24:13 +02:00
209 changed files with 45036 additions and 32854 deletions
+22 -7
View File
@@ -1,13 +1,14 @@
module.exports = {
extends: ["matrix-org"],
plugins: [
"babel",
"matrix-org",
],
extends: [
"plugin:matrix-org/babel",
],
env: {
browser: true,
node: true,
},
rules: {
"no-var": ["warn"],
"prefer-rest-params": ["warn"],
@@ -32,12 +33,26 @@ module.exports = {
"no-console": "error",
},
overrides: [{
"files": ["src/**/*.ts"],
"extends": ["matrix-org/ts"],
"rules": {
// While we're converting to ts we make heavy use of this
files: [
"**/*.ts",
],
extends: [
"plugin:matrix-org/typescript",
],
rules: {
// TypeScript has its own version of this
"@babel/no-invalid-this": "off",
// We're okay being explicit at the moment
"@typescript-eslint/no-empty-interface": "off",
// We disable this while we're transitioning
"@typescript-eslint/no-explicit-any": "off",
// We'd rather not do this but we do
"@typescript-eslint/ban-ts-comment": "off",
"quotes": "off",
// We use a `logger` intermediary module
"no-console": "error",
},
}],
};
+1
View File
@@ -0,0 +1 @@
* @matrix-org/element-web
+7
View File
@@ -0,0 +1,7 @@
<!-- Please read https://github.com/matrix-org/matrix-js-sdk/blob/develop/CONTRIBUTING.md before submitting your pull request -->
<!-- Include a Sign-Off as described in https://github.com/matrix-org/matrix-js-sdk/blob/develop/CONTRIBUTING.md#sign-off -->
<!-- To specify text for the changelog entry (otherwise the PR title will be used):
Notes:
-->
+12
View File
@@ -0,0 +1,12 @@
name: Preview Changelog
on:
pull_request_target:
types: [ opened, edited, labeled ]
jobs:
changelog:
runs-on: ubuntu-latest
steps:
- name: Preview Changelog
uses: matrix-org/allchange@main
with:
ghToken: ${{ secrets.GITHUB_TOKEN }}
+3
View File
@@ -16,3 +16,6 @@ out
# version file and tarball created by `npm pack` / `yarn pack`
/git-revision.txt
/matrix-js-sdk-*.tgz
.vscode
.vscode/
+748
View File
@@ -1,3 +1,751 @@
Changes in [15.3.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.3.0) (2021-12-20)
==================================================================================================
## ✨ Features
* Improve fallback key behaviour ([\#2037](https://github.com/matrix-org/matrix-js-sdk/pull/2037)).
* Add new room event filter fields ([\#2051](https://github.com/matrix-org/matrix-js-sdk/pull/2051)).
* Add method to fetch /account/whoami ([\#2046](https://github.com/matrix-org/matrix-js-sdk/pull/2046)).
## 🐛 Bug Fixes
* Filter out falsey opts in /relations API hits ([\#2059](https://github.com/matrix-org/matrix-js-sdk/pull/2059)). Fixes vector-im/element-web#20137.
* Fix paginateEventTimeline resolve to boolean ([\#2054](https://github.com/matrix-org/matrix-js-sdk/pull/2054)).
* Fix incorrect MSC3089 typings and add null checks ([\#2049](https://github.com/matrix-org/matrix-js-sdk/pull/2049)).
Changes in [15.3.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.3.0-rc.1) (2021-12-14)
============================================================================================================
## ✨ Features
* Improve fallback key behaviour ([\#2037](https://github.com/matrix-org/matrix-js-sdk/pull/2037)).
* Add new room event filter fields ([\#2051](https://github.com/matrix-org/matrix-js-sdk/pull/2051)).
* Add method to fetch /account/whoami ([\#2046](https://github.com/matrix-org/matrix-js-sdk/pull/2046)).
## 🐛 Bug Fixes
* Filter out falsey opts in /relations API hits ([\#2059](https://github.com/matrix-org/matrix-js-sdk/pull/2059)). Fixes vector-im/element-web#20137.
* Fix paginateEventTimeline resolve to boolean ([\#2054](https://github.com/matrix-org/matrix-js-sdk/pull/2054)).
* Fix incorrect MSC3089 typings and add null checks ([\#2049](https://github.com/matrix-org/matrix-js-sdk/pull/2049)).
Changes in [15.2.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.2.1) (2021-12-13)
==================================================================================================
* Security release with updated version of Olm to fix https://matrix.org/blog/2021/12/03/pre-disclosure-upcoming-security-release-of-libolm-and-matrix-js-sdk
Changes in [15.2.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.2.0) (2021-12-06)
==================================================================================================
## ✨ Features
* Remove support for `ArrayBuffer` in unstable MSC3089 `createFile()` and `createNewVersion()` and instead use same content types as handled by `MatrixClient.uploadContent()`. This enables support for Node.js. ([\#2014](https://github.com/matrix-org/matrix-js-sdk/pull/2014)).
* Support for password-based backup on Node.js ([\#2021](https://github.com/matrix-org/matrix-js-sdk/pull/2021)).
* Add optional force parameter when ensuring Olm sessions ([\#2027](https://github.com/matrix-org/matrix-js-sdk/pull/2027)).
## 🐛 Bug Fixes
* Fix call upgrades ([\#2024](https://github.com/matrix-org/matrix-js-sdk/pull/2024)). Contributed by @SimonBrandner.
Changes in [15.2.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.2.0-rc.1) (2021-11-30)
============================================================================================================
## ✨ Features
* Remove support for `ArrayBuffer` in unstable MSC3089 `createFile()` and `createNewVersion()` and instead use same content types as handled by `MatrixClient.uploadContent()`. This enables support for Node.js. ([\#2014](https://github.com/matrix-org/matrix-js-sdk/pull/2014)).
* Support for password-based backup on Node.js ([\#2021](https://github.com/matrix-org/matrix-js-sdk/pull/2021)).
* Add optional force parameter when ensuring Olm sessions ([\#2027](https://github.com/matrix-org/matrix-js-sdk/pull/2027)).
## 🐛 Bug Fixes
* Fix call upgrades ([\#2024](https://github.com/matrix-org/matrix-js-sdk/pull/2024)). Contributed by @SimonBrandner.
Changes in [15.1.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.1.1) (2021-11-22)
==================================================================================================
## 🐛 Bug Fixes
* Fix edit history being broken after editing an unencrypted event with an encrypted event ([\#2013](https://github.com/matrix-org/matrix-js-sdk/pull/2013)). Fixes vector-im/element-web#19651 and vector-im/element-web#19651. Contributed by @aaronraimist.
* Make events pagination responses parse threads ([\#2011](https://github.com/matrix-org/matrix-js-sdk/pull/2011)). Fixes vector-im/element-web#19587 and vector-im/element-web#19587.
Changes in [15.1.1-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.1.1-rc.1) (2021-11-17)
============================================================================================================
## 🐛 Bug Fixes
* Fix edit history being broken after editing an unencrypted event with an encrypted event ([\#2013](https://github.com/matrix-org/matrix-js-sdk/pull/2013)). Fixes vector-im/element-web#19651 and vector-im/element-web#19651. Contributed by @aaronraimist.
* Make events pagination responses parse threads ([\#2011](https://github.com/matrix-org/matrix-js-sdk/pull/2011)). Fixes vector-im/element-web#19587 and vector-im/element-web#19587.
Changes in [15.1.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.1.0) (2021-11-08)
==================================================================================================
## 🦖 Deprecations
* Mark old verification methods as deprecated ([\#1994](https://github.com/matrix-org/matrix-js-sdk/pull/1994)).
## ✨ Features
* Try to set a sender on search result events if possible ([\#2004](https://github.com/matrix-org/matrix-js-sdk/pull/2004)).
* Port some changes from group calls branch to develop ([\#2001](https://github.com/matrix-org/matrix-js-sdk/pull/2001)). Contributed by @SimonBrandner.
* Fetch room membership from server rather than relying on stored data ([\#1998](https://github.com/matrix-org/matrix-js-sdk/pull/1998)).
* Add method to fetch the MSC3266 Room Summary of a Room ([\#1988](https://github.com/matrix-org/matrix-js-sdk/pull/1988)).
## 🐛 Bug Fixes
* Don't show `Unable to access microphone` when cancelling screensharing dialog ([\#2005](https://github.com/matrix-org/matrix-js-sdk/pull/2005)). Fixes vector-im/element-web#19533 and vector-im/element-web#19533. Contributed by @SimonBrandner.
* Strip direction override characters from display names ([\#1992](https://github.com/matrix-org/matrix-js-sdk/pull/1992)). Fixes vector-im/element-web#1712 and vector-im/element-web#1712.
Changes in [15.1.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.1.0-rc.1) (2021-11-02)
============================================================================================================
## 🦖 Deprecations
* Mark old verification methods as deprecated ([\#1994](https://github.com/matrix-org/matrix-js-sdk/pull/1994)).
## ✨ Features
* Try to set a sender on search result events if possible ([\#2004](https://github.com/matrix-org/matrix-js-sdk/pull/2004)).
* Port some changes from group calls branch to develop ([\#2001](https://github.com/matrix-org/matrix-js-sdk/pull/2001)). Contributed by @SimonBrandner.
* Fetch room membership from server rather than relying on stored data ([\#1998](https://github.com/matrix-org/matrix-js-sdk/pull/1998)).
* Add method to fetch the MSC3266 Room Summary of a Room ([\#1988](https://github.com/matrix-org/matrix-js-sdk/pull/1988)).
## 🐛 Bug Fixes
* Don't show `Unable to access microphone` when cancelling screensharing dialog ([\#2005](https://github.com/matrix-org/matrix-js-sdk/pull/2005)). Fixes vector-im/element-web#19533 and vector-im/element-web#19533. Contributed by @SimonBrandner.
* Strip direction override characters from display names ([\#1992](https://github.com/matrix-org/matrix-js-sdk/pull/1992)). Fixes vector-im/element-web#1712 and vector-im/element-web#1712.
Changes in [15.0.0](https://github.com/vector-im/element-desktop/releases/tag/v15.0.0) (2021-10-25)
===================================================================================================
## 🚨 BREAKING CHANGES
* Use `ICallFeedOpts` in the `CallFeed` constructor. To construct a new `CallFeed` object you have to pass `ICallFeedOpts` e.g. `const callFeed = new CallFeed({client ([\#1964](https://github.com/matrix-org/matrix-js-sdk/pull/1964)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
## ✨ Features
* Make threads use 'm.thread' relation ([\#1980](https://github.com/matrix-org/matrix-js-sdk/pull/1980)).
* Try to answer a call without video if we can't access the camera ([\#1972](https://github.com/matrix-org/matrix-js-sdk/pull/1972)). Fixes vector-im/element-web#17975 and vector-im/element-web#17975. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Make `opts` in `importRoomKeys()` optional ([\#1974](https://github.com/matrix-org/matrix-js-sdk/pull/1974)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Enable TypeScript declaration maps ([\#1966](https://github.com/matrix-org/matrix-js-sdk/pull/1966)). Contributed by [Alexendoo](https://github.com/Alexendoo).
## 🐛 Bug Fixes
* Fix `requestVerificationDM` with chronological `pendingEventOrdering` ([\#1943](https://github.com/matrix-org/matrix-js-sdk/pull/1943)). Contributed by [freaktechnik](https://github.com/freaktechnik).
Changes in [15.0.0-rc.1](https://github.com/vector-im/element-desktop/releases/tag/v15.0.0-rc.1) (2021-10-19)
=============================================================================================================
## 🚨 BREAKING CHANGES
* Use `ICallFeedOpts` in the `CallFeed` constructor. To construct a new `CallFeed` object you have to pass `ICallFeedOpts` e.g. `const callFeed = new CallFeed({client ([\#1964](https://github.com/matrix-org/matrix-js-sdk/pull/1964)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
## ✨ Features
* Make threads use 'm.thread' relation ([\#1980](https://github.com/matrix-org/matrix-js-sdk/pull/1980)).
* Try to answer a call without video if we can't access the camera ([\#1972](https://github.com/matrix-org/matrix-js-sdk/pull/1972)). Fixes vector-im/element-web#17975 and vector-im/element-web#17975. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Make `opts` in `importRoomKeys()` optional ([\#1974](https://github.com/matrix-org/matrix-js-sdk/pull/1974)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Enable TypeScript declaration maps ([\#1966](https://github.com/matrix-org/matrix-js-sdk/pull/1966)). Contributed by [Alexendoo](https://github.com/Alexendoo).
## 🐛 Bug Fixes
* Fix `requestVerificationDM` with chronological `pendingEventOrdering` ([\#1943](https://github.com/matrix-org/matrix-js-sdk/pull/1943)). Contributed by [freaktechnik](https://github.com/freaktechnik).
Changes in [14.0.1](https://github.com/vector-im/element-desktop/releases/tag/v14.0.1) (2021-10-12)
===================================================================================================
## 🚨 BREAKING CHANGES
* Support for call upgrades. `setLocalVideoMuted()` and `setMicrophoneMuted()` are now `async` and return the new mute state ([\#1827](https://github.com/matrix-org/matrix-js-sdk/pull/1827)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
## ✨ Features
* Implement file versioning for tree spaces ([\#1952](https://github.com/matrix-org/matrix-js-sdk/pull/1952)).
* Allow answering calls without audio/video ([\#1950](https://github.com/matrix-org/matrix-js-sdk/pull/1950)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Add `bound` to `IThreepid` ([\#1941](https://github.com/matrix-org/matrix-js-sdk/pull/1941)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Add `trusted_locally` to `TrustInfo` ([\#1942](https://github.com/matrix-org/matrix-js-sdk/pull/1942)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
## 🐛 Bug Fixes
* Fix incorrect return value type in getJoinedRooms() ([\#1959](https://github.com/matrix-org/matrix-js-sdk/pull/1959)). Contributed by [psrpinto](https://github.com/psrpinto).
* Make sure to set `callLengthInterval` only once ([\#1958](https://github.com/matrix-org/matrix-js-sdk/pull/1958)). Fixes vector-im/element-web#19221 and vector-im/element-web#19221. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Fix event partitioning from non threading ready clients ([\#1948](https://github.com/matrix-org/matrix-js-sdk/pull/1948)).
* Ensure unencrypted fields get exposed by getEffectiveEvent() ([\#1938](https://github.com/matrix-org/matrix-js-sdk/pull/1938)). Fixes vector-im/element-web#19062 and vector-im/element-web#19062.
Changes in [14.0.0-rc.1](https://github.com/vector-im/element-desktop/releases/tag/v14.0.0-rc.1) (2021-10-04)
=============================================================================================================
## 🚨 BREAKING CHANGES
* Support for call upgrades. `setLocalVideoMuted()` and `setMicrophoneMuted()` are now `async` and return the new mute state ([\#1827](https://github.com/matrix-org/matrix-js-sdk/pull/1827)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
## ✨ Features
* Implement file versioning for tree spaces ([\#1952](https://github.com/matrix-org/matrix-js-sdk/pull/1952)).
* Allow answering calls without audio/video ([\#1950](https://github.com/matrix-org/matrix-js-sdk/pull/1950)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Add `bound` to `IThreepid` ([\#1941](https://github.com/matrix-org/matrix-js-sdk/pull/1941)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Add `trusted_locally` to `TrustInfo` ([\#1942](https://github.com/matrix-org/matrix-js-sdk/pull/1942)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
## 🐛 Bug Fixes
* Fix incorrect return value type in getJoinedRooms() ([\#1959](https://github.com/matrix-org/matrix-js-sdk/pull/1959)). Contributed by [psrpinto](https://github.com/psrpinto).
* Make sure to set `callLengthInterval` only once ([\#1958](https://github.com/matrix-org/matrix-js-sdk/pull/1958)). Fixes vector-im/element-web#19221 and vector-im/element-web#19221. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Fix event partitioning from non threading ready clients ([\#1948](https://github.com/matrix-org/matrix-js-sdk/pull/1948)).
* Ensure unencrypted fields get exposed by getEffectiveEvent() ([\#1938](https://github.com/matrix-org/matrix-js-sdk/pull/1938)). Fixes vector-im/element-web#19062 and vector-im/element-web#19062.
Changes in [13.0.0](https://github.com/vector-im/element-desktop/releases/tag/v13.0.0) (2021-09-27)
===================================================================================================
## ✨ Features
* Add `getHistoryVisibility()` and `getGuestAccess()` ([\#1940](https://github.com/matrix-org/matrix-js-sdk/pull/1940)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Add `getBuffer()` to `QRCodeData` ([\#1927](https://github.com/matrix-org/matrix-js-sdk/pull/1927)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Added `createDataChannel()` and `CallEvent.DataChannel` to `MatrixCall` for creating and listening for WebRTC datachannels. ([\#1929](https://github.com/matrix-org/matrix-js-sdk/pull/1929)). Contributed by [robertlong](https://github.com/robertlong).
* Add file locking to MSC3089 branches ([\#1909](https://github.com/matrix-org/matrix-js-sdk/pull/1909)).
* Add `hasBeenCancelled` to `VerificationBase` ([\#1915](https://github.com/matrix-org/matrix-js-sdk/pull/1915)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Add `ISasEvent` ([\#1908](https://github.com/matrix-org/matrix-js-sdk/pull/1908)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Count notifications in encrypted rooms client-side ([\#1872](https://github.com/matrix-org/matrix-js-sdk/pull/1872)). Fixes vector-im/element-web#15393 and vector-im/element-web#15393. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Exclude opt-in Element performance metrics from encryption ([\#1897](https://github.com/matrix-org/matrix-js-sdk/pull/1897)).
## 🐛 Bug Fixes
* Fix race on automatic backup restore ([\#1936](https://github.com/matrix-org/matrix-js-sdk/pull/1936)). Fixes vector-im/element-web#17781 and vector-im/element-web#17781.
Changes in [13.0.0-rc.1](https://github.com/vector-im/element-desktop/releases/tag/v13.0.0-rc.1) (2021-09-21)
=============================================================================================================
## ✨ Features
* Add `getHistoryVisibility()` and `getGuestAccess()` ([\#1940](https://github.com/matrix-org/matrix-js-sdk/pull/1940)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Add `getBuffer()` to `QRCodeData` ([\#1927](https://github.com/matrix-org/matrix-js-sdk/pull/1927)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Added `createDataChannel()` and `CallEvent.DataChannel` to `MatrixCall` for creating and listening for WebRTC datachannels. ([\#1929](https://github.com/matrix-org/matrix-js-sdk/pull/1929)). Contributed by [robertlong](https://github.com/robertlong).
* Add file locking to MSC3089 branches ([\#1909](https://github.com/matrix-org/matrix-js-sdk/pull/1909)).
* Add `hasBeenCancelled` to `VerificationBase` ([\#1915](https://github.com/matrix-org/matrix-js-sdk/pull/1915)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Add `ISasEvent` ([\#1908](https://github.com/matrix-org/matrix-js-sdk/pull/1908)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Count notifications in encrypted rooms client-side ([\#1872](https://github.com/matrix-org/matrix-js-sdk/pull/1872)). Fixes vector-im/element-web#15393 and vector-im/element-web#15393. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Exclude opt-in Element performance metrics from encryption ([\#1897](https://github.com/matrix-org/matrix-js-sdk/pull/1897)).
## 🐛 Bug Fixes
* Fix race on automatic backup restore ([\#1936](https://github.com/matrix-org/matrix-js-sdk/pull/1936)). Fixes vector-im/element-web#17781 and vector-im/element-web#17781.
Changes in [12.5.0](https://github.com/vector-im/element-desktop/releases/tag/v12.5.0) (2021-09-14)
===================================================================================================
## ✨ Features
* [Release] Exclude opt-in Element performance metrics from encryption ([\#1901](https://github.com/matrix-org/matrix-js-sdk/pull/1901)).
* Give `MatrixCall` the capability to emit `LengthChanged` events ([\#1873](https://github.com/matrix-org/matrix-js-sdk/pull/1873)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Improve browser example ([\#1875](https://github.com/matrix-org/matrix-js-sdk/pull/1875)). Contributed by [psrpinto](https://github.com/psrpinto).
* Give `CallFeed` the capability to emit on volume changes ([\#1865](https://github.com/matrix-org/matrix-js-sdk/pull/1865)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
## 🐛 Bug Fixes
* Fix verification request cancellation ([\#1871](https://github.com/matrix-org/matrix-js-sdk/pull/1871)).
Changes in [12.4.1](https://github.com/vector-im/element-desktop/releases/tag/v12.4.1) (2021-09-13)
===================================================================================================
## 🔒 SECURITY FIXES
* Fix a security issue with message key sharing. See https://matrix.org/blog/2021/09/13/vulnerability-disclosure-key-sharing
for details.
Changes in [12.4.0](https://github.com/vector-im/element-desktop/releases/tag/v12.4.0) (2021-08-31)
===================================================================================================
## 🦖 Deprecations
* Deprecate groups APIs. Groups are no longer supported, only Synapse has support. They are being replaced by Spaces which build off of Rooms and are far more flexible. ([\#1792](https://github.com/matrix-org/matrix-js-sdk/pull/1792)).
## ✨ Features
* Add method for including extra fields when uploading to a tree space ([\#1850](https://github.com/matrix-org/matrix-js-sdk/pull/1850)).
## 🐛 Bug Fixes
* Fix broken voice calls, no ringing and broken call notifications ([\#1858](https://github.com/matrix-org/matrix-js-sdk/pull/1858)). Fixes vector-im/element-web#18578 vector-im/element-web#18538 and vector-im/element-web#18578. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Revert "Fix glare related regressions" ([\#1857](https://github.com/matrix-org/matrix-js-sdk/pull/1857)).
* Fix glare related regressions ([\#1851](https://github.com/matrix-org/matrix-js-sdk/pull/1851)). Fixes vector-im/element-web#18538 and vector-im/element-web#18538. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Fix temporary call messages being handled without call ([\#1834](https://github.com/matrix-org/matrix-js-sdk/pull/1834)). Contributed by [Palid](https://github.com/Palid).
* Fix conditional on returning file tree spaces ([\#1841](https://github.com/matrix-org/matrix-js-sdk/pull/1841)).
Changes in [12.3.1](https://github.com/vector-im/element-desktop/releases/tag/v12.3.1) (2021-08-17)
===================================================================================================
## 🐛 Bug Fixes
* Fix multiple VoIP regressions ([\#1860](https://github.com/matrix-org/matrix-js-sdk/pull/1860)).
Changes in [12.3.0](https://github.com/vector-im/element-desktop/releases/tag/v12.3.0) (2021-08-16)
===================================================================================================
## ✨ Features
* Support for MSC3291: Muting in VoIP calls ([\#1812](https://github.com/matrix-org/matrix-js-sdk/pull/1812)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Support for screen-sharing using multi-stream VoIP (MSC3077) ([\#1685](https://github.com/matrix-org/matrix-js-sdk/pull/1685)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Handle DTMF support ([\#1813](https://github.com/matrix-org/matrix-js-sdk/pull/1813)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
## 🐛 Bug Fixes
* [Release] Fix glare related regressions ([\#1854](https://github.com/matrix-org/matrix-js-sdk/pull/1854)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Fix the types in shipped package ([\#1842](https://github.com/matrix-org/matrix-js-sdk/pull/1842)). Fixes vector-im/element-web#18503 and vector-im/element-web#18503.
* Fix error on turning off screensharing ([\#1833](https://github.com/matrix-org/matrix-js-sdk/pull/1833)). Fixes vector-im/element-web#18449. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Fix blank profile in join events ([\#1837](https://github.com/matrix-org/matrix-js-sdk/pull/1837)). Fixes vector-im/element-web#18321.
* fix TURN by fixing regression preventing multiple ICE candidates from sending. ([\#1838](https://github.com/matrix-org/matrix-js-sdk/pull/1838)).
* Send `user_hangup` reason if the opponent supports it ([\#1820](https://github.com/matrix-org/matrix-js-sdk/pull/1820)). Fixes vector-im/element-web#18219. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Apply hidden char check to rawDisplayName too ([\#1816](https://github.com/matrix-org/matrix-js-sdk/pull/1816)).
* Only clear bit 63 when we create the IV ([\#1819](https://github.com/matrix-org/matrix-js-sdk/pull/1819)).
Changes in [12.2.0](https://github.com/vector-im/element-desktop/releases/tag/v12.2.0) (2021-08-02)
===================================================================================================
## ✨ Features
* Improve calculateRoomName performances by using Intl.Collator
[\#1801](https://github.com/matrix-org/matrix-js-sdk/pull/1801)
* Switch callEventHandler from listening on `event` to `Room.timeline`
[\#1789](https://github.com/matrix-org/matrix-js-sdk/pull/1789)
* Expose MatrixEvent's internal clearEvent as a function
[\#1784](https://github.com/matrix-org/matrix-js-sdk/pull/1784)
## 🐛 Bug Fixes
* Clean up Event.clearEvent handling to fix a bug where malformed events with falsey content wouldn't be considered decrypted
[\#1807](https://github.com/matrix-org/matrix-js-sdk/pull/1807)
* Standardise spelling and casing of homeserver, identity server, and integration manager
[\#1782](https://github.com/matrix-org/matrix-js-sdk/pull/1782)
Changes in [12.1.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v12.1.0) (2021-07-19)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v12.1.0-rc.1...v12.1.0)
* No changes from rc.1
Changes in [12.1.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v12.1.0-rc.1) (2021-07-14)
============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v12.0.1...v12.1.0-rc.1)
* Add VS Code to gitignore
[\#1783](https://github.com/matrix-org/matrix-js-sdk/pull/1783)
* Make `Crypto::inRoomVerificationRequests` public
[\#1781](https://github.com/matrix-org/matrix-js-sdk/pull/1781)
* Call `setEventMetadata()` for filtered `timelineSet`s
[\#1765](https://github.com/matrix-org/matrix-js-sdk/pull/1765)
* Symmetric backup
[\#1775](https://github.com/matrix-org/matrix-js-sdk/pull/1775)
* Attempt to fix megolm key not being in SSSS
[\#1776](https://github.com/matrix-org/matrix-js-sdk/pull/1776)
* Convert SecretStorage to TypeScript
[\#1774](https://github.com/matrix-org/matrix-js-sdk/pull/1774)
* Strip hash from urls being previewed to de-duplicate
[\#1721](https://github.com/matrix-org/matrix-js-sdk/pull/1721)
* Do not generate a lockfile when running in CI
[\#1773](https://github.com/matrix-org/matrix-js-sdk/pull/1773)
* Tidy up secret requesting code
[\#1766](https://github.com/matrix-org/matrix-js-sdk/pull/1766)
* Convert Sync and SyncAccumulator to Typescript
[\#1763](https://github.com/matrix-org/matrix-js-sdk/pull/1763)
* Convert EventTimeline, EventTimelineSet and TimelineWindow to TS
[\#1762](https://github.com/matrix-org/matrix-js-sdk/pull/1762)
* Comply with new member-delimiter-style rule
[\#1764](https://github.com/matrix-org/matrix-js-sdk/pull/1764)
* Do not honor string power levels
[\#1754](https://github.com/matrix-org/matrix-js-sdk/pull/1754)
* Typescriptify some crypto stuffs
[\#1508](https://github.com/matrix-org/matrix-js-sdk/pull/1508)
* Make filterId read/write and optional
[\#1760](https://github.com/matrix-org/matrix-js-sdk/pull/1760)
Changes in [12.0.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v12.0.1) (2021-07-05)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v12.0.1-rc.1...v12.0.1)
* No changes from rc.1
Changes in [12.0.1-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v12.0.1-rc.1) (2021-06-29)
============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v12.0.0...v12.0.1-rc.1)
* Fix broken /messages filtering due to internal field changes in
FilterComponent
[\#1759](https://github.com/matrix-org/matrix-js-sdk/pull/1759)
* Convert crypto index to TS
[\#1749](https://github.com/matrix-org/matrix-js-sdk/pull/1749)
* Fix typescript return types for membership update events
[\#1739](https://github.com/matrix-org/matrix-js-sdk/pull/1739)
* Fix types of MatrixEvent sender & target
[\#1753](https://github.com/matrix-org/matrix-js-sdk/pull/1753)
* Add keysharing on invites to File Tree Spaces
[\#1744](https://github.com/matrix-org/matrix-js-sdk/pull/1744)
* Convert Room and RoomState to Typescript
[\#1746](https://github.com/matrix-org/matrix-js-sdk/pull/1746)
* Improve type of IContent msgtype
[\#1752](https://github.com/matrix-org/matrix-js-sdk/pull/1752)
* Add PR template
[\#1747](https://github.com/matrix-org/matrix-js-sdk/pull/1747)
* Add functions to assist in immutability of Event objects
[\#1738](https://github.com/matrix-org/matrix-js-sdk/pull/1738)
* Convert Event Context to TS
[\#1742](https://github.com/matrix-org/matrix-js-sdk/pull/1742)
* Bump lodash from 4.17.20 to 4.17.21
[\#1743](https://github.com/matrix-org/matrix-js-sdk/pull/1743)
* Add invite retries to file trees
[\#1740](https://github.com/matrix-org/matrix-js-sdk/pull/1740)
* Convert IndexedDBStore to TS
[\#1741](https://github.com/matrix-org/matrix-js-sdk/pull/1741)
* Convert additional files to typescript
[\#1736](https://github.com/matrix-org/matrix-js-sdk/pull/1736)
Changes in [12.0.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v12.0.0) (2021-06-21)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v12.0.0-rc.1...v12.0.0)
* No changes since rc.1
Changes in [12.0.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v12.0.0-rc.1) (2021-06-15)
============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v11.2.0...v12.0.0-rc.1)
* Rework how disambiguation is handled
[\#1730](https://github.com/matrix-org/matrix-js-sdk/pull/1730)
* Fix baseToString for n=0 edge case to match inverse stringToBase
[\#1735](https://github.com/matrix-org/matrix-js-sdk/pull/1735)
* Move various types from the react-sdk to the js-sdk
[\#1734](https://github.com/matrix-org/matrix-js-sdk/pull/1734)
* Unstable implementation of MSC3089: File Trees
[\#1732](https://github.com/matrix-org/matrix-js-sdk/pull/1732)
* Add MSC3230 event type to enum
[\#1729](https://github.com/matrix-org/matrix-js-sdk/pull/1729)
* Add separate reason code for transferred calls
[\#1731](https://github.com/matrix-org/matrix-js-sdk/pull/1731)
* Use sendonly for call hold
[\#1728](https://github.com/matrix-org/matrix-js-sdk/pull/1728)
* Stop breeding sync listeners
[\#1727](https://github.com/matrix-org/matrix-js-sdk/pull/1727)
* Fix semicolons in TS files
[\#1724](https://github.com/matrix-org/matrix-js-sdk/pull/1724)
* [BREAKING] Convert MatrixClient to TypeScript
[\#1718](https://github.com/matrix-org/matrix-js-sdk/pull/1718)
* Factor out backup management to a separate module
[\#1697](https://github.com/matrix-org/matrix-js-sdk/pull/1697)
* Ignore power_levels events with unknown state_key on room-state
initialization
[\#1723](https://github.com/matrix-org/matrix-js-sdk/pull/1723)
* Revert 1579 (Fix extra negotiate message in Firefox)
[\#1725](https://github.com/matrix-org/matrix-js-sdk/pull/1725)
Changes in [11.2.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v11.2.0) (2021-06-07)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v11.2.0-rc.1...v11.2.0)
* No changes since rc.1
Changes in [11.2.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v11.2.0-rc.1) (2021-06-01)
============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v11.1.0...v11.2.0-rc.1)
* Switch to stable endpoint/fields for MSC2858
[\#1720](https://github.com/matrix-org/matrix-js-sdk/pull/1720)
* Bump ws from 7.4.2 to 7.4.6
[\#1715](https://github.com/matrix-org/matrix-js-sdk/pull/1715)
* Make consistent call event type checks
[\#1712](https://github.com/matrix-org/matrix-js-sdk/pull/1712)
* Apply new Babel linting config
[\#1714](https://github.com/matrix-org/matrix-js-sdk/pull/1714)
* Bump browserslist from 4.16.1 to 4.16.6
[\#1709](https://github.com/matrix-org/matrix-js-sdk/pull/1709)
* Add user_busy call hangup reason
[\#1713](https://github.com/matrix-org/matrix-js-sdk/pull/1713)
* 👕 New linting rules
[\#1688](https://github.com/matrix-org/matrix-js-sdk/pull/1688)
* Emit relations created when target event added later
[\#1710](https://github.com/matrix-org/matrix-js-sdk/pull/1710)
* Bump libolm version and update package name.
[\#1705](https://github.com/matrix-org/matrix-js-sdk/pull/1705)
* Fix uploadContent not rejecting promise when http status code >= 400
[\#1703](https://github.com/matrix-org/matrix-js-sdk/pull/1703)
* Reduce noise in tests
[\#1702](https://github.com/matrix-org/matrix-js-sdk/pull/1702)
* Only log once if a Room lacks an m.room.create event
[\#1700](https://github.com/matrix-org/matrix-js-sdk/pull/1700)
* Cache normalized room name
[\#1701](https://github.com/matrix-org/matrix-js-sdk/pull/1701)
* Change call event handlers to adapt to undecrypted events
[\#1698](https://github.com/matrix-org/matrix-js-sdk/pull/1698)
Changes in [11.1.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v11.1.0) (2021-05-24)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v11.1.0-rc.1...v11.1.0)
* [Release] Bump libolm version and update package name
[\#1707](https://github.com/matrix-org/matrix-js-sdk/pull/1707)
* [Release] Change call event handlers to adapt to undecrypted events
[\#1699](https://github.com/matrix-org/matrix-js-sdk/pull/1699)
Changes in [11.1.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v11.1.0-rc.1) (2021-05-19)
============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v11.0.0...v11.1.0-rc.1)
* Fix regressed glare
[\#1690](https://github.com/matrix-org/matrix-js-sdk/pull/1690)
* Add m.reaction to EventType enum
[\#1692](https://github.com/matrix-org/matrix-js-sdk/pull/1692)
* Prioritise and reduce the amount of events decrypted on application startup
[\#1684](https://github.com/matrix-org/matrix-js-sdk/pull/1684)
* Decrypt relations before applying them to target event
[\#1696](https://github.com/matrix-org/matrix-js-sdk/pull/1696)
* Guard against duplicates in `Relations` model
Changes in [11.0.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v11.0.0) (2021-05-17)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v11.0.0-rc.1...v11.0.0)
* [Release] Fix regressed glare
[\#1695](https://github.com/matrix-org/matrix-js-sdk/pull/1695)
Changes in [11.0.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v11.0.0-rc.1) (2021-05-11)
============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v10.1.0...v11.0.0-rc.1)
BREAKING CHANGES
---
* `MatrixCall` and related APIs have been redesigned to support multiple streams
(see [\#1660](https://github.com/matrix-org/matrix-js-sdk/pull/1660) for more details)
All changes
---
* Switch from MSC1772 unstable prefixes to stable
[\#1679](https://github.com/matrix-org/matrix-js-sdk/pull/1679)
* Update the VoIP example to work with the new changes
[\#1680](https://github.com/matrix-org/matrix-js-sdk/pull/1680)
* Bump hosted-git-info from 2.8.8 to 2.8.9
[\#1687](https://github.com/matrix-org/matrix-js-sdk/pull/1687)
* Support for multiple streams (not MSC3077)
[\#1660](https://github.com/matrix-org/matrix-js-sdk/pull/1660)
* Tweak missing m.room.create errors to describe their source
[\#1683](https://github.com/matrix-org/matrix-js-sdk/pull/1683)
Changes in [10.1.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v10.1.0) (2021-05-10)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v10.1.0-rc.1...v10.1.0)
* No changes since rc.1
Changes in [10.1.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v10.1.0-rc.1) (2021-05-04)
============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v10.0.0...v10.1.0-rc.1)
* Revert "Raise logging dramatically to chase pending event errors"
[\#1681](https://github.com/matrix-org/matrix-js-sdk/pull/1681)
* Add test coverage collection script
[\#1677](https://github.com/matrix-org/matrix-js-sdk/pull/1677)
* Raise logging dramatically to chase pending event errors
[\#1678](https://github.com/matrix-org/matrix-js-sdk/pull/1678)
* Support MSC3086 asserted identity
[\#1674](https://github.com/matrix-org/matrix-js-sdk/pull/1674)
* Fix `/search` with no results field work again
[\#1670](https://github.com/matrix-org/matrix-js-sdk/pull/1670)
* Add room.getMembers method
[\#1672](https://github.com/matrix-org/matrix-js-sdk/pull/1672)
Changes in [10.0.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v10.0.0) (2021-04-26)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v10.0.0-rc.1...v10.0.0)
* No changes since rc.1
Changes in [10.0.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v10.0.0-rc.1) (2021-04-21)
============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.11.0...v10.0.0-rc.1)
BREAKING CHANGES
---
* The `RoomState.members` event is now only emitted when the room member's power level or the room's normal power level actually changes
All changes
---
* Restrict event emit for room members that had power levels changed
[\#1675](https://github.com/matrix-org/matrix-js-sdk/pull/1675)
* Fix sync with misconfigured push rules
[\#1669](https://github.com/matrix-org/matrix-js-sdk/pull/1669)
* Add missing await
[\#1665](https://github.com/matrix-org/matrix-js-sdk/pull/1665)
* Migrate to `eslint-plugin-matrix-org`
[\#1642](https://github.com/matrix-org/matrix-js-sdk/pull/1642)
* Add missing event type enum for key verification done
[\#1664](https://github.com/matrix-org/matrix-js-sdk/pull/1664)
* Fix timeline jumpiness by setting correct txnId
[\#1663](https://github.com/matrix-org/matrix-js-sdk/pull/1663)
* Fix calling addEventListener if it does not exist
[\#1661](https://github.com/matrix-org/matrix-js-sdk/pull/1661)
* Persist unsent messages for subsequent sessions
[\#1655](https://github.com/matrix-org/matrix-js-sdk/pull/1655)
Changes in [9.11.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.11.0) (2021-04-12)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.11.0-rc.1...v9.11.0)
* No changes since rc.1
Changes in [9.11.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.11.0-rc.1) (2021-04-07)
============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.10.0...v9.11.0-rc.1)
* Only try to cache private keys we know exist
[\#1657](https://github.com/matrix-org/matrix-js-sdk/pull/1657)
* Properly terminate screen-share calls if NoUserMedia
[\#1654](https://github.com/matrix-org/matrix-js-sdk/pull/1654)
* Attended transfer
[\#1652](https://github.com/matrix-org/matrix-js-sdk/pull/1652)
* Remove catch handlers in private key retrieval
[\#1653](https://github.com/matrix-org/matrix-js-sdk/pull/1653)
* Fixed the media fail error on caller's side
[\#1651](https://github.com/matrix-org/matrix-js-sdk/pull/1651)
* Add function to share megolm keys for historical messages, take 2
[\#1640](https://github.com/matrix-org/matrix-js-sdk/pull/1640)
* Cache cross-signing private keys if needed on bootstrap
[\#1649](https://github.com/matrix-org/matrix-js-sdk/pull/1649)
Changes in [9.10.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.10.0) (2021-03-29)
==================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.10.0-rc.1...v9.10.0)
* No changes since rc.1
Changes in [9.10.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.10.0-rc.1) (2021-03-25)
============================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.9.0...v9.10.0-rc.1)
* Don't send m.call.hangup if m.call.invite wasn't sent either
[\#1647](https://github.com/matrix-org/matrix-js-sdk/pull/1647)
* docs: registerGuest()
[\#1641](https://github.com/matrix-org/matrix-js-sdk/pull/1641)
* Download device keys in chunks of 250
[\#1639](https://github.com/matrix-org/matrix-js-sdk/pull/1639)
* More VoIP connectivity fixes
[\#1646](https://github.com/matrix-org/matrix-js-sdk/pull/1646)
* Make selectDesktopCapturerSource param optional
[\#1644](https://github.com/matrix-org/matrix-js-sdk/pull/1644)
* Expose APIs needed for reworked cross-signing login flow
[\#1632](https://github.com/matrix-org/matrix-js-sdk/pull/1632)
Changes in [9.9.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.9.0) (2021-03-15)
================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.9.0-rc.1...v9.9.0)
* No changes since rc.1
Changes in [9.9.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.9.0-rc.1) (2021-03-10)
==========================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.8.0...v9.9.0-rc.1)
* Remove detailed Olm session logging
[\#1638](https://github.com/matrix-org/matrix-js-sdk/pull/1638)
* Add space summary suggested only param
[\#1637](https://github.com/matrix-org/matrix-js-sdk/pull/1637)
* Check TURN servers periodically, and at start of calls
[\#1634](https://github.com/matrix-org/matrix-js-sdk/pull/1634)
* Support sending invite reasons
[\#1624](https://github.com/matrix-org/matrix-js-sdk/pull/1624)
* Bump elliptic from 6.5.3 to 6.5.4
[\#1636](https://github.com/matrix-org/matrix-js-sdk/pull/1636)
* Add a function to get a room's MXC URI
[\#1635](https://github.com/matrix-org/matrix-js-sdk/pull/1635)
* Stop streams if the call has ended
[\#1633](https://github.com/matrix-org/matrix-js-sdk/pull/1633)
* Remove export keyword from global.d.ts
[\#1631](https://github.com/matrix-org/matrix-js-sdk/pull/1631)
* Fix IndexedDB store creation example
[\#1445](https://github.com/matrix-org/matrix-js-sdk/pull/1445)
* An attempt to cleanup how constraints are handled in calls
[\#1613](https://github.com/matrix-org/matrix-js-sdk/pull/1613)
* Extract display name patterns to constants
[\#1628](https://github.com/matrix-org/matrix-js-sdk/pull/1628)
* Bump pug-code-gen from 2.0.2 to 2.0.3
[\#1630](https://github.com/matrix-org/matrix-js-sdk/pull/1630)
* Avoid deadlocks when ensuring Olm sessions for devices
[\#1627](https://github.com/matrix-org/matrix-js-sdk/pull/1627)
* Filter out edits from other senders in history
[\#1626](https://github.com/matrix-org/matrix-js-sdk/pull/1626)
* Fix ContentHelpers export
[\#1618](https://github.com/matrix-org/matrix-js-sdk/pull/1618)
* Add logging to in progress Olm sessions
[\#1621](https://github.com/matrix-org/matrix-js-sdk/pull/1621)
* Don't ignore ICE candidates received before offer/answer
[\#1623](https://github.com/matrix-org/matrix-js-sdk/pull/1623)
* Better handling of send failures on VoIP events
[\#1622](https://github.com/matrix-org/matrix-js-sdk/pull/1622)
* Log when turn creds expire
[\#1620](https://github.com/matrix-org/matrix-js-sdk/pull/1620)
* Initial Spaces [MSC1772] support
[\#1563](https://github.com/matrix-org/matrix-js-sdk/pull/1563)
* Add logging to crypto store transactions
[\#1617](https://github.com/matrix-org/matrix-js-sdk/pull/1617)
* Room helper for getting type and checking if it is a space room
[\#1610](https://github.com/matrix-org/matrix-js-sdk/pull/1610)
Changes in [9.8.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.8.0) (2021-03-01)
================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.8.0-rc.1...v9.8.0)
* No changes since rc.1
Changes in [9.8.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.8.0-rc.1) (2021-02-24)
==========================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.7.0...v9.8.0-rc.1)
* Optimise prefixed logger
[\#1615](https://github.com/matrix-org/matrix-js-sdk/pull/1615)
* Add debug logs to encryption prep, take 3
[\#1614](https://github.com/matrix-org/matrix-js-sdk/pull/1614)
* Add functions for upper & lowercase random strings
[\#1612](https://github.com/matrix-org/matrix-js-sdk/pull/1612)
* Room helpers for invite permissions and join rules
[\#1609](https://github.com/matrix-org/matrix-js-sdk/pull/1609)
* Fixed wording in "Adding video track with id" log
[\#1606](https://github.com/matrix-org/matrix-js-sdk/pull/1606)
* Add more debug logs to encryption prep
[\#1605](https://github.com/matrix-org/matrix-js-sdk/pull/1605)
* Add option to set ice candidate pool size
[\#1604](https://github.com/matrix-org/matrix-js-sdk/pull/1604)
* Cancel call if no source was selected
[\#1601](https://github.com/matrix-org/matrix-js-sdk/pull/1601)
Changes in [9.7.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.7.0) (2021-02-16)
================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.7.0-rc.1...v9.7.0)
* No changes since rc.1
Changes in [9.7.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.7.0-rc.1) (2021-02-10)
==========================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.6.0...v9.7.0-rc.1)
* Handle undefined peerconn
[\#1600](https://github.com/matrix-org/matrix-js-sdk/pull/1600)
* ReEmitter: Don't throw if no error handler is attached
[\#1599](https://github.com/matrix-org/matrix-js-sdk/pull/1599)
* Convert ReEmitter to TS
[\#1598](https://github.com/matrix-org/matrix-js-sdk/pull/1598)
* Fix typo in main readme
[\#1597](https://github.com/matrix-org/matrix-js-sdk/pull/1597)
* Remove rogue plus character
[\#1596](https://github.com/matrix-org/matrix-js-sdk/pull/1596)
* Fix call ID NaN
[\#1595](https://github.com/matrix-org/matrix-js-sdk/pull/1595)
* Fix Electron type merging
[\#1594](https://github.com/matrix-org/matrix-js-sdk/pull/1594)
* Fix browser screen share
[\#1593](https://github.com/matrix-org/matrix-js-sdk/pull/1593)
* Fix desktop Matrix screen sharing
[\#1570](https://github.com/matrix-org/matrix-js-sdk/pull/1570)
* Guard against confused server retry times
[\#1591](https://github.com/matrix-org/matrix-js-sdk/pull/1591)
* Decrypt redaction events
[\#1589](https://github.com/matrix-org/matrix-js-sdk/pull/1589)
* Fix edge cases with peeking where a room is re-peeked
[\#1587](https://github.com/matrix-org/matrix-js-sdk/pull/1587)
Changes in [9.6.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.6.0) (2021-02-03)
================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.6.0-rc.1...v9.6.0)
* [Release] Fix edge cases with peeking where a room is re-peeked
[\#1588](https://github.com/matrix-org/matrix-js-sdk/pull/1588)
Changes in [9.6.0-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.6.0-rc.1) (2021-01-29)
==========================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.5.1...v9.6.0-rc.1)
* Add support for getting call stats
[\#1584](https://github.com/matrix-org/matrix-js-sdk/pull/1584)
* Fix compatibility with v0 calls
[\#1583](https://github.com/matrix-org/matrix-js-sdk/pull/1583)
* Upgrade deps 2021-01
[\#1582](https://github.com/matrix-org/matrix-js-sdk/pull/1582)
* Log the call ID when logging that we've received VoIP events
[\#1581](https://github.com/matrix-org/matrix-js-sdk/pull/1581)
* Fix extra negotiate message in Firefox
[\#1579](https://github.com/matrix-org/matrix-js-sdk/pull/1579)
* Add debug logs to encryption prep
[\#1580](https://github.com/matrix-org/matrix-js-sdk/pull/1580)
* Expose getPresence endpoint
[\#1578](https://github.com/matrix-org/matrix-js-sdk/pull/1578)
* Queue keys for backup even if backup isn't enabled yet
[\#1577](https://github.com/matrix-org/matrix-js-sdk/pull/1577)
* Stop retrying TURN access when forbidden
[\#1576](https://github.com/matrix-org/matrix-js-sdk/pull/1576)
* Add DTMF sending support
[\#1573](https://github.com/matrix-org/matrix-js-sdk/pull/1573)
Changes in [9.5.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.5.1) (2021-01-26)
================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.5.0...v9.5.1)
* [Release] Fix compatibility with v0 calls
[\#1585](https://github.com/matrix-org/matrix-js-sdk/pull/1585)
Changes in [9.5.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v9.5.0) (2021-01-18)
================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v9.5.0-rc.1...v9.5.0)
+215
View File
@@ -0,0 +1,215 @@
Contributing code to matrix-js-sdk
==================================
Everyone is welcome to contribute code to matrix-js-sdk, provided that they are
willing to license their contributions under the same license as the project
itself. We follow a simple 'inbound=outbound' model for contributions: the act
of submitting an 'inbound' contribution means that the contributor agrees to
license the code under the same terms as the project's overall 'outbound'
license - in this case, Apache Software License v2 (see
[LICENSE](LICENSE)).
How to contribute
-----------------
The preferred and easiest way to contribute changes to the project is to fork
it on github, and then create a pull request to ask us to pull your changes
into our repo (https://help.github.com/articles/using-pull-requests/)
We use GitHub's pull request workflow to review the contribution, and either
ask you to make any refinements needed or merge it and make them ourselves.
Things that should go into your PR description:
* A changelog entry in the `Notes` section (see below)
* References to any bugs fixed by the change (in GitHub's `Fixes` notation)
* Describe the why and what is changing in the PR description so it's easy for
onlookers and reviewers to onboard and context switch.
* Include both **before** and **after** screenshots to easily compare and discuss
what's changing.
* Include a step-by-step testing strategy so that a reviewer can check out the
code locally and easily get to the point of testing your change.
* Add comments to the diff for the reviewer that might help them to understand
why the change is necessary or how they might better understand and review it.
Things that should *not* go into your PR description:
* Any information on how the code works or why you chose to do it the way
you did. If this isn't obvious from your code, you haven't written enough
comments.
We rely on information in pull request to populate the information that goes
into the changelogs our users see, both for the JS SDK itself and also for some
projects based on it. This is picked up from both labels on the pull request and
the `Notes:` annotation in the description. By default, the PR title will be
used for the changelog entry, but you can specify more options, as follows.
To add a longer, more detailed description of the change for the changelog:
*Fix llama herding bug*
```
Notes: Fix a bug (https://github.com/matrix-org/notaproject/issues/123) where the 'Herd' button would not herd more than 8 Llamas if the moon was in the waxing gibbous phase
```
For some PRs, it's not useful to have an entry in the user-facing changelog (this is
the default for PRs labelled with `T-Task`):
*Remove outdated comment from `Ungulates.ts`*
```
Notes: none
```
Sometimes, you're fixing a bug in a downstream project, in which case you want
an entry in that project's changelog. You can do that too:
*Fix another herding bug*
```
Notes: Fix a bug where the `herd()` function would only work on Tuesdays
element-web notes: Fix a bug where the 'Herd' button only worked on Tuesdays
```
This example is for Element Web. You can specify:
* matrix-react-sdk
* element-web
* element-desktop
If your PR introduces a breaking change, use the `Notes` section in the same
way, additionally adding the `X-Breaking-Change` label (see below). There's no need
to specify in the notes that it's a breaking change - this will be added
automatically based on the label - but remember to tell the developer how to
migrate:
*Remove legacy class*
```
Notes: Remove legacy `Camelopard` class. `Giraffe` should be used instead.
```
Other metadata can be added using labels.
* `X-Breaking-Change`: A breaking change - adding this label will mean the change causes a *major* version bump.
* `T-Enhancement`: A new feature - adding this label will mean the change causes a *minor* version bump.
* `T-Defect`: A bug fix (in either code or docs).
* `T-Task`: No user-facing changes, eg. code comments, CI fixes, refactors or tests. Won't have a changelog entry unless you specify one.
If you don't have permission to add labels, your PR reviewer(s) can work with you
to add them: ask in the PR description or comments.
We use continuous integration, and all pull requests get automatically tested:
if your change breaks the build, then the PR will show that there are failed
checks, so please check back after a few minutes.
Tests
-----
If your PR is a feature (ie. if it's being labelled with the 'T-Enhancement'
label) then we require that the PR also includes tests. These need to test that
your feature works as expected and ideally test edge cases too. For the js-sdk
itself, your tests should generally be unit tests. matrix-react-sdk also uses
these guidelines, so for that your tests can be unit tests using
react-test-utils, snapshot tests or screenshot tests.
We don't require tests for bug fixes (T-Defect) but strongly encourage regression
tests for the bug itself wherever possible.
In the future we may formalise this more with a minimum test coverage
percentage for the diff.
Code style
----------
The js-sdk aims to target TypeScript/ES6. All new files should be written in
TypeScript and existing files should use ES6 principles where possible.
Members should not be exported as a default export in general - it causes problems
with the architecture of the SDK (index file becomes less clear) and could
introduce naming problems (as default exports get aliased upon import). In
general, avoid using `export default`.
The remaining code-style for matrix-js-sdk is not formally documented, but
contributors are encouraged to read the
[code style document for matrix-react-sdk](https://github.com/matrix-org/matrix-react-sdk/blob/master/code_style.md)
and follow the principles set out there.
Please ensure your changes match the cosmetic style of the existing project,
and ***never*** mix cosmetic and functional changes in the same commit, as it
makes it horribly hard to review otherwise.
Attribution
-----------
Everyone who contributes anything to Matrix is welcome to be listed in the
AUTHORS.rst file for the project in question. Please feel free to include a
change to AUTHORS.rst in your pull request to list yourself and a short
description of the area(s) you've worked on. Also, we sometimes have swag to
give away to contributors - if you feel that Matrix-branded apparel is missing
from your life, please mail us your shipping address to matrix at matrix.org
and we'll try to fix it :)
Sign off
--------
In order to have a concrete record that your contribution is intentional
and you agree to license it under the same terms as the project's license, we've
adopted the same lightweight approach that the Linux Kernel
(https://www.kernel.org/doc/Documentation/SubmittingPatches), Docker
(https://github.com/docker/docker/blob/master/CONTRIBUTING.md), and many other
projects use: the DCO (Developer Certificate of Origin:
http://developercertificate.org/). This is a simple declaration that you wrote
the contribution or otherwise have the right to contribute it to Matrix:
```
Developer Certificate of Origin
Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
660 York Street, Suite 102,
San Francisco, CA 94110 USA
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
```
If you agree to this for your contribution, then all that's needed is to
include the line in your commit or pull request comment:
```
Signed-off-by: Your Name <your@email.example.org>
```
We accept contributions under a legally identifiable name, such as your name on
government documentation or common-law names (names claimed by legitimate usage
or repute). Unfortunately, we cannot accept anonymous contributions at this
time.
Git allows you to add this signoff automatically when using the `-s` flag to
`git commit`, which uses the name and email set in your `user.name` and
`user.email` git configs.
If you forgot to sign off your commits before making your pull request and are
on Git 2.17+ you can mass signoff using rebase:
```
git rebase --signoff origin/develop
```
-131
View File
@@ -1,131 +0,0 @@
Contributing code to matrix-js-sdk
==================================
Everyone is welcome to contribute code to matrix-js-sdk, provided that they are
willing to license their contributions under the same license as the project
itself. We follow a simple 'inbound=outbound' model for contributions: the act
of submitting an 'inbound' contribution means that the contributor agrees to
license the code under the same terms as the project's overall 'outbound'
license - in this case, Apache Software License v2 (see `<LICENSE>`_).
How to contribute
~~~~~~~~~~~~~~~~~
The preferred and easiest way to contribute changes to the project is to fork
it on github, and then create a pull request to ask us to pull your changes
into our repo (https://help.github.com/articles/using-pull-requests/)
**The single biggest thing you need to know is: please base your changes on
the develop branch - /not/ master.**
We use the master branch to track the most recent release, so that folks who
blindly clone the repo and automatically check out master get something that
works. Develop is the unstable branch where all the development actually
happens: the workflow is that contributors should fork the develop branch to
make a 'feature' branch for a particular contribution, and then make a pull
request to merge this back into the matrix.org 'official' develop branch. We
use GitHub's pull request workflow to review the contribution, and either ask
you to make any refinements needed or merge it and make them ourselves. The
changes will then land on master when we next do a release.
We use continuous integration, and all pull requests get automatically tested:
if your change breaks the build, then the PR will show that there are failed
checks, so please check back after a few minutes.
Code style
~~~~~~~~~~
The js-sdk aims to target TypeScript/ES6. All new files should be written in
TypeScript and existing files should use ES6 principles where possible.
Members should not be exported as a default export in general - it causes problems
with the architecture of the SDK (index file becomes less clear) and could
introduce naming problems (as default exports get aliased upon import). In
general, avoid using `export default`.
The remaining code-style for matrix-js-sdk is not formally documented, but
contributors are encouraged to read the code style document for matrix-react-sdk
(`<https://github.com/matrix-org/matrix-react-sdk/blob/master/code_style.md>`_)
and follow the principles set out there.
Please ensure your changes match the cosmetic style of the existing project,
and **never** mix cosmetic and functional changes in the same commit, as it
makes it horribly hard to review otherwise.
Attribution
~~~~~~~~~~~
Everyone who contributes anything to Matrix is welcome to be listed in the
AUTHORS.rst file for the project in question. Please feel free to include a
change to AUTHORS.rst in your pull request to list yourself and a short
description of the area(s) you've worked on. Also, we sometimes have swag to
give away to contributors - if you feel that Matrix-branded apparel is missing
from your life, please mail us your shipping address to matrix at matrix.org
and we'll try to fix it :)
Sign off
~~~~~~~~
In order to have a concrete record that your contribution is intentional
and you agree to license it under the same terms as the project's license, we've
adopted the same lightweight approach that the Linux Kernel
(https://www.kernel.org/doc/Documentation/SubmittingPatches), Docker
(https://github.com/docker/docker/blob/master/CONTRIBUTING.md), and many other
projects use: the DCO (Developer Certificate of Origin:
http://developercertificate.org/). This is a simple declaration that you wrote
the contribution or otherwise have the right to contribute it to Matrix::
Developer Certificate of Origin
Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
660 York Street, Suite 102,
San Francisco, CA 94110 USA
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
If you agree to this for your contribution, then all that's needed is to
include the line in your commit or pull request comment::
Signed-off-by: Your Name <your@email.example.org>
We accept contributions under a legally identifiable name, such as your name on
government documentation or common-law names (names claimed by legitimate usage
or repute). Unfortunately, we cannot accept anonymous contributions at this
time.
Git allows you to add this signoff automatically when using the ``-s`` flag to
``git commit``, which uses the name and email set in your ``user.name`` and
``user.email`` git configs.
If you forgot to sign off your commits before making your pull request and are
on Git 2.17+ you can mass signoff using rebase::
git rebase --signoff origin/develop
+1 -1
View File
@@ -307,7 +307,7 @@ 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.
It is also necessry to call ``matrixClient.initCrypto()`` after creating a new
It is also necessary to call ``matrixClient.initCrypto()`` after creating a new
``MatrixClient`` (but **before** calling ``matrixClient.startClient()``) to
initialise the crypto layer.
+1 -1
View File
@@ -1,6 +1,6 @@
console.log("Loading browser sdk");
var client = matrixcs.createClient("http://matrix.org");
var client = matrixcs.createClient("https://matrix.org");
client.publicRooms(function (err, data) {
if (err) {
console.error("err %s", JSON.stringify(err));
+3 -1
View File
@@ -1,6 +1,8 @@
<html>
<html lang="en">
<head>
<title>Test</title>
<meta charset="utf-8"/>
<link rel="icon" href="data:,">
<script src="lib/matrix.js"></script>
<script src="browserTest.js"></script>
</head>
+18 -4
View File
@@ -31,6 +31,23 @@ function addListeners(call) {
call.hangup();
disableButtons(false, true, true);
});
call.on("feeds_changed", function(feeds) {
const localFeed = feeds.find((feed) => feed.isLocal());
const remoteFeed = feeds.find((feed) => !feed.isLocal());
const remoteElement = document.getElementById("remote");
const localElement = document.getElementById("local");
if (remoteFeed) {
remoteElement.srcObject = remoteFeed.stream;
remoteElement.play();
}
if (localFeed) {
localElement.muted = true;
localElement.srcObject = localFeed.stream;
localElement.play();
}
});
}
window.onload = function() {
@@ -62,10 +79,7 @@ function syncComplete() {
);
console.log("Call => %s", call);
addListeners(call);
call.placeVideoCall(
document.getElementById("remote"),
document.getElementById("local")
);
call.placeVideoCall();
document.getElementById("result").innerHTML = "<p>Placed call.</p>";
disableButtons(true, true, false);
};
+21 -13
View File
@@ -1,26 +1,34 @@
<html>
<head>
<title>VoIP Test</title>
<script src="lib/matrix.js"></script>
<script src="browserTest.js"></script>
<title>VoIP Test</title>
<script src="lib/matrix.js"></script>
<script src="browserTest.js"></script>
</head>
<body>
You can place and receive calls with this example. Make sure to edit the
You can place and receive calls with this example. Make sure to edit the
constants in <code>browserTest.js</code> first.
<div id="config"></div>
<div id="result"></div>
<button id="call">Place Call</button>
<button id="answer">Answer Call</button>
<button id="hangup">Hangup Call</button>
<div id="videoBackground">
<div id="videoContainer">
<video id="remote"></video>
</div>
</div>
<div id="videoBackground">
<div id="videoContainer">
<video id="local"></video>
</div>
<div id="videoBackground" class="video-background">
<video class="video-element" id="local"></video>
<video class="video-element" id="remote"></video>
</div>
</body>
</html>
<style>
.video-background {
height: 500px;
margin: 10px;
}
.video-element {
height: 100%;
}
</style>
+41 -23
View File
@@ -1,6 +1,6 @@
{
"name": "matrix-js-sdk",
"version": "9.5.0",
"version": "15.3.0",
"description": "Matrix Client-Server SDK for Javascript",
"scripts": {
"prepublishOnly": "yarn build",
@@ -9,16 +9,18 @@
"clean": "rimraf lib dist",
"build": "yarn build:dev && yarn build:compile-browser && yarn build:minify-browser",
"build:dev": "yarn clean && git rev-parse HEAD > git-revision.txt && yarn build:compile && yarn build:types",
"build:types": "tsc --emitDeclarationOnly",
"build:types": "tsc -p tsconfig-build.json --emitDeclarationOnly",
"build:compile": "babel -d lib --verbose --extensions \".ts,.js\" src",
"build:compile-browser": "mkdirp dist && browserify -d src/browser-index.js -p [ tsify -p ./tsconfig.json ] -t [ babelify --sourceMaps=inline --presets [ @babel/preset-env @babel/preset-typescript ] ] | exorcist dist/browser-matrix.js.map > dist/browser-matrix.js",
"build:compile-browser": "mkdirp dist && browserify -d src/browser-index.js -p [ tsify -p ./tsconfig-build.json ] -t [ babelify --sourceMaps=inline --presets [ @babel/preset-env @babel/preset-typescript ] ] | exorcist dist/browser-matrix.js.map > dist/browser-matrix.js",
"build:minify-browser": "terser dist/browser-matrix.js --compress --mangle --source-map --output dist/browser-matrix.min.js",
"gendoc": "jsdoc -c jsdoc.json -P package.json",
"lint": "yarn lint:types && yarn lint:js",
"lint:js": "eslint --max-warnings 73 src spec",
"lint:js": "eslint --max-warnings 4 src spec",
"lint:js-fix": "eslint --fix src spec",
"lint:types": "tsc --noEmit",
"test": "jest spec/ --coverage --testEnvironment node",
"test:watch": "jest spec/ --coverage --testEnvironment node --watch"
"test": "jest",
"test:watch": "jest --watch",
"coverage": "yarn test --coverage"
},
"repository": {
"type": "git",
@@ -53,48 +55,64 @@
"browser-request": "^0.3.3",
"bs58": "^4.0.1",
"content-type": "^1.0.4",
"eslint-plugin-import": "^2.25.2",
"loglevel": "^1.7.1",
"qs": "^6.9.4",
"p-retry": "^4.5.0",
"qs": "^6.9.6",
"request": "^2.88.2",
"unhomoglyph": "^1.0.6"
},
"devDependencies": {
"@babel/cli": "^7.12.8",
"@babel/core": "^7.12.9",
"@babel/cli": "^7.12.10",
"@babel/core": "^7.12.10",
"@babel/eslint-parser": "^7.12.10",
"@babel/eslint-plugin": "^7.12.10",
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@babel/plugin-proposal-numeric-separator": "^7.12.7",
"@babel/plugin-proposal-object-rest-spread": "^7.12.1",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-runtime": "^7.12.1",
"@babel/preset-env": "^7.12.7",
"@babel/plugin-transform-runtime": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@babel/preset-typescript": "^7.12.7",
"@babel/register": "^7.12.1",
"@types/jest": "^26.0.15",
"@babel/register": "^7.12.10",
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz",
"@types/bs58": "^4.0.1",
"@types/jest": "^26.0.20",
"@types/node": "12",
"@types/request": "^2.48.5",
"babel-eslint": "^10.1.0",
"@typescript-eslint/eslint-plugin": "^5.6.0",
"@typescript-eslint/parser": "^5.6.0",
"allchange": "^1.0.6",
"babel-jest": "^26.6.3",
"babelify": "^10.0.0",
"better-docs": "^2.3.2",
"better-docs": "^2.4.0-beta.9",
"browserify": "^17.0.0",
"docdash": "^1.2.0",
"eslint": "7.14.0",
"eslint-config-matrix-org": "^0.1.2",
"eslint-plugin-babel": "^5.3.1",
"eslint": "7.18.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-matrix-org": "github:matrix-org/eslint-plugin-matrix-org#48ec1e6af2cfb8310b9a6e23edf2dc7a26ddd580",
"exorcist": "^1.0.1",
"fake-indexeddb": "^3.1.2",
"jest": "^26.6.3",
"jest-localstorage-mock": "^2.4.3",
"jest-localstorage-mock": "^2.4.6",
"jsdoc": "^3.6.6",
"matrix-mock-request": "^1.2.3",
"olm": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz",
"rimraf": "^3.0.2",
"terser": "^5.5.0",
"terser": "^5.5.1",
"tsify": "^5.0.2",
"typescript": "^4.1.2"
"typescript": "^4.5.3"
},
"jest": {
"testEnvironment": "node"
"testEnvironment": "node",
"testMatch": [
"<rootDir>/spec/**/*.spec.{js,ts}"
],
"collectCoverageFrom": [
"<rootDir>/src/**/*.{js,ts}"
],
"coverageReporters": [
"text"
]
},
"typings": "./lib/index.d.ts"
}
+7 -17
View File
@@ -100,12 +100,7 @@ fi
# global cache here to ensure we get the right thing.
yarn cache clean
# Ensure all dependencies are updated
yarn install --ignore-scripts
if [ -z "$skip_changelog" ]; then
# update_changelog doesn't have a --version flag
update_changelog -h > /dev/null || (echo "github-changelog-generator is required: please install it"; exit)
fi
yarn install --ignore-scripts --pure-lockfile
# Login and publish continues to use `npm`, as it seems to have more clearly
# defined options and semantics than `yarn` for writing to the registry.
@@ -133,14 +128,6 @@ if [ $prerelease -eq 1 ]; then
echo Making a PRE-RELEASE
fi
if [ -z "$skip_changelog" ]; then
if ! command -v update_changelog >/dev/null 2>&1; then
echo "release.sh requires github-changelog-generator. Try:" >&2
echo " pip install git+https://github.com/matrix-org/github-changelog-generator.git" >&2
exit 1
fi
fi
# we might already be on the release branch, in which case, yay
# If we're on any branch starting with 'release', we don't create
# a separate release branch (this allows us to use the same
@@ -156,7 +143,7 @@ fi
if [ -z "$skip_changelog" ]; then
echo "Generating changelog"
update_changelog -f "$changelog_file" "$release"
yarn run allchange "$release"
read -p "Edit $changelog_file manually, or press enter to continue " REPLY
if [ -n "$(git ls-files --modified $changelog_file)" ]; then
@@ -204,7 +191,10 @@ git commit package.json $pkglock -m "$tag"
# figure out if we should be signing this release
signing_id=
if [ -f release_config.yaml ]; then
signing_id=`cat release_config.yaml | python -c "import yaml; import sys; print yaml.load(sys.stdin)['signing_id']"`
result=`cat release_config.yaml | python -c "import yaml; import sys; print yaml.load(sys.stdin)['signing_id']" 2> /dev/null || true`
if [ "$?" -eq 0 ]; then
signing_id=$result
fi
fi
@@ -225,7 +215,7 @@ if [ $dodist -eq 0 ]; then
pushd "$builddir"
git clone "$projdir" .
git checkout "$rel_branch"
yarn install
yarn install --pure-lockfile
# We haven't tagged yet, so tell the dist script what version
# it's building
DIST_VERSION="$tag" yarn dist
+13 -15
View File
@@ -20,12 +20,13 @@ limitations under the License.
import './olm-loader';
import MockHttpBackend from 'matrix-mock-request';
import {LocalStorageCryptoStore} from '../src/crypto/store/localStorage-crypto-store';
import {logger} from '../src/logger';
import {WebStorageSessionStore} from "../src/store/session/webstorage";
import {syncPromise} from "./test-utils";
import {createClient} from "../src/matrix";
import {MockStorageApi} from "./MockStorageApi";
import { LocalStorageCryptoStore } from '../src/crypto/store/localStorage-crypto-store';
import { logger } from '../src/logger';
import { WebStorageSessionStore } from "../src/store/session/webstorage";
import { syncPromise } from "./test-utils";
import { createClient } from "../src/matrix";
import { MockStorageApi } from "./MockStorageApi";
/**
* Wrapper for a MockStorageApi, MockHttpBackend and MatrixClient
@@ -69,7 +70,7 @@ export function TestClient(
this.deviceKeys = null;
this.oneTimeKeys = {};
this._callEventHandler = {
this.callEventHandler = {
calls: new Map(),
};
}
@@ -129,11 +130,10 @@ TestClient.prototype.expectDeviceKeyUpload = function() {
expect(Object.keys(self.oneTimeKeys).length).toEqual(0);
self.deviceKeys = content.device_keys;
return {one_time_key_counts: {signed_curve25519: 0}};
return { one_time_key_counts: { signed_curve25519: 0 } };
});
};
/**
* If one-time keys have already been uploaded, return them. Otherwise,
* set up an expectation that the keys will be uploaded, and wait for
@@ -151,9 +151,9 @@ TestClient.prototype.awaitOneTimeKeyUpload = function() {
.respond(200, (path, content) => {
expect(content.device_keys).toBe(undefined);
expect(content.one_time_keys).toBe(undefined);
return {one_time_key_counts: {
return { one_time_key_counts: {
signed_curve25519: Object.keys(this.oneTimeKeys).length,
}};
} };
});
this.httpBackend.when("POST", "/keys/upload")
@@ -164,9 +164,9 @@ TestClient.prototype.awaitOneTimeKeyUpload = function() {
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: {
return { one_time_key_counts: {
signed_curve25519: Object.keys(this.oneTimeKeys).length,
}};
} };
});
// this can take ages
@@ -197,7 +197,6 @@ TestClient.prototype.expectKeyQuery = function(response) {
});
};
/**
* get the uploaded curve25519 device key
*
@@ -208,7 +207,6 @@ TestClient.prototype.getDeviceKey = function() {
return this.deviceKeys.keys[keyId];
};
/**
* get the uploaded ed25519 device key
*
+5 -4
View File
@@ -17,10 +17,11 @@ limitations under the License.
// load XmlHttpRequest mock
import "./setupTests";
import "../../dist/browser-matrix"; // uses browser-matrix instead of the src
import {MockStorageApi} from "../MockStorageApi";
import {WebStorageSessionStore} from "../../src/store/session/webstorage";
import MockHttpBackend from "matrix-mock-request";
import {LocalStorageCryptoStore} from "../../src/crypto/store/localStorage-crypto-store";
import { MockStorageApi } from "../MockStorageApi";
import { WebStorageSessionStore } from "../../src/store/session/webstorage";
import { LocalStorageCryptoStore } from "../../src/crypto/store/localStorage-crypto-store";
import * as utils from "../test-utils";
const USER_ID = "@user:test.server";
@@ -58,7 +59,7 @@ describe("Browserify Test", function() {
}
beforeEach(async () => {
({client, httpBackend} = await createTestClient());
({ client, httpBackend } = await createTestClient());
await client.startClient();
});
+15 -18
View File
@@ -16,9 +16,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {TestClient} from '../TestClient';
import { TestClient } from '../TestClient';
import * as testUtils from '../test-utils';
import {logger} from '../../src/logger';
import { logger } from '../../src/logger';
const ROOM_ID = "!room:id";
@@ -67,7 +67,6 @@ function getSyncResponse(roomMembers) {
return syncResponse;
}
describe("DeviceList management:", function() {
if (!global.Olm) {
logger.warn('not running deviceList tests: Olm not present');
@@ -98,7 +97,7 @@ describe("DeviceList management:", function() {
});
it("Alice shouldn't do a second /query for non-e2e-capable devices", function() {
aliceTestClient.expectKeyQuery({device_keys: {'@alice:localhost': {}}});
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} } });
return aliceTestClient.start().then(function() {
const syncResponse = getSyncResponse(['@bob:xyz']);
aliceTestClient.httpBackend.when('GET', '/sync').respond(200, syncResponse);
@@ -137,11 +136,10 @@ describe("DeviceList management:", function() {
});
});
it("We should not get confused by out-of-order device query responses",
() => {
// https://github.com/vector-im/element-web/issues/3126
aliceTestClient.expectKeyQuery({device_keys: {'@alice:localhost': {}}});
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} } });
return aliceTestClient.start().then(() => {
aliceTestClient.httpBackend.when('GET', '/sync').respond(
200, getSyncResponse(['@bob:xyz', '@chris:abc']));
@@ -160,14 +158,14 @@ describe("DeviceList management:", function() {
);
aliceTestClient.httpBackend.when('PUT', '/send/').respond(
200, {event_id: '$event1'});
200, { event_id: '$event1' });
return Promise.all([
aliceTestClient.client.sendTextMessage(ROOM_ID, 'test'),
aliceTestClient.httpBackend.flush('/keys/query', 1).then(
() => aliceTestClient.httpBackend.flush('/send/', 1),
),
aliceTestClient.client._crypto._deviceList.saveIfDirty(),
aliceTestClient.client.crypto.deviceList.saveIfDirty(),
]);
}).then(() => {
aliceTestClient.cryptoStore.getEndToEndDeviceData(null, (data) => {
@@ -199,12 +197,12 @@ describe("DeviceList management:", function() {
},
token: '3',
}).respond(200, {
device_keys: {'@chris:abc': {}},
device_keys: { '@chris:abc': {} },
});
return aliceTestClient.httpBackend.flush('/keys/query', 1);
}).then((flushed) => {
expect(flushed).toEqual(0);
return aliceTestClient.client._crypto._deviceList.saveIfDirty();
return aliceTestClient.client.crypto.deviceList.saveIfDirty();
}).then(() => {
aliceTestClient.cryptoStore.getEndToEndDeviceData(null, (data) => {
const bobStat = data.trackingStatus['@bob:xyz'];
@@ -228,7 +226,7 @@ describe("DeviceList management:", function() {
},
token: '2',
}).respond(200, {
device_keys: {'@bob:xyz': {}},
device_keys: { '@bob:xyz': {} },
});
return aliceTestClient.httpBackend.flush('/keys/query', 1);
}).then((flushed) => {
@@ -237,7 +235,7 @@ describe("DeviceList management:", function() {
// wait for the client to stop processing the response
return aliceTestClient.client.downloadKeys(['@bob:xyz']);
}).then(() => {
return aliceTestClient.client._crypto._deviceList.saveIfDirty();
return aliceTestClient.client.crypto.deviceList.saveIfDirty();
}).then(() => {
aliceTestClient.cryptoStore.getEndToEndDeviceData(null, (data) => {
const bobStat = data.trackingStatus['@bob:xyz'];
@@ -258,7 +256,7 @@ describe("DeviceList management:", function() {
// wait for the client to stop processing the response
return aliceTestClient.client.downloadKeys(['@chris:abc']);
}).then(() => {
return aliceTestClient.client._crypto._deviceList.saveIfDirty();
return aliceTestClient.client.crypto.deviceList.saveIfDirty();
}).then(() => {
aliceTestClient.cryptoStore.getEndToEndDeviceData(null, (data) => {
const bobStat = data.trackingStatus['@bob:xyz'];
@@ -288,7 +286,7 @@ describe("DeviceList management:", function() {
},
);
await aliceTestClient.httpBackend.flush('/keys/query', 1);
await aliceTestClient.client._crypto._deviceList.saveIfDirty();
await aliceTestClient.client.crypto.deviceList.saveIfDirty();
aliceTestClient.cryptoStore.getEndToEndDeviceData(null, (data) => {
const bobStat = data.trackingStatus['@bob:xyz'];
@@ -323,9 +321,8 @@ describe("DeviceList management:", function() {
},
);
await aliceTestClient.flushSync();
await aliceTestClient.client._crypto._deviceList.saveIfDirty();
await aliceTestClient.client.crypto.deviceList.saveIfDirty();
aliceTestClient.cryptoStore.getEndToEndDeviceData(null, (data) => {
const bobStat = data.trackingStatus['@bob:xyz'];
@@ -361,7 +358,7 @@ describe("DeviceList management:", function() {
);
await aliceTestClient.flushSync();
await aliceTestClient.client._crypto._deviceList.saveIfDirty();
await aliceTestClient.client.crypto.deviceList.saveIfDirty();
aliceTestClient.cryptoStore.getEndToEndDeviceData(null, (data) => {
const bobStat = data.trackingStatus['@bob:xyz'];
@@ -382,7 +379,7 @@ describe("DeviceList management:", function() {
anotherTestClient.httpBackend.when('GET', '/sync').respond(
200, getSyncResponse([]));
await anotherTestClient.flushSync();
await anotherTestClient.client._crypto._deviceList.saveIfDirty();
await anotherTestClient.client.crypto.deviceList.saveIfDirty();
anotherTestClient.cryptoStore.getEndToEndDeviceData(null, (data) => {
const bobStat = data.trackingStatus['@bob:xyz'];
+20 -25
View File
@@ -28,11 +28,10 @@ limitations under the License.
// load olm before the sdk if possible
import '../olm-loader';
import {logger} from '../../src/logger';
import { logger } from '../../src/logger';
import * as testUtils from "../test-utils";
import * as utils from "../../src/utils";
import {TestClient} from "../TestClient";
import {CRYPTO_ENABLED} from "../../src/client";
import { TestClient } from "../TestClient";
import { CRYPTO_ENABLED } from "../../src/client";
let aliTestClient;
const roomId = "!room:localhost";
@@ -76,7 +75,7 @@ function expectAliQueryKeys() {
);
const result = {};
result[bobUserId] = bobKeys;
return {device_keys: result};
return { device_keys: result };
});
return aliTestClient.httpBackend.flush("/keys/query", 1);
}
@@ -104,7 +103,7 @@ function expectBobQueryKeys() {
);
const result = {};
result[aliUserId] = aliKeys;
return {device_keys: result};
return { device_keys: result };
});
return bobTestClient.httpBackend.flush("/keys/query", 1);
}
@@ -133,7 +132,7 @@ function expectAliClaimKeys() {
result[bobUserId] = {};
result[bobUserId][bobDeviceId] = {};
result[bobUserId][bobDeviceId][keyId] = keys[keyId];
return {one_time_keys: result};
return { one_time_keys: result };
});
}).then(() => {
// it can take a while to process the key query, so give it some extra
@@ -145,7 +144,6 @@ function expectAliClaimKeys() {
});
}
function aliDownloadsKeys() {
// can't query keys before bob has uploaded them
expect(bobTestClient.getSigningKey()).toBeTruthy();
@@ -161,7 +159,7 @@ function aliDownloadsKeys() {
// check that the localStorage is updated as we expect (not sure this is
// an integration test, but meh)
return Promise.all([p1, p2]).then(() => {
return aliTestClient.client._crypto._deviceList.saveIfDirty();
return aliTestClient.client.crypto.deviceList.saveIfDirty();
}).then(() => {
aliTestClient.cryptoStore.getEndToEndDeviceData(null, (data) => {
const devices = data.devices[bobUserId];
@@ -244,7 +242,7 @@ function bobSendsReplyMessage() {
function expectAliSendMessageRequest() {
return expectSendMessageRequest(aliTestClient.httpBackend).then(function(content) {
aliMessages.push(content);
expect(utils.keys(content.ciphertext)).toEqual([bobTestClient.getDeviceKey()]);
expect(Object.keys(content.ciphertext)).toEqual([bobTestClient.getDeviceKey()]);
const ciphertext = content.ciphertext[bobTestClient.getDeviceKey()];
expect(ciphertext).toBeTruthy();
return ciphertext;
@@ -261,7 +259,7 @@ function expectBobSendMessageRequest() {
bobMessages.push(content);
const aliKeyId = "curve25519:" + aliDeviceId;
const aliDeviceCurve25519Key = aliTestClient.deviceKeys.keys[aliKeyId];
expect(utils.keys(content.ciphertext)).toEqual([aliDeviceCurve25519Key]);
expect(Object.keys(content.ciphertext)).toEqual([aliDeviceCurve25519Key]);
const ciphertext = content.ciphertext[aliDeviceCurve25519Key];
expect(ciphertext).toBeTruthy();
return ciphertext;
@@ -270,7 +268,7 @@ function expectBobSendMessageRequest() {
function sendMessage(client) {
return client.sendMessage(
roomId, {msgtype: "m.text", body: "Hello, World"},
roomId, { msgtype: "m.text", body: "Hello, World" },
);
}
@@ -358,7 +356,6 @@ function recvMessage(httpBackend, client, sender, message) {
});
}
/**
* Send an initial sync response to the client (which just includes the member
* list for our test room).
@@ -396,7 +393,6 @@ function firstSync(testClient) {
return testClient.flushSync();
}
describe("MatrixClient crypto", function() {
if (!CRYPTO_ENABLED) {
return;
@@ -478,7 +474,7 @@ describe("MatrixClient crypto", function() {
).respond(200, function(path, content) {
const result = {};
result[bobUserId] = bobKeys;
return {device_keys: result};
return { device_keys: result };
});
return Promise.all([
@@ -520,7 +516,7 @@ describe("MatrixClient crypto", function() {
).respond(200, function(path, content) {
const result = {};
result[bobUserId] = bobKeys;
return {device_keys: result};
return { device_keys: result };
});
return Promise.all([
@@ -534,7 +530,6 @@ describe("MatrixClient crypto", function() {
});
});
it("Bob starts his client and uploads device keys and one-time keys", function() {
return Promise.resolve()
.then(() => bobTestClient.start())
@@ -546,7 +541,7 @@ describe("MatrixClient crypto", function() {
});
it("Ali sends a message", function() {
aliTestClient.expectKeyQuery({device_keys: {[aliUserId]: {}}});
aliTestClient.expectKeyQuery({ device_keys: { [aliUserId]: {} } });
return Promise.resolve()
.then(() => aliTestClient.start())
.then(() => bobTestClient.start())
@@ -556,7 +551,7 @@ describe("MatrixClient crypto", function() {
});
it("Bob receives a message", function() {
aliTestClient.expectKeyQuery({device_keys: {[aliUserId]: {}}});
aliTestClient.expectKeyQuery({ device_keys: { [aliUserId]: {} } });
return Promise.resolve()
.then(() => aliTestClient.start())
.then(() => bobTestClient.start())
@@ -567,7 +562,7 @@ describe("MatrixClient crypto", function() {
});
it("Bob receives a message with a bogus sender", function() {
aliTestClient.expectKeyQuery({device_keys: {[aliUserId]: {}}});
aliTestClient.expectKeyQuery({ device_keys: { [aliUserId]: {} } });
return Promise.resolve()
.then(() => aliTestClient.start())
.then(() => bobTestClient.start())
@@ -621,7 +616,7 @@ describe("MatrixClient crypto", function() {
});
it("Ali blocks Bob's device", function() {
aliTestClient.expectKeyQuery({device_keys: {[aliUserId]: {}}});
aliTestClient.expectKeyQuery({ device_keys: { [aliUserId]: {} } });
return Promise.resolve()
.then(() => aliTestClient.start())
.then(() => bobTestClient.start())
@@ -641,7 +636,7 @@ describe("MatrixClient crypto", function() {
});
it("Bob receives two pre-key messages", function() {
aliTestClient.expectKeyQuery({device_keys: {[aliUserId]: {}}});
aliTestClient.expectKeyQuery({ device_keys: { [aliUserId]: {} } });
return Promise.resolve()
.then(() => aliTestClient.start())
.then(() => bobTestClient.start())
@@ -654,8 +649,8 @@ describe("MatrixClient crypto", function() {
});
it("Bob replies to the message", function() {
aliTestClient.expectKeyQuery({device_keys: {[aliUserId]: {}}});
bobTestClient.expectKeyQuery({device_keys: {[bobUserId]: {}}});
aliTestClient.expectKeyQuery({ device_keys: { [aliUserId]: {} } });
bobTestClient.expectKeyQuery({ device_keys: { [bobUserId]: {} } });
return Promise.resolve()
.then(() => aliTestClient.start())
.then(() => bobTestClient.start())
@@ -673,7 +668,7 @@ describe("MatrixClient crypto", function() {
it("Ali does a key query when encryption is enabled", function() {
// enabling encryption in the room should make alice download devices
// for both members.
aliTestClient.expectKeyQuery({device_keys: {[aliUserId]: {}}});
aliTestClient.expectKeyQuery({ device_keys: { [aliUserId]: {} } });
return Promise.resolve()
.then(() => aliTestClient.start())
.then(() => firstSync(aliTestClient))
@@ -1,5 +1,5 @@
import * as utils from "../test-utils";
import {TestClient} from "../TestClient";
import { TestClient } from "../TestClient";
describe("MatrixClient events", function() {
let client;
@@ -1,7 +1,7 @@
import * as utils from "../test-utils";
import {EventTimeline} from "../../src/matrix";
import {logger} from "../../src/logger";
import {TestClient} from "../TestClient";
import { EventTimeline } from "../../src/matrix";
import { logger } from "../../src/logger";
import { TestClient } from "../TestClient";
const userId = "@alice:localhost";
const userName = "Alice";
@@ -127,7 +127,7 @@ describe("getEventTimeline support", function() {
"DEVICE",
accessToken,
undefined,
{timelineSupport: true},
{ timelineSupport: true },
);
client = testClient.client;
httpBackend = testClient.httpBackend;
@@ -141,7 +141,6 @@ describe("getEventTimeline support", function() {
});
});
it("scrollback should be able to scroll back to before a gappy /sync",
function() {
// need a client with timelineSupport disabled to make this work
@@ -218,7 +217,7 @@ describe("MatrixClient event timelines", function() {
"DEVICE",
accessToken,
undefined,
{timelineSupport: true},
{ timelineSupport: true },
);
client = testClient.client;
httpBackend = testClient.httpBackend;
@@ -516,7 +515,7 @@ describe("MatrixClient event timelines", function() {
client.getEventTimeline(timelineSet, EVENTS[0].event_id,
).then(function(tl0) {
tl = tl0;
return client.paginateEventTimeline(tl, {backwards: true});
return client.paginateEventTimeline(tl, { backwards: true });
}).then(function(success) {
expect(success).toBeTruthy();
expect(tl.getEvents().length).toEqual(3);
@@ -532,7 +531,6 @@ describe("MatrixClient event timelines", function() {
]);
});
it("should allow you to paginate forwards", function() {
const room = client.getRoom(roomId);
const timelineSet = room.getTimelineSets()[0];
@@ -569,7 +567,7 @@ describe("MatrixClient event timelines", function() {
).then(function(tl0) {
tl = tl0;
return client.paginateEventTimeline(
tl, {backwards: false, limit: 20});
tl, { backwards: false, limit: 20 });
}).then(function(success) {
expect(success).toBeTruthy();
expect(tl.getEvents().length).toEqual(3);
@@ -591,7 +589,7 @@ describe("MatrixClient event timelines", function() {
const event = utils.mkMessage({
room: roomId, user: userId, msg: "a body",
});
event.unsigned = {transaction_id: TXN_ID};
event.unsigned = { transaction_id: TXN_ID };
beforeEach(function() {
// set up handlers for both the message send, and the
@@ -680,7 +678,6 @@ describe("MatrixClient event timelines", function() {
});
});
it("should handle gappy syncs after redactions", function() {
// https://github.com/vector-im/vector-web/issues/1389
+8 -9
View File
@@ -1,7 +1,7 @@
import * as utils from "../test-utils";
import {CRYPTO_ENABLED} from "../../src/client";
import {Filter, MemoryStore, Room} from "../../src/matrix";
import {TestClient} from "../TestClient";
import { CRYPTO_ENABLED } from "../../src/client";
import { Filter, MemoryStore, Room } from "../../src/matrix";
import { TestClient } from "../TestClient";
describe("MatrixClient", function() {
let client = null;
@@ -285,7 +285,6 @@ describe("MatrixClient", function() {
});
});
describe("downloadKeys", function() {
if (!CRYPTO_ENABLED) {
return;
@@ -337,7 +336,7 @@ describe("MatrixClient", function() {
var b = JSON.parse(JSON.stringify(o));
delete(b.signatures);
delete(b.unsigned);
return client._crypto._olmDevice.sign(anotherjson.stringify(b));
return client.crypto.olmDevice.sign(anotherjson.stringify(b));
};
logger.log("Ed25519: " + ed25519key);
@@ -346,10 +345,10 @@ describe("MatrixClient", function() {
*/
httpBackend.when("POST", "/keys/query").check(function(req) {
expect(req.data).toEqual({device_keys: {
expect(req.data).toEqual({ device_keys: {
'boris': [],
'chaz': [],
}});
} });
}).respond(200, {
device_keys: {
boris: borisKeys,
@@ -379,12 +378,12 @@ describe("MatrixClient", function() {
});
describe("deleteDevice", function() {
const auth = {a: 1};
const auth = { a: 1 };
it("should pass through an auth dict", function() {
httpBackend.when(
"DELETE", "/_matrix/client/r0/devices/my_device",
).check(function(req) {
expect(req.data).toEqual({auth: auth});
expect(req.data).toEqual({ auth: auth });
}).respond(200);
const prom = client.deleteDevice("my_device", auth);
+6 -5
View File
@@ -1,9 +1,10 @@
import * as utils from "../test-utils";
import HttpBackend from "matrix-mock-request";
import {MatrixClient} from "../../src/matrix";
import {MatrixScheduler} from "../../src/scheduler";
import {MemoryStore} from "../../src/store/memory";
import {MatrixError} from "../../src/http-api";
import * as utils from "../test-utils";
import { MatrixClient } from "../../src/matrix";
import { MatrixScheduler } from "../../src/scheduler";
import { MemoryStore } from "../../src/store/memory";
import { MatrixError } from "../../src/http-api";
describe("MatrixClient opts", function() {
const baseUrl = "http://localhost.or.something";
@@ -1,16 +1,16 @@
import {EventStatus} from "../../src/matrix";
import {MatrixScheduler} from "../../src/scheduler";
import {Room} from "../../src/models/room";
import {TestClient} from "../TestClient";
import { EventStatus } from "../../src/matrix";
import { MatrixScheduler } from "../../src/scheduler";
import { Room } from "../../src/models/room";
import { TestClient } from "../TestClient";
describe("MatrixClient retrying", function() {
let client = null;
let httpBackend = null;
let client: TestClient = null;
let httpBackend: TestClient["httpBackend"] = null;
let scheduler;
const userId = "@alice:localhost";
const accessToken = "aseukfgwef";
const roomId = "!room:here";
let room;
let room: Room;
beforeEach(function() {
scheduler = new MatrixScheduler();
@@ -19,11 +19,11 @@ describe("MatrixClient retrying", function() {
"DEVICE",
accessToken,
undefined,
{scheduler},
{ scheduler },
);
httpBackend = testClient.httpBackend;
client = testClient.client;
room = new Room(roomId);
room = new Room(roomId, client, userId);
client.store.storeRoom(room);
});
@@ -50,17 +50,23 @@ describe("MatrixClient retrying", function() {
it("should mark events as EventStatus.CANCELLED when cancelled", function() {
// send a couple of events; the second will be queued
const p1 = client.sendMessage(roomId, "m1").then(function(ev) {
const p1 = client.sendMessage(roomId, {
"msgtype": "m.text",
"body": "m1",
}).then(function() {
// we expect the first message to fail
throw new Error('Message 1 unexpectedly sent successfully');
}, (e) => {
}, () => {
// this is expected
});
// XXX: it turns out that the promise returned by this message
// never gets resolved.
// https://github.com/matrix-org/matrix-js-sdk/issues/496
client.sendMessage(roomId, "m2");
client.sendMessage(roomId, {
"msgtype": "m.text",
"body": "m2",
});
// both events should be in the timeline at this point
const tl = room.getLiveTimeline().getEvents();
@@ -72,7 +78,7 @@ describe("MatrixClient retrying", function() {
expect(ev2.status).toEqual(EventStatus.SENDING);
// the first message should get sent, and the second should get queued
httpBackend.when("PUT", "/send/m.room.message/").check(function(rq) {
httpBackend.when("PUT", "/send/m.room.message/").check(function() {
// ev2 should now have been queued
expect(ev2.status).toEqual(EventStatus.QUEUED);
@@ -88,7 +94,7 @@ describe("MatrixClient retrying", function() {
}).respond(400); // fail the first message
// wait for the localecho of ev1 to be updated
const p3 = new Promise((resolve, reject) => {
const p3 = new Promise<void>((resolve, reject) => {
room.on("Room.localEchoUpdated", (ev0) => {
if (ev0 === ev1) {
resolve();
+11 -12
View File
@@ -1,7 +1,6 @@
import * as utils from "../test-utils";
import {EventStatus} from "../../src/models/event";
import {TestClient} from "../TestClient";
import { EventStatus } from "../../src/models/event";
import { TestClient } from "../TestClient";
describe("MatrixClient room timelines", function() {
let client = null;
@@ -104,7 +103,7 @@ describe("MatrixClient room timelines", function() {
"DEVICE",
accessToken,
undefined,
{timelineSupport: true},
{ timelineSupport: true },
);
httpBackend = testClient.httpBackend;
client = testClient.client;
@@ -166,7 +165,7 @@ describe("MatrixClient room timelines", function() {
body: "I am a fish", user: userId, room: roomId,
});
ev.event_id = eventId;
ev.unsigned = {transaction_id: "txn1"};
ev.unsigned = { transaction_id: "txn1" };
setNextSyncData([ev]);
client.on("sync", function(state) {
@@ -198,7 +197,7 @@ describe("MatrixClient room timelines", function() {
body: "I am a fish", user: userId, room: roomId,
});
ev.event_id = eventId;
ev.unsigned = {transaction_id: "txn1"};
ev.unsigned = { transaction_id: "txn1" };
setNextSyncData([ev]);
client.on("sync", function(state) {
@@ -396,8 +395,8 @@ describe("MatrixClient room timelines", function() {
describe("new events", function() {
it("should be added to the right place in the timeline", function() {
const eventData = [
utils.mkMessage({user: userId, room: roomId}),
utils.mkMessage({user: userId, room: roomId}),
utils.mkMessage({ user: userId, room: roomId }),
utils.mkMessage({ user: userId, room: roomId }),
];
setNextSyncData(eventData);
@@ -434,11 +433,11 @@ describe("MatrixClient room timelines", function() {
it("should set the right event.sender values", function() {
const eventData = [
utils.mkMessage({user: userId, room: roomId}),
utils.mkMessage({ user: userId, room: roomId }),
utils.mkMembership({
user: userId, room: roomId, mship: "join", name: "New Name",
}),
utils.mkMessage({user: userId, room: roomId}),
utils.mkMessage({ user: userId, room: roomId }),
];
eventData[1].__prev_event = USER_MEMBERSHIP_EVENT;
setNextSyncData(eventData);
@@ -546,7 +545,7 @@ describe("MatrixClient room timelines", function() {
describe("gappy sync", function() {
it("should copy the last known state to the new timeline", function() {
const eventData = [
utils.mkMessage({user: userId, room: roomId}),
utils.mkMessage({ user: userId, room: roomId }),
];
setNextSyncData(eventData);
NEXT_SYNC_DATA.rooms.join[roomId].timeline.limited = true;
@@ -579,7 +578,7 @@ describe("MatrixClient room timelines", function() {
it("should emit a 'Room.timelineReset' event", function() {
const eventData = [
utils.mkMessage({user: userId, room: roomId}),
utils.mkMessage({ user: userId, room: roomId }),
];
setNextSyncData(eventData);
NEXT_SYNC_DATA.rooms.join[roomId].timeline.limited = true;
+5 -6
View File
@@ -1,7 +1,7 @@
import {MatrixEvent} from "../../src/models/event";
import {EventTimeline} from "../../src/models/event-timeline";
import { MatrixEvent } from "../../src/models/event";
import { EventTimeline } from "../../src/models/event-timeline";
import * as utils from "../test-utils";
import {TestClient} from "../TestClient";
import { TestClient } from "../TestClient";
describe("MatrixClient syncing", function() {
let client = null;
@@ -122,7 +122,6 @@ describe("MatrixClient syncing", function() {
resolveInvitesToProfiles: true,
});
return Promise.all([
httpBackend.flushAllExpected(),
awaitSyncEvent(),
@@ -677,8 +676,8 @@ describe("MatrixClient syncing", function() {
it("should create and use an appropriate filter", function() {
httpBackend.when("POST", "/filter").check(function(req) {
expect(req.data).toEqual({
room: { timeline: {limit: 1},
include_leave: true }});
room: { timeline: { limit: 1 },
include_leave: true } });
}).respond(200, { filter_id: "another_id" });
const prom = new Promise((resolve) => {
+83 -20
View File
@@ -16,10 +16,10 @@ limitations under the License.
*/
import anotherjson from "another-json";
import * as utils from "../../src/utils";
import * as testUtils from "../test-utils";
import {TestClient} from "../TestClient";
import {logger} from "../../src/logger";
import { TestClient } from "../TestClient";
import { logger } from "../../src/logger";
const ROOM_ID = "!room:id";
@@ -32,7 +32,7 @@ const ROOM_ID = "!room:id";
*/
function createOlmSession(olmAccount, recipientTestClient) {
return recipientTestClient.awaitOneTimeKeyUpload().then((keys) => {
const otkId = utils.keys(keys)[0];
const otkId = Object.keys(keys)[0];
const otk = keys[otkId];
const session = new global.Olm.Session();
@@ -197,7 +197,6 @@ function getSyncResponse(roomMembers) {
return syncResponse;
}
describe("megolm", function() {
if (!global.Olm) {
logger.warn('not running megolm tests: Olm not present');
@@ -257,7 +256,7 @@ describe("megolm", function() {
const testOneTimeKeys = JSON.parse(testOlmAccount.one_time_keys());
testOlmAccount.mark_keys_as_published();
const keyId = utils.keys(testOneTimeKeys.curve25519)[0];
const keyId = Object.keys(testOneTimeKeys.curve25519)[0];
const oneTimeKey = testOneTimeKeys.curve25519[keyId];
const keyResult = {
'key': oneTimeKey,
@@ -269,7 +268,7 @@ describe("megolm", function() {
'ed25519:DEVICE_ID': sig,
};
const claimResponse = {one_time_keys: {}};
const claimResponse = { one_time_keys: {} };
claimResponse.one_time_keys[userId] = {
'DEVICE_ID': {},
};
@@ -484,8 +483,9 @@ describe("megolm", function() {
return aliceTestClient.flushSync().then(() => {
return aliceTestClient.flushSync();
});
}).then(function() {
}).then(async function() {
const room = aliceTestClient.client.getRoom(ROOM_ID);
await room.decryptCriticalEvents();
const event = room.getLiveTimeline().getEvents()[0];
expect(event.getContent().body).toEqual('42');
});
@@ -494,7 +494,7 @@ describe("megolm", function() {
it('Alice sends a megolm message', function() {
let p2pSession;
aliceTestClient.expectKeyQuery({device_keys: {'@alice:localhost': {}}});
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} } });
return aliceTestClient.start().then(() => {
// establish an olm session with alice
return createOlmSession(testOlmAccount, aliceTestClient);
@@ -577,7 +577,7 @@ describe("megolm", function() {
});
it("We shouldn't attempt to send to blocked devices", function() {
aliceTestClient.expectKeyQuery({device_keys: {'@alice:localhost': {}}});
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} } });
return aliceTestClient.start().then(() => {
// establish an olm session with alice
return createOlmSession(testOlmAccount, aliceTestClient);
@@ -634,7 +634,7 @@ describe("megolm", function() {
let p2pSession;
let megolmSessionId;
aliceTestClient.expectKeyQuery({device_keys: {'@alice:localhost': {}}});
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} } });
return aliceTestClient.start().then(() => {
// establish an olm session with alice
return createOlmSession(testOlmAccount, aliceTestClient);
@@ -841,13 +841,12 @@ describe("megolm", function() {
});
});
it('Alice should wait for device list to complete when sending a megolm message',
function() {
let downloadPromise;
let sendPromise;
aliceTestClient.expectKeyQuery({device_keys: {'@alice:localhost': {}}});
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} } });
return aliceTestClient.start().then(() => {
// establish an olm session with alice
return createOlmSession(testOlmAccount, aliceTestClient);
@@ -887,11 +886,10 @@ describe("megolm", function() {
});
});
it("Alice exports megolm keys and imports them to a new device", function() {
let messageEncrypted;
aliceTestClient.expectKeyQuery({device_keys: {'@alice:localhost': {}}});
aliceTestClient.expectKeyQuery({ device_keys: { '@alice:localhost': {} } });
return aliceTestClient.start().then(() => {
// establish an olm session with alice
return createOlmSession(testOlmAccount, aliceTestClient);
@@ -933,8 +931,9 @@ describe("megolm", function() {
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse);
return aliceTestClient.flushSync();
}).then(function() {
}).then(async function() {
const room = aliceTestClient.client.getRoom(ROOM_ID);
await room.decryptCriticalEvents();
const event = room.getLiveTimeline().getEvents()[0];
expect(event.getContent().body).toEqual('42');
@@ -1000,7 +999,7 @@ describe("megolm", function() {
...rawEvent,
room: ROOM_ID,
});
return event.attemptDecryption(testClient.client._crypto, true).then(() => {
return event.attemptDecryption(testClient.client.crypto, true).then(() => {
expect(event.isKeySourceUntrusted()).toBeTruthy();
});
}).then(() => {
@@ -1014,17 +1013,81 @@ describe("megolm", function() {
},
event: true,
});
event._senderCurve25519Key = testSenderKey;
return testClient.client._crypto._onRoomKeyEvent(event);
event.senderCurve25519Key = testSenderKey;
return testClient.client.crypto.onRoomKeyEvent(event);
}).then(() => {
const event = testUtils.mkEvent({
event: true,
...rawEvent,
room: ROOM_ID,
});
return event.attemptDecryption(testClient.client._crypto, true).then(() => {
return event.attemptDecryption(testClient.client.crypto, true).then(() => {
expect(event.isKeySourceUntrusted()).toBeFalsy();
});
});
});
it("Alice can decrypt a message with falsey content", function() {
return aliceTestClient.start().then(() => {
return createOlmSession(testOlmAccount, aliceTestClient);
}).then((p2pSession) => {
const groupSession = new Olm.OutboundGroupSession();
groupSession.create();
// make the room_key event
const roomKeyEncrypted = encryptGroupSessionKey({
senderKey: testSenderKey,
recipient: aliceTestClient,
p2pSession: p2pSession,
groupSession: groupSession,
room_id: ROOM_ID,
});
const plaintext = {
type: "m.room.message",
content: undefined,
room_id: ROOM_ID,
};
const messageEncrypted = {
event_id: 'test_megolm_event',
content: {
algorithm: "m.megolm.v1.aes-sha2",
ciphertext: groupSession.encrypt(JSON.stringify(plaintext)),
device_id: "testDevice",
sender_key: testSenderKey,
session_id: groupSession.session_id(),
},
type: "m.room.encrypted",
};
// Alice gets both the events in a single sync
const syncResponse = {
next_batch: 1,
to_device: {
events: [roomKeyEncrypted],
},
rooms: {
join: {},
},
};
syncResponse.rooms.join[ROOM_ID] = {
timeline: {
events: [messageEncrypted],
},
};
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse);
return aliceTestClient.flushSync();
}).then(function() {
const room = aliceTestClient.client.getRoom(ROOM_ID);
const event = room.getLiveTimeline().getEvents()[0];
expect(event.isEncrypted()).toBe(true);
return testUtils.awaitDecryption(event);
}).then((event) => {
expect(event.getRoomId()).toEqual(ROOM_ID);
expect(event.getContent()).toEqual({});
expect(event.getClearContent()).toBeUndefined();
});
});
});
+2 -2
View File
@@ -15,12 +15,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {logger} from '../src/logger';
import { logger } from '../src/logger';
import * as utils from "../src/utils";
// try to load the olm library.
try {
global.Olm = require('olm');
global.Olm = require('@matrix-org/olm');
logger.log('loaded libolm');
} catch (e) {
logger.warn("unable to run crypto tests: libolm not available");
+22 -22
View File
@@ -1,8 +1,8 @@
// load olm before the sdk if possible
import './olm-loader';
import {logger} from '../src/logger';
import {MatrixEvent} from "../src/models/event";
import { logger } from '../src/logger';
import { MatrixEvent } from "../src/models/event";
/**
* Return a promise that is resolved when the client next emits a
@@ -51,7 +51,7 @@ export function mock(constr, name) {
result.toString = function() {
return "mock" + (name ? " of " + name : "");
};
for (const key in constr.prototype) { // eslint-disable-line guard-for-in
for (const key of Object.getOwnPropertyNames(constr.prototype)) { // eslint-disable-line guard-for-in
try {
if (constr.prototype[key] instanceof Function) {
result[key] = jest.fn();
@@ -91,7 +91,7 @@ export function mkEvent(opts) {
event.state_key = opts.skey;
} else if (["m.room.name", "m.room.topic", "m.room.create", "m.room.join_rules",
"m.room.power_levels", "m.room.topic",
"com.example.state"].indexOf(opts.type) !== -1) {
"com.example.state"].includes(opts.type)) {
event.state_key = "";
}
return opts.event ? new MatrixEvent(event) : event;
@@ -177,7 +177,6 @@ export function mkMessage(opts) {
return mkEvent(opts);
}
/**
* A mock implementation of webstorage
*
@@ -204,7 +203,6 @@ MockStorageApi.prototype = {
},
};
/**
* If an event is being decrypted, wait for it to finish being decrypted.
*
@@ -212,21 +210,23 @@ MockStorageApi.prototype = {
* @returns {Promise} promise which resolves (to `event`) when the event has been decrypted
*/
export function awaitDecryption(event) {
if (!event.isBeingDecrypted()) {
return Promise.resolve(event);
}
// An event is not always decrypted ahead of time
// getClearContent is a good signal to know whether an event has been decrypted
// already
if (event.getClearContent() !== null) {
return event;
} else {
logger.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) => {
logger.log(`${Date.now()} event ${event.getId()} now decrypted`);
resolve(ev);
return new Promise((resolve, reject) => {
event.once('Event.decrypted', (ev) => {
logger.log(`${Date.now()} event ${event.getId()} now decrypted`);
resolve(ev);
});
});
});
}
}
export function HttpResponse(
httpLookups, acceptKeepalives, ignoreUnhandledSync,
) {
@@ -357,12 +357,12 @@ export function setHttpResponses(
);
const httpReq = httpResponseObj.request.bind(httpResponseObj);
client._http = [
client.http = [
"authedRequest", "authedRequestWithPrefix", "getContentUri",
"request", "requestWithPrefix", "uploadContent",
].reduce((r, k) => {r[k] = jest.fn(); return r;}, {});
client._http.authedRequest.mockImplementation(httpReq);
client._http.authedRequestWithPrefix.mockImplementation(httpReq);
client._http.requestWithPrefix.mockImplementation(httpReq);
client._http.request.mockImplementation(httpReq);
client.http.authedRequest.mockImplementation(httpReq);
client.http.authedRequestWithPrefix.mockImplementation(httpReq);
client.http.requestWithPrefix.mockImplementation(httpReq);
client.http.request.mockImplementation(httpReq);
}
+78
View File
@@ -0,0 +1,78 @@
/*
Copyright 2021 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.
*/
import { NamespacedValue, UnstableValue } from "../../src/NamespacedValue";
describe("NamespacedValue", () => {
it("should prefer stable over unstable", () => {
const ns = new NamespacedValue("stable", "unstable");
expect(ns.name).toBe(ns.stable);
expect(ns.altName).toBe(ns.unstable);
});
it("should return unstable if there is no stable", () => {
const ns = new NamespacedValue(null, "unstable");
expect(ns.name).toBe(ns.unstable);
expect(ns.altName).toBeFalsy();
});
it("should have a falsey unstable if needed", () => {
const ns = new NamespacedValue("stable", null);
expect(ns.name).toBe(ns.stable);
expect(ns.altName).toBeFalsy();
});
it("should match against either stable or unstable", () => {
const ns = new NamespacedValue("stable", "unstable");
expect(ns.matches("no")).toBe(false);
expect(ns.matches(ns.stable)).toBe(true);
expect(ns.matches(ns.unstable)).toBe(true);
});
it("should not permit falsey values for both parts", () => {
try {
new UnstableValue(null, null);
// noinspection ExceptionCaughtLocallyJS
throw new Error("Failed to fail");
} catch (e) {
expect(e.message).toBe("One of stable or unstable values must be supplied");
}
});
});
describe("UnstableValue", () => {
it("should prefer unstable over stable", () => {
const ns = new UnstableValue("stable", "unstable");
expect(ns.name).toBe(ns.unstable);
expect(ns.altName).toBe(ns.stable);
});
it("should return unstable if there is no stable", () => {
const ns = new UnstableValue(null, "unstable");
expect(ns.name).toBe(ns.unstable);
expect(ns.altName).toBeFalsy();
});
it("should not permit falsey unstable values", () => {
try {
new UnstableValue("stable", null);
// noinspection ExceptionCaughtLocallyJS
throw new Error("Failed to fail");
} catch (e) {
expect(e.message).toBe("Unstable value must be supplied");
}
});
});
+73
View File
@@ -0,0 +1,73 @@
/*
Copyright 2021 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.
*/
import { EventEmitter } from "events";
import { ReEmitter } from "../../src/ReEmitter";
const EVENTNAME = "UnknownEntry";
class EventSource extends EventEmitter {
doTheThing() {
this.emit(EVENTNAME, "foo", "bar");
}
doAnError() {
this.emit('error');
}
}
class EventTarget extends EventEmitter {
}
describe("ReEmitter", function() {
it("Re-Emits events with the same args", function() {
const src = new EventSource();
const tgt = new EventTarget();
const handler = jest.fn();
tgt.on(EVENTNAME, handler);
const reEmitter = new ReEmitter(tgt);
reEmitter.reEmit(src, [EVENTNAME]);
src.doTheThing();
// Args should be the args passed to 'emit' after the event name, and
// also the source object of the event which re-emitter adds
expect(handler).toHaveBeenCalledWith("foo", "bar", src);
});
it("Doesn't throw if no handler for 'error' event", function() {
const src = new EventSource();
const tgt = new EventTarget();
const reEmitter = new ReEmitter(tgt);
reEmitter.reEmit(src, ['error']);
// without the workaround in ReEmitter, this would throw
src.doAnError();
const handler = jest.fn();
tgt.on('error', handler);
src.doAnError();
// Now we've attached an error handler, it should be called
expect(handler).toHaveBeenCalled();
});
});
+2 -1
View File
@@ -16,8 +16,9 @@ limitations under the License.
*/
import MockHttpBackend from "matrix-mock-request";
import * as sdk from "../../src";
import {AutoDiscovery} from "../../src/autodiscovery";
import { AutoDiscovery } from "../../src/autodiscovery";
describe("AutoDiscovery", function() {
let httpBackend = null;
+1 -1
View File
@@ -1,4 +1,4 @@
import {getHttpUriForMxc} from "../../src/content-repo";
import { getHttpUriForMxc } from "../../src/content-repo";
describe("ContentRepo", function() {
const baseUrl = "https://my.home.server";
+25 -24
View File
@@ -1,16 +1,17 @@
import '../olm-loader';
import {Crypto} from "../../src/crypto";
import {WebStorageSessionStore} from "../../src/store/session/webstorage";
import {MemoryCryptoStore} from "../../src/crypto/store/memory-crypto-store";
import {MockStorageApi} from "../MockStorageApi";
import {TestClient} from "../TestClient";
import {MatrixEvent} from "../../src/models/event";
import {Room} from "../../src/models/room";
import { EventEmitter } from "events";
import { Crypto } from "../../src/crypto";
import { WebStorageSessionStore } from "../../src/store/session/webstorage";
import { MemoryCryptoStore } from "../../src/crypto/store/memory-crypto-store";
import { MockStorageApi } from "../MockStorageApi";
import { TestClient } from "../TestClient";
import { MatrixEvent } from "../../src/models/event";
import { Room } from "../../src/models/room";
import * as olmlib from "../../src/crypto/olmlib";
import {sleep} from "../../src/utils";
import {EventEmitter} from "events";
import {CRYPTO_ENABLED} from "../../src/client";
import {DeviceInfo} from "../../src/crypto/deviceinfo";
import { sleep } from "../../src/utils";
import { CRYPTO_ENABLED } from "../../src/client";
import { DeviceInfo } from "../../src/crypto/deviceinfo";
const Olm = global.Olm;
@@ -46,7 +47,7 @@ describe("Crypto", function() {
// unknown sender (e.g. deleted device), forwarded megolm key (untrusted)
event.getSenderKey = () => 'YmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmI';
event.getWireContent = () => {return {algorithm: olmlib.MEGOLM_ALGORITHM};};
event.getWireContent = () => {return { algorithm: olmlib.MEGOLM_ALGORITHM };};
event.getForwardingCurve25519KeyChain = () => ["not empty"];
event.isKeySourceUntrusted = () => false;
event.getClaimedEd25519Key =
@@ -65,7 +66,7 @@ describe("Crypto", function() {
'YmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmI';
device.keys["ed25519:FLIBBLE"] =
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
client._crypto._deviceList.getDeviceByIdentityKey = () => device;
client.crypto.deviceList.getDeviceByIdentityKey = () => device;
encryptionInfo = client.getEventEncryptionInfo(event);
expect(encryptionInfo.encrypted).toBeTruthy();
@@ -213,7 +214,7 @@ describe("Crypto", function() {
async function keyshareEventForEvent(event, index) {
const eventContent = event.getWireContent();
const key = await aliceClient._crypto._olmDevice
const key = await aliceClient.crypto.olmDevice
.getInboundGroupSessionKey(
roomId, eventContent.sender_key, eventContent.session_id,
index,
@@ -234,7 +235,7 @@ describe("Crypto", function() {
},
});
// make onRoomKeyEvent think this was an encrypted event
ksEvent._senderCurve25519Key = "akey";
ksEvent.senderCurve25519Key = "akey";
return ksEvent;
}
@@ -273,19 +274,19 @@ describe("Crypto", function() {
await Promise.all(events.map(async (event) => {
// alice encrypts each event, and then bob tries to decrypt
// them without any keys, so that they'll be in pending
await aliceClient._crypto.encryptEvent(event, aliceRoom);
event._clearEvent = {};
event._senderCurve25519Key = null;
event._claimedEd25519Key = null;
await aliceClient.crypto.encryptEvent(event, aliceRoom);
event.clearEvent = undefined;
event.senderCurve25519Key = null;
event.claimedEd25519Key = null;
try {
await bobClient._crypto.decryptEvent(event);
await bobClient.crypto.decryptEvent(event);
} catch (e) {
// we expect this to fail because we don't have the
// decryption keys yet
}
}));
const bobDecryptor = bobClient._crypto._getRoomDecryptor(
const bobDecryptor = bobClient.crypto.getRoomDecryptor(
roomId, olmlib.MEGOLM_ALGORITHM,
);
@@ -302,7 +303,7 @@ describe("Crypto", function() {
expect(events[0].getContent().msgtype).toBe("m.bad.encrypted");
expect(events[1].getContent().msgtype).not.toBe("m.bad.encrypted");
const cryptoStore = bobClient._cryptoStore;
const cryptoStore = bobClient.cryptoStore;
const eventContent = events[0].getWireContent();
const senderKey = eventContent.sender_key;
const sessionId = eventContent.session_id;
@@ -344,7 +345,7 @@ describe("Crypto", function() {
},
});
await aliceClient.cancelAndResendEventRoomKeyRequest(event);
const cryptoStore = aliceClient._cryptoStore;
const cryptoStore = aliceClient.cryptoStore;
const roomKeyRequestBody = {
algorithm: olmlib.MEGOLM_ALGORITHM,
room_id: "!someroom",
@@ -377,7 +378,7 @@ describe("Crypto", function() {
// key requests get queued until the sync has finished, but we don't
// let the client set up enough for that to happen, so gut-wrench a bit
// to force it to send now.
aliceClient._crypto._outgoingRoomKeyRequestManager.sendQueuedRequests();
aliceClient.crypto.outgoingRoomKeyRequestManager.sendQueuedRequests();
jest.runAllTimers();
await Promise.resolve();
expect(aliceClient.sendToDevice).toBeCalledTimes(1);
+4 -4
View File
@@ -22,11 +22,11 @@ import {
import {
IndexedDBCryptoStore,
} from '../../../src/crypto/store/indexeddb-crypto-store';
import {MemoryCryptoStore} from '../../../src/crypto/store/memory-crypto-store';
import { MemoryCryptoStore } from '../../../src/crypto/store/memory-crypto-store';
import 'fake-indexeddb/auto';
import 'jest-localstorage-mock';
import {OlmDevice} from "../../../src/crypto/OlmDevice";
import {logger} from '../../../src/logger';
import { OlmDevice } from "../../../src/crypto/OlmDevice";
import { logger } from '../../../src/logger';
const userId = "@alice:example.com";
@@ -66,7 +66,7 @@ describe("CrossSigningInfo.getCrossSigningKey", function() {
});
it.each(types)("should throw if the callback returns falsey",
async ({type, shouldCache}) => {
async ({ type, shouldCache }) => {
const info = new CrossSigningInfo(userId, {
getCrossSigningKey: () => false,
});
+61 -5
View File
@@ -16,10 +16,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {logger} from "../../../src/logger";
import { logger } from "../../../src/logger";
import * as utils from "../../../src/utils";
import {MemoryCryptoStore} from "../../../src/crypto/store/memory-crypto-store";
import {DeviceList} from "../../../src/crypto/DeviceList";
import { MemoryCryptoStore } from "../../../src/crypto/store/memory-crypto-store";
import { DeviceList } from "../../../src/crypto/DeviceList";
const signedDeviceList = {
"failures": {},
@@ -51,6 +51,36 @@ const signedDeviceList = {
},
};
const signedDeviceList2 = {
"failures": {},
"device_keys": {
"@test2:sw1v.org": {
"QJVRHWAKGH": {
"signatures": {
"@test2:sw1v.org": {
"ed25519:QJVRHWAKGH":
"w1xxdLe1iIqzEFHLRVYQeuiM6t2N2ZRiI8s5nDKxf054BP8" +
"1CPEX/AQXh5BhkKAVMlKnwg4T9zU1/wBALeajk3",
},
},
"user_id": "@test2:sw1v.org",
"keys": {
"ed25519:QJVRHWAKGH":
"Ig0/C6T+bBII1l2By2Wnnvtjp1nm/iXBlLU5/QESFXL",
"curve25519:QJVRHWAKGH":
"YR3eQnUvTQzGlWih4rsmJkKxpDxzgkgIgsBd1DEZIbm",
},
"algorithms": [
"m.olm.v1.curve25519-aes-sha2",
"m.megolm.v1.aes-sha2",
],
"device_id": "QJVRHWAKGH",
"unsigned": {},
},
},
},
};
describe('DeviceList', function() {
let downloadSpy;
let cryptoStore;
@@ -69,7 +99,7 @@ describe('DeviceList', function() {
}
});
function createTestDeviceList() {
function createTestDeviceList(keyDownloadChunkSize = 250) {
const baseApis = {
downloadKeysForUsers: downloadSpy,
getUserId: () => '@test1:sw1v.org',
@@ -78,7 +108,7 @@ describe('DeviceList', function() {
const mockOlm = {
verifySignature: function(key, message, signature) {},
};
const dl = new DeviceList(baseApis, cryptoStore, mockOlm);
const dl = new DeviceList(baseApis, cryptoStore, mockOlm, keyDownloadChunkSize);
deviceLists.push(dl);
return dl;
}
@@ -150,4 +180,30 @@ describe('DeviceList', function() {
expect(Object.keys(storedKeys)).toEqual(['HGKAWHRVJQ']);
});
});
it("should download device keys in batches", function() {
const dl = createTestDeviceList(1);
dl.startTrackingDeviceList('@test1:sw1v.org');
dl.startTrackingDeviceList('@test2:sw1v.org');
const queryDefer1 = utils.defer();
downloadSpy.mockReturnValueOnce(queryDefer1.promise);
const queryDefer2 = utils.defer();
downloadSpy.mockReturnValueOnce(queryDefer2.promise);
const prom1 = dl.refreshOutdatedDeviceLists();
expect(downloadSpy).toBeCalledTimes(2);
expect(downloadSpy).toHaveBeenNthCalledWith(1, ['@test1:sw1v.org'], {});
expect(downloadSpy).toHaveBeenNthCalledWith(2, ['@test2:sw1v.org'], {});
queryDefer1.resolve(utils.deepCopy(signedDeviceList));
queryDefer2.resolve(utils.deepCopy(signedDeviceList2));
return prom1.then(() => {
const storedKeys1 = dl.getRawStoredDevicesForUser('@test1:sw1v.org');
expect(Object.keys(storedKeys1)).toEqual(['HGKAWHRVJQ']);
const storedKeys2 = dl.getRawStoredDevicesForUser('@test2:sw1v.org');
expect(Object.keys(storedKeys2)).toEqual(['QJVRHWAKGH']);
});
});
});
+156 -106
View File
@@ -1,14 +1,14 @@
import '../../../olm-loader';
import * as algorithms from "../../../../src/crypto/algorithms";
import {MemoryCryptoStore} from "../../../../src/crypto/store/memory-crypto-store";
import {MockStorageApi} from "../../../MockStorageApi";
import { MemoryCryptoStore } from "../../../../src/crypto/store/memory-crypto-store";
import { MockStorageApi } from "../../../MockStorageApi";
import * as testUtils from "../../../test-utils";
import {OlmDevice} from "../../../../src/crypto/OlmDevice";
import {Crypto} from "../../../../src/crypto";
import {logger} from "../../../../src/logger";
import {MatrixEvent} from "../../../../src/models/event";
import {TestClient} from "../../../TestClient";
import {Room} from "../../../../src/models/room";
import { OlmDevice } from "../../../../src/crypto/OlmDevice";
import { Crypto } from "../../../../src/crypto";
import { logger } from "../../../../src/logger";
import { MatrixEvent } from "../../../../src/models/event";
import { TestClient } from "../../../TestClient";
import { Room } from "../../../../src/models/room";
import * as olmlib from "../../../../src/crypto/olmlib";
const MegolmDecryption = algorithms.DECRYPTION_CLASSES['m.megolm.v1.aes-sha2'];
@@ -50,7 +50,6 @@ describe("MegolmDecryption", function() {
roomId: ROOM_ID,
});
// we stub out the olm encryption bits
mockOlmLib = {};
mockOlmLib.ensureOlmSessionsForDevices = jest.fn();
@@ -136,9 +135,9 @@ describe("MegolmDecryption", function() {
mockCrypto.getStoredDevice.mockReturnValue(deviceInfo);
mockOlmLib.ensureOlmSessionsForDevices.mockResolvedValue({
'@alice:foo': {'alidevice': {
'@alice:foo': { 'alidevice': {
sessionId: 'alisession',
}},
} },
});
const awaitEncryptForDevice = new Promise((res, rej) => {
@@ -257,94 +256,145 @@ describe("MegolmDecryption", function() {
});
});
it("re-uses sessions for sequential messages", async function() {
const mockStorage = new MockStorageApi();
const cryptoStore = new MemoryCryptoStore(mockStorage);
describe("session reuse and key reshares", () => {
let megolmEncryption;
let aliceDeviceInfo;
let mockRoom;
let olmDevice;
const olmDevice = new OlmDevice(cryptoStore);
olmDevice.verifySignature = jest.fn();
await olmDevice.init();
beforeEach(async () => {
mockCrypto.backupManager = {
backupGroupSession: () => {},
};
const mockStorage = new MockStorageApi();
const cryptoStore = new MemoryCryptoStore(mockStorage);
mockBaseApis.claimOneTimeKeys = jest.fn().mockReturnValue(Promise.resolve({
one_time_keys: {
'@alice:home.server': {
aliceDevice: {
'signed_curve25519:flooble': {
key: 'YmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmI',
signatures: {
'@alice:home.server': {
'ed25519:aliceDevice': 'totally valid',
olmDevice = new OlmDevice(cryptoStore);
olmDevice.verifySignature = jest.fn();
await olmDevice.init();
mockBaseApis.claimOneTimeKeys = jest.fn().mockReturnValue(Promise.resolve({
one_time_keys: {
'@alice:home.server': {
aliceDevice: {
'signed_curve25519:flooble': {
key: 'YmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmI',
signatures: {
'@alice:home.server': {
'ed25519:aliceDevice': 'totally valid',
},
},
},
},
},
},
},
}));
mockBaseApis.sendToDevice = jest.fn().mockResolvedValue(undefined);
}));
mockBaseApis.sendToDevice = jest.fn().mockResolvedValue(undefined);
mockCrypto.downloadKeys.mockReturnValue(Promise.resolve({
'@alice:home.server': {
aliceDevice: {
deviceId: 'aliceDevice',
isBlocked: jest.fn().mockReturnValue(false),
isUnverified: jest.fn().mockReturnValue(false),
getIdentityKey: jest.fn().mockReturnValue(
'YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWE',
),
getFingerprint: jest.fn().mockReturnValue(''),
aliceDeviceInfo = {
deviceId: 'aliceDevice',
isBlocked: jest.fn().mockReturnValue(false),
isUnverified: jest.fn().mockReturnValue(false),
getIdentityKey: jest.fn().mockReturnValue(
'YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWE',
),
getFingerprint: jest.fn().mockReturnValue(''),
};
mockCrypto.downloadKeys.mockReturnValue(Promise.resolve({
'@alice:home.server': {
aliceDevice: aliceDeviceInfo,
},
},
}));
}));
mockCrypto.checkDeviceTrust.mockReturnValue({
isVerified: () => false,
mockCrypto.checkDeviceTrust.mockReturnValue({
isVerified: () => false,
});
megolmEncryption = new MegolmEncryption({
userId: '@user:id',
crypto: mockCrypto,
olmDevice: olmDevice,
baseApis: mockBaseApis,
roomId: ROOM_ID,
config: {
rotation_period_ms: 9999999999999,
},
});
mockRoom = {
getEncryptionTargetMembers: jest.fn().mockReturnValue(
[{ userId: "@alice:home.server" }],
),
getBlacklistUnverifiedDevices: jest.fn().mockReturnValue(false),
};
});
const megolmEncryption = new MegolmEncryption({
userId: '@user:id',
crypto: mockCrypto,
olmDevice: olmDevice,
baseApis: mockBaseApis,
roomId: ROOM_ID,
config: {
rotation_period_ms: 9999999999999,
},
});
const mockRoom = {
getEncryptionTargetMembers: jest.fn().mockReturnValue(
[{userId: "@alice:home.server"}],
),
getBlacklistUnverifiedDevices: jest.fn().mockReturnValue(false),
};
const ct1 = await megolmEncryption.encryptMessage(mockRoom, "a.fake.type", {
body: "Some text",
});
expect(mockRoom.getEncryptionTargetMembers).toHaveBeenCalled();
it("re-uses sessions for sequential messages", async function() {
const ct1 = await megolmEncryption.encryptMessage(mockRoom, "a.fake.type", {
body: "Some text",
});
expect(mockRoom.getEncryptionTargetMembers).toHaveBeenCalled();
// this should have claimed a key for alice as it's starting a new session
expect(mockBaseApis.claimOneTimeKeys).toHaveBeenCalledWith(
[['@alice:home.server', 'aliceDevice']], 'signed_curve25519', 2000,
);
expect(mockCrypto.downloadKeys).toHaveBeenCalledWith(
['@alice:home.server'], false,
);
expect(mockBaseApis.sendToDevice).toHaveBeenCalled();
expect(mockBaseApis.claimOneTimeKeys).toHaveBeenCalledWith(
[['@alice:home.server', 'aliceDevice']], 'signed_curve25519', 2000,
);
// this should have claimed a key for alice as it's starting a new session
expect(mockBaseApis.claimOneTimeKeys).toHaveBeenCalledWith(
[['@alice:home.server', 'aliceDevice']], 'signed_curve25519', 2000,
);
expect(mockCrypto.downloadKeys).toHaveBeenCalledWith(
['@alice:home.server'], false,
);
expect(mockBaseApis.sendToDevice).toHaveBeenCalled();
expect(mockBaseApis.claimOneTimeKeys).toHaveBeenCalledWith(
[['@alice:home.server', 'aliceDevice']], 'signed_curve25519', 2000,
);
mockBaseApis.claimOneTimeKeys.mockReset();
mockBaseApis.claimOneTimeKeys.mockReset();
const ct2 = await megolmEncryption.encryptMessage(mockRoom, "a.fake.type", {
body: "Some more text",
const ct2 = await megolmEncryption.encryptMessage(mockRoom, "a.fake.type", {
body: "Some more text",
});
// this should *not* have claimed a key as it should be using the same session
expect(mockBaseApis.claimOneTimeKeys).not.toHaveBeenCalled();
// likewise they should show the same session ID
expect(ct2.session_id).toEqual(ct1.session_id);
});
// this should *not* have claimed a key as it should be using the same session
expect(mockBaseApis.claimOneTimeKeys).not.toHaveBeenCalled();
it("re-shares keys to devices it's already sent to", async function() {
const ct1 = await megolmEncryption.encryptMessage(mockRoom, "a.fake.type", {
body: "Some text",
});
// likewise they should show the same session ID
expect(ct2.session_id).toEqual(ct1.session_id);
mockBaseApis.sendToDevice.mockClear();
await megolmEncryption.reshareKeyWithDevice(
olmDevice.deviceCurve25519Key,
ct1.session_id,
'@alice:home.server',
aliceDeviceInfo,
);
expect(mockBaseApis.sendToDevice).toHaveBeenCalled();
});
it("does not re-share keys to devices whose keys have changed", async function() {
const ct1 = await megolmEncryption.encryptMessage(mockRoom, "a.fake.type", {
body: "Some text",
});
aliceDeviceInfo.getIdentityKey = jest.fn().mockReturnValue(
'YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWI',
);
mockBaseApis.sendToDevice.mockClear();
await megolmEncryption.reshareKeyWithDevice(
olmDevice.deviceCurve25519Key,
ct1.session_id,
'@alice:home.server',
aliceDeviceInfo,
);
expect(mockBaseApis.sendToDevice).not.toHaveBeenCalled();
});
});
});
@@ -363,9 +413,9 @@ describe("MegolmDecryption", function() {
bobClient1.initCrypto(),
bobClient2.initCrypto(),
]);
const aliceDevice = aliceClient._crypto._olmDevice;
const bobDevice1 = bobClient1._crypto._olmDevice;
const bobDevice2 = bobClient2._crypto._olmDevice;
const aliceDevice = aliceClient.crypto.olmDevice;
const bobDevice1 = bobClient1.crypto.olmDevice;
const bobDevice2 = bobClient2.crypto.olmDevice;
const encryptionCfg = {
"algorithm": "m.megolm.v1.aes-sha2",
@@ -373,7 +423,7 @@ describe("MegolmDecryption", function() {
const roomId = "!someroom";
const room = new Room(roomId, aliceClient, "@alice:example.com", {});
room.getEncryptionTargetMembers = async function() {
return [{userId: "@bob:example.com"}];
return [{ userId: "@bob:example.com" }];
};
room.setBlacklistUnverifiedDevices(true);
aliceClient.store.storeRoom(room);
@@ -402,11 +452,11 @@ describe("MegolmDecryption", function() {
},
};
aliceClient._crypto._deviceList.storeDevicesForUser(
aliceClient.crypto.deviceList.storeDevicesForUser(
"@bob:example.com", BOB_DEVICES,
);
aliceClient._crypto._deviceList.downloadKeys = async function(userIds) {
return this._getDevicesFromStore(userIds);
aliceClient.crypto.deviceList.downloadKeys = async function(userIds) {
return this.getDevicesFromStore(userIds);
};
let run = false;
@@ -446,7 +496,7 @@ describe("MegolmDecryption", function() {
body: "secret",
},
});
await aliceClient._crypto.encryptEvent(event, room);
await aliceClient.crypto.encryptEvent(event, room);
expect(run).toBe(true);
@@ -466,8 +516,8 @@ describe("MegolmDecryption", function() {
aliceClient.initCrypto(),
bobClient.initCrypto(),
]);
const aliceDevice = aliceClient._crypto._olmDevice;
const bobDevice = bobClient._crypto._olmDevice;
const aliceDevice = aliceClient.crypto.olmDevice;
const bobDevice = bobClient.crypto.olmDevice;
const encryptionCfg = {
"algorithm": "m.megolm.v1.aes-sha2",
@@ -506,11 +556,11 @@ describe("MegolmDecryption", function() {
},
};
aliceClient._crypto._deviceList.storeDevicesForUser(
aliceClient.crypto.deviceList.storeDevicesForUser(
"@bob:example.com", BOB_DEVICES,
);
aliceClient._crypto._deviceList.downloadKeys = async function(userIds) {
return this._getDevicesFromStore(userIds);
aliceClient.crypto.deviceList.downloadKeys = async function(userIds) {
return this.getDevicesFromStore(userIds);
};
aliceClient.claimOneTimeKeys = async () => {
@@ -544,7 +594,7 @@ describe("MegolmDecryption", function() {
event_id: "$event",
content: {},
});
await aliceClient._crypto.encryptEvent(event, aliceRoom);
await aliceClient.crypto.encryptEvent(event, aliceRoom);
await sendPromise;
});
@@ -559,11 +609,11 @@ describe("MegolmDecryption", function() {
aliceClient.initCrypto(),
bobClient.initCrypto(),
]);
const bobDevice = bobClient._crypto._olmDevice;
const bobDevice = bobClient.crypto.olmDevice;
const roomId = "!someroom";
aliceClient._crypto._onToDeviceEvent(new MatrixEvent({
aliceClient.crypto.onToDeviceEvent(new MatrixEvent({
type: "org.matrix.room_key.withheld",
sender: "@bob:example.com",
content: {
@@ -576,7 +626,7 @@ describe("MegolmDecryption", function() {
},
}));
await expect(aliceClient._crypto.decryptEvent(new MatrixEvent({
await expect(aliceClient.crypto.decryptEvent(new MatrixEvent({
type: "m.room.encrypted",
sender: "@bob:example.com",
event_id: "$event",
@@ -602,14 +652,14 @@ describe("MegolmDecryption", function() {
aliceClient.initCrypto(),
bobClient.initCrypto(),
]);
aliceClient._crypto.downloadKeys = async () => {};
const bobDevice = bobClient._crypto._olmDevice;
aliceClient.crypto.downloadKeys = async () => {};
const bobDevice = bobClient.crypto.olmDevice;
const roomId = "!someroom";
const now = Date.now();
aliceClient._crypto._onToDeviceEvent(new MatrixEvent({
aliceClient.crypto.onToDeviceEvent(new MatrixEvent({
type: "org.matrix.room_key.withheld",
sender: "@bob:example.com",
content: {
@@ -626,7 +676,7 @@ describe("MegolmDecryption", function() {
setTimeout(resolve, 100);
});
await expect(aliceClient._crypto.decryptEvent(new MatrixEvent({
await expect(aliceClient.crypto.decryptEvent(new MatrixEvent({
type: "m.room.encrypted",
sender: "@bob:example.com",
event_id: "$event",
@@ -653,15 +703,15 @@ describe("MegolmDecryption", function() {
aliceClient.initCrypto(),
bobClient.initCrypto(),
]);
const bobDevice = bobClient._crypto._olmDevice;
aliceClient._crypto.downloadKeys = async () => {};
const bobDevice = bobClient.crypto.olmDevice;
aliceClient.crypto.downloadKeys = async () => {};
const roomId = "!someroom";
const now = Date.now();
// pretend we got an event that we can't decrypt
aliceClient._crypto._onToDeviceEvent(new MatrixEvent({
aliceClient.crypto.onToDeviceEvent(new MatrixEvent({
type: "m.room.encrypted",
sender: "@bob:example.com",
content: {
@@ -676,7 +726,7 @@ describe("MegolmDecryption", function() {
setTimeout(resolve, 100);
});
await expect(aliceClient._crypto.decryptEvent(new MatrixEvent({
await expect(aliceClient.crypto.decryptEvent(new MatrixEvent({
type: "m.room.encrypted",
sender: "@bob:example.com",
event_id: "$event",
+91 -5
View File
@@ -16,12 +16,12 @@ limitations under the License.
*/
import '../../../olm-loader';
import {MemoryCryptoStore} from "../../../../src/crypto/store/memory-crypto-store";
import {MockStorageApi} from "../../../MockStorageApi";
import {logger} from "../../../../src/logger";
import {OlmDevice} from "../../../../src/crypto/OlmDevice";
import { MemoryCryptoStore } from "../../../../src/crypto/store/memory-crypto-store";
import { MockStorageApi } from "../../../MockStorageApi";
import { logger } from "../../../../src/logger";
import { OlmDevice } from "../../../../src/crypto/OlmDevice";
import * as olmlib from "../../../../src/crypto/olmlib";
import {DeviceInfo} from "../../../../src/crypto/deviceinfo";
import { DeviceInfo } from "../../../../src/crypto/deviceinfo";
function makeOlmDevice() {
const mockStorage = new MockStorageApi();
@@ -190,5 +190,91 @@ describe("OlmDevice", function() {
// new session and will have called claimOneTimeKeys
expect(count).toBe(2);
});
it("avoids deadlocks when two tasks are ensuring the same devices", async function() {
// This test checks whether `ensureOlmSessionsForDevices` properly
// handles multiple tasks in flight ensuring some set of devices in
// common without deadlocks.
let claimRequestCount = 0;
const baseApis = {
claimOneTimeKeys: () => {
// simulate a very slow server (.5 seconds to respond)
claimRequestCount++;
return new Promise((resolve, reject) => {
setTimeout(reject, 500);
});
},
};
const deviceBobA = DeviceInfo.fromStorage({
keys: {
"curve25519:BOB-A": "akey",
},
}, "BOB-A");
const deviceBobB = DeviceInfo.fromStorage({
keys: {
"curve25519:BOB-B": "bkey",
},
}, "BOB-B");
// There's no required ordering of devices per user, so here we
// create two different orderings so that each task reserves a
// device the other task needs before continuing.
const devicesByUserAB = {
"@bob:example.com": [
deviceBobA,
deviceBobB,
],
};
const devicesByUserBA = {
"@bob:example.com": [
deviceBobB,
deviceBobA,
],
};
function alwaysSucceed(promise) {
// swallow any exception thrown by a promise, so that
// Promise.all doesn't abort
return promise.catch(() => {});
}
const task1 = alwaysSucceed(olmlib.ensureOlmSessionsForDevices(
aliceOlmDevice, baseApis, devicesByUserAB,
));
// After a single tick through the first task, it should have
// claimed ownership of all devices to avoid deadlocking others.
expect(Object.keys(aliceOlmDevice.sessionsInProgress).length).toBe(2);
const task2 = alwaysSucceed(olmlib.ensureOlmSessionsForDevices(
aliceOlmDevice, baseApis, devicesByUserBA,
));
// The second task should not have changed the ownership count, as
// it's waiting on the first task.
expect(Object.keys(aliceOlmDevice.sessionsInProgress).length).toBe(2);
// Track the tasks, but don't await them yet.
const promises = Promise.all([
task1,
task2,
]);
await new Promise((resolve) => {
setTimeout(resolve, 200);
});
// After .2s, the first task should have made an initial claim request.
expect(claimRequestCount).toBe(1);
await promises;
// After waiting for both tasks to complete, the first task should
// have failed, so the second task should have tried to create a
// new session and will have called claimOneTimeKeys
expect(claimRequestCount).toBe(2);
});
});
});
+224 -75
View File
@@ -16,18 +16,19 @@ limitations under the License.
*/
import '../../olm-loader';
import {logger} from "../../../src/logger";
import { logger } from "../../../src/logger";
import * as olmlib from "../../../src/crypto/olmlib";
import {MatrixClient} from "../../../src/client";
import {MatrixEvent} from "../../../src/models/event";
import { MatrixClient } from "../../../src/client";
import { MatrixEvent } from "../../../src/models/event";
import * as algorithms from "../../../src/crypto/algorithms";
import {WebStorageSessionStore} from "../../../src/store/session/webstorage";
import {MemoryCryptoStore} from "../../../src/crypto/store/memory-crypto-store";
import {MockStorageApi} from "../../MockStorageApi";
import { WebStorageSessionStore } from "../../../src/store/session/webstorage";
import { MemoryCryptoStore } from "../../../src/crypto/store/memory-crypto-store";
import { MockStorageApi } from "../../MockStorageApi";
import * as testUtils from "../../test-utils";
import {OlmDevice} from "../../../src/crypto/OlmDevice";
import {Crypto} from "../../../src/crypto";
import {resetCrossSigningKeys} from "./crypto-utils";
import { OlmDevice } from "../../../src/crypto/OlmDevice";
import { Crypto } from "../../../src/crypto";
import { resetCrossSigningKeys } from "./crypto-utils";
import { BackupManager } from "../../../src/crypto/backup";
const Olm = global.Olm;
@@ -51,7 +52,7 @@ const ENCRYPTED_EVENT = new MatrixEvent({
origin_server_ts: 1507753886000,
});
const KEY_BACKUP_DATA = {
const CURVE25519_KEY_BACKUP_DATA = {
first_message_index: 0,
forwarded_count: 0,
is_verified: false,
@@ -72,14 +73,41 @@ const KEY_BACKUP_DATA = {
},
};
const BACKUP_INFO = {
algorithm: "m.megolm_backup.v1",
const AES256_KEY_BACKUP_DATA = {
first_message_index: 0,
forwarded_count: 0,
is_verified: false,
session_data: {
iv: 'b3Jqqvm5S9QdmXrzssspLQ',
ciphertext: 'GOOASO3E9ThogkG0zMjEduGLM3u9jHZTkS7AvNNbNj3q1znwk4OlaVKXce'
+ '7ynofiiYIiS865VlOqrKEEXv96XzRyUpgn68e3WsicwYl96EtjIEh/iY003PG2Qd'
+ 'EluT899Ax7PydpUHxEktbWckMppYomUR5q8x1KI1SsOQIiJaIGThmIMPANRCFiK0'
+ 'WQj+q+dnhzx4lt9AFqU5bKov8qKnw2qGYP7/+6RmJ0Kpvs8tG6lrcNDEHtFc2r0r'
+ 'KKubDypo0Vc8EWSwsAHdKa36ewRavpreOuE8Z9RLfY0QIR1ecXrMqW0CdGFr7H3P'
+ 'vcjF8sjwvQAavzxEKT1WMGizSMLeKWo2mgZ5cKnwV5HGUAw596JQvKs9laG2U89K'
+ 'YrT0sH30vi62HKzcBLcDkWkUSNYPz7UiZ1MM0L380UA+1ZOXSOmtBA9xxzzbc8Xd'
+ 'fRimVgklGdxrxjzuNLYhL2BvVH4oPWonD9j0bvRwE6XkimdbGQA8HB7UmXXjE8WA'
+ 'RgaDHkfzoA3g3aeQ',
mac: 'uR988UYgGL99jrvLLPX3V1ows+UYbktTmMxPAo2kxnU',
},
};
const CURVE25519_BACKUP_INFO = {
algorithm: "m.megolm_backup.v1.curve25519-aes-sha2",
version: 1,
auth_data: {
public_key: "hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo",
},
};
const AES256_BACKUP_INFO = {
algorithm: "org.matrix.msc3270.v1.aes-hmac-sha2",
version: 1,
auth_data: {
// FIXME: add iv and mac
},
};
const keys = {};
function getCrossSigningKey(type) {
@@ -138,11 +166,12 @@ describe("MegolmBackup", function() {
let megolmDecryption;
beforeEach(async function() {
mockCrypto = testUtils.mock(Crypto, 'Crypto');
mockCrypto.backupManager = testUtils.mock(BackupManager, "BackupManager");
mockCrypto.backupKey = new Olm.PkEncryption();
mockCrypto.backupKey.set_recipient_key(
"hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo",
);
mockCrypto.backupInfo = BACKUP_INFO;
mockCrypto.backupInfo = CURVE25519_BACKUP_INFO;
mockStorage = new MockStorageApi();
sessionStore = new WebStorageSessionStore(mockStorage);
@@ -215,16 +244,18 @@ describe("MegolmBackup", function() {
};
mockCrypto.cancelRoomKeyRequest = function() {};
mockCrypto.backupGroupSession = jest.fn();
mockCrypto.backupManager = {
backupGroupSession: jest.fn(),
};
return event.attemptDecryption(mockCrypto).then(() => {
return megolmDecryption.onRoomKeyEvent(event);
}).then(() => {
expect(mockCrypto.backupGroupSession).toHaveBeenCalled();
expect(mockCrypto.backupManager.backupGroupSession).toHaveBeenCalled();
});
});
it('sends backups to the server', function() {
it('sends backups to the server (Curve25519 version)', function() {
const groupSession = new Olm.OutboundGroupSession();
groupSession.create();
const ibGroupSession = new Olm.InboundGroupSession();
@@ -257,14 +288,14 @@ describe("MegolmBackup", function() {
ed25519: "SENDER_ED25519",
},
room_id: ROOM_ID,
session: ibGroupSession.pickle(olmDevice._pickleKey),
session: ibGroupSession.pickle(olmDevice.pickleKey),
},
txn);
});
})
.then(() => {
client.enableKeyBackup({
algorithm: "m.megolm_backup.v1",
algorithm: "m.megolm_backup.v1.curve25519-aes-sha2",
version: 1,
auth_data: {
public_key: "hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo",
@@ -272,7 +303,7 @@ describe("MegolmBackup", function() {
});
let numCalls = 0;
return new Promise((resolve, reject) => {
client._http.authedRequest = function(
client.http.authedRequest = function(
callback, method, path, queryParams, data, opts,
) {
++numCalls;
@@ -292,12 +323,91 @@ describe("MegolmBackup", function() {
resolve();
return Promise.resolve({});
};
client._crypto.backupGroupSession(
"roomId",
client.crypto.backupManager.backupGroupSession(
"F0Q2NmyJNgUVj9DGsb4ZQt3aVxhVcUQhg7+gvW0oyKI",
groupSession.session_id(),
);
}).then(() => {
expect(numCalls).toBe(1);
});
});
});
it('sends backups to the server (AES-256 version)', function() {
const groupSession = new Olm.OutboundGroupSession();
groupSession.create();
const ibGroupSession = new Olm.InboundGroupSession();
ibGroupSession.create(groupSession.session_key());
const client = makeTestClient(sessionStore, cryptoStore);
megolmDecryption = new MegolmDecryption({
userId: '@user:id',
crypto: mockCrypto,
olmDevice: olmDevice,
baseApis: client,
roomId: ROOM_ID,
});
megolmDecryption.olmlib = mockOlmLib;
return client.initCrypto()
.then(() => {
return client.crypto.storeSessionBackupPrivateKey(new Uint8Array(32));
})
.then(() => {
return cryptoStore.doTxn(
"readwrite",
[cryptoStore.STORE_SESSION],
(txn) => {
cryptoStore.addEndToEndInboundGroupSession(
"F0Q2NmyJNgUVj9DGsb4ZQt3aVxhVcUQhg7+gvW0oyKI",
groupSession.session_id(),
{
forwardingCurve25519KeyChain: undefined,
keysClaimed: {
ed25519: "SENDER_ED25519",
},
room_id: ROOM_ID,
session: ibGroupSession.pickle(olmDevice.pickleKey),
},
txn);
});
})
.then(() => {
client.enableKeyBackup({
algorithm: "org.matrix.msc3270.v1.aes-hmac-sha2",
version: 1,
auth_data: {
iv: "PsCAtR7gMc4xBd9YS3A9Ow",
mac: "ZSDsTFEZK7QzlauCLMleUcX96GQZZM7UNtk4sripSqQ",
},
});
let numCalls = 0;
return new Promise((resolve, reject) => {
client.http.authedRequest = function(
callback, method, path, queryParams, data, opts,
) {
++numCalls;
expect(numCalls).toBeLessThanOrEqual(1);
if (numCalls >= 2) {
// exit out of retry loop if there's something wrong
reject(new Error("authedRequest called too many timmes"));
return Promise.resolve({});
}
expect(method).toBe("PUT");
expect(path).toBe("/room_keys/keys");
expect(queryParams.version).toBe(1);
expect(data.rooms[ROOM_ID].sessions).toBeDefined();
expect(data.rooms[ROOM_ID].sessions).toHaveProperty(
groupSession.session_id(),
);
resolve();
return Promise.resolve({});
};
client.crypto.backupManager.backupGroupSession(
"F0Q2NmyJNgUVj9DGsb4ZQt3aVxhVcUQhg7+gvW0oyKI",
[],
groupSession.session_id(),
groupSession.session_key(),
);
}).then(() => {
expect(numCalls).toBe(1);
@@ -335,39 +445,48 @@ describe("MegolmBackup", function() {
});
await resetCrossSigningKeys(client);
let numCalls = 0;
await new Promise((resolve, reject) => {
client._http.authedRequest = function(
callback, method, path, queryParams, data, opts,
) {
++numCalls;
expect(numCalls).toBeLessThanOrEqual(1);
if (numCalls >= 2) {
// exit out of retry loop if there's something wrong
reject(new Error("authedRequest called too many timmes"));
return Promise.resolve({});
}
expect(method).toBe("POST");
expect(path).toBe("/room_keys/version");
try {
// make sure auth_data is signed by the master key
olmlib.pkVerify(
data.auth_data, client.getCrossSigningId(), "@alice:bar",
);
} catch (e) {
reject(e);
return Promise.resolve({});
}
resolve();
return Promise.resolve({});
};
await Promise.all([
new Promise((resolve, reject) => {
let backupInfo;
client.http.authedRequest = function(
callback, method, path, queryParams, data, opts,
) {
++numCalls;
expect(numCalls).toBeLessThanOrEqual(2);
if (numCalls === 1) {
expect(method).toBe("POST");
expect(path).toBe("/room_keys/version");
try {
// make sure auth_data is signed by the master key
olmlib.pkVerify(
data.auth_data, client.getCrossSigningId(), "@alice:bar",
);
} catch (e) {
reject(e);
return Promise.resolve({});
}
backupInfo = data;
return Promise.resolve({});
} else if (numCalls === 2) {
expect(method).toBe("GET");
expect(path).toBe("/room_keys/version");
resolve();
return Promise.resolve(backupInfo);
} else {
// exit out of retry loop if there's something wrong
reject(new Error("authedRequest called too many times"));
return Promise.resolve({});
}
};
}),
client.createKeyBackupVersion({
algorithm: "m.megolm_backup.v1",
algorithm: "m.megolm_backup.v1.curve25519-aes-sha2",
auth_data: {
public_key: "hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo",
},
});
});
expect(numCalls).toBe(1);
}),
]);
expect(numCalls).toBe(2);
});
it('retries when a backup fails', function() {
@@ -427,14 +546,14 @@ describe("MegolmBackup", function() {
ed25519: "SENDER_ED25519",
},
room_id: ROOM_ID,
session: ibGroupSession.pickle(olmDevice._pickleKey),
session: ibGroupSession.pickle(olmDevice.pickleKey),
},
txn);
});
})
.then(() => {
client.enableKeyBackup({
algorithm: "foobar",
algorithm: "m.megolm_backup.v1.curve25519-aes-sha2",
version: 1,
auth_data: {
public_key: "hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo",
@@ -442,7 +561,7 @@ describe("MegolmBackup", function() {
});
let numCalls = 0;
return new Promise((resolve, reject) => {
client._http.authedRequest = function(
client.http.authedRequest = function(
callback, method, path, queryParams, data, opts,
) {
++numCalls;
@@ -468,12 +587,9 @@ describe("MegolmBackup", function() {
);
}
};
client._crypto.backupGroupSession(
"roomId",
client.crypto.backupManager.backupGroupSession(
"F0Q2NmyJNgUVj9DGsb4ZQt3aVxhVcUQhg7+gvW0oyKI",
[],
groupSession.session_id(),
groupSession.session_key(),
);
}).then(() => {
expect(numCalls).toBe(2);
@@ -505,30 +621,47 @@ describe("MegolmBackup", function() {
client.stopClient();
});
it('can restore from backup', function() {
client._http.authedRequest = function() {
return Promise.resolve(KEY_BACKUP_DATA);
it('can restore from backup (Curve25519 version)', function() {
client.http.authedRequest = function() {
return Promise.resolve(CURVE25519_KEY_BACKUP_DATA);
};
return client.restoreKeyBackupWithRecoveryKey(
"EsTc LW2K PGiF wKEA 3As5 g5c4 BXwk qeeJ ZJV8 Q9fu gUMN UE4d",
ROOM_ID,
SESSION_ID,
BACKUP_INFO,
CURVE25519_BACKUP_INFO,
).then(() => {
return megolmDecryption.decryptEvent(ENCRYPTED_EVENT);
}).then((res) => {
expect(res.clearEvent.content).toEqual('testytest');
expect(res.untrusted).toBeTruthy(); // keys from backup are untrusted
expect(res.untrusted).toBeTruthy(); // keys from Curve25519 backup are untrusted
});
});
it('can restore backup by room', function() {
client._http.authedRequest = function() {
it('can restore from backup (AES-256 version)', function() {
client.http.authedRequest = function() {
return Promise.resolve(AES256_KEY_BACKUP_DATA);
};
return client.restoreKeyBackupWithRecoveryKey(
"EsTc LW2K PGiF wKEA 3As5 g5c4 BXwk qeeJ ZJV8 Q9fu gUMN UE4d",
ROOM_ID,
SESSION_ID,
AES256_BACKUP_INFO,
).then(() => {
return megolmDecryption.decryptEvent(ENCRYPTED_EVENT);
}).then((res) => {
expect(res.clearEvent.content).toEqual('testytest');
expect(res.untrusted).toBeFalsy(); // keys from AES backup are trusted
});
});
it('can restore backup by room (Curve25519 version)', function() {
client.http.authedRequest = function() {
return Promise.resolve({
rooms: {
[ROOM_ID]: {
sessions: {
[SESSION_ID]: KEY_BACKUP_DATA,
[SESSION_ID]: CURVE25519_KEY_BACKUP_DATA,
},
},
},
@@ -536,7 +669,7 @@ describe("MegolmBackup", function() {
};
return client.restoreKeyBackupWithRecoveryKey(
"EsTc LW2K PGiF wKEA 3As5 g5c4 BXwk qeeJ ZJV8 Q9fu gUMN UE4d",
null, null, BACKUP_INFO,
null, null, CURVE25519_BACKUP_INFO,
).then(() => {
return megolmDecryption.decryptEvent(ENCRYPTED_EVENT);
}).then((res) => {
@@ -546,28 +679,44 @@ describe("MegolmBackup", function() {
it('has working cache functions', async function() {
const key = Uint8Array.from([1, 2, 3, 4, 5, 6, 7, 8]);
await client._crypto.storeSessionBackupPrivateKey(key);
const result = await client._crypto.getSessionBackupPrivateKey();
await client.crypto.storeSessionBackupPrivateKey(key);
const result = await client.crypto.getSessionBackupPrivateKey();
expect(new Uint8Array(result)).toEqual(key);
});
it('caches session backup keys as it encounters them', async function() {
const cachedNull = await client._crypto.getSessionBackupPrivateKey();
const cachedNull = await client.crypto.getSessionBackupPrivateKey();
expect(cachedNull).toBeNull();
client._http.authedRequest = function() {
return Promise.resolve(KEY_BACKUP_DATA);
client.http.authedRequest = function() {
return Promise.resolve(CURVE25519_KEY_BACKUP_DATA);
};
await new Promise((resolve) => {
client.restoreKeyBackupWithRecoveryKey(
"EsTc LW2K PGiF wKEA 3As5 g5c4 BXwk qeeJ ZJV8 Q9fu gUMN UE4d",
ROOM_ID,
SESSION_ID,
BACKUP_INFO,
CURVE25519_BACKUP_INFO,
{ cacheCompleteCallback: resolve },
);
});
const cachedKey = await client._crypto.getSessionBackupPrivateKey();
const cachedKey = await client.crypto.getSessionBackupPrivateKey();
expect(cachedKey).not.toBeNull();
});
it("fails if an known algorithm is used", async function() {
const BAD_BACKUP_INFO = Object.assign({}, CURVE25519_BACKUP_INFO, {
algorithm: "this.algorithm.does.not.exist",
});
client.http.authedRequest = function() {
return Promise.resolve(CURVE25519_KEY_BACKUP_DATA);
};
await expect(client.restoreKeyBackupWithRecoveryKey(
"EsTc LW2K PGiF wKEA 3As5 g5c4 BXwk qeeJ ZJV8 Q9fu gUMN UE4d",
ROOM_ID,
SESSION_ID,
BAD_BACKUP_INFO,
)).rejects.toThrow();
});
});
});
+61 -54
View File
@@ -17,12 +17,13 @@ limitations under the License.
import '../../olm-loader';
import anotherjson from 'another-json';
import * as olmlib from "../../../src/crypto/olmlib";
import {TestClient} from '../../TestClient';
import {HttpResponse, setHttpResponses} from '../../test-utils';
import { TestClient } from '../../TestClient';
import { HttpResponse, setHttpResponses } from '../../test-utils';
import { resetCrossSigningKeys } from "./crypto-utils";
import { MatrixError } from '../../../src/http-api';
import {logger} from '../../../src/logger';
import { logger } from '../../../src/logger';
async function makeTestClient(userInfo, options, keys) {
if (!keys) keys = {};
@@ -60,12 +61,12 @@ describe("Cross Signing", function() {
it("should sign the master key with the device key", async function() {
const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
);
alice.uploadDeviceSigningKeys = jest.fn(async (auth, keys) => {
await olmlib.verifySignature(
alice._crypto._olmDevice, keys.master_key, "@alice:example.com",
"Osborne2", alice._crypto._olmDevice.deviceEd25519Key,
alice.crypto.olmDevice, keys.master_key, "@alice:example.com",
"Osborne2", alice.crypto.olmDevice.deviceEd25519Key,
);
});
alice.uploadKeySignatures = async () => {};
@@ -80,7 +81,7 @@ describe("Cross Signing", function() {
it("should abort bootstrap if device signing auth fails", async function() {
const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
);
alice.uploadDeviceSigningKeys = async (auth, keys) => {
const errorResponse = {
@@ -131,14 +132,14 @@ describe("Cross Signing", function() {
it("should upload a signature when a user is verified", async function() {
const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
);
alice.uploadDeviceSigningKeys = async () => {};
alice.uploadKeySignatures = async () => {};
// set Alice's cross-signing key
await resetCrossSigningKeys(alice);
// Alice downloads Bob's device key
alice._crypto._deviceList.storeCrossSigningForUser("@bob:example.com", {
alice.crypto.deviceList.storeCrossSigningForUser("@bob:example.com", {
keys: {
master: {
user_id: "@bob:example.com",
@@ -175,7 +176,7 @@ describe("Cross Signing", function() {
]);
const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
{
cryptoCallbacks: {
// will be called to sign our own device
@@ -193,30 +194,36 @@ describe("Cross Signing", function() {
const keyChangePromise = new Promise((resolve, reject) => {
alice.once("crossSigning.keysChanged", async (e) => {
resolve(e);
await alice.checkOwnCrossSigningTrust();
await alice.checkOwnCrossSigningTrust({
allowPrivateKeyRequests: true,
});
});
});
const uploadSigsPromise = new Promise((resolve, reject) => {
alice.uploadKeySignatures = jest.fn(async (content) => {
await olmlib.verifySignature(
alice._crypto._olmDevice,
content["@alice:example.com"][
"nqOvzeuGWT/sRx3h7+MHoInYj3Uk2LD/unI9kDYcHwk"
],
"@alice:example.com",
"Osborne2", alice._crypto._olmDevice.deviceEd25519Key,
);
olmlib.pkVerify(
content["@alice:example.com"]["Osborne2"],
"EmkqvokUn8p+vQAGZitOk4PWjp7Ukp3txV2TbMPEiBQ",
"@alice:example.com",
);
resolve();
try {
await olmlib.verifySignature(
alice.crypto.olmDevice,
content["@alice:example.com"][
"nqOvzeuGWT/sRx3h7+MHoInYj3Uk2LD/unI9kDYcHwk"
],
"@alice:example.com",
"Osborne2", alice.crypto.olmDevice.deviceEd25519Key,
);
olmlib.pkVerify(
content["@alice:example.com"]["Osborne2"],
"EmkqvokUn8p+vQAGZitOk4PWjp7Ukp3txV2TbMPEiBQ",
"@alice:example.com",
);
resolve();
} catch (e) {
reject(e);
}
});
});
const deviceInfo = alice._crypto._deviceList._devices["@alice:example.com"]
const deviceInfo = alice.crypto.deviceList.devices["@alice:example.com"]
.Osborne2;
const aliceDevice = {
user_id: "@alice:example.com",
@@ -224,7 +231,7 @@ describe("Cross Signing", function() {
};
aliceDevice.keys = deviceInfo.keys;
aliceDevice.algorithms = deviceInfo.algorithms;
await alice._crypto._signObject(aliceDevice);
await alice.crypto.signObject(aliceDevice);
olmlib.pkSign(aliceDevice, selfSigningKey, "@alice:example.com");
// feed sync result that includes master key, ssk, device key
@@ -326,7 +333,7 @@ describe("Cross Signing", function() {
it("should use trust chain to determine device verification", async function() {
const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
);
alice.uploadDeviceSigningKeys = async () => {};
alice.uploadKeySignatures = async () => {};
@@ -352,7 +359,7 @@ describe("Cross Signing", function() {
["ed25519:" + bobMasterPubkey]: sskSig,
},
};
alice._crypto._deviceList.storeCrossSigningForUser("@bob:example.com", {
alice.crypto.deviceList.storeCrossSigningForUser("@bob:example.com", {
keys: {
master: {
user_id: "@bob:example.com",
@@ -381,7 +388,7 @@ describe("Cross Signing", function() {
["ed25519:" + bobPubkey]: sig,
},
};
alice._crypto._deviceList.storeDevicesForUser("@bob:example.com", {
alice.crypto.deviceList.storeDevicesForUser("@bob:example.com", {
Dynabook: bobDevice,
});
// Bob's device key should be TOFU
@@ -411,12 +418,12 @@ describe("Cross Signing", function() {
it("should trust signatures received from other devices", async function() {
const aliceKeys = {};
const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
null,
aliceKeys,
);
alice._crypto._deviceList.startTrackingDeviceList("@bob:example.com");
alice._crypto._deviceList.stopTrackingAllDeviceLists = () => {};
alice.crypto.deviceList.startTrackingDeviceList("@bob:example.com");
alice.crypto.deviceList.stopTrackingAllDeviceLists = () => {};
alice.uploadDeviceSigningKeys = async () => {};
alice.uploadKeySignatures = async () => {};
@@ -431,14 +438,14 @@ describe("Cross Signing", function() {
]);
const keyChangePromise = new Promise((resolve, reject) => {
alice._crypto._deviceList.once("userCrossSigningUpdated", (userId) => {
alice.crypto.deviceList.once("userCrossSigningUpdated", (userId) => {
if (userId === "@bob:example.com") {
resolve();
}
});
});
const deviceInfo = alice._crypto._deviceList._devices["@alice:example.com"]
const deviceInfo = alice.crypto.deviceList.devices["@alice:example.com"]
.Osborne2;
const aliceDevice = {
user_id: "@alice:example.com",
@@ -446,7 +453,7 @@ describe("Cross Signing", function() {
};
aliceDevice.keys = deviceInfo.keys;
aliceDevice.algorithms = deviceInfo.algorithms;
await alice._crypto._signObject(aliceDevice);
await alice.crypto.signObject(aliceDevice);
const bobOlmAccount = new global.Olm.Account();
bobOlmAccount.create();
@@ -573,7 +580,7 @@ describe("Cross Signing", function() {
it("should dis-trust an unsigned device", async function() {
const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
);
alice.uploadDeviceSigningKeys = async () => {};
alice.uploadKeySignatures = async () => {};
@@ -600,7 +607,7 @@ describe("Cross Signing", function() {
["ed25519:" + bobMasterPubkey]: sskSig,
},
};
alice._crypto._deviceList.storeCrossSigningForUser("@bob:example.com", {
alice.crypto.deviceList.storeCrossSigningForUser("@bob:example.com", {
keys: {
master: {
user_id: "@bob:example.com",
@@ -623,7 +630,7 @@ describe("Cross Signing", function() {
"ed25519:Dynabook": "someOtherPubkey",
},
};
alice._crypto._deviceList.storeDevicesForUser("@bob:example.com", {
alice.crypto.deviceList.storeDevicesForUser("@bob:example.com", {
Dynabook: bobDevice,
});
// Bob's device key should be untrusted
@@ -642,7 +649,7 @@ describe("Cross Signing", function() {
it("should dis-trust a user when their ssk changes", async function() {
const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
);
alice.uploadDeviceSigningKeys = async () => {};
alice.uploadKeySignatures = async () => {};
@@ -667,7 +674,7 @@ describe("Cross Signing", function() {
["ed25519:" + bobMasterPubkey]: sskSig,
},
};
alice._crypto._deviceList.storeCrossSigningForUser("@bob:example.com", {
alice.crypto.deviceList.storeCrossSigningForUser("@bob:example.com", {
keys: {
master: {
user_id: "@bob:example.com",
@@ -695,7 +702,7 @@ describe("Cross Signing", function() {
bobDevice.signatures = {};
bobDevice.signatures["@bob:example.com"] = {};
bobDevice.signatures["@bob:example.com"]["ed25519:" + bobPubkey] = sig;
alice._crypto._deviceList.storeDevicesForUser("@bob:example.com", {
alice.crypto.deviceList.storeDevicesForUser("@bob:example.com", {
Dynabook: bobDevice,
});
// Alice verifies Bob's SSK
@@ -727,7 +734,7 @@ describe("Cross Signing", function() {
["ed25519:" + bobMasterPubkey2]: sskSig2,
},
};
alice._crypto._deviceList.storeCrossSigningForUser("@bob:example.com", {
alice.crypto.deviceList.storeCrossSigningForUser("@bob:example.com", {
keys: {
master: {
user_id: "@bob:example.com",
@@ -764,7 +771,7 @@ describe("Cross Signing", function() {
// Alice gets new signature for device
const sig2 = bobSigning2.sign(bobDeviceString);
bobDevice.signatures["@bob:example.com"]["ed25519:" + bobPubkey2] = sig2;
alice._crypto._deviceList.storeDevicesForUser("@bob:example.com", {
alice.crypto.deviceList.storeDevicesForUser("@bob:example.com", {
Dynabook: bobDevice,
});
@@ -780,7 +787,7 @@ describe("Cross Signing", function() {
let upgradeResolveFunc;
const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
{
cryptoCallbacks: {
shouldUpgradeDeviceVerifications: (verifs) => {
@@ -792,27 +799,27 @@ describe("Cross Signing", function() {
},
);
const bob = await makeTestClient(
{userId: "@bob:example.com", deviceId: "Dynabook"},
{ userId: "@bob:example.com", deviceId: "Dynabook" },
);
bob.uploadDeviceSigningKeys = async () => {};
bob.uploadKeySignatures = async () => {};
// set Bob's cross-signing key
await resetCrossSigningKeys(bob);
alice._crypto._deviceList.storeDevicesForUser("@bob:example.com", {
alice.crypto.deviceList.storeDevicesForUser("@bob:example.com", {
Dynabook: {
algorithms: ["m.olm.curve25519-aes-sha256", "m.megolm.v1.aes-sha"],
keys: {
"curve25519:Dynabook": bob._crypto._olmDevice.deviceCurve25519Key,
"ed25519:Dynabook": bob._crypto._olmDevice.deviceEd25519Key,
"curve25519:Dynabook": bob.crypto.olmDevice.deviceCurve25519Key,
"ed25519:Dynabook": bob.crypto.olmDevice.deviceEd25519Key,
},
verified: 1,
known: true,
},
});
alice._crypto._deviceList.storeCrossSigningForUser(
alice.crypto.deviceList.storeCrossSigningForUser(
"@bob:example.com",
bob._crypto._crossSigningInfo.toStorage(),
bob.crypto.crossSigningInfo.toStorage(),
);
alice.uploadDeviceSigningKeys = async () => {};
@@ -832,7 +839,7 @@ describe("Cross Signing", function() {
expect(bobTrust.isTofu()).toBeTruthy();
// "forget" that Bob is trusted
delete alice._crypto._deviceList._crossSigningInfo["@bob:example.com"]
delete alice.crypto.deviceList.crossSigningInfo["@bob:example.com"]
.keys.master.signatures["@alice:example.com"];
const bobTrust2 = alice.checkUserTrust("@bob:example.com");
@@ -842,9 +849,9 @@ describe("Cross Signing", function() {
upgradePromise = new Promise((resolve) => {
upgradeResolveFunc = resolve;
});
alice._crypto._deviceList.emit("userCrossSigningUpdated", "@bob:example.com");
alice.crypto.deviceList.emit("userCrossSigningUpdated", "@bob:example.com");
await new Promise((resolve) => {
alice._crypto.on("userTrustStatusChanged", resolve);
alice.crypto.on("userTrustStatusChanged", resolve);
});
await upgradePromise;
+11 -12
View File
@@ -1,5 +1,4 @@
import {IndexedDBCryptoStore} from '../../../src/crypto/store/indexeddb-crypto-store';
import { IndexedDBCryptoStore } from '../../../src/crypto/store/indexeddb-crypto-store';
// needs to be phased out and replaced with bootstrapSecretStorage,
// but that is doing too much extra stuff for it to be an easy transition.
@@ -7,28 +6,28 @@ export async function resetCrossSigningKeys(client, {
level,
authUploadDeviceSigningKeys = async func => await func(),
} = {}) {
const crypto = client._crypto;
const crypto = client.crypto;
const oldKeys = Object.assign({}, crypto._crossSigningInfo.keys);
const oldKeys = Object.assign({}, crypto.crossSigningInfo.keys);
try {
await crypto._crossSigningInfo.resetKeys(level);
await crypto._signObject(crypto._crossSigningInfo.keys.master);
await crypto.crossSigningInfo.resetKeys(level);
await crypto.signObject(crypto.crossSigningInfo.keys.master);
// write a copy locally so we know these are trusted keys
await crypto._cryptoStore.doTxn(
await crypto.cryptoStore.doTxn(
'readwrite', [IndexedDBCryptoStore.STORE_ACCOUNT],
(txn) => {
crypto._cryptoStore.storeCrossSigningKeys(
txn, crypto._crossSigningInfo.keys);
crypto.cryptoStore.storeCrossSigningKeys(
txn, crypto.crossSigningInfo.keys);
},
);
} catch (e) {
// If anything failed here, revert the keys so we know to try again from the start
// next time.
crypto._crossSigningInfo.keys = oldKeys;
crypto.crossSigningInfo.keys = oldKeys;
throw e;
}
crypto._baseApis.emit("crossSigning.keysChanged", {});
await crypto._afterCrossSigningLocalKeyChange();
crypto.baseApis.emit("crossSigning.keysChanged", {});
await crypto.afterCrossSigningLocalKeyChange();
}
export async function createSecretStorageKey() {
@@ -17,29 +17,27 @@ limitations under the License.
import {
IndexedDBCryptoStore,
} from '../../../src/crypto/store/indexeddb-crypto-store';
import {MemoryCryptoStore} from '../../../src/crypto/store/memory-crypto-store';
import { MemoryCryptoStore } from '../../../src/crypto/store/memory-crypto-store';
import { RoomKeyRequestState } from '../../../src/crypto/OutgoingRoomKeyRequestManager';
import 'fake-indexeddb/auto';
import 'jest-localstorage-mock';
import {
ROOM_KEY_REQUEST_STATES,
} from '../../../src/crypto/OutgoingRoomKeyRequestManager';
const requests = [
{
requestId: "A",
requestBody: { session_id: "A", room_id: "A" },
state: ROOM_KEY_REQUEST_STATES.SENT,
state: RoomKeyRequestState.Sent,
},
{
requestId: "B",
requestBody: { session_id: "B", room_id: "B" },
state: ROOM_KEY_REQUEST_STATES.SENT,
state: RoomKeyRequestState.Sent,
},
{
requestId: "C",
requestBody: { session_id: "C", room_id: "C" },
state: ROOM_KEY_REQUEST_STATES.UNSENT,
state: RoomKeyRequestState.Unsent,
},
];
@@ -68,9 +66,9 @@ describe.each([
it("getAllOutgoingRoomKeyRequestsByState retrieves all entries in a given state",
async () => {
const r = await
store.getAllOutgoingRoomKeyRequestsByState(ROOM_KEY_REQUEST_STATES.SENT);
store.getAllOutgoingRoomKeyRequestsByState(RoomKeyRequestState.Sent);
expect(r).toHaveLength(2);
requests.filter((e) => e.state == ROOM_KEY_REQUEST_STATES.SENT).forEach((e) => {
requests.filter((e) => e.state === RoomKeyRequestState.Sent).forEach((e) => {
expect(r).toContainEqual(e);
});
});
@@ -78,10 +76,10 @@ describe.each([
test("getOutgoingRoomKeyRequestByState retrieves any entry in a given state",
async () => {
const r =
await store.getOutgoingRoomKeyRequestByState([ROOM_KEY_REQUEST_STATES.SENT]);
await store.getOutgoingRoomKeyRequestByState([RoomKeyRequestState.Sent]);
expect(r).not.toBeNull();
expect(r).not.toBeUndefined();
expect(r.state).toEqual(ROOM_KEY_REQUEST_STATES.SENT);
expect(r.state).toEqual(RoomKeyRequestState.Sent);
expect(requests).toContainEqual(r);
});
});
+43 -44
View File
@@ -16,14 +16,13 @@ limitations under the License.
import '../../olm-loader';
import * as olmlib from "../../../src/crypto/olmlib";
import {SECRET_STORAGE_ALGORITHM_V1_AES} from "../../../src/crypto/SecretStorage";
import {MatrixEvent} from "../../../src/models/event";
import {TestClient} from '../../TestClient';
import {makeTestClients} from './verification/util';
import {encryptAES} from "../../../src/crypto/aes";
import {resetCrossSigningKeys, createSecretStorageKey} from "./crypto-utils";
import {logger} from '../../../src/logger';
import { SECRET_STORAGE_ALGORITHM_V1_AES } from "../../../src/crypto/SecretStorage";
import { MatrixEvent } from "../../../src/models/event";
import { TestClient } from '../../TestClient';
import { makeTestClients } from './verification/util';
import { encryptAES } from "../../../src/crypto/aes";
import { resetCrossSigningKeys, createSecretStorageKey } from "./crypto-utils";
import { logger } from '../../../src/logger';
import * as utils from "../../../src/utils";
try {
@@ -47,7 +46,7 @@ async function makeTestClient(userInfo, options) {
await client.initCrypto();
// No need to download keys for these tests
client._crypto.downloadKeys = async function() {};
client.crypto.downloadKeys = async function() {};
return client;
}
@@ -91,7 +90,7 @@ describe("Secrets", function() {
});
const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
{
cryptoCallbacks: {
getCrossSigningKey: t => signingKey,
@@ -99,11 +98,11 @@ describe("Secrets", function() {
},
},
);
alice._crypto._crossSigningInfo.setKeys({
alice.crypto.crossSigningInfo.setKeys({
master: signingkeyInfo,
});
const secretStorage = alice._crypto._secretStorage;
const secretStorage = alice.crypto.secretStorage;
alice.setAccountData = async function(eventType, contents, callback) {
alice.store.storeAccountDataEvents([
@@ -120,7 +119,7 @@ describe("Secrets", function() {
const keyAccountData = {
algorithm: SECRET_STORAGE_ALGORITHM_V1_AES,
};
await alice._crypto._crossSigningInfo.signObject(keyAccountData, 'master');
await alice.crypto.crossSigningInfo.signObject(keyAccountData, 'master');
alice.store.storeAccountDataEvents([
new MatrixEvent({
@@ -141,7 +140,7 @@ describe("Secrets", function() {
it("should throw if given a key that doesn't exist", async function() {
const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
);
try {
@@ -155,7 +154,7 @@ describe("Secrets", function() {
it("should refuse to encrypt with zero keys", async function() {
const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
);
try {
@@ -175,7 +174,7 @@ describe("Secrets", function() {
let keys = {};
const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
{
cryptoCallbacks: {
getCrossSigningKey: t => keys[t],
@@ -208,7 +207,7 @@ describe("Secrets", function() {
it("should refuse to encrypt if no keys given and no default key", async function() {
const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
);
try {
@@ -221,8 +220,8 @@ describe("Secrets", function() {
it("should request secrets from other clients", async function() {
const [osborne2, vax] = await makeTestClients(
[
{userId: "@alice:example.com", deviceId: "Osborne2"},
{userId: "@alice:example.com", deviceId: "VAX"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
{ userId: "@alice:example.com", deviceId: "VAX" },
],
{
cryptoCallbacks: {
@@ -234,11 +233,11 @@ describe("Secrets", function() {
},
);
const vaxDevice = vax.client._crypto._olmDevice;
const osborne2Device = osborne2.client._crypto._olmDevice;
const secretStorage = osborne2.client._crypto._secretStorage;
const vaxDevice = vax.client.crypto.olmDevice;
const osborne2Device = osborne2.client.crypto.olmDevice;
const secretStorage = osborne2.client.crypto.secretStorage;
osborne2.client._crypto._deviceList.storeDevicesForUser("@alice:example.com", {
osborne2.client.crypto.deviceList.storeDevicesForUser("@alice:example.com", {
"VAX": {
user_id: "@alice:example.com",
device_id: "VAX",
@@ -249,7 +248,7 @@ describe("Secrets", function() {
},
},
});
vax.client._crypto._deviceList.storeDevicesForUser("@alice:example.com", {
vax.client.crypto.deviceList.storeDevicesForUser("@alice:example.com", {
"Osborne2": {
user_id: "@alice:example.com",
device_id: "Osborne2",
@@ -265,7 +264,7 @@ describe("Secrets", function() {
const otks = (await osborne2Device.getOneTimeKeys()).curve25519;
await osborne2Device.markKeysAsPublished();
await vax.client._crypto._olmDevice.createOutboundSession(
await vax.client.crypto.olmDevice.createOutboundSession(
osborne2Device.deviceCurve25519Key,
Object.values(otks)[0],
);
@@ -334,8 +333,8 @@ describe("Secrets", function() {
createSecretStorageKey,
});
const crossSigning = bob._crypto._crossSigningInfo;
const secretStorage = bob._crypto._secretStorage;
const crossSigning = bob.crypto.crossSigningInfo;
const secretStorage = bob.crypto.secretStorage;
expect(crossSigning.getId()).toBeTruthy();
expect(await crossSigning.isStoredInSecretStorage(secretStorage))
@@ -376,10 +375,10 @@ describe("Secrets", function() {
]);
this.emit("accountData", event);
};
bob._crypto.checkKeyBackup = async () => {};
bob.crypto.backupManager.checkKeyBackup = async () => {};
const crossSigning = bob._crypto._crossSigningInfo;
const secretStorage = bob._crypto._secretStorage;
const crossSigning = bob.crypto.crossSigningInfo;
const secretStorage = bob.crypto.secretStorage;
// Set up cross-signing keys from scratch with specific storage key
await bob.bootstrapCrossSigning({
@@ -394,7 +393,7 @@ describe("Secrets", function() {
});
// Clear local cross-signing keys and read from secret storage
bob._crypto._deviceList.storeCrossSigningForUser(
bob.crypto.deviceList.storeCrossSigningForUser(
"@bob:example.com",
crossSigning.toStorage(),
);
@@ -419,12 +418,12 @@ describe("Secrets", function() {
key_id: SSSSKey,
};
const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
{
cryptoCallbacks: {
getCrossSigningKey: t => crossSigningKeys[t],
saveCrossSigningKeys: k => crossSigningKeys = k,
getSecretStorageKey: ({keys}, name) => {
getSecretStorageKey: ({ keys }, name) => {
for (const keyId of Object.keys(keys)) {
if (secretStorageKeys[keyId]) {
return [keyId, secretStorageKeys[keyId]];
@@ -458,7 +457,7 @@ describe("Secrets", function() {
type: "m.cross_signing.master",
content: {
encrypted: {
key_id: {ciphertext: "bla", mac: "bla", iv: "bla"},
key_id: { ciphertext: "bla", mac: "bla", iv: "bla" },
},
},
}),
@@ -466,7 +465,7 @@ describe("Secrets", function() {
type: "m.cross_signing.self_signing",
content: {
encrypted: {
key_id: {ciphertext: "bla", mac: "bla", iv: "bla"},
key_id: { ciphertext: "bla", mac: "bla", iv: "bla" },
},
},
}),
@@ -474,12 +473,12 @@ describe("Secrets", function() {
type: "m.cross_signing.user_signing",
content: {
encrypted: {
key_id: {ciphertext: "bla", mac: "bla", iv: "bla"},
key_id: { ciphertext: "bla", mac: "bla", iv: "bla" },
},
},
}),
]);
alice._crypto._deviceList.storeCrossSigningForUser("@alice:example.com", {
alice.crypto.deviceList.storeCrossSigningForUser("@alice:example.com", {
keys: {
master: {
user_id: "@alice:example.com",
@@ -525,7 +524,7 @@ describe("Secrets", function() {
await alice.bootstrapSecretStorage();
expect(alice.getAccountData("m.secret_storage.default_key").getContent())
.toEqual({key: "key_id"});
.toEqual({ key: "key_id" });
const keyInfo = alice.getAccountData("m.secret_storage.key.key_id")
.getContent();
expect(keyInfo.algorithm)
@@ -550,12 +549,12 @@ describe("Secrets", function() {
key_id: SSSSKey,
};
const alice = await makeTestClient(
{userId: "@alice:example.com", deviceId: "Osborne2"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
{
cryptoCallbacks: {
getCrossSigningKey: t => crossSigningKeys[t],
saveCrossSigningKeys: k => crossSigningKeys = k,
getSecretStorageKey: ({keys}, name) => {
getSecretStorageKey: ({ keys }, name) => {
for (const keyId of Object.keys(keys)) {
if (secretStorageKeys[keyId]) {
return [keyId, secretStorageKeys[keyId]];
@@ -587,7 +586,7 @@ describe("Secrets", function() {
type: "m.cross_signing.master",
content: {
encrypted: {
key_id: {ciphertext: "bla", mac: "bla", iv: "bla"},
key_id: { ciphertext: "bla", mac: "bla", iv: "bla" },
},
},
}),
@@ -595,7 +594,7 @@ describe("Secrets", function() {
type: "m.cross_signing.self_signing",
content: {
encrypted: {
key_id: {ciphertext: "bla", mac: "bla", iv: "bla"},
key_id: { ciphertext: "bla", mac: "bla", iv: "bla" },
},
},
}),
@@ -603,7 +602,7 @@ describe("Secrets", function() {
type: "m.cross_signing.user_signing",
content: {
encrypted: {
key_id: {ciphertext: "bla", mac: "bla", iv: "bla"},
key_id: { ciphertext: "bla", mac: "bla", iv: "bla" },
},
},
}),
@@ -619,7 +618,7 @@ describe("Secrets", function() {
},
}),
]);
alice._crypto._deviceList.storeCrossSigningForUser("@alice:example.com", {
alice.crypto.deviceList.storeCrossSigningForUser("@alice:example.com", {
keys: {
master: {
user_id: "@alice:example.com",
@@ -13,9 +13,9 @@ 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 {InRoomChannel} from "../../../../src/crypto/verification/request/InRoomChannel";
import { InRoomChannel } from "../../../../src/crypto/verification/request/InRoomChannel";
import { MatrixEvent } from "../../../../src/models/event";
"../../../../src/crypto/verification/request/ToDeviceChannel";
import {MatrixEvent} from "../../../../src/models/event";
describe("InRoomChannel tests", function() {
const ALICE = "@alice:hs.tld";
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import "../../../olm-loader";
import {logger} from "../../../../src/logger";
import { logger } from "../../../../src/logger";
const Olm = global.Olm;
@@ -15,10 +15,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import "../../../olm-loader";
import {verificationMethods} from "../../../../src/crypto";
import {logger} from "../../../../src/logger";
import {SAS} from "../../../../src/crypto/verification/SAS";
import {makeTestClients, setupWebcrypto, teardownWebcrypto} from './util';
import { verificationMethods } from "../../../../src/crypto";
import { logger } from "../../../../src/logger";
import { SAS } from "../../../../src/crypto/verification/SAS";
import { makeTestClients, setupWebcrypto, teardownWebcrypto } from './util';
const Olm = global.Olm;
@@ -42,14 +42,14 @@ describe("verification request integration tests with crypto layer", function()
it("should request and accept a verification", async function() {
const [alice, bob] = await makeTestClients(
[
{userId: "@alice:example.com", deviceId: "Osborne2"},
{userId: "@bob:example.com", deviceId: "Dynabook"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
{ userId: "@bob:example.com", deviceId: "Dynabook" },
],
{
verificationMethods: [verificationMethods.SAS],
},
);
alice.client._crypto._deviceList.getRawStoredDevicesForUser = function() {
alice.client.crypto.deviceList.getRawStoredDevicesForUser = function() {
return {
Dynabook: {
keys: {
@@ -69,7 +69,7 @@ describe("verification request integration tests with crypto layer", function()
bobVerifier.verify();
// XXX: Private function access (but it's a test, so we're okay)
bobVerifier._endTimer();
bobVerifier.endTimer();
});
const aliceRequest = await alice.client.requestVerification("@bob:example.com");
await aliceRequest.waitFor(r => r.started);
@@ -77,6 +77,6 @@ describe("verification request integration tests with crypto layer", function()
expect(aliceVerifier).toBeInstanceOf(SAS);
// XXX: Private function access (but it's a test, so we're okay)
aliceVerifier._endTimer();
aliceVerifier.endTimer();
});
});
+19 -19
View File
@@ -15,14 +15,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import "../../../olm-loader";
import {makeTestClients, setupWebcrypto, teardownWebcrypto} from './util';
import {MatrixEvent} from "../../../../src/models/event";
import {SAS} from "../../../../src/crypto/verification/SAS";
import {DeviceInfo} from "../../../../src/crypto/deviceinfo";
import {verificationMethods} from "../../../../src/crypto";
import { makeTestClients, setupWebcrypto, teardownWebcrypto } from './util';
import { MatrixEvent } from "../../../../src/models/event";
import { SAS } from "../../../../src/crypto/verification/SAS";
import { DeviceInfo } from "../../../../src/crypto/deviceinfo";
import { verificationMethods } from "../../../../src/crypto";
import * as olmlib from "../../../../src/crypto/olmlib";
import {logger} from "../../../../src/logger";
import {resetCrossSigningKeys} from "../crypto-utils";
import { logger } from "../../../../src/logger";
import { resetCrossSigningKeys } from "../crypto-utils";
const Olm = global.Olm;
@@ -79,16 +79,16 @@ describe("SAS verification", function() {
beforeEach(async () => {
[alice, bob] = await makeTestClients(
[
{userId: "@alice:example.com", deviceId: "Osborne2"},
{userId: "@bob:example.com", deviceId: "Dynabook"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
{ userId: "@bob:example.com", deviceId: "Dynabook" },
],
{
verificationMethods: [verificationMethods.SAS],
},
);
const aliceDevice = alice.client._crypto._olmDevice;
const bobDevice = bob.client._crypto._olmDevice;
const aliceDevice = alice.client.crypto.olmDevice;
const bobDevice = bob.client.crypto.olmDevice;
ALICE_DEVICES = {
Osborne2: {
@@ -114,14 +114,14 @@ describe("SAS verification", function() {
},
};
alice.client._crypto._deviceList.storeDevicesForUser(
alice.client.crypto.deviceList.storeDevicesForUser(
"@bob:example.com", BOB_DEVICES,
);
alice.client.downloadKeys = () => {
return Promise.resolve();
};
bob.client._crypto._deviceList.storeDevicesForUser(
bob.client.crypto.deviceList.storeDevicesForUser(
"@alice:example.com", ALICE_DEVICES,
);
bob.client.downloadKeys = () => {
@@ -296,9 +296,9 @@ describe("SAS verification", function() {
await resetCrossSigningKeys(bob.client);
bob.client._crypto._deviceList.storeCrossSigningForUser(
bob.client.crypto.deviceList.storeCrossSigningForUser(
"@alice:example.com", {
keys: alice.client._crypto._crossSigningInfo.keys,
keys: alice.client.crypto.crossSigningInfo.keys,
},
);
@@ -336,8 +336,8 @@ describe("SAS verification", function() {
it("should send a cancellation message on error", async function() {
const [alice, bob] = await makeTestClients(
[
{userId: "@alice:example.com", deviceId: "Osborne2"},
{userId: "@bob:example.com", deviceId: "Dynabook"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
{ userId: "@bob:example.com", deviceId: "Dynabook" },
],
{
verificationMethods: [verificationMethods.SAS],
@@ -390,8 +390,8 @@ describe("SAS verification", function() {
beforeEach(async function() {
[alice, bob] = await makeTestClients(
[
{userId: "@alice:example.com", deviceId: "Osborne2"},
{userId: "@bob:example.com", deviceId: "Dynabook"},
{ userId: "@alice:example.com", deviceId: "Osborne2" },
{ userId: "@bob:example.com", deviceId: "Dynabook" },
],
{
verificationMethods: [verificationMethods.SAS],
@@ -14,10 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {VerificationBase} from '../../../../src/crypto/verification/Base';
import {CrossSigningInfo} from '../../../../src/crypto/CrossSigning';
import {encodeBase64} from "../../../../src/crypto/olmlib";
import {setupWebcrypto, teardownWebcrypto} from './util';
import { VerificationBase } from '../../../../src/crypto/verification/Base';
import { CrossSigningInfo } from '../../../../src/crypto/CrossSigning';
import { encodeBase64 } from "../../../../src/crypto/olmlib";
import { setupWebcrypto, teardownWebcrypto } from './util';
jest.useFakeTimers();
@@ -48,18 +48,18 @@ describe("self-verifications", () => {
storeCrossSigningKeyCache: jest.fn(),
};
const _crossSigningInfo = new CrossSigningInfo(
const crossSigningInfo = new CrossSigningInfo(
userId,
{},
cacheCallbacks,
);
_crossSigningInfo.keys = {
crossSigningInfo.keys = {
master: { keys: { X: testKeyPub } },
self_signing: { keys: { X: testKeyPub } },
user_signing: { keys: { X: testKeyPub } },
};
const _secretStorage = {
const secretStorage = {
request: jest.fn().mockReturnValue({
promise: Promise.resolve(encodeBase64(testKey)),
}),
@@ -69,13 +69,13 @@ describe("self-verifications", () => {
const restoreKeyBackupWithCache = jest.fn(() => Promise.resolve());
const client = {
_crypto: {
_crossSigningInfo,
_secretStorage,
crypto: {
crossSigningInfo,
secretStorage,
storeSessionBackupPrivateKey,
getSessionBackupPrivateKey: () => null,
},
requestSecret: _secretStorage.request.bind(_secretStorage),
requestSecret: secretStorage.request.bind(secretStorage),
getUserId: () => userId,
getKeyBackupVersion: () => Promise.resolve({}),
restoreKeyBackupWithCache,
@@ -93,13 +93,13 @@ describe("self-verifications", () => {
undefined, // startEvent
request,
);
verification._resolve = () => undefined;
verification.resolve = () => undefined;
const result = await verification.done();
/* We should request, and store, 3 cross signing keys and the key backup key */
expect(cacheCallbacks.storeCrossSigningKeyCache.mock.calls.length).toBe(3);
expect(_secretStorage.request.mock.calls.length).toBe(4);
expect(secretStorage.request.mock.calls.length).toBe(4);
expect(cacheCallbacks.storeCrossSigningKeyCache.mock.calls[0][1])
.toEqual(testKey);
+11 -10
View File
@@ -15,10 +15,11 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {TestClient} from '../../../TestClient';
import {MatrixEvent} from "../../../../src/models/event";
import nodeCrypto from "crypto";
import {logger} from '../../../../src/logger';
import { TestClient } from '../../../TestClient';
import { MatrixEvent } from "../../../../src/models/event";
import { logger } from '../../../../src/logger';
export async function makeTestClients(userInfos, options) {
const clients = [];
@@ -30,13 +31,13 @@ export async function makeTestClients(userInfos, options) {
for (const [deviceId, msg] of Object.entries(devMap)) {
if (deviceId in clientMap[userId]) {
const event = new MatrixEvent({
sender: this.getUserId(), // eslint-disable-line babel/no-invalid-this
sender: this.getUserId(), // eslint-disable-line @babel/no-invalid-this
type: type,
content: msg,
});
const client = clientMap[userId][deviceId];
const decryptionPromise = event.isEncrypted() ?
event.attemptDecryption(client._crypto) :
event.attemptDecryption(client.crypto) :
Promise.resolve();
decryptionPromise.then(
@@ -49,9 +50,9 @@ export async function makeTestClients(userInfos, options) {
};
const sendEvent = function(room, type, content) {
// make up a unique ID as the event ID
const eventId = "$" + this.makeTxnId(); // eslint-disable-line babel/no-invalid-this
const eventId = "$" + this.makeTxnId(); // eslint-disable-line @babel/no-invalid-this
const rawEvent = {
sender: this.getUserId(), // eslint-disable-line babel/no-invalid-this
sender: this.getUserId(), // eslint-disable-line @babel/no-invalid-this
type: type,
content: content,
room_id: room,
@@ -61,13 +62,13 @@ export async function makeTestClients(userInfos, options) {
const event = new MatrixEvent(rawEvent);
const remoteEcho = new MatrixEvent(Object.assign({}, rawEvent, {
unsigned: {
transaction_id: this.makeTxnId(), // eslint-disable-line babel/no-invalid-this
transaction_id: this.makeTxnId(), // eslint-disable-line @babel/no-invalid-this
},
}));
setImmediate(() => {
for (const tc of clients) {
if (tc.client === this) { // eslint-disable-line babel/no-invalid-this
if (tc.client === this) { // eslint-disable-line @babel/no-invalid-this
logger.log("sending remote echo!!");
tc.client.emit("Room.timeline", remoteEcho);
} else {
@@ -76,7 +77,7 @@ export async function makeTestClients(userInfos, options) {
}
});
return Promise.resolve({event_id: eventId});
return Promise.resolve({ event_id: eventId });
};
for (const userInfo of userInfos) {
@@ -13,13 +13,13 @@ 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 {VerificationRequest, READY_TYPE, START_TYPE, DONE_TYPE} from
import { VerificationRequest, READY_TYPE, START_TYPE, DONE_TYPE } from
"../../../../src/crypto/verification/request/VerificationRequest";
import {InRoomChannel} from "../../../../src/crypto/verification/request/InRoomChannel";
import {ToDeviceChannel} from
import { InRoomChannel } from "../../../../src/crypto/verification/request/InRoomChannel";
import { ToDeviceChannel } from
"../../../../src/crypto/verification/request/ToDeviceChannel";
import {MatrixEvent} from "../../../../src/models/event";
import {setupWebcrypto, teardownWebcrypto} from "./util";
import { MatrixEvent } from "../../../../src/models/event";
import { setupWebcrypto, teardownWebcrypto } from "./util";
function makeMockClient(userId, deviceId) {
let counter = 1;
@@ -40,7 +40,7 @@ function makeMockClient(userId, deviceId) {
content,
origin_server_ts: Date.now(),
}));
return Promise.resolve({event_id: eventId});
return Promise.resolve({ event_id: eventId });
},
sendToDevice(type, msgMap) {
@@ -48,7 +48,7 @@ function makeMockClient(userId, deviceId) {
const deviceMap = msgMap[userId];
for (const deviceId of Object.keys(deviceMap)) {
const content = deviceMap[deviceId];
const event = new MatrixEvent({content, type});
const event = new MatrixEvent({ content, type });
deviceEvents[userId] = deviceEvents[userId] || {};
deviceEvents[userId][deviceId] = deviceEvents[userId][deviceId] || [];
deviceEvents[userId][deviceId].push(event);
@@ -90,7 +90,7 @@ class MockVerifier {
if (this._startEvent) {
await this._channel.send(DONE_TYPE, {});
} else {
await this._channel.send(START_TYPE, {method: MOCK_METHOD});
await this._channel.send(START_TYPE, { method: MOCK_METHOD });
}
}
@@ -226,7 +226,7 @@ describe("verification request unit tests", function() {
new ToDeviceChannel(bob1, bob1.getUserId(), ["device1", "device2"],
ToDeviceChannel.makeTransactionId(), "device2"),
new Map([[MOCK_METHOD, MockVerifier]]), bob1);
const to = {userId: "@bob:matrix.tld", deviceId: "device2"};
const to = { userId: "@bob:matrix.tld", deviceId: "device2" };
const verifier = bob1Request.beginKeyVerification(MOCK_METHOD, to);
expect(verifier).toBeInstanceOf(MockVerifier);
await verifier.start();
+11 -13
View File
@@ -1,10 +1,10 @@
import * as utils from "../test-utils";
import {EventTimeline} from "../../src/models/event-timeline";
import {RoomState} from "../../src/models/room-state";
import { EventTimeline } from "../../src/models/event-timeline";
import { RoomState } from "../../src/models/room-state";
function mockRoomStates(timeline) {
timeline._startState = utils.mock(RoomState, "startState");
timeline._endState = utils.mock(RoomState, "endState");
timeline.startState = utils.mock(RoomState, "startState");
timeline.endState = utils.mock(RoomState, "endState");
}
describe("EventTimeline", function() {
@@ -15,7 +15,7 @@ describe("EventTimeline", function() {
beforeEach(function() {
// XXX: this is a horrid hack; should use sinon or something instead to mock
const timelineSet = { room: { roomId: roomId }};
const timelineSet = { room: { roomId: roomId } };
timelineSet.room.getUnfilteredTimelineSet = function() {
return timelineSet;
};
@@ -48,10 +48,10 @@ describe("EventTimeline", function() {
}),
];
timeline.initialiseState(events);
expect(timeline._startState.setStateEvents).toHaveBeenCalledWith(
expect(timeline.startState.setStateEvents).toHaveBeenCalledWith(
events,
);
expect(timeline._endState.setStateEvents).toHaveBeenCalledWith(
expect(timeline.endState.setStateEvents).toHaveBeenCalledWith(
events,
);
});
@@ -94,7 +94,6 @@ describe("EventTimeline", function() {
});
});
describe("neighbouringTimelines", function() {
it("neighbouring timelines should start null", function() {
expect(timeline.getNeighbouringTimeline(EventTimeline.BACKWARDS)).toBe(null);
@@ -102,8 +101,8 @@ describe("EventTimeline", function() {
});
it("setNeighbouringTimeline should set neighbour", function() {
const prev = {a: "a"};
const next = {b: "b"};
const prev = { a: "a" };
const next = { b: "b" };
timeline.setNeighbouringTimeline(prev, EventTimeline.BACKWARDS);
timeline.setNeighbouringTimeline(next, EventTimeline.FORWARDS);
expect(timeline.getNeighbouringTimeline(EventTimeline.BACKWARDS)).toBe(prev);
@@ -111,8 +110,8 @@ describe("EventTimeline", function() {
});
it("setNeighbouringTimeline should throw if called twice", function() {
const prev = {a: "a"};
const next = {b: "b"};
const prev = { a: "a" };
const next = { b: "b" };
expect(function() {
timeline.setNeighbouringTimeline(prev, EventTimeline.BACKWARDS);
}).not.toThrow();
@@ -278,7 +277,6 @@ describe("EventTimeline", function() {
not.toHaveBeenCalled();
});
it("should call setStateEvents on the right RoomState with the right " +
"forwardLooking value for old events", function() {
const events = [
+2 -2
View File
@@ -15,8 +15,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {logger} from "../../src/logger";
import {MatrixEvent} from "../../src/models/event";
import { logger } from "../../src/logger";
import { MatrixEvent } from "../../src/models/event";
describe("MatrixEvent", () => {
describe(".attemptDecryption", () => {
+2 -2
View File
@@ -1,5 +1,5 @@
import {FilterComponent} from "../../src/filter-component";
import {mkEvent} from '../test-utils';
import { FilterComponent } from "../../src/filter-component";
import { mkEvent } from '../test-utils';
describe("Filter Component", function() {
describe("types", function() {
+1 -1
View File
@@ -1,4 +1,4 @@
import {Filter} from "../../src/filter";
import { Filter } from "../../src/filter";
describe("Filter", function() {
const filterId = "f1lt3ring15g00d4ursoul";
+5 -5
View File
@@ -15,9 +15,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {logger} from "../../src/logger";
import {InteractiveAuth} from "../../src/interactive-auth";
import {MatrixError} from "../../src/http-api";
import { logger } from "../../src/logger";
import { InteractiveAuth } from "../../src/interactive-auth";
import { MatrixError } from "../../src/http-api";
// Trivial client object to test interactive auth
// (we do not need TestClient here)
@@ -63,7 +63,7 @@ describe("InteractiveAuth", function() {
});
// .. which should trigger a call here
const requestRes = {"a": "b"};
const requestRes = { "a": "b" };
doRequest.mockImplementation(function(authData) {
logger.log('cccc');
expect(authData).toEqual({
@@ -112,7 +112,7 @@ describe("InteractiveAuth", function() {
});
// .. which should be followed by a call to stateUpdated
const requestRes = {"a": "b"};
const requestRes = { "a": "b" };
stateUpdated.mockImplementation(function(stage) {
expect(stage).toEqual("logintype");
expect(ia.getSessionId()).toEqual("sessionId");
+1 -1
View File
@@ -1,4 +1,4 @@
import {TestClient} from '../TestClient';
import { TestClient } from '../TestClient';
describe('Login request', function() {
let client;
+216 -9
View File
@@ -1,6 +1,18 @@
import {logger} from "../../src/logger";
import {MatrixClient} from "../../src/client";
import {Filter} from "../../src/filter";
import { logger } from "../../src/logger";
import { MatrixClient } from "../../src/client";
import { Filter } from "../../src/filter";
import { DEFAULT_TREE_POWER_LEVELS_TEMPLATE } from "../../src/models/MSC3089TreeSpace";
import {
EventType,
RoomCreateTypeField,
RoomType,
UNSTABLE_MSC3088_ENABLED,
UNSTABLE_MSC3088_PURPOSE,
UNSTABLE_MSC3089_TREE_SUBTYPE,
} from "../../src/@types/event";
import { MEGOLM_ALGORITHM } from "../../src/crypto/olmlib";
import { MatrixEvent } from "../../src/models/event";
import { Preset } from "../../src/@types/partials";
jest.useFakeTimers();
@@ -144,12 +156,12 @@ describe("MatrixClient", function() {
scheduler: scheduler,
userId: userId,
});
// FIXME: We shouldn't be yanking _http like this.
client._http = [
// FIXME: We shouldn't be yanking http like this.
client.http = [
"authedRequest", "getContentUri", "request", "uploadContent",
].reduce((r, k) => { r[k] = jest.fn(); return r; }, {});
client._http.authedRequest.mockImplementation(httpReq);
client._http.request.mockImplementation(httpReq);
client.http.authedRequest.mockImplementation(httpReq);
client.http.request.mockImplementation(httpReq);
// set reasonable working defaults
acceptKeepalives = true;
@@ -166,11 +178,191 @@ describe("MatrixClient", function() {
// means they may call /events and then fail an expect() which will fail
// a DIFFERENT test (pollution between tests!) - we return unresolved
// promises to stop the client from continuing to run.
client._http.authedRequest.mockImplementation(function() {
client.http.authedRequest.mockImplementation(function() {
return new Promise(() => {});
});
});
it("should create (unstable) file trees", async () => {
const userId = "@test:example.org";
const roomId = "!room:example.org";
const roomName = "Test Tree";
const mockRoom = {};
const fn = jest.fn().mockImplementation((opts) => {
expect(opts).toMatchObject({
name: roomName,
preset: Preset.PrivateChat,
power_level_content_override: {
...DEFAULT_TREE_POWER_LEVELS_TEMPLATE,
users: {
[userId]: 100,
},
},
creation_content: {
[RoomCreateTypeField]: RoomType.Space,
},
initial_state: [
{
// We use `unstable` to ensure that the code is actually using the right identifier
type: UNSTABLE_MSC3088_PURPOSE.unstable,
state_key: UNSTABLE_MSC3089_TREE_SUBTYPE.unstable,
content: {
[UNSTABLE_MSC3088_ENABLED.unstable]: true,
},
},
{
type: EventType.RoomEncryption,
state_key: "",
content: {
algorithm: MEGOLM_ALGORITHM,
},
},
],
});
return { room_id: roomId };
});
client.getUserId = () => userId;
client.createRoom = fn;
client.getRoom = (getRoomId) => {
expect(getRoomId).toEqual(roomId);
return mockRoom;
};
const tree = await client.unstableCreateFileTree(roomName);
expect(tree).toBeDefined();
expect(tree.roomId).toEqual(roomId);
expect(tree.room).toBe(mockRoom);
expect(fn.mock.calls.length).toBe(1);
});
it("should get (unstable) file trees with valid state", async () => {
const roomId = "!room:example.org";
const mockRoom = {
getMyMembership: () => "join",
currentState: {
getStateEvents: (eventType, stateKey) => {
if (eventType === EventType.RoomCreate) {
expect(stateKey).toEqual("");
return new MatrixEvent({
content: {
[RoomCreateTypeField]: RoomType.Space,
},
});
} else if (eventType === UNSTABLE_MSC3088_PURPOSE.unstable) {
// We use `unstable` to ensure that the code is actually using the right identifier
expect(stateKey).toEqual(UNSTABLE_MSC3089_TREE_SUBTYPE.unstable);
return new MatrixEvent({
content: {
[UNSTABLE_MSC3088_ENABLED.unstable]: true,
},
});
} else {
throw new Error("Unexpected event type or state key");
}
},
},
};
client.getRoom = (getRoomId) => {
expect(getRoomId).toEqual(roomId);
return mockRoom;
};
const tree = client.unstableGetFileTreeSpace(roomId);
expect(tree).toBeDefined();
expect(tree.roomId).toEqual(roomId);
expect(tree.room).toBe(mockRoom);
});
it("should not get (unstable) file trees if not joined", async () => {
const roomId = "!room:example.org";
const mockRoom = {
getMyMembership: () => "leave", // "not join"
};
client.getRoom = (getRoomId) => {
expect(getRoomId).toEqual(roomId);
return mockRoom;
};
const tree = client.unstableGetFileTreeSpace(roomId);
expect(tree).toBeFalsy();
});
it("should not get (unstable) file trees for unknown rooms", async () => {
const roomId = "!room:example.org";
client.getRoom = (getRoomId) => {
expect(getRoomId).toEqual(roomId);
return null; // imply unknown
};
const tree = client.unstableGetFileTreeSpace(roomId);
expect(tree).toBeFalsy();
});
it("should not get (unstable) file trees with invalid create contents", async () => {
const roomId = "!room:example.org";
const mockRoom = {
getMyMembership: () => "join",
currentState: {
getStateEvents: (eventType, stateKey) => {
if (eventType === EventType.RoomCreate) {
expect(stateKey).toEqual("");
return new MatrixEvent({
content: {
[RoomCreateTypeField]: "org.example.not_space",
},
});
} else if (eventType === UNSTABLE_MSC3088_PURPOSE.unstable) {
// We use `unstable` to ensure that the code is actually using the right identifier
expect(stateKey).toEqual(UNSTABLE_MSC3089_TREE_SUBTYPE.unstable);
return new MatrixEvent({
content: {
[UNSTABLE_MSC3088_ENABLED.unstable]: true,
},
});
} else {
throw new Error("Unexpected event type or state key");
}
},
},
};
client.getRoom = (getRoomId) => {
expect(getRoomId).toEqual(roomId);
return mockRoom;
};
const tree = client.unstableGetFileTreeSpace(roomId);
expect(tree).toBeFalsy();
});
it("should not get (unstable) file trees with invalid purpose/subtype contents", async () => {
const roomId = "!room:example.org";
const mockRoom = {
getMyMembership: () => "join",
currentState: {
getStateEvents: (eventType, stateKey) => {
if (eventType === EventType.RoomCreate) {
expect(stateKey).toEqual("");
return new MatrixEvent({
content: {
[RoomCreateTypeField]: RoomType.Space,
},
});
} else if (eventType === UNSTABLE_MSC3088_PURPOSE.unstable) {
expect(stateKey).toEqual(UNSTABLE_MSC3089_TREE_SUBTYPE.unstable);
return new MatrixEvent({
content: {
[UNSTABLE_MSC3088_ENABLED.unstable]: false,
},
});
} else {
throw new Error("Unexpected event type or state key");
}
},
},
};
client.getRoom = (getRoomId) => {
expect(getRoomId).toEqual(roomId);
return mockRoom;
};
const tree = client.unstableGetFileTreeSpace(roomId);
expect(tree).toBeFalsy();
});
it("should not POST /filter if a matching filter already exists", async function() {
httpLookups = [];
httpLookups.push(PUSH_RULES_RESPONSE);
@@ -178,7 +370,7 @@ describe("MatrixClient", function() {
const filterId = "ehfewf";
store.getFilterIdByName.mockReturnValue(filterId);
const filter = new Filter(0, filterId);
filter.setDefinition({"room": {"timeline": {"limit": 8}}});
filter.setDefinition({ "room": { "timeline": { "limit": 8 } } });
store.getFilter.mockReturnValue(filter);
const syncPromise = new Promise((resolve, reject) => {
client.on("sync", function syncListener(state) {
@@ -521,4 +713,19 @@ describe("MatrixClient", function() {
xit("should be able to peek into a room using peekInRoom", function(done) {
});
});
describe("getPresence", function() {
it("should send a presence HTTP GET", function() {
httpLookups = [{
method: "GET",
path: `/presence/${encodeURIComponent(userId)}/status`,
data: {
"presence": "unavailable",
"last_active_ago": 420845,
},
}];
client.getPresence(userId);
expect(httpLookups.length).toEqual(0);
});
});
});
+331
View File
@@ -0,0 +1,331 @@
/*
Copyright 2021 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.
*/
import { IContent, MatrixClient, MatrixEvent } from "../../../src";
import { Room } from "../../../src/models/room";
import { IEncryptedFile, RelationType, UNSTABLE_MSC3089_BRANCH } from "../../../src/@types/event";
import { EventTimelineSet } from "../../../src/models/event-timeline-set";
import { EventTimeline } from "../../../src/models/event-timeline";
import { MSC3089Branch } from "../../../src/models/MSC3089Branch";
import { MSC3089TreeSpace } from "../../../src/models/MSC3089TreeSpace";
describe("MSC3089Branch", () => {
let client: MatrixClient;
// @ts-ignore - TS doesn't know that this is a type
let indexEvent: any;
let directory: MSC3089TreeSpace;
let branch: MSC3089Branch;
let branch2: MSC3089Branch;
const branchRoomId = "!room:example.org";
const fileEventId = "$file";
const fileEventId2 = "$second_file";
const staticTimelineSets = {} as EventTimelineSet;
const staticRoom = {
getUnfilteredTimelineSet: () => staticTimelineSets,
} as any as Room; // partial
beforeEach(() => {
// TODO: Use utility functions to create test rooms and clients
client = <MatrixClient>{
getRoom: (roomId: string) => {
if (roomId === branchRoomId) {
return staticRoom;
} else {
throw new Error("Unexpected fetch for unknown room");
}
},
};
indexEvent = ({
getRoomId: () => branchRoomId,
getStateKey: () => fileEventId,
});
directory = new MSC3089TreeSpace(client, branchRoomId);
branch = new MSC3089Branch(client, indexEvent, directory);
branch2 = new MSC3089Branch(client, {
getRoomId: () => branchRoomId,
getStateKey: () => fileEventId2,
} as MatrixEvent, directory);
});
it('should know the file event ID', () => {
expect(branch.id).toEqual(fileEventId);
});
it('should know if the file is active or not', () => {
indexEvent.getContent = () => ({});
expect(branch.isActive).toBe(false);
indexEvent.getContent = () => ({ active: false });
expect(branch.isActive).toBe(false);
indexEvent.getContent = () => ({ active: true });
expect(branch.isActive).toBe(true);
indexEvent.getContent = () => ({ active: "true" }); // invalid boolean, inactive
expect(branch.isActive).toBe(false);
});
it('should be able to delete the file', async () => {
const eventIdOrder = [fileEventId, fileEventId2];
const stateFn = jest.fn()
.mockImplementation((roomId: string, eventType: string, content: any, stateKey: string) => {
expect(roomId).toEqual(branchRoomId);
expect(eventType).toEqual(UNSTABLE_MSC3089_BRANCH.unstable); // test that we're definitely using the unstable value
expect(content).toMatchObject({});
expect(content['active']).toBeUndefined();
expect(stateKey).toEqual(eventIdOrder[stateFn.mock.calls.length - 1]);
return Promise.resolve(); // return value not used
});
client.sendStateEvent = stateFn;
const redactFn = jest.fn().mockImplementation((roomId: string, eventId: string) => {
expect(roomId).toEqual(branchRoomId);
expect(eventId).toEqual(eventIdOrder[stateFn.mock.calls.length - 1]);
return Promise.resolve(); // return value not used
});
client.redactEvent = redactFn;
branch.getVersionHistory = () => Promise.resolve([branch, branch2]);
branch2.getVersionHistory = () => Promise.resolve([branch2]);
await branch.delete();
expect(stateFn).toHaveBeenCalledTimes(2);
expect(redactFn).toHaveBeenCalledTimes(2);
});
it('should know its name', async () => {
const name = "My File.txt";
indexEvent.getContent = () => ({ active: true, name: name });
const res = branch.getName();
expect(res).toEqual(name);
});
it('should be able to change its name', async () => {
const name = "My File.txt";
indexEvent.getContent = () => ({ active: true, retained: true });
const stateFn = jest.fn()
.mockImplementation((roomId: string, eventType: string, content: any, stateKey: string) => {
expect(roomId).toEqual(branchRoomId);
expect(eventType).toEqual(UNSTABLE_MSC3089_BRANCH.unstable); // test that we're definitely using the unstable value
expect(content).toMatchObject({
retained: true, // canary for copying state
active: true,
name: name,
});
expect(stateKey).toEqual(fileEventId);
return Promise.resolve(); // return value not used
});
client.sendStateEvent = stateFn;
await branch.setName(name);
expect(stateFn).toHaveBeenCalledTimes(1);
});
it('should be v1 by default', () => {
indexEvent.getContent = () => ({ active: true });
const res = branch.version;
expect(res).toEqual(1);
});
it('should be vN when set', () => {
indexEvent.getContent = () => ({ active: true, version: 3 });
const res = branch.version;
expect(res).toEqual(3);
});
it('should be unlocked by default', async () => {
indexEvent.getContent = () => ({ active: true });
const res = branch.isLocked();
expect(res).toEqual(false);
});
it('should use lock status from index event', async () => {
indexEvent.getContent = () => ({ active: true, locked: true });
const res = branch.isLocked();
expect(res).toEqual(true);
});
it('should be able to change its locked status', async () => {
const locked = true;
indexEvent.getContent = () => ({ active: true, retained: true });
const stateFn = jest.fn()
.mockImplementation((roomId: string, eventType: string, content: any, stateKey: string) => {
expect(roomId).toEqual(branchRoomId);
expect(eventType).toEqual(UNSTABLE_MSC3089_BRANCH.unstable); // test that we're definitely using the unstable value
expect(content).toMatchObject({
retained: true, // canary for copying state
active: true,
locked: locked,
});
expect(stateKey).toEqual(fileEventId);
return Promise.resolve(); // return value not used
});
client.sendStateEvent = stateFn;
await branch.setLocked(locked);
expect(stateFn).toHaveBeenCalledTimes(1);
});
it('should be able to return event information', async () => {
const mxcLatter = "example.org/file";
const fileContent = { isFile: "not quite", url: "mxc://" + mxcLatter };
const fileEvent = { getId: () => fileEventId, getOriginalContent: () => ({ file: fileContent }) };
staticRoom.getUnfilteredTimelineSet = () => ({
findEventById: (eventId) => {
expect(eventId).toEqual(fileEventId);
return fileEvent;
},
}) as EventTimelineSet;
client.mxcUrlToHttp = (mxc: string) => {
expect(mxc).toEqual("mxc://" + mxcLatter);
return `https://example.org/_matrix/media/v1/download/${mxcLatter}`;
};
client.decryptEventIfNeeded = () => Promise.resolve();
const res = await branch.getFileInfo();
expect(res).toBeDefined();
expect(res).toMatchObject({
info: fileContent,
// Escape regex from MDN guides: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
httpUrl: expect.stringMatching(`.+${mxcLatter.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`),
});
});
it('should be able to return the event object', async () => {
const mxcLatter = "example.org/file";
const fileContent = { isFile: "not quite", url: "mxc://" + mxcLatter };
const fileEvent = { getId: () => fileEventId, getOriginalContent: () => ({ file: fileContent }) };
staticRoom.getUnfilteredTimelineSet = () => ({
findEventById: (eventId) => {
expect(eventId).toEqual(fileEventId);
return fileEvent;
},
}) as EventTimelineSet;
client.mxcUrlToHttp = (mxc: string) => {
expect(mxc).toEqual("mxc://" + mxcLatter);
return `https://example.org/_matrix/media/v1/download/${mxcLatter}`;
};
client.decryptEventIfNeeded = () => Promise.resolve();
const res = await branch.getFileEvent();
expect(res).toBeDefined();
expect(res).toBe(fileEvent);
});
it('should create new versions of itself', async () => {
const canaryName = "canary";
const canaryContents = "contents go here";
const canaryFile = {} as IEncryptedFile;
const canaryAddl = { canary: true };
indexEvent.getContent = () => ({ active: true, retained: true });
const stateKeyOrder = [fileEventId2, fileEventId];
const stateFn = jest.fn()
.mockImplementation((roomId: string, eventType: string, content: any, stateKey: string) => {
expect(roomId).toEqual(branchRoomId);
expect(eventType).toEqual(UNSTABLE_MSC3089_BRANCH.unstable); // test that we're definitely using the unstable value
expect(stateKey).toEqual(stateKeyOrder[stateFn.mock.calls.length - 1]);
if (stateKey === fileEventId) {
expect(content).toMatchObject({
retained: true, // canary for copying state
active: false,
});
} else if (stateKey === fileEventId2) {
expect(content).toMatchObject({
active: true,
version: 2,
name: canaryName,
});
} else {
throw new Error("Unexpected state key: " + stateKey);
}
return Promise.resolve(); // return value not used
});
client.sendStateEvent = stateFn;
const createFn = jest.fn().mockImplementation((
name: string,
contents: ArrayBuffer,
info: Partial<IEncryptedFile>,
addl: IContent,
) => {
expect(name).toEqual(canaryName);
expect(contents).toBe(canaryContents);
expect(info).toBe(canaryFile);
expect(addl).toMatchObject({
...canaryAddl,
"m.new_content": true,
"m.relates_to": {
"rel_type": RelationType.Replace,
"event_id": fileEventId,
},
});
return Promise.resolve({ event_id: fileEventId2 });
});
directory.createFile = createFn;
await branch.createNewVersion(canaryName, canaryContents, canaryFile, canaryAddl);
expect(stateFn).toHaveBeenCalledTimes(2);
expect(createFn).toHaveBeenCalledTimes(1);
});
it('should fetch file history', async () => {
branch2.getFileEvent = () => Promise.resolve({
replacingEventId: () => undefined,
getId: () => fileEventId2,
} as MatrixEvent);
branch.getFileEvent = () => Promise.resolve({
replacingEventId: () => fileEventId2,
getId: () => fileEventId,
} as MatrixEvent);
const events = [await branch.getFileEvent(), await branch2.getFileEvent(), {
replacingEventId: () => null,
getId: () => "$unknown",
}];
staticRoom.getLiveTimeline = () => ({ getEvents: () => events }) as EventTimeline;
directory.getFile = (evId: string) => {
expect(evId).toEqual(fileEventId);
return branch;
};
const results = await branch2.getVersionHistory();
expect(results).toMatchObject([
branch2,
branch,
]);
});
});
File diff suppressed because it is too large Load Diff
+60
View File
@@ -0,0 +1,60 @@
/*
Copyright 2021 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.
*/
import { MatrixEvent } from "../../../src/models/event";
describe('MatrixEvent', () => {
it('should create copies of itself', () => {
const a = new MatrixEvent({
type: "com.example.test",
content: {
isTest: true,
num: 42,
},
});
const clone = a.toSnapshot();
expect(clone).toBeDefined();
expect(clone).not.toBe(a);
expect(clone.event).not.toBe(a.event);
expect(clone.event).toMatchObject(a.event);
// The other properties we're not super interested in, honestly.
});
it('should compare itself to other events using json', () => {
const a = new MatrixEvent({
type: "com.example.test",
content: {
isTest: true,
num: 42,
},
});
const b = new MatrixEvent({
type: "com.example.test______B",
content: {
isTest: true,
num: 42,
},
});
expect(a.isEquivalentTo(b)).toBe(false);
expect(a.isEquivalentTo(a)).toBe(true);
expect(b.isEquivalentTo(a)).toBe(false);
expect(b.isEquivalentTo(b)).toBe(true);
expect(a.toSnapshot().isEquivalentTo(a)).toBe(true);
expect(a.toSnapshot().isEquivalentTo(b)).toBe(false);
});
});
+1 -1
View File
@@ -1,5 +1,5 @@
import * as utils from "../test-utils";
import {PushProcessor} from "../../src/pushprocessor";
import { PushProcessor } from "../../src/pushprocessor";
describe('NotificationService', function() {
const testUserId = "@ali:matrix.org";
+2 -2
View File
@@ -46,8 +46,8 @@ describe("realtime-callbacks", function() {
it("should set 'this' to the global object", function() {
let passed = false;
const callback = function() {
expect(this).toBe(global); // eslint-disable-line babel/no-invalid-this
expect(this.console).toBeTruthy(); // eslint-disable-line babel/no-invalid-this
expect(this).toBe(global); // eslint-disable-line @babel/no-invalid-this
expect(this.console).toBeTruthy(); // eslint-disable-line @babel/no-invalid-this
passed = true;
};
callbacks.setTimeout(callback);
+133
View File
@@ -0,0 +1,133 @@
/*
Copyright 2021 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.
*/
import { EventTimelineSet } from "../../src/models/event-timeline-set";
import { MatrixEvent } from "../../src/models/event";
import { Room } from "../../src/models/room";
import { Relations } from "../../src/models/relations";
describe("Relations", function() {
it("should deduplicate annotations", function() {
const room = new Room("room123", null, null);
const relations = new Relations("m.annotation", "m.reaction", room);
// Create an instance of an annotation
const eventData = {
"sender": "@bob:example.com",
"type": "m.reaction",
"event_id": "$cZ1biX33ENJqIm00ks0W_hgiO_6CHrsAc3ZQrnLeNTw",
"room_id": "!pzVjCQSoQPpXQeHpmK:example.com",
"content": {
"m.relates_to": {
"event_id": "$2s4yYpEkVQrPglSCSqB_m6E8vDhWsg0yFNyOJdVIb_o",
"key": "👍️",
"rel_type": "m.annotation",
},
},
};
const eventA = new MatrixEvent(eventData);
// Add the event once and check results
{
relations.addEvent(eventA);
const annotationsByKey = relations.getSortedAnnotationsByKey();
expect(annotationsByKey.length).toEqual(1);
const [key, events] = annotationsByKey[0];
expect(key).toEqual("👍️");
expect(events.size).toEqual(1);
}
// Add the event again and expect the same
{
relations.addEvent(eventA);
const annotationsByKey = relations.getSortedAnnotationsByKey();
expect(annotationsByKey.length).toEqual(1);
const [key, events] = annotationsByKey[0];
expect(key).toEqual("👍️");
expect(events.size).toEqual(1);
}
// Create a fresh object with the same event content
const eventB = new MatrixEvent(eventData);
// Add the event again and expect the same
{
relations.addEvent(eventB);
const annotationsByKey = relations.getSortedAnnotationsByKey();
expect(annotationsByKey.length).toEqual(1);
const [key, events] = annotationsByKey[0];
expect(key).toEqual("👍️");
expect(events.size).toEqual(1);
}
});
it("should emit created regardless of ordering", async function() {
const targetEvent = new MatrixEvent({
"sender": "@bob:example.com",
"type": "m.room.message",
"event_id": "$2s4yYpEkVQrPglSCSqB_m6E8vDhWsg0yFNyOJdVIb_o",
"room_id": "!pzVjCQSoQPpXQeHpmK:example.com",
"content": {},
});
const relationEvent = new MatrixEvent({
"sender": "@bob:example.com",
"type": "m.reaction",
"event_id": "$cZ1biX33ENJqIm00ks0W_hgiO_6CHrsAc3ZQrnLeNTw",
"room_id": "!pzVjCQSoQPpXQeHpmK:example.com",
"content": {
"m.relates_to": {
"event_id": "$2s4yYpEkVQrPglSCSqB_m6E8vDhWsg0yFNyOJdVIb_o",
"key": "👍️",
"rel_type": "m.annotation",
},
},
});
// Stub the room
const room = new Room("room123", null, null);
// Add the target event first, then the relation event
{
const relationsCreated = new Promise(resolve => {
targetEvent.once("Event.relationsCreated", resolve);
});
const timelineSet = new EventTimelineSet(room, {
unstableClientRelationAggregation: true,
});
timelineSet.addLiveEvent(targetEvent);
timelineSet.addLiveEvent(relationEvent);
await relationsCreated;
}
// Add the relation event first, then the target event
{
const relationsCreated = new Promise(resolve => {
targetEvent.once("Event.relationsCreated", resolve);
});
const timelineSet = new EventTimelineSet(room, {
unstableClientRelationAggregation: true,
});
timelineSet.addLiveEvent(relationEvent);
timelineSet.addLiveEvent(targetEvent);
await relationsCreated;
}
});
});
+29 -1
View File
@@ -1,5 +1,5 @@
import * as utils from "../test-utils";
import {RoomMember} from "../../src/models/room-member";
import { RoomMember } from "../../src/models/room-member";
describe("RoomMember", function() {
const roomId = "!foo:bar";
@@ -124,6 +124,34 @@ describe("RoomMember", function() {
expect(member.powerLevel).toEqual(0);
expect(emitCount).toEqual(1);
});
it("should not honor string power levels.",
function() {
const event = utils.mkEvent({
type: "m.room.power_levels",
room: roomId,
user: userA,
content: {
users_default: 20,
users: {
"@alice:bar": "5",
},
},
event: true,
});
let emitCount = 0;
member.on("RoomMember.powerLevel", function(emitEvent, emitMember) {
emitCount += 1;
expect(emitMember.userId).toEqual('@alice:bar');
expect(emitMember.powerLevel).toEqual(20);
expect(emitEvent).toEqual(event);
});
member.setPowerLevelEvent(event);
expect(member.powerLevel).toEqual(20);
expect(emitCount).toEqual(1);
});
});
describe("setTypingEvent", function() {
+40 -53
View File
@@ -1,6 +1,5 @@
import * as utils from "../test-utils";
import {RoomState} from "../../src/models/room-state";
import {RoomMember} from "../../src/models/room-member";
import { RoomState } from "../../src/models/room-state";
describe("RoomState", function() {
const roomId = "!foo:bar";
@@ -193,12 +192,7 @@ describe("RoomState", function() {
expect(emitCount).toEqual(2);
});
it("should call setPowerLevelEvent on each RoomMember for m.room.power_levels",
function() {
// mock up the room members
state.members[userA] = utils.mock(RoomMember);
state.members[userB] = utils.mock(RoomMember);
it("should call setPowerLevelEvent on each RoomMember for m.room.power_levels", function() {
const powerLevelEvent = utils.mkEvent({
type: "m.room.power_levels", room: roomId, user: userA, event: true,
content: {
@@ -208,18 +202,16 @@ describe("RoomState", function() {
},
});
// spy on the room members
jest.spyOn(state.members[userA], "setPowerLevelEvent");
jest.spyOn(state.members[userB], "setPowerLevelEvent");
state.setStateEvents([powerLevelEvent]);
expect(state.members[userA].setPowerLevelEvent).toHaveBeenCalledWith(
powerLevelEvent,
);
expect(state.members[userB].setPowerLevelEvent).toHaveBeenCalledWith(
powerLevelEvent,
);
expect(state.members[userA].setPowerLevelEvent).toHaveBeenCalledWith(powerLevelEvent);
expect(state.members[userB].setPowerLevelEvent).toHaveBeenCalledWith(powerLevelEvent);
});
it("should call setPowerLevelEvent on a new RoomMember if power levels exist",
function() {
it("should call setPowerLevelEvent on a new RoomMember if power levels exist", function() {
const memberEvent = utils.mkMembership({
mship: "join", user: userC, room: roomId, event: true,
});
@@ -243,13 +235,12 @@ describe("RoomState", function() {
});
it("should call setMembershipEvent on the right RoomMember", function() {
// mock up the room members
state.members[userA] = utils.mock(RoomMember);
state.members[userB] = utils.mock(RoomMember);
const memberEvent = utils.mkMembership({
user: userB, mship: "leave", room: roomId, event: true,
});
// spy on the room members
jest.spyOn(state.members[userA], "setMembershipEvent");
jest.spyOn(state.members[userB], "setMembershipEvent");
state.setStateEvents([memberEvent]);
expect(state.members[userA].setMembershipEvent).not.toHaveBeenCalled();
@@ -374,17 +365,13 @@ describe("RoomState", function() {
user_ids: [userA],
},
});
// mock up the room members
state.members[userA] = utils.mock(RoomMember);
state.members[userB] = utils.mock(RoomMember);
// spy on the room members
jest.spyOn(state.members[userA], "setTypingEvent");
jest.spyOn(state.members[userB], "setTypingEvent");
state.setTypingEvent(typingEvent);
expect(state.members[userA].setTypingEvent).toHaveBeenCalledWith(
typingEvent,
);
expect(state.members[userB].setTypingEvent).toHaveBeenCalledWith(
typingEvent,
);
expect(state.members[userA].setTypingEvent).toHaveBeenCalledWith(typingEvent);
expect(state.members[userB].setTypingEvent).toHaveBeenCalledWith(typingEvent);
});
});
@@ -471,13 +458,13 @@ describe("RoomState", function() {
it("should update after adding joined member", function() {
state.setStateEvents([
utils.mkMembership({event: true, mship: "join",
user: userA, room: roomId}),
utils.mkMembership({ event: true, mship: "join",
user: userA, room: roomId }),
]);
expect(state.getJoinedMemberCount()).toEqual(1);
state.setStateEvents([
utils.mkMembership({event: true, mship: "join",
user: userC, room: roomId}),
utils.mkMembership({ event: true, mship: "join",
user: userC, room: roomId }),
]);
expect(state.getJoinedMemberCount()).toEqual(2);
});
@@ -490,13 +477,13 @@ describe("RoomState", function() {
it("should update after adding invited member", function() {
state.setStateEvents([
utils.mkMembership({event: true, mship: "invite",
user: userA, room: roomId}),
utils.mkMembership({ event: true, mship: "invite",
user: userA, room: roomId }),
]);
expect(state.getInvitedMemberCount()).toEqual(1);
state.setStateEvents([
utils.mkMembership({event: true, mship: "invite",
user: userC, room: roomId}),
utils.mkMembership({ event: true, mship: "invite",
user: userC, room: roomId }),
]);
expect(state.getInvitedMemberCount()).toEqual(2);
});
@@ -509,15 +496,15 @@ describe("RoomState", function() {
it("should, once used, override counting members from state", function() {
state.setStateEvents([
utils.mkMembership({event: true, mship: "join",
user: userA, room: roomId}),
utils.mkMembership({ event: true, mship: "join",
user: userA, room: roomId }),
]);
expect(state.getJoinedMemberCount()).toEqual(1);
state.setJoinedMemberCount(100);
expect(state.getJoinedMemberCount()).toEqual(100);
state.setStateEvents([
utils.mkMembership({event: true, mship: "join",
user: userC, room: roomId}),
utils.mkMembership({ event: true, mship: "join",
user: userC, room: roomId }),
]);
expect(state.getJoinedMemberCount()).toEqual(100);
});
@@ -525,14 +512,14 @@ describe("RoomState", function() {
it("should, once used, override counting members from state, " +
"also after clone", function() {
state.setStateEvents([
utils.mkMembership({event: true, mship: "join",
user: userA, room: roomId}),
utils.mkMembership({ event: true, mship: "join",
user: userA, room: roomId }),
]);
state.setJoinedMemberCount(100);
const copy = state.clone();
copy.setStateEvents([
utils.mkMembership({event: true, mship: "join",
user: userC, room: roomId}),
utils.mkMembership({ event: true, mship: "join",
user: userC, room: roomId }),
]);
expect(state.getJoinedMemberCount()).toEqual(100);
});
@@ -545,15 +532,15 @@ describe("RoomState", function() {
it("should, once used, override counting members from state", function() {
state.setStateEvents([
utils.mkMembership({event: true, mship: "invite",
user: userB, room: roomId}),
utils.mkMembership({ event: true, mship: "invite",
user: userB, room: roomId }),
]);
expect(state.getInvitedMemberCount()).toEqual(1);
state.setInvitedMemberCount(100);
expect(state.getInvitedMemberCount()).toEqual(100);
state.setStateEvents([
utils.mkMembership({event: true, mship: "invite",
user: userC, room: roomId}),
utils.mkMembership({ event: true, mship: "invite",
user: userC, room: roomId }),
]);
expect(state.getInvitedMemberCount()).toEqual(100);
});
@@ -561,14 +548,14 @@ describe("RoomState", function() {
it("should, once used, override counting members from state, " +
"also after clone", function() {
state.setStateEvents([
utils.mkMembership({event: true, mship: "invite",
user: userB, room: roomId}),
utils.mkMembership({ event: true, mship: "invite",
user: userB, room: roomId }),
]);
state.setInvitedMemberCount(100);
const copy = state.clone();
copy.setStateEvents([
utils.mkMembership({event: true, mship: "invite",
user: userC, room: roomId}),
utils.mkMembership({ event: true, mship: "invite",
user: userC, room: roomId }),
]);
expect(state.getInvitedMemberCount()).toEqual(100);
});
+336 -38
View File
@@ -1,8 +1,10 @@
import * as utils from "../test-utils";
import {EventStatus, MatrixEvent} from "../../src/models/event";
import {EventTimeline} from "../../src/models/event-timeline";
import {RoomState} from "../../src/models/room-state";
import {Room} from "../../src/models/room";
import { DuplicateStrategy, EventStatus, MatrixEvent } from "../../src";
import { EventTimeline } from "../../src/models/event-timeline";
import { RoomState } from "../../src";
import { Room } from "../../src";
import { UNSTABLE_ELEMENT_FUNCTIONAL_USERS } from "../../src/@types/event";
import { TestClient } from "../TestClient";
describe("Room", function() {
const roomId = "!foo:bar";
@@ -15,9 +17,9 @@ describe("Room", function() {
beforeEach(function() {
room = new Room(roomId);
// mock RoomStates
room.oldState = room.getLiveTimeline()._startState =
room.oldState = room.getLiveTimeline().startState =
utils.mock(RoomState, "oldState");
room.currentState = room.getLiveTimeline()._endState =
room.currentState = room.getLiveTimeline().endState =
utils.mock(RoomState, "currentState");
});
@@ -85,9 +87,11 @@ describe("Room", function() {
];
it("should call RoomState.setTypingEvent on m.typing events", function() {
room.currentState = utils.mock(RoomState);
const typing = utils.mkEvent({
room: roomId, type: "m.typing", event: true, content: {
room: roomId,
type: "m.typing",
event: true,
content: {
user_ids: [userA],
},
});
@@ -109,7 +113,7 @@ describe("Room", function() {
dupe.event.event_id = events[0].getId();
room.addLiveEvents(events);
expect(room.timeline[0]).toEqual(events[0]);
room.addLiveEvents([dupe], "replace");
room.addLiveEvents([dupe], DuplicateStrategy.Replace);
expect(room.timeline[0]).toEqual(dupe);
});
@@ -139,8 +143,8 @@ describe("Room", function() {
expect(callCount).toEqual(2);
});
it("should call setStateEvents on the right RoomState with the right " +
"forwardLooking value for new events", function() {
it("should call setStateEvents on the right RoomState with the right forwardLooking value for new events",
function() {
const events = [
utils.mkMembership({
room: roomId, mship: "invite", user: userB, skey: userA, event: true,
@@ -190,7 +194,7 @@ describe("Room", function() {
const remoteEvent = utils.mkMessage({
room: roomId, user: userA, event: true,
});
remoteEvent.event.unsigned = {transaction_id: "TXN_ID"};
remoteEvent.event.unsigned = { transaction_id: "TXN_ID" };
const remoteEventId = remoteEvent.getId();
let callCount = 0;
@@ -374,7 +378,7 @@ describe("Room", function() {
let events = null;
beforeEach(function() {
room = new Room(roomId, null, null, {timelineSupport: timelineSupport});
room = new Room(roomId, null, null, { timelineSupport: timelineSupport });
// set events each time to avoid resusing Event objects (which
// doesn't work because they get frozen)
events = [
@@ -456,7 +460,7 @@ describe("Room", function() {
describe("compareEventOrdering", function() {
beforeEach(function() {
room = new Room(roomId, null, null, {timelineSupport: true});
room = new Room(roomId, null, null, { timelineSupport: true });
});
const events = [
@@ -651,7 +655,8 @@ describe("Room", function() {
const roomName = "flibble";
const event = addMember(userA, "invite");
event.event.invite_room_state = [
event.event.unsigned = {};
event.event.unsigned.invite_room_state = [
{
type: "m.room.name",
state_key: "",
@@ -670,7 +675,8 @@ describe("Room", function() {
const roomName = "flibble";
setRoomName(roomName);
const roomNameToIgnore = "ignoreme";
event.event.invite_room_state = [
event.event.unsigned = {};
event.event.unsigned.invite_room_state = [
{
type: "m.room.name",
state_key: "",
@@ -712,7 +718,7 @@ describe("Room", function() {
it("uses hero name from state", function() {
const name = "Mr B";
addMember(userA, "invite");
addMember(userB, "join", {name});
addMember(userB, "join", { name });
room.setSummary({
"m.heroes": [userB],
});
@@ -723,7 +729,7 @@ describe("Room", function() {
it("uses counts from summary", function() {
const name = "Mr B";
addMember(userB, "join", {name});
addMember(userB, "join", { name });
room.setSummary({
"m.heroes": [userB],
"m.joined_member_count": 50,
@@ -736,8 +742,8 @@ describe("Room", function() {
it("relies on heroes in case of absent counts", function() {
const nameB = "Mr Bean";
const nameC = "Mel C";
addMember(userB, "join", {name: nameB});
addMember(userC, "join", {name: nameC});
addMember(userB, "join", { name: nameB });
addMember(userC, "join", { name: nameC });
room.setSummary({
"m.heroes": [userB, userC],
});
@@ -747,7 +753,7 @@ describe("Room", function() {
it("uses only heroes", function() {
const nameB = "Mr Bean";
addMember(userB, "join", {name: nameB});
addMember(userB, "join", { name: nameB });
addMember(userC, "join");
room.setSummary({
"m.heroes": [userB],
@@ -840,7 +846,7 @@ describe("Room", function() {
it("should show the other user's name for private" +
" (invite join_rules) rooms if you are invited to it.", function() {
setJoinRule("invite");
addMember(userA, "invite", {user: userB});
addMember(userA, "invite", { user: userB });
addMember(userB);
room.recalculate();
const name = room.name;
@@ -915,8 +921,8 @@ describe("Room", function() {
"available",
function() {
setJoinRule("invite");
addMember(userB, 'join', {name: "Alice"});
addMember(userA, "invite", {user: userA});
addMember(userB, 'join', { name: "Alice" });
addMember(userA, "invite", { user: userA });
room.recalculate();
const name = room.name;
expect(name).toEqual("Alice");
@@ -926,7 +932,7 @@ describe("Room", function() {
function() {
setJoinRule("invite");
addMember(userB);
addMember(userA, "invite", {user: userA});
addMember(userA, "invite", { user: userA });
room.recalculate();
const name = room.name;
expect(name).toEqual(userB);
@@ -1176,7 +1182,10 @@ describe("Room", function() {
describe("addPendingEvent", function() {
it("should add pending events to the pendingEventList if " +
"pendingEventOrdering == 'detached'", function() {
const room = new Room(roomId, null, userA, {
const client = (new TestClient(
"@alice:example.com", "alicedevice",
)).client;
const room = new Room(roomId, client, userA, {
pendingEventOrdering: "detached",
});
const eventA = utils.mkMessage({
@@ -1226,7 +1235,10 @@ describe("Room", function() {
describe("updatePendingEvent", function() {
it("should remove cancelled events from the pending list", function() {
const room = new Room(roomId, null, userA, {
const client = (new TestClient(
"@alice:example.com", "alicedevice",
)).client;
const room = new Room(roomId, client, userA, {
pendingEventOrdering: "detached",
});
const eventA = utils.mkMessage({
@@ -1260,7 +1272,6 @@ describe("Room", function() {
expect(callCount).toEqual(1);
});
it("should remove cancelled events from the timeline", function() {
const room = new Room(roomId, null, userA);
const eventA = utils.mkMessage({
@@ -1308,13 +1319,13 @@ describe("Room", function() {
isRoomEncrypted: function() {
return false;
},
_http: {
http: {
serverResponse,
authedRequest: function() {
if (this.serverResponse instanceof Error) {
return Promise.reject(this.serverResponse);
} else {
return Promise.resolve({chunk: this.serverResponse});
return Promise.resolve({ chunk: this.serverResponse });
}
},
},
@@ -1344,7 +1355,7 @@ describe("Room", function() {
it("should load members from server on first call", async function() {
const client = createClientMock([memberEvent]);
const room = new Room(roomId, client, null, {lazyLoadMembers: true});
const room = new Room(roomId, client, null, { lazyLoadMembers: true });
await room.loadMembersIfNeeded();
const memberA = room.getMember("@user_a:bar");
expect(memberA.name).toEqual("User A");
@@ -1359,7 +1370,7 @@ describe("Room", function() {
room: roomId, event: true, name: "Ms A",
});
const client = createClientMock([memberEvent2], [memberEvent]);
const room = new Room(roomId, client, null, {lazyLoadMembers: true});
const room = new Room(roomId, client, null, { lazyLoadMembers: true });
await room.loadMembersIfNeeded();
@@ -1369,7 +1380,7 @@ describe("Room", function() {
it("should allow retry on error", async function() {
const client = createClientMock(new Error("server says no"));
const room = new Room(roomId, client, null, {lazyLoadMembers: true});
const room = new Room(roomId, client, null, { lazyLoadMembers: true });
let hasThrown = false;
try {
await room.loadMembersIfNeeded();
@@ -1378,7 +1389,7 @@ describe("Room", function() {
}
expect(hasThrown).toEqual(true);
client._http.serverResponse = [memberEvent];
client.http.serverResponse = [memberEvent];
await room.loadMembersIfNeeded();
const memberA = room.getMember("@user_a:bar");
expect(memberA.name).toEqual("User A");
@@ -1397,17 +1408,17 @@ describe("Room", function() {
const room = new Room(roomId, null, userA);
const events = [];
room.on("Room.myMembership", (_room, membership, oldMembership) => {
events.push({membership, oldMembership});
events.push({ membership, oldMembership });
});
room.updateMyMembership("invite");
expect(room.getMyMembership()).toEqual("invite");
expect(events[0]).toEqual({membership: "invite", oldMembership: null});
expect(events[0]).toEqual({ membership: "invite", oldMembership: null });
events.splice(0); //clear
room.updateMyMembership("invite");
expect(events.length).toEqual(0);
room.updateMyMembership("join");
expect(room.getMyMembership()).toEqual("join");
expect(events[0]).toEqual({membership: "join", oldMembership: "invite"});
expect(events[0]).toEqual({ membership: "join", oldMembership: "invite" });
});
});
@@ -1415,7 +1426,7 @@ describe("Room", function() {
it("should return first hero id",
function() {
const room = new Room(roomId, null, userA);
room.setSummary({'m.heroes': [userB]});
room.setSummary({ 'm.heroes': [userB] });
expect(room.guessDMUserId()).toEqual(userB);
});
it("should return first member that isn't self",
@@ -1446,4 +1457,291 @@ describe("Room", function() {
expect(room.maySendMessage()).toEqual(true);
});
});
describe("getDefaultRoomName", function() {
it("should return 'Empty room' if a user is the only member",
function() {
const room = new Room(roomId, null, userA);
expect(room.getDefaultRoomName(userA)).toEqual("Empty room");
});
it("should return a display name if one other member is in the room",
function() {
const room = new Room(roomId, null, userA);
room.addLiveEvents([
utils.mkMembership({
user: userA, mship: "join",
room: roomId, event: true, name: "User A",
}),
utils.mkMembership({
user: userB, mship: "join",
room: roomId, event: true, name: "User B",
}),
]);
expect(room.getDefaultRoomName(userA)).toEqual("User B");
});
it("should return a display name if one other member is banned",
function() {
const room = new Room(roomId, null, userA);
room.addLiveEvents([
utils.mkMembership({
user: userA, mship: "join",
room: roomId, event: true, name: "User A",
}),
utils.mkMembership({
user: userB, mship: "ban",
room: roomId, event: true, name: "User B",
}),
]);
expect(room.getDefaultRoomName(userA)).toEqual("Empty room (was User B)");
});
it("should return a display name if one other member is invited",
function() {
const room = new Room(roomId, null, userA);
room.addLiveEvents([
utils.mkMembership({
user: userA, mship: "join",
room: roomId, event: true, name: "User A",
}),
utils.mkMembership({
user: userB, mship: "invite",
room: roomId, event: true, name: "User B",
}),
]);
expect(room.getDefaultRoomName(userA)).toEqual("User B");
});
it("should return 'Empty room (was User B)' if User B left the room",
function() {
const room = new Room(roomId, null, userA);
room.addLiveEvents([
utils.mkMembership({
user: userA, mship: "join",
room: roomId, event: true, name: "User A",
}),
utils.mkMembership({
user: userB, mship: "leave",
room: roomId, event: true, name: "User B",
}),
]);
expect(room.getDefaultRoomName(userA)).toEqual("Empty room (was User B)");
});
it("should return 'User B and User C' if in a room with two other users",
function() {
const room = new Room(roomId, null, userA);
room.addLiveEvents([
utils.mkMembership({
user: userA, mship: "join",
room: roomId, event: true, name: "User A",
}),
utils.mkMembership({
user: userB, mship: "join",
room: roomId, event: true, name: "User B",
}),
utils.mkMembership({
user: userC, mship: "join",
room: roomId, event: true, name: "User C",
}),
]);
expect(room.getDefaultRoomName(userA)).toEqual("User B and User C");
});
it("should return 'User B and 2 others' if in a room with three other users",
function() {
const room = new Room(roomId, null, userA);
room.addLiveEvents([
utils.mkMembership({
user: userA, mship: "join",
room: roomId, event: true, name: "User A",
}),
utils.mkMembership({
user: userB, mship: "join",
room: roomId, event: true, name: "User B",
}),
utils.mkMembership({
user: userC, mship: "join",
room: roomId, event: true, name: "User C",
}),
utils.mkMembership({
user: userD, mship: "join",
room: roomId, event: true, name: "User D",
}),
]);
expect(room.getDefaultRoomName(userA)).toEqual("User B and 2 others");
});
describe("io.element.functional_users", function() {
it("should return a display name (default behaviour) if no one is marked as a functional member",
function() {
const room = new Room(roomId, null, userA);
room.addLiveEvents([
utils.mkMembership({
user: userA, mship: "join",
room: roomId, event: true, name: "User A",
}),
utils.mkMembership({
user: userB, mship: "join",
room: roomId, event: true, name: "User B",
}),
utils.mkEvent({
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.name, skey: "",
room: roomId, event: true,
content: {
service_members: [],
},
}),
]);
expect(room.getDefaultRoomName(userA)).toEqual("User B");
});
it("should return a display name (default behaviour) if service members is a number (invalid)",
function() {
const room = new Room(roomId, null, userA);
room.addLiveEvents([
utils.mkMembership({
user: userA, mship: "join",
room: roomId, event: true, name: "User A",
}),
utils.mkMembership({
user: userB, mship: "join",
room: roomId, event: true, name: "User B",
}),
utils.mkEvent({
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.name, skey: "",
room: roomId, event: true,
content: {
service_members: 1,
},
}),
]);
expect(room.getDefaultRoomName(userA)).toEqual("User B");
});
it("should return a display name (default behaviour) if service members is a string (invalid)",
function() {
const room = new Room(roomId, null, userA);
room.addLiveEvents([
utils.mkMembership({
user: userA, mship: "join",
room: roomId, event: true, name: "User A",
}),
utils.mkMembership({
user: userB, mship: "join",
room: roomId, event: true, name: "User B",
}),
utils.mkEvent({
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.name, skey: "",
room: roomId, event: true,
content: {
service_members: userB,
},
}),
]);
expect(room.getDefaultRoomName(userA)).toEqual("User B");
});
it("should return 'Empty room' if the only other member is a functional member",
function() {
const room = new Room(roomId, null, userA);
room.addLiveEvents([
utils.mkMembership({
user: userA, mship: "join",
room: roomId, event: true, name: "User A",
}),
utils.mkMembership({
user: userB, mship: "join",
room: roomId, event: true, name: "User B",
}),
utils.mkEvent({
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.name, skey: "",
room: roomId, event: true,
content: {
service_members: [userB],
},
}),
]);
expect(room.getDefaultRoomName(userA)).toEqual("Empty room");
});
it("should return 'User B' if User B is the only other member who isn't a functional member",
function() {
const room = new Room(roomId, null, userA);
room.addLiveEvents([
utils.mkMembership({
user: userA, mship: "join",
room: roomId, event: true, name: "User A",
}),
utils.mkMembership({
user: userB, mship: "join",
room: roomId, event: true, name: "User B",
}),
utils.mkMembership({
user: userC, mship: "join",
room: roomId, event: true, name: "User C",
}),
utils.mkEvent({
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.name, skey: "",
room: roomId, event: true, user: userA,
content: {
service_members: [userC],
},
}),
]);
expect(room.getDefaultRoomName(userA)).toEqual("User B");
});
it("should return 'Empty room' if all other members are functional members",
function() {
const room = new Room(roomId, null, userA);
room.addLiveEvents([
utils.mkMembership({
user: userA, mship: "join",
room: roomId, event: true, name: "User A",
}),
utils.mkMembership({
user: userB, mship: "join",
room: roomId, event: true, name: "User B",
}),
utils.mkMembership({
user: userC, mship: "join",
room: roomId, event: true, name: "User C",
}),
utils.mkEvent({
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.name, skey: "",
room: roomId, event: true, user: userA,
content: {
service_members: [userB, userC],
},
}),
]);
expect(room.getDefaultRoomName(userA)).toEqual("Empty room");
});
it("should not break if an unjoined user is marked as a service user",
function() {
const room = new Room(roomId, null, userA);
room.addLiveEvents([
utils.mkMembership({
user: userA, mship: "join",
room: roomId, event: true, name: "User A",
}),
utils.mkMembership({
user: userB, mship: "join",
room: roomId, event: true, name: "User B",
}),
utils.mkEvent({
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.name, skey: "",
room: roomId, event: true, user: userA,
content: {
service_members: [userC],
},
}),
]);
expect(room.getDefaultRoomName(userA)).toEqual("User B");
});
});
});
});
+8 -8
View File
@@ -1,9 +1,9 @@
// This file had a function whose name is all caps, which displeases eslint
/* eslint new-cap: "off" */
import {defer} from '../../src/utils';
import {MatrixError} from "../../src/http-api";
import {MatrixScheduler} from "../../src/scheduler";
import { defer } from '../../src/utils';
import { MatrixError } from "../../src/http-api";
import { MatrixScheduler } from "../../src/scheduler";
import * as utils from "../test-utils";
jest.useFakeTimers();
@@ -62,8 +62,8 @@ describe("MatrixScheduler", function() {
scheduler.queueEvent(eventA),
scheduler.queueEvent(eventB),
]);
deferB.resolve({b: true});
deferA.resolve({a: true});
deferB.resolve({ b: true });
deferA.resolve({ a: true });
const [a, b] = await abPromise;
expect(a.a).toEqual(true);
expect(b.b).toEqual(true);
@@ -156,8 +156,8 @@ describe("MatrixScheduler", function() {
// Expect to have processFn invoked for A&B.
// Resolve A.
// Expect to have processFn invoked for D.
const eventC = utils.mkMessage({user: "@a:bar", room: roomId, event: true});
const eventD = utils.mkMessage({user: "@b:bar", room: roomId, event: true});
const eventC = utils.mkMessage({ user: "@a:bar", room: roomId, event: true });
const eventD = utils.mkMessage({ user: "@b:bar", room: roomId, event: true });
const buckets = {};
buckets[eventA.getId()] = "queue_A";
@@ -241,7 +241,7 @@ describe("MatrixScheduler", function() {
expect(queue).toEqual([eventA, eventB]);
// modify the queue
const eventC = utils.mkMessage(
{user: "@a:bar", room: roomId, event: true},
{ user: "@a:bar", room: roomId, event: true },
);
queue.push(eventC);
const queueAgain = scheduler.getQueueForEvent(eventA);
+1 -1
View File
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {SyncAccumulator} from "../../src/sync-accumulator";
import { SyncAccumulator } from "../../src/sync-accumulator";
// The event body & unsigned object get frozen to assert that they don't get altered
// by the impl
+11 -15
View File
@@ -1,5 +1,5 @@
import {EventTimeline} from "../../src/models/event-timeline";
import {TimelineIndex, TimelineWindow} from "../../src/timeline-window";
import { EventTimeline } from "../../src/models/event-timeline";
import { TimelineIndex, TimelineWindow } from "../../src/timeline-window";
import * as utils from "../test-utils";
const ROOM_ID = "roomId";
@@ -18,7 +18,7 @@ function createTimeline(numEvents, baseIndex) {
}
// XXX: this is a horrid hack
const timelineSet = { room: { roomId: ROOM_ID }};
const timelineSet = { room: { roomId: ROOM_ID } };
timelineSet.room.getUnfilteredTimelineSet = function() {
return timelineSet;
};
@@ -46,7 +46,6 @@ function addEventsToTimeline(timeline, numEvents, atStart) {
}
}
/*
* create a pair of linked timelines
*/
@@ -58,7 +57,6 @@ function createLinkedTimelines() {
return [tl1, tl2];
}
describe("TimelineIndex", function() {
describe("minIndex", function() {
it("should return the min index relative to BaseIndex", function() {
@@ -133,7 +131,6 @@ describe("TimelineIndex", function() {
});
});
describe("TimelineWindow", function() {
/**
* create a dummy eventTimelineSet and client, and a TimelineWindow
@@ -142,7 +139,7 @@ describe("TimelineWindow", function() {
let timelineSet;
let client;
function createWindow(timeline, opts) {
timelineSet = {getTimelineForEvent: () => null};
timelineSet = { getTimelineForEvent: () => null };
client = {};
client.getEventTimeline = function(timelineSet0, eventId0) {
expect(timelineSet0).toBe(timelineSet);
@@ -171,7 +168,7 @@ describe("TimelineWindow", function() {
const timeline = createTimeline();
const eventId = timeline.getEvents()[1].getId();
const timelineSet = {getTimelineForEvent: () => null};
const timelineSet = { getTimelineForEvent: () => null };
const client = {};
client.getEventTimeline = function(timelineSet0, eventId0) {
expect(timelineSet0).toBe(timelineSet);
@@ -193,7 +190,7 @@ describe("TimelineWindow", function() {
const eventId = timeline.getEvents()[1].getId();
const timelineSet = {getTimelineForEvent: () => null};
const timelineSet = { getTimelineForEvent: () => null };
const client = {};
const timelineWindow = new TimelineWindow(client, timelineSet);
@@ -266,7 +263,7 @@ describe("TimelineWindow", function() {
it("should advance into next timeline", function() {
const tls = createLinkedTimelines();
const eventId = tls[0].getEvents()[1].getId();
const timelineWindow = createWindow(tls[0], {windowLimit: 5});
const timelineWindow = createWindow(tls[0], { windowLimit: 5 });
return timelineWindow.load(eventId, 3).then(function() {
const expectedEvents = tls[0].getEvents();
@@ -311,7 +308,7 @@ describe("TimelineWindow", function() {
it("should retreat into previous timeline", function() {
const tls = createLinkedTimelines();
const eventId = tls[1].getEvents()[1].getId();
const timelineWindow = createWindow(tls[1], {windowLimit: 5});
const timelineWindow = createWindow(tls[1], { windowLimit: 5 });
return timelineWindow.load(eventId, 3).then(function() {
const expectedEvents = tls[1].getEvents();
@@ -357,7 +354,7 @@ describe("TimelineWindow", function() {
const timeline = createTimeline();
timeline.setPaginationToken("toktok", EventTimeline.FORWARDS);
const timelineWindow = createWindow(timeline, {windowLimit: 5});
const timelineWindow = createWindow(timeline, { windowLimit: 5 });
const eventId = timeline.getEvents()[1].getId();
client.paginateEventTimeline = function(timeline0, opts) {
@@ -385,12 +382,11 @@ describe("TimelineWindow", function() {
});
});
it("should make backward pagination requests", function() {
const timeline = createTimeline();
timeline.setPaginationToken("toktok", EventTimeline.BACKWARDS);
const timelineWindow = createWindow(timeline, {windowLimit: 5});
const timelineWindow = createWindow(timeline, { windowLimit: 5 });
const eventId = timeline.getEvents()[1].getId();
client.paginateEventTimeline = function(timeline0, opts) {
@@ -422,7 +418,7 @@ describe("TimelineWindow", function() {
const timeline = createTimeline();
timeline.setPaginationToken("toktok", EventTimeline.FORWARDS);
const timelineWindow = createWindow(timeline, {windowLimit: 5});
const timelineWindow = createWindow(timeline, { windowLimit: 5 });
const eventId = timeline.getEvents()[1].getId();
let paginateCount = 0;
+1 -1
View File
@@ -1,4 +1,4 @@
import {User} from "../../src/models/user";
import { User } from "../../src/models/user";
import * as utils from "../test-utils";
describe("User", function() {
-285
View File
@@ -1,285 +0,0 @@
import * as utils from "../../src/utils";
describe("utils", function() {
describe("encodeParams", function() {
it("should url encode and concat with &s", function() {
const params = {
foo: "bar",
baz: "beer@",
};
expect(utils.encodeParams(params)).toEqual(
"foo=bar&baz=beer%40",
);
});
});
describe("encodeUri", function() {
it("should replace based on object keys and url encode", function() {
const path = "foo/bar/%something/%here";
const vals = {
"%something": "baz",
"%here": "beer@",
};
expect(utils.encodeUri(path, vals)).toEqual(
"foo/bar/baz/beer%40",
);
});
});
describe("forEach", function() {
it("should be invoked for each element", function() {
const arr = [];
utils.forEach([55, 66, 77], function(element) {
arr.push(element);
});
expect(arr).toEqual([55, 66, 77]);
});
});
describe("findElement", function() {
it("should find only 1 element if there is a match", function() {
const matchFn = function() {
return true;
};
const arr = [55, 66, 77];
expect(utils.findElement(arr, matchFn)).toEqual(55);
});
it("should be able to find in reverse order", function() {
const matchFn = function() {
return true;
};
const arr = [55, 66, 77];
expect(utils.findElement(arr, matchFn, true)).toEqual(77);
});
it("should find nothing if the function never returns true", function() {
const matchFn = function() {
return false;
};
const arr = [55, 66, 77];
expect(utils.findElement(arr, matchFn)).toBeFalsy();
});
});
describe("removeElement", function() {
it("should remove only 1 element if there is a match", function() {
const matchFn = function() {
return true;
};
const arr = [55, 66, 77];
utils.removeElement(arr, matchFn);
expect(arr).toEqual([66, 77]);
});
it("should be able to remove in reverse order", function() {
const matchFn = function() {
return true;
};
const arr = [55, 66, 77];
utils.removeElement(arr, matchFn, true);
expect(arr).toEqual([55, 66]);
});
it("should remove nothing if the function never returns true", function() {
const matchFn = function() {
return false;
};
const arr = [55, 66, 77];
utils.removeElement(arr, matchFn);
expect(arr).toEqual(arr);
});
});
describe("isFunction", function() {
it("should return true for functions", function() {
expect(utils.isFunction([])).toBe(false);
expect(utils.isFunction([5, 3, 7])).toBe(false);
expect(utils.isFunction()).toBe(false);
expect(utils.isFunction(null)).toBe(false);
expect(utils.isFunction({})).toBe(false);
expect(utils.isFunction("foo")).toBe(false);
expect(utils.isFunction(555)).toBe(false);
expect(utils.isFunction(function() {})).toBe(true);
const s = { foo: function() {} };
expect(utils.isFunction(s.foo)).toBe(true);
});
});
describe("isArray", function() {
it("should return true for arrays", function() {
expect(utils.isArray([])).toBe(true);
expect(utils.isArray([5, 3, 7])).toBe(true);
expect(utils.isArray()).toBe(false);
expect(utils.isArray(null)).toBe(false);
expect(utils.isArray({})).toBe(false);
expect(utils.isArray("foo")).toBe(false);
expect(utils.isArray(555)).toBe(false);
expect(utils.isArray(function() {})).toBe(false);
});
});
describe("checkObjectHasKeys", function() {
it("should throw for missing keys", function() {
expect(function() {
utils.checkObjectHasKeys({}, ["foo"]);
}).toThrow();
expect(function() {
utils.checkObjectHasKeys({
foo: "bar",
}, ["foo"]);
}).not.toThrow();
});
});
describe("checkObjectHasNoAdditionalKeys", function() {
it("should throw for extra keys", function() {
expect(function() {
utils.checkObjectHasNoAdditionalKeys({
foo: "bar",
baz: 4,
}, ["foo"]);
}).toThrow();
expect(function() {
utils.checkObjectHasNoAdditionalKeys({
foo: "bar",
}, ["foo"]);
}).not.toThrow();
});
});
describe("deepCompare", function() {
const assert = {
isTrue: function(x) {
expect(x).toBe(true);
},
isFalse: function(x) {
expect(x).toBe(false);
},
};
it("should handle primitives", function() {
assert.isTrue(utils.deepCompare(null, null));
assert.isFalse(utils.deepCompare(null, undefined));
assert.isTrue(utils.deepCompare("hi", "hi"));
assert.isTrue(utils.deepCompare(5, 5));
assert.isFalse(utils.deepCompare(5, 10));
});
it("should handle regexps", function() {
assert.isTrue(utils.deepCompare(/abc/, /abc/));
assert.isFalse(utils.deepCompare(/abc/, /123/));
const r = /abc/;
assert.isTrue(utils.deepCompare(r, r));
});
it("should handle dates", function() {
assert.isTrue(utils.deepCompare(new Date("2011-03-31"),
new Date("2011-03-31")));
assert.isFalse(utils.deepCompare(new Date("2011-03-31"),
new Date("1970-01-01")));
});
it("should handle arrays", function() {
assert.isTrue(utils.deepCompare([], []));
assert.isTrue(utils.deepCompare([1, 2], [1, 2]));
assert.isFalse(utils.deepCompare([1, 2], [2, 1]));
assert.isFalse(utils.deepCompare([1, 2], [1, 2, 3]));
});
it("should handle simple objects", function() {
assert.isTrue(utils.deepCompare({}, {}));
assert.isTrue(utils.deepCompare({a: 1, b: 2}, {a: 1, b: 2}));
assert.isTrue(utils.deepCompare({a: 1, b: 2}, {b: 2, a: 1}));
assert.isFalse(utils.deepCompare({a: 1, b: 2}, {a: 1, b: 3}));
assert.isTrue(utils.deepCompare({1: {name: "mhc", age: 28},
2: {name: "arb", age: 26}},
{1: {name: "mhc", age: 28},
2: {name: "arb", age: 26}}));
assert.isFalse(utils.deepCompare({1: {name: "mhc", age: 28},
2: {name: "arb", age: 26}},
{1: {name: "mhc", age: 28},
2: {name: "arb", age: 27}}));
assert.isFalse(utils.deepCompare({}, null));
assert.isFalse(utils.deepCompare({}, undefined));
});
it("should handle functions", function() {
// no two different function is equal really, they capture their
// context variables so even if they have same toString(), they
// won't have same functionality
const func = function(x) {
return true;
};
const func2 = function(x) {
return true;
};
assert.isTrue(utils.deepCompare(func, func));
assert.isFalse(utils.deepCompare(func, func2));
assert.isTrue(utils.deepCompare({ a: { b: func } }, { a: { b: func } }));
assert.isFalse(utils.deepCompare({ a: { b: func } }, { a: { b: func2 } }));
});
});
describe("extend", function() {
const SOURCE = { "prop2": 1, "string2": "x", "newprop": "new" };
it("should extend", function() {
const target = {
"prop1": 5, "prop2": 7, "string1": "baz", "string2": "foo",
};
const merged = {
"prop1": 5, "prop2": 1, "string1": "baz", "string2": "x",
"newprop": "new",
};
const sourceOrig = JSON.stringify(SOURCE);
utils.extend(target, SOURCE);
expect(JSON.stringify(target)).toEqual(JSON.stringify(merged));
// check the originial wasn't modified
expect(JSON.stringify(SOURCE)).toEqual(sourceOrig);
});
it("should ignore null", function() {
const target = {
"prop1": 5, "prop2": 7, "string1": "baz", "string2": "foo",
};
const merged = {
"prop1": 5, "prop2": 1, "string1": "baz", "string2": "x",
"newprop": "new",
};
const sourceOrig = JSON.stringify(SOURCE);
utils.extend(target, null, SOURCE);
expect(JSON.stringify(target)).toEqual(JSON.stringify(merged));
// check the originial wasn't modified
expect(JSON.stringify(SOURCE)).toEqual(sourceOrig);
});
it("should handle properties created with defineProperties", function() {
const source = Object.defineProperties({}, {
"enumerableProp": {
get: function() {
return true;
},
enumerable: true,
},
"nonenumerableProp": {
get: function() {
return true;
},
},
});
const target = {};
utils.extend(target, source);
expect(target.enumerableProp).toBe(true);
expect(target.nonenumerableProp).toBe(undefined);
});
});
});
+509
View File
@@ -0,0 +1,509 @@
import * as utils from "../../src/utils";
import {
alphabetPad,
averageBetweenStrings,
baseToString,
deepSortedObjectEntries,
DEFAULT_ALPHABET,
lexicographicCompare,
nextString,
prevString,
simpleRetryOperation,
stringToBase,
} from "../../src/utils";
import { logger } from "../../src/logger";
// TODO: Fix types throughout
describe("utils", function() {
describe("encodeParams", function() {
it("should url encode and concat with &s", function() {
const params = {
foo: "bar",
baz: "beer@",
};
expect(utils.encodeParams(params)).toEqual(
"foo=bar&baz=beer%40",
);
});
it("should handle boolean and numeric values", function() {
const params = {
string: "foobar",
number: 12345,
boolean: false,
};
expect(utils.encodeParams(params)).toEqual("string=foobar&number=12345&boolean=false");
});
});
describe("encodeUri", function() {
it("should replace based on object keys and url encode", function() {
const path = "foo/bar/%something/%here";
const vals = {
"%something": "baz",
"%here": "beer@",
};
expect(utils.encodeUri(path, vals)).toEqual(
"foo/bar/baz/beer%40",
);
});
});
describe("removeElement", function() {
it("should remove only 1 element if there is a match", function() {
const matchFn = function() {
return true;
};
const arr = [55, 66, 77];
utils.removeElement(arr, matchFn);
expect(arr).toEqual([66, 77]);
});
it("should be able to remove in reverse order", function() {
const matchFn = function() {
return true;
};
const arr = [55, 66, 77];
utils.removeElement(arr, matchFn, true);
expect(arr).toEqual([55, 66]);
});
it("should remove nothing if the function never returns true", function() {
const matchFn = function() {
return false;
};
const arr = [55, 66, 77];
utils.removeElement(arr, matchFn);
expect(arr).toEqual(arr);
});
});
describe("isFunction", function() {
it("should return true for functions", function() {
expect(utils.isFunction([])).toBe(false);
expect(utils.isFunction([5, 3, 7])).toBe(false);
expect(utils.isFunction(undefined)).toBe(false);
expect(utils.isFunction(null)).toBe(false);
expect(utils.isFunction({})).toBe(false);
expect(utils.isFunction("foo")).toBe(false);
expect(utils.isFunction(555)).toBe(false);
expect(utils.isFunction(function() {})).toBe(true);
const s = { foo: function() {} };
expect(utils.isFunction(s.foo)).toBe(true);
});
});
describe("checkObjectHasKeys", function() {
it("should throw for missing keys", function() {
expect(function() {
utils.checkObjectHasKeys({}, ["foo"]);
}).toThrow();
expect(function() {
utils.checkObjectHasKeys({
foo: "bar",
}, ["foo"]);
}).not.toThrow();
});
});
describe("checkObjectHasNoAdditionalKeys", function() {
it("should throw for extra keys", function() {
expect(function() {
utils.checkObjectHasNoAdditionalKeys({ foo: "bar", baz: 4 }, ["foo"]);
}).toThrow();
expect(function() {
utils.checkObjectHasNoAdditionalKeys({ foo: "bar" }, ["foo"]);
}).not.toThrow();
});
});
describe("deepCompare", function() {
const assert = {
isTrue: function(x: any) {
expect(x).toBe(true);
},
isFalse: function(x: any) {
expect(x).toBe(false);
},
};
it("should handle primitives", function() {
assert.isTrue(utils.deepCompare(null, null));
assert.isFalse(utils.deepCompare(null, undefined));
assert.isTrue(utils.deepCompare("hi", "hi"));
assert.isTrue(utils.deepCompare(5, 5));
assert.isFalse(utils.deepCompare(5, 10));
});
it("should handle regexps", function() {
assert.isTrue(utils.deepCompare(/abc/, /abc/));
assert.isFalse(utils.deepCompare(/abc/, /123/));
const r = /abc/;
assert.isTrue(utils.deepCompare(r, r));
});
it("should handle dates", function() {
assert.isTrue(utils.deepCompare(new Date("2011-03-31"), new Date("2011-03-31")));
assert.isFalse(utils.deepCompare(new Date("2011-03-31"), new Date("1970-01-01")));
});
it("should handle arrays", function() {
assert.isTrue(utils.deepCompare([], []));
assert.isTrue(utils.deepCompare([1, 2], [1, 2]));
assert.isFalse(utils.deepCompare([1, 2], [2, 1]));
assert.isFalse(utils.deepCompare([1, 2], [1, 2, 3]));
});
it("should handle simple objects", function() {
assert.isTrue(utils.deepCompare({}, {}));
assert.isTrue(utils.deepCompare({ a: 1, b: 2 }, { a: 1, b: 2 }));
assert.isTrue(utils.deepCompare({ a: 1, b: 2 }, { b: 2, a: 1 }));
assert.isFalse(utils.deepCompare({ a: 1, b: 2 }, { a: 1, b: 3 }));
assert.isTrue(utils.deepCompare({
1: { name: "mhc", age: 28 },
2: { name: "arb", age: 26 },
}, {
1: { name: "mhc", age: 28 },
2: { name: "arb", age: 26 },
}));
assert.isFalse(utils.deepCompare({
1: { name: "mhc", age: 28 },
2: { name: "arb", age: 26 },
}, {
1: { name: "mhc", age: 28 },
2: { name: "arb", age: 27 },
}));
assert.isFalse(utils.deepCompare({}, null));
assert.isFalse(utils.deepCompare({}, undefined));
});
it("should handle functions", function() {
// no two different function is equal really, they capture their
// context variables so even if they have same toString(), they
// won't have same functionality
const func = function() {
return true;
};
const func2 = function() {
return true;
};
assert.isTrue(utils.deepCompare(func, func));
assert.isFalse(utils.deepCompare(func, func2));
assert.isTrue(utils.deepCompare({ a: { b: func } }, { a: { b: func } }));
assert.isFalse(utils.deepCompare({ a: { b: func } }, { a: { b: func2 } }));
});
});
describe("chunkPromises", function() {
it("should execute promises in chunks", async function() {
let promiseCount = 0;
async function fn1() {
await utils.sleep(1);
expect(promiseCount).toEqual(0);
++promiseCount;
}
async function fn2() {
expect(promiseCount).toEqual(1);
++promiseCount;
}
await utils.chunkPromises([fn1, fn2], 1);
expect(promiseCount).toEqual(2);
});
});
describe('simpleRetryOperation', () => {
it('should retry', async () => {
let count = 0;
const val = {};
const fn = (attempt: any) => {
count++;
// If this expectation fails then it can appear as a Jest Timeout due to
// the retry running beyond the test limit.
expect(attempt).toEqual(count);
if (count > 1) {
return Promise.resolve(val);
} else {
return Promise.reject(new Error("Iterative failure"));
}
};
const ret = await simpleRetryOperation(fn);
expect(ret).toBe(val);
expect(count).toEqual(2);
});
// We don't test much else of the function because then we're just testing that the
// underlying library behaves, which should be tested on its own. Our API surface is
// all that concerns us.
});
describe('DEFAULT_ALPHABET', () => {
it('should be usefully printable ASCII in order', () => {
expect(DEFAULT_ALPHABET).toEqual(
" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~",
);
});
});
describe('alphabetPad', () => {
it('should pad to the alphabet length', () => {
const len = 12;
expect(alphabetPad("a", len)).toEqual("a" + ("".padEnd(len - 1, DEFAULT_ALPHABET[0])));
expect(alphabetPad("a", len, "123")).toEqual("a" + ("".padEnd(len - 1, '1')));
});
});
describe('baseToString', () => {
it('should calculate the appropriate string from numbers', () => {
// Verify the whole alphabet
for (let i = BigInt(1); i <= DEFAULT_ALPHABET.length; i++) {
logger.log({ i }); // for debugging
expect(baseToString(i)).toEqual(DEFAULT_ALPHABET[Number(i) - 1]);
}
// Just quickly double check that repeated characters aren't treated as padding, particularly
// at the beginning of the alphabet where they are most vulnerable to this behaviour.
expect(baseToString(BigInt(1))).toEqual(DEFAULT_ALPHABET[0].repeat(1));
expect(baseToString(BigInt(96))).toEqual(DEFAULT_ALPHABET[0].repeat(2));
expect(baseToString(BigInt(9121))).toEqual(DEFAULT_ALPHABET[0].repeat(3));
expect(baseToString(BigInt(866496))).toEqual(DEFAULT_ALPHABET[0].repeat(4));
expect(baseToString(BigInt(82317121))).toEqual(DEFAULT_ALPHABET[0].repeat(5));
expect(baseToString(BigInt(7820126496))).toEqual(DEFAULT_ALPHABET[0].repeat(6));
expect(baseToString(BigInt(10))).toEqual(DEFAULT_ALPHABET[9]);
expect(baseToString(BigInt(10), "abcdefghijklmnopqrstuvwxyz")).toEqual('j');
expect(baseToString(BigInt(6337))).toEqual("ab");
expect(baseToString(BigInt(80), "abcdefghijklmnopqrstuvwxyz")).toEqual('cb');
});
});
describe('stringToBase', () => {
it('should calculate the appropriate number for a string', () => {
expect(stringToBase(DEFAULT_ALPHABET[0].repeat(1))).toEqual(BigInt(1));
expect(stringToBase(DEFAULT_ALPHABET[0].repeat(2))).toEqual(BigInt(96));
expect(stringToBase(DEFAULT_ALPHABET[0].repeat(3))).toEqual(BigInt(9121));
expect(stringToBase(DEFAULT_ALPHABET[0].repeat(4))).toEqual(BigInt(866496));
expect(stringToBase(DEFAULT_ALPHABET[0].repeat(5))).toEqual(BigInt(82317121));
expect(stringToBase(DEFAULT_ALPHABET[0].repeat(6))).toEqual(BigInt(7820126496));
expect(stringToBase("a", "abcdefghijklmnopqrstuvwxyz")).toEqual(BigInt(1));
expect(stringToBase("a")).toEqual(BigInt(66));
expect(stringToBase("c", "abcdefghijklmnopqrstuvwxyz")).toEqual(BigInt(3));
expect(stringToBase("ab")).toEqual(BigInt(6337));
expect(stringToBase("cb", "abcdefghijklmnopqrstuvwxyz")).toEqual(BigInt(80));
});
});
describe('averageBetweenStrings', () => {
it('should average appropriately', () => {
expect(averageBetweenStrings(" ", "!!")).toEqual(" P");
expect(averageBetweenStrings(" ", "!")).toEqual(" ");
expect(averageBetweenStrings('A', 'B')).toEqual('A ');
expect(averageBetweenStrings('AA', 'BB')).toEqual('Aq');
expect(averageBetweenStrings('A', 'z')).toEqual(']');
expect(averageBetweenStrings('a', 'z', "abcdefghijklmnopqrstuvwxyz")).toEqual('m');
expect(averageBetweenStrings('AA', 'zz')).toEqual('^.');
expect(averageBetweenStrings('aa', 'zz', "abcdefghijklmnopqrstuvwxyz")).toEqual('mz');
expect(averageBetweenStrings('cat', 'doggo')).toEqual("d9>Cw");
expect(averageBetweenStrings('cat', 'doggo', "abcdefghijklmnopqrstuvwxyz")).toEqual("cumqh");
});
});
describe('nextString', () => {
it('should find the next string appropriately', () => {
expect(nextString('A')).toEqual('B');
expect(nextString('b', 'abcdefghijklmnopqrstuvwxyz')).toEqual('c');
expect(nextString('cat')).toEqual('cau');
expect(nextString('cat', 'abcdefghijklmnopqrstuvwxyz')).toEqual('cau');
});
});
describe('prevString', () => {
it('should find the next string appropriately', () => {
expect(prevString('B')).toEqual('A');
expect(prevString('c', 'abcdefghijklmnopqrstuvwxyz')).toEqual('b');
expect(prevString('cau')).toEqual('cat');
expect(prevString('cau', 'abcdefghijklmnopqrstuvwxyz')).toEqual('cat');
});
});
// Let's just ensure the ordering is sensible for lexicographic ordering
describe('string averaging unified', () => {
it('should be truly previous and next', () => {
let midpoint = "cat";
// We run this test 100 times to ensure we end up with a sane sequence.
for (let i = 0; i < 100; i++) {
const next = nextString(midpoint);
const prev = prevString(midpoint);
logger.log({ i, midpoint, next, prev }); // for test debugging
expect(lexicographicCompare(midpoint, next) < 0).toBe(true);
expect(lexicographicCompare(midpoint, prev) > 0).toBe(true);
expect(averageBetweenStrings(prev, next)).toBe(midpoint);
midpoint = next;
}
});
it('should roll over', () => {
const lastAlpha = DEFAULT_ALPHABET[DEFAULT_ALPHABET.length - 1];
const firstAlpha = DEFAULT_ALPHABET[0];
const highRoll = firstAlpha + firstAlpha;
const lowRoll = lastAlpha;
expect(nextString(lowRoll)).toEqual(highRoll);
expect(prevString(highRoll)).toEqual(lowRoll);
});
it('should be reversible on small strings', () => {
// Large scale reversibility is tested for max space order value
const input = "cats";
expect(prevString(nextString(input))).toEqual(input);
});
// We want to explicitly make sure that Space order values are supported and roll appropriately
it('should properly handle rolling over at 50 characters', () => {
// Note: we also test reversibility of large strings here.
const maxSpaceValue = DEFAULT_ALPHABET[DEFAULT_ALPHABET.length - 1].repeat(50);
const fiftyFirstChar = DEFAULT_ALPHABET[0].repeat(51);
expect(nextString(maxSpaceValue)).toBe(fiftyFirstChar);
expect(prevString(fiftyFirstChar)).toBe(maxSpaceValue);
// We're testing that the rollover happened, which means that the next string come before
// the maximum space order value lexicographically.
expect(lexicographicCompare(maxSpaceValue, fiftyFirstChar) > 0).toBe(true);
});
});
describe('lexicographicCompare', () => {
it('should work', () => {
// Simple tests
expect(lexicographicCompare('a', 'b') < 0).toBe(true);
expect(lexicographicCompare('ab', 'b') < 0).toBe(true);
expect(lexicographicCompare('cat', 'dog') < 0).toBe(true);
// Simple tests (reversed)
expect(lexicographicCompare('b', 'a') > 0).toBe(true);
expect(lexicographicCompare('b', 'ab') > 0).toBe(true);
expect(lexicographicCompare('dog', 'cat') > 0).toBe(true);
// Simple equality tests
expect(lexicographicCompare('a', 'a') === 0).toBe(true);
expect(lexicographicCompare('A', 'A') === 0).toBe(true);
// ASCII rule testing
expect(lexicographicCompare('A', 'a') < 0).toBe(true);
expect(lexicographicCompare('a', 'A') > 0).toBe(true);
});
});
describe('deepSortedObjectEntries', () => {
it('should auto-return non-objects', () => {
expect(deepSortedObjectEntries(42)).toEqual(42);
expect(deepSortedObjectEntries("not object")).toEqual("not object");
expect(deepSortedObjectEntries(true)).toEqual(true);
expect(deepSortedObjectEntries([42])).toEqual([42]);
expect(deepSortedObjectEntries(null)).toEqual(null);
expect(deepSortedObjectEntries(undefined)).toEqual(undefined);
});
it('should sort objects appropriately', () => {
const input = {
a: 42,
b: {
d: {},
a: "test",
b: "alpha",
},
[72]: "test",
};
const output: any = [
["72", "test"],
["a", 42],
["b", [
["a", "test"],
["b", "alpha"],
["d", []],
]],
];
expect(deepSortedObjectEntries(input)).toMatchObject(output);
});
});
describe("recursivelyAssign", () => {
it("doesn't override with null/undefined", () => {
const result = utils.recursivelyAssign(
{
string: "Hello world",
object: {},
float: 0.1,
}, {
string: null,
object: undefined,
},
true,
);
expect(result).toStrictEqual({
string: "Hello world",
object: {},
float: 0.1,
});
});
it("assigns recursively", () => {
const result = utils.recursivelyAssign(
{
number: 42,
object: {
message: "Hello world",
day: "Monday",
langs: {
compiled: ["c++"],
},
},
thing: "string",
}, {
number: 2,
object: {
message: "How are you",
day: "Friday",
langs: {
compiled: ["c++", "c"],
},
},
thing: {
aSubThing: "something",
},
},
);
expect(result).toStrictEqual({
number: 2,
object: {
message: "How are you",
day: "Friday",
langs: {
compiled: ["c++", "c"],
},
},
thing: {
aSubThing: "something",
},
});
});
});
});
+217 -11
View File
@@ -14,8 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {TestClient} from '../../TestClient';
import {MatrixCall, CallErrorCode} from '../../../src/webrtc/call';
import { TestClient } from '../../TestClient';
import { MatrixCall, CallErrorCode, CallEvent } from '../../../src/webrtc/call';
import { SDPStreamMetadataKey, SDPStreamMetadataPurpose } from '../../../src/webrtc/callEventTypes';
import { RoomMember } from "../../../src";
const DUMMY_SDP = (
"v=0\r\n" +
@@ -79,6 +81,29 @@ class MockRTCPeerConnection {
return Promise.resolve();
}
close() {}
getStats() { return []; }
}
class MockMediaStream {
constructor(
public id: string,
) {}
getTracks() { return []; }
getAudioTracks() { return [{ enabled: true }]; }
getVideoTracks() { return [{ enabled: true }]; }
addEventListener() {}
}
class MockMediaDeviceInfo {
constructor(
public kind: "audio" | "video",
) {}
}
class MockMediaHandler {
getUserMediaStream() { return new MockMediaStream("mock_stream_from_media_handler"); }
stopUserMediaStream() {}
}
describe('Call', function() {
@@ -96,13 +121,9 @@ describe('Call', function() {
global.navigator = {
mediaDevices: {
// @ts-ignore Mock
getUserMedia: () => {
return {
getTracks: () => [],
getAudioTracks: () => [],
getVideoTracks: () => [],
};
},
getUserMedia: () => new MockMediaStream("local_stream"),
// @ts-ignore Mock
enumerateDevices: async () => [new MockMediaDeviceInfo("audio"), new MockMediaDeviceInfo("video")],
},
};
@@ -113,7 +134,7 @@ describe('Call', function() {
RTCSessionDescription: {},
// @ts-ignore Mock
RTCIceCandidate: {},
getUserMedia: {},
getUserMedia: () => new MockMediaStream("local_stream"),
};
// @ts-ignore Mock
global.document = {};
@@ -122,6 +143,9 @@ describe('Call', function() {
// We just stub out sendEvent: we're not interested in testing the client's
// event sending code here
client.client.sendEvent = () => {};
client.client.mediaHandler = new MockMediaHandler;
client.client.getMediaHandler = () => client.client.mediaHandler;
client.httpBackend.when("GET", "/voip/turnServer").respond(200, {});
call = new MatrixCall({
client: client.client,
roomId: '!foo:bar',
@@ -138,7 +162,9 @@ describe('Call', function() {
});
it('should ignore candidate events from non-matching party ID', async function() {
await call.placeVoiceCall();
const callPromise = call.placeVoiceCall();
await client.httpBackend.flush();
await callPromise;
await call.onAnswerReceived({
getContent: () => {
return {
@@ -190,4 +216,184 @@ describe('Call', function() {
// Hangup to stop timers
call.hangup(CallErrorCode.UserHangup, true);
});
it('should add candidates received before answer if party ID is correct', async function() {
const callPromise = call.placeVoiceCall();
await client.httpBackend.flush();
await callPromise;
call.peerConn.addIceCandidate = jest.fn();
call.onRemoteIceCandidatesReceived({
getContent: () => {
return {
version: 1,
call_id: call.callId,
party_id: 'the_correct_party_id',
candidates: [
{
candidate: 'the_correct_candidate',
sdpMid: '',
},
],
};
},
});
call.onRemoteIceCandidatesReceived({
getContent: () => {
return {
version: 1,
call_id: call.callId,
party_id: 'some_other_party_id',
candidates: [
{
candidate: 'the_wrong_candidate',
sdpMid: '',
},
],
};
},
});
expect(call.peerConn.addIceCandidate.mock.calls.length).toBe(0);
await call.onAnswerReceived({
getContent: () => {
return {
version: 1,
call_id: call.callId,
party_id: 'the_correct_party_id',
answer: {
sdp: DUMMY_SDP,
},
};
},
});
expect(call.peerConn.addIceCandidate.mock.calls.length).toBe(1);
expect(call.peerConn.addIceCandidate).toHaveBeenCalledWith({
candidate: 'the_correct_candidate',
sdpMid: '',
});
});
it('should map asserted identity messages to remoteAssertedIdentity', async function() {
const callPromise = call.placeVoiceCall();
await client.httpBackend.flush();
await callPromise;
await call.onAnswerReceived({
getContent: () => {
return {
version: 1,
call_id: call.callId,
party_id: 'party_id',
answer: {
sdp: DUMMY_SDP,
},
};
},
});
const identChangedCallback = jest.fn();
call.on(CallEvent.AssertedIdentityChanged, identChangedCallback);
await call.onAssertedIdentityReceived({
getContent: () => {
return {
version: 1,
call_id: call.callId,
party_id: 'party_id',
asserted_identity: {
id: "@steve:example.com",
display_name: "Steve Gibbons",
},
};
},
});
expect(identChangedCallback).toHaveBeenCalled();
const ident = call.getRemoteAssertedIdentity();
expect(ident.id).toEqual("@steve:example.com");
expect(ident.displayName).toEqual("Steve Gibbons");
// Hangup to stop timers
call.hangup(CallErrorCode.UserHangup, true);
});
it("should map SDPStreamMetadata to feeds", async () => {
const callPromise = call.placeVoiceCall();
await client.httpBackend.flush();
await callPromise;
call.getOpponentMember = () => {
return { userId: "@bob:bar.uk" };
};
await call.onAnswerReceived({
getContent: () => {
return {
version: 1,
call_id: call.callId,
party_id: 'party_id',
answer: {
sdp: DUMMY_SDP,
},
[SDPStreamMetadataKey]: {
"remote_stream": {
purpose: SDPStreamMetadataPurpose.Usermedia,
audio_muted: true,
video_muted: false,
},
},
};
},
});
call.pushRemoteFeed(new MockMediaStream("remote_stream"));
const feed = call.getFeeds().find((feed) => feed.stream.id === "remote_stream");
expect(feed?.purpose).toBe(SDPStreamMetadataPurpose.Usermedia);
expect(feed?.isAudioMuted()).toBeTruthy();
expect(feed?.isVideoMuted()).not.toBeTruthy();
});
it("should fallback to replaceTrack() if the other side doesn't support SPDStreamMetadata", async () => {
const callPromise = call.placeVoiceCall();
await client.httpBackend.flush();
await callPromise;
call.getOpponentMember = () => {
return { userId: "@bob:bar.uk" } as RoomMember;
};
await call.onAnswerReceived({
getContent: () => {
return {
version: 1,
call_id: call.callId,
party_id: 'party_id',
answer: {
sdp: DUMMY_SDP,
},
};
},
});
call.setScreensharingEnabledWithoutMetadataSupport = jest.fn();
call.setScreensharingEnabled(true);
expect(call.setScreensharingEnabledWithoutMetadataSupport).toHaveBeenCalled();
});
it("should fallback to answering with no video", async () => {
await client.httpBackend.flush();
call.shouldAnswerWithMediaType = (wantedValue: boolean) => wantedValue;
client.client.mediaHandler.getUserMediaStream = jest.fn().mockRejectedValue("reject");
await call.answer(true, true);
expect(client.client.mediaHandler.getUserMediaStream).toHaveBeenNthCalledWith(1, true, true);
expect(client.client.mediaHandler.getUserMediaStream).toHaveBeenNthCalledWith(2, true, false);
});
});
+24
View File
@@ -0,0 +1,24 @@
/*
Copyright 2021 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 interface IIdentityServerProvider {
/**
* Gets an access token for use against the identity server,
* for the associated client.
* @returns {Promise<string>} Resolves to the access token.
*/
getAccessToken(): Promise<string>;
}
+165
View File
@@ -0,0 +1,165 @@
/*
Copyright 2021 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.
*/
// allow camelcase as these are things that go onto the wire
/* eslint-disable camelcase */
export enum PushRuleActionName {
DontNotify = "dont_notify",
Notify = "notify",
Coalesce = "coalesce",
}
export enum TweakName {
Highlight = "highlight",
Sound = "sound",
}
export type Tweak<N extends TweakName, V> = {
set_tweak: N;
value: V;
};
export type TweakHighlight = Tweak<TweakName.Highlight, boolean>;
export type TweakSound = Tweak<TweakName.Sound, string>;
export type Tweaks = TweakHighlight | TweakSound;
export enum ConditionOperator {
ExactEquals = "==",
LessThan = "<",
GreaterThan = ">",
GreaterThanOrEqual = ">=",
LessThanOrEqual = "<=",
}
export type PushRuleAction = Tweaks | PushRuleActionName;
export type MemberCountCondition
<N extends number, Op extends ConditionOperator = ConditionOperator.ExactEquals>
= `${Op}${N}` | (Op extends ConditionOperator.ExactEquals ? `${N}` : never);
export type AnyMemberCountCondition = MemberCountCondition<number, ConditionOperator>;
export const DMMemberCountCondition: MemberCountCondition<2> = "2";
export function isDmMemberCountCondition(condition: AnyMemberCountCondition): boolean {
return condition === "==2" || condition === "2";
}
export enum ConditionKind {
EventMatch = "event_match",
ContainsDisplayName = "contains_display_name",
RoomMemberCount = "room_member_count",
SenderNotificationPermission = "sender_notification_permission",
}
export interface IPushRuleCondition<N extends ConditionKind | string> {
[k: string]: any; // for custom conditions, there can be other fields here
kind: N;
}
export interface IEventMatchCondition extends IPushRuleCondition<ConditionKind.EventMatch> {
key: string;
pattern: string;
}
export interface IContainsDisplayNameCondition extends IPushRuleCondition<ConditionKind.ContainsDisplayName> {
// no additional fields
}
export interface IRoomMemberCountCondition extends IPushRuleCondition<ConditionKind.RoomMemberCount> {
is: AnyMemberCountCondition;
}
export interface ISenderNotificationPermissionCondition
extends IPushRuleCondition<ConditionKind.SenderNotificationPermission> {
key: string;
}
// XXX: custom conditions are possible but always fail, and break the typescript discriminated union so ignore them here
// IPushRuleCondition<Exclude<string, ConditionKind>> unfortunately does not resolve this at the time of writing.
export type PushRuleCondition = IEventMatchCondition
| IContainsDisplayNameCondition
| IRoomMemberCountCondition
| ISenderNotificationPermissionCondition;
export enum PushRuleKind {
Override = "override",
ContentSpecific = "content",
RoomSpecific = "room",
SenderSpecific = "sender",
Underride = "underride",
}
export enum RuleId {
Master = ".m.rule.master",
ContainsDisplayName = ".m.rule.contains_display_name",
ContainsUserName = ".m.rule.contains_user_name",
AtRoomNotification = ".m.rule.roomnotif",
DM = ".m.rule.room_one_to_one",
EncryptedDM = ".m.rule.encrypted_room_one_to_one",
Message = ".m.rule.message",
EncryptedMessage = ".m.rule.encrypted",
InviteToSelf = ".m.rule.invite_for_me",
MemberEvent = ".m.rule.member_event",
IncomingCall = ".m.rule.call",
SuppressNotices = ".m.rule.suppress_notices",
Tombstone = ".m.rule.tombstone",
}
export type PushRuleSet = {
[k in PushRuleKind]?: IPushRule[];
};
export interface IPushRule {
actions: PushRuleAction[];
conditions?: PushRuleCondition[];
default: boolean;
enabled: boolean;
pattern?: string;
rule_id: RuleId | string;
}
export interface IAnnotatedPushRule extends IPushRule {
kind: PushRuleKind;
}
export interface IPushRules {
global: PushRuleSet;
device?: PushRuleSet;
}
export interface IPusher {
app_display_name: string;
app_id: string;
data: {
format?: string;
url?: string; // TODO: Required if kind==http
brand?: string; // TODO: For email notifications only? Unspecced field
};
device_display_name: string;
kind: "http" | string;
lang: string;
profile_tag?: string;
pushkey: string;
}
export interface IPusherRequest extends IPusher {
append?: boolean;
}
/* eslint-enable camelcase */
@@ -1,5 +1,5 @@
/*
Copyright 2019 The Matrix.org Foundation C.I.C.
Copyright 2021 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.
@@ -14,7 +14,6 @@ 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
});
declare module "another-json" {
export function stringify(o: object): string;
}
+104
View File
@@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { UnstableValue } from "../NamespacedValue";
export enum EventType {
// Room state events
RoomCanonicalAlias = "m.room.canonical_alias",
@@ -36,6 +38,9 @@ export enum EventType {
*/
RoomAliases = "m.room.aliases", // deprecated https://matrix.org/docs/spec/client_server/r0.6.1#historical-events
SpaceChild = "m.space.child",
SpaceParent = "m.space.parent",
// Room timeline events
RoomRedaction = "m.room.redaction",
RoomMessage = "m.room.message",
@@ -48,13 +53,19 @@ export enum EventType {
CallReject = "m.call.reject",
CallSelectAnswer = "m.call.select_answer",
CallNegotiate = "m.call.negotiate",
CallSDPStreamMetadataChanged = "m.call.sdp_stream_metadata_changed",
CallSDPStreamMetadataChangedPrefix = "org.matrix.call.sdp_stream_metadata_changed",
CallReplaces = "m.call.replaces",
CallAssertedIdentity = "m.call.asserted_identity",
CallAssertedIdentityPrefix = "org.matrix.call.asserted_identity",
KeyVerificationRequest = "m.key.verification.request",
KeyVerificationStart = "m.key.verification.start",
KeyVerificationCancel = "m.key.verification.cancel",
KeyVerificationMac = "m.key.verification.mac",
KeyVerificationDone = "m.key.verification.done",
// use of this is discouraged https://matrix.org/docs/spec/client_server/r0.6.1#m-room-message-feedback
RoomMessageFeedback = "m.room.message.feedback",
Reaction = "m.reaction",
// Room ephemeral events
Typing = "m.typing",
@@ -64,6 +75,7 @@ export enum EventType {
// Room account_data events
FullyRead = "m.fully_read",
Tag = "m.tag",
SpaceOrder = "org.matrix.msc3230.space_order", // MSC3230
// User account_data events
PushRules = "m.push_rules",
@@ -77,6 +89,19 @@ export enum EventType {
Dummy = "m.dummy",
}
export enum RelationType {
Annotation = "m.annotation",
Replace = "m.replace",
/**
* Note, "io.element.thread" is hardcoded
* Should be replaced with "m.thread" once MSC3440 lands
* Can not use `UnstableValue` as TypeScript does not
* allow computed values in enums
* https://github.com/microsoft/TypeScript/issues/27976
*/
Thread = "io.element.thread",
}
export enum MsgType {
Text = "m.text",
Emote = "m.emote",
@@ -86,4 +111,83 @@ export enum MsgType {
Audio = "m.audio",
Location = "m.location",
Video = "m.video",
KeyVerificationRequest = "m.key.verification.request",
}
export const RoomCreateTypeField = "type";
export enum RoomType {
Space = "m.space",
}
/**
* Identifier for an [MSC3088](https://github.com/matrix-org/matrix-doc/pull/3088)
* room purpose. Note that this reference is UNSTABLE and subject to breaking changes,
* including its eventual removal.
*/
export const UNSTABLE_MSC3088_PURPOSE = new UnstableValue("m.room.purpose", "org.matrix.msc3088.purpose");
/**
* Enabled flag for an [MSC3088](https://github.com/matrix-org/matrix-doc/pull/3088)
* room purpose. Note that this reference is UNSTABLE and subject to breaking changes,
* including its eventual removal.
*/
export const UNSTABLE_MSC3088_ENABLED = new UnstableValue("m.enabled", "org.matrix.msc3088.enabled");
/**
* Subtype for an [MSC3089](https://github.com/matrix-org/matrix-doc/pull/3089) space-room.
* Note that this reference is UNSTABLE and subject to breaking changes, including its
* eventual removal.
*/
export const UNSTABLE_MSC3089_TREE_SUBTYPE = new UnstableValue("m.data_tree", "org.matrix.msc3089.data_tree");
/**
* Leaf type for an event in a [MSC3089](https://github.com/matrix-org/matrix-doc/pull/3089) space-room.
* Note that this reference is UNSTABLE and subject to breaking changes, including its
* eventual removal.
*/
export const UNSTABLE_MSC3089_LEAF = new UnstableValue("m.leaf", "org.matrix.msc3089.leaf");
/**
* Branch (Leaf Reference) type for the index approach in a
* [MSC3089](https://github.com/matrix-org/matrix-doc/pull/3089) space-room. Note that this reference is
* UNSTABLE and subject to breaking changes, including its eventual removal.
*/
export const UNSTABLE_MSC3089_BRANCH = new UnstableValue("m.branch", "org.matrix.msc3089.branch");
/**
* Functional members type for declaring a purpose of room members (e.g. helpful bots).
* Note that this reference is UNSTABLE and subject to breaking changes, including its
* eventual removal.
*
* Schema (TypeScript):
* {
* service_members?: string[]
* }
*
* Example:
* {
* "service_members": [
* "@helperbot:localhost",
* "@reminderbot:alice.tdl"
* ]
* }
*/
export const UNSTABLE_ELEMENT_FUNCTIONAL_USERS = new UnstableValue(
"io.element.functional_members",
"io.element.functional_members");
export interface IEncryptedFile {
url: string;
mimetype?: string;
key: {
alg: string;
key_ops: string[]; // eslint-disable-line camelcase
kty: string;
k: string;
ext: boolean;
};
iv: string;
hashes: {[alg: string]: string};
v: string;
}
+52 -2
View File
@@ -15,21 +15,51 @@ limitations under the License.
*/
// this is needed to tell TS about global.Olm
import * as Olm from "olm"; // eslint-disable-line @typescript-eslint/no-unused-vars
import "@matrix-org/olm";
export {};
declare global {
// use `number` as the return type in all cases for global.set{Interval,Timeout},
// so we don't accidentally use the methods on NodeJS.Timeout - they only exist in a subset of environments.
// The overload for clear{Interval,Timeout} is resolved as expected.
function setInterval(handler: TimerHandler, timeout: number, ...arguments: any[]): number;
function setTimeout(handler: TimerHandler, timeout: number, ...arguments: any[]): number;
namespace NodeJS {
interface Global {
localStorage: Storage;
}
}
interface Window {
webkitAudioContext: typeof AudioContext;
}
interface Crypto {
webkitSubtle?: Window["crypto"]["subtle"];
}
interface MediaDevices {
// This is experimental and types don't know about it yet
// https://github.com/microsoft/TypeScript/issues/33232
getDisplayMedia(constraints: MediaStreamConstraints): Promise<MediaStream>;
getDisplayMedia(constraints: MediaStreamConstraints | DesktopCapturerConstraints): Promise<MediaStream>;
getUserMedia(constraints: MediaStreamConstraints | DesktopCapturerConstraints): Promise<MediaStream>;
}
interface DesktopCapturerConstraints {
audio: boolean | {
mandatory: {
chromeMediaSource: string;
chromeMediaSourceId: string;
};
};
video: boolean | {
mandatory: {
chromeMediaSource: string;
chromeMediaSourceId: string;
};
};
}
interface HTMLAudioElement {
@@ -45,4 +75,24 @@ declare global {
// on webkit: we should check if we still need to do this
webkitGetUserMedia: DummyInterfaceWeShouldntBeUsingThis;
}
export interface ISettledFulfilled<T> {
status: "fulfilled";
value: T;
}
export interface ISettledRejected {
status: "rejected";
reason: any;
}
interface PromiseConstructor {
allSettled<T>(promises: Promise<T>[]): Promise<Array<ISettledFulfilled<T> | ISettledRejected>>;
}
interface RTCRtpTransceiver {
// This has been removed from TS
// (https://github.com/microsoft/TypeScript-DOM-lib-generator/issues/1029),
// but we still need this for MatrixCall::getRidOfRTXCodecs()
setCodecPreferences(codecs: RTCRtpCodecCapability[]): void;
}
}
+84
View File
@@ -0,0 +1,84 @@
/*
Copyright 2021 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 interface IImageInfo {
size?: number;
mimetype?: string;
thumbnail_info?: { // eslint-disable-line camelcase
w?: number;
h?: number;
size?: number;
mimetype?: string;
};
w?: number;
h?: number;
}
export enum Visibility {
Public = "public",
Private = "private",
}
export enum Preset {
PrivateChat = "private_chat",
TrustedPrivateChat = "trusted_private_chat",
PublicChat = "public_chat",
}
export type ResizeMethod = "crop" | "scale";
// TODO move to http-api after TSification
export interface IAbortablePromise<T> extends Promise<T> {
abort(): void;
}
export type IdServerUnbindResult = "no-support" | "success";
// Knock and private are reserved keywords which are not yet implemented.
export enum JoinRule {
Public = "public",
Invite = "invite",
/**
* @deprecated Reserved keyword. Should not be used. Not yet implemented.
*/
Private = "private",
Knock = "knock",
Restricted = "restricted",
}
export enum RestrictedAllowType {
RoomMembership = "m.room_membership",
}
export interface IJoinRuleEventContent {
join_rule: JoinRule; // eslint-disable-line camelcase
allow?: {
type: RestrictedAllowType;
room_id: string; // eslint-disable-line camelcase
}[];
}
export enum GuestAccess {
CanJoin = "can_join",
Forbidden = "forbidden",
}
export enum HistoryVisibility {
Invited = "invited",
Joined = "joined",
Shared = "shared",
WorldReadable = "world_readable",
}
+156
View File
@@ -0,0 +1,156 @@
/*
Copyright 2021 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.
*/
import { Callback } from "../client";
import { IContent, IEvent } from "../models/event";
import { Preset, Visibility } from "./partials";
import { SearchKey } from "./search";
import { IRoomEventFilter } from "../filter";
// allow camelcase as these are things that go onto the wire
/* eslint-disable camelcase */
export interface IJoinRoomOpts {
/**
* True to do a room initial sync on the resulting
* room. If false, the <strong>returned Room object will have no current state.
* </strong> Default: true.
*/
syncRoom?: boolean;
/**
* If the caller has a keypair 3pid invite, the signing URL is passed in this parameter.
*/
inviteSignUrl?: string;
/**
* The server names to try and join through in addition to those that are automatically chosen.
*/
viaServers?: string[];
}
export interface IRedactOpts {
reason?: string;
}
export interface ISendEventResponse {
event_id: string;
}
export interface IPresenceOpts {
presence: "online" | "offline" | "unavailable";
status_msg?: string;
}
export interface IPaginateOpts {
backwards?: boolean;
limit?: number;
}
export interface IGuestAccessOpts {
allowJoin: boolean;
allowRead: boolean;
}
export interface ISearchOpts {
keys?: SearchKey[];
query: string;
}
export interface IEventSearchOpts {
filter?: IRoomEventFilter;
term: string;
}
export interface IInvite3PID {
id_server: string;
id_access_token?: string; // this gets injected by the js-sdk
medium: string;
address: string;
}
export interface ICreateRoomStateEvent {
type: string;
state_key?: string; // defaults to an empty string
content: IContent;
}
export interface ICreateRoomOpts {
room_alias_name?: string;
visibility?: Visibility;
name?: string;
topic?: string;
preset?: Preset;
power_level_content_override?: object;
creation_content?: object;
initial_state?: ICreateRoomStateEvent[];
invite?: string[];
invite_3pid?: IInvite3PID[];
is_direct?: boolean;
room_version?: string;
}
export interface IRoomDirectoryOptions {
server?: string;
limit?: number;
since?: string;
filter?: {
generic_search_term: string;
};
include_all_networks?: boolean;
third_party_instance_id?: string;
}
export interface IUploadOpts {
name?: string;
includeFilename?: boolean;
type?: string;
rawResponse?: boolean;
onlyContentUri?: boolean;
callback?: Callback;
progressHandler?: (state: {loaded: number, total: number}) => void;
}
export interface IAddThreePidOnlyBody {
auth?: {
type: string;
session?: string;
};
client_secret: string;
sid: string;
}
export interface IBindThreePidBody {
client_secret: string;
id_server: string;
id_access_token: string;
sid: string;
}
export interface IRelationsRequestOpts {
from?: string;
to?: string;
limit?: number;
}
export interface IRelationsResponse {
original_event: IEvent;
chunk: IEvent[];
next_batch?: string;
prev_batch?: string;
}
/* eslint-enable camelcase */
+118
View File
@@ -0,0 +1,118 @@
/*
Copyright 2021 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.
*/
// Types relating to the /search API
import { IRoomEvent, IStateEvent } from "../sync-accumulator";
import { IRoomEventFilter } from "../filter";
import { SearchResult } from "../models/search-result";
/* eslint-disable camelcase */
export interface IEventWithRoomId extends IRoomEvent {
room_id: string;
}
export interface IStateEventWithRoomId extends IStateEvent {
room_id: string;
}
export interface IMatrixProfile {
avatar_url?: string;
displayname?: string;
}
export interface IResultContext {
events_before: IEventWithRoomId[];
events_after: IEventWithRoomId[];
profile_info: Record<string, IMatrixProfile>;
start?: string;
end?: string;
}
export interface ISearchResult {
rank: number;
result: IEventWithRoomId;
context: IResultContext;
}
enum GroupKey {
RoomId = "room_id",
Sender = "sender",
}
export interface IResultRoomEvents {
count: number;
highlights: string[];
results: ISearchResult[];
state?: { [roomId: string]: IStateEventWithRoomId[] };
groups?: {
[groupKey in GroupKey]: {
[value: string]: {
next_batch?: string;
order: number;
results: string[];
};
};
};
next_batch?: string;
}
interface IResultCategories {
room_events: IResultRoomEvents;
}
export type SearchKey = "content.body" | "content.name" | "content.topic";
export enum SearchOrderBy {
Recent = "recent",
Rank = "rank",
}
export interface ISearchRequestBody {
search_categories: {
room_events: {
search_term: string;
keys?: SearchKey[];
filter?: IRoomEventFilter;
order_by?: SearchOrderBy;
event_context?: {
before_limit?: number;
after_limit?: number;
include_profile?: boolean;
};
include_state?: boolean;
groupings?: {
group_by: {
key: GroupKey;
}[];
};
};
};
}
export interface ISearchResponse {
search_categories: IResultCategories;
}
export interface ISearchResults {
_query?: ISearchRequestBody;
results: SearchResult[];
highlights: string[];
count?: number;
next_batch?: string;
pendingRequest?: Promise<ISearchResults>;
}
/* eslint-enable camelcase */
+25
View File
@@ -0,0 +1,25 @@
/*
Copyright 2021 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 interface ISignatures {
[entity: string]: {
[keyId: string]: string;
};
}
export interface ISigned {
signatures?: ISignatures;
}
+60
View File
@@ -0,0 +1,60 @@
/*
Copyright 2021 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.
*/
import { IPublicRoomsChunkRoom } from "../client";
import { RoomType } from "./event";
import { IStrippedState } from "../sync-accumulator";
// Types relating to Rooms of type `m.space` and related APIs
/* eslint-disable camelcase */
/** @deprecated Use hierarchy instead where possible. */
export interface ISpaceSummaryRoom extends IPublicRoomsChunkRoom {
num_refs: number;
room_type: string;
}
/** @deprecated Use hierarchy instead where possible. */
export interface ISpaceSummaryEvent {
room_id: string;
event_id: string;
origin_server_ts: number;
type: string;
state_key: string;
sender: string;
content: {
order?: string;
suggested?: boolean;
auto_join?: boolean;
via?: string[];
};
}
export interface IHierarchyRelation extends IStrippedState {
room_id: string;
origin_server_ts: number;
content: {
order?: string;
suggested?: boolean;
via?: string[];
};
}
export interface IHierarchyRoom extends IPublicRoomsChunkRoom {
room_type?: RoomType | string;
children_state: IHierarchyRelation[];
}
/* eslint-enable camelcase */
+40
View File
@@ -0,0 +1,40 @@
/*
Copyright 2021 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.
*/
import { IdServerUnbindResult } from "./partials";
// Types relating to Synapse Admin APIs
/* eslint-disable camelcase */
export interface ISynapseAdminWhoisResponse {
user_id: string;
devices: {
[deviceId: string]: {
sessions: {
connections: {
ip: string;
last_seen: number; // millis since epoch
user_agent: string;
}[];
}[];
};
};
}
export interface ISynapseAdminDeactivateResponse {
id_server_unbind_result: IdServerUnbindResult;
}
/* eslint-enable camelcase */
+29
View File
@@ -0,0 +1,29 @@
/*
Copyright 2021 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 enum ThreepidMedium {
Email = "email",
Phone = "msisdn",
}
// TODO: Are these types universal, or specific to just /account/3pid?
export interface IThreepid {
medium: ThreepidMedium;
address: string;
validated_at: number; // eslint-disable-line camelcase
added_at: number; // eslint-disable-line camelcase
bound?: boolean;
}
+93
View File
@@ -0,0 +1,93 @@
/*
Copyright 2021 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.
*/
/**
* Represents a simple Matrix namespaced value. This will assume that if a stable prefix
* is provided that the stable prefix should be used when representing the identifier.
*/
export class NamespacedValue<S extends string, U extends string> {
// Stable is optional, but one of the two parameters is required, hence the weird-looking types.
// Goal is to to have developers explicitly say there is no stable value (if applicable).
public constructor(public readonly stable: S | null | undefined, public readonly unstable?: U) {
if (!this.unstable && !this.stable) {
throw new Error("One of stable or unstable values must be supplied");
}
}
public get name(): U | S {
if (this.stable) {
return this.stable;
}
return this.unstable;
}
public get altName(): U | S | null {
if (!this.stable) {
return null;
}
return this.unstable;
}
public matches(val: string): boolean {
return this.name === val || this.altName === val;
}
// this desperately wants https://github.com/microsoft/TypeScript/pull/26349 at the top level of the class
// so we can instantiate `NamespacedValue<string, _, _>` as a default type for that namespace.
public findIn<T>(obj: any): T {
let val: T;
if (this.name) {
val = obj?.[this.name];
}
if (!val && this.altName) {
val = obj?.[this.altName];
}
return val;
}
public includedIn(arr: any[]): boolean {
let included = false;
if (this.name) {
included = arr.includes(this.name);
}
if (!included && this.altName) {
included = arr.includes(this.altName);
}
return included;
}
}
/**
* Represents a namespaced value which prioritizes the unstable value over the stable
* value.
*/
export class UnstableValue<S extends string, U extends string> extends NamespacedValue<S, U> {
// Note: Constructor difference is that `unstable` is *required*.
public constructor(stable: S, unstable: U) {
super(stable, unstable);
if (!this.unstable) {
throw new Error("Unstable value must be supplied");
}
}
public get name(): U {
return this.unstable;
}
public get altName(): S {
return this.stable;
}
}
-52
View File
@@ -1,52 +0,0 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd
Copyright 2017 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.
*/
/**
* @module
*/
export class ReEmitter {
constructor(target) {
this.target = target;
// We keep one bound event handler for each event name so we know
// what event is arriving
this.boundHandlers = {};
}
_handleEvent(eventName, ...args) {
this.target.emit(eventName, ...args);
}
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 = forSource.bind(this, this.boundHandlers[eventName]);
source.on(eventName, boundHandler);
}
}
}
+50
View File
@@ -0,0 +1,50 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd
Copyright 2017 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.
*/
import { EventEmitter } from "events";
export class ReEmitter {
private target: EventEmitter;
constructor(target: EventEmitter) {
this.target = target;
}
reEmit(source: EventEmitter, eventNames: string[]) {
for (const eventName of 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 = (...args: any[]) => {
// EventEmitter special cases 'error' to make the emit function throw if no
// handler is attached, which sort of makes sense for making sure that something
// handles an error, but for re-emitting, there could be a listener on the original
// source object so the test doesn't really work. We *could* try to replicate the
// same logic and throw if there is no listener on either the source or the target,
// but this behaviour is fairly undesireable for us anyway: the main place we throw
// 'error' events is for calls, where error events are usually emitted some time
// later by a different part of the code where 'emit' throwing because the app hasn't
// added an error handler isn't terribly helpful. (A better fix in retrospect may
// have been to just avoid using the event name 'error', but backwards compat...)
if (eventName === 'error' && this.target.listenerCount('error') === 0) return;
this.target.emit(eventName, ...args, source);
};
source.on(eventName, forSource);
}
}
}
+58 -135
View File
@@ -17,79 +17,20 @@ limitations under the License.
/** @module auto-discovery */
import {logger} from './logger';
import {URL as NodeURL} from "url";
import { URL as NodeURL } from "url";
import { IClientWellKnown, IWellKnownConfig } from "./client";
import { logger } from './logger';
// Dev note: Auto discovery is part of the spec.
// See: https://matrix.org/docs/spec/client_server/r0.4.0.html#server-discovery
/**
* Description for what an automatically discovered client configuration
* would look like. Although this is a class, it is recommended that it
* be treated as an interface definition rather than as a class.
*
* Additional properties than those defined here may be present, and
* should follow the Java package naming convention.
*/
class DiscoveredClientConfig { // eslint-disable-line no-unused-vars
// Dev note: this is basically a copy/paste of the .well-known response
// object as defined in the spec. It does have additional information,
// however. Overall, this exists to serve as a place for documentation
// and not functionality.
// See https://matrix.org/docs/spec/client_server/r0.4.0.html#get-well-known-matrix-client
constructor() {
/**
* The homeserver configuration the client should use. This will
* always be present on the object.
* @type {{state: string, base_url: string}} The configuration.
*/
this["m.homeserver"] = {
/**
* The lookup result state. If this is anything other than
* AutoDiscovery.SUCCESS then base_url may be falsey. Additionally,
* if this is not AutoDiscovery.SUCCESS then the client should
* assume the other properties in the client config (such as
* the identity server configuration) are not valid.
*/
state: AutoDiscovery.PROMPT,
/**
* If the state is AutoDiscovery.FAIL_ERROR or .FAIL_PROMPT
* then this will contain a human-readable (English) message
* for what went wrong. If the state is none of those previously
* mentioned, this will be falsey.
*/
error: "Something went wrong",
/**
* The base URL clients should use to talk to the homeserver,
* particularly for the login process. May be falsey if the
* state is not AutoDiscovery.SUCCESS.
*/
base_url: "https://matrix.org",
};
/**
* The identity server configuration the client should use. This
* will always be present on teh object.
* @type {{state: string, base_url: string}} The configuration.
*/
this["m.identity_server"] = {
/**
* The lookup result state. If this is anything other than
* AutoDiscovery.SUCCESS then base_url may be falsey.
*/
state: AutoDiscovery.PROMPT,
/**
* The base URL clients should use for interacting with the
* identity server. May be falsey if the state is not
* AutoDiscovery.SUCCESS.
*/
base_url: "https://vector.im",
};
}
export enum AutoDiscoveryAction {
SUCCESS = "SUCCESS",
IGNORE = "IGNORE",
PROMPT = "PROMPT",
FAIL_PROMPT = "FAIL_PROMPT",
FAIL_ERROR = "FAIL_ERROR",
}
/**
@@ -102,55 +43,36 @@ export class AutoDiscovery {
// translate the meaning of the states in the spec, but also
// support our own if needed.
static get ERROR_INVALID() {
return "Invalid homeserver discovery response";
}
public static readonly ERROR_INVALID = "Invalid homeserver discovery response";
static get ERROR_GENERIC_FAILURE() {
return "Failed to get autodiscovery configuration from server";
}
public static readonly ERROR_GENERIC_FAILURE = "Failed to get autodiscovery configuration from server";
static get ERROR_INVALID_HS_BASE_URL() {
return "Invalid base_url for m.homeserver";
}
public static readonly ERROR_INVALID_HS_BASE_URL = "Invalid base_url for m.homeserver";
static get ERROR_INVALID_HOMESERVER() {
return "Homeserver URL does not appear to be a valid Matrix homeserver";
}
public static readonly ERROR_INVALID_HOMESERVER = "Homeserver URL does not appear to be a valid Matrix homeserver";
static get ERROR_INVALID_IS_BASE_URL() {
return "Invalid base_url for m.identity_server";
}
public static readonly ERROR_INVALID_IS_BASE_URL = "Invalid base_url for m.identity_server";
static get ERROR_INVALID_IDENTITY_SERVER() {
return "Identity server URL does not appear to be a valid identity server";
}
// eslint-disable-next-line
public static readonly ERROR_INVALID_IDENTITY_SERVER = "Identity server URL does not appear to be a valid identity server";
static get ERROR_INVALID_IS() {
return "Invalid identity server discovery response";
}
public static readonly ERROR_INVALID_IS = "Invalid identity server discovery response";
static get ERROR_MISSING_WELLKNOWN() {
return "No .well-known JSON file found";
}
public static readonly ERROR_MISSING_WELLKNOWN = "No .well-known JSON file found";
static get ERROR_INVALID_JSON() {
return "Invalid JSON";
}
public static readonly ERROR_INVALID_JSON = "Invalid JSON";
static get ALL_ERRORS() {
return [
AutoDiscovery.ERROR_INVALID,
AutoDiscovery.ERROR_GENERIC_FAILURE,
AutoDiscovery.ERROR_INVALID_HS_BASE_URL,
AutoDiscovery.ERROR_INVALID_HOMESERVER,
AutoDiscovery.ERROR_INVALID_IS_BASE_URL,
AutoDiscovery.ERROR_INVALID_IDENTITY_SERVER,
AutoDiscovery.ERROR_INVALID_IS,
AutoDiscovery.ERROR_MISSING_WELLKNOWN,
AutoDiscovery.ERROR_INVALID_JSON,
];
}
public static readonly ALL_ERRORS = [
AutoDiscovery.ERROR_INVALID,
AutoDiscovery.ERROR_GENERIC_FAILURE,
AutoDiscovery.ERROR_INVALID_HS_BASE_URL,
AutoDiscovery.ERROR_INVALID_HOMESERVER,
AutoDiscovery.ERROR_INVALID_IS_BASE_URL,
AutoDiscovery.ERROR_INVALID_IDENTITY_SERVER,
AutoDiscovery.ERROR_INVALID_IS,
AutoDiscovery.ERROR_MISSING_WELLKNOWN,
AutoDiscovery.ERROR_INVALID_JSON,
];
/**
* The auto discovery failed. The client is expected to communicate
@@ -158,7 +80,7 @@ export class AutoDiscovery {
* @return {string}
* @constructor
*/
static get FAIL_ERROR() { return "FAIL_ERROR"; }
public static readonly FAIL_ERROR = AutoDiscoveryAction.FAIL_ERROR;
/**
* The auto discovery failed, however the client may still recover
@@ -169,7 +91,7 @@ export class AutoDiscovery {
* @return {string}
* @constructor
*/
static get FAIL_PROMPT() { return "FAIL_PROMPT"; }
public static readonly FAIL_PROMPT = AutoDiscoveryAction.FAIL_PROMPT;
/**
* The auto discovery didn't fail but did not find anything of
@@ -178,14 +100,14 @@ export class AutoDiscovery {
* @return {string}
* @constructor
*/
static get PROMPT() { return "PROMPT"; }
public static readonly PROMPT = AutoDiscoveryAction.PROMPT;
/**
* The auto discovery was successful.
* @return {string}
* @constructor
*/
static get SUCCESS() { return "SUCCESS"; }
public static readonly SUCCESS = AutoDiscoveryAction.SUCCESS;
/**
* Validates and verifies client configuration information for purposes
@@ -193,13 +115,13 @@ export class AutoDiscovery {
* and identity server URL the client would want. Additional details
* may also be included, and will be transparently brought into the
* response object unaltered.
* @param {string} wellknown The configuration object itself, as returned
* @param {object} wellknown The configuration object itself, as returned
* by the .well-known auto-discovery endpoint.
* @return {Promise<DiscoveredClientConfig>} Resolves to the verified
* configuration, which may include error states. Rejects on unexpected
* failure, not when verification fails.
*/
static async fromDiscoveryConfig(wellknown) {
public static async fromDiscoveryConfig(wellknown: any): Promise<IClientWellKnown> {
// Step 1 is to get the config, which is provided to us here.
// We default to an error state to make the first few checks easier to
@@ -240,7 +162,7 @@ export class AutoDiscovery {
// Step 2: Make sure the homeserver URL is valid *looking*. We'll make
// sure it points to a homeserver in Step 3.
const hsUrl = this._sanitizeWellKnownUrl(
const hsUrl = this.sanitizeWellKnownUrl(
wellknown["m.homeserver"]["base_url"],
);
if (!hsUrl) {
@@ -250,7 +172,7 @@ export class AutoDiscovery {
}
// Step 3: Make sure the homeserver URL points to a homeserver.
const hsVersions = await this._fetchWellKnownObject(
const hsVersions = await this.fetchWellKnownObject(
`${hsUrl}/_matrix/client/versions`,
);
if (!hsVersions || !hsVersions.raw["versions"]) {
@@ -272,7 +194,7 @@ export class AutoDiscovery {
};
// Step 5: Try to pull out the identity server configuration
let isUrl = "";
let isUrl: string | boolean = "";
if (wellknown["m.identity_server"]) {
// We prepare a failing identity server response to save lines later
// in this branch.
@@ -287,7 +209,7 @@ export class AutoDiscovery {
// Step 5a: Make sure the URL is valid *looking*. We'll make sure it
// points to an identity server in Step 5b.
isUrl = this._sanitizeWellKnownUrl(
isUrl = this.sanitizeWellKnownUrl(
wellknown["m.identity_server"]["base_url"],
);
if (!isUrl) {
@@ -299,10 +221,10 @@ export class AutoDiscovery {
// Step 5b: Verify there is an identity server listening on the provided
// URL.
const isResponse = await this._fetchWellKnownObject(
const isResponse = await this.fetchWellKnownObject(
`${isUrl}/_matrix/identity/api/v1`,
);
if (!isResponse || !isResponse.raw || isResponse.action !== "SUCCESS") {
if (!isResponse || !isResponse.raw || isResponse.action !== AutoDiscoveryAction.SUCCESS) {
logger.error("Invalid /api/v1 response");
failingClientConfig["m.identity_server"].error =
AutoDiscovery.ERROR_INVALID_IDENTITY_SERVER;
@@ -317,7 +239,7 @@ export class AutoDiscovery {
// Step 6: Now that the identity server is valid, or never existed,
// populate the IS section.
if (isUrl && isUrl.length > 0) {
if (isUrl && isUrl.toString().length > 0) {
clientConfig["m.identity_server"] = {
state: AutoDiscovery.SUCCESS,
error: null,
@@ -359,7 +281,7 @@ export class AutoDiscovery {
* configuration, which may include error states. Rejects on unexpected
* failure, not when discovery fails.
*/
static async findClientConfig(domain) {
public static async findClientConfig(domain: string): Promise<IClientWellKnown> {
if (!domain || typeof(domain) !== "string" || domain.length === 0) {
throw new Error("'domain' must be a string of non-zero length");
}
@@ -395,13 +317,13 @@ export class AutoDiscovery {
// Step 1: Actually request the .well-known JSON file and make sure it
// at least has a homeserver definition.
const wellknown = await this._fetchWellKnownObject(
const wellknown = await this.fetchWellKnownObject(
`https://${domain}/.well-known/matrix/client`,
);
if (!wellknown || wellknown.action !== "SUCCESS") {
if (!wellknown || wellknown.action !== AutoDiscoveryAction.SUCCESS) {
logger.error("No response or error when parsing .well-known");
if (wellknown.reason) logger.error(wellknown.reason);
if (wellknown.action === "IGNORE") {
if (wellknown.action === AutoDiscoveryAction.IGNORE) {
clientConfig["m.homeserver"] = {
state: AutoDiscovery.PROMPT,
error: null,
@@ -427,12 +349,12 @@ export class AutoDiscovery {
* @returns {Promise<object>} Resolves to the domain's client config. Can
* be an empty object.
*/
static async getRawClientConfig(domain) {
public static async getRawClientConfig(domain: string): Promise<IClientWellKnown> {
if (!domain || typeof(domain) !== "string" || domain.length === 0) {
throw new Error("'domain' must be a string of non-zero length");
}
const response = await this._fetchWellKnownObject(
const response = await this.fetchWellKnownObject(
`https://${domain}/.well-known/matrix/client`,
);
if (!response) return {};
@@ -447,7 +369,7 @@ export class AutoDiscovery {
* @return {string|boolean} The sanitized URL or a falsey value if the URL is invalid.
* @private
*/
static _sanitizeWellKnownUrl(url) {
private static sanitizeWellKnownUrl(url: string): string | boolean {
if (!url) return false;
try {
@@ -495,8 +417,9 @@ export class AutoDiscovery {
* @return {Promise<object>} Resolves to the returned state.
* @private
*/
static async _fetchWellKnownObject(url) {
private static async fetchWellKnownObject(url: string): Promise<IWellKnownConfig> {
return new Promise(function(resolve, reject) {
// eslint-disable-next-line
const request = require("./matrix").getRequest();
if (!request) throw new Error("No request library available");
request(
@@ -505,18 +428,18 @@ export class AutoDiscovery {
if (err || response &&
(response.statusCode < 200 || response.statusCode >= 300)
) {
let action = "FAIL_PROMPT";
let action = AutoDiscoveryAction.FAIL_PROMPT;
let reason = (err ? err.message : null) || "General failure";
if (response && response.statusCode === 404) {
action = "IGNORE";
action = AutoDiscoveryAction.IGNORE;
reason = AutoDiscovery.ERROR_MISSING_WELLKNOWN;
}
resolve({raw: {}, action: action, reason: reason, error: err});
resolve({ raw: {}, action: action, reason: reason, error: err });
return;
}
try {
resolve({raw: JSON.parse(body), action: "SUCCESS"});
resolve({ raw: JSON.parse(body), action: AutoDiscoveryAction.SUCCESS });
} catch (e) {
let reason = AutoDiscovery.ERROR_INVALID;
if (e.name === "SyntaxError") {
@@ -524,7 +447,7 @@ export class AutoDiscovery {
}
resolve({
raw: {},
action: "FAIL_PROMPT",
action: AutoDiscoveryAction.FAIL_PROMPT,
reason: reason,
error: e,
});
-2376
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -14,10 +14,11 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import * as matrixcs from "./matrix";
import request from "browser-request";
import queryString from "qs";
import * as matrixcs from "./matrix";
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
-5923
View File
File diff suppressed because it is too large Load Diff
+9251
View File
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,6 @@
/*
Copyright 2018 New Vector Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Copyright 2018 - 2021 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.
@@ -17,15 +17,17 @@ limitations under the License.
/** @module ContentHelpers */
import { MsgType } from "./@types/event";
/**
* Generates the content for a HTML Message event
* @param {string} body the plaintext body of the message
* @param {string} htmlBody the HTML representation of the message
* @returns {{msgtype: string, format: string, body: string, formatted_body: string}}
*/
export function makeHtmlMessage(body, htmlBody) {
export function makeHtmlMessage(body: string, htmlBody: string) {
return {
msgtype: "m.text",
msgtype: MsgType.Text,
format: "org.matrix.custom.html",
body: body,
formatted_body: htmlBody,
@@ -38,9 +40,9 @@ export function makeHtmlMessage(body, htmlBody) {
* @param {string} htmlBody the HTML representation of the notice
* @returns {{msgtype: string, format: string, body: string, formatted_body: string}}
*/
export function makeHtmlNotice(body, htmlBody) {
export function makeHtmlNotice(body: string, htmlBody: string) {
return {
msgtype: "m.notice",
msgtype: MsgType.Notice,
format: "org.matrix.custom.html",
body: body,
formatted_body: htmlBody,
@@ -53,9 +55,9 @@ export function makeHtmlNotice(body, htmlBody) {
* @param {string} htmlBody the HTML representation of the emote
* @returns {{msgtype: string, format: string, body: string, formatted_body: string}}
*/
export function makeHtmlEmote(body, htmlBody) {
export function makeHtmlEmote(body: string, htmlBody: string) {
return {
msgtype: "m.emote",
msgtype: MsgType.Emote,
format: "org.matrix.custom.html",
body: body,
formatted_body: htmlBody,
@@ -67,9 +69,9 @@ export function makeHtmlEmote(body, htmlBody) {
* @param {string} body the plaintext body of the emote
* @returns {{msgtype: string, body: string}}
*/
export function makeTextMessage(body) {
export function makeTextMessage(body: string) {
return {
msgtype: "m.text",
msgtype: MsgType.Text,
body: body,
};
}
@@ -79,9 +81,9 @@ export function makeTextMessage(body) {
* @param {string} body the plaintext body of the notice
* @returns {{msgtype: string, body: string}}
*/
export function makeNotice(body) {
export function makeNotice(body: string) {
return {
msgtype: "m.notice",
msgtype: MsgType.Notice,
body: body,
};
}
@@ -91,9 +93,9 @@ export function makeNotice(body) {
* @param {string} body the plaintext body of the emote
* @returns {{msgtype: string, body: string}}
*/
export function makeEmoteMessage(body) {
export function makeEmoteMessage(body: string) {
return {
msgtype: "m.emote",
msgtype: MsgType.Emote,
body: body,
};
}
+17 -12
View File
@@ -1,6 +1,5 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Copyright 2015 - 2021 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.
@@ -34,8 +33,14 @@ import * as utils from "./utils";
* for such URLs.
* @return {string} The complete URL to the content.
*/
export function getHttpUriForMxc(baseUrl, mxc, width, height,
resizeMethod, allowDirectLinks) {
export function getHttpUriForMxc(
baseUrl: string,
mxc: string,
width: number,
height: number,
resizeMethod: string,
allowDirectLinks = false,
): string {
if (typeof mxc !== "string" || !mxc) {
return '';
}
@@ -48,18 +53,18 @@ export function getHttpUriForMxc(baseUrl, mxc, width, height,
}
let serverAndMediaId = mxc.slice(6); // strips mxc://
let prefix = "/_matrix/media/r0/download/";
const params = {};
const params: Record<string, string> = {};
if (width) {
params.width = Math.round(width);
params["width"] = Math.round(width).toString();
}
if (height) {
params.height = Math.round(height);
params["height"] = Math.round(height).toString();
}
if (resizeMethod) {
params.method = resizeMethod;
params["method"] = resizeMethod;
}
if (utils.keys(params).length > 0) {
if (Object.keys(params).length > 0) {
// these are thumbnailing params so they probably want the
// thumbnailing API...
prefix = "/_matrix/media/r0/thumbnail/";
@@ -71,7 +76,7 @@ export function getHttpUriForMxc(baseUrl, mxc, width, height,
fragment = serverAndMediaId.substr(fragmentOffset);
serverAndMediaId = serverAndMediaId.substr(0, fragmentOffset);
}
return baseUrl + prefix + serverAndMediaId +
(utils.keys(params).length === 0 ? "" :
("?" + utils.encodeParams(params))) + fragment;
const urlParams = (Object.keys(params).length === 0 ? "" : ("?" + utils.encodeParams(params)));
return baseUrl + prefix + serverAndMediaId + urlParams + fragment;
}
@@ -1,6 +1,5 @@
/*
Copyright 2019 New Vector Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Copyright 2019 - 2021 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.
@@ -20,22 +19,51 @@ limitations under the License.
* @module crypto/CrossSigning
*/
import {decodeBase64, encodeBase64, pkSign, pkVerify} from './olmlib';
import {EventEmitter} from 'events';
import {logger} from '../logger';
import {IndexedDBCryptoStore} from '../crypto/store/indexeddb-crypto-store';
import {decryptAES, encryptAES} from './aes';
import { EventEmitter } from 'events';
import { PkSigning } from "@matrix-org/olm";
import { decodeBase64, encodeBase64, pkSign, pkVerify } from './olmlib';
import { logger } from '../logger';
import { IndexedDBCryptoStore } from '../crypto/store/indexeddb-crypto-store';
import { decryptAES, encryptAES } from './aes';
import { DeviceInfo } from "./deviceinfo";
import { SecretStorage } from "./SecretStorage";
import { ICrossSigningKey, ISignedKey, MatrixClient } from "../client";
import { OlmDevice } from "./OlmDevice";
import { ICryptoCallbacks } from "../matrix";
import { ISignatures } from "../@types/signed";
import { CryptoStore } from "./store/base";
const KEY_REQUEST_TIMEOUT_MS = 1000 * 60;
function publicKeyFromKeyInfo(keyInfo) {
function publicKeyFromKeyInfo(keyInfo: ICrossSigningKey): string {
// `keys` is an object with { [`ed25519:${pubKey}`]: pubKey }
// We assume only a single key, and we want the bare form without type
// prefix, so we select the values.
return Object.values(keyInfo.keys)[0];
}
export interface ICacheCallbacks {
getCrossSigningKeyCache?(type: string, expectedPublicKey?: string): Promise<Uint8Array>;
storeCrossSigningKeyCache?(type: string, key: Uint8Array): Promise<void>;
}
export interface ICrossSigningInfo {
keys: Record<string, ICrossSigningKey>;
firstUse: boolean;
crossSigningVerifiedBefore: boolean;
}
export class CrossSigningInfo extends EventEmitter {
public keys: Record<string, ICrossSigningKey> = {};
public firstUse = true;
// This tracks whether we've ever verified this user with any identity.
// When you verify a user, any devices online at the time that receive
// the verifying signature via the homeserver will latch this to true
// and can use it in the future to detect cases where the user has
// become unverified later for any reason.
private crossSigningVerifiedBefore = false;
/**
* Information about a user's cross-signing keys
*
@@ -46,27 +74,15 @@ export class CrossSigningInfo extends EventEmitter {
* Requires getCrossSigningKey and saveCrossSigningKeys
* @param {object} cacheCallbacks Callbacks used to interact with the cache
*/
constructor(userId, callbacks, cacheCallbacks) {
constructor(
public readonly userId: string,
private callbacks: ICryptoCallbacks = {},
private cacheCallbacks: ICacheCallbacks = {},
) {
super();
// you can't change the userId
Object.defineProperty(this, 'userId', {
enumerable: true,
value: userId,
});
this._callbacks = callbacks || {};
this._cacheCallbacks = cacheCallbacks || {};
this.keys = {};
this.firstUse = true;
// This tracks whether we've ever verified this user with any identity.
// When you verify a user, any devices online at the time that receive
// the verifying signature via the homeserver will latch this to true
// and can use it in the future to detect cases where the user has
// become unverifed later for any reason.
this.crossSigningVerifiedBefore = false;
}
static fromStorage(obj, userId) {
public static fromStorage(obj: ICrossSigningInfo, userId: string): CrossSigningInfo {
const res = new CrossSigningInfo(userId);
for (const prop in obj) {
if (obj.hasOwnProperty(prop)) {
@@ -76,7 +92,7 @@ export class CrossSigningInfo extends EventEmitter {
return res;
}
toStorage() {
public toStorage(): ICrossSigningInfo {
return {
keys: this.keys,
firstUse: this.firstUse,
@@ -92,10 +108,10 @@ export class CrossSigningInfo extends EventEmitter {
* the stored public key for the given key type.
* @returns {Array} An array with [ public key, Olm.PkSigning ]
*/
async getCrossSigningKey(type, expectedPubkey) {
public async getCrossSigningKey(type: string, expectedPubkey?: string): Promise<[string, PkSigning]> {
const shouldCache = ["master", "self_signing", "user_signing"].indexOf(type) >= 0;
if (!this._callbacks.getCrossSigningKey) {
if (!this.callbacks.getCrossSigningKey) {
throw new Error("No getCrossSigningKey callback supplied");
}
@@ -103,7 +119,7 @@ export class CrossSigningInfo extends EventEmitter {
expectedPubkey = this.getId(type);
}
function validateKey(key) {
function validateKey(key: Uint8Array): [string, PkSigning] {
if (!key) return;
const signing = new global.Olm.PkSigning();
const gotPubkey = signing.init_with_seed(key);
@@ -114,9 +130,8 @@ export class CrossSigningInfo extends EventEmitter {
}
let privkey;
if (this._cacheCallbacks.getCrossSigningKeyCache && shouldCache) {
privkey = await this._cacheCallbacks
.getCrossSigningKeyCache(type, expectedPubkey);
if (this.cacheCallbacks.getCrossSigningKeyCache && shouldCache) {
privkey = await this.cacheCallbacks.getCrossSigningKeyCache(type, expectedPubkey);
}
const cacheresult = validateKey(privkey);
@@ -124,11 +139,11 @@ export class CrossSigningInfo extends EventEmitter {
return cacheresult;
}
privkey = await this._callbacks.getCrossSigningKey(type, expectedPubkey);
privkey = await this.callbacks.getCrossSigningKey(type, expectedPubkey);
const result = validateKey(privkey);
if (result) {
if (this._cacheCallbacks.storeCrossSigningKeyCache && shouldCache) {
await this._cacheCallbacks.storeCrossSigningKeyCache(type, privkey);
if (this.cacheCallbacks.storeCrossSigningKeyCache && shouldCache) {
await this.cacheCallbacks.storeCrossSigningKeyCache(type, privkey);
}
return result;
}
@@ -156,10 +171,9 @@ export class CrossSigningInfo extends EventEmitter {
* with, or null if it is not present or not encrypted with a trusted
* key
*/
async isStoredInSecretStorage(secretStorage) {
public async isStoredInSecretStorage(secretStorage: SecretStorage): Promise<Record<string, object>> {
// check what SSSS keys have encrypted the master key (if any)
const stored =
await secretStorage.isStored("m.cross_signing.master", false) || {};
const stored = await secretStorage.isStored("m.cross_signing.master", false) || {};
// then check which of those SSSS keys have also encrypted the SSK and USK
function intersect(s) {
for (const k of Object.keys(stored)) {
@@ -169,9 +183,7 @@ export class CrossSigningInfo extends EventEmitter {
}
}
for (const type of ["self_signing", "user_signing"]) {
intersect(
await secretStorage.isStored(`m.cross_signing.${type}`, false) || {},
);
intersect(await secretStorage.isStored(`m.cross_signing.${type}`, false) || {});
}
return Object.keys(stored).length ? stored : null;
}
@@ -184,7 +196,10 @@ export class CrossSigningInfo extends EventEmitter {
* @param {Map} keys The keys to store
* @param {SecretStorage} secretStorage The secret store using account data
*/
static async storeInSecretStorage(keys, secretStorage) {
public static async storeInSecretStorage(
keys: Map<string, Uint8Array>,
secretStorage: SecretStorage,
): Promise<void> {
for (const [type, privateKey] of keys) {
const encodedKey = encodeBase64(privateKey);
await secretStorage.store(`m.cross_signing.${type}`, encodedKey);
@@ -200,7 +215,7 @@ export class CrossSigningInfo extends EventEmitter {
* @param {SecretStorage} secretStorage The secret store using account data
* @return {Uint8Array} The private key
*/
static async getFromSecretStorage(type, secretStorage) {
public static async getFromSecretStorage(type: string, secretStorage: SecretStorage): Promise<Uint8Array> {
const encodedKey = await secretStorage.get(`m.cross_signing.${type}`);
if (!encodedKey) {
return null;
@@ -215,8 +230,8 @@ export class CrossSigningInfo extends EventEmitter {
* "self_signing", or "user_signing". Optional, will check all by default.
* @returns {boolean} True if all keys are stored in the local cache.
*/
async isStoredInKeyCache(type) {
const cacheCallbacks = this._cacheCallbacks;
public async isStoredInKeyCache(type?: string): Promise<boolean> {
const cacheCallbacks = this.cacheCallbacks;
if (!cacheCallbacks) return false;
const types = type ? [type] : ["master", "self_signing", "user_signing"];
for (const t of types) {
@@ -232,9 +247,9 @@ export class CrossSigningInfo extends EventEmitter {
*
* @returns {Map} A map from key type (string) to private key (Uint8Array)
*/
async getCrossSigningKeysFromCache() {
public async getCrossSigningKeysFromCache(): Promise<Map<string, Uint8Array>> {
const keys = new Map();
const cacheCallbacks = this._cacheCallbacks;
const cacheCallbacks = this.cacheCallbacks;
if (!cacheCallbacks) return keys;
for (const type of ["master", "self_signing", "user_signing"]) {
const privKey = await cacheCallbacks.getCrossSigningKeyCache(type);
@@ -255,8 +270,7 @@ export class CrossSigningInfo extends EventEmitter {
*
* @return {string} the ID
*/
getId(type) {
type = type || "master";
public getId(type = "master"): string {
if (!this.keys[type]) return null;
const keyInfo = this.keys[type];
return publicKeyFromKeyInfo(keyInfo);
@@ -269,8 +283,8 @@ export class CrossSigningInfo extends EventEmitter {
*
* @param {CrossSigningLevel} level The key types to reset
*/
async resetKeys(level) {
if (!this._callbacks.saveCrossSigningKeys) {
public async resetKeys(level?: CrossSigningLevel): Promise<void> {
if (!this.callbacks.saveCrossSigningKeys) {
throw new Error("No saveCrossSigningKeys callback supplied");
}
@@ -285,12 +299,12 @@ export class CrossSigningInfo extends EventEmitter {
CrossSigningLevel.USER_SIGNING |
CrossSigningLevel.SELF_SIGNING
);
} else if (level === 0) {
} else if (level === 0 as CrossSigningLevel) {
return;
}
const privateKeys = {};
const keys = {};
const privateKeys: Record<string, Uint8Array> = {};
const keys: Record<string, ICrossSigningKey> = {};
let masterSigning;
let masterPub;
@@ -347,7 +361,7 @@ export class CrossSigningInfo extends EventEmitter {
}
Object.assign(this.keys, keys);
this._callbacks.saveCrossSigningKeys(privateKeys);
this.callbacks.saveCrossSigningKeys(privateKeys);
} finally {
if (masterSigning) {
masterSigning.free();
@@ -358,12 +372,12 @@ export class CrossSigningInfo extends EventEmitter {
/**
* unsets the keys, used when another session has reset the keys, to disable cross-signing
*/
clearKeys() {
public clearKeys(): void {
this.keys = {};
}
setKeys(keys) {
const signingKeys = {};
public setKeys(keys: Record<string, ICrossSigningKey>): void {
const signingKeys: Record<string, ICrossSigningKey> = {};
if (keys.master) {
if (keys.master.user_id !== this.userId) {
const error = "Mismatched user ID " + keys.master.user_id +
@@ -434,7 +448,7 @@ export class CrossSigningInfo extends EventEmitter {
}
}
updateCrossSigningVerifiedBefore(isCrossSigningVerified) {
public updateCrossSigningVerifiedBefore(isCrossSigningVerified: boolean): void {
// It is critical that this value latches forward from false to true but
// never back to false to avoid a downgrade attack.
if (!this.crossSigningVerifiedBefore && isCrossSigningVerified) {
@@ -442,7 +456,7 @@ export class CrossSigningInfo extends EventEmitter {
}
}
async signObject(data, type) {
public async signObject<T extends object>(data: T, type: string): Promise<T & { signatures: ISignatures }> {
if (!this.keys[type]) {
throw new Error(
"Attempted to sign with " + type + " key but no such key present",
@@ -451,13 +465,13 @@ export class CrossSigningInfo extends EventEmitter {
const [pubkey, signing] = await this.getCrossSigningKey(type);
try {
pkSign(data, signing, this.userId, pubkey);
return data;
return data as T & { signatures: ISignatures };
} finally {
signing.free();
}
}
async signUser(key) {
public async signUser(key: CrossSigningInfo): Promise<ICrossSigningKey> {
if (!this.keys.user_signing) {
logger.info("No user signing key: not signing user");
return;
@@ -465,7 +479,7 @@ export class CrossSigningInfo extends EventEmitter {
return this.signObject(key.keys.master, "user_signing");
}
async signDevice(userId, device) {
public async signDevice(userId: string, device: DeviceInfo): Promise<ISignedKey> {
if (userId !== this.userId) {
throw new Error(
`Trying to sign ${userId}'s device; can only sign our own device`,
@@ -475,7 +489,7 @@ export class CrossSigningInfo extends EventEmitter {
logger.info("No self signing key: not signing device");
return;
}
return this.signObject(
return this.signObject<Omit<ISignedKey, "signatures">>(
{
algorithms: device.algorithms,
keys: device.keys,
@@ -492,7 +506,7 @@ export class CrossSigningInfo extends EventEmitter {
*
* @returns {UserTrustLevel}
*/
checkUserTrust(userCrossSigning) {
public checkUserTrust(userCrossSigning: CrossSigningInfo): UserTrustLevel {
// if we're checking our own key, then it's trusted if the master key
// and self-signing key match
if (this.userId === userCrossSigning.userId
@@ -530,12 +544,17 @@ export class CrossSigningInfo extends EventEmitter {
*
* @param {CrossSigningInfo} userCrossSigning Cross signing info for user
* @param {module:crypto/deviceinfo} device The device to check
* @param {bool} localTrust Whether the device is trusted locally
* @param {bool} trustCrossSignedDevices Whether we trust cross signed devices
* @param {boolean} localTrust Whether the device is trusted locally
* @param {boolean} trustCrossSignedDevices Whether we trust cross signed devices
*
* @returns {DeviceTrustLevel}
*/
checkDeviceTrust(userCrossSigning, device, localTrust, trustCrossSignedDevices) {
public checkDeviceTrust(
userCrossSigning: CrossSigningInfo,
device: DeviceInfo,
localTrust: boolean,
trustCrossSignedDevices: boolean,
): DeviceTrustLevel {
const userTrust = this.checkUserTrust(userCrossSigning);
const userSSK = userCrossSigning.keys.self_signing;
@@ -552,29 +571,23 @@ export class CrossSigningInfo extends EventEmitter {
// if we can verify the user's SSK from their master key...
pkVerify(userSSK, userCrossSigning.getId(), userCrossSigning.userId);
// ...and this device's key from their SSK...
pkVerify(
deviceObj, publicKeyFromKeyInfo(userSSK), userCrossSigning.userId,
);
pkVerify(deviceObj, publicKeyFromKeyInfo(userSSK), userCrossSigning.userId);
// ...then we trust this device as much as far as we trust the user
return DeviceTrustLevel.fromUserTrustLevel(
userTrust, localTrust, trustCrossSignedDevices,
);
return DeviceTrustLevel.fromUserTrustLevel(userTrust, localTrust, trustCrossSignedDevices);
} catch (e) {
return new DeviceTrustLevel(
false, false, localTrust, trustCrossSignedDevices,
);
return new DeviceTrustLevel(false, false, localTrust, trustCrossSignedDevices);
}
}
/**
* @returns {object} Cache callbacks
*/
getCacheCallbacks() {
return this._cacheCallbacks;
public getCacheCallbacks(): ICacheCallbacks {
return this.cacheCallbacks;
}
}
function deviceToObject(device, userId) {
function deviceToObject(device: DeviceInfo, userId: string) {
return {
algorithms: device.algorithms,
keys: device.keys,
@@ -584,49 +597,49 @@ function deviceToObject(device, userId) {
};
}
export const CrossSigningLevel = {
MASTER: 4,
USER_SIGNING: 2,
SELF_SIGNING: 1,
};
export enum CrossSigningLevel {
MASTER = 4,
USER_SIGNING = 2,
SELF_SIGNING = 1,
}
/**
* Represents the ways in which we trust a user
*/
export class UserTrustLevel {
constructor(crossSigningVerified, crossSigningVerifiedBefore, tofu) {
this._crossSigningVerified = crossSigningVerified;
this._crossSigningVerifiedBefore = crossSigningVerifiedBefore;
this._tofu = tofu;
}
constructor(
private readonly crossSigningVerified: boolean,
private readonly crossSigningVerifiedBefore: boolean,
private readonly tofu: boolean,
) {}
/**
* @returns {bool} true if this user is verified via any means
* @returns {boolean} true if this user is verified via any means
*/
isVerified() {
public isVerified(): boolean {
return this.isCrossSigningVerified();
}
/**
* @returns {bool} true if this user is verified via cross signing
* @returns {boolean} true if this user is verified via cross signing
*/
isCrossSigningVerified() {
return this._crossSigningVerified;
public isCrossSigningVerified(): boolean {
return this.crossSigningVerified;
}
/**
* @returns {bool} true if we ever verified this user before (at least for
* @returns {boolean} true if we ever verified this user before (at least for
* the history of verifications observed by this device).
*/
wasCrossSigningVerified() {
return this._crossSigningVerifiedBefore;
public wasCrossSigningVerified(): boolean {
return this.crossSigningVerifiedBefore;
}
/**
* @returns {bool} true if this user's key is trusted on first use
* @returns {boolean} true if this user's key is trusted on first use
*/
isTofu() {
return this._tofu;
public isTofu(): boolean {
return this.tofu;
}
}
@@ -634,58 +647,62 @@ export class UserTrustLevel {
* Represents the ways in which we trust a device
*/
export class DeviceTrustLevel {
constructor(crossSigningVerified, tofu, localVerified, trustCrossSignedDevices) {
this._crossSigningVerified = crossSigningVerified;
this._tofu = tofu;
this._localVerified = localVerified;
this._trustCrossSignedDevices = trustCrossSignedDevices;
}
constructor(
public readonly crossSigningVerified: boolean,
public readonly tofu: boolean,
private readonly localVerified: boolean,
private readonly trustCrossSignedDevices: boolean,
) {}
static fromUserTrustLevel(userTrustLevel, localVerified, trustCrossSignedDevices) {
public static fromUserTrustLevel(
userTrustLevel: UserTrustLevel,
localVerified: boolean,
trustCrossSignedDevices: boolean,
): DeviceTrustLevel {
return new DeviceTrustLevel(
userTrustLevel._crossSigningVerified,
userTrustLevel._tofu,
userTrustLevel.isCrossSigningVerified(),
userTrustLevel.isTofu(),
localVerified,
trustCrossSignedDevices,
);
}
/**
* @returns {bool} true if this device is verified via any means
* @returns {boolean} true if this device is verified via any means
*/
isVerified() {
public isVerified(): boolean {
return Boolean(this.isLocallyVerified() || (
this._trustCrossSignedDevices && this.isCrossSigningVerified()
this.trustCrossSignedDevices && this.isCrossSigningVerified()
));
}
/**
* @returns {bool} true if this device is verified via cross signing
* @returns {boolean} true if this device is verified via cross signing
*/
isCrossSigningVerified() {
return this._crossSigningVerified;
public isCrossSigningVerified(): boolean {
return this.crossSigningVerified;
}
/**
* @returns {bool} true if this device is verified locally
* @returns {boolean} true if this device is verified locally
*/
isLocallyVerified() {
return this._localVerified;
public isLocallyVerified(): boolean {
return this.localVerified;
}
/**
* @returns {bool} true if this device is trusted from a user's key
* @returns {boolean} true if this device is trusted from a user's key
* that is trusted on first use
*/
isTofu() {
return this._tofu;
public isTofu(): boolean {
return this.tofu;
}
}
export function createCryptoStoreCacheCallbacks(store, olmdevice) {
export function createCryptoStoreCacheCallbacks(store: CryptoStore, olmDevice: OlmDevice): ICacheCallbacks {
return {
getCrossSigningKeyCache: async function(type, _expectedPublicKey) {
const key = await new Promise((resolve) => {
getCrossSigningKeyCache: async function(type: string, _expectedPublicKey: string): Promise<Uint8Array> {
const key = await new Promise<any>((resolve) => {
return store.doTxn(
'readonly',
[IndexedDBCryptoStore.STORE_ACCOUNT],
@@ -696,50 +713,56 @@ export function createCryptoStoreCacheCallbacks(store, olmdevice) {
});
if (key && key.ciphertext) {
const pickleKey = Buffer.from(olmdevice._pickleKey);
const pickleKey = Buffer.from(olmDevice.pickleKey);
const decrypted = await decryptAES(key, pickleKey, type);
return decodeBase64(decrypted);
} else {
return key;
}
},
storeCrossSigningKeyCache: async function(type, key) {
storeCrossSigningKeyCache: async function(type: string, key: Uint8Array): Promise<void> {
if (!(key instanceof Uint8Array)) {
throw new Error(
`storeCrossSigningKeyCache expects Uint8Array, got ${key}`,
);
}
const pickleKey = Buffer.from(olmdevice._pickleKey);
key = await encryptAES(encodeBase64(key), pickleKey, type);
const pickleKey = Buffer.from(olmDevice.pickleKey);
const encryptedKey = await encryptAES(encodeBase64(key), pickleKey, type);
return store.doTxn(
'readwrite',
[IndexedDBCryptoStore.STORE_ACCOUNT],
(txn) => {
store.storeSecretStorePrivateKey(txn, type, key);
store.storeSecretStorePrivateKey(txn, type, encryptedKey);
},
);
},
};
}
export type KeysDuringVerification = [[string, PkSigning], [string, PkSigning], [string, PkSigning], void];
/**
* Request cross-signing keys from another device during verification.
*
* @param {module:base-apis~MatrixBaseApis} baseApis base Matrix API interface
* @param {MatrixClient} baseApis base Matrix API interface
* @param {string} userId The user ID being verified
* @param {string} deviceId The device ID being verified
*/
export async function requestKeysDuringVerification(baseApis, userId, deviceId) {
export function requestKeysDuringVerification(
baseApis: MatrixClient,
userId: string,
deviceId: string,
): Promise<KeysDuringVerification | void> {
// If this is a self-verification, ask the other party for keys
if (baseApis.getUserId() !== userId) {
return;
}
logger.log("Cross-signing: Self-verification done; requesting keys");
// This happens asynchronously, and we're not concerned about waiting for
// it. We return here in order to test.
return new Promise((resolve, reject) => {
// it. We return here in order to test.
return new Promise<KeysDuringVerification | void>((resolve, reject) => {
const client = baseApis;
const original = client._crypto._crossSigningInfo;
const original = client.crypto.crossSigningInfo;
// We already have all of the infrastructure we need to validate and
// cache cross-signing keys, so instead of replicating that, here we set
@@ -748,8 +771,7 @@ export async function requestKeysDuringVerification(baseApis, userId, deviceId)
const crossSigning = new CrossSigningInfo(
original.userId,
{ getCrossSigningKey: async (type) => {
logger.debug("Cross-signing: requesting secret",
type, deviceId);
logger.debug("Cross-signing: requesting secret", type, deviceId);
const { promise } = client.requestSecret(
`m.cross_signing.${type}`, [deviceId],
);
@@ -757,7 +779,7 @@ export async function requestKeysDuringVerification(baseApis, userId, deviceId)
const decoded = decodeBase64(result);
return Uint8Array.from(decoded);
} },
original._cacheCallbacks,
original.getCacheCallbacks(),
);
crossSigning.keys = original.keys;
@@ -765,7 +787,7 @@ export async function requestKeysDuringVerification(baseApis, userId, deviceId)
// https://github.com/vector-im/element-web/issues/12604
// then change here to reject on the timeout
// Requests can be ignored, so don't wait around forever
const timeout = new Promise((resolve, reject) => {
const timeout = new Promise<void>((resolve) => {
setTimeout(
resolve,
KEY_REQUEST_TIMEOUT_MS,
@@ -774,8 +796,8 @@ export async function requestKeysDuringVerification(baseApis, userId, deviceId)
});
// also request and cache the key backup key
const backupKeyPromise = new Promise(async resolve => {
const cachedKey = await client._crypto.getSessionBackupPrivateKey();
const backupKeyPromise = (async () => {
const cachedKey = await client.crypto.getSessionBackupPrivateKey();
if (!cachedKey) {
logger.info("No cached backup key found. Requesting...");
const secretReq = client.requestSecret(
@@ -785,29 +807,26 @@ export async function requestKeysDuringVerification(baseApis, userId, deviceId)
logger.info("Got key backup key, decoding...");
const decodedKey = decodeBase64(base64Key);
logger.info("Decoded backup key, storing...");
client._crypto.storeSessionBackupPrivateKey(
await client.crypto.storeSessionBackupPrivateKey(
Uint8Array.from(decodedKey),
);
logger.info("Backup key stored. Starting backup restore...");
const backupInfo = await client.getKeyBackupVersion();
// no need to await for this - just let it go in the bg
client.restoreKeyBackupWithCache(
undefined, undefined, backupInfo,
).then(() => {
client.restoreKeyBackupWithCache(undefined, undefined, backupInfo).then(() => {
logger.info("Backup restored.");
});
}
resolve();
});
})();
// We call getCrossSigningKey() for its side-effects
return Promise.race([
return Promise.race<KeysDuringVerification | void>([
Promise.all([
crossSigning.getCrossSigningKey("master"),
crossSigning.getCrossSigningKey("self_signing"),
crossSigning.getCrossSigningKey("user_signing"),
backupKeyPromise,
]),
]) as Promise<KeysDuringVerification>,
timeout,
]).then(resolve, reject);
}).catch((e) => {
File diff suppressed because it is too large Load Diff
@@ -1,11 +1,41 @@
/*
Copyright 2021 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.
*/
import { EventEmitter } from "events";
import { logger } from "../logger";
import {MatrixEvent} from "../models/event";
import {EventEmitter} from "events";
import {createCryptoStoreCacheCallbacks} from "./CrossSigning";
import {IndexedDBCryptoStore} from './store/indexeddb-crypto-store';
import { MatrixEvent } from "../models/event";
import { createCryptoStoreCacheCallbacks, ICacheCallbacks } from "./CrossSigning";
import { IndexedDBCryptoStore } from './store/indexeddb-crypto-store';
import { PREFIX_UNSTABLE } from "../http-api";
import { Crypto, IBootstrapCrossSigningOpts } from "./index";
import {
PREFIX_UNSTABLE,
} from "../http-api";
CrossSigningKeys,
ICrossSigningKey,
ICryptoCallbacks,
ISignedKey,
KeySignatures,
} from "../matrix";
import { ISecretStorageKeyInfo } from "./api";
import { IKeyBackupInfo } from "./keybackup";
interface ICrossSigningKeys {
authUpload: IBootstrapCrossSigningOpts["authUploadDeviceSigningKeys"];
keys: Record<string, ICrossSigningKey>;
}
/**
* Builds an EncryptionSetupOperation by calling any of the add.. methods.
@@ -17,18 +47,23 @@ import {
* more than once.
*/
export class EncryptionSetupBuilder {
public readonly accountDataClientAdapter: AccountDataClientAdapter;
public readonly crossSigningCallbacks: CrossSigningCallbacks;
public readonly ssssCryptoCallbacks: SSSSCryptoCallbacks;
private crossSigningKeys: ICrossSigningKeys = null;
private keySignatures: KeySignatures = null;
private keyBackupInfo: IKeyBackupInfo = null;
private sessionBackupPrivateKey: Uint8Array;
/**
* @param {Object.<String, MatrixEvent>} accountData pre-existing account data, will only be read, not written.
* @param {CryptoCallbacks} delegateCryptoCallbacks crypto callbacks to delegate to if the key isn't in cache yet
*/
constructor(accountData, delegateCryptoCallbacks) {
constructor(accountData: Record<string, MatrixEvent>, delegateCryptoCallbacks?: ICryptoCallbacks) {
this.accountDataClientAdapter = new AccountDataClientAdapter(accountData);
this.crossSigningCallbacks = new CrossSigningCallbacks();
this.ssssCryptoCallbacks = new SSSSCryptoCallbacks(delegateCryptoCallbacks);
this._crossSigningKeys = null;
this._keySignatures = null;
this._keyBackupInfo = null;
}
/**
@@ -42,8 +77,8 @@ export class EncryptionSetupBuilder {
* an empty authDict, to obtain the flows.
* @param {Object} keys the new keys
*/
addCrossSigningKeys(authUpload, keys) {
this._crossSigningKeys = {authUpload, keys};
public addCrossSigningKeys(authUpload: ICrossSigningKeys["authUpload"], keys: ICrossSigningKeys["keys"]): void {
this.crossSigningKeys = { authUpload, keys };
}
/**
@@ -54,8 +89,8 @@ export class EncryptionSetupBuilder {
*
* @param {Object} keyBackupInfo as received from/sent to the server
*/
addSessionBackup(keyBackupInfo) {
this._keyBackupInfo = keyBackupInfo;
public addSessionBackup(keyBackupInfo: IKeyBackupInfo): void {
this.keyBackupInfo = keyBackupInfo;
}
/**
@@ -65,8 +100,8 @@ export class EncryptionSetupBuilder {
*
* @param {Uint8Array} privateKey
*/
addSessionBackupPrivateKeyToCache(privateKey) {
this._sessionBackupPrivateKey = privateKey;
public addSessionBackupPrivateKeyToCache(privateKey: Uint8Array): void {
this.sessionBackupPrivateKey = privateKey;
}
/**
@@ -75,38 +110,37 @@ export class EncryptionSetupBuilder {
*
* @param {String} userId
* @param {String} deviceId
* @param {String} signature
* @param {Object} signature
*/
addKeySignature(userId, deviceId, signature) {
if (!this._keySignatures) {
this._keySignatures = {};
public addKeySignature(userId: string, deviceId: string, signature: ISignedKey): void {
if (!this.keySignatures) {
this.keySignatures = {};
}
const userSignatures = this._keySignatures[userId] || {};
this._keySignatures[userId] = userSignatures;
const userSignatures = this.keySignatures[userId] || {};
this.keySignatures[userId] = userSignatures;
userSignatures[deviceId] = signature;
}
/**
* @param {String} type
* @param {Object} content
* @return {Promise}
*/
setAccountData(type, content) {
return this.accountDataClientAdapter.setAccountData(type, content);
public async setAccountData(type: string, content: object): Promise<void> {
await this.accountDataClientAdapter.setAccountData(type, content);
}
/**
* builds the operation containing all the parts that have been added to the builder
* @return {EncryptionSetupOperation}
*/
buildOperation() {
const accountData = this.accountDataClientAdapter._values;
public buildOperation(): EncryptionSetupOperation {
const accountData = this.accountDataClientAdapter.values;
return new EncryptionSetupOperation(
accountData,
this._crossSigningKeys,
this._keyBackupInfo,
this._keySignatures,
this.crossSigningKeys,
this.keyBackupInfo,
this.keySignatures,
);
}
@@ -119,28 +153,27 @@ export class EncryptionSetupBuilder {
* @param {Crypto} crypto
* @return {Promise}
*/
async persist(crypto) {
public async persist(crypto: Crypto): Promise<void> {
// store private keys in cache
if (this._crossSigningKeys) {
const cacheCallbacks = createCryptoStoreCacheCallbacks(
crypto._cryptoStore, crypto._olmDevice);
if (this.crossSigningKeys) {
const cacheCallbacks = createCryptoStoreCacheCallbacks(crypto.cryptoStore, crypto.olmDevice);
for (const type of ["master", "self_signing", "user_signing"]) {
logger.log(`Cache ${type} cross-signing private key locally`);
const privateKey = this.crossSigningCallbacks.privateKeys.get(type);
await cacheCallbacks.storeCrossSigningKeyCache(type, privateKey);
}
// store own cross-sign pubkeys as trusted
await crypto._cryptoStore.doTxn(
await crypto.cryptoStore.doTxn(
'readwrite', [IndexedDBCryptoStore.STORE_ACCOUNT],
(txn) => {
crypto._cryptoStore.storeCrossSigningKeys(
txn, this._crossSigningKeys.keys);
crypto.cryptoStore.storeCrossSigningKeys(
txn, this.crossSigningKeys.keys);
},
);
}
// store session backup key in cache
if (this._sessionBackupPrivateKey) {
await crypto.storeSessionBackupPrivateKey(this._sessionBackupPrivateKey);
if (this.sessionBackupPrivateKey) {
await crypto.storeSessionBackupPrivateKey(this.sessionBackupPrivateKey);
}
}
}
@@ -158,93 +191,92 @@ export class EncryptionSetupOperation {
* @param {Object} keyBackupInfo
* @param {Object} keySignatures
*/
constructor(accountData, crossSigningKeys, keyBackupInfo, keySignatures) {
this._accountData = accountData;
this._crossSigningKeys = crossSigningKeys;
this._keyBackupInfo = keyBackupInfo;
this._keySignatures = keySignatures;
}
constructor(
private readonly accountData: Map<string, object>,
private readonly crossSigningKeys: ICrossSigningKeys,
private readonly keyBackupInfo: IKeyBackupInfo,
private readonly keySignatures: KeySignatures,
) {}
/**
* Runs the (remaining part of, in the future) operation by sending requests to the server.
* @param {Crypto} crypto
* @param {Crypto} crypto
*/
async apply(crypto) {
const baseApis = crypto._baseApis;
public async apply(crypto: Crypto): Promise<void> {
const baseApis = crypto.baseApis;
// upload cross-signing keys
if (this._crossSigningKeys) {
const keys = {};
for (const [name, key] of Object.entries(this._crossSigningKeys.keys)) {
if (this.crossSigningKeys) {
const keys: Partial<CrossSigningKeys> = {};
for (const [name, key] of Object.entries(this.crossSigningKeys.keys)) {
keys[name + "_key"] = key;
}
// We must only call `uploadDeviceSigningKeys` from inside this auth
// helper to ensure we properly handle auth errors.
await this._crossSigningKeys.authUpload(authDict => {
return baseApis.uploadDeviceSigningKeys(authDict, keys);
await this.crossSigningKeys.authUpload(authDict => {
return baseApis.uploadDeviceSigningKeys(authDict, keys as CrossSigningKeys);
});
// pass the new keys to the main instance of our own CrossSigningInfo.
crypto._crossSigningInfo.setKeys(this._crossSigningKeys.keys);
crypto.crossSigningInfo.setKeys(this.crossSigningKeys.keys);
}
// set account data
if (this._accountData) {
for (const [type, content] of this._accountData) {
if (this.accountData) {
for (const [type, content] of this.accountData) {
await baseApis.setAccountData(type, content);
}
}
// upload first cross-signing signatures with the new key
// (e.g. signing our own device)
if (this._keySignatures) {
await baseApis.uploadKeySignatures(this._keySignatures);
if (this.keySignatures) {
await baseApis.uploadKeySignatures(this.keySignatures);
}
// need to create/update key backup info
if (this._keyBackupInfo) {
if (this._keyBackupInfo.version) {
if (this.keyBackupInfo) {
if (this.keyBackupInfo.version) {
// session backup signature
// The backup is trusted because the user provided the private key.
// Sign the backup with the cross signing key so the key backup can
// be trusted via cross-signing.
await baseApis._http.authedRequest(
undefined, "PUT", "/room_keys/version/" + this._keyBackupInfo.version,
await baseApis.http.authedRequest(
undefined, "PUT", "/room_keys/version/" + this.keyBackupInfo.version,
undefined, {
algorithm: this._keyBackupInfo.algorithm,
auth_data: this._keyBackupInfo.auth_data,
algorithm: this.keyBackupInfo.algorithm,
auth_data: this.keyBackupInfo.auth_data,
},
{prefix: PREFIX_UNSTABLE},
{ prefix: PREFIX_UNSTABLE },
);
} else {
// add new key backup
await baseApis._http.authedRequest(
await baseApis.http.authedRequest(
undefined, "POST", "/room_keys/version",
undefined, this._keyBackupInfo,
{prefix: PREFIX_UNSTABLE},
undefined, this.keyBackupInfo,
{ prefix: PREFIX_UNSTABLE },
);
}
}
}
}
/**
* Catches account data set by SecretStorage during bootstrapping by
* implementing the methods related to account data in MatrixClient
*/
class AccountDataClientAdapter extends EventEmitter {
public readonly values = new Map<string, MatrixEvent>();
/**
* @param {Object.<String, MatrixEvent>} accountData existing account data
* @param {Object.<String, MatrixEvent>} existingValues existing account data
*/
constructor(accountData) {
constructor(private readonly existingValues: Record<string, MatrixEvent>) {
super();
this._existingValues = accountData;
this._values = new Map();
}
/**
* @param {String} type
* @return {Promise<Object>} the content of the account data
*/
getAccountDataFromServer(type) {
public getAccountDataFromServer(type: string): Promise<any> {
return Promise.resolve(this.getAccountData(type));
}
@@ -252,12 +284,12 @@ class AccountDataClientAdapter extends EventEmitter {
* @param {String} type
* @return {Object} the content of the account data
*/
getAccountData(type) {
const modifiedValue = this._values.get(type);
public getAccountData(type: string): MatrixEvent {
const modifiedValue = this.values.get(type);
if (modifiedValue) {
return modifiedValue;
}
const existingValue = this._existingValues[type];
const existingValue = this.existingValues[type];
if (existingValue) {
return existingValue.getContent();
}
@@ -269,15 +301,16 @@ class AccountDataClientAdapter extends EventEmitter {
* @param {Object} content
* @return {Promise}
*/
setAccountData(type, content) {
const lastEvent = this._values.get(type);
this._values.set(type, content);
public setAccountData(type: string, content: any): Promise<{}> {
const lastEvent = this.values.get(type);
this.values.set(type, content);
// ensure accountData is emitted on the next tick,
// as SecretStorage listens for it while calling this method
// and it seems to rely on this.
return Promise.resolve().then(() => {
const event = new MatrixEvent({type, content});
const event = new MatrixEvent({ type, content });
this.emit("accountData", event, lastEvent);
return {};
});
}
}
@@ -287,27 +320,25 @@ class AccountDataClientAdapter extends EventEmitter {
* by both cache callbacks (see createCryptoStoreCacheCallbacks) as non-cache callbacks.
* See CrossSigningInfo constructor
*/
class CrossSigningCallbacks {
constructor() {
this.privateKeys = new Map();
}
class CrossSigningCallbacks implements ICryptoCallbacks, ICacheCallbacks {
public readonly privateKeys = new Map<string, Uint8Array>();
// cache callbacks
getCrossSigningKeyCache(type, expectedPublicKey) {
public getCrossSigningKeyCache(type: string, expectedPublicKey: string): Promise<Uint8Array> {
return this.getCrossSigningKey(type, expectedPublicKey);
}
storeCrossSigningKeyCache(type, key) {
public storeCrossSigningKeyCache(type: string, key: Uint8Array): Promise<void> {
this.privateKeys.set(type, key);
return Promise.resolve();
}
// non-cache callbacks
getCrossSigningKey(type, _expectedPubkey) {
public getCrossSigningKey(type: string, expectedPubkey: string): Promise<Uint8Array> {
return Promise.resolve(this.privateKeys.get(type));
}
saveCrossSigningKeys(privateKeys) {
public saveCrossSigningKeys(privateKeys: Record<string, Uint8Array>) {
for (const [type, privateKey] of Object.entries(privateKeys)) {
this.privateKeys.set(type, privateKey);
}
@@ -319,39 +350,37 @@ class CrossSigningCallbacks {
* the SecretStorage crypto callbacks
*/
class SSSSCryptoCallbacks {
constructor(delegateCryptoCallbacks) {
this._privateKeys = new Map();
this._delegateCryptoCallbacks = delegateCryptoCallbacks;
}
private readonly privateKeys = new Map<string, Uint8Array>();
async getSecretStorageKey({ keys }, name) {
constructor(private readonly delegateCryptoCallbacks?: ICryptoCallbacks) {}
public async getSecretStorageKey(
{ keys }: { keys: Record<string, ISecretStorageKeyInfo> },
name: string,
): Promise<[string, Uint8Array]|null> {
for (const keyId of Object.keys(keys)) {
const privateKey = this._privateKeys.get(keyId);
const privateKey = this.privateKeys.get(keyId);
if (privateKey) {
return [keyId, privateKey];
}
}
// if we don't have the key cached yet, ask
// for it to the general crypto callbacks and cache it
if (this._delegateCryptoCallbacks) {
const result = await this._delegateCryptoCallbacks.
getSecretStorageKey({keys}, name);
if (this?.delegateCryptoCallbacks?.getSecretStorageKey) {
const result = await this.delegateCryptoCallbacks.
getSecretStorageKey({ keys }, name);
if (result) {
const [keyId, privateKey] = result;
this._privateKeys.set(keyId, privateKey);
this.privateKeys.set(keyId, privateKey);
}
return result;
}
return null;
}
addPrivateKey(keyId, keyInfo, privKey) {
this._privateKeys.set(keyId, privKey);
public addPrivateKey(keyId: string, keyInfo: ISecretStorageKeyInfo, privKey: Uint8Array): void {
this.privateKeys.set(keyId, privKey);
// Also pass along to application to cache if it wishes
if (
this._delegateCryptoCallbacks &&
this._delegateCryptoCallbacks.cacheSecretStorageKey
) {
this._delegateCryptoCallbacks.cacheSecretStorageKey(keyId, keyInfo, privKey);
}
this.delegateCryptoCallbacks?.cacheSecretStorageKey?.(keyId, keyInfo, privKey);
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More