Compare commits

...

1703 Commits

Author SHA1 Message Date
Benjamin Kampmann 402d061d42 ci(crypto-nodejs): fixing path to npm package for publishing 2022-07-12 18:02:59 +02:00
Benjamin Kampmann 2a1bc372fc chore(crypto-nodejs): setting version 2022-07-12 17:35:46 +02:00
Benjamin Kampmann bcab2a6d8c ci(crypto-nodejs): setting base branch 2022-07-12 17:24:34 +02:00
Benjamin Kampmann 703b3a3561 ci(crypto-nodejs): Fixing typo in workflow 2022-07-12 17:18:54 +02:00
Benjamin Kampmann 36f62ce67f ci(crypto-nodejs): Use regular npm version to set version 2022-07-12 17:14:15 +02:00
Benjamin Kampmann 9bc605a76d ci(crypto-nodejs): FIxing name and directory for action 2022-07-12 17:11:20 +02:00
Benjamin Kampmann 13a6825af7 ci(crypto-nodejs): Fix workflow syntax error 2022-07-12 17:07:49 +02:00
Benjamin Kampmann c5796991e8 chore(crypto-nodejs): Adding changelog 2022-07-12 17:05:40 +02:00
Benjamin Kampmann 9a45325683 ci(crypto-nodejs): use org-wide secrets (#835) 2022-07-12 17:00:44 +02:00
Ivan Enderlin 0bde5ccf38 feat(bindings/crypto-nodejs): Add #[napi(strict)] to force type checking from JavaScript (#829)
* feat(bindings/crypto-nodejs): Add `#[napi(strict)]` to force type checking from JavaScript.

* chore(bindings/crypto-nodejs): Use our own fork of `napi-rs` for the moment.
2022-07-12 16:24:24 +02:00
Benjamin Kampmann 94b635c074 build(crypto-nodejs): Crypto Node.js release infrastructure (#763)
* feat(crypto-nodejs): Download lib binary in postinstall

* build(crypto-nodejs): Workflow to prebuild napi bindings

* ci(crypto-nodejs): Disable broken target, install without download

* ci(apple-ffi): Don't run for drafts

* ci(coverage): Don't run for draft PRs

* fix(crypto-nodejs): bind to current version for download

* fix(crypto-nodejs): Ignore libs and package

* ci(crypto-nodejs): Build and upload NPM package

* fix(crypto-nodejs): Set proper target list

* ci(crypto-nodejs): Remove FreeBSD from build pipeline

* ci(crypto-nodejs): Linkers for linux cross compile

* ci(crypto-nodejs): Add arm64 build for windows

* ci(crypto-nodejs): Proper linkers for arm and musl

* ci(crypto-nodejs): Correct apt command for musl

* fix(crypto-nodejs): Drop arm64 linux musl support

* ci(crypto-nodejs): Manual Workflow trigger process

* chore(crypto-nodejs): Get Github to pickup our action

* ci(crypto-nodejs): Add i686 Linux built

* ci(crypto-nodejs): Configure cliff for nodejs changelogs

* ci(crypto-nodejs): Proper gcc for i868 targets

* docs(crypto-nodejs): Add supported targets for npm install

* ci(crypto-nodejs): Limit building of binaries to tags

* style: consol.log -> console.info; Improve docs

Co-authored-by: Ivan Enderlin <ivan@mnt.io>

* activate for testing

* fix broken merge

* 0.1.0

* fix(js): put in the proper package name

* activate for PR for testing

* fix(nodejs): getting ready for publishing

* ci(crypto-nodejs): Adding docs and fixing naming for workflows

* typo: missed one

* fixing package name

Co-authored-by: Ivan Enderlin <ivan@mnt.io>
2022-07-12 16:05:57 +02:00
Benjamin Kampmann 15be2dc45e Merge pull request #832 from johannescpk/sdk/identity-assertion-session
fix(sdk): Can't assert identity without session
2022-07-12 12:25:46 +02:00
Johannes Becker 420ca26bf5 fix(sdk): Can't assert identity without session 2022-07-12 10:44:56 +02:00
Kévin Commaille 2d0653894c refactor(test): Rename LOGOUT to EMPTY
This name is more accurate for its uses.
2022-07-09 17:59:45 +02:00
Damir Jelić 47cfac7f4c test: Optimize sha2 even in debug builds
This makes the tests finish on my machine twice as fast. This works
mainly because some tests utilize pbkdf2 to derive a key from a
passphrase.
2022-07-08 18:47:36 +02:00
Kévin Commaille 9539cbcfb9 test(appservice): Replace mockito with wiremock 2022-07-08 16:33:29 +02:00
Kévin Commaille 9778518347 test(sdk): Replace mockito with wiremock 2022-07-08 16:33:29 +02:00
Ivan Enderlin dc2276cd8a feat(bindings/crypto-nodejs): Implement an Attachment API.
feat(bindings/crypto-nodejs): Implement an `Attachment` API.
2022-07-08 16:26:19 +02:00
Damir Jelić f1c880ff5f feat(bindings/ffi): Add an authentication service
This adds a basic authentication service to the bindings that abstracts away the Client until a login has been completed successfully.
2022-07-08 12:24:15 +02:00
Damir Jelić 93e5728d65 test(sdk): Move the integration tests
This moves the bulk of the Client tests into integration tests.
2022-07-08 12:08:27 +02:00
Damir Jelić a7af96d081 feat(crypto): Customized event types
This patch adds customized event types, currently only for the
m.room_key and m.secret.send to-device events.

This allows us to:
    a) Deserialize the session_key field into a vodozemac type
    b) Control when we zeroize secrets better
2022-07-07 19:20:42 +02:00
Doug 0dee880cd0 Address PR comments. 2022-07-07 17:15:12 +01:00
Ivan Enderlin f0190b4601 feat(bindings/crypto-nodejs): Transform timeout into milliseconds
feat(bindings/crypto-nodejs): Transform `timeout` into milliseconds
2022-07-07 14:54:18 +02:00
Ivan Enderlin 6d83f01e73 fix(sdk): THe MediaEncryptionInfo.web_key has been renamed. 2022-07-07 13:59:36 +02:00
Ivan Enderlin 2eb5fc77f5 feat(bindings/crypto-nodejs): Remove Clone impl for MediaEncryptionInfo.
We don't want to clone a struct that contains a secret.

However, on the Node.js side, we can only receive arguments by
references. The problem we have is that we cannot transfer the
ownership of `MediaEncryptionInfo` to `AttachmentDecryptor` because we
don't own it. To simulate this behavior, we use `Option.take`.

A new method then appears:
`EncryptedAttachment.hasMediaEncryptionInfoBeenConsumed` to know if
the media encryption info has been consumed by `Attachment.decrypt`
already or not. That way, we can decrypt only once. It is possible to
do a JSON-encoded backup of the media encryption info by calling
`EncryptedAttachment.mediaEncryptionInfo` though.
2022-07-07 13:53:46 +02:00
Kévin Commaille 5ab8bd0885 Fix missing import 2022-07-07 13:24:54 +02:00
Kévin Commaille ee69863912 Move event permalink test 2022-07-07 13:19:31 +02:00
Kévin Commaille e87d599f84 Merge remote-tracking branch 'upstream/main' into integration-tests 2022-07-07 13:16:09 +02:00
Ivan Enderlin 0b011d9097 doc(bindings/crypto-nodejs): Add link to the specification. 2022-07-07 13:15:14 +02:00
Ivan Enderlin 0f5851cc01 chore(crypto): Rename MediaEncryptionInfo.web_key to .key. 2022-07-07 13:14:05 +02:00
Kévin Commaille d6a2f15c68 Simplify use of via
Due to a ruma upgrade
2022-07-07 12:30:15 +02:00
Kévin Commaille 36a47c28ed Add note that the event should be part of the room 2022-07-07 12:30:15 +02:00
Kévin Commaille 900016b249 feat(sdk): Get a permalink for an event 2022-07-07 12:30:15 +02:00
Kévin Commaille de60a24602 Remove __test feature 2022-07-07 11:26:49 +02:00
Ivan Enderlin 29c10b8424 feat(bindings/crypto-nodejs): Convert timeout from u128 to u64.
First, u128 has a bug in `serde`,
cf. https://github.com/serde-rs/json/issues/625.

Second, we don't need to represent the timeout as a u128, it's clearly
too large. This patch tries to convert it to u64. It should never
fail, but we propagate the error anyway.
2022-07-07 11:12:12 +02:00
Johannes Becker 4b856ce9d6 fix(sdk): Use the local config variable to decide identity assertion 2022-07-07 10:16:23 +02:00
Ivan Enderlin c043daede0 test(crypto): Fix a test. 2022-07-07 10:15:24 +02:00
Ivan Enderlin 9f6988f766 Merge branch 'main' into fix-issue-796 2022-07-07 10:11:43 +02:00
Ivan Enderlin ed0709373d fix(crypto): Rename web_key to key for MediaEncryptionInfo.
Based on the [Section 11.11.1.6.1 Extensions to `m.room.message`
msgtypes](https://spec.matrix.org/v1.2/client-server-api/#extensions-to-mroommessage-msgtypes),
the parameter for the JSON Web Key is named `key`, not `web_key`. This
patch fixes that by renaming the field when serializing and
deserializing.
2022-07-07 10:04:34 +02:00
Ivan Enderlin acf9b15571 feat(bindings/crypto-nodejs): Use latest napi-rs version to avoid cloning Uint8Array.
The new `napi-rs` release includes a patch that avoids cloning and
copying data inside a `Uint8Array`
(https://github.com/napi-rs/napi-rs/pull/1224), it now returns a
“Node.js reference” of it.

This new `napi-rs` release also includes one of our patch,
https://github.com/napi-rs/napi-rs/pull/1200, which means we no longer
need to depend on our fork.
2022-07-07 09:49:34 +02:00
Charles Wright ba39185679 Fix build errors 2022-07-06 18:08:02 +02:00
Doug da277c4978 Create a new client on login.
More clippy errors.
2022-07-06 12:43:02 +01:00
Doug 9925d73e7b Fix typos and clippy errors. 2022-07-06 11:52:33 +01:00
Doug fec879f0f3 Simplify AuthenticationError for now. 2022-07-06 10:29:13 +01:00
Doug 91427b82a5 Use an Optional client instead of failable init. 2022-07-05 18:14:25 +01:00
Ivan Enderlin d7739369ae chore(bindings/crypto-nodejs): Remove useless napi::Result. 2022-07-05 17:45:09 +02:00
Ivan Enderlin 4fd24eebea feat(bindings/crypto-nodejs): Implement an Attachment API.
This patch provides a new API to encrypt and decrypt attachment,
i.e. big buffer of type `Uint8Array`.

It's based on `matrix_sdk_crypto::AttachmentEncryptor` and `AttachmentDecryptor`.
2022-07-05 17:31:52 +02:00
Benjamin Kampmann 73daec3757 Merge pull request #810 from gnunicorn/expose-invite-details
feat(sdk): Expose details of invite for invited room
2022-07-05 14:56:05 +02:00
Benjamin Kampmann d9f3b257b4 Apply suggestions from code review
Co-authored-by: Ivan Enderlin <ivan@mnt.io>
2022-07-05 14:38:53 +02:00
Damir Jelić 771c33d710 chore(crypto): Bump vodozemac
Vodozemac used to accept and return strings when encrypting and
decrypting. This is quite unusual for a pure cryptographic library so we
switched towards the usual setup where we encrypt/decrypt raw bytes.

Since we do encrypt/decrypt JSON strings in Matrix land, we do the
string conversions over here.
2022-07-05 13:23:50 +02:00
Doug 56adf6a89b Add a client_container with locks. 2022-07-05 11:43:10 +01:00
Ivan Enderlin e5a7a975a3 feat(bindings/crypto-nodejs): Transform timeout into milliseconds. 2022-07-05 12:05:53 +02:00
Ivan Enderlin f3e69a2352 fix(bindings/cryto-nodejs): Fix memory corruption in async functions
fix(bindings/cryto-nodejs): Fix memory corruption in async functions
2022-07-05 10:25:16 +02:00
Ivan Enderlin 607d7ebc22 fix(bindings/cryto-nodejs): Fix memory corruption in async functions.
In async functions, the Node.js GC may or may not (that's a random
behavior) collect the arguments passed to the function as soon as it
returns. The function may not be executed yet, since it's async. Thus,
it leads to memory corruption: The function tries to read later on the
value inside an argument and… it crashes at best.

To avoid this bug, there is no other choice than cloning the values
before the function returns, in its “sync path” (so before any
transformation of an `.await` point into an “async block”).

The performance impact is not “massive”, I'm not sure it could be
noticeable easily since it is most of the time related to identifiers
(e.g. `UserId`), which are cheap to clone. I have to find the balance
here, and cloning offers the best trade off from my point of view.
2022-07-05 09:07:20 +02:00
Doug 0178b71437 Add basic AuthenticationService to the FFI. 2022-07-04 16:55:50 +01:00
Kévin Commaille dd6a902240 test(sdk): Move integration tests 2022-07-04 16:22:20 +02:00
Kévin Commaille 4eb1337dc8 ci: Remove whitespaces in config file 2022-07-04 16:22:19 +02:00
Benjamin Kampmann 81f02f0d0b Merge pull request #804 from gnunicorn/ben-hunting-the-nodjs-segfault
Hunting the nodejs segfault bug, long-term
2022-07-04 15:25:09 +02:00
Ivan Enderlin 76fe6d54ac feat(bindings/crypto-*): Add fallback_keys field to KeysUploadRequest
feat(bindings/crypto-*): Add `fallback_keys` field to `KeysUploadRequest`
2022-07-04 15:02:38 +02:00
Ivan Enderlin eb358889e9 Merge branch 'main' into fix-issue-800 2022-07-04 14:31:28 +02:00
Ivan Enderlin c82631c414 feat(bindings/crypto-js): Implement OlmMachine.sign
feat(bindings/crypto-js): Implement `OlmMachine.sign`
2022-07-04 14:16:27 +02:00
Ivan Enderlin fb4a940a26 chore: Make Clippy happy… 2022-07-04 13:50:28 +02:00
Ivan Enderlin 05561a8777 chore(crypto): Make Clippy happy. 2022-07-04 13:06:14 +02:00
Ivan Enderlin 909ada43d7 chore(base): Make Clippy happy.
So, Clippy suggests to change `(&member).into()` to `member.into()`
but it's the same, and `From<T>` is not implemented for this `T`, only
`From<&T>` is present. Thus, to deceive Clippy, I'm using
`std::borrow::Borrow` here. Not super happy with that though…
2022-07-04 12:00:42 +02:00
Ivan Enderlin 6176b3b658 feat(bindings/crypto-ffi): Add fallback_keys field to KeysUpload. 2022-07-04 11:49:45 +02:00
Ivan Enderlin 566227576e feat(bindings/crypto-js): Add fallback_keys field to KeysUploadRequest. 2022-07-04 11:47:27 +02:00
Ivan Enderlin d6c0ef1497 feat(bindings/crypto-nodejs): Add fallback_keys field to KeysUploadRequest. 2022-07-04 11:47:15 +02:00
Ivan Enderlin f72a14890d chore(crypto) Make Clippy happy. 2022-07-04 11:42:50 +02:00
Ivan Enderlin 62378b4abc Merge branch 'main' into fix-issue-797 2022-07-04 11:24:33 +02:00
Ivan Enderlin f96069f591 chore(store-encryption): Call DerefMut manually.
Clippy on nigtly is raising a warning, which is turned into an error
on the CI. It's the [`explicit_auto_deref`
lint](https://rust-lang.github.io/rust-clippy/master/index.html#explicit_auto_deref). I
suspect it's a false-positive but I'm not sure. Anyway, to workaround
this and unblock our CI, let's call `DerefMut::deref_mut` manually:
it's clearer anyway.
2022-07-04 11:00:23 +02:00
Ivan Enderlin 59615d4ae3 chore(bindings/crypto-nodejs): Clean up based on feedback. 2022-07-04 10:17:11 +02:00
Benjamin Kampmann fd38c757e4 feat(sdk): Expose details of invite for invited room 2022-07-01 19:44:27 +02:00
Jonas Platte 861d899541 refactor(base): Remove an unnecessary allocation 2022-07-01 16:16:29 +02:00
Jonas Platte fd08c9e7da refactor(base): Remove check for own user in notification handling
This is now done in Ruma.
Reverts commit bc78095611.
2022-07-01 16:16:29 +02:00
Jonas Platte cffb565a5f chore: Allow some usage of deprecated fields
… to allow CI to succeed. They should be removed soon.
2022-07-01 16:16:29 +02:00
Jonas Platte f20d1c3d76 chore: Upgrade ruma 2022-07-01 16:16:29 +02:00
Jonas Platte e4f6c0cc58 chore(sdk): Remove feature ruma/appservice-api-helper
No longer used as of https://github.com/matrix-org/matrix-rust-sdk/pull/710
2022-07-01 16:16:29 +02:00
Jonas Platte d3ae99eb22 chore: Silence new clippy lint 2022-07-01 12:39:46 +02:00
Jonas Platte bc47caa356 chore: Remove unnecessary map_err's 2022-07-01 11:55:28 +02:00
Ivan Enderlin afa96f1bf4 test(bindings/crypto-nodejs): Add more signing test cases. 2022-06-30 16:58:39 +02:00
Ivan Enderlin c99f42347c chore(bindings/crypto-nodejs): Simplify code by removing matches!. 2022-06-30 16:52:08 +02:00
Ivan Enderlin 51cb35502d doc(bindings/crypto-nodejs): Add missing documentation. 2022-06-30 16:50:33 +02:00
Ivan Enderlin b59077e83d chore(bindings/crypto-nodejs): Replacing into_iter by iter on &BTreeMap.
Calling `into_iter` on `&BTreeMap` will not consume it. It has the
same effect as calling `iter`. So let's do it.
2022-06-30 16:48:44 +02:00
Ivan Enderlin 3f197734d9 feat(bindings/crypto-nodejs) Implement OlmMachine.sign.
This patch first implements the new `Signatures`, `Signature` and `MaybeSignature` types.

Then, it moves some Vodozemac types into their own module, and
implements the new `Ed25519Signature` type.

Finally, it implements `OlmMachine.sign`.
2022-06-30 16:44:07 +02:00
Benjamin Kampmann 1961403512 ci(crypto-nodejs): Only build non-release version on failure, improve CI build time 2022-06-30 12:53:51 +02:00
Benjamin Kampmann f1ebbfd245 ci(crypto-nodejs): Create non-release build of version and upload everything as artifacts upon failure 2022-06-30 12:24:21 +02:00
Ivan Enderlin 0458ed9be1 feat(bindings/crypto-js): Implement DeviceKeyId, DeviceKeyAlgorithm and DeviceKeyAlgorithmName. 2022-06-30 08:51:36 +02:00
Ivan Enderlin 12c7b76fea feat(bindings/crypto-js): Implement `OlmMachine.crossSigningStatus. 2022-06-30 08:33:28 +02:00
Marcel a8601e186a fix(appservice): Don't process the same transaction twice 2022-06-29 16:17:25 +00:00
Stefan Ceriu 8a2d13feea feat(bindings): Session verification through FFI 2022-06-29 13:59:52 +02:00
Benjamin Kampmann e2ca56114e Merge pull request #785 from zecakeh/room-permalink
feat(sdk): Add method to get a room permalink
2022-06-29 13:58:25 +02:00
Anderas 3c6d159a04 refactor: Use ClientBuilder pattern in SDK FFI
Co-authored-by: Jonas Platte <jplatte@matrix.org>
2022-06-29 13:13:31 +02:00
Benjamin Kampmann 464bc43290 Merge pull request #793 from Hywan/test-crypto-nodejs-timeout
test(crypto-nodejs): Increase timeout
2022-06-29 12:58:11 +02:00
Kévin Commaille 297861e186 Fix docs styling 2022-06-29 12:20:57 +02:00
Kévin Commaille 8313029e33 Split into methods for both Matrix URI formats 2022-06-29 12:02:26 +02:00
Ivan Enderlin 913bdd683e feat(crypto-js): Change the package name
feat(crypto-js): Change the package name
2022-06-28 19:28:58 +02:00
Ivan Enderlin 041b9bc405 feat(crypto-js): Change the package name. 2022-06-28 17:05:21 +02:00
Ivan Enderlin 1526f76686 test(crypto-nodejs): Increase timeout.
For some unknown reasons, sometimes, randomly, one test (initializing
an `OlmMachine` with a local store with a passphrase) can take more
than 5s, only on Github Actions. Let's increase the test timeout value
so that the entire test suite doesn't fail.
2022-06-28 16:47:46 +02:00
Kévin Commaille f0e0194ff2 feat(sdk): Add method to get a room permalink
Include routing for room IDs
2022-06-26 13:38:01 +02:00
Kévin Commaille ebc7177438 feat(base): Add method to get Room alt aliases 2022-06-26 12:01:51 +02:00
Ivan Enderlin 091fab8a2a chore(bindings): Move matrix-sdk-ffi and matrix-sdk-crypto-ffi into the bindings/ directory
chore(bindings): Move `matrix-sdk-ffi` and `matrix-sdk-crypto-ffi` into the `bindings/` directory
2022-06-23 15:54:32 +02:00
Ivan Enderlin 818d715395 chore: Implement feedback. 2022-06-23 15:53:19 +02:00
Ivan Enderlin 5a0089da52 doc(bindings): Mention bindings in the top README.md file. 2022-06-23 15:12:51 +02:00
Ivan Enderlin 68b6c19dd4 test: Ensure all crates members of the workspace are compiled & tested. 2022-06-23 14:10:31 +02:00
Ivan Enderlin c29e2b9563 !fixup 2022-06-23 11:35:42 +02:00
Ivan Enderlin ecc28efd53 chore(bindings): Move matrix-sdk-ffi and matrix-sdk-crypto-ffi into the bindings/ directory. 2022-06-23 11:31:59 +02:00
Jonas Platte f3a61020e7 refactor(sdk): Rewrite sso login to be easier to read 2022-06-22 17:17:52 +02:00
Jonas Platte a423e92246 chore: Consistently capitalize 'device ID' 2022-06-22 17:17:52 +02:00
Jonas Platte b5d7f10c6b feature: Introduce a login builder API
This improves the readability of login calls.
The old login API is kept, but deprecated.
2022-06-22 17:17:52 +02:00
Ivan Enderlin 931eabf55c chore(bindings): Move crypto-nodejs and crypto-js into the bindings/ directory
chore(bindings): Move `crypto-nodejs` and `crypto-js` into the `bindings/` directory
2022-06-22 16:33:20 +02:00
Ivan Enderlin 8cd7fa9fb0 chore: Implement feedback. 2022-06-22 16:03:37 +02:00
Ivan Enderlin 1604f24136 chore(test): Fix YAML. 2022-06-22 16:03:37 +02:00
Ivan Enderlin 3da737b9e2 chore(test): Shorten job name for test-matrix-sdk-crypto-nodejs.
In the Github UI, we can only see:

    🐧 [m]-crypto-nodejs, Node.js…

What interests us is the Node.js version number.
2022-06-22 16:03:37 +02:00
Ivan Enderlin 2ffcc1a415 chore: Use [m] as an alias for matrix-sdk. 2022-06-22 16:03:37 +02:00
Ivan Enderlin 829dab42c5 chore(test): Rename the test-matrix-sdk-crypto-js job. 2022-06-22 16:03:37 +02:00
Ivan Enderlin 54acd314cc chore(test): Move the wasm workflow inside the ci workflow. 2022-06-22 16:03:37 +02:00
Ivan Enderlin 74953031ee chore(test): Use os-name in step name for test-appservice. 2022-06-22 16:03:37 +02:00
Ivan Enderlin 0436eb9349 chore(ci): Rephrase a little bit the Github Actions steps. 2022-06-22 16:03:37 +02:00
Ivan Enderlin a23bb8f5a0 chore(docs): Rephrase a little bit the Github Actions steps. 2022-06-22 11:57:41 +02:00
Ivan Enderlin 8db58986fb chore(bindings): Move crypto-nodejs and crypto-js into the bindings/ directory.
`matrix-sdk-crypto-nodejs` and `matrix-sdk-crypto-js` are no longer
default members of the Cargo virtual workspace. The Github Actions
workflows for the bindings now live in a `bindings_ci.yml` files
(ideally, it should be in a subdirectory,
`.github/workflows/bindings/ci.yml` but it doesn't work).
2022-06-22 11:54:49 +02:00
Ivan Enderlin 6ad323bc4e test: Run tests faster with nextest
test: Run tests faster with `nextest`
2022-06-22 09:56:02 +02:00
Ivan Enderlin b0d51fdfa5 test: There is no doctest for matrix-sdk-crypto-ffi. 2022-06-22 09:26:51 +02:00
Ivan Enderlin 3bfc68d476 test: Add missing cargo-nextest installation.
This patch also changes the step's name from Clippy to Test.
2022-06-22 09:26:51 +02:00
Ivan Enderlin eb33333925 test: Run doctests manually.
`cargo-nextest` doesn't support doctests for now, so we must run them
“manually” by running a separate `cargo test --doc` command.
2022-06-22 09:26:51 +02:00
Ivan Enderlin d9475c131a test(xtask): Remove xtask -- ci test as it is unused. 2022-06-22 09:26:48 +02:00
Ivan Enderlin 399862d955 test: Run tests faster with nextest.
> [`cargo-nextest`](https://nexte.st/index.html) is a next-generation
> test runner for Rust projects.

This patch installs and uses `nextest` to run our own tests.

Comparing `cargo test` and `cargo nextest` with hyperfine provides the
following results:

```sh
$ hyperfine 'cargo test --workspace' 'cargo nextest run --workspace && cargo test --doc'
Benchmark 1: cargo test --workspace
  Time (mean ± σ):     51.785 s ±  2.066 s    [User: 183.471 s, System: 10.563 s]
  Range (min … max):   49.151 s … 56.641 s    10 runs

Benchmark 2: cargo nextest run --workspace && cargo test --doc
  Time (mean ± σ):     44.556 s ±  0.894 s    [User: 192.213 s, System: 11.441 s]
  Range (min … max):   43.170 s … 45.762 s    10 runs
```

Benchmark 2 is 1.16 times faster than Benchmark 1.
2022-06-22 09:26:07 +02:00
Ivan Enderlin 2c1f5fed8d feat(crypto-js): Migrate tests and polish the API
feat(crypto-js): Migrate tests and polish the API
2022-06-21 12:04:45 +02:00
Ivan Enderlin 8b2237fa7a Merge branch 'main' into feat-crypto-js-next 2022-06-21 11:38:48 +02:00
Ivan Enderlin e5ea2a770b chore(crypto-js): Implement feedback from PR. 2022-06-21 11:25:58 +02:00
Jonas Platte 5f31e9d131 chore: Add missing json language specification to docs 2022-06-20 22:33:35 +02:00
Jonas Platte 6cb9c11b88 chore: Remove unnecessary pub visibility from OnceCell imports 2022-06-20 22:33:35 +02:00
Jonas Platte a00c130fc3 feature: Allow passing already-Arc'ed stores to StoreConfig methods 2022-06-20 18:00:33 +02:00
Jonas Platte 4971802e75 chore: Replace usage of Store with Arc<dyn StateStore> 2022-06-17 17:35:33 +02:00
Jonas Platte 8690addfd5 chore: Add Clone impl for ClientBuilder 2022-06-17 14:59:22 +02:00
Jonas Platte 00a20f325b chore: Add Clone impl for StoreConfig
… by storing the stores inside Arc's instead of Box'es.
2022-06-17 14:59:22 +02:00
Jonas Platte a4e4bfe833 refactor(sdk)!: Change store builder methods from Box<dyn Trait> to impl Trait
To migrate, don't box the store before passing it to `builder.state_store` or
`builder.crypto_store` (remove `Box::new`).
2022-06-17 14:59:22 +02:00
Jonas Platte 02aa537f2a chore: Keep uniffi version in sync across deps, CI 2022-06-17 13:37:07 +02:00
Anderas c755e19fb3 Merge pull request #765 from matrix-org/andy/crypto_ffi
Build Crypto iOS framework
2022-06-16 11:25:39 +01:00
Jonas Platte 8250c24525 chore: Undo pinning of clap 2022-06-15 20:47:55 +02:00
Andy Uhnak fe29fa57eb Build Crypto iOS framework 2022-06-15 13:52:21 +01:00
Ivan Enderlin c564b1a5e1 feat(crypto-nodejs): Add store_path and store_passphrase to the OlmMachine constructor
feat(crypto-nodejs): Add `store_path` and `store_passphrase` to the `OlmMachine` constructor
2022-06-15 07:28:29 +02:00
Benjamin Kampmann 9d691e238a Merge pull request #759 from Hywan/fix-codecov-labs
chore(test): Remove `labs` from the projects + exclude `matrix-sdk-indexeddb` from code coverage report
2022-06-14 20:29:07 +02:00
Ivan Enderlin 520e2f30f7 doc(crypto-js): Add missing module documentation. 2022-06-14 16:54:22 +02:00
Ivan Enderlin c56ab5928c test(crypto-js): Add a workflow to test matrix-sdk-crypto-js. 2022-06-14 16:34:08 +02:00
Ivan Enderlin f8cd2310be feat(crypto-js): Implement OlmMachine.decryptRoomEvent & siblings. 2022-06-14 16:16:54 +02:00
Ivan Enderlin 073fb45580 feat(crypto-nodejs): Define Node.js versions policy.
We now support only “current”, “active” or “maintenance” versions
according to https://nodejs.org/en/about/releases/, which are
compatible with NAPI v6.
2022-06-14 16:05:01 +02:00
Ivan Enderlin 3833d35348 chore(crypto-nodejs): Drop Node.js v12.17.
There is a segfault with `napi-rs` and Node.js in v12.17. It's an old
version, it may be fair to drop its support for now. Let's see if
people would need it in the future, we may work on `napi-rs` to fix
this bug in case it's really necessary.
2022-06-14 16:05:01 +02:00
Ivan Enderlin 83b730d1c8 chore(crypto-nodejs): Make the code compatible with Node.js < 18. 2022-06-14 16:05:01 +02:00
Ivan Enderlin 6477cc5072 feat(crypto-nodejs): Add store_path and store_passphrase to the OlmMachine constructor.
This patch adds the `store_path` and the `store_passphrase` arguments
to the `OlmMachine` constructor to use a `CryptoStore` instead of
having an in-memory Olm machine.
2022-06-14 16:05:01 +02:00
Ivan Enderlin 2117b36a75 chore(test): Exclude matrix-sdk-indexeddb from code coverage report. 2022-06-14 16:04:41 +02:00
Ivan Enderlin 5e8ed3bcbf chore(test): Remove labs from the projects.
It's already part of the `ignore` section.
2022-06-14 16:04:41 +02:00
Jonas Platte 87639a4c4c fix(appservice): Remove erroneous ? operator 2022-06-14 15:20:24 +02:00
Amanda Graven de04aba5b3 fix(appservice): Remove erroneous ? operator 2022-06-14 15:02:55 +02:00
Amanda Graven 5243091bec test(appservice): Virtual client membership
Test that virtual clients get assigned the correct membership to rooms
when processing received transactions.
2022-06-14 14:39:54 +02:00
Amanda Graven 1d746f1ef1 fix(appservice): Virtual client non-membership
Don't assume virtual client membership is join if none is stored, since
that leads to a client being told it's joined in rooms it has no
membership of. The main appservice client still assumes it's joined
every room it receives transaction events about.
2022-06-14 14:39:54 +02:00
Ivan Enderlin 56d74e25b8 test(crypto-js): Finish to migrate the test suites + code clean up. 2022-06-14 14:09:52 +02:00
Ivan Enderlin a758d98f84 feat(crypto-nodejs): Update license. 2022-06-14 12:12:27 +02:00
Ivan Enderlin 5adae6fd41 feat(crypto-js): Migrate tests and polish the API. 2022-06-14 12:12:27 +02:00
Damir Jelić 38d771cca6 ci(coverage): Set the correct out format for CI coverage reports 2022-06-14 12:01:03 +02:00
Jonas Platte dd4c329f57 chore: Prevent clap upgrades beyond 3.2 2022-06-14 11:02:19 +02:00
Jonas Platte e3edf0139a Enable rustdoc-map nightly feature via .cargo/config.toml
… instead of using -Z on the command line.
2022-06-13 14:30:10 +02:00
Jonas Platte d07001a581 chore: Work around a cargo bug 2022-06-13 14:30:10 +02:00
Ivan Enderlin 62b8169ac2 chore(test): Ajust code coverage configurations (tarpaulin and codecov)
chore(test):  Code Coverage must ignore some `matrix-sdk-crypto-(js|nodejs)`
2022-06-13 14:24:22 +02:00
Ivan Enderlin d35063412f chore(test): Ignore matrix-sdk-test-macros and matrix-sdk-ffi. 2022-06-13 12:52:37 +02:00
Damir Jelić 1a162e5dd5 test(crypto): Test the double verification cancellation 2022-06-13 12:30:52 +02:00
Damir Jelić b8069af8ba fix(crypto): Cancel the verification flow if we multiple verifications
The spec claims that we should cancel verifications if multiple
verifications are attempted at once[1]:
    When the same device attempts to initiate multiple verification
    attempts, the recipient should cancel all attempts with that device.

So let's start doing this.

[1]: https://spec.matrix.org/v1.2/client-server-api/#error-and-exception-handling
2022-06-13 12:30:52 +02:00
Damir Jelić fa3e192c37 docs(crypto): Improve the signature verification docs some more
Co-authored-by: Denis Kasak <dkasak@termina.org.uk>
2022-06-13 12:12:09 +02:00
Damir Jelić efc53569ed refactor(crypto): Rename our is_signed_by methods 2022-06-13 12:12:09 +02:00
Damir Jelić 5c12132569 refactor(crypto): Introduce a SignedJsonObject trait
This should mostly remove the wild west of signature verification. We
define a trait that tells us which objects can contain signatures and
thus can be passed on to signature verification methods.

It also should be slightly more efficient, since we removed a bunch of
duplicate canonicalization steps.
2022-06-13 12:12:09 +02:00
Amanda Graven 251a38285c perf(appservice): Cache namespace regexes 2022-06-13 11:57:50 +02:00
Ivan Enderlin b500fa1daa chore(test): Configure Tarpaulin to collect data from matrix-sdk-common. 2022-06-13 11:27:22 +02:00
Ivan Enderlin 4430dae421 chore(test): Configure Tarpaulin to ignore more crates. 2022-06-13 11:25:54 +02:00
Ivan Enderlin eead09984c chore(test): Ask codecov.io to ignore the crates/matrix-sdk-crypto-ffi directory. 2022-06-13 11:25:38 +02:00
Ivan Enderlin dcfcac0bd3 chore(test): Ask codecov.io to ignore labs and xtask directories. 2022-06-13 11:24:10 +02:00
Jonas Platte dc32fc282d Remove sync_token from BaseClient
… as it is also accessible as self.store.sync_token in BaseClient methods.
2022-06-13 11:10:12 +02:00
Jonas Platte b6eed09564 Make session field in Store private
… for cleaner encapsulation.
2022-06-13 11:10:12 +02:00
Jonas Platte 29ba171953 Simplify ownership of server_versions
We couldn't originally take references to it when it was behind RwLock,
with OnceCell this is no longer a problem.
2022-06-13 11:10:12 +02:00
Jonas Platte 9e9152745c Remove homeserver_url from HttpClient 2022-06-13 11:10:12 +02:00
Jonas Platte 12d1607cdc Remove session from HttpClient 2022-06-13 11:10:12 +02:00
Jonas Platte 6c8b520f14 Remove unused Clone impls on private types 2022-06-13 11:10:12 +02:00
Jonas Platte fedcdb1e63 chore: Add some more tracing events 2022-06-13 11:10:12 +02:00
Jonas Platte 1cfd69a880 chore: Improve doc comment formatting 2022-06-13 11:10:12 +02:00
Ivan Enderlin dad035d170 chore(test): Configure tarpaulin to use its config file. 2022-06-13 10:46:29 +02:00
Ivan Enderlin 3c14acf163 chore(test): Exclude matrix-sdk-crypto-(js|nodejs) from code coverage reports. 2022-06-13 10:38:07 +02:00
Ivan Enderlin 253affeb0c feat(crypto-nodejs) Implement missing APIs
feat(crypto-nodejs) Implement missing APIs
2022-06-09 21:38:41 +02:00
Ivan Enderlin fe4ddfde89 chore(crypto-nodejs): Remove clone calls when possible. 2022-06-09 21:15:25 +02:00
Ivan Enderlin 8a332ca9e1 chore(crypto-nodejs): Implement feedbacks / polish. 2022-06-09 18:02:29 +02:00
Ivan Enderlin 506f57a22c feat(crypto-nodejs): Enable traace filtering and change the env var to MATRIX_LOG. 2022-06-09 14:06:42 +02:00
Damir Jelić 8b05f9276f fix(sdk): Remove a duplicate Session cell from the HttpClient 2022-06-09 13:37:42 +02:00
Damir Jelić e8b2655d52 docs(crypto-ffi): Explain what a timeout of 0 means when fetching identities 2022-06-09 11:58:23 +02:00
Damir Jelić 537ef1409b test(crypto): Test that we're now notifying when we receive a /keys/query 2022-06-09 11:58:23 +02:00
Damir Jelić e2bf3d0d18 chore(crypto-js): Silence some doc warnings 2022-06-09 11:58:23 +02:00
Damir Jelić d188ef3386 feat(crypto): Add a way wait for a keys/query to be done when fetching identities. 2022-06-09 11:58:23 +02:00
Damir Jelić ba7ccb40cc feat(crypto): Wait for a key query to be done if we're claming one-time keys 2022-06-09 11:58:23 +02:00
Ivan Enderlin 1b2c644277 test(crypto-nodejs): Set up CI to run the test suites. 2022-06-09 11:34:16 +02:00
Benjamin Kampmann 6a853d0173 Merge pull request #744 from matrix-org/jplatte/readme
chore: Fix `main` docs link in readme
2022-06-09 10:51:58 +02:00
Jonas Platte 7487b24fe3 chore: Fix main docs link in readme 2022-06-09 10:21:04 +02:00
Amanda Graven 5c4f2b3430 fix(appservice): Make membership keys consistent
Correct the inconsistency between the keys used for reading and writing
the membership of a virtual user in the appservice's namespace
2022-06-08 10:42:35 +02:00
Stefan Ceriu 901b670a22 Use the nightly toolchain together with the newly introduced target-applies-to-host on the sdk-ffi crate debug builds to avoid cache corruption issues. Switched back to debug mode as the internal tokio crashes went away 2022-06-08 08:55:28 +02:00
Jonas Platte 28d6e2821b chore: Replace new usage of Box<UserId> 2022-06-07 21:12:43 +02:00
Jonas Platte 7f0b74a39d fixup! style: Remove usage of assign! macro from doctests 2022-06-07 21:07:34 +02:00
Jonas Platte 7b6869310f style: Make assign! formatting consistent 2022-06-07 21:07:34 +02:00
Jonas Platte 445b2e627d style: Remove usage of assign! macro from examples 2022-06-07 21:07:34 +02:00
Jonas Platte 0e206506d9 style: Remove usage of assign! macro from doctests 2022-06-07 21:07:34 +02:00
Jonas Platte 0fb1d72100 style: Use anyhow::Ok in more places 2022-06-07 21:07:34 +02:00
Ivan Enderlin 6d8c54deb5 chore(crypto-nodejs): Add missing newline. 2022-06-07 17:03:02 +02:00
Ivan Enderlin 07620452df chore(crypto-node): Make Clippy happy. 2022-06-07 16:50:26 +02:00
Jonas Platte 099db20555 Use target-applies-to-host to avoid unnecessary cache invalidation 2022-06-07 16:43:17 +02:00
Ivan Enderlin 75571c2c30 fix(crypto-js): Fix missing symbol. 2022-06-07 16:42:34 +02:00
Ivan Enderlin 8c95b1c4cf chore(crypto-nodejs): Fix a typo. 2022-06-07 16:40:54 +02:00
Ivan Enderlin 530c268e61 doc(crypto-nodejs): Include the README.md in the generated documentation. 2022-06-07 16:35:22 +02:00
Ivan Enderlin 99dcf84340 chore(crypto-nodejs): Use napi::Result when possible. 2022-06-07 16:28:55 +02:00
Ivan Enderlin 2a76d17bd9 doc(crypto-nodejs): Generate JavaScript/TypeScript documentation. 2022-06-07 16:26:23 +02:00
Ivan Enderlin 15af364c97 Merge branch 'main' into feat-crypto-nodejs-next 2022-06-07 15:31:03 +02:00
Ivan Enderlin ec7724f393 doc(crypto-nodejs): Improve the README.md. 2022-06-07 15:27:35 +02:00
Ivan Enderlin 1e7d509920 chore(crypto-nodejs): Clean up. 2022-06-07 14:45:20 +02:00
Ivan Enderlin 520758bf1e test(crypto-nodejs): Finish the OlmMachine test suite. 2022-06-07 14:42:24 +02:00
Benjamin Kampmann 7f49618d35 Merge pull request #729 from gnunicorn/gnunicorn/issue609
Ensure all data state stores save is encrypted
2022-06-07 12:41:38 +02:00
Benjamin Kampmann a308771a7a fix(sled): Deserialize encrypted TimelineMetadata properly 2022-06-07 12:22:54 +02:00
Benjamin Kampmann 2c4379909c fix(sled): Wrap [u8] encoding in an explicit type to prevent accidential misuse 2022-06-07 12:22:54 +02:00
Damir Jelić d4f49ca334 chore: Fix some new clippy warnings 2022-06-07 11:41:29 +02:00
Damir Jelić c97bb83af9 refactor(base): Remove a bunch of OlmMachine wrapper methods
The whole machine is nowadays exposed through the base Client, so no
need to re-expose individual methods that don't add more functionality.
2022-06-07 11:41:29 +02:00
Ivan Enderlin 12c53bb2bc test(crypto-nodejs): Add more test cases. 2022-06-07 11:05:19 +02:00
Damir Jelić 7fd973c563 refactor(crypto-ffi): Make use of the BackupRecoveryKey type instead of a string 2022-06-07 10:47:19 +02:00
Benjamin Kampmann f8dae723c3 style: Fix review remarks 2022-06-07 10:20:55 +02:00
Benjamin Kampmann 8ccf78c025 fix(indexeddb): Ensure all values are encrypted (namely filters and timeline metadata) if asked to 2022-06-07 10:20:40 +02:00
Benjamin Kampmann 47bb73cf89 fix(sled): Ensure timeline metadata is also saved encrypted 2022-06-07 10:20:27 +02:00
Benjamin Kampmann f3d952839e style: Clean up rustfmt and clippy 2022-06-07 10:19:43 +02:00
Benjamin Kampmann 85ea9279dc fix(indexeddb): Use random db in plain test for consistency 2022-06-07 10:19:27 +02:00
Benjamin Kampmann be159356cd fix(sled): Encrypt custom key and value 2022-06-07 10:19:23 +02:00
Benjamin Kampmann 571b5e61cf fix(sled): Encrypt media content 2022-06-07 10:19:20 +02:00
Benjamin Kampmann 77af11bcbc fix(sled): Encrypt saved sync_token 2022-06-07 10:19:20 +02:00
Benjamin Kampmann 335251695a fix(sled): Encrypt saved filters 2022-06-07 10:19:17 +02:00
Benjamin Kampmann bf17012d6b test(base): Add integration store test for saving filters 2022-06-07 10:19:13 +02:00
Benjamin Kampmann 328ebdba9c fix(sled): Encrypt saved user_ids 2022-06-07 10:19:08 +02:00
Benjamin Kampmann c359b011fa refactor(sled): Rename for consistency event -> value 2022-06-07 10:19:04 +02:00
Ivan Enderlin 07fed7f4df test(crypto-nodejs): Continue to test OlmMachine and add tracing support. 2022-06-06 16:27:32 +02:00
Ivan Enderlin 0ed74d8c31 test(crypto-nodejs): Test OlmMachine.receiveSyncChanges, .outgoingRequests and .markRequestAsSent. 2022-06-06 12:09:37 +02:00
Ivan Enderlin 35d7cab330 feat(crypto-nodejs): Rename requests request_id to id + add type. 2022-06-06 12:08:58 +02:00
Ivan Enderlin 407e27d176 feat(crypto-nodejs): Make changed and left optional in DeviceLists constructor. 2022-06-06 10:27:32 +02:00
Damir Jelić 0f758a643c refactor(crypto): Make the boolean parameter for the backup verification clearer 2022-06-03 16:29:17 +02:00
Damir Jelić fd2ae1ed8f docs(crypto): Improve some backup verfication docs
Co-authored-by: Denis Kasak <dkasak@termina.org.uk>
2022-06-03 16:29:17 +02:00
Damir Jelić 2b13c0832f refactor(crypto): Introduce a struct for the backup info 2022-06-03 16:29:17 +02:00
Damir Jelić b3fbd15270 feat(crypto): Improve the API to verify backups
This API change allows us to inspect why a backup is considered to be
trusted instead of just returning a boolean telling us if it's trusted
or not.
2022-06-03 16:29:17 +02:00
Amanda Graven 4e3e393596 refactor(appservice): Better virtual client sync
Store the membership state of clients in the appservice's namespace, and
construct sync events based on that information
2022-06-03 15:03:31 +02:00
Jonas Platte 7f81e7c61b chore: Optimize quote even in debug mode 2022-06-03 14:48:48 +02:00
Ivan Enderlin a75ae16b79 test(crypto-nodejs): Add more test suites. 2022-06-02 15:58:30 +02:00
Ivan Enderlin 9ebc61ad0f test(crypto-nodejs): Adding more test suites. 2022-06-02 15:24:22 +02:00
Ivan Enderlin 0d66480cd6 fix(crypto-nodejs): OlmMachine.new effectively raises an error.
Returning an `napi::Error` doesn't raise it. We must return a
`Result<_, napi::Error>` to ensure `napi` will raise the error as
expected.
2022-06-02 15:23:25 +02:00
Ivan Enderlin 02802e9088 feat(crypto-nodejs): EncryptionSettings.rotation_period and .…_period_messages are now BigInt. 2022-06-02 13:59:00 +02:00
Ivan Enderlin 1a6adc6d41 chore(crypto-nodejs): Ignore package-lock.json for now. 2022-06-02 11:10:55 +02:00
Ivan Enderlin 6d10d6150c test(crypto-nodejs): Add some test suites. 2022-06-02 11:09:57 +02:00
Damir Jelić fb1a2f6d94 feat(appservice): Add support for appservice login
An appservice can log in by providing a valid appservice token and a user within the appservice’s namespace.

This allows the appservice to acquire a scoped access token for a single user. matrix-appservice-sdk can now take a persisted device id for virtual users. If e2ee is enabled, it will automatically perform an appservice login to create the an E2EE backed session for the virtual user.
2022-06-02 10:36:33 +02:00
Damir Jelić bdee4e0547 refactor(crypto): Use a result type for invalid signatures 2022-06-02 09:31:37 +02:00
Denis Kasak 42d5eec8b7 docs(crypto): Improve Signature doc comment. 2022-06-02 09:31:37 +02:00
Damir Jelić e50c1465ea docs(crypto): Improve some signature verification related docs
Co-authored-by: Denis Kasak <dkasak@termina.org.uk>
2022-06-02 09:31:37 +02:00
Damir Jelić 5827cc9a39 refactor(crypto): Use ? instead of nesting closures when searching for a key
Co-authored-by: Jonas Platte <jplatte@element.io>
2022-06-02 09:31:36 +02:00
Damir Jelić c95fd93666 fix(types): Allow Ed25519 signatures to be invalid
Since signatures can be uploaded by anyone, unlike one-time keys which
might only be uploaded by the given device for themselves, a Signatures
struct might fail to be deserialized because a signature was maliciously
attached to the object by someone else.

We don't want to fail to deserialize all the signatures just because
someone attached an invalid one. We still would like to have the
signature be deserialized into its proper type if possible so the Raw<T>
pattern was not used.
2022-06-02 09:31:36 +02:00
Damir Jelić d96fcf7199 refactor(crypto): Return a Signatures struct in the sign method 2022-06-02 09:31:36 +02:00
Damir Jelić e2348471db fix(crypto): Make fetching of the first cross signing key more robust 2022-06-02 09:31:36 +02:00
Ivan Enderlin 8e120eb648 doc(crypto-nodejs): Write missing documentation. 2022-06-02 09:23:26 +02:00
Ivan Enderlin c573985c64 chore(crypto-nodejs): Add a .gitignore for artifacts. 2022-06-02 09:19:17 +02:00
Ivan Enderlin 6a996c7657 doc(crypto-nodejs): Write missing documentation and clean up the code. 2022-06-02 09:18:26 +02:00
Ivan Enderlin 7bb96e0ece chore(crypto-node): Use Either7 (new pending feature). 2022-06-01 22:38:52 +02:00
Ivan Enderlin dc7f0389b1 chore(crypto-node): Document and add napi(getter) when necessary. 2022-06-01 20:55:34 +02:00
Ivan Enderlin 5d4b3a0457 feat(crypto-nodejs): Implement OlmMachine.decrypt_room_event. 2022-06-01 20:55:34 +02:00
Ivan Enderlin 888ffb0a56 chore(crypto-node): Use Either5 + Either3 instead of Either. 2022-06-01 20:55:34 +02:00
Ivan Enderlin 475fffb64d feat(crypto-nodejs): Implement OlmMachine.encrypt_room_event. 2022-06-01 20:55:34 +02:00
Ivan Enderlin a8b44f26ea feat(crypto-nodejs): Implement OlmMachine.share_room_key. 2022-06-01 20:55:34 +02:00
Ivan Enderlin a7697fbd32 feat(crypto-nodejs): Implement OlmMachine.get_missing_sessions. 2022-06-01 20:55:34 +02:00
Ivan Enderlin 02e63ab9c1 chore(crypto-js): Remove a useless import. 2022-06-01 20:55:34 +02:00
Ivan Enderlin 8d909ccabe feat(crypto-nodejs): Implement OlmMachine.mark_request_as_sent. 2022-06-01 20:55:34 +02:00
Ivan Enderlin 2e22f6b6c0 feat(crypto-nodejs): Implement OlmMachine.outgoing_requests. 2022-06-01 20:55:34 +02:00
Ivan Enderlin 7c85fdaf28 doc(crypto-js): Update documentation. 2022-06-01 20:55:34 +02:00
Ivan Enderlin 1ecf90bb42 feat(crypto-nodejs): Implement OlmMachine.receive_sync_changes. 2022-06-01 20:55:34 +02:00
Ivan Enderlin e2ecba7d45 feat(crypto-nodejs): Implement OlmMachine.update_tracked_users. 2022-06-01 20:55:34 +02:00
Ivan Enderlin 8a0e0a7a4d feat(crypto-nodejs): Start implementing OlmMachine API. 2022-06-01 20:55:34 +02:00
Charlotte 🦝 Delenk c562d91533 feat(appservice): Use appservice logins for e2ee
This commit also adds a virtual user builder, which allows you to
control the device id, change the client builder, perform an appservice
login, and even restore a previously created session.

https://spec.matrix.org/v1.2/client-server-api/#appservice-login
2022-06-01 15:29:04 +01:00
Ivan Enderlin 3cf4150df2 feat: Rename OlmMachine.share_group_session to OlmMachine.share_room_key
feat: Rename `OlmMachine.share_group_session` to `OlmMachine.share_room_key`
2022-06-01 15:08:58 +02:00
Ivan Enderlin b3d52ca68c feat: Rename OlmMachine.share_group_session to OlmMachine.share_room_key.
As discussed with @poljar, the Matrix event we are creating is
`m.room.key`, so it's preferable to rename the function
`share_room_key`. Note: Olm calls the things an inbound group session,
that's where the name comes from, but it's not aligned with the
specification.
2022-06-01 14:32:11 +02:00
Ivan Enderlin e673954b98 chore: Add missing new lines at the end of files
chore: Add missing new lines at the end of files
2022-05-31 10:31:08 +02:00
Ivan Enderlin 6d7573dced chore: Add missing new lines at the end of files. 2022-05-31 10:06:35 +02:00
Ivan Enderlin 2d14452398 Merge pull request #675 from Hywan/feat-crypto-wasm
feat(crypto): Port to Wasm (in a JS host) and to NodeJS
2022-05-31 10:01:57 +02:00
Ivan Enderlin 7931c4a589 chore(crypto-js): Clean up code and make CI happy. 2022-05-31 08:44:36 +02:00
Ivan Enderlin 4db1ad350b feat(crypto-nodejs): Derive Debug for UserId. 2022-05-31 08:40:16 +02:00
Ivan Enderlin 0debbf24d7 chore(crypto-js): Remove an unknown Clippy lint for now. 2022-05-31 08:40:16 +02:00
Ivan Enderlin bb8217d10f doc(crypto-nodejs) Disable missing docs for now. 2022-05-31 08:40:16 +02:00
Ivan Enderlin 6ff5c8e918 chore(crypto-js): Thanks Clippy. 2022-05-31 08:40:16 +02:00
Ivan Enderlin 7fa89f76aa chore(crypto-js): Update vodozemac's version to match matrix-sdk-crypto's. 2022-05-31 08:40:16 +02:00
Ivan Enderlin 0335fdd07f doc(crypto): Add missing module documentation. 2022-05-31 08:40:16 +02:00
Ivan Enderlin 3f8e3b61ff test(xtask) Replace WasmFeatureSet::MatrixSdkCrypto by *Js. 2022-05-31 08:40:16 +02:00
Ivan Enderlin efe5ea6a9c test(ci): Exclude matrix-sdk-crypto-(js|nodejs) from code coverage. 2022-05-31 08:40:16 +02:00
Ivan Enderlin 6afeeea56c test(ci): Do not compile matrix-sdk-crypto to Wasm, but -crypto-js instead. 2022-05-31 08:40:16 +02:00
Ivan Enderlin bef1dfbf79 chore(crypto-js): Fix typos. 2022-05-31 08:40:16 +02:00
Ivan Enderlin 51488b40d0 doc(crypto-js) Add missing documentation. 2022-05-31 08:40:16 +02:00
Ivan Enderlin b6a637893e chore(crypto-js): Fix cargo fmt. 2022-05-31 08:40:16 +02:00
Ivan Enderlin 2a4dce30b2 Merge branch 'main' into feat-crypto-wasm 2022-05-31 08:40:11 +02:00
Ivan Enderlin 3194ad1f9a feat(crypto-js): Implement OlmMachine.get_verification. 2022-05-31 08:39:34 +02:00
Ivan Enderlin ee648144a2 feat(crypto-nodejs): Split into a new crate: matrix-sdk-crypto-nodejs.
Why? Because `napi` and `wasm-bindgen` are too different. At this
step, the most notable bugs are the way `napi` is handling its proc
macros. There is too much conflicts when used with `#[cfg_attr]`. It
makes the code repetitive and harder to read and to understand (and
also to compile, we must be very careful). But on the short-term,
quickly, we will see more notable differences between `wasm-bindgen`
and `napi`, e.g. with array (in `wasm-bindgen`, we can downcast array
items into particular types, with `napi` it's going to be a very
different code).

Instead of fighting the proc macros bugs now, and having to split the
code later inside the same crate, we believe it's a good idea to split
the code now into 2 crates. At first we will see obvious code
duplications, but on the short-term, the code is likely to be more and
more different.
2022-05-31 08:39:34 +02:00
Ivan Enderlin afef9103a3 feat(crypto-js): Continue to port the API to NodeJS. 2022-05-31 08:39:34 +02:00
Ivan Enderlin 4df5ee6087 chore(crypto-js): Improve the Makefile for NodeJS support. 2022-05-31 08:39:34 +02:00
Ivan Enderlin 1a731ec385 feat(crypto-js): Rename OlmMachine.encrypt to .encrypt_room_event. 2022-05-31 08:39:34 +02:00
Ivan Enderlin 84fe78bab3 Merge branch 'main' into feat-crypto-wasm 2022-05-31 08:39:29 +02:00
Ivan Enderlin bce11b209e feat(crypto-js): Implement OlmMachine.update_tracked_users. 2022-05-31 08:38:24 +02:00
Ivan Enderlin 6c472f873f feat(crypto-js): Start adding support for NodeJS. 2022-05-31 08:38:24 +02:00
Ivan Enderlin 250b85dc79 feat(crypto): Extract js module to its own crate: matrix-sdk-crypto-js. 2022-05-31 08:38:13 +02:00
Ivan Enderlin f3ab1ae276 chore(crypto): Fix a typo. 2022-05-31 08:36:37 +02:00
Ivan Enderlin 6b2df7afdd feat(crypto): Implement `OlmMachine.get_missing_sessions. 2022-05-31 08:36:37 +02:00
Ivan Enderlin cdb252be5e chore(crypto): Move everything inside crates/matrix-sdk-crypto/. 2022-05-31 08:36:37 +02:00
Ivan Enderlin db30ef6ee4 test(crypto): Add tests for the Wasm API. 2022-05-31 08:36:37 +02:00
Ivan Enderlin da8699fe40 feat(crypto): DeviceLists.new expects Array<UserId>s now. 2022-05-31 08:36:37 +02:00
Ivan Enderlin 16b5eebe23 feat(crypto): Implement a hacky downcast function. 2022-05-31 08:36:37 +02:00
Ivan Enderlin 8161360852 feat(crypto): Add toString methods on identifier objects. 2022-05-31 08:36:37 +02:00
Ivan Enderlin f01cfe42b4 feat(crypto): Implement EncryptionSettings.new with default values. 2022-05-31 08:36:37 +02:00
Ivan Enderlin a024c9b268 docs(crypto): Add missing documentation. 2022-05-31 08:36:37 +02:00
Ivan Enderlin c20349f46f feat(crypto): Implement OlmMachine.share_group_session. 2022-05-31 08:36:37 +02:00
Ivan Enderlin e9d37d7c4e docs(crypto): Add missing docs. 2022-05-31 08:36:37 +02:00
Ivan Enderlin 8b94aed27f fix(crypto): Use txn_id for transaction_id. 2022-05-31 08:36:37 +02:00
Ivan Enderlin dc5b15e799 fix(crypto): OutgoingRequest::ToDeviceRequest was not correctly mapped. 2022-05-31 08:36:37 +02:00
Ivan Enderlin 30e9189f7b fix(crypto): Use JavaScript naming convention for OlmMachine.invalidate_group_session. 2022-05-31 08:36:37 +02:00
Ivan Enderlin b6a5d4962b Merge branch 'main' into feat-crypto-wasm 2022-05-31 08:36:30 +02:00
Ivan Enderlin ee713f928f feat(crypto): Implement OlmMachine.encrypt and .invalidate_group_session. 2022-05-31 08:35:09 +02:00
Ivan Enderlin 444ff9936b feat(crypto): Implement RoomId. 2022-05-31 08:35:09 +02:00
Ivan Enderlin 2451815226 feat(crypto): Implement *PublicKey.to_base64 and .length. 2022-05-31 08:35:09 +02:00
Ivan Enderlin 86c6e601bd chore(crypto): Refactor the code with TryFrom on a tuple. 2022-05-31 08:35:09 +02:00
Ivan Enderlin 9f159ff5a4 feat(crypto): Implement OlmMachine.mark_request_as_sent.
To implement this method, a new `responses::OwnedResponse`
intermediate type was needed. In addition to that, the `http` crate is
now required when the `js` feature is enabled.
2022-05-31 08:35:09 +02:00
Ivan Enderlin 056f34883f feat(crypto): Implement OlmMachine.trackedUsers. 2022-05-31 08:35:09 +02:00
Ivan Enderlin 2d15f758da feat(crypto): Use JavaScript naming style for methods. 2022-05-31 08:35:09 +02:00
Ivan Enderlin acd5de3cf3 feat(crypto): Implement ServerName, and add UserId.serverName. 2022-05-31 08:35:09 +02:00
Ivan Enderlin f0bb35a96c feat(crypto): Add changed and left to the constructor of DeviceLists. 2022-05-31 08:35:09 +02:00
Ivan Enderlin 1d38e54739 feat(crypto): Return a JsError rather than a String. 2022-05-31 08:35:09 +02:00
Ivan Enderlin 08665dcd1c feat(crypto): Implement our own future_to_promise helper to simplify code.
`wasm_bindgen_future::future_to_promise` expects a `Future<Output =
Result<JsValue, JsValue>>`. We reimplement this function by expecting
a `Future<Output = Result<T, anyhow::Error>>` where `T:
Into<JsValue>`. That way, we apply the type conversions to `JsValue`
inside this helper rather than in the call site. Additionally, all
errors are managed automatically without having to deal with `JsError`
or `JsValue`. It makes the code simpler to read and easier to write
from my point of view.
2022-05-31 08:35:09 +02:00
Ivan Enderlin 569adb7ceb feat(crypto) Implement OlmMachine.identity_keys. 2022-05-31 08:35:09 +02:00
Ivan Enderlin fd4dff79d4 feat(crypto) Implement OlmMachine.user_id, .device_id and .display_name. 2022-05-31 08:35:09 +02:00
Ivan Enderlin fdb9fe21c6 feat(crypto) Remove existing unwrap code. 2022-05-31 08:35:09 +02:00
Ivan Enderlin 7e5eec82c5 feat(crypto) Implement OlmMachine.outgoing_requests. 2022-05-31 08:35:09 +02:00
Ivan Enderlin 901715bcf3 chore(crypto) Generate a smaller Wasm module. 2022-05-31 08:35:09 +02:00
Ivan Enderlin 3aa46fa746 feat(crypto) Implement OlmMachine.receive_sync_changes & friends. 2022-05-31 08:35:09 +02:00
Ivan Enderlin 3318789a8b feat(crypto) Implement UserId, DeviceId and OlmMachine in Wasm for JS. 2022-05-31 08:35:09 +02:00
Ivan Enderlin 0fe0910fea feat(crypto) Reduce Wasm binary size by enabling LTO. 2022-05-31 08:35:09 +02:00
Damir Jelić a11633381b Merge branch 'poljar/borrow-signature-check-fix' 2022-05-30 12:54:35 +02:00
Benjamin Kampmann 2ff6497604 Merge pull request #715 from gnunicorn/gnunicorn/issue694
docs: configure docs.rs build to contain more features
2022-05-27 22:24:02 +02:00
Damir Jelić 7f87abf408 refactor(crypto): Simplify the signature checking method 2022-05-27 21:29:58 +02:00
Damir Jelić dd49a8bd43 fix(crypto): Don't require mutable borrows when signature checking 2022-05-27 21:28:35 +02:00
Damir Jelić f8c3a1d03b Merge branch 'poljar/signatures-struct' 2022-05-27 20:58:45 +02:00
Damir Jelić 808c4c6f3c chore(crypto): Remove some indentation levels in the types module
Co-authored-by: Jonas Platte <jplatte@element.io>
2022-05-27 20:55:17 +02:00
Damir Jelić a14549d5cc fix(crypto): Don't unwrap when converting to canonical json 2022-05-27 20:55:17 +02:00
Damir Jelić 9b5b4ab2b2 refactor(crypto): Use the Signatures struct for the CrossSigningKey 2022-05-27 20:55:17 +02:00
Damir Jelić 5756057719 refactor(crypto): Use the new Signatures struct for the DeviceKeys 2022-05-27 20:55:17 +02:00
Damir Jelić c5ef3e7c94 refactor(crypto): Turn the SignedKeySignatures into a struct 2022-05-27 20:55:17 +02:00
Damir Jelić fa7c1b60f6 feat(sdk): Replace some Mutex usage with a OnceCell
This makes some simpler getter methods non-async.
2022-05-27 16:37:51 +02:00
Julian Sparber 39b1fff218 Merge remote-tracking branch 'origin/main' into user_once_cell_for_session 2022-05-27 15:53:22 +02:00
Benjamin Kampmann c6df6b421c docs: fix target and feature-list for docsrs 2022-05-27 13:04:07 +02:00
Benjamin Kampmann f9b4fd2d12 docs: configure docs.rs build to contain more features 2022-05-27 10:44:16 +02:00
Damir Jelić e5390e18de refactor(crypto): Introduce a SignJson trait
This patch collects our json signing logic into a single place.
2022-05-27 10:39:12 +02:00
Brandon Lau 28cd0c19e9 fix(crypto-ffi): make crypto-ffi generate a static library for iOS clients 2022-05-27 10:38:21 +02:00
Damir Jelić 15ebc95cd0 chore(qrcode): Add more missing Eq implementations 2022-05-25 13:52:22 +02:00
Damir Jelić 39e12a86ca chore(crypto): Bump vodozemac 2022-05-25 13:49:00 +02:00
依云 ec9ec2567f feat: Add .resolve_room_alias() method to the Client 2022-05-24 08:43:02 +02:00
Damir Jelić fa9c91fb0e fix(crypto-ffi): Add support to encrypt custom events 2022-05-23 19:37:04 +02:00
Johannes Becker 24b71bf869 feat(appservice): Improve autojoin example 2022-05-23 14:14:05 +02:00
Benjamin Kampmann dd83cdd74b Merge pull request #704 from matrix-org/poljar/eq-store-encryption
feat(store-encryption): Derive Eq for some structs
2022-05-23 13:07:29 +02:00
Jonas Platte 453cae641b fix(docs): Remove history gh-pages branch
This should drastically reduce the repository size.
2022-05-23 12:57:45 +02:00
Damir Jelić f838b5fae8 fix(base): Fix a clippy warning about temporary variables 2022-05-23 11:35:23 +02:00
Damir Jelić 1f722f224f feat(crypto): Add a bunch of Eq implementations 2022-05-23 11:35:07 +02:00
Damir Jelić a992a4e831 feat(store-encryption): Derive Eq for some structs 2022-05-23 11:14:09 +02:00
Benjamin Kampmann 017359b081 Merge pull request #700 from gnunicorn/b-improve-coverage-reporting
Improve CI coverage reporting
2022-05-20 12:33:05 +02:00
Benjamin Kampmann 08718acd57 Merge pull request #698 from matrix-org/poljar/rename-encrypt-method
refactor(crypto): Make it clear that the encrypt method is for room events
2022-05-20 10:35:03 +02:00
Benjamin Kampmann dd1f817701 ci(CodeCoverage): exclude ffi & wasm from default project 2022-05-20 10:26:31 +02:00
Benjamin Kampmann 81db9ef4ca ci(CodeCoverage): Remove patch-level coverage reporting 2022-05-20 08:34:56 +02:00
Benjamin Kampmann e927834108 ci(CodeCoverage): split code coverage reporting in mandatory and optional areas 2022-05-20 08:34:39 +02:00
Damir Jelić f3045dbf99 fixup! refactor(crypto): Make it clear that the encrypt method is for room events 2022-05-20 08:32:50 +02:00
Jonas Platte d6c6211c00 chore: Use matrix_sdk::Result alias more 2022-05-20 07:52:39 +02:00
Jonas Platte 85949081ce chore: Consistently use anyhow for Result-returning doctests
Cuts down on syntactic noise.
2022-05-20 07:52:39 +02:00
Jonas Platte cbcc5feef2 fix(sled): Fix unused import when experimental-timeline isn't enabled 2022-05-20 07:52:39 +02:00
Jonas Platte 1b569a8fd4 chore: Consistently use anyhow::Result for example main fn's
When an `Err` is propagated out of `main`, it will be printed using
`Debug`, which is much easier to read in anyhow::Error's case. See also
https://docs.rs/anyhow/latest/anyhow/struct.Error.html#display-representations
2022-05-20 07:52:39 +02:00
Damir Jelić 813f388812 refactor(crypto): Make it clear that the encrypt method is for room events 2022-05-20 07:47:47 +02:00
Damir Jelić 552de33dbc Merge branch 'dkasak/docs-improvements' 2022-05-20 07:26:00 +02:00
Denis Kasak c3f2003eb7 docs: Slightly reword CryptoStore doc for consistency. 2022-05-19 16:22:09 +02:00
Denis Kasak 3b70d7f9ba docs: Improve wording of store module-level comment
Includes a fix to refer to the `e2e-encryption` feature instead of
`encryption` (which doesn't exist).
2022-05-19 16:22:09 +02:00
Denis Kasak c00c9d7b81 docs: Reword feature table so the wording is more uniform 2022-05-19 16:22:09 +02:00
Denis Kasak 126e8f1bd9 docs: Unify references to "cryptostore" as "crypto store" 2022-05-19 16:22:09 +02:00
Denis Kasak 9e6e76e5ed docs: Fix reference to ClientConfig in doc comment 2022-05-19 15:38:13 +02:00
Damir Jelić d1410fcded ci: Run cargo audit every day 2022-05-19 10:03:46 +02:00
Jonas Platte b955e7aad9 Use anyhow::Ok instead of turbofish on Result 2022-05-18 22:04:44 +02:00
Jonas Platte a364018c0e chore: Use serde::de::DeserializeOwned convenience trait 2022-05-18 22:04:44 +02:00
Jonas Platte 0f910b6229 fix(base): Make max_power_level reflect the current maximum only
… instead of taking into account an older maximum as well.
2022-05-18 14:03:12 +02:00
Benjamin Kampmann 736f0e7687 feat: Initial apple platforms support
Merge pull request #571 from matrix-org/jplatte/matrix-sdk-ffi
2022-05-18 13:14:29 +02:00
Stefan Ceriu 6a1b85c560 Fix xcframework debug build script 2022-05-18 13:43:29 +03:00
Benjamin Kampmann e3503fe102 ci: one more move 2022-05-18 11:56:38 +02:00
Benjamin Kampmann 4522b4e8f5 ci: move rust cache to include uniffi bindgen install 2022-05-18 11:32:03 +02:00
Benjamin Kampmann 886809b579 chore(Apple): Move apple into subfolder 2022-05-18 11:24:30 +02:00
Benjamin Kampmann 97b91a47f1 ci: Setup CI test runs FFI crate (Apple platforms support)
Merge pull request #679 from matrix-org/stefan/matrix-sdk-ffi
2022-05-18 10:52:39 +02:00
Stefan Ceriu 4b8b9db075 Have FII action only run on PRs targetting main, similar to the CI one. 2022-05-18 11:49:29 +03:00
Jonas Platte bc207f1e5c chore(sdk): Upgrade async-once-cell to 0.3.1 2022-05-18 10:31:52 +02:00
Stefan Ceriu d863b4eb75 Bump uniffi to version 0.18.0 2022-05-18 11:13:15 +03:00
Stefan Ceriu 45cb162e5a Fix sample project, cleanup tests and add github action 2022-05-18 11:08:51 +03:00
Stefan Ceriu ba2cef62b0 Move apple scripts; tweak the debug one to allow for CI builds 2022-05-18 11:08:51 +03:00
Jonas Platte 2d7fb1b61c fix(matrix-sdk): room::Common:messages() don't return decryption error
If decryption fails we want that the user still has access to
the events.
This was broken in a previous commit.
2022-05-17 18:09:09 +02:00
Julian Sparber d6f9e5f6b6 Remove extra controll flow 2022-05-17 17:52:12 +02:00
Julian Sparber 9c07ff1166 matrix-sdk: room::Common:messages() don't return decryption error
If decryption fails we want that the user still has access to
the events.
This was broken in a previous commit.
2022-05-17 17:23:32 +02:00
Julian Sparber 5bd7d17234 fix(matrix-sdk): room::Common:event() don't return decryption error 2022-05-17 17:03:28 +02:00
Benjamin Kampmann 7d439b1697 Merge pull request #680 from gnunicorn/ben-fix-docs
Fixing docs
2022-05-17 15:45:39 +02:00
Benjamin Kampmann 39f1b9d464 docs: fix link
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
2022-05-17 13:54:37 +02:00
Benjamin Kampmann 8a86369e68 Merge branch 'ben-fix-docs' into jplatte/matrix-sdk-ffi 2022-05-17 13:39:46 +02:00
Benjamin Kampmann a19999b240 docs: fixing broken inner link 2022-05-17 13:38:07 +02:00
Benjamin Kampmann a72a05edc3 Merge remote-tracking branch 'origin/main' into jplatte/matrix-sdk-ffi 2022-05-17 13:05:24 +02:00
Julian Sparber d0cc3d9c2b Don't split links to two lines
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
2022-05-17 12:56:24 +02:00
Benjamin Kampmann 2862934b87 style: fix clippy lints for ffi 2022-05-17 12:51:47 +02:00
Julian Sparber 3f3f9d653b Fix code style 2022-05-17 12:46:06 +02:00
Julian Sparber 83fc91f87e Add a pretty label for Session link 2022-05-17 12:39:11 +02:00
Julian Sparber 1e77c39498 Fix store example 2022-05-17 12:37:51 +02:00
Julian Sparber 1de27bcc0c Fix CI and address requested changes 2022-05-17 12:22:35 +02:00
Amanda Graven 248fff370a test(base): Remove invalid sync event from json
The test json used for mocking a sync response contained an ill-formed
event with a room_id key present in the event. Since the deserialization
ignores the room_id key, this resulted in the client's membership state
evaluating to left going by the contents of the state events, despite
the room being in the "joined" section of the sync response. This is a
violation of the spec.
2022-05-17 11:31:36 +02:00
Julian Sparber 26dd2d0e62 Merge remote-tracking branch 'origin/main' into user_once_cell_for_session 2022-05-17 11:14:28 +02:00
Benjamin Kampmann 4bbfa4345f Merge pull request #678 from Hywan/fix-crypto-doc
docs(crypto): Remove outdated documentation and use auto-link
2022-05-17 10:28:07 +02:00
Johannes Becker 5f92113627 chore: Use resolver2 for workspace 2022-05-17 10:24:28 +02:00
Ivan Enderlin 426a93f07c docs(crypto): Remove outdated documentation and use auto-link. 2022-05-17 10:08:42 +02:00
Benjamin Kampmann 0949979a1b Merge remote-tracking branch 'origin/main' into jplatte/matrix-sdk-ffi 2022-05-16 13:35:51 +02:00
Benjamin Kampmann 76144de881 Fix(SDK): add missing import for experimental-timeline feature
Merge pull request #671 from jsparber/fix_import
2022-05-13 10:33:03 +02:00
Stefan Ceriu bd4763235a chore(matrix-sdk-ffi) Use stable toolchain for targeting aarch64-apple-ios-sim 2022-05-12 16:49:49 +03:00
Julian Sparber 911b5415b9 ci: Use experimental-timeline feature 2022-05-12 13:59:18 +02:00
Julian Sparber c3fc6ff58f Fix missing import for experimental-timeline feature 2022-05-12 12:38:58 +02:00
Benjamin Kampmann 4c84f252d2 Merge pull request #667 from matrix-org/ben-releasing-base-0.5.1
Release matrix-sdk-base 0.5.1
2022-05-11 19:23:16 +02:00
Benjamin Kampmann 70c0626882 chore: tag base 0.5.1 2022-05-11 19:01:12 +02:00
Benjamin Kampmann 5570181bf8 fix(sdk): Fix regression with push rules being applied to the own user_id only instead of all but the own user_id
Merge pull request #664 from JCWasmx86/ignore_notification
2022-05-11 18:52:55 +02:00
Benjamin Kampmann 7088ff89b5 Merge pull request #665 from matrix-org/ben-releasing-0.5.0
Releasing 0.5.0
2022-05-11 18:50:34 +02:00
Benjamin Kampmann 2561ed1df9 docs: Adding release notes for 0.5.0 2022-05-11 18:16:44 +02:00
JCWasmx86 3f36528a98 fix(sdk): Fix regression 2022-05-11 18:15:33 +02:00
Benjamin Kampmann 34da27222f chore: Preparing all the small things for release
Merge pull request #657 from gnunicorn/ben-preping-for-release
2022-05-11 18:10:11 +02:00
Benjamin Kampmann aa69bda05b feat(matrix-sdk): Expose method to decrypt room events
Merge pull request #614 from jsparber/fix_decrypt_timeline
2022-05-11 17:34:19 +02:00
Benjamin Kampmann 8bdd0ffc5d docs: Update crates/matrix-sdk-crypto-ffi/README.md
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
2022-05-11 17:32:22 +02:00
Benjamin Kampmann c21408934c chore: Mark crypto-ffi as non-publish 2022-05-11 17:31:19 +02:00
Benjamin Kampmann daa0768a04 Apply suggestions from code review
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
2022-05-11 17:30:12 +02:00
Benjamin Kampmann 706ea248eb Merge pull request #660 from gnunicorn/ben-encrypt-indexeddb-cryptostore-keys
fix(indexeddb): encrypt crypto-store key
2022-05-11 17:26:41 +02:00
Benjamin Kampmann d120d9b70f style(indexeddb): fix import order 2022-05-11 17:09:29 +02:00
Benjamin Kampmann ef2754736a docs(sled): Document doubts on sled in the readme 2022-05-11 17:07:07 +02:00
Jonas Platte bc78095611 fix(sdk): Don't send notifications for your own user 2022-05-11 17:02:30 +02:00
Benjamin Kampmann 45ea472c83 Merge remote-tracking branch 'origin/main' into ben-preping-for-release 2022-05-11 16:57:40 +02:00
Benjamin Kampmann 583810726d style(indexeddb): Minor style fixes for fmt and clippy 2022-05-11 16:56:18 +02:00
JCWasmx86 5fef975ef2 fix(sdk): Don't send notifications for your own user 2022-05-11 16:52:24 +02:00
Benjamin Kampmann 86d2a74c25 Chore: adding issue tracker link to fixme 2022-05-11 15:32:09 +02:00
Benjamin Kampmann aa5e28e58f style(indexeddb): &self.store_cipher instead of Some(ref cipher) 2022-05-11 15:27:28 +02:00
Benjamin Kampmann 0080a74d3b fix(indexeddb): temporarily disable tests 2022-05-11 15:24:56 +02:00
Benjamin Kampmann 44c5244b9a style: fixing cargo format 2022-05-11 13:09:07 +02:00
Benjamin Kampmann 339d701477 fix(indexeddb): Encrypt key with store-cipher 2022-05-11 13:04:15 +02:00
Benjamin Kampmann 74a01376c7 test(sled): Add tests for encrypted crypto-store 2022-05-11 12:42:45 +02:00
Julian Sparber 379e3f27af Merge remote-tracking branch 'origin/main' into fix_decrypt_timeline 2022-05-11 12:28:43 +02:00
Julian Sparber 89e0af97af Drop trait used in room::Common::decrypt_event 2022-05-11 12:28:20 +02:00
Damir Jelić fbb369da8d refactor(crypto): Remove the dead pickle key 2022-05-11 12:02:35 +02:00
Jonas Platte 1fdd1ab23a Cleanup after rebase 2022-05-11 11:57:27 +02:00
Jonas Platte 40dcc988d6 fixup! feat: Initial apple platforms support 2022-05-11 11:07:50 +02:00
Jonas Platte 9909cb597a squash! feat: Initial apple platforms support
Enable sending of messages
2022-05-11 11:07:50 +02:00
Jonas Platte 56cfe8f231 squash! feat: Initial apple platforms support
Some FFI API cleanup
2022-05-11 11:07:50 +02:00
Jonas Platte ab9d8eb52b feat: Initial apple platforms support
Co-authored-by: Stefan Ceriu <stefan.ceriu@gmail.com>
Co-authored-by: Benjamin Kampmann <ben.kampmann@gmail.com>
2022-05-11 11:07:42 +02:00
Julian Sparber af01c64712 Fix doc ofr room::Common::decrypt_event() 2022-05-11 11:01:54 +02:00
Julian Sparber c8233b6c85 Drop CryptoHolder and use OnceCell for OlmMachine
THe CryptoHolder is just used to hold the crypto-store till the
matrix_sdk::Session is set and it is possible to create the OlmMachine.
But with this approch we need to use a Mutex and getting the OlmMachine
becomes more expensive because of this. Therefore this replaces the
Mutex with a OnceCell. The only downside is that the BaseClient needs to
hold onto a referance to the crypto-store. (It would be possible to drop
it after the OlmMachine is created, but I don't think gives use any
improvment)
2022-05-11 10:48:12 +02:00
Julian Sparber b72bdcd7d4 Use OnceCell to store matrix_sdk::Session
Since the session can be set only once there is no point in using a
Mutex or RwLock.
2022-05-10 17:10:34 +02:00
Benjamin Kampmann ab87013125 chore: make wasm-example non-publish 2022-05-10 15:10:01 +02:00
Benjamin Kampmann e146daf2a3 chore: bump main crate 2022-05-10 15:09:41 +02:00
Julian Sparber 5501378a77 Merge remote-tracking branch 'origin/main' into fix_decrypt_timeline 2022-05-10 14:55:29 +02:00
Julian Sparber b586f1690b use trait as argument for room::Common::decrypt_event 2022-05-10 14:54:13 +02:00
Benjamin Kampmann 1c967669d9 chore: Bumping crate versions 2022-05-10 13:41:00 +02:00
Benjamin Kampmann 89a8245ce6 fix(test-macros): Add missing feature from syn 2022-05-10 13:09:27 +02:00
Benjamin Kampmann d2f251b2d5 chore: version and path fixes for releasing 2022-05-09 20:11:10 +02:00
Benjamin Kampmann c72b769389 Merge remote-tracking branch 'origin/main' into ben-preping-for-release 2022-05-09 20:09:26 +02:00
Benjamin Kampmann 41799a08ed Merge pull request #655 from matrix-org/ben-name-alignment
Align crate names
2022-05-09 20:04:02 +02:00
Benjamin Kampmann 4b2bac965d docs: Adding Readmes 2022-05-09 17:58:31 +02:00
Benjamin Kampmann c61215630b chore: Fixing missing Cargo.toml Metadata" 2022-05-09 17:43:41 +02:00
Benjamin Kampmann 23a13a77a4 Merge remote-tracking branch 'origin/main' into ben-name-alignment 2022-05-09 17:04:17 +02:00
Benjamin Kampmann cea57724e7 missed one 2022-05-09 16:39:50 +02:00
Jonas Platte 1f714e9cc5 feat(sdk): Allow OriginalSyncRoomRedactionEvent as first event handler param 2022-05-09 16:38:58 +02:00
Jonas Platte 02587bf6bf fix(sdk): Fix wrong event handler ID for redacted redaction event 2022-05-09 16:38:58 +02:00
Jonas Platte 320a20b787 chore: Add store error backend variant constructors 2022-05-09 16:38:58 +02:00
Jonas Platte 844b22fd8e chore: Remove From<Box<dyn Error + …>> impls for store errors 2022-05-09 16:38:58 +02:00
Benjamin Kampmann 26c82b3010 fix: fixing missed cases and style 2022-05-09 16:22:37 +02:00
Benjamin Kampmann 1de4a6cdd6 refactor: Rename matrix-crypto-ffi to matrix-sdk-crypto-ffi 2022-05-09 16:12:11 +02:00
Benjamin Kampmann 08f180cdb7 refactor: Rename matrix-qrcode to matrix-sdk-qrcode 2022-05-09 16:12:11 +02:00
Denis Kasak 8c3843f392 Merge pull request #654 from matrix-org/dkasak/switch-to-vodozemac-release
chore: Switch to released vodozemac
2022-05-09 12:46:15 +00:00
Denis Kasak b396232756 refactor: clippy fixes 2022-05-09 14:34:31 +02:00
Denis Kasak 9e3089074f chore: Switch to released vodozemac. 2022-05-09 14:06:05 +02:00
Julian Sparber fa37a2dea2 Fix missing referance 2022-05-09 13:58:04 +02:00
Julian Sparber 3910122fd5 Remove uneeded ref
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
2022-05-09 13:51:03 +02:00
Julian Sparber 2919c2d5d1 matrix-sdk: Expose method to decrypt room events
The also adds an enum so that the user can give many different rust
types to the decryption method.
2022-05-09 13:12:40 +02:00
Jonas Platte 0fad7b60a9 feat(base): Properly handle redacted m.room.member events 2022-05-09 12:38:22 +02:00
Jonas Platte a2fb420635 chore(base): Use PowerLevels::for_user helper 2022-05-09 12:38:22 +02:00
Jonas Platte 6088993706 chore(base): Move MinimalStateEvent higher up the module hierarchy 2022-05-09 12:38:22 +02:00
Jonas Platte 41bcc9bdd7 chore(base): Remove unnecessary bounds on MinimalStateEvent 2022-05-09 12:38:22 +02:00
Jonas Platte dc08d5f62b chore: Update MemberEvent to allow redacted member events 2022-05-09 12:38:22 +02:00
Jonas Platte 985c7d7b36 chore: Inline From trait implementations for MemberEvent
They were each just used in a single place.
2022-05-09 12:38:22 +02:00
Jonas Platte 58bcd354f6 chore(sdk): Reduce unnecessary clones 2022-05-09 12:38:22 +02:00
Ivan Enderlin 5c6a6464c4 chore(crypto) Fix a typo in the code. 2022-05-09 11:50:40 +02:00
Ivan Enderlin d3c20b2a13 feat(crypto) Generate a cdylib for the crate.
Ask `rustc` to generate a dynamic system library, which will be useful
to generate a Wasm module.
2022-05-09 10:51:18 +02:00
Ivan Enderlin 7817af9aa6 feat(crypto) Add the js feature.
This patch updates to code to raise a compilation error if the `js`
feature is used for another architecture than `wasm32`.
2022-05-09 10:40:32 +02:00
Ivan Enderlin 7569c08ada feat(crypto) Add wasm-bindgen as a dep and simplify Cargo.toml. 2022-05-09 10:40:13 +02:00
Charlotte be2a818c84 feat(base)!: Use boxed errors in StoreError and CryptoStoreError 2022-05-06 17:05:27 +02:00
Benjamin Kampmann 8b805f9f01 Merge pull request #649 from zecakeh/display-name
DisplayName fixes
2022-05-06 14:46:49 +02:00
Benjamin Kampmann 86b9dc5e57 style(appservice): Remove allocation and make clippy happy 2022-05-06 14:08:27 +02:00
Jonas Platte 260f888a89 chore(appservice): Fix another clippy warning 2022-05-06 14:08:01 +02:00
Jonas Platte 5907fac248 chore(base): Rewrite BaseRoomInfo::handle_redaction 2022-05-06 14:08:01 +02:00
Jonas Platte 3c8da5f7e1 feat(base): Handle redactions in BaseRoomInfo 2022-05-06 14:08:01 +02:00
Jonas Platte 8043b6c1e1 chore(base): Store topic event's ID in BaseRoomInfo 2022-05-06 14:08:01 +02:00
Jonas Platte 4e16f79ad2 chore(base): Store tombstone event's ID in BaseRoomInfo 2022-05-06 14:08:01 +02:00
Jonas Platte f93baf7ed4 chore(base): Store name event's ID in BaseRoomInfo 2022-05-06 14:08:01 +02:00
Jonas Platte 9e058b6202 chore(base): Store join_rules event's ID in BaseRoomInfo 2022-05-06 14:08:01 +02:00
Jonas Platte a5e81ebcc9 chore(base): Store history_visibility event's ID in BaseRoomInfo 2022-05-06 14:08:01 +02:00
Jonas Platte aa7fc8ff47 chore(base): Store guest_access event's ID in BaseRoomInfo 2022-05-06 14:08:01 +02:00
Jonas Platte 849fbe94f1 chore(base): Store create event's ID in BaseRoomInfo 2022-05-06 14:08:01 +02:00
Jonas Platte c9527e7263 chore(base): Store canonical_alias event's ID in BaseRoomInfo 2022-05-06 14:08:01 +02:00
Jonas Platte 9a3b81178f chore(base): Store avatar event's ID in BaseRoomInfo
Required to make redactions work properly.
2022-05-06 14:08:01 +02:00
Jonas Platte 1e9e13ab63 chore(base): Use RoomInfo::room_version accessor 2022-05-06 14:08:01 +02:00
Kévin Commaille 2545e1bd72 fix(sdk): Re-export DisplayName 2022-05-06 11:35:48 +02:00
Kévin Commaille 1b8337cdc2 doc(sdk-base): Fix typo 2022-05-06 11:35:48 +02:00
Jonas Platte b95aea9cf0 chore(crypto): Fix new clippy warning 2022-05-06 11:29:35 +02:00
Julian Sparber 12cdf8c159 chore(sdk): Use OnceCell to store server versions 2022-05-06 11:08:10 +02:00
Benjamin Kampmann 2054f5deef docs(crypto-ffi) Fix a typo in the README.md
Merge pull request #645 from Hywan/doc-readme-typo
2022-05-06 08:23:28 +02:00
Benjamin Kampmann 0a6983512a Merge pull request #646 from Hywan/doc-sdk-base-readme-typo
docs(sdk-base) Fix a typo in the `README.md`
2022-05-06 08:07:34 +02:00
Ivan Enderlin 977438207c docs(sdk-base) Fix a typo in the README.md. 2022-05-05 13:42:34 +02:00
Ivan Enderlin 87b849a95b docs(crypto-ffi) Fix a typo in the README.md. 2022-05-05 13:36:39 +02:00
Damir Jelić 3a4656cedd Merge branch 'poljar/cleanup-verification-constructors' 2022-05-05 13:16:34 +02:00
Benjamin Kampmann 7e399e1e8d Merge pull request #644 from matrix-org/poljar/fix-sled-cryptostore-only-compilation
fix(sled): Fix the compilation if only the cryptostore is enabled
2022-05-05 12:43:38 +02:00
Benjamin Kampmann b9e92886de refactor!: Put timeline behind experimental-timeline-feature-flag 2022-05-05 12:31:02 +02:00
Damir Jelić 2c415abce8 fix(sled): Fix the compilation if only the cryptostore is enabled 2022-05-05 12:22:16 +02:00
Benjamin Kampmann 3de2a9ad22 feat(sled): Add state store db schema version support
Merge pull request #640 from matrix-org/gnunicorn/issue585
2022-05-05 12:13:30 +02:00
Benjamin Kampmann 0f95687bec fix(base): Don't create empty changeset for each run 2022-05-05 12:11:33 +02:00
Damir Jelić 2a5f17005d refactor(crypto): Make the transaction id non-optional in the Sas constructor 2022-05-05 11:55:00 +02:00
Benjamin Kampmann 5fce18f4dd chore: remove unneccessary feature-flag 2022-05-05 11:21:34 +02:00
Benjamin Kampmann 93b42236fe chore: Merge remote-tracking branch 'origin/main' into b-featureflag-timeline 2022-05-05 10:33:56 +02:00
Benjamin Kampmann 26935ee1c0 Fix(room)!: Calculate display_name correctly for invited rooms
- [x] Make the `DisplayName` an actual type to allow API users to localize the generic name
 - [x] tests for various naming use cases
 - [x] fix the cases where we currently calculate a faulty name, fixes #133 
 - [x] strong-typed EitherMemberEvent from storage
 - [x] add tests for eithermember in store integration tests 
 - [x] update sled store for new trait signature
 - [x] update indexeddb store for new signature
 - [x] rename `DisplayName::Computed` to `DisplayName::Calculated`
 - [x] fix renaming failing test(s)
2022-05-04 20:04:07 +02:00
Benjamin Kampmann ab08ce6ff1 style(sled): cargo fmt 2022-05-04 16:54:03 +02:00
Benjamin Kampmann ae3cd70904 feat(sled): Add store db schema version support 2022-05-04 16:39:08 +02:00
Benjamin Kampmann 7b21166784 chore: Merge remote-tracking branch 'origin/main' into b-featureflag-timeline 2022-05-04 16:17:06 +02:00
Benjamin Kampmann 403ce9b711 chore: Merge remote-tracking branch 'origin/main' into gnunicorn/issue133 2022-05-04 16:10:22 +02:00
Benjamin Kampmann 98fa629f38 fix(memstore): Separate stripped and regular user indixes 2022-05-04 16:09:54 +02:00
Benjamin Kampmann 75f0fe94e8 fix(indexeddb): Separate stripped and regular user_id indixes 2022-05-04 16:02:02 +02:00
Benjamin Kampmann c0c4c603aa refactor!: Cleaning up feature gates
Merge pull request #591 from matrix-org/ben-feature-fixup

 - [x] switches to latest rust 1.60 as MSRV
 - [x] renames `encryption`-feature to `e2e-encryption` for clarity
 - [x] combines the `*-state-store`/`*-crypto-store` features into a single feature `sled` and `indexeddb` respectivly
 - [x] and combines them with weak `e2e-encryption`-dependencies to activate the features as necessary
 - [x] moves the code back to the sled-store, where it belongs
 - [x] updates the docs accordingly

BREAKING CHANGE
2022-05-04 15:26:20 +02:00
Benjamin Kampmann 0abdebfe8b docs: typo in feature name
Co-authored-by: Damir Jelić <poljar@termina.org.uk>
2022-05-04 15:15:06 +02:00
Benjamin Kampmann 8e2e4e6058 style(xtask): Fixing formatting 2022-05-04 13:54:55 +02:00
Benjamin Kampmann aaee28b34f style: Improved wording
As suggested in the review.

Co-authored-by: Damir Jelić <poljar@termina.org.uk>
2022-05-04 13:48:11 +02:00
Benjamin Kampmann 335a7d03c3 fix: Put all MSRV to 1.60 2022-05-04 13:41:07 +02:00
Benjamin Kampmann f61248cbbd style: Put warnings aside by feature-gating properly 2022-05-04 13:38:08 +02:00
Damir Jelić 83d6e8ea82 refactor(crypto): Simplify the verification object constructors
This patch moves all the important identities that we need for
verification into the already existing IdentitiesBeingVerified struct.

It adds a method to get those identities to the store, and streamlines
our to-device and in-room verification constructors.
2022-05-04 13:36:26 +02:00
Benjamin Kampmann fdcbd59557 fix(SDK): Put timeline behind a feature-flag 2022-05-04 12:55:01 +02:00
Benjamin Kampmann 3a06908755 fix(sled): Put timeline behind feature-flag 2022-05-04 12:42:34 +02:00
Benjamin Kampmann 5f6e0ae033 fix(base): Put further timeline features behind feature-flag 2022-05-04 12:36:53 +02:00
Benjamin Kampmann e1e919dd2c fix(indexeddb): Put timeline feature behind feature-flag 2022-05-04 12:24:21 +02:00
Benjamin Kampmann 98d2b8a0fe fix(base): Put timeline behind exprimental-timeline-feature-flag 2022-05-04 11:54:14 +02:00
Benjamin Kampmann e60d2fde7e fixing xtask wasm-pack cli command 2022-05-04 11:11:01 +02:00
Benjamin Kampmann 5d3351f5cc chore(sledstore): Revert user-id removing code 2022-05-04 10:52:42 +02:00
Jonas Platte b2273ab7a1 chore: Add semicolons after unit-typed expressions 2022-05-03 14:23:29 +02:00
Jonas Platte 17a26bfe68 chore: Use Entry::or_default() where applicable 2022-05-03 14:23:29 +02:00
Jonas Platte d44f2657f4 chore(base): Fix inconsistent order of common function parameters 2022-05-03 14:23:29 +02:00
Jonas Platte 1c3890651d chore(base): Simplify signature of handle_invited_state 2022-05-03 14:23:29 +02:00
Jonas Platte 92f3737be6 chore: Remove unneeded lint silencing 2022-05-03 14:23:29 +02:00
Benjamin Kampmann 3cc5e48aac ci: Fix new no-crypto ci wasm command 2022-05-03 12:05:34 +02:00
Damir Jelić c01cbdd3f2 fix(crypto-ffi): Allow room message requests to be marked as sent 2022-05-03 10:59:16 +02:00
ganfra 84d1af1332 [crypto-ffi] Add RoomMessage in RequestType 2022-05-03 10:49:17 +02:00
Benjamin Kampmann e3016482e1 fix: Simplify UnknownError in SDK 2022-05-03 10:28:28 +02:00
Benjamin Kampmann a58a58f30d Merge remote-tracking branch 'origin/main' into ben-feature-fixup 2022-05-03 10:21:11 +02:00
Benjamin Kampmann 7dd7f5a611 Merge pull request #626 from matrix-org/gnunicorn/issue565
Fixing benchmarking, 

fixes #565
2022-05-03 10:20:15 +02:00
Benjamin Kampmann aad0cbe496 ci(benchmarking): disable benchmark runs other than manually requested 2022-05-03 09:39:35 +02:00
Benjamin Kampmann 68d5097d96 fix(sled): Unmix stripped and regular user_ids 2022-05-03 09:03:13 +02:00
Benjamin Kampmann 06085a0c74 Merge remote-tracking branch 'origin/main' into gnunicorn/issue133 2022-05-03 08:45:24 +02:00
Benjamin Kampmann f416ebfdd8 fix(sled-store): Fix faulty mixing of stripped and regular user_ids 2022-05-03 08:44:52 +02:00
Benjamin Kampmann 4de29b8178 test(state tests): Put stripped_member test into its own DB to ensure separation 2022-05-03 08:22:57 +02:00
Benjamin Kampmann 12894aff99 ci(benchmark): Fixing output format 2022-05-02 17:01:56 +02:00
Benjamin Kampmann f20390036b fix(indexeddb): Ensure internal account info is up to date on regular save_changes 2022-05-02 16:58:21 +02:00
Benjamin Kampmann 9763c13a34 ci(benchmarks): Switch to Mr. B access token 2022-05-02 16:36:44 +02:00
Benjamin Kampmann 54c93e4982 ci(benchmarks): more specific cargo-bench params 2022-05-02 16:30:30 +02:00
Benjamin Kampmann b6d71cbeba fix(benchmarks): keep the temprorary dir until end of tests 2022-05-02 16:29:50 +02:00
Benjamin Kampmann a4ec6cb6d6 fix(sled-crypto): Ensure cryptostore.save_changes for account updates internal account_info 2022-05-02 16:29:02 +02:00
Benjamin Kampmann 1ea377bdbf chore: Merge pull request #625 from matrix-org/ben-ci-fixup
xtask fixup
2022-05-02 15:45:29 +02:00
Benjamin Kampmann 827f8c3e17 ci(benchmarking): Add github token to benchmarking 2022-05-02 14:17:13 +02:00
Benjamin Kampmann 32cd372f49 Merge remote-tracking branch 'origin/main' into ben-feature-fixup 2022-05-02 13:30:42 +02:00
Benjamin Kampmann b592fc5cac Update xtask/src/fixup.rs
Co-authored-by: Jonas Platte <jplatte@element.io>
2022-05-02 12:44:31 +02:00
Benjamin Kampmann d077aa6a90 chore(indexeddb): Merge fixes 2022-05-02 12:07:40 +02:00
Benjamin Kampmann 392d48ba01 Merge remote-tracking branch 'origin/main' into gnunicorn/issue133 2022-05-02 11:51:26 +02:00
Benjamin Kampmann d1aa463b7c Apply suggestions from code review
Co-authored-by: Jonas Platte <jplatte@element.io>
2022-05-02 11:43:37 +02:00
Benjamin Kampmann fb8ddfa07d style: Fixing name 2022-04-29 17:56:50 +02:00
Benjamin Kampmann 2803694cdf ci(benchmarks): Adding Benchmarks to CI 2022-04-29 17:54:53 +02:00
Benjamin Kampmann a7b8cc5810 ci: remove unnecessary dependency 2022-04-29 17:28:51 +02:00
Jonas Platte f8b9ec9626 chore: Remove ruma re-export from matrix-sdk-common
The user-facing re-exports in matrix-sdk-base and matrix-sdk remain.
2022-04-29 17:13:22 +02:00
Jonas Platte c3d9a60067 chore: Remove async_trait from matrix-sdk-common 2022-04-29 17:13:22 +02:00
Benjamin Kampmann a70d05cb63 Merge branch 'main' into ben-ci-fixup 2022-04-29 15:15:46 +02:00
Benjamin Kampmann 5682b3bc09 ci(xtask): Adding fixup to xtask 2022-04-29 15:13:43 +02:00
Benjamin Kampmann 29674213e8 style: Cleanup styles with pre-commit 2022-04-29 14:52:41 +02:00
Benjamin Kampmann 9b6fe94bc8 ci(tooling): Improved Style Checking
- separate Styles from ci.yaml into its own for clarity
- extend pre-commit config with other useful defaults
- move clippy, tests and typos into a push-based pre-commit
2022-04-29 14:50:12 +02:00
Jonas Platte c0c30438ab chore: Upgrade Ruma to 0.6.1 2022-04-29 13:17:51 +02:00
Jonas Platte 814e415374 chore: Use new Ruma helper methods for some events 2022-04-29 13:03:50 +02:00
Jonas Platte dfd193e3b0 chore: Change TOML inline tables to be single-line consistently 2022-04-29 13:03:50 +02:00
Jonas Platte 82164b098a chore: Sort dependencies
Mostly automated (cargo sort --workspace).
2022-04-29 13:03:50 +02:00
Jonas Platte 4b1c77ec5a chore: Use js Date.now() support from Ruma 2022-04-29 13:03:49 +02:00
Benjamin Kampmann d9d143eba7 fix(sled-store): Seperate stripped and non-stripped buckets 2022-04-29 12:42:36 +02:00
Jonas Platte 097cb99ae5 chore: Make target-specific dependency formatting more consistent
* Put target-specific dependencies last
* Put cfg(wasm) before cfg(not(wasm))
* Use long table names only where lines get too long otherwise
2022-04-29 11:30:31 +02:00
Jonas Platte aae8989f99 chore(sdk): Merge local import with file-level imports 2022-04-29 11:09:14 +02:00
Jonas Platte 70174e1fea Upgrade Ruma to 0.6.0 2022-04-29 11:07:17 +02:00
Benjamin Kampmann 301cf3561f chore(indexeddb): Fix merge leftover 2022-04-29 10:41:14 +02:00
Benjamin Kampmann 18864d9722 chore: Merge remote-tracking branch 'origin/main' into gnunicorn/issue133 2022-04-29 10:27:33 +02:00
Benjamin Kampmann 9c6bc066f2 chore(CI): Add Wasm-Pack to CI
Merge pull request #619 from matrix-org/gnunicorn/issue617
2022-04-28 17:50:39 +02:00
Benjamin Kampmann 83b5d8f20e style: cargo fmt 2022-04-28 17:32:54 +02:00
Benjamin Kampmann ebd85ebaa2 feat(indexeddb): Add support for key backup v1 2022-04-28 17:31:09 +02:00
Denis Kasak 1962e7ec1d Merge pull request #621 from matrix-org/dkasak/doc-improvements2
Document `OlmDecryptionInfo` and make it `pub(crate)`.
2022-04-28 14:35:32 +00:00
Denis Kasak 73bd3a0598 fix(crypto): Make OlmDecryptionInfo and decrypt_to_device_event pub(crate). 2022-04-28 16:21:39 +02:00
Denis Kasak 698ab5328f docs(crypto): Document OlmDecryptionInfo and fix some errors. 2022-04-28 16:08:07 +02:00
Benjamin Kampmann 87ae677fc3 fix(ci): fixing it right this time 2022-04-28 13:15:27 +02:00
Benjamin Kampmann 5d3c14f309 fix(ci): fixing the wasm ci command 2022-04-28 13:12:06 +02:00
cutecutecat 33425a43d0 chore: Replace lazy_static with once_cell 2022-04-28 11:10:34 +00:00
Benjamin Kampmann 608eca6166 test(indexeddb): activate indexeddb tests for CI 2022-04-28 12:43:07 +02:00
Benjamin Kampmann a49dfa8aa2 Merge branch 'main' into gnunicorn/issue133 2022-04-28 12:36:36 +02:00
Benjamin Kampmann 3caed26f93 test(base): fix wasm tests 2022-04-28 12:00:19 +02:00
Benjamin Kampmann 7aeb8cf482 style: cargo fmt 2022-04-28 11:24:59 +02:00
Benjamin Kampmann 16ec5fe9ff chore: Merge remote-tracking branch 'origin/main' into gnunicorn/issue617 2022-04-28 11:23:32 +02:00
Benjamin Kampmann aff106f0d6 style: cargo fmt 2022-04-28 11:08:27 +02:00
Benjamin Kampmann 4b575d3d2b style: newline 2022-04-28 11:08:03 +02:00
Benjamin Kampmann 0f2424d140 test(crypto): fix wasm tests 2022-04-28 11:06:35 +02:00
Benjamin Kampmann 9c80774140 feat(common-utils): helper for modified MilliSecondsSinceUnixEpoch 2022-04-28 11:06:35 +02:00
Benjamin Kampmann d46b5ab0b6 tests: add js to get-random on matrix-sdk to allow compilation 2022-04-28 11:06:35 +02:00
Benjamin Kampmann 5b13cf4e92 Apply suggestions from code review
Co-authored-by: Jonas Platte <jplatte@element.io>
2022-04-28 10:25:03 +02:00
Damir Jelić 649aff2c92 fix(crypto-ffi): Rename the error message field for MigrationError
The field is called message which clashes with the field of the same
name in the Kotlin Exception class.
2022-04-27 18:56:30 +02:00
Damir Jelić 5d8c485a51 chore: Bump most of our deps 2022-04-27 17:30:53 +02:00
Damir Jelić d8ff18322e feat(crypto-ffi): Allow unencrypted verification events to be handled 2022-04-27 17:30:41 +02:00
Damir Jelić 4780c560e1 feat(base): Pass unencrypted verification events to the olm machine 2022-04-27 17:30:41 +02:00
Damir Jelić d94f415db4 feat(crypto): Allow unencrypted verification events to be handled 2022-04-27 17:30:41 +02:00
Benjamin Kampmann 4b6ed22476 chore(ci): install wasm-pack 2022-04-27 17:20:14 +02:00
Benjamin Kampmann 868afffc4d formatting 2022-04-27 17:05:50 +02:00
Benjamin Kampmann 6a81ec226e chore: enable wasm-pack tests in ci 2022-04-27 16:58:42 +02:00
Benjamin Kampmann c0fc7c9f7e chore: Adding ci-subcommand to xtask for testing 2022-04-27 16:50:27 +02:00
Benjamin Kampmann 1bf1147d18 fixing style 2022-04-27 16:22:47 +02:00
Benjamin Kampmann 2bdd44ce1d Merge branch 'main' into gnunicorn/issue133 2022-04-27 15:45:39 +02:00
Julian Sparber 910bf531fe feat(sdk): Add method to set whether a room is DM and store all targets
This ensures also that we use, for user verification, only a DM room with
no members other then ourself and the user to be verified.
2022-04-27 12:53:51 +02:00
Benjamin Kampmann 66fcc1e486 forgot two instances in rename 2022-04-27 12:36:19 +02:00
Benjamin Kampmann 628de09938 rename Full -> Original 2022-04-27 12:22:19 +02:00
Benjamin Kampmann 703a95c486 grumbles 2022-04-27 12:21:06 +02:00
Benjamin Kampmann 48cb625f19 fixing lints 2022-04-27 12:06:42 +02:00
Benjamin Kampmann 266d7c6da7 fixing last broken display_name tests 2022-04-27 12:06:15 +02:00
Benjamin Kampmann b5ab076546 tests(matrix-sdk-base): allowing enable debugging logs for tests 2022-04-27 12:02:56 +02:00
Jonas Platte e5c2ba4bd8 fix(sdk): Export RumaApiError 2022-04-26 19:16:36 +02:00
Kévin Commaille d62cb9650f Fix typo 2022-04-26 18:59:51 +02:00
Kévin Commaille dfdaea786b docs: Document RumaApiError variants 2022-04-26 18:49:21 +02:00
Damir Jelić 6e89ecfbf0 fix(indexeddb): Don't derive a StoreCipher twice if we're reusing the db 2022-04-26 18:46:55 +02:00
Damir Jelić 742c1944eb fix(sled): Put the StoreCipher behind the Arc, not the Option 2022-04-26 18:46:55 +02:00
Damir Jelić e1baa25713 fix(sled): Don't derive a StoreCipher twice if we're reusing the db 2022-04-26 18:46:55 +02:00
Kévin Commaille 189ae93e90 fix(sdk): Export RumaApiError 2022-04-26 18:17:04 +02:00
Benjamin Kampmann 4431a2d48a fix(room name): check for proper type 2022-04-26 17:40:04 +02:00
Benjamin Kampmann 3cdee30fc1 fixing docs 2022-04-26 17:33:17 +02:00
Benjamin Kampmann 592a9338eb style, and other fixes 2022-04-26 17:27:18 +02:00
Benjamin Kampmann 55b7fd617c fix(indexeddb-store): implement merge room members 2022-04-26 17:04:46 +02:00
Benjamin Kampmann ca2f598d9e fix(sled-store): implement merge room members 2022-04-26 16:23:22 +02:00
Benjamin Kampmann 8cdfd43863 test(store): additional intergration test for stripped members 2022-04-26 15:38:58 +02:00
Benjamin Kampmann e9e21c1b25 rename computed -> calculated 2022-04-26 15:34:49 +02:00
Benjamin Kampmann 61ea1c9003 Merge remote-tracking branch 'origin/main' into gnunicorn/issue133 2022-04-26 15:24:13 +02:00
Damir Jelić 39ef1d550d chore(crypto): Improve a log line 2022-04-26 14:46:07 +02:00
Damir Jelić a425ddf97f fix(crypto): Don't try to encrypt a room key for our own device 2022-04-26 14:46:07 +02:00
Damir Jelić d38995b3f9 fix(crypto): Add our own device to the store when we create a new account 2022-04-26 14:46:07 +02:00
Damir Jelić 3490a9f726 chore(crypto): Remove a useless compile_error! call 2022-04-26 13:56:45 +02:00
Damir Jelić 610e3ffc5f fix(crypto): Be more restrictive around Megolm session rotation periods 2022-04-26 13:56:45 +02:00
Benjamin Kampmann cfeda54fc6 fix(store): combine stripped and regular membership and allow fetching that 2022-04-26 13:35:06 +02:00
Jonas Platte 2a11df01c7 chore(indexeddb): Remove unneeded matrix-sdk-common dependency 2022-04-26 11:40:54 +02:00
Jonas Platte 08fd85ea09 chore: Upgrade Ruma 2022-04-26 11:40:54 +02:00
Jonas Platte 32d1997dfc feat(crypto): Accept borrowed identifiers in some public functions 2022-04-26 11:40:54 +02:00
Jonas Platte 00249ab96e fix: Fix a typo 2022-04-26 11:40:54 +02:00
Damir Jelić 7710b0b14f Merge branch 'poljar/encrypted-reactions-fix' 2022-04-26 11:22:39 +02:00
Damir Jelić cc6e5b868e chore(sdk): Use the % sigil to record room ids 2022-04-26 09:58:25 +02:00
Damir Jelić 5f83184512 fix(sdk): Don't encrypt reactions 2022-04-26 09:41:50 +02:00
Jonas Platte 16a35081ed feat(sdk): Merge HttpError::{Api, ClientApi} 2022-04-25 19:55:56 +02:00
Jonas Platte ddb6d6af90 chore: Fix typos 2022-04-25 19:42:06 +02:00
Damir Jelić 1f8f7c853b docs(crypto-ffi): Slight docs improvements
Co-authored-by: Denis Kasak <dkasak@termina.org.uk>
2022-04-25 14:22:01 +02:00
Damir Jelić a25a88bd25 refactor(crypto-ffi): Use the anyhow Result type for the migration function 2022-04-25 14:22:01 +02:00
Damir Jelić 94832d1a8b fix(crypto-ffi): Allow the machine to be opened with a passphrase 2022-04-25 14:22:01 +02:00
Damir Jelić 2552c0f393 docs(crypto-ffi): Add docs to the migrate method 2022-04-25 14:22:01 +02:00
Damir Jelić 797fbb2fda feat(crypto-ffi): Add a progress listener to the migrate method 2022-04-25 14:22:01 +02:00
Damir Jelić 35d4749ba7 feat(crypto-ffi): Add support to migrate from a libolm based setup 2022-04-25 14:22:01 +02:00
Damir Jelić c5ddca3bc4 feat(sled): Add a method to save tracked users in a batched way 2022-04-25 14:22:01 +02:00
Damir Jelić a6b7c98002 feat(crypto): Add a public method to import private cross signing keys 2022-04-25 14:22:01 +02:00
Benjamin Kampmann 84b721abb0 Merge pull request #599 from zecakeh/pr-cov
ci: Run code coverage for pull requests
2022-04-25 14:07:27 +02:00
Benjamin Kampmann 7ea6cb3e95 rename Calculated -> Computed 2022-04-25 13:31:45 +02:00
Benjamin Kampmann 15e76b90b1 adding display name integration tests for DM invite 2022-04-25 13:29:59 +02:00
Kévin Commaille 5c41b992b7 ci: Add newline at end of codecov.yaml
Co-authored-by: Benjamin Kampmann <ben.kampmann@gmail.com>
2022-04-25 12:53:42 +02:00
Kévin Commaille 5ce6c07d9c ci: Update codecov github action to v3 2022-04-25 12:44:33 +02:00
Kévin Commaille 8090220963 ci: Add codecov config file
Be tolerant for coverage of new PRs
2022-04-25 12:43:22 +02:00
Kévin Commaille 314a9dec6c ci: Run code coverage for pull requests 2022-04-25 12:08:58 +02:00
Benjamin Kampmann 48fc26a35b tests for broken room name 2022-04-22 17:45:27 +02:00
Benjamin Kampmann b420d7022a typed display name for i18n 2022-04-22 15:35:38 +02:00
Benjamin Kampmann 79e543eceb fix(state-stores): ensure counter consistency 2022-04-21 16:20:24 +02:00
Benjamin Kampmann 375e976289 formatting 2022-04-21 13:02:55 +02:00
Benjamin Kampmann 071d440567 fix(indexeddb-store): always pad counter with u64 padding size to ensure order consistency 2022-04-21 12:56:32 +02:00
Benjamin Kampmann d4053e2c54 fix(sled-store): save index as i64 to ensure portability 2022-04-21 12:53:10 +02:00
Benjamin Kampmann a0ba610e0b fixing wasm example 2022-04-20 16:35:55 +02:00
Benjamin Kampmann c995331f57 fixing typo 2022-04-20 16:22:32 +02:00
Benjamin Kampmann 577b45f8ce activate encryption on base if crypto-store is activated, handle non_exhaustive errors raised 2022-04-20 16:19:55 +02:00
Jonas Platte 0c7e0167c7 Merge pull request #592 from zecakeh/login-sso 2022-04-20 15:45:43 +02:00
Benjamin Kampmann 9761934bf5 fixing features in ci jobs 2022-04-20 15:43:57 +02:00
Kévin Commaille 04d62bbe1e Apply suggestions to docs
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
2022-04-20 15:35:54 +02:00
Benjamin Kampmann 115300fa5e Addressing review comments 2022-04-20 15:27:41 +02:00
Benjamin Kampmann ae8943e050 fixing style 2022-04-20 15:25:56 +02:00
Kévin Commaille 11292b5e5a fix(sdk): Don't convert SSO login URL parse error to IoError. 2022-04-20 15:21:23 +02:00
Kévin Commaille 559fe35e1b fix(sdk): Bind SSO login server to 127.0.0.1 instead of localhost
Avoid name resolution failure in some devices
2022-04-20 15:21:23 +02:00
Kévin Commaille 32b5e5d48b feat(sdk): Improve docs for SSO login server's random ports 2022-04-20 15:21:14 +02:00
Benjamin Kampmann 3de9c54552 more feature related fixups 2022-04-20 14:39:42 +02:00
Benjamin Kampmann b29a50bed5 moving make_store_config features back to sled, fxies #562 2022-04-20 14:36:11 +02:00
Benjamin Kampmann d36220ed7c e2e-encrypted weak feature dependency 2022-04-20 14:26:54 +02:00
Benjamin Kampmann 117fd1612b explain in readme 2022-04-20 14:10:24 +02:00
Benjamin Kampmann 2c506717c8 setting rust-version 2022-04-20 14:08:27 +02:00
Damir Jelić e57721be09 Merge branch 'poljar/session-timestamp-improvements' 2022-04-20 12:11:53 +02:00
Damir Jelić 954bba6fdf fix(crypto): Don't put the session timestamps behind an Arc 2022-04-20 10:49:32 +02:00
Damir Jelić edbf831a0f fix(crypto): Make sure to sort the sessions by timestamp before encrypting
This ensures that we're using the correct Session even if our store
doesn't provide those in the correct order. The set is small anyways, so
this shouldn't have any performance impact.
2022-04-20 10:49:22 +02:00
Damir Jelić c0172c4858 fix(crypto): Fix an error message 2022-04-20 10:49:22 +02:00
Benjamin Kampmann 06f5b67b23 feat(state_store): Store keys and values encrypted, too
Merge pull request #586 from matrix-org/ben-remove-store-key

This removes the store_key and replaces it with the new key cipher for both sled and indexeddb state stores. If they are given a passphrase, we are now encrypted/hashing all keys and values stored in the store, no leaking of metadata in any key or value anymore.
2022-04-19 16:46:11 +02:00
Benjamin Kampmann 07c5f625d4 fixing encryption examples 2022-04-19 16:30:20 +02:00
Benjamin Kampmann 805044ed41 Merge branch 'ben-remove-store-key' of github.com:matrix-org/matrix-rust-sdk into ben-remove-store-key 2022-04-19 16:23:29 +02:00
Benjamin Kampmann 4da7d31770 fixing unnecessary lifetimes 2022-04-19 16:22:25 +02:00
Benjamin Kampmann cdab735ce5 Apply suggestions from code review
Co-authored-by: Jonas Platte <jplatte@element.io>
2022-04-19 16:19:30 +02:00
Benjamin Kampmann e989b9aff7 merge sledstore's EncodeKey and SecureEncodeKey into one 2022-04-19 16:01:18 +02:00
Damir Jelić a8466f5069 refactor(crypto): Use the ruma time types for group sessions as well 2022-04-19 14:07:44 +02:00
Damir Jelić 95a3fe136d refactor(crypto): Use the ruma time types for the Session timestamps 2022-04-19 14:03:31 +02:00
Benjamin Kampmann 88d1aa615c remove unnecessary reference making 2022-04-19 12:42:39 +02:00
Benjamin Kampmann ac8500759c newline 2022-04-19 12:27:11 +02:00
Benjamin Kampmann 07f01eb985 typos 2022-04-19 12:26:27 +02:00
Benjamin Kampmann 953d759238 sort and typo 2022-04-19 12:21:26 +02:00
Benjamin Kampmann 9d09401ede .into instead of ::from 2022-04-19 12:20:41 +02:00
Benjamin Kampmann 872f32a7e0 sorting line order 2022-04-19 12:08:26 +02:00
Benjamin Kampmann 05b3077a7a fixing lints again 2022-04-19 11:00:13 +02:00
Benjamin Kampmann 8fdd8648c7 Merge remote-tracking branch 'origin/main' into ben-remove-store-key 2022-04-19 10:41:40 +02:00
Benjamin Kampmann 4e8383ea4f fixing clippy lints 2022-04-19 09:26:28 +02:00
Benjamin Kampmann 80791860fe fixing style and typos 2022-04-19 09:23:29 +02:00
Benjamin Kampmann 9698a50ad8 fixing timeline for encrypted indexeddb store 2022-04-13 15:52:57 +02:00
Benjamin Kampmann a390c3b40b more explicit naming 2022-04-13 15:52:10 +02:00
Benjamin Kampmann 70a5517c5c make room timeline test more debuggable 2022-04-13 15:23:50 +02:00
Benjamin Kampmann 262bee51b1 also implement room timeline in encrypted fashion on sled store 2022-04-13 15:23:14 +02:00
Benjamin Kampmann 897bb5aed2 new db for every encrypted test 2022-04-12 20:00:11 +02:00
Benjamin Kampmann 24266fe254 fixing ranges 2022-04-12 19:59:55 +02:00
Benjamin Kampmann 5d6c4852b1 fix media content test 2022-04-12 19:37:43 +02:00
Benjamin Kampmann 64e0356756 implementing encrypted keys 2022-04-12 19:17:49 +02:00
Benjamin Kampmann b611aa2503 remove store key feature and references 2022-04-12 16:58:56 +02:00
Benjamin Kampmann 1cdde23bc4 replace storeky with storecipher in wasm 2022-04-12 16:50:58 +02:00
Benjamin Kampmann b3c8f80b6e expose internal functionality for wasm-based storage 2022-04-12 16:50:44 +02:00
Jonas Platte 35f598a095 fix(sdk): Change the default guest_access state to Forbidden 2022-04-12 14:39:30 +02:00
Jonas Platte ad538f3f28 Upgrade Ruma 2022-04-12 14:39:30 +02:00
Jonas Platte 073d9db29f chore(crypto): Remove redundant match arms 2022-04-12 14:39:30 +02:00
Benjamin Kampmann cebe7bee92 adding encrypted tests for indexeddb store 2022-04-12 13:11:59 +02:00
Damir Jelić 7bd0f2c50c chore(sled): Fix a clippy warning 2022-04-12 13:06:17 +02:00
Benjamin Kampmann fb8f123616 fixing remaining key lookup 2022-04-12 12:44:34 +02:00
Damir Jelić 87632e7ead chore(crypto): Update vodozemac 2022-04-12 12:37:56 +02:00
Benjamin Kampmann 88be0ee9c1 fix user id streams 2022-04-12 12:24:11 +02:00
Benjamin Kampmann 000be73e80 making tests more explicit 2022-04-11 23:47:20 +02:00
Benjamin Kampmann 551711261d integration tests for encrypted version 2022-04-11 22:49:09 +02:00
Benjamin Kampmann 918d95a672 first batch of data for testing encrypted sled store 2022-04-11 22:11:14 +02:00
Benjamin Kampmann f79e6b87e2 use result 2022-04-11 20:42:35 +02:00
Benjamin Kampmann 529d1e0117 removing store key from sled store - for values 2022-04-11 13:52:08 +02:00
Jonas Platte 0dafd8cd65 chore: Update all unit test module names to the conventional 'tests' 2022-04-08 12:35:54 +00:00
Jonas Platte 1dbb0226ad feat(sdk): Check server versions after creating the Client 2022-04-08 14:16:55 +02:00
Damir Jelić 05826de639 fix(crypto): Box the RecoveryKey array so moves don't copy the key 2022-04-06 10:02:00 +02:00
Damir Jelić 4e05fe9f4a refactor(crypto): Simplify the Signing struct 2022-04-06 09:24:57 +02:00
Damir Jelić 26172ded49 ci: Test the WASM example in the CI run 2022-04-05 14:57:13 +02:00
Damir Jelić 814d4dcb8b chore(xtask): Check the wasm example when running the wasm tests 2022-04-05 14:47:24 +02:00
Damir Jelić b9f415e81e chore(sdk): Fix some clippy lints in the wasm example 2022-04-05 14:47:01 +02:00
Damir Jelić 124efe6f67 ci(wasm): Emscripten isn't needed anymore 2022-04-05 14:02:07 +02:00
Damir Jelić f2e2976496 fix(sdk): Make the wasm_command_bot example compile and work
This patch does a couple of things:

1. Fix the compilation of the example, Message -> MessageLike
2. Update Webpack and friends for the example
3. Remove futures-timer's Delay method and use equivalent methods from
   Tokio and wasm-timers.

The last point was needed because futures-timer would end up triggering
this error:
    ReferenceError: can't access lexical declaration '__wbg_clearTimeout_d8b36ad8fa330187' before initialization
2022-04-05 14:02:07 +02:00
Benjamin Kampmann 44be0cf12a chore(base): Make fields of RoomInfo and BaseRoomInfo private
Merge pull request #569 from matrix-org/jplatte/room-info-privacy
2022-04-05 11:20:12 +02:00
Benjamin Kampmann 64d9a1f633 docs: Add example to print the room history
Merge pull request #566 from jsparber/add_timeline_example
2022-04-04 17:21:14 +02:00
Jonas Platte 6f9664c9f4 chore(base): Make fields of RoomInfo and BaseRoomInfo private 2022-04-04 16:35:07 +02:00
Julian Sparber f1c1b3d319 example: Require sled-state-store for timeline example 2022-04-04 15:33:04 +02:00
Damir Jelić 6007aa7056 fix(crypto): Add some missing zeroization calls in the key export logic 2022-04-04 13:34:13 +02:00
Kévin Commaille acd8ecbd22 feat(sdk): Retrieve account data from room::Common 2022-04-04 12:15:12 +02:00
Jonas Platte eab68131e7 chore: Split auxiliary tools into separate crates 2022-03-31 14:37:52 +02:00
Julian Sparber 8807a2abaf Add example to print the room history 2022-03-31 14:37:38 +02:00
Jonas Platte e2aab504fb Move sled state inspector into a separate crate 2022-03-31 14:26:32 +02:00
Jonas Platte 9567f8f28f Move the crypto benchmarks into a separate crate
Avoids issues from circular dev-dependency.
2022-03-31 14:26:32 +02:00
Damir Jelić 1e09577a8a chore: Make the Verification and OpenStoreError enums non exhaustive 2022-03-30 13:47:56 +02:00
Damir Jelić 155abb262b chore(crypto-ffi): Add a wildcard pattern to the store opening
This is only useful in our workspace, the workspace enables the
state-store in the matrix-sdk-sled crate, which turns an additional enum
variant on.
2022-03-30 13:47:56 +02:00
Damir Jelić 8782e0068f chore(sdk): Add a wildcard match for the verifcation enum conversion
This is needed because we now have multiple consumers of the
matrix-sdk-crypto crate in the workspace. The different consumers
might enable different feature sets.

Compilation of the workspace might fail if the qrcode feature is enabled
on the `matrix-sdk-crypto` crate but disabled on the `matrix-sdk` crate.

This patch adds a wildcard pattern to the Verification enum so we handle
the case where the matrix-sdk qrcode feature remains disabled.
2022-03-30 13:47:56 +02:00
Damir Jelić 66e4ea979c refactor(crypto-ffi): Use a type alias for the encrypted event type 2022-03-30 13:47:56 +02:00
Damir Jelić a957a02d5d refactor(crypto-ffi): Use the parse methods to parse identifiers 2022-03-30 11:10:46 +02:00
Damir Jelić 8079da7b0a chore(crypto-ffi): Use the the latest matrix-sdk-crypto crate. 2022-03-30 10:44:39 +02:00
Damir Jelić 8793efebc7 chore(crypto): Expose the types module publicly 2022-03-30 10:44:39 +02:00
Damir Jelić f5d2ea0efa fix(sdk): Use a consistent naming scheme for our features 2022-03-30 10:26:38 +02:00
Damir Jelić e720b4d5e3 chore(sdk): Fix a clippy warning for the sso_login feature 2022-03-30 10:26:38 +02:00
Damir Jelić d3f4db258f chore(crypto): Remove some dead code mentioning the sled_cryptostore feature 2022-03-30 10:26:38 +02:00
Damir Jelić 13d1048d7e fix(sled): Allow the crypto-store to be used without the state-store 2022-03-30 10:26:38 +02:00
Jonas Platte d9001409a2 chore(sdk): Remove qrcode from default features
Breaking change: If you need QR code support, you now need to enable the
qrcode feature on the matrix-sdk crate.
2022-03-30 10:03:29 +02:00
Jonas Platte 890c191884 Clean up toml formatting 2022-03-30 10:03:29 +02:00
Jonas Platte 8d3441b51b Deduplicate / clean up EncodeKey trait 2022-03-30 10:03:29 +02:00
Jonas Platte 1912a63f17 chore(indexeddb): Implement SafeEncode for RoomAccountDataEventType 2022-03-30 10:03:29 +02:00
Jonas Platte e4c6040de4 Generalize SafeEncode tuple implementations 2022-03-30 10:03:29 +02:00
Jonas Platte b8c7ab9867 fix(indexeddb): Add missing as_encoded_string call 2022-03-30 10:03:29 +02:00
Jonas Platte d56d50e96f Use field shorthands in tracing macros
Automated using search `\b(\w+) = \?\1` => replace `?$1`.
2022-03-30 10:03:29 +02:00
Jonas Platte f375d8c141 Move ? in tracing macros away from =
To make it obvious that it's more like a modifier to the field value,
rather than a single `=?` operator.
2022-03-30 10:03:29 +02:00
Jonas Platte 7f9e1c8799 Remove unnecessary uses of event content enums 2022-03-30 10:03:29 +02:00
Jonas Platte ed52cfc43c fix(base): Propagate push rules deserialization errors
… from BaseClient::get_push_rules.
2022-03-30 10:03:29 +02:00
Jonas Platte 09893651a4 Remove unnecessary allocations 2022-03-30 10:03:29 +02:00
Benjamin Kampmann 7e48034cc8 Merge pull request #555 from jsparber/fix_timeline
store: Make sure that event position in store is contiguous
2022-03-29 12:26:27 +02:00
Jonas Platte 8815e77576 chore: Upgrade Ruma 2022-03-28 18:21:32 +02:00
Jonas Platte db9b3febd3 Upgrade Ruma 2022-03-28 17:54:06 +02:00
Damir Jelić 36d1ba34a9 chore(crypto): Rename the Other key enum variant into Unknown 2022-03-28 17:05:00 +02:00
Damir Jelić 105961a78d chore(crypto): Change the expect message for device key serialization
Co-authored-by: Benjamin Kampmann <ben.kampmann@gmail.com>
2022-03-28 17:05:00 +02:00
Damir Jelić 23040a1bf7 refactor(crypto): Use vodozemac types for the cross signing and device keys 2022-03-28 17:05:00 +02:00
Julian Sparber 07066e1c1f store: Make sure that event position in store is contiguous
This fixes the breaking gap in the timeline when reading the events from
store.
2022-03-28 15:50:48 +02:00
Damir Jelić 4b58017951 chore(crypto): Add umlauts to a copyright holder
Co-authored-by: Jonas Platte <jplatte@element.io>
2022-03-28 14:24:38 +02:00
Damir Jelić 5db5341974 chore(crypto): Use a specialized CrossSigning type 2022-03-28 13:53:01 +02:00
Damir Jelić 9a3d097331 chore(crypto): Use a specialized DeviceKeys type 2022-03-28 13:53:01 +02:00
Damir Jelić c50b369d72 fix(crypto): Remove some unwraps when creating inbound sessions 2022-03-28 13:48:18 +02:00
Julian Sparber 28893ec388 fix(store): Fix sync message order 2022-03-25 14:47:55 +01:00
Damir Jelić 6968edd704 feat(crypto): Start uploading fallback keys to the server 2022-03-25 13:11:53 +01:00
Damir Jelić f4010b597f feat(crypto): Use a specialized SignedKey type instead of the Ruma type 2022-03-25 13:11:53 +01:00
Damir Jelić 2bacbf1b53 feat(crypto): Add a store error variant for breaking database format changes 2022-03-25 11:15:29 +01:00
Damir Jelić 0ce74b956c fix(sled): Throw an error if we can't upgrade our database 2022-03-25 11:15:29 +01:00
Damir Jelić e2725483e4 refactor(crypto): Make it clear that olm decryption failures are normal 2022-03-25 11:15:29 +01:00
Damir Jelić 03990ab19e test(crypto): Improve the device saving test
The test didn't check if we can actually save/restore multiple devices,
this patch fixes this.
2022-03-25 11:15:29 +01:00
Damir Jelić 8b89023aff feat(indxeddb): Use the new store-cipher to encrypt our values 2022-03-25 11:15:29 +01:00
Damir Jelić 75de41bb2e feat(sled): Use the new store cipher to encrypt our keys and values 2022-03-25 11:15:29 +01:00
Damir Jelić 54e555f295 refactor(crypto): Don't use getrandom directly, we already use the rand crate 2022-03-25 11:15:29 +01:00
Damir Jelić dbb500c4b8 feat(crypto): Switch to vodozemac for the olm/megolm support 2022-03-25 11:15:29 +01:00
Damir Jelić 61ca5c7aab fix(base): Make room invitations for previously-left rooms work 2022-03-24 12:35:08 +01:00
Jonas Platte ae3b4f6640 Add a failing test for room invitations putting a left room back into invited 2022-03-24 12:21:21 +01:00
Jonas Platte 9ff6c1bc16 chore(base): Simplify BaseRoomInfo::handle_state_event 2022-03-23 14:25:14 +01:00
Jonas Platte 68a6655cb4 chore(base): Get rid of confusing double-as_ref 2022-03-23 14:25:14 +01:00
Alexandra ec97c354e2 feat(sdk): Detect invalid .well-known endpoint response 2022-03-23 11:57:13 +01:00
Jonas Platte db079065e4 refactor(sdk): Some cleanup of the HTTP code 2022-03-23 11:29:12 +01:00
Jonas Platte cbebf8c4fe Don't import reqwest::Client
… to avoid confusion with the SDKs Client type.
2022-03-23 11:04:28 +01:00
Jonas Platte 92a532a4ba Inline single-use method HttpClient::send_request 2022-03-23 10:50:15 +01:00
Jonas Platte 4601b43651 Remove unnecessary specialized send-request method from HttpClient 2022-03-23 10:43:14 +01:00
Benjamin Kampmann 9ebabf818d Chore: Add tracing span to request sending 2022-03-21 20:45:22 +01:00
Jonas Platte 68385f0ff7 Add tracing span to request sending 2022-03-18 14:40:26 +01:00
Jonas Platte 3b1400b6f8 Merge pull request #539 from matrix-org/jplatte/cleanup 2022-03-17 14:44:30 +01:00
Jonas Platte 5b5e13fe2c Remove request field from Client::keys_upload tracing span
It results in a lot of log noise for initial syncs.
2022-03-17 14:26:28 +01:00
Jonas Platte 7b8568f5c8 Simplify get_or_upload_filter example 2022-03-17 14:24:50 +01:00
Jonas Platte ea3ca1a8ca Remove unnecessary semicolons after if-let expressions 2022-03-17 14:23:55 +01:00
Jonas Platte baa869552f Implement Default for SyncSettings in terms of SyncSettings::new
… rather than the other way around.
2022-03-17 14:23:11 +01:00
Jonas Platte c9c31fa1c2 Simplify SyncSettings::default() 2022-03-17 14:22:40 +01:00
Jonas Platte 5ff38eff00 Activate tracing-subscriber's env-filter feature
This allows the log level of examples to be controlled using the
RUST_LOG environment variable.
2022-03-17 14:22:12 +01:00
Jonas Platte f9420acdfd Remove unhelpful Client self fields from tracing spans
Client's Debug implementation just returns "Client".
2022-03-17 14:21:41 +01:00
Jonas Platte c83f8f2a45 feat(sdk): Add convenience methods for getting state events of statically-known type 2022-03-16 14:26:18 +01:00
Damir Jelić 4741df627d feat(sdk): Add a method to check if the other side has scanned a qr verification 2022-03-16 14:23:35 +01:00
Julian Sparber 04e5434c9a QrVerification: Use consistent name for re-exported method 2022-03-16 14:06:26 +01:00
Julian Sparber adf463a4be QrVerification: expose whether the QrCode was scanned by the other device 2022-03-16 13:05:15 +01:00
Damir Jelić a455f23520 docs(store-cipher): Make the docs about the way the StoreCipher works clearer
Co-authored-by: Denis Kasak <dkasak@termina.org.uk>
2022-03-16 12:48:16 +01:00
Damir Jelić 3af08059da fix(store-cipher): Use the MacKeySeed type alias in more places
Co-authored-by: Denis Kasak <dkasak@termina.org.uk>
2022-03-16 12:48:16 +01:00
Damir Jelić bf3d2ebea3 chore(store-cipher): Rename the store-key crate and it's main type 2022-03-16 12:48:16 +01:00
Damir Jelić 8ab7bfd5fa fix(store-key): Zeroize the derived MacKeys
Co-authored-by: Denis Kasak <dkasak@termina.org.uk>
2022-03-16 12:48:16 +01:00
Damir Jelić d03eefc49a docs(store-key): Improve the docs a bit
Co-authored-by: Denis Kasak <dkasak@termina.org.uk>
2022-03-16 12:48:16 +01:00
Damir Jelić 5766b65eeb feat(store-key): Add a feature flag to enable WASM support 2022-03-16 12:48:16 +01:00
Damir Jelić 11d27007fc fix(store-key): Add some missing zeroize calls 2022-03-16 12:48:16 +01:00
Damir Jelić 4ed06be10d chore(store-key): Add more crate metadata
Co-authored-by: Benjamin Kampmann <ben.kampmann@gmail.com>
2022-03-16 12:48:16 +01:00
Damir Jelić 6a0bda47ae chore(store-key): Rename the crate
Co-authored-by: Benjamin Kampmann <ben.kampmann@gmail.com>
2022-03-16 12:48:16 +01:00
Damir Jelić 41466eae66 feat(store-key): Add a dedicated store key crate
This crate can be used to add at-rest encryption support for a
matrix-sdk state store or crypto store.
2022-03-16 12:48:16 +01:00
Damir Jelić 440b49ce5c feat(sdk): Add store specific errors to the ClientBuildError
This makes it easier to handle store specific errors while building a
Client as long as the user is using one of our main stores.
2022-03-16 12:29:10 +01:00
Kévin Commaille 7b8c52b043 indexeddb: Move attribute below docs 2022-03-16 10:30:56 +01:00
Kévin Commaille 3a94c2115f sdk: Add store opening errors to ClientBuildError 2022-03-15 14:43:02 +01:00
Kévin Commaille 6785c07793 indexeddb: Make store opening error more specific 2022-03-15 14:43:02 +01:00
Kévin Commaille e23b22857f sled: Make store opening error more specific 2022-03-15 14:42:54 +01:00
Jonas Platte 3bf5388da0 feat(sdk): Fetch supported matrix versions from server in initialization 2022-03-14 15:23:13 +01:00
Jonas Platte 15df8fef95 Fix broken tests 2022-03-14 15:08:54 +01:00
Jonas Platte 8df7e1cc8b Fix hanging tests 2022-03-14 15:08:48 +01:00
Jonas Platte 7b2dfa39cf Remove Client::get_supported_versions
This is now always done as part of constructing the Client, unless the
user actively opted out.
2022-03-14 12:57:58 +01:00
Jonas Platte fdc8f79728 Merge branch 'main' into jplatte/server-versions 2022-03-14 12:56:57 +01:00
Benjamin Kampmann f76bcda64f feat(client): Replacing ClientConfig with a ClientBuilder to configure how the client will be set up
Merge pull request #533 from matrix-org/jplatte/client-builder
2022-03-14 12:43:38 +01:00
Jonas Platte 718fa18e7f Merge branch 'main' into jplatte/client-builder 2022-03-14 11:26:45 +01:00
Damir Jelić b8b61ce214 refactor(sdk): Scope the encryption specific Client methods behind a struct 2022-03-14 10:16:19 +01:00
Jonas Platte a2ad774112 Add ClientBuilder::server_name 2022-03-14 10:02:31 +01:00
Jonas Platte d94ba8c64f Remove Client::for_user_id 2022-03-14 10:02:31 +01:00
Jonas Platte 81d07d886c Rename Client::{new_from_user_id => for_user_id} 2022-03-13 19:56:26 +01:00
Jonas Platte 147e948fe6 Replace ClientConfig with ClientBuilder
This includes a few not-strictly-related changes that made sense to do at the
same time:

* Check for a functioning homeserver via get_supported_versions regardless of
  whether a homeserver URL or user ID was supplied
* Rename use_discovery_response to respect_login_well_known
* Small appservice documentation improvement because those docs had to be
  touched anyways
* Some test refactorings in tests that had to be touched anyways
2022-03-13 19:56:26 +01:00
Kévin Commaille d8c7fbd9dc sdk: Create Encryption struct
Lower the API surface of Client
2022-03-12 13:30:55 +01:00
Jonas Platte bd7fbea155 Fix intra-doc link 2022-03-11 18:04:32 +01:00
Jonas Platte 628e2fb716 Allow configuring assert_identity on the client level only
Completely removing it from RequestConfig is left up to a future refactoring.
2022-03-11 15:31:11 +01:00
Jonas Platte 503f4d73a0 Merge pull request #532 from matrix-org/jplatte/ctors 2022-03-11 13:05:20 +01:00
Jonas Platte 8a927df2b3 Rename PrivateCrossSigningIdentity::{new_with_account => with_account} 2022-03-11 12:48:30 +01:00
Jonas Platte 14ddcfb06e Remove new_ prefix from ToDeviceRequest ctors 2022-03-11 12:48:30 +01:00
Jonas Platte 932ef6270b Remove new_ prefix from OlmMachine ctors 2022-03-11 12:48:30 +01:00
Jonas Platte 1be68f57a5 Merge BaseClient impl blocks 2022-03-11 12:36:08 +01:00
Jonas Platte cfdf4a032e Rename BaseClient::{new_with_store_config => with_store_config} 2022-03-11 12:36:08 +01:00
Jonas Platte f5a7a1bcf0 Rename AppService::{new_with_config => with_config} 2022-03-11 12:36:08 +01:00
Jonas Platte e60b07336d Rename Client::{new_with_config => with_config} 2022-03-11 12:36:08 +01:00
Jonas Platte 48660c482f Use regular builder pattern for ClientConfig::store_config 2022-03-11 12:36:00 +01:00
Jonas Platte 27ee7c32ca Remove new_with_* constructors for StoreConfig
The regular builder pattern works just fine for the stores.
2022-03-11 11:49:01 +01:00
Benjamin Kampmann 88f1552a70 feat(stores): Improve Store initialisation to allow for reusing the same instance
Merge pull request #523 from zecakeh/stores
2022-03-11 11:40:12 +01:00
Kévin Commaille faa5cf54eb indexeddb: Make make_store_config public 2022-03-10 17:42:37 +01:00
Kévin Commaille 2bdc754140 ci: Lint matrix-sdk-crypto with a separate command 2022-03-10 17:29:20 +01:00
Kévin Commaille 597999acba sdk-base: Add constructors with stores for StoreConfig 2022-03-10 17:29:19 +01:00
Kévin Commaille 81605b731d sdk-base: Fix wording on StoreConfig docs 2022-03-10 17:29:19 +01:00
Kévin Commaille d7673257b4 stores: Rename make_config to make_store_config 2022-03-10 17:29:19 +01:00
Kévin Commaille 54c8b4f8bb sdk-base: Remove BaseClientConfig 2022-03-10 17:29:15 +01:00
Kévin Commaille ad31540b10 sdk: Don't enable store encryption by default 2022-03-10 17:28:34 +01:00
Kévin Commaille 8c7bbb0e07 sdk: Update store setup instructions for encryption. 2022-03-10 17:22:36 +01:00
Kévin Commaille 0f60dfcfc5 sdk: Re-export stores and store config 2022-03-10 17:15:18 +01:00
Kévin Commaille 0327b4f8fc indexeddb: Add methods to create a StoreConfig 2022-03-10 17:15:18 +01:00
Kévin Commaille 4b7f05e913 sled: Add a method to create a StoreConfig 2022-03-10 17:15:18 +01:00
Kévin Commaille 0ea12b3b4a base: Separate store config from the client config 2022-03-10 17:15:18 +01:00
Kévin Commaille 28a83da421 sdk: Remove default store constructors 2022-03-10 17:15:14 +01:00
Kévin Commaille 4d41f94199 sled: Add helper to open stores for encryption 2022-03-10 17:14:01 +01:00
Kévin Commaille 692f95da79 sled: Add method to create CryptoStore from StateStore
Allow to use the same database for both stores
2022-03-10 17:14:00 +01:00
Jonas Platte 872c35efd2 Fix a typo 2022-03-10 16:52:01 +01:00
Jonas Platte 65e7688a3f Don't require discovery to be mocked in tests 2022-03-10 16:05:51 +01:00
Jonas Platte b1f2adf9c0 Ensure random request with Request: Send gets a Send future as well 2022-03-10 15:01:10 +01:00
Jonas Platte 81cea84a37 Fetch supported matrix versions from server in initialization 2022-03-10 15:00:40 +01:00
Jonas Platte 5f8d3dec82 Merge pull request #529 from matrix-org/jplatte/event-type
Use fine-grained *EventType types
2022-03-10 14:49:31 +01:00
poljar e5359826e1 Merge pull request #528 from matrix-org/backup-fix
Fix the room key backup support in the crypto crate
2022-03-10 14:10:18 +01:00
Jonas Platte 1dec224210 Use fine-grained *EventType types 2022-03-10 13:54:00 +01:00
Damir Jelić 691ea2d138 ci(crypto): Test the crypto crate features when we run the CI 2022-03-10 13:52:31 +01:00
Damir Jelić 4af4faacef feat(xtask): Add a task to check the crypto crate features 2022-03-10 13:52:31 +01:00
Damir Jelić 54a253c0bf fix(crypto): Make our backup feature compile again 2022-03-10 13:50:29 +01:00
Jonas Platte 89ff804333 Remove extraneous newline 2022-03-10 13:49:40 +01:00
Jonas Platte 4d16370dba Merge pull request #527 from matrix-org/jplatte/wasm-ci 2022-03-10 13:49:16 +01:00
Jonas Platte 30b3bd1c3d Delete complicated and partially broken wasm tests 2022-03-10 13:18:59 +01:00
Jonas Platte ff15ccaf28 Merge pull request #525 from matrix-org/jplatte/refactor 2022-03-10 12:56:05 +01:00
Jonas Platte 6af9285874 Don't use Raw::from_json where it's not needed 2022-03-10 11:59:31 +01:00
Jonas Platte 9154e93089 Allow other tests to continue when indexeddb test fails 2022-03-10 11:41:01 +01:00
Jonas Platte ea2c9a2986 ci: Use clippy instead of check for wasm checks 2022-03-10 11:28:55 +01:00
Jonas Platte c01475701d Move some wasm CI logic into xtask 2022-03-10 11:02:16 +01:00
Jonas Platte 0721c7ddb2 Add missing ci subcommand description 2022-03-10 10:30:56 +01:00
Jonas Platte 36e4836c06 Merge pull request #522 from matrix-org/jplatte/send-req-refactor 2022-03-10 10:25:50 +01:00
Jonas Platte b777617515 Replace matches! with == 2022-03-10 10:12:53 +01:00
Jonas Platte 8a60154882 Use only #[warn], not #[deny] for lints
CI passes `-D warnings` to clippy, so there it will be an error either way.
For local development it is nice not to block compilation of dependent
crates on lints though.
2022-03-09 18:13:04 +01:00
Jonas Platte d2e70c16b4 Deduplicate lint configuration 2022-03-09 18:09:02 +01:00
Jonas Platte e6d20265bf Allow rustfmt to format the encryption module again 2022-03-09 18:01:48 +01:00
Jonas Platte 5602deb226 Move encryption module docs into a separate markdown file 2022-03-09 18:00:57 +01:00
Jonas Platte e4289405f5 Stop importing Result as StdResult
The SDK's Result aliases can optionally take the error parameter, so
there is no need to disambiguate this way.
2022-03-09 17:56:26 +01:00
Jonas Platte 76973fdc30 Improve consistency across sending requests with/out identity assertion 2022-03-09 16:48:28 +01:00
Jonas Platte d5d6b80e08 Inline single-callsite request serialization functions 2022-03-09 15:13:06 +01:00
Jonas Platte 1ed2b8841d Simplify HTTP request serialization logic
… the removed AuthenticationRequired branch was not necessary, Ruma's
`try_into_http_request` will take care of reporting the error.
2022-03-09 15:13:06 +01:00
Jonas Platte a33898847b Reduce duration of holding session lock
… by cloning the access token out.
2022-03-09 15:13:06 +01:00
Jonas Platte bc1eb9a792 Merge pull request #521 from matrix-org/jplatte/appservice-refactor 2022-03-09 13:15:59 +01:00
Jonas Platte 3b3fede756 Merge pull request #520 from matrix-org/jplatte/clippy 2022-03-09 12:55:27 +01:00
Jonas Platte 9f72eb9490 Enable more default-off clippy lints 2022-03-09 12:41:57 +01:00
Jonas Platte 2c181bca4f Consistently use .to_owned() instead of .to_string() for &str => String 2022-03-09 12:41:57 +01:00
Jonas Platte b67c51c267 Remove unnecessary double reference 2022-03-09 12:41:57 +01:00
Jonas Platte 7fee5b59e8 crypto: Use Box<UserId> instead of String in SignatureError
… to make the field's meaning more obvious.
2022-03-09 12:41:56 +01:00
Jonas Platte 5d6f66be54 appservice: Make warp a regular dependency
It was optional but always required to be activated.
2022-03-09 10:35:39 +01:00
Jonas Platte 5075c2730c Move appservice CI logic into xtask 2022-03-09 10:35:11 +01:00
Jonas Platte 1d5ba87b72 ci: Simplify test command by using -p instead of --manifest-path 2022-03-09 10:35:11 +01:00
Damir Jelić 4fa44f90bb Merge branch 'appservice/fix-user-room-query' 2022-03-09 09:08:04 +01:00
Johannes Becker a86da98cc2 fix(appservice): urldecode ids for user/room queries 2022-03-07 16:51:06 +01:00
Damir Jelić 6dff06579c fix(sdk): Ensure that our login_with_sso() Client method is Send 2022-03-07 14:43:42 +01:00
Julian Sparber 38cbf24e8e Add back homeserver logging for sso login
We can't use `.await` inside `info!()` because of
https://github.com/rust-lang/rust/issues/93274
2022-03-07 14:12:00 +01:00
Julian Sparber 642c4f5cfc Ensure Client::login_with_sso() to be send
This removes the `info!()` log because of
https://github.com/rust-lang/rust/issues/93274
2022-03-07 13:11:52 +01:00
Damir Jelić 89e4d47ee1 chore: Bump the dashmap version across our crates 2022-03-07 09:58:00 +01:00
Jonas Platte 896d451c47 Merge pull request #515 from matrix-org/jplatte/ci 2022-03-04 12:10:47 +01:00
Jonas Platte abe0bf0a29 Enable some useful non-default rustc lints 2022-03-04 11:35:24 +01:00
Jonas Platte 804c8e6c43 ci: Add test and test-features xtask commands 2022-03-04 10:59:17 +01:00
Jonas Platte b64d855b25 ci: Fix inconsistent formatting 2022-03-04 10:59:17 +01:00
Jonas Platte beb4ecb581 ci: Remove mentions of non-existant matrix variables 2022-03-04 10:59:17 +01:00
Jonas Platte ed7667dc8d ci: Remove unnecessary ${{ }} 2022-03-04 10:59:17 +01:00
Jonas Platte e136199bfd ci: Don't run check / build before test
It is redundant.
2022-03-04 10:59:17 +01:00
Damir Jelić 95665c8bc0 Merge branch 'poljar/matrix-crypto-ffi' 2022-03-04 10:27:12 +01:00
Damir Jelić 6bb8fd7853 feat: Import the Uniffi based matrix-sdk-crypto bindings 2022-03-04 09:45:50 +01:00
Benjamin Kampmann b3038545f5 feat(stores): Splitting Sled and Indexeddb Store into separate crates
More details in pull request #498 .
2022-03-03 16:32:31 +01:00
Benjamin Kampmann 44fe3a62a1 remove unneeded helper function 2022-03-03 15:38:22 +01:00
Benjamin Kampmann ba1b3e0c7c fix the indexeddb tests, that clippy tried to fix 2022-03-03 15:27:21 +01:00
Benjamin Kampmann 6435ea655b fix testing function wrongly exposed 2022-03-03 13:47:25 +01:00
Benjamin Kampmann 193a5ed3c9 fixing if syntax 2022-03-03 13:07:09 +01:00
Benjamin Kampmann 4e6b80d7df fix docs 2022-03-03 13:05:32 +01:00
Benjamin Kampmann e7fb512ae6 adding another encryption wasm tests 2022-03-03 12:59:23 +01:00
Benjamin Kampmann ab57fb329f Addressing review remark 2022-03-03 12:57:15 +01:00
Benjamin Kampmann fd6f4385d4 Merge remote-tracking branch 'origin/main' into ben-splitting-out-store-impls 2022-03-03 12:57:00 +01:00
Jonas Platte e03ee913f8 Merge pull request #513 from matrix-org/jplatte/xtask 2022-03-03 12:10:02 +01:00
Benjamin Kampmann 8aed72a085 Update crates/matrix-sdk-crypto/src/olm/account.rs
Co-authored-by: poljar <poljar@termina.org.uk>
2022-03-03 11:35:02 +01:00
Jonas Platte 2182ebdd16 ci: Fix toolchain installation job name inconsistencies 2022-03-03 11:10:30 +01:00
Jonas Platte e575c27601 ci: Use uppercase for docs workflow / job name 2022-03-03 11:10:29 +01:00
Jonas Platte 439081e1db ci: Move wasm and appservice into separate workflows
… to reduce the size of `ci.yml` and to allow more fine-grained retries.
2022-03-03 11:10:29 +01:00
Jonas Platte 1968ae60aa ci: Fix inconsistencies in workflow yml formatting 2022-03-03 11:10:29 +01:00
Jonas Platte b7a4ca4cff Create an xtask crate for workspace task automation
Initially covering:

* Building docs
* Nightly CI jobs
2022-03-03 11:10:28 +01:00
Jonas Platte b276087969 ci: Fail if rustdoc raises warnings 2022-03-03 11:10:13 +01:00
Jonas Platte 6e091dd5b8 ci: Use Swatinem/rust-cache@v1 instead of actions/cache@v2
Simplifies the cache configuration and could also improve build times by
disabling incremental compilation and potentially caching fewer things
or using a better cache key.
2022-03-03 11:04:07 +01:00
Jonas Platte ea5478c61c Merge pull request #510 from matrix-org/jplatte/up-ruma 2022-03-03 09:29:26 +01:00
Jonas Platte 1f2fd380b2 Upgrade Ruma to 0.5.0 2022-03-03 08:59:44 +01:00
Jonas Platte 012954e7f4 ci: Remove --all flag from cargo fmt arguments
It is only relevant for non-workspace path dependencies.
2022-03-02 14:34:22 +01:00
Jonas Platte bc0c8d529e Simplify Cargo workspace configuration 2022-03-02 14:34:22 +01:00
Jonas Platte ba3ccc7d3d Remove explicit 'static lifetimes from constants 2022-03-02 14:34:22 +01:00
Jonas Platte b3f6d1cf63 Fix inconsistent indentation 2022-03-02 14:32:37 +01:00
Jonas Platte af0375ca99 Remove unnecessary serialize / deserialize roundtrips 2022-03-02 14:26:49 +01:00
Jonas Platte a1a0ae62ba base: Use Option::get_or_insert_with to get rid of an unwrap() call 2022-03-02 14:26:48 +01:00
Damir Jelić dec4772740 Merge branch 'gnunicorn-limited-ci-runs' 2022-03-02 14:21:54 +01:00
Benjamin Kampmann 85dd7a03e2 fix(MemoryStore): undeadlock timeline saving
Merge pull request #509 from matrix-org/gnunicorn/issue508
2022-03-02 13:44:47 +01:00
Benjamin Kampmann cf674b6a46 Update crates/matrix-sdk-base/src/store/memory_store.rs 2022-03-02 13:14:38 +01:00
Benjamin Kampmann 102f960d25 chore(ci): limit CI to pull-requests & push main
Running CI on every push means running it twice for any PR as well as commit on branches that aren't PRs. This limits the CI run to pull-requests against main and pushes to main directly, removing unnecessary workload for the CI and making PRs CI faster.
2022-03-02 13:01:18 +01:00
Benjamin Kampmann 7e2e43c51c Addressing review
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
2022-03-02 12:34:04 +01:00
Benjamin Kampmann 161d79eaa1 fixing typo 2022-03-02 12:22:47 +01:00
Benjamin Kampmann eacffb5126 creating better tests, ensure sled and memory store act consistently 2022-03-02 12:13:07 +01:00
Benjamin Kampmann 40fa17f5b7 fixing timeline test 2022-03-02 08:36:10 +01:00
Benjamin Kampmann 9eee50da66 fixing clippy warnings 2022-03-01 15:32:23 +01:00
Benjamin Kampmann 2b9bb422cf fix(MemoryStore): undeadlock timeline saving 2022-03-01 14:39:27 +01:00
Benjamin Kampmann ca18fca20b make Sled store benchmarks use SledStore again 2022-03-01 11:52:52 +01:00
Benjamin Kampmann 33be17d5d0 review requests 2022-03-01 11:52:38 +01:00
Benjamin Kampmann c2bb1b9ad1 remove unneded braces in ci 2022-03-01 11:20:04 +01:00
Damir Jelić 70490277eb fix(sdk): Use a short request retry for login/register/get_version methods 2022-02-28 15:26:30 +01:00
Damir Jelić 48fff04ffd Merge branch 'enable_ruma_unstable_pre_spec' 2022-02-28 14:20:52 +01:00
Manuel Schmidbauer 6bf7b212cf Changed register to really use short_retry() 2022-02-26 15:19:38 +01:00
Manuel Schmidbauer 01e080842a Implemented short_retry for intial methods
Implemented RequestConfig::short_retry()
Changed few client methods to use it
Adjusted and added tests for it
2022-02-26 15:13:04 +01:00
Benjamin Kampmann 25e98db5aa missing .to_string 2022-02-25 17:24:50 +01:00
Benjamin Kampmann fce78ea84e fixing style 2022-02-25 17:16:19 +01:00
Benjamin Kampmann e414c88347 fixing integration test example 2022-02-25 17:14:45 +01:00
Benjamin Kampmann 56b3b2cec6 minor fix in ci 2022-02-25 16:11:32 +01:00
Benjamin Kampmann 13c39dbeab fixing crypto bench 2022-02-25 15:53:36 +01:00
Benjamin Kampmann 5e05411036 fixing typos 2022-02-25 15:40:35 +01:00
Benjamin Kampmann a6514b0cff indexeddb formatting 2022-02-25 15:32:59 +01:00
Benjamin Kampmann 2e9ca5642a more clippy for indexeddb 2022-02-25 15:31:39 +01:00
Benjamin Kampmann 06c9b1abe3 fixing proepr cargo build call 2022-02-25 15:23:04 +01:00
Benjamin Kampmann c97f7e9ed0 clippy 2022-02-25 15:19:57 +01:00
Benjamin Kampmann e1f898e6a5 fixing clippy and docs for base and crypto 2022-02-25 13:05:48 +01:00
Benjamin Kampmann 75953d6022 fixing machine doc builds 2022-02-24 17:29:08 +01:00
Benjamin Kampmann 6c90af1bd7 fixing indexeddb test 2022-02-24 17:16:10 +01:00
Benjamin Kampmann 8706ab68f8 fixing formatting 2022-02-24 16:57:39 +01:00
Benjamin Kampmann 9386e9df51 fixing name path 2022-02-24 16:56:14 +01:00
Benjamin Kampmann 418fac8574 fixing missing import for tests 2022-02-24 16:56:06 +01:00
Benjamin Kampmann 4c1e3ac03a fix missing import 2022-02-24 16:50:57 +01:00
Benjamin Kampmann 4d6d13b9c8 fixing some clippies and wrong package naming 2022-02-24 15:40:24 +01:00
Benjamin Kampmann cccad6104c fixing formatting 2022-02-24 15:18:16 +01:00
Benjamin Kampmann 259ba3b794 refactor CI tests 2022-02-24 15:14:54 +01:00
Benjamin Kampmann 9c5cb08ac0 fixing crypto testing problems 2022-02-24 15:14:42 +01:00
Benjamin Kampmann d7f30167a0 moving safe encode, making regular build work again 2022-02-24 13:02:35 +01:00
Benjamin Kampmann e20bdfa2b5 cleaning up more cryptocrate 2022-02-23 21:33:31 +01:00
Benjamin Kampmann 12cf187e51 indexeddb store and passphrase opening 2022-02-23 21:07:39 +01:00
Benjamin Kampmann ed0974eba3 re-integrate sled and indexeddb stores into base 2022-02-23 19:38:35 +01:00
Benjamin Kampmann 692f9d893a chore(CI): also skip docs making on draft PRs 2022-02-23 16:07:16 +01:00
Benjamin Kampmann 21887877da chore(CI): limit CI runs to non-draft PRs and manual dispatching 2022-02-23 16:04:05 +01:00
Julian Sparber 0dd623970b Enable 'unstable-pre-spec' ruma feature 2022-02-23 15:52:19 +01:00
Benjamin Kampmann 73227623e6 one more fmt 2022-02-23 15:46:44 +01:00
Benjamin Kampmann eeea757719 clippy and formatting 2022-02-23 15:44:36 +01:00
Benjamin Kampmann f6a3c765e9 Merge remote-tracking branch 'origin/main' into ben-splitting-out-store-impls 2022-02-23 15:33:38 +01:00
Benjamin Kampmann 8414718371 feat(StateStore): Adding forward and backwards streams for room timelines
Merge pull request #486 from jsparber/timeline_stream
2022-02-23 14:38:14 +01:00
Benjamin Kampmann 78af96dab3 Clippy and Cargo fmt 2022-02-23 12:50:57 +01:00
Benjamin Kampmann 2598001c8f room version simplification 2022-02-23 12:40:37 +01:00
Benjamin Kampmann c22b4fcfb2 minor refactor for simplicity 2022-02-23 12:37:10 +01:00
Damir Jelić 2b20055eb5 Merge branch 'test-refactor' 2022-02-23 10:30:23 +01:00
Damir Jelić e846fedc3f feat(sdk): Support logging in using SSO with an identity provider 2022-02-23 10:27:07 +01:00
Julian Sparber 980076fd73 Merge remote-tracking branch 'origin/main' into timeline_stream 2022-02-22 17:30:51 +01:00
Julian Sparber 3378d18ca8 store: Add comment why we can ignore unexpected TimelineSlices 2022-02-22 16:49:42 +01:00
Julian Sparber 70e826ff25 Fix style issue 2022-02-22 15:48:56 +01:00
Julian Sparber 890a8675c9 store: Use BoxStream type without explicit lifetime 2022-02-22 15:43:26 +01:00
Julian Sparber 7627c142c4 Add method to optain timeline stream in one direction 2022-02-22 15:42:39 +01:00
Julian Sparber 84c46affa3 Fix example for Room::Common::timeline() 2022-02-22 12:51:44 +01:00
Benjamin Kampmann 5b1746e451 Merge pull request #503 from ShadowJonathan/labs-folder
Add `labs/` folder
2022-02-22 12:01:47 +01:00
Julian Sparber d7592cce29 Merge remote-tracking branch 'origin/main' into timeline_stream 2022-02-22 11:47:17 +01:00
Julian Sparber 088086715f store: Save timeline to IndexedDbStore 2022-02-22 11:43:12 +01:00
Jonathan de Jong 7c9d139031 Apply suggestions from code review
Co-authored-by: Benjamin Kampmann <ben.kampmann@gmail.com>
2022-02-21 22:08:41 +01:00
Jonathan de Jong 28ac6f9f52 add labs folder 2022-02-21 21:37:56 +01:00
Jonas Platte b39a72ceac matrix-sdk-test: Stop relying on event enum Serialize impls
In the latest version of Ruma, the event enums no longer implement
`Serialize` because it was somewhat of a footgun when custom /
unrecognized events were involved.
2022-02-21 14:50:41 +01:00
Benjamin Kampmann 6aeb382706 move state inspector for sled store into corresponding crate 2022-02-21 12:08:45 +01:00
Benjamin Kampmann 87cd9a3afc clean up base 2022-02-18 20:41:42 +01:00
Benjamin Kampmann 95384f0f33 make encryption in new crates optional 2022-02-18 18:50:35 +01:00
Benjamin Kampmann 00ea5d9cad moving sled cryptostore, too 2022-02-18 18:46:59 +01:00
Benjamin Kampmann 1563ecdf1a Merge pull request #499 from matrix-org/ben-docs-for-custom-http-client
Minor improvements on ClientConfig
2022-02-17 20:37:47 +01:00
Benjamin Kampmann 7ab8872dd5 fix(Version): removing (crate only) VERSION const 2022-02-17 19:25:09 +01:00
Benjamin Kampmann 5d812d4aa7 fixing style 2022-02-17 19:09:10 +01:00
Benjamin Kampmann 0ca6ec1377 moving sled state store into separate crate 2022-02-17 19:02:17 +01:00
Benjamin Kampmann 1d0d32858b fix(ClientConfig): Do not expose crate version in user agent anymore 2022-02-17 18:53:32 +01:00
Julian Sparber 8e80e02a78 Add test for matrix_sdk::room::Common::timeline()
The test is only run when the `sled_state_store` feature is enabled.
This also changes the test_json::MORE_SYNC and test_json::MORE_SYNC_2 to
not responsed with a limited timeline.
2022-02-17 18:32:44 +01:00
Julian Sparber 9e7bee89c8 Add test for timeline cache 2022-02-17 18:32:44 +01:00
Julian Sparber fb3edeb206 store: Save timeline to MemoryStore 2022-02-17 18:32:36 +01:00
Julian Sparber 516aa26589 store: Save timeline to SledStore
This writes slices from StateChanges::timeline to the SledStore.
The cache is removed when ever a limited sync response is received or
when an event already known to the store is received.

Stored events are redacted when a redaction event is received.
2022-02-17 16:15:17 +01:00
Julian Sparber 7d19e9aa34 test: Add mocked responses need for timeline storage 2022-02-17 16:15:17 +01:00
Julian Sparber 64c49cd137 Add stream to obtain the timeline of a room 2022-02-17 16:15:17 +01:00
Julian Sparber c5950ac929 common: add TimelineSlice
The TimelineSlice is a slice of the timeline of a room and contains the
start and end of the slice.
2022-02-17 16:13:04 +01:00
Benjamin Kampmann ea92bc676c Merge remote-tracking branch 'origin/main' into ben-splitting-out-store-impls 2022-02-17 16:03:07 +01:00
Benjamin Kampmann 839136118f fixing style 2022-02-17 13:06:44 +01:00
Benjamin Kampmann 6751413673 Merge remote-tracking branch 'origin/main' into ben-docs-for-custom-http-client 2022-02-17 13:01:57 +01:00
Benjamin Kampmann 094fb176b6 chore: remove unused lifetime found by clippy 2022-02-17 12:13:56 +01:00
Benjamin Kampmann 75f45c8df6 chore: Update clippy, removes deprecations to make clippy happy 2022-02-17 12:12:19 +01:00
Benjamin Kampmann e9e0ba216b chore: fixing formatting 2022-02-17 11:49:49 +01:00
Benjamin Kampmann bbc92d912f docs(ClientConfig): Add example for customn reqwest::ClientBuilder 2022-02-17 11:43:20 +01:00
Benjamin Kampmann 81e90c5699 chore(ClientConfig): Simplify user agent storing 2022-02-17 11:40:59 +01:00
Benjamin Kampmann 54303a03bf feat(sdk): Move Account related functions from Client into a new separated Account struct
Create Account struct
2022-02-16 19:51:16 +01:00
Benjamin Kampmann 78ea330d3a Merge remote-tracking branch 'origin/main' into pr/zecakeh/487 2022-02-16 18:30:24 +01:00
Benjamin Kampmann 93c46280ab feat(sdk): Add method to get homeserver capabilities
Merge pull request #495 from zecakeh/capabilities
2022-02-16 18:27:04 +01:00
JCWasmx86 c119d71d8b Added support for logging in with specific SSO-Provider 2022-02-16 16:46:08 +01:00
Pass Automated Testing Suite 1e0a240701 feat(sdk): Support to autogenerate thumbnails for image attachments 2022-02-16 16:04:46 +01:00
Kévin Commaille 2f7d271c16 fix(sdk): Add license to attachment.rs 2022-02-15 19:15:06 +01:00
Kévin Commaille 9e545c34ba fix(sdk): Fix clippy warning 2022-02-15 19:00:39 +01:00
Kévin Commaille 69b0b04e70 fix(sdk): Add ruma feature for blurhash support 2022-02-15 18:43:56 +01:00
Kévin Commaille de8aa7b4f7 fix(sdk): Simplify code in room::Joined::send_attachment 2022-02-15 18:15:59 +01:00
Kévin Commaille ebd913f50f fix(sdk): Fix dead links in AttachmentConfig docs 2022-02-15 18:15:59 +01:00
Kévin Commaille 409afc6684 feat(sdk): Create AttachmentConfig struct 2022-02-15 18:15:59 +01:00
Kévin Commaille c2c9d5ecc0 fix(sdk): Enable image_proc with image_rayon 2022-02-15 18:15:59 +01:00
Kévin Commaille e926d7e928 chore: Update image dependency 2022-02-15 18:15:59 +01:00
Kévin Commaille 78489391d2 feat(sdk): Add method to send attachments with generated thumbnails 2022-02-15 18:15:59 +01:00
Kévin Commaille 5dc7dfd4c8 feat(sdk): Add method to generate thumbnails from images 2022-02-15 18:15:58 +01:00
Kévin Commaille 0436780292 feat(sdk): Allow to add info and thumbnail to attachments 2022-02-15 18:15:58 +01:00
Kévin Commaille 6389749931 fix(sdk): Return whole responses in Account 2022-02-15 18:15:05 +01:00
Kévin Commaille abed1e2986 fix(sdk): Fix Account docs
Add a license and fix the dead links.
2022-02-15 18:15:05 +01:00
Kévin Commaille 9449b3ef23 feat(sdk): Add more methods to Account
- get_profile
- change_password
- deactivate
- get_3pids
- request_3pid_email_token
- request_3pid_msisdn_token
- add_3pid
- delete_3pid
2022-02-15 18:15:05 +01:00
Kévin Commaille 30d3cafa0c feat(sdk): Make upload_avatar return an MXC URI 2022-02-15 18:15:05 +01:00
Kévin Commaille 467005b603 feat(sdk): Move account-related methods to Account struct
Methods moved from Client to Account:
- display_name renamed to get_display_name
- set_display_name
- avatar_url renamed to get_avatar_url
- set_avatar_url
- avatar renamed to get_avatar
- upload_avatar
2022-02-15 18:15:05 +01:00
Kévin Commaille c67d5afaf4 feat(sdk): Add method to get homeserver capabilities 2022-02-15 17:42:12 +01:00
Benjamin Kampmann 393cfb1851 move indexeddb cryptostore into new crate 2022-02-15 15:09:31 +01:00
Damir Jelić a4ccbf0386 Merge branch 'up-ruma' 2022-02-15 14:46:18 +01:00
Damir Jelić f220f2e743 fix(crypto): Remove an unused lifetime 2022-02-15 12:32:53 +01:00
Benjamin Kampmann 5cae4e08af making tests pass again 2022-02-14 17:38:58 +01:00
Benjamin Kampmann e928d02c6f Move indexeddb out into a separate crate 2022-02-14 17:00:55 +01:00
Benjamin Kampmann 95e06ec732 Merge pull request #492 from zecakeh/fix-docs
fix(doc): Build nightly docs with correct features
2022-02-14 12:03:21 +01:00
Kévin Commaille 0570cd9439 fix(doc): Build nightly docs with correct features 2022-02-13 10:22:05 +01:00
Jonas Platte c3d9c73d00 Make identifier parsing easier to read
… by using `Id::parse` instead of `Box::<Id>::try_from`.
2022-02-12 04:20:37 +01:00
Jonas Platte a7dcd26588 Remove unused variable from test 2022-02-12 04:15:50 +01:00
Jonas Platte 735d9e5894 Use user_id! macro in more tests 2022-02-12 04:15:48 +01:00
Jonas Platte 8e41bccf8b Upgrade Ruma 2022-02-11 20:45:22 +01:00
Daniel García Moreno 4b5aae1123 Do not fail when no session if force_auth
It looks like the force_auth is working correctly when restoring the
session, but it's not working with the call to client.login, so it
cannot be used.

The access_token is not available in the login query, so if the option
force_auth is set, this call will fail always. This patch just ignores
the force_auth if there's no session, so any query will work when
force_auth is true.

Fix https://github.com/matrix-org/matrix-rust-sdk/issues/488
2022-02-11 15:22:39 +01:00
Benjamin Kampmann 8538bdcce2 fix[state store]: Persist stripped rooms in the right bucket
fixes #467 as well as persistence problems with the indexeddb store
2022-02-07 11:53:31 +01:00
Benjamin Kampmann 7aa99448c3 fix style 2022-02-04 18:02:00 +01:00
Benjamin Kampmann 29c851f463 fixing indexeddb store 2022-02-04 18:01:37 +01:00
Benjamin Kampmann d20abe05ed lookup sync-token in proper bucket 2022-02-04 17:47:01 +01:00
Benjamin Kampmann 560ef86747 fixing style 2022-02-04 14:20:51 +01:00
Benjamin Kampmann e68c75451e fixing failing test and naming convention 2022-02-04 14:18:26 +01:00
Benjamin Kampmann 355bb0a091 fixing style 2022-02-04 12:21:31 +01:00
Benjamin Kampmann 2a8c6dabaf Re-add population test 2022-02-04 12:20:10 +01:00
Benjamin Kampmann 772a585b80 stick to naming convention, clarify name 2022-02-04 12:10:53 +01:00
Benjamin Kampmann 51bf07fc34 fixing #467 2022-02-04 12:10:22 +01:00
Erik Johnston 59d21d9683 Replace uses of Vec::drain(..) with into_iter
`drain` is designed to be used when you want to reuse the `Vec` or only
move out a subset range. Using `.into_iter()` is more efficient and
idiomatic, and can be dropped entirely when used in `for` loops.
2022-02-03 14:43:14 +00:00
Benjamin Kampmann 1286357bcf Merge pull request #414 from gnunicorn/ben-wasm-store
IndexedDB support for wasm/browser environments
2022-02-03 09:14:54 +01:00
Benjamin Kampmann fa60881e2d disable broken test 2022-02-02 20:34:52 +01:00
Benjamin Kampmann 990b897e94 switch tokio:test to async_test 2022-02-02 15:10:24 +01:00
Benjamin Kampmann 64709f1d6b fixing style 2022-02-02 14:54:29 +01:00
Benjamin Kampmann b8d93d0179 implementing room removal for indexeddb 2022-02-02 14:53:21 +01:00
Benjamin Kampmann 666bec48bc fixing indexeddb types merge 2022-02-02 14:25:34 +01:00
Benjamin Kampmann 7e008d00e4 fixing linux tests 2022-02-02 14:10:04 +01:00
Benjamin Kampmann c07c284c5e fixing docs for await 2022-02-02 14:03:07 +01:00
Benjamin Kampmann b4d5ad95cf fixing style 2022-02-02 13:15:54 +01:00
Benjamin Kampmann ea959a17e2 Merge remote-tracking branch 'upstream/main' into ben-wasm-store 2022-02-02 13:05:52 +01:00
Benjamin Kampmann e2c6dc33fb Merge remote-tracking branch 'upstream/main' into ben-wasm-store 2022-02-02 12:16:49 +01:00
Damir Jelić 261772c4e2 chore: Upgrade our deps 2022-02-02 10:27:03 +01:00
Damir Jelić 27eed9d9bd refactor(matrix-sdk): Use the ruma cancel code for mismatched sas 2022-02-01 16:10:06 +01:00
Jonas Platte 8a97936228 Fix one more clippy warning 2022-02-01 15:44:22 +01:00
Jonas Platte 0df1f6007b Silence invalid clippy warnings 2022-02-01 15:44:16 +01:00
Benjamin Kampmann 8270304485 Fix build warnings and clippy lints 2022-02-01 15:30:09 +01:00
Benjamin Kampmann 93c75c1e4d fixing build warnings and clippy lints 2022-02-01 15:09:58 +01:00
Jonas Platte 2f67b62509 Unbreak wasm_command_bot compilation 2022-02-01 15:08:02 +01:00
Jonas Platte 74172dac32 Activate ruma's rand feature unconditionally in matrix-sdk, matrix-sdk-crypto
… because it is required for `TransactionId::new()`.
2022-02-01 15:08:02 +01:00
Jonas Platte 96d9fd80eb Silence new clippy lint occurrence 2022-02-01 15:08:02 +01:00
Jonas Platte 8dec390258 Upgrade Ruma 2022-02-01 15:08:01 +01:00
Jonas Platte 6baffc4b0b Refactor EncodeKey implementations 2022-02-01 15:05:10 +01:00
Jonas Platte c6594edc92 Use faster sorting algorithm
… because Clippy complained.
2022-02-01 15:05:10 +01:00
Jonas Platte 80e8d4fbd5 Remove unnecessary copying 2022-02-01 15:05:10 +01:00
Jonas Platte aa4a31d81b crypto: Refactor some test code 2022-02-01 15:05:10 +01:00
Jonas Platte df93cfde8b Remove unnecessary Result from private function return type 2022-02-01 15:05:10 +01:00
Jonas Platte f56f27a2e1 Remove unnecessary parentheses 2022-02-01 15:05:10 +01:00
Jonas Platte 3e496dba50 Remove unnecessary .iter() calls 2022-02-01 15:05:10 +01:00
Damir Jelić b55362a35b Merge branch 'forget' 2022-02-01 14:36:23 +01:00
Damir Jelić 88b64950dc Merge branch 'not_match_sas' 2022-02-01 14:05:54 +01:00
Benjamin Kampmann a0f2e38b89 Merge remote-tracking branch 'upstream/main' into ben-wasm-store 2022-02-01 14:04:26 +01:00
Damir Jelić fe2323cd33 Merge branch 'doc-store-path-feature' 2022-02-01 13:53:31 +01:00
Damir Jelić d09792e402 docs(matrix-sdk): Clarify that an in-memory store will be used 2022-02-01 13:47:16 +01:00
Damir Jelić ac7f2c94fb Merge branch 'fix-verification-done-wait' 2022-02-01 13:43:58 +01:00
Damir Jelić 906dcfe423 Merge branch 'messages-param' 2022-02-01 12:34:40 +01:00
Damir Jelić b5ce7e7bd0 Merge branch 'tags' 2022-02-01 12:01:17 +01:00
Damir Jelić c9c03fd9b1 Merge branch 'encrypt-custom-events' 2022-02-01 11:48:31 +01:00
Julian Sparber 960c90cdff Add method to mismatch SAS verifications
The method sets the proper CancelCode for the case when SAS doesn't
match on both devices.
2022-01-13 10:26:53 +01:00
Kévin Commaille e1d78c01f0 test(base): Add store test for room removal 2022-01-12 18:41:26 +01:00
Kévin Commaille 76d1b6e4d2 test(base): Add test to populate a store 2022-01-12 18:40:57 +01:00
Kévin Commaille 94e5ee71c7 fix(sdk): Remove a room from the store on forget 2022-01-12 16:53:47 +01:00
Kévin Commaille d455b0d318 test(base): Use common data for store tests 2022-01-12 16:42:04 +01:00
Kévin Commaille 535d1ec30f feat(sdk): Use TagName in set/remove tag methods 2022-01-11 12:25:27 +01:00
Kévin Commaille 52deff1db2 fix(sdk): Move set/remove tag methods to room::Common 2022-01-11 12:24:46 +01:00
Jonas Platte 4603ee136d Remove unnecessary string copies 2022-01-10 16:30:45 +01:00
Jonas Platte da657b8643 Allow custom events in OlmMachine::encrypt 2022-01-10 16:29:49 +01:00
Jonas Platte c2888e56a4 Use a custom options type for room::Common::messages
With the previous API, one would have to supply the room's ID manually,
despite the method already being called on a room.
2022-01-09 01:54:38 +01:00
Benjamin Kampmann 92044cedb9 fixing style again 2022-01-07 12:03:19 +01:00
Benjamin Kampmann fb81ebf301 fixing style again 2022-01-07 12:00:12 +01:00
Benjamin Kampmann 278d934973 fix broken merge 2022-01-07 11:49:51 +01:00
Benjamin Kampmann 0937c2e6f6 [fix ci] remove unused import 2022-01-07 10:46:46 +01:00
Benjamin Kampmann e1ad8fe8e0 Merge remote-tracking branch 'upstream/main' into ben-wasm-store 2022-01-07 10:42:52 +01:00
Antoine Martin 27f2cd3db0 docs(sdk): document features needed for store_path
If default features `sled_state_store` and `sled_cryptostore` aren't
enabled, then passing a store path to the Client does nothing.
2022-01-06 16:09:24 +01:00
Amanda Graven 038adea6d7 appservice: Examples for query handler registry fns
Add examples for functions for registering handlers for room and user
queries. Also remove a needless mut requirement for these functions.
2022-01-05 14:33:46 +01:00
ftilde b1501fcb1d Add test for verification started from a request 2022-01-04 21:27:06 +01:00
ftilde b877d15616 Do not send Done message after receiving a Done
Done messages are supposed to indicate that the verification was
successful and _can be_ finalized. The correct time to send Done events
is after the user has confirmed the verification (after checking the
emoji or similar) and after receiving and checking a mac from the other
party (whatever happens later). Waiting for the other side to send Done
before sending it ourselves does not make sense.
2022-01-04 21:27:06 +01:00
ftilde 1c72472706 Send Done message when confirming in MacReceived state
Being in MacReceived state means that the other party has confirmed that
emojis/numbers match and the sent mac messages has been successfully
checked. When now confirming ourselves this means that the verification
was successful and thus the Done message can be sent to the other party.
2022-01-04 21:27:06 +01:00
ftilde 0e4057f3a3 Do not drop requests after receiving mac if sas is not complete
When during verification we are the first party to complete the
verification workflow and then receive a (correct) MAC from the other
party, we need to send out the Done message even if we have not received
the Done message from the other party ourselves and are thus still
"WaitingForDone".
2022-01-04 21:27:06 +01:00
Damir Jelić c79e62d80e Merge branch 'fix-verification-double-start' 2022-01-04 14:59:52 +01:00
ftilde f4249c591a Return RoomEvents from decryption methods
Previously, these methods returned `SyncRoomEvent`s instead, even though
the decrypted events are required to contain a room_id field (in order
for the server to not to be able to change these). As a side effect,
glue code which adds a room_id to the `SyncRoomEvent` to convert it to a
`RoomEvent` is be removed in some places.

When a `SyncRoomEvent` is required (such as in code handling sync
responses), the `From` implementation of `SyncRoomEvent` can be used.
2022-01-03 22:48:51 +01:00
ftilde 37cadc7c29 Add From<RoomEvent> for SyncRoomEvent
Since SyncRoomEvents are just RoomEvents without a room_id, it is safe
to just discard the information that this field exists in the underlying
json.
2022-01-03 22:48:30 +01:00
ftilde a1cf8b613d Drop start requests from lower precedence parties if sas has already been started.
According to the guide for implementing verification started from
a verification request, both parties should (or at least allowed to)
send a start request when the verification is ready. However, only the
start request from the party with lexicographically smaller user id (or
device id, for device verification, and thus equal user id) is supposed
to be accepted, and the other one ignored.
2022-01-03 21:04:07 +01:00
ftilde 798464b68e Verification: Handle Accept after Start on both sides
Previously, when a sas-workflow was started by the other party (e.g.
from a verification request), but the own start request was answered with
an "accept" this accept would be ignored. However, this is incorrect
since the official guide on implementing verification actually states
that both parties are expected to send start-requests, where of those
only one request is actually accepted (depending on user id and possibly
the device id).
2022-01-03 21:02:53 +01:00
ftilde 87de0b5883 Return broken messages unchanged from messages()
Without this change, a batch with a message that cannot be deserialized
(for whatever reason) means that the batch cannot be processed at all by
the caller. Now, those messages are returned unchanged in the batch so
that the caller can handle them.
2022-01-03 19:49:19 +01:00
Damir Jelić 5003ed1493 docs: Enable all features for some of our crates when building docs 2022-01-03 13:14:36 +01:00
Damir Jelić f12f03b8da docs: Switch to the doc_auto_cfg feature 2022-01-03 12:33:24 +01:00
Damir Jelić 9856270e75 fix(crypto): Don't enable the backup feature by default 2022-01-03 12:27:03 +01:00
Damir Jelić c22fa4e3fd fix(base): Fix a new clippy warning 2022-01-03 10:23:38 +01:00
Julien Merzoug f7f30f1636 docs(sdk): Fix a typo 2022-01-03 13:05:35 +08:00
Damir Jelić ae9a554808 Merge branch 'supported-versions' 2021-12-31 14:00:11 +01:00
Kévin Commaille 5ecd74b2e4 feat(sdk): Make get_supported_versions public 2021-12-31 13:02:15 +01:00
Damir Jelić dd29e2087c Merge branch 'common-fixes' 2021-12-31 12:54:49 +01:00
Jonas Platte 99ce9419aa Fix futures-util dependency
Turn on alloc feature that is required for `future::join_all`.
2021-12-31 11:00:51 +01:00
Kévin Commaille 0d771565f9 feat(sdk): Simplify the API of Common::event 2021-12-31 02:34:16 +01:00
Kévin Commaille c35f8c55ac fix(sdk): Fix docs of Common::active_members_no_sync 2021-12-31 02:16:20 +01:00
ftilde 703e965172 Decrypt messages from room::Common::messages()
Due to additional error possibilities and encryption info for messages,
the return type of the method was changed accordingly and a wrapper
struct `Messages` was introduced.
2021-12-29 15:26:45 +01:00
ftilde 046bfa9dad Fix typo in comment 2021-12-29 15:26:39 +01:00
Damir Jelić 035d319122 Merge branch 'travis/misc' 2021-12-28 11:52:23 +01:00
Damir Jelić 81b730d8c3 Merge branch 'request-config-expose-force_auth' 2021-12-28 11:31:08 +01:00
Damir Jelić 6170be95e1 Merge branch 'membership' 2021-12-28 10:59:34 +01:00
Benjamin Kampmann 34687733e5 create sync token store 2021-12-27 23:54:51 +01:00
Benjamin Kampmann 8ce622d11e fixin style 2021-12-27 23:37:45 +01:00
Benjamin Kampmann 9ff4609f3d testing emcc versions 2021-12-27 23:35:21 +01:00
Benjamin Kampmann 15cdaead50 fix broken now call 2021-12-27 23:27:11 +01:00
Benjamin Kampmann 3cde28a438 trying older emscripten 2021-12-27 21:37:37 +01:00
Jonas Platte d92d7771d9 Add must_use attribute to config constructors and methods
These all don't have side effects so discarding the result wouldn't make
sense.
2021-12-27 17:21:21 +01:00
Jonas Platte f6d7933601 Simplify filter closure 2021-12-27 14:56:31 +01:00
Jonas Platte abf525390e Fix clippy warning (remove unnecessary clone) 2021-12-27 14:56:19 +01:00
Jonas Platte fea80843eb Remove redundant calls to .into_iter() 2021-12-27 14:21:46 +01:00
Jonas Platte 1a7baf631e Avoid enormous type name in GroupSessionManager::encrypt_session_for 2021-12-27 14:20:16 +01:00
Benjamin Kampmann cbd4aa0a37 disable test failing on macosx 2021-12-22 13:58:54 +01:00
Benjamin Kampmann 98beff4455 resolve clippy complaints 2021-12-22 12:36:07 +01:00
Benjamin Kampmann 574893368b refine wasm tests 2021-12-22 12:32:59 +01:00
Benjamin Kampmann 1f5a084ccf don't fail fast 2021-12-22 11:38:52 +01:00
Benjamin Kampmann 8dda7ea8fa please consider all includes 2021-12-22 11:19:39 +01:00
Benjamin Kampmann e619cc1eb7 don't combine 2021-12-22 10:59:17 +01:00
Benjamin Kampmann 1a206ff36c let them all run out 2021-12-16 18:46:00 +01:00
Benjamin Kampmann afe7d055a1 [ci] fix syntax 2021-12-16 18:24:31 +01:00
Benjamin Kampmann 9d4d8667ff latest and node 2021-12-16 17:14:03 +01:00
Benjamin Kampmann 8feab722f8 [CI] dynamic node version 2021-12-16 11:35:24 +01:00
Benjamin Kampmann 7ad5bc7dee version listing 2021-12-16 11:15:10 +01:00
Benjamin Kampmann 71bc043d19 extended testing for wasm example 2021-12-16 10:52:15 +01:00
Travis Ralston 171c334cb1 Add .idea directory to gitignore 2021-12-14 18:59:23 -07:00
Benjamin Kampmann 4f93e739f5 fixing typo 2021-12-13 23:25:26 +01:00
Benjamin Kampmann fa00cba8bb fixing style 2021-12-13 22:37:12 +01:00
Benjamin Kampmann 678527e1e6 libolm is fixed, so should our code be 2021-12-13 22:35:56 +01:00
Benjamin Kampmann 7fc040d86c Merge remote-tracking branch 'upstream/main' into ben-wasm-store 2021-12-13 22:34:33 +01:00
Marc 'risson' Schmitt ba05dd5b8c feat(RequestConfig): expose force_auth setting
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2021-12-13 20:45:51 +01:00
Kévin Commaille b697bcb4fd feat(base): Add RoomMember::membership accessor 2021-12-13 16:20:46 +01:00
Benjamin Kampmann 2982741dd1 minor style fix 2021-12-10 16:32:09 +01:00
Benjamin Kampmann 3f9b5511d1 activate IdbKeyRange feature on web-sys dependency 2021-12-10 14:02:02 +01:00
Benjamin Kampmann 35f2a004e1 style and docs fixes 2021-12-10 13:58:02 +01:00
Benjamin Kampmann e02407ef37 Merge remote-tracking branch 'upstream/main' into ben-wasm-store 2021-12-10 13:30:46 +01:00
Benjamin Kampmann bf9ad7a5c0 fix typo 2021-12-10 13:28:28 +01:00
Benjamin Kampmann 186bd975c1 reuse SafeEncode for indexeddb_cryptostore 2021-12-10 13:28:16 +01:00
Benjamin Kampmann 007b7e2403 outsource SafeEncode helper 2021-12-10 12:53:57 +01:00
Benjamin Kampmann a6dbd6bcbb escaped characters for indexeddb keys 2021-12-10 11:47:35 +01:00
Damir Jelić 009ead2eea chore: Bump Ruma. 2021-12-08 16:50:25 +01:00
Benjamin Kampmann 3de6f60f90 remove unneccessary imports and compiler flags 2021-12-08 13:42:44 +01:00
Benjamin Kampmann 2ccb1d2813 don't pickle 2021-12-08 12:39:50 +01:00
Benjamin Kampmann 89523241fd fixing main sdk wasm testing 2021-12-02 14:37:59 +01:00
Benjamin Kampmann 5734afc7ab [CI] fixing test syntax 2021-12-02 12:45:29 +01:00
Benjamin Kampmann 4e18286c1c remove another dependency 2021-12-01 23:53:07 +01:00
Benjamin Kampmann 10e27536ba fix CI format 2021-12-01 23:51:22 +01:00
Benjamin Kampmann 9883ca0d84 [CI] parallel and the correct crates 2021-12-01 23:46:05 +01:00
Benjamin Kampmann aab1fd2147 fixing ci job 2021-12-01 21:03:26 +01:00
Benjamin Kampmann 652ef6e160 sled store needs tokio 2021-12-01 20:48:27 +01:00
Benjamin Kampmann 53ad5810ef typo fixes 2021-12-01 20:36:44 +01:00
Benjamin Kampmann d0838d6784 fixing style 2021-12-01 20:34:27 +01:00
Benjamin Kampmann 1bbe38e376 compiling matrix-sdk for wasm 2021-12-01 20:32:26 +01:00
Benjamin Kampmann d155f9a020 can work on wasm32 2021-12-01 20:06:25 +01:00
Benjamin Kampmann 7e6ac4222f cleaning up store 2021-12-01 20:03:47 +01:00
Benjamin Kampmann d0395906ab activate available tests for wasm32 2021-12-01 19:32:34 +01:00
Benjamin Kampmann ac2771b997 add docs 2021-12-01 19:00:06 +01:00
Benjamin Kampmann 470c81b8ad be specific with dead_code 2021-12-01 18:58:22 +01:00
Benjamin Kampmann f5485088a0 limit test execution to platforms that support it 2021-12-01 18:55:34 +01:00
Benjamin Kampmann 2ee7a95fc4 (now really) ensure Instant::now is working properly 2021-12-01 18:03:43 +01:00
Benjamin Kampmann 6b3f008b32 ensure Instant::now is working properly 2021-12-01 18:01:00 +01:00
Benjamin Kampmann 8ab5df490a remove appservice, as it won't support wasm for a while 2021-12-01 15:39:41 +01:00
Benjamin Kampmann 787f8265d3 fixing CI 2021-12-01 15:15:26 +01:00
Benjamin Kampmann 293700ce69 checking all crates for wasm32 2021-12-01 14:53:21 +01:00
Damir Jelić f97aed0e41 Merge branch 'MTRNord-wasm-fix' 2021-12-01 14:51:28 +01:00
Benjamin Kampmann afaeae8e6b unify indexeddb-features and improve example build 2021-12-01 12:57:09 +01:00
Benjamin Kampmann b150dea329 fix style 2021-12-01 11:58:22 +01:00
Benjamin Kampmann 4b12260af3 move store implementations into files 2021-12-01 11:56:33 +01:00
Benjamin Kampmann 9d5c1fc14c move store tests into separate reusable macro, too 2021-12-01 11:52:29 +01:00
Benjamin Kampmann c7a9fc6c8e syntax fix 2021-12-01 11:48:30 +01:00
Benjamin Kampmann a1b62a1f4b allow helper to be unused 2021-11-30 19:21:16 +01:00
Benjamin Kampmann 1a20e62de7 remove trouble causing unnecessary ref-clone 2021-11-30 18:54:12 +01:00
Benjamin Kampmann 4fdada55b8 fixing typo 2021-11-30 18:50:50 +01:00
Benjamin Kampmann c5e7ca0c5e undo my olm-sys-hack 2021-11-30 18:45:40 +01:00
Benjamin Kampmann 97d675f216 fix formatting 2021-11-30 18:45:00 +01:00
Benjamin Kampmann 9a0cf2b507 Merge remote-tracking branch 'upstream/main' into ben-wasm-store 2021-11-30 18:43:20 +01:00
Benjamin Kampmann 9b7c1d7c4d Merge remote-tracking branch 'upstream/main' into ben-wasm-store 2021-11-30 18:40:14 +01:00
Benjamin Kampmann 968f80cc1b minor fix 2021-11-30 18:00:20 +01:00
Benjamin Kampmann f185aa2eae reuse cryptostore for sled 2021-11-30 17:58:14 +01:00
Jonas Platte 6519aaff4d crypto: Fix docs for SledStore 2021-11-30 17:48:49 +01:00
Benjamin Kampmann 9f0fe18dfc fix async_test for non-wasm32 envs 2021-11-30 17:46:50 +01:00
Benjamin Kampmann 954cce463e make cryptostore tests reusable 2021-11-30 16:01:42 +01:00
Benjamin Kampmann e3c62825b6 test and impl for outbound 2021-11-30 14:49:00 +01:00
Benjamin Kampmann 1e654acc29 backup and reset for inbound_groups 2021-11-30 13:20:49 +01:00
Benjamin Kampmann 59e3baf819 cover more inbound_group_session functions 2021-11-30 13:01:49 +01:00
Damir Jelić 8494f10583 Merge branch 'up-ruma' 2021-11-30 09:56:01 +01:00
Benjamin Kampmann d509eaa959 implement tracked user 2021-11-29 21:23:01 +01:00
Benjamin Kampmann 85dde94dd5 implement sessions 2021-11-29 20:57:30 +01:00
Benjamin Kampmann c9a10353f2 implement olm_hashes 2021-11-29 20:47:18 +01:00
Benjamin Kampmann 41faa59121 implement keyrequests 2021-11-29 19:43:20 +01:00
Benjamin Kampmann 833802677b implement devices saving and deleting 2021-11-29 15:04:20 +01:00
Jonas Platte 5824cb649e Update tests 2021-11-29 14:30:45 +01:00
Benjamin Kampmann fe257effce properly open encrypted state db 2021-11-29 14:05:48 +01:00
Benjamin Kampmann 47168ca3da implement saving user 2021-11-29 14:05:22 +01:00
Jonas Platte dfd59f42a9 Fix warp build error 2021-11-29 13:36:05 +01:00
Jonas Platte 557e038869 Minimal style improvements 2021-11-29 13:27:38 +01:00
Damir Jelić a628e84b63 fix(crypto): Fix a copy paste error preventing us from verifying users 2021-11-29 09:31:05 +01:00
Jonas Platte 36db5e47dd Upgrade Ruma 2021-11-26 19:22:54 +01:00
Damir Jelić 56d80b91c9 fix(sdk): Send the crypto requests out before a sync as well 2021-11-26 16:52:32 +01:00
Damir Jelić b0f48c9660 fix(crypto): Let users fetch our own device out of the store 2021-11-26 16:52:31 +01:00
Damir Jelić 68a2020516 fix(crypto): Check if the device we get from the server matches our own 2021-11-26 16:26:40 +01:00
Damir Jelić 13db642143 fix(cyrpto): Log database upgrades using the debug log level 2021-11-26 16:26:40 +01:00
Damir Jelić f2c344b39a fix(crypto): Use the DeviceKeys as the inner type for a ReadOnlyDevice 2021-11-26 16:26:40 +01:00
Benjamin Kampmann b42b04e887 account loading and saving 2021-11-26 14:36:14 +01:00
Benjamin Kampmann 229a81bfd6 Implement saving 2021-11-26 12:37:57 +01:00
Benjamin Kampmann 6d9920c239 various minor cleanups of unused imports 2021-11-25 16:44:20 +01:00
Damir Jelić 7b6132b71e feat(crypto): Return the list of room keys we imported
Clients might want to retry decryption after they import room keys, for
this to be efficient they'll need to know which room keys got imported.

This patch extends the return value of the room key import result to
include the map of room keys that got imported.
2021-11-25 16:41:28 +01:00
Benjamin Kampmann 47dff21eda update trait impl of indexeddb 2021-11-25 15:52:57 +01:00
Benjamin Kampmann 32a8ec7782 minor wasm32 fixes 2021-11-25 15:52:27 +01:00
Benjamin Kampmann 4c60db94a2 Implement helper for wasm32 MilliSecondsSinceUnixEpoch 2021-11-25 15:52:03 +01:00
Benjamin Kampmann 42680164ea fix up CI test 2021-11-25 15:49:20 +01:00
Benjamin Kampmann 5cf56adce7 Adding result-signature support for wasm32 async-test-macro 2021-11-25 15:46:17 +01:00
Damir Jelić 10173b990d fix(sdk): Degrade some logs that show user ids to the debug log level 2021-11-25 14:49:07 +01:00
Damir Jelić fc74526699 fix(crypto): Add the ability to mark room keys as backed up when importing 2021-11-25 11:18:09 +01:00
Damir Jelić 55973b5bf1 fix(crypto): Make ExportedRoomKey deserialization laxer
Some clients might have skipped the serialization of an empty
sender_claimed_keys and the forwarding_curve25519_key_chain, while these
fields are required there's really no upside in requiring them if they
are empty.

So create defaults if they are missing.
2021-11-25 10:20:09 +01:00
Marcel 406aaa0b50 Make sure to also include the uuid create serde feature with wasm 2021-11-24 20:50:36 +01:00
Damir Jelić 33b198d505 fix(crypto): Make sure we remove the unsigned object before signing 2021-11-24 15:56:32 +01:00
Damir Jelić be70d38e2a fix(crypto): Use the from constructor for some maps with known values 2021-11-24 15:56:05 +01:00
Damir Jelić 1e70b4f804 fix(crypto): Automatically track your own user if the caller doesn't do so
Users of the crypto crate should mark all members that are part of an
E2EE room for tracking, this will of course mark your own user for
tracking.

If the crypto crate user doesn't have any E2EE rooms he may not add any
members to be tracked. The user might still want to inspect their own
E2EE devices and identities. This patch makes sure that our member is
tracked.
2021-11-24 15:21:50 +01:00
Benjamin Kampmann 4c0bbebb07 Merge remote-tracking branch 'upstream/main' into ben-wasm-store 2021-11-24 11:48:45 +01:00
Benjamin Kampmann 9835c4ad92 Update to webpack5 2021-11-24 11:00:52 +01:00
Damir Jelić a49a7fe1f9 fix(crypto): Clear the master key signatures when we verify our own user 2021-11-22 18:00:52 +01:00
Damir Jelić fa42373cf8 Merge branch 'client-arc' 2021-11-22 16:27:27 +01:00
Damir Jelić a8c36b4041 Merge branch 'fix-session-doc-example' 2021-11-22 16:24:31 +01:00
Damir Jelić b91773a276 Merge branch 'store-upgrade-fix' 2021-11-22 16:23:53 +01:00
Damir Jelić fbc01f015d fix(sdk): Use the correct restore method in an example 2021-11-22 15:44:35 +01:00
Damir Jelić 5d26e36e1f fix(crypto): Make sure we store the store version using the right key 2021-11-22 15:28:21 +01:00
Damir Jelić c4f60dd163 fix(crypto): Only upload our own signature when verifying user identities 2021-11-22 12:33:18 +01:00
Jonas Platte b4220bd824 Reduce the size of Client
… by moving all of its fields into an inner reference-counted type
rather than using reference counting for all fields individually.
Some fields are still refcounted individually and thus go through an
extra layer of indirection, but the size and clone simplification should
still make this change worthwhile.
2021-11-20 02:01:07 +01:00
Jonas Platte 73c5bfed28 Switch from futures-locks to async-lock 2021-11-20 02:01:07 +01:00
Jonas Platte 2456beaf88 Make Result alias more flexible 2021-11-20 00:00:08 +01:00
Jonas Platte cc6f97bee9 Fix missing word 2021-11-20 00:00:08 +01:00
Jonas Platte 8f47e6ffe9 Remove copy-pasted module documentation
It doesn't seem right that both room and room_member have  the same
description. Also room_member is private and doesn't usually show up in
docs.
2021-11-20 00:00:08 +01:00
Jonas Platte 544b24b0ef Move some code out of client.rs
It is by far the biggest module of the matrix-sdk crate.
2021-11-20 00:00:08 +01:00
Benjamin Kampmann 94d3ffa18d infrastructure for indexeddb cryptostore 2021-11-19 21:26:33 +01:00
Jonas Platte 1e13e06e34 Make event-handling related Client fields private 2021-11-19 20:48:27 +01:00
Benjamin Kampmann 9e83bcb6ce fixing browser test 2021-11-19 14:52:11 +01:00
Benjamin Kampmann 917e9016cd clean up API and corresponding docs 2021-11-19 13:52:03 +01:00
Damir Jelić 5a4aa71f6a feat(base): Add a From login response implementation for the Session 2021-11-19 09:41:48 +01:00
Damir Jelić 6606703001 docs(base): Remove anyhow from an example since it isn't used 2021-11-19 09:12:51 +01:00
Andy Balaam 0c35d8890d Improve Session docs example 2021-11-18 17:14:34 +00:00
Benjamin Kampmann 76454e6b8b style fix 2021-11-18 17:40:56 +01:00
Andy Balaam 7d7bd97812 Document how to create a Session 2021-11-18 14:18:16 +00:00
Benjamin Kampmann 10d4fe53f2 clarify API 2021-11-18 15:01:07 +01:00
Benjamin Kampmann 3fcfe98de2 minor clippy fixes 2021-11-18 13:54:24 +01:00
Benjamin Kampmann b16c660258 fixing typo 2021-11-18 13:48:56 +01:00
Benjamin Kampmann 7df36e3d49 first attempt at creating a CI job for wasm tests 2021-11-18 13:37:11 +01:00
Benjamin Kampmann 3e11e0dbb4 fixing style 2021-11-18 13:36:45 +01:00
Benjamin Kampmann a2b80f03d3 move and unify usage of store_key 2021-11-18 12:58:17 +01:00
Benjamin Kampmann e60349604d implement custom value 2021-11-18 12:40:45 +01:00
Andy Balaam f5ba9a5eea Update BackupMachine documentaton to refer to enable_backup_v1 2021-11-18 10:28:03 +00:00
Benjamin Kampmann e7ec86140b generic tests passing' 2021-11-17 21:30:12 +01:00
Benjamin Kampmann 5bba24ce77 activating browser tests 2021-11-17 18:18:20 +01:00
Benjamin Kampmann b8af613aef big batch 2021-11-17 13:08:58 +01:00
Damir Jelić 2e4d5f25cb feat(crypto): Add a method to get the algorithm of the public backup key 2021-11-17 13:02:23 +01:00
Damir Jelić 534e50da57 fix(crypto): Rename the enable_backup method so we can add a v2 one 2021-11-17 13:02:23 +01:00
Damir Jelić 1ffa06884a fix(crypto): Rename the decrypt method on the RecoveryKey struct
The new backup algorithm reuses the same key but uses a different
construct to encrypt/decrypt room keys. This reflects that our decrypt
method uses the v1 algorithm.
2021-11-17 13:02:23 +01:00
Damir Jelić 670e212d9b docs(crypto): Fill out the docs for the backup related types 2021-11-17 13:02:23 +01:00
Damir Jelić 6fc703b4a3 fix(crypto): Fix a bunch of clippy warnings 2021-11-17 13:02:23 +01:00
Damir Jelić 33b7062515 fix(crypto): Fix a bunch of typos 2021-11-17 13:01:58 +01:00
Damir Jelić a7bbeb7ef5 improvement(crypto): Add tests for the recovery key 2021-11-17 13:01:58 +01:00
Damir Jelić 34ec4ac3c9 improvement(crypto): Add tests for the backup machine 2021-11-17 13:01:58 +01:00
Damir Jelić 3f227de023 fix(crypto): Fix the backed up room key count in the memory store 2021-11-17 13:01:58 +01:00
Damir Jelić a417aa23fa fix(crypto): Load the recovery key from the sled store 2021-11-17 13:01:58 +01:00
Damir Jelić f8fdfd1613 fix(crypto): Add a proper exception when creating the Pk decryption object 2021-11-17 13:01:58 +01:00
Damir Jelić 1fdd560ff0 fix(crypto): Remove a unneeded clippy attribute 2021-11-17 13:01:58 +01:00
Damir Jelić 878969a5c4 docs(crypto): Add some docs for the backup related types 2021-11-17 13:01:58 +01:00
Damir Jelić c6d073ebd7 fix(crypto): Remove some dead code 2021-11-17 13:01:58 +01:00
Damir Jelić 2b5ae869cd feat(crypto): Gossip the backup recovery key if requested 2021-11-17 13:01:58 +01:00
Damir Jelić 2db52eed7c feat(crypto): Request the recovery key when we request secrets 2021-11-17 13:01:58 +01:00
Damir Jelić 656edce75a improvement(crypto): Make the backup logging prettier 2021-11-17 13:01:58 +01:00
Damir Jelić 4c021dea5e fix(crypto): Correctly reset the backup state of room keys 2021-11-17 13:01:58 +01:00
Damir Jelić bbd76dafa0 fix(crypto): Fix a bunch of clippy warnings 2021-11-17 13:01:58 +01:00
Damir Jelić 4f2c91d848 feat(crypto): Add a method to decrypt messages using the recovery key 2021-11-17 13:01:58 +01:00
Damir Jelić 6f5b6900d6 fix(crypto): Flush when we ugprade the DB 2021-11-17 13:01:58 +01:00
Damir Jelić eddc7bd6af feat(crypto): Add a method to check the signature of a backup version 2021-11-17 13:01:58 +01:00
Damir Jelić dfef6370b6 feat(crypto): Add a method to verify uploaded backups 2021-11-17 13:01:58 +01:00
Damir Jelić b5babdb6c4 fix(crypto): Don't load all room keys when backing up 2021-11-17 13:01:58 +01:00
Damir Jelić df53eb00ab fix(crypto): Fix a deadlock when generating the backup request 2021-11-17 13:01:58 +01:00
Damir Jelić 63915171fc feat(crypto): Add a method to check if backups are enabled 2021-11-17 13:01:58 +01:00
Damir Jelić 4873914d4d feat(crypto): Initial support for server-side backups of room keys 2021-11-17 13:01:44 +01:00
Benjamin Kampmann 8a2732ab5d first steps 2021-11-15 20:05:43 +01:00
Damir Jelić f069387d58 docs(sdk): Add an example to the restore_login method 2021-11-15 16:15:05 +01:00
ftilde 8815c05108 Refactor Joined::send_attachment
Instead of manually modifying *EventContent structs, the ruma
constructors *::encrypted and *::plain are used now depending on whether
encryption should be used for the attachment or not.
2021-11-13 01:39:00 +01:00
ftilde dfc2ed7a33 Prefer MediaType::Encrypted if url and file are present
Some clients (including those using matrix-rust-sdk currently) may add
encrypted file info as well as the url to the encrypted blob to the
*EventContent. Interpreting the presence of an url as an indicator of
unencrypted message (like was done before) would result in access to the
encrypted blob in `get_media_content`.

Fixes #406.
2021-11-13 01:39:00 +01:00
Jonas Platte 38a8253aa8 Turn register_event_handler(_context)? examples into proper doctests
Previously, they didn't actually run the methods they were showing the
use of.
2021-11-12 12:39:07 +01:00
Jonas Platte 5fed5cdeed Allow adding custom event handler context 2021-11-12 12:39:07 +01:00
Jonas Platte df50d59de2 Update signature of AppService::register_event_handler
It no longer requires a mutable `AppService` and can also be chained,
like `Client::register_event_handler`.
2021-11-11 19:28:40 +01:00
Damir Jelić 1651952903 docs(sdk): Remove a bunch of unwraps from some doc examples 2021-11-11 16:58:43 +01:00
Damir Jelić 33a43af20e improvement(crypto): Use a type for the result of the room key import method 2021-11-11 16:57:31 +01:00
Damir Jelić 6a66a67454 fix(crypto): Fix the importing of exported room keys 2021-11-11 16:05:14 +01:00
Jonas Platte 83b908754e Remove unused dependencies
Found by cargo-udeps.
2021-11-10 21:43:56 +01:00
Jonas Platte 02b0ed2b42 Reduce dependencies on futures-* crates 2021-11-10 20:39:35 +01:00
Jonas Platte c124cf5b62 Remove unnecessary use of future::ready 2021-11-10 20:39:03 +01:00
Jonas Platte dfdf794199 Remove unnecessary use of TryFutureExt 2021-11-10 20:12:56 +01:00
Damir Jelić df2c0bd6e9 docs(sdk): Fix a typo in the enable_encryption method 2021-11-09 19:52:46 +01:00
Damir Jelić 2e04a3753d Merge branch 'one-time-key-generationf-fix' 2021-11-09 13:50:08 +01:00
Damir Jelić e1e864c606 fix(crypto): Save the account if we created a new key upload request 2021-11-09 12:30:48 +01:00
Damir Jelić 7f3067553b fix(crypto): Don't generate new one-time keys unless the existing ones are uploaded
This is helpful if the caller doesn't have propper request retrying.
Calling the outgoing_requests() method without actually uploading
all the requests would end up generating too many one-time keys and
removing some one-time keys that weren't used yet.

This would manifest itself down the line as undecryptable to-device
messages.
2021-11-09 11:45:20 +01:00
Julian Sparber 253d6c9af8 matrix-qrcode: Use GenericImage and GenericImageView trait
This changes `QrVerificationData::from_luma()` to accept any struct that
implements GenericImage and GenericImageView.
This way we don't force a specific container for the ImageBufffer, hence
the developer doesn't necessarily need to copy the image data into a
Vec<u8>.
2021-11-09 11:33:38 +01:00
Damir Jelić 1f1ae0059e docs: Remove the now unneeded doc cfg attributes 2021-11-09 10:43:42 +01:00
Damir Jelić 05a190ee5a docs(sdk): Add an example that prints out the SAS emojis 2021-11-08 17:17:42 +01:00
Damir Jelić ed561f7b9e improvement(crypto): Use a struct for the SAS emoji/description pairs 2021-11-08 17:17:14 +01:00
Damir Jelić fba12b3926 docs(sdk): Explain how room keys work in the encryption module 2021-11-08 15:32:51 +01:00
Damir Jelić 1b2ef50ded docs(sdk): Explain why it may be problematic to manually verify devices 2021-11-08 15:32:51 +01:00
Damir Jelić c79481c6fa docs(sdk): Clarify what it means for a device to be verified 2021-11-08 15:32:51 +01:00
Damir Jelić f5b98a62ab docs(sdk): Describe the ways we can restore a client 2021-11-08 15:32:51 +01:00
Damir Jelić f5a6972feb improvement(crypto): Rename the EncryptionInfo struct for attachments 2021-11-08 15:32:51 +01:00
Damir Jelić 1faaba39c7 docs(sdk): Explain how cross signing helps a bit better 2021-11-08 15:32:51 +01:00
Damir Jelić e58eb70924 chore: Switch to the 2021 edition 2021-11-08 15:32:51 +01:00
Damir Jelić 4bfc1041cc docs(sdk): Improve an entry in the e2ee failure table 2021-11-08 15:32:51 +01:00
Damir Jelić b6f7e85964 feat(sdk): Add a method to enable encryption for a room 2021-11-08 15:32:51 +01:00
Damir Jelić b9b02ff167 docs(sdk): Add another entry to the failure table 2021-11-08 15:32:51 +01:00
Damir Jelić 1aba90cd0b docs(sdk): Consistent headings 2021-11-08 15:32:51 +01:00
Damir Jelić 3f689e9c74 docs(sdk): Introduce a failure table for the encryption module 2021-11-08 15:32:51 +01:00
Damir Jelić d744948a27 docs(sdk): Fix a typo 2021-11-08 15:32:51 +01:00
Damir Jelić ccc3a005cb docs(sdk): A couple small clarifications 2021-11-08 15:32:51 +01:00
Damir Jelić 605c3b056f docs(sdk): Use a table to describe our features 2021-11-08 15:32:51 +01:00
Damir Jelić 387d25c438 docs(sdk): Explain a bit more how devices are backed by device keys 2021-11-08 15:32:51 +01:00
Damir Jelić 050f62baa7 docs(sdk): Clarify the manual verification a bit more 2021-11-08 15:32:51 +01:00
Damir Jelić afe4f628c3 docs(sdk): Improve the UserIdentity docs 2021-11-08 15:32:51 +01:00
Damir Jelić 3964eea2e2 docs(sdk): Add some more E2EE related docs 2021-11-08 15:32:51 +01:00
Damir Jelić 687ebabca9 Merge branch 'reciprocate_qr_scanning' 2021-11-05 19:35:57 +01:00
Julian Sparber 635ee5f130 matrix-sdk: Send reciprocate to other side when scanning a Qr Code
We need to tell the other side that we scanned there Qr Code.
2021-11-05 19:05:43 +01:00
Jonas Platte b27795c0d1 Upgrade ruma 2021-11-05 16:05:25 +01:00
Jonas Platte f21faa9e2e Remove unused imports in doctests 2021-11-05 15:39:02 +01:00
Jonas Platte 77de8383fe Fix clippy warning 2021-11-05 15:25:16 +01:00
Jonas Platte cdfd5f9f0c Remove unnecessary use of Ruma event content enums 2021-11-05 15:16:17 +01:00
Kévin Commaille 5eb7029568 matrix-sdk: Allow to reconfigure client with login response discovery info
Fixes #219
2021-11-02 16:45:03 +01:00
Kévin Commaille 52910d50b4 matrix-sdk: Remove unecessary mut for client
Client does not need to be mutable to set the homeserver
2021-11-02 11:59:44 +01:00
Julian Sparber 8dcfd1176f matrix-sdk-crypto: Drop MutexGuard in VerificationRequest::scan_qr_code()
We can't move MutexGuards across threads and therefore we need to drop
it before awaitng on a future since a task may be moved between threads.
2021-10-29 16:33:25 +02:00
Damir Jelić a85f29d904 feat(sdk): Expose the method and types to scan QR codes 2021-10-28 11:54:28 +02:00
Damir Jelić 292425fd80 fix(crypto): Make sure we don't treat our own device as a new one every time 2021-10-28 11:24:02 +02:00
Damir Jelić 19266f643c improvement(crypto): Improve the logs for the keys/query handling 2021-10-28 11:24:02 +02:00
Damir Jelić 3853d0c9d7 improvement(crypto): Log the mismatched user/key if checking fails 2021-10-27 16:23:34 +02:00
Damir Jelić 3c59e186d9 improvement(crypto): Improve the logging when we decrypt room events 2021-10-27 15:00:04 +02:00
Damir Jelić e448a76484 improvement(crypto): Improve the to-device decryption logs 2021-10-27 14:57:07 +02:00
Damir Jelić 0ee8d2733a fix(crypto): Improve the log lines for the room key encryption flow 2021-10-27 14:44:27 +02:00
Damir Jelić 38ae79ba3c Merge branch 'room-is-space' 2021-10-27 11:08:33 +02:00
Amanda Graven d06371d458 Add convenience function to check if a room is a space 2021-10-27 10:39:19 +02:00
Damir Jelić 8b200c8200 Merge branch 'appservice-user-store' 2021-10-26 12:00:27 +02:00
Damir Jelić 2a285de1b0 Merge branch 'appservice-event-handler' 2021-10-26 11:30:30 +02:00
Amanda Graven 093588d5a3 Event handlers for room and user queries
Add a member to AppService which can store closures that will be invoked
when the homeserver invokes query endpoints.
2021-10-26 10:50:23 +02:00
Amanda Graven a9e990142a appservice: Store which users have been registered 2021-10-26 09:51:51 +02:00
Damir Jelić 42bec97b68 Merge branch 'blocking' 2021-10-25 14:25:59 +02:00
Damir Jelić bc8641666c fix(sdk): Only import the crypto store type if encryption is enabled 2021-10-25 13:30:33 +02:00
Damir Jelić 74342a8775 Merge branch 'event-handling' 2021-10-25 13:02:27 +02:00
Damir Jelić bc92c02772 Merge branch 'erikj/add_crypto_store_setting' 2021-10-25 13:00:55 +02:00
Damir Jelić f434b4d970 Merge branch 'erikj/export_gossip_request' 2021-10-25 13:00:07 +02:00
Damir Jelić 86657736e8 chore: Fix some new clippy warnings. 2021-10-25 12:40:34 +02:00
Erik Johnston a037e6b1a7 Add Config::crypto_store
This allows setting of the crypto store in the high level client, in the
same way you can in the base client.
2021-10-25 10:38:28 +01:00
Jonas Platte 4570d7194e Add SyncEvent impls for SyncRedactionEvent 2021-10-22 22:11:01 +02:00
Erik Johnston a7c97e731d Document types correctly 2021-10-22 11:57:21 +01:00
Erik Johnston c093b68078 Also export SecretInfo 2021-10-22 11:33:34 +01:00
Erik Johnston c824278565 Export GossipRequest
The `matrix-sdk-store::CryptoStore` uses the type in its definition,
so we export it to allow third party implementations.
2021-10-22 11:29:15 +01:00
Julian Sparber 8ee3b6f909 sled_store: Run read operations on blocking thread 2021-10-21 14:59:33 +02:00
Denis Kasak 9e1024f4b5 refactor: Use structured logging field for room_id. 2021-10-14 12:22:13 +02:00
Denis Kasak 8cab5b811f docs: Doc tweaks. 2021-10-14 10:22:25 +02:00
Denis Kasak 1c36e62e2c fix: Unbreak encryption.
And add some docs and logging statements.

cb8a42a529 broke encryption because it
elided the call to `send_raw` from `send` and instead did a direct HTTP
request. Since event encryption is only called from `send_raw`, this
made all events cleartext.
2021-10-14 10:22:25 +02:00
Julian Sparber 0a92f7161a client: make sync_stream() return an infallible stream
This way the developer can decide what to do on an error
2021-10-11 18:33:06 +02:00
Damir Jelić 8af768bf30 chore(base): Remove the non-exhaustive patterns lint
The lint is only available on nightly, but requires to be enabled via a
feature, which is only available for nightly.
2021-10-11 11:06:32 +02:00
Damir Jelić 61375a6245 chore: Add a github action to check for typos 2021-10-11 09:49:27 +02:00
Damir Jelić 3c08b5cf09 chore: Fix a bunch of typos 2021-10-11 09:49:25 +02:00
Damir Jelić 498d7b4666 Merge branch 'dkasak/doc-improvements' 2021-10-11 09:47:21 +02:00
Damir Jelić 7cfa9dbf58 Merge branch 'dkasak/key-sharing-algorithm-rendering' 2021-10-11 09:46:43 +02:00
Damir Jelić 5aa6aeac16 Merge branch 'flow_id' 2021-10-05 20:47:33 +02:00
Jonas Platte b6261d014c Add custom event examples for Joined::{send,send_state_event} 2021-10-05 18:42:21 +02:00
Jonas Platte 8455164a69 Simplify command_bot example 2021-10-05 18:20:07 +02:00
Jonas Platte b959d4be29 Use new event type aliases 2021-10-05 18:20:07 +02:00
Jonas Platte 39d6ebdd53 Don't panic if serialization of user-provided events fails 2021-10-05 18:20:07 +02:00
Jonas Platte 0f52cd8039 Stop relying on enum deserialization for adding room_id 2021-10-05 18:20:07 +02:00
Jonas Platte 4a50561867 crypto: Simplify Account::parse_decrypted_to_device_event 2021-10-05 18:20:07 +02:00
Jonas Platte cb8a42a529 Upgrade to latest Ruma git main 2021-10-05 18:20:07 +02:00
Jonas Platte d16d21c54f crypto: Refactor ToDeviceRequest construction 2021-10-05 18:20:07 +02:00
Jonas Platte 339dfefb53 Replace qualified path with use (style consistency) 2021-10-05 18:20:07 +02:00
Jonas Platte b8e8cfd149 Fix clippy warnings 2021-10-05 18:20:07 +02:00
Jonas Platte a40cf26aa7 Fix formatting 2021-10-05 17:40:50 +02:00
Damir Jelić fe8ecbbeb8 Merge branch 'fix_lock_on_await' 2021-10-05 10:36:02 +02:00
Damir Jelić 2686e987a6 Merge branch 'dkasak/share-all-indices-with-own-trusted-devices' 2021-10-05 10:13:49 +02:00
Julian Sparber a3f078cb96 encryption: Expose FlowId on VerificationRequest
Fixes: https://github.com/matrix-org/matrix-rust-sdk/issues/367
2021-10-04 22:42:39 +02:00
Julian Sparber 82659142c5 crypto: Fix VerificationRequest::generate_qr_code()
We can't keep a lock on the `inner` therefore clone it. It's not pretty
but we do the same in `start_sas()`.
2021-10-04 17:04:09 +02:00
Denis Kasak 3c03c64778 docs(crypto): Reword.
- Bring the wording in line with the wording on the matrix_sdk crate.
- Style fixes.
- Formatting.
2021-10-04 14:53:30 +02:00
Denis Kasak fdbed7fbf8 docs(crypto): Add room key sharing decision tree to the docs. 2021-10-04 14:48:12 +02:00
Denis Kasak 759bc76f04 docs: More typo/style fixes. 2021-10-04 14:36:37 +02:00
Denis Kasak ab1657b811 docs: Flesh out intro section a bit.
- Mention subcrates.
- Point out `Client` as the central component.
2021-10-04 14:34:18 +02:00
Denis Kasak b219a347f6 Reword opening paragraph. 2021-10-04 13:15:22 +02:00
Denis Kasak bd82738630 Fix typo. 2021-10-04 13:06:50 +02:00
Amanda Graven 9829b45ce8 Specifiy edition in rustfmt.toml 2021-10-04 12:56:49 +02:00
Denis Kasak f2c0abeb58 Add decision tree rendering of the algorithm. 2021-10-04 12:51:16 +02:00
Denis Kasak 55731922e8 Add decision tree model of the key sharing algorithm.
And a tool to render it.

Signed-off-by: Denis Kasak <dkasak@termina.org.uk>
2021-10-04 12:49:16 +02:00
Denis Kasak 671efb2313 Await result. 2021-10-04 11:13:02 +02:00
Denis Kasak da052ed9aa clippy fix 2021-10-04 11:12:46 +02:00
Denis Kasak 49e722ffbf cargo fmt 2021-10-04 10:57:11 +02:00
Denis Kasak de2e2539b7 Write a test.
Signed-off-by: Denis Kasak <dkasak@termina.org.uk>
2021-10-04 10:51:31 +02:00
Denis Kasak 5f87ccdcd9 Explain return value in the docstring.
Signed-off-by: Denis Kasak <dkasak@termina.org.uk>
2021-10-04 10:51:31 +02:00
Denis Kasak bf2195b999 crypto: Share all indices with own trusted devices.
This fixes an edge case in the key sharing decision algorithm in which
your own trusted devices could be getting a limited session upon a
reshare. It also simplifies the algorithm a bit by bringing the check
for an own and trusted device to the start.

If the requesting device is a trusted/verified device of our own, we
share the session in full, regardless of whether we've previously shared
with that device and at which index. Otherwise, we do the "have we
shared previously" check via the outbound session and only share from
the index it was originally shared at, as before.

Signed-off-by: Denis Kasak <dkasak@termina.org.uk>
2021-10-04 10:45:25 +02:00
Damir Jelić 3042209cf6 crypto: Check that the event was encrypted for the right room 2021-09-21 17:27:31 +02:00
Damir Jelić 87728268e2 crypto: Don't borrow the plaintext to later clone it 2021-09-21 16:48:42 +02:00
Jonas Platte bbbd5648e0 Fix comment typos 2021-09-21 15:36:04 +02:00
Jonas Platte b813735dd2 Remove unused dev-dependency 2021-09-21 15:24:55 +02:00
Jonas Platte 871a245702 crypto: Avoid unnecessary event serialization 2021-09-21 15:20:02 +02:00
Jonas Platte f783fb9830 Fix typo: Missmatched => Mismatched 2021-09-21 15:19:21 +02:00
Damir Jelić fa5aea2ca1 Merge branch 'fix-anyhow-feature' 2021-09-21 14:54:40 +02:00
Jonas Platte 2128d0bfcc CI: Use Nightly Clippy 2021-09-21 13:12:46 +02:00
Jonas Platte 42061c9bf5 CI: Run clippy on more (Cargo) targets 2021-09-21 13:12:34 +02:00
Jonas Platte d0851c8a9e Fix new (Nightly) Clippy warnings 2021-09-21 13:11:53 +02:00
Jonas Platte 0817bc490e Add missing required-features for examples 2021-09-21 13:11:31 +02:00
Jonas Platte 3621b62418 Fix Client::register future not being Send under warp feature
Caused by https://github.com/tokio-rs/tracing/issues/1487.
2021-09-21 13:07:40 +02:00
Jonas Platte cbc0739041 Re-export anyhow and eyre features from matrix-sdk-appservice 2021-09-21 11:59:47 +02:00
Jonas Platte f752bded4b Add eyre feature to matrix-sdk 2021-09-21 11:59:47 +02:00
Jonas Platte 6cbb07bc2d Fix broken anyhow feature 2021-09-21 11:59:15 +02:00
Damir Jelić 4d048934e6 Merge branch 'master-rename' 2021-09-20 11:18:17 +02:00
Damir Jelić 544a66fa34 chore: Rename the master branch 2021-09-20 10:09:40 +02:00
Jonas Platte 533c86d285 Run event / notification handler callbacks in order 2021-09-17 20:46:32 +02:00
Damir Jelić 15e9d03c2c fix(sdk): Don't retry requests in the tests
Since now sync_once() sends out E2EE requests after the sync and our
tests only set up the `/sync` endpoint using mockito we're going to be
stuck in a retry loop trying to send out the mentioned requests.

It's fine to disable request retrying and let those requests fail.
2021-09-17 20:19:13 +02:00
Damir Jelić ef3f827769 docs(sdk): Fix a typo 2021-09-17 20:18:42 +02:00
Damir Jelić d34b83851f feat(sdk): Add a getter for the Session 2021-09-17 20:18:17 +02:00
Damir Jelić 61eefbbadd docs(sdk): Fix some doc links. 2021-09-17 11:10:18 +02:00
Damir Jelić 544d15c574 docs(sdk): Improve a bunch of Client docs 2021-09-17 11:10:18 +02:00
Damir Jelić 8ed06883f6 fix(sdk): Don't take ownership of the user id when logging in using SSO 2021-09-17 11:10:18 +02:00
Damir Jelić 39edd32072 feat(sdk): Add a method to sync as an async stream 2021-09-17 10:54:20 +02:00
Damir Jelić 051d935b28 docs(sdk): Add better docs and examples to the sync methods 2021-09-17 10:54:20 +02:00
Damir Jelić 37904007bb feat(sdk): Send the outgoing E2EE requests out concurrently 2021-09-16 15:43:50 +02:00
Damir Jelić 3dc9f78051 fix(sdk): Move the crypto plumbing in the sync to the sync_once method
This would allow people to avoid the `sync()` method and let them drive
their own syncs.

Until now using `sync()` only would mean that the crypto requests would
never have been sent out.
2021-09-16 14:36:16 +02:00
Damir Jelić 729a29352b chore(sdk): Move the crypto plumbing of the sync into a separate method 2021-09-16 14:14:37 +02:00
Damir Jelić 626f4b92b5 chore(sdk): Remove some unwraps 2021-09-16 14:06:44 +02:00
Damir Jelić fa6230a08a fix(sdk): Use a better variable name for the file when uploading 2021-09-15 22:08:45 +02:00
Damir Jelić 866ab33c45 chore: Remove some unneeded clippy silences 2021-09-15 20:48:15 +02:00
Damir Jelić 7764f01b59 fix(crypto): Only send cancellations if there were multiple request recipients 2021-09-15 20:28:16 +02:00
Damir Jelić ff9bb94ab4 docs(sdk): Simplify the event sending examples 2021-09-15 20:27:36 +02:00
Damir Jelić 28412344d5 docs(sdk): Fix the link to the examples dir 2021-09-15 14:20:14 +02:00
Damir Jelić bae6b33497 feat(sdk): Add the ability to send out custom message events 2021-09-15 14:20:14 +02:00
Damir Jelić 7a21bdd573 docs(sdk): Fix a small typo 2021-09-15 10:36:58 +02:00
Damir Jelić 43011261a8 fix(sdk): Remove the room_send method from the Client
This method is a bit dangerous if the room is encrypted, e.g. people can
send events before the room state has been fetched and thus accidentally
send out unencrypted events in an encrypted room.
2021-09-15 10:36:58 +02:00
Damir Jelić d8b60dfe55 feat(sdk): Add support to send out custom state events 2021-09-14 23:36:09 +02:00
Damir Jelić 70ab0f446d chore: Sort the deps in our Cargo.toml files 2021-09-14 16:38:33 +02:00
Damir Jelić af74988a83 chore: Rename the crate folders to use dashes instead of underscores 2021-09-14 16:38:33 +02:00
Damir Jelić 31b7063e68 docs(sdk): Remove unwraps from the joined room doc examples 2021-09-14 16:38:33 +02:00
Damir Jelić f42883eaad docs(sdk): Remove some unwraps from the encryption doc examples 2021-09-14 16:38:33 +02:00
Damir Jelić 7de782d3a2 chore(sdk): Move the various config structs into its own module 2021-09-14 16:38:33 +02:00
Damir Jelić cf26557cc2 chore(sdk): Move the sso related imports into the sso login method 2021-09-14 13:20:03 +02:00
Damir Jelić 29d11db73a chore(sdk): Move the e2ee related client methods to the encryption module 2021-09-14 13:10:22 +02:00
Damir Jelić e8c5b0766e chore(sdk): Move all the crypto related module under an encryption module 2021-09-14 12:32:59 +02:00
Damir Jelić 041ef66c01 chore: Move the crates into a subfolder 2021-09-14 11:59:21 +02:00
Damir Jelić b3bbcd1729 chore: Set a rust version in our crates 2021-09-14 10:25:04 +02:00
Damir Jelić 69ccc5a9f9 chore(sdk): Bump the version
CI / Run clippy (push) Has been skipped
CI / linux / WASM (push) Has been skipped
CI / linux / appservice / stable / warp (push) Has been skipped
CI / macOS / appservice / stable / warp (push) Has been skipped
CI / linux / features-markdown (push) Has been skipped
CI / linux / features-socks (push) Has been skipped
CI / linux / features-sso_login (push) Has been skipped
CI / linux / features-no-sled (push) Has been skipped
CI / linux / features-sled_cryptostore (push) Has been skipped
CI / linux / features-no-encryption-and-sled (push) Has been skipped
CI / linux / features-require_auth_for_profile_requests (push) Has been skipped
CI / linux / features-no-encryption (push) Has been skipped
CI / linux / features-rustls-tls (push) Has been skipped
CI / linux / beta (push) Has been skipped
CI / linux / stable (push) Has been skipped
CI / macOS / stable (push) Has been skipped
CI / Check style (push) Failing after 38s
2021-09-13 11:49:39 +02:00
Damir Jelić f9f83eaa39 chore(base): Bump the version 2021-09-13 11:49:39 +02:00
Damir Jelić f243a684d4 chore(crypto): Bump the version 2021-09-13 11:49:39 +02:00
Damir Jelić a82de88963 chore(common): Bump the version 2021-09-13 11:49:39 +02:00
Damir Jelić 97e15feb0d Merge branch 'fix-sdk-common-dep-feature' 2021-09-13 11:47:20 +02:00
Antoine Martin 51072a5dab fix(common): wasm_bindgen dependency feature
instant doesn't need wasm_bindgen on non wasm targets
2021-09-13 11:01:05 +02:00
Damir Jelić 500bb6e940 fix(sdk): Test that invited member events get emitted 2021-09-13 11:00:24 +02:00
Jonas Platte 140630745f Fix confusion between initial / stripped state events
InviteState contains stripped state events, and initial state events are
not used anywhere in the sync response.
2021-09-13 11:00:24 +02:00
Damir Jelić 1ea9c9a915 fix(base): Allow the presence of a room member to be dead for now 2021-09-13 10:18:45 +02:00
Damir Jelić b8001b78b4 fix(crypto): Fix some clippy warnings 2021-09-13 10:18:23 +02:00
Damir Jelić a6916dd9dd chore(sdk): Bump the version
CI / Check style (push) Failing after 38s
CI / Run clippy (push) Has been skipped
CI / linux / WASM (push) Has been skipped
CI / linux / appservice / stable / warp (push) Has been skipped
CI / macOS / appservice / stable / warp (push) Has been skipped
CI / linux / features-markdown (push) Has been skipped
CI / linux / features-socks (push) Has been skipped
CI / linux / features-sso_login (push) Has been skipped
CI / linux / features-no-sled (push) Has been skipped
CI / linux / features-sled_cryptostore (push) Has been skipped
CI / linux / features-no-encryption-and-sled (push) Has been skipped
CI / linux / features-require_auth_for_profile_requests (push) Has been skipped
CI / linux / features-no-encryption (push) Has been skipped
CI / linux / features-rustls-tls (push) Has been skipped
CI / linux / beta (push) Has been skipped
CI / linux / stable (push) Has been skipped
CI / macOS / stable (push) Has been skipped
2021-09-10 21:41:37 +02:00
Damir Jelić b96624890e Merge branch 'event-handler-encryption-info' 2021-09-10 21:36:16 +02:00
Damir Jelić 7e9090399b chore(qrcode): Bump the version
CI / Run clippy (push) Has been skipped
CI / linux / WASM (push) Has been skipped
CI / linux / appservice / stable / warp (push) Has been skipped
CI / macOS / appservice / stable / warp (push) Has been skipped
CI / linux / features-markdown (push) Has been skipped
CI / linux / features-socks (push) Has been skipped
CI / linux / features-sso_login (push) Has been skipped
CI / linux / features-no-sled (push) Has been skipped
CI / linux / features-sled_cryptostore (push) Has been skipped
CI / linux / features-no-encryption-and-sled (push) Has been skipped
CI / linux / features-require_auth_for_profile_requests (push) Has been skipped
CI / linux / features-no-encryption (push) Has been skipped
CI / linux / features-rustls-tls (push) Has been skipped
CI / linux / beta (push) Has been skipped
CI / linux / stable (push) Has been skipped
CI / macOS / stable (push) Has been skipped
CI / Check style (push) Failing after 34s
2021-09-10 20:45:17 +02:00
Damir Jelić 9c53c478d9 chore(base): Bump the version 2021-09-10 19:54:58 +02:00
Damir Jelić e0447c8190 chore(crypto): Bump the version 2021-09-10 19:28:13 +02:00
Damir Jelić 4bcbcb146e Merge branch 'feature/qrcode-feature' 2021-09-10 19:20:08 +02:00
Damir Jelić ae0f4c4cc5 docs(sdk): Add some missing hints for the qrcode feature 2021-09-10 17:41:33 +02:00
Damir Jelić 40b465a093 chore(test): Bump the version
CI / Check style (push) Failing after 41s
CI / Run clippy (push) Has been skipped
CI / linux / WASM (push) Has been skipped
CI / linux / appservice / stable / warp (push) Has been skipped
CI / macOS / appservice / stable / warp (push) Has been skipped
CI / linux / features-markdown (push) Has been skipped
CI / linux / features-socks (push) Has been skipped
CI / linux / features-sso_login (push) Has been skipped
CI / linux / features-no-sled (push) Has been skipped
CI / linux / features-sled_cryptostore (push) Has been skipped
CI / linux / features-no-encryption-and-sled (push) Has been skipped
CI / linux / features-require_auth_for_profile_requests (push) Has been skipped
CI / linux / features-no-encryption (push) Has been skipped
CI / linux / features-rustls-tls (push) Has been skipped
CI / linux / beta (push) Has been skipped
CI / linux / stable (push) Has been skipped
CI / macOS / stable (push) Has been skipped
2021-09-10 17:23:43 +02:00
Damir Jelić a4de38ce28 chore(common): Bump the version
CI / Check style (push) Failing after 32s
CI / Run clippy (push) Has been skipped
CI / linux / WASM (push) Has been skipped
CI / linux / appservice / stable / warp (push) Has been skipped
CI / macOS / appservice / stable / warp (push) Has been skipped
CI / linux / features-markdown (push) Has been skipped
CI / linux / features-socks (push) Has been skipped
CI / linux / features-sso_login (push) Has been skipped
CI / linux / features-no-sled (push) Has been skipped
CI / linux / features-sled_cryptostore (push) Has been skipped
CI / linux / features-no-encryption-and-sled (push) Has been skipped
CI / linux / features-require_auth_for_profile_requests (push) Has been skipped
CI / linux / features-no-encryption (push) Has been skipped
CI / linux / features-rustls-tls (push) Has been skipped
CI / linux / beta (push) Has been skipped
CI / linux / stable (push) Has been skipped
CI / macOS / stable (push) Has been skipped
2021-09-10 17:23:43 +02:00
Jonas Platte d6d51ef4b1 Show Option<EncryptionInfo> event handler context in doc example 2021-09-10 17:12:17 +02:00
Damir Jelić 92b0ba21e4 docs(common): Use the readme for the crate level docs 2021-09-10 16:41:50 +02:00
Alexander Sieg 82a99b5267 address code review issues 2021-09-10 16:26:21 +02:00
Alexander Sieg 349e3cae06 Merge remote-tracking branch 'origin/master' into feature/qrcode-feature 2021-09-10 16:00:41 +02:00
Damir Jelić 48b3307934 chore: Bump our deps 2021-09-10 10:08:48 +02:00
Jonas Platte 24253128ae Add support for Option<EncryptionInfo> as event handler context 2021-09-09 21:03:01 +02:00
Damir Jelić 018544b775 fix(crypto): Remove some dead code 2021-09-09 20:57:58 +02:00
Damir Jelić 44dcd1abdf docs(crypto): Improve the docs and use the readme for the crate docs 2021-09-09 20:57:58 +02:00
Damir Jelić 9c62908162 docs(base): Use the readme for the crate docs 2021-09-09 20:57:58 +02:00
Damir Jelić 913cb39d28 docs(sdk): Add an example that attaches data to an event handler 2021-09-09 20:57:58 +02:00
Damir Jelić 804a941762 docs(rust): Run the register event handler doc example 2021-09-09 20:57:58 +02:00
Damir Jelić a7b83d9cd1 docs(sdk): Improve the docs docs and use the readme for the crate docs 2021-09-09 20:57:58 +02:00
Damir Jelić 924405270a fix(sdk): Use the markdown feature flag of ruma dirrectly 2021-09-09 20:57:58 +02:00
Damir Jelić 4c8412f4a1 docs(qrcode): Use the readme for the crate docs 2021-09-09 20:57:58 +02:00
Jonas Platte 8f46a87f52 Inline handle_sync_events_wrapped
It was only used in one place.
2021-09-09 20:44:25 +02:00
Alexander Sieg c47ac8d6b1 Merge remote-tracking branch 'origin/master' into feature/qrcode-feature 2021-09-09 15:10:18 +02:00
Alexander Sieg 3f09a6abdd fix clippy warnings 2021-09-09 15:05:57 +02:00
Damir Jelić b94faa3121 feat(crypto): Document our crypto benchmarks 2021-09-09 13:41:28 +02:00
Damir Jelić 56a30b3a02 chore(crypto): Bump the pprof version and remove our custom profiler 2021-09-09 13:35:43 +02:00
Damir Jelić ed198a22b6 Merge branch 'custom-store' 2021-09-09 12:24:27 +02:00
Damir Jelić 13b97f6dba fix(base): Remove an unnecessary unwrap from a test 2021-09-09 12:24:15 +02:00
Damir Jelić b09b667782 fix(base): Flush when we're saving custom stuff in the sled store 2021-09-09 11:55:05 +02:00
Damir Jelić 85fde6796a fix(sdk): Remove the custom storage methods from the Client 2021-09-09 11:54:08 +02:00
Damir Jelić db1efcd1fc feat(sdk): Expose the cross signing user identities
This patch adds support to fetch cross signing user identities from the
crypto store, those can now be used to request verifications and inspect
the master keys of users.
2021-09-09 10:40:36 +02:00
Damir Jelić f80e4b3f06 feat(sdk): Add a way to wait for a sync to be done 2021-09-09 10:31:35 +02:00
Damir Jelić 5049e8bfbe docs(sdk): Linkify some verification struct docs 2021-09-09 10:31:35 +02:00
Damir Jelić 6e4a57046e fix(sdk): Use a pure HTTP error for methods that don't touch local state 2021-09-09 10:30:46 +02:00
Damir Jelić afc8597d3b fixup! feat(sdk): Expose the list of tracked users publicly 2021-09-09 10:27:59 +02:00
Damir Jelić 5ff69ad1a9 fix(base): Mark rooms as DMs when we receive an m.direct event 2021-09-09 10:21:05 +02:00
Damir Jelić 05663a42ed feat(sdk): Add a method to check the status of our private cross signing keys 2021-09-09 10:21:05 +02:00
Damir Jelić 7c2b6ede1f feat(crypto): Expose the master pubkey struct publicly 2021-09-09 10:21:05 +02:00
Damir Jelić c6100404e5 feat(sdk): Expose the list of tracked users publicly 2021-09-09 10:20:50 +02:00
Alexander Sieg df65081785 run nightly rustfmt 2021-09-09 10:15:14 +02:00
Damir Jelić 1bcc74738e feat(sdk): Add a method to check if a room contains only verified devices 2021-09-09 10:13:00 +02:00
Damir Jelić 0e9a1b42ec Merge branch 'new-event-handler' 2021-09-09 10:07:02 +02:00
Jonas Platte c3081de611 Add async context to register_event_handler doctest 2021-09-09 00:49:04 +02:00
Jonas Platte 97731d1240 Add a test for register_event_handler 2021-09-08 23:34:05 +02:00
Jonas Platte e2432d476e Add Client::register_notification_handler
It had been planned but forgotten.
2021-09-08 23:34:05 +02:00
Jonas Platte 6e571c579d Allow chaining .register_event_handler() 2021-09-08 23:34:05 +02:00
Jonas Platte 8c499a63dc Add missing .awaits in event handler doctests 2021-09-08 23:34:01 +02:00
Jonas Platte ce0cb273bb Use matrix_sdk_common::executor::spawn instead of tokio::spawn 2021-09-08 21:08:23 +02:00
Jonas Platte 971cdf37f6 Fix doctest imports 2021-09-08 20:45:40 +02:00
Jonas Platte 699039f788 Better document event context argument restrictions 2021-09-08 20:40:26 +02:00
Jonas Platte c3e25bda1a Run event / notification handlers in separate async tasks
Prevents deadlocks when new handlers are registered from within an
existing handler.
2021-09-08 20:32:06 +02:00
Jonas Platte 606a57203e Add some documentation about how the event handler abstraction works 2021-09-08 20:29:09 +02:00
Jonas Platte 3c38b26770 Rewrap doc comments 2021-09-08 20:19:07 +02:00
Jonas Platte 67912f3768 Fix / improve event handler documentation 2021-09-08 19:23:19 +02:00
Jonas Platte bf8945430f Fix Copyright header 2021-09-08 19:23:03 +02:00
Jonas Platte cb33f26d5c Log room retrieval failure in Client::process_sync 2021-09-08 19:22:54 +02:00
Jonas Platte ddea1bdb9e Rewrap crate feature flag docs 2021-09-08 19:12:58 +02:00
Alexander Sieg 9b90175500 matrix_sdk: add encryption to qrcode feature 2021-09-08 17:46:26 +02:00
Alexander Sieg 44f6e7a0cf matrix_sdk: remove compile_error for qrcode feature 2021-09-08 17:31:06 +02:00
Alexander Sieg 55692802c0 crypto: feature-gate dependency on matrix_qrcode 2021-09-08 17:23:10 +02:00
Amanda Graven 5be7bb980d Add custom storage
Add an additional tree to the Store where custom api consumer data may
be stored.
2021-08-25 11:39:43 +02:00
Johannes Becker 33c49c5cd8 appservice: Re-export sdk features 2021-08-17 20:17:17 +02:00
Jonas Platte d348e77468 Remove extraneous space 2021-08-17 00:32:24 +02:00
Jonas Platte a5ff4fbef7 Simplify struct initializations by using Default::default 2021-08-17 00:32:23 +02:00
Jonas Platte cfa69e74f4 Delete unused file 2021-08-17 00:26:02 +02:00
Jonas Platte 36ceb66ba5 Remove prev_content compat hacks
This is now handled by Ruma.
2021-08-17 00:26:01 +02:00
Jonas Platte 2fdad12521 Rewrite event handler abstraction 2021-08-17 00:26:01 +02:00
Damir Jelić 623408913c Merge branch 'secret-sharing' 2021-08-13 20:38:31 +02:00
Damir Jelić 9bae87b0ac crypto: Fix some clippy warnings 2021-08-13 18:28:52 +02:00
Damir Jelić 00e11d33f1 crypto: Fix user-signing signature uploads 2021-08-13 18:28:52 +02:00
Damir Jelić 680f77beb9 crypto: Add the master key to the SAS MAC if we trust it 2021-08-13 18:28:52 +02:00
Damir Jelić 356506060c crypto: Remove private cross signing keys if we detect that they changed 2021-08-13 18:28:52 +02:00
Damir Jelić 4e9fe79619 crypto: Start remembering if an inbound group session has been backed up 2021-08-13 18:28:52 +02:00
Damir Jelić e4a9cf0bba crypto: Disallow re-sharing room keys with devices with changed curve keys 2021-08-13 18:28:52 +02:00
Damir Jelić f9de77a75d crypto: Make sure we request secrets only if the user became trusted 2021-08-13 18:28:52 +02:00
Damir Jelić 315e77ebf2 crypto: Add the users for key claiming to the outgoing requests
This makes sure that we immediately claim one-time keys after we
receive the sync changes instead of waiting for a room message to be
sent by the user.

Users may not send a message in a long time which would mean that we'll
likely never share secrets or forward room keys if a Olm session was
missing with the requester.
2021-08-13 18:28:52 +02:00
Damir Jelić da82fbab4f crypto: Connect the responding to secret request logic 2021-08-13 18:28:52 +02:00
Damir Jelić 4f46212d1a crypto: Add a method to manually verify our own user identity 2021-08-13 18:28:52 +02:00
Damir Jelić d4fe6f5133 crypto: Add methods to manually verify devices and users 2021-08-13 18:28:52 +02:00
Damir Jelić ee838087ca crypto: Add methods to export/import cross signing keys 2021-08-13 18:28:52 +02:00
Damir Jelić b540b8df62 crypto: Add a method to check the state of our private cross signing keys 2021-08-13 18:28:52 +02:00
Damir Jelić 1157594530 crypto: Add a method to check if a user identity is verified 2021-08-13 18:28:52 +02:00
Damir Jelić 8d7fe5e575 crypto: Add a method to check if our own device has been signed by our identity 2021-08-13 18:28:52 +02:00
Damir Jelić 0598bdebc7 crypto: Store our own device we receive from the server 2021-08-13 18:28:52 +02:00
Damir Jelić 7d851a10b5 crypto: Collect common verification stuff into a VerificationStore 2021-08-13 18:28:52 +02:00
Damir Jelić e401c87246 crypto: When we check the signature of a device use the DeviceKeys struct 2021-08-13 18:28:52 +02:00
Damir Jelić 2cf6ad21d3 crypto: Refactor and split out the gossiping logic 2021-08-13 18:28:52 +02:00
Damir Jelić adca302dfe crypto: Fix some clippy warnings 2021-08-13 18:28:52 +02:00
Damir Jelić 68df9b6ed2 crypto: Allow secrets to be requested and imported 2021-08-13 18:28:52 +02:00
Damir Jelić e57d70b089 crypto: Use the correct pickle key when unpickling cross signing keys 2021-08-13 18:28:52 +02:00
Damir Jelić 5f1e972b3d crypto: Properly mark verification requests as done 2021-08-13 18:28:52 +02:00
Damir Jelić 3726492cf9 crypto: Improve some log lines 2021-08-13 18:28:52 +02:00
Damir Jelić bc8c2752e4 crypto: Store newly created Olm sessions immediately
This fixes a bug where we would try to create a new Olm session, even if
we already created one, because we didn't yet add the new one to the
store.

This would be triggered every time two or more Olm pre-key messages
arrive that don't yet have an Olm session. This leads to decryption
failures for every message that arrived in the same sync after the
first one which created the new Olm session.
2021-08-13 18:28:52 +02:00
Damir Jelić d27a08bc91 crypto: Fix a comment in the attachment encryption logic 2021-08-13 18:28:52 +02:00
Damir Jelić 5192feb836 crypto: Add support to request secrets 2021-08-13 18:28:52 +02:00
Damir Jelić a916288d03 crypto: Support responding to secret requests 2021-08-13 18:28:52 +02:00
Damir Jelić 96e26651bc crypto: Bump the olm-rs version 2021-08-13 14:07:37 +02:00
Damir Jelić 725fd817c2 Merge branch 'ruma-0.3' 2021-08-12 15:22:21 +02:00
Damir Jelić 79dd53639b Merge branch 'set-tag' 2021-08-12 15:06:26 +02:00
Jonas Platte 578ddd2698 Upgrade to ruma 0.3.0 2021-08-12 10:41:20 +02:00
Emelie e175ab79c7 matrix-sdk: Add helpers for room tags 2021-08-09 17:01:48 +02:00
Johannes Becker 937d0aca79 appservice: Support appservice located on sub path 2021-08-09 14:35:26 +02:00
stoically 0bd438e617 Fix clippy warnings 2021-08-05 22:48:05 +02:00
Damir Jelić 1fd1570e07 Merge branch 'wip/haeckerfelix/room-event' 2021-07-29 09:37:31 +02:00
Felix Häcker 91e9a5f9f3 Add new RoomEvent type, try to decrypt event 2021-07-28 19:49:41 +02:00
Damir Jelić aa5f532f86 Merge branch 'master' into room-state-getters 2021-07-27 11:18:29 +02:00
Damir Jelić c499d2e465 matris-sdk: Test getting state events out of the store 2021-07-27 10:22:11 +02:00
Damir Jelić 3d734a120d Merge branch 'hoist-deserialize-fix' 2021-07-26 16:16:08 +02:00
Damir Jelić 05eeba067c base: Add docs to the newly public hoist and deserialize method 2021-07-26 15:58:18 +02:00
Damir Jelić 778867e3ef crypto: Test that edits get properly decrypted 2021-07-26 15:28:17 +02:00
Damir Jelić 4432be48e0 crypto: Fix a broken doc link 2021-07-26 11:47:53 +02:00
Felix Häcker f3620e7072 room: Add event() method to retrieve a room event 2021-07-25 20:51:46 +02:00
Damir Jelić 46f9c292ab crypto: Streamline how we update one-time key counts
There is no reason to use different logic when updating one-time key
counts coming from an upload response vs when coming from a sync
response.

Switch to an AtomicU64 for the count as well, the i64 is probably a
remnant of the SQLite based crypto store.
2021-07-22 16:06:10 +02:00
Damir Jelić e919a82b2c Merge branch 'verification-improvements' 2021-07-19 14:31:31 +02:00
Damir Jelić 3a8ff2f6b4 matrix-sdk: Allow the key import error to be dead under WASM 2021-07-19 11:19:14 +02:00
Damir Jelić 26310def0a crypto: Silence a couple of clippy warnings 2021-07-19 10:49:22 +02:00
Damir Jelić 24377a45ff matrix-sdk: Add methods to request verification for devices 2021-07-19 10:34:34 +02:00
Damir Jelić 5566886f20 crypto: Add public methods to request verifications with devices 2021-07-19 10:26:39 +02:00
Damir Jelić 8f03679935 matrix-sdk: Add more getters to the high level verification structs 2021-07-19 09:59:08 +02:00
Damir Jelić 0053d2a874 crypto: Don't send cancellations for passive verification requests 2021-07-19 09:48:22 +02:00
Damir Jelić 55a9e6836d crypto: Introduce a CancelInfo struct
This replaces the separate methods to fetch info about the cancellation.
It was a bit annoying to gather all the different info where each method
can return None.
2021-07-19 09:45:47 +02:00
Damir Jelić cf30c42563 crypto: Correctly remember our chosen SAS methods 2021-07-19 09:43:35 +02:00
Damir Jelić ff8089912e crypto: Only send cancellations to other devices if we're the requester 2021-07-19 09:36:21 +02:00
Damir Jelić 909cd42ac1 crypto: Cancel the verification request for to-device Sas verifications 2021-07-19 09:32:48 +02:00
Damir Jelić 7433003ffa matrix-sdk: Don't panic when importing invalid key exports 2021-07-19 09:21:28 +02:00
Damir Jelić ead91a1e6b crypto: Send cancellations if the other device picks up over to-device 2021-07-12 18:12:02 +02:00
Damir Jelić b53518d1b8 crypto: Improve a log line 2021-07-09 17:13:15 +02:00
Damir Jelić 71c89c2670 crypto: Time out verification requests as well 2021-07-09 17:01:35 +02:00
Damir Jelić cca73b2622 crypto: Update the SAS event timeout when we receive events 2021-07-09 16:13:30 +02:00
Damir Jelić 7644ceea8a crypto: Make sure we don't deadlock when we cancel the verification request 2021-07-09 14:31:54 +02:00
Damir Jelić b0e8f12426 crypto: Cancel the verification request if the child flow gets cancelled 2021-07-09 13:53:47 +02:00
Damir Jelić 4e5cc03673 crypto: Only go into a done verification request if we're in the correct state 2021-07-09 11:50:12 +02:00
Damir Jelić 76d57baa11 crypto: Add the verification to the cache after we scan a QR code 2021-07-09 11:49:46 +02:00
Damir Jelić 5c9840daf8 crypto: Return a request when we start QR code verification instead of the content 2021-07-09 11:39:25 +02:00
Damir Jelić ae37e6ec9d crypto: Add a state getter where we scanned the QR code 2021-07-09 11:38:10 +02:00
Damir Jelić c5df7c5356 crypto: Add methods to request verification from users 2021-07-08 12:30:30 +02:00
Sorunome 27ad1f42da use hoist_and_deserialize for state events 2021-07-04 08:42:59 +02:00
Jonas Platte 69225ad00b Use rustdoc-map to link to external crates in master docs 2021-07-02 18:05:34 +02:00
Damir Jelić db0843a47a crypto: Don't panic if we don't have the keys to generate a QR code 2021-07-01 10:27:45 +02:00
Damir Jelić 9052843acb crypto: Add another SAS state so we know when both parties accepted 2021-06-29 12:56:28 +02:00
Damir Jelić 113587247e crypto: Notify our users that a verification timed out on our end 2021-06-29 12:56:28 +02:00
Damir Jelić ee6b804804 crypto: Allow QR code verifications to get into the cancelled state as well. 2021-06-29 12:56:28 +02:00
Damir Jelić 63659c9604 crypto: Fix verification requests getting cancelled 2021-06-29 12:56:28 +02:00
Damir Jelić 100a936f1b crypto: Add a method to check if the scanning has been confirmed 2021-06-29 12:56:28 +02:00
Damir Jelić 80a30bcdd6 crypto: Add all the common accessors to the qr code verification 2021-06-29 12:56:28 +02:00
Damir Jelić 728d298810 crypto: Add a getter for the room id for the SAS verifications 2021-06-29 12:56:28 +02:00
Damir Jelić af084528c8 crypto: Remember who cancelled the verification
This seems to be of limited use considering that people can just see the
sender of the cancellation event or they perform the cancellation
themselves using the cancel() method but EA seems to want this.
2021-06-29 12:56:28 +02:00
Damir Jelić d4e80883dc crypto: Propagate the we_started info to the SAS verification 2021-06-29 12:56:28 +02:00
Damir Jelić 55690ddd54 crypto: Allow canceling a SAS verification with a specific cancel code 2021-06-29 12:56:28 +02:00
Damir Jelić 9a685d685c crypto: Add a couple more getters for the SAS verification 2021-06-29 12:56:28 +02:00
Damir Jelić c78406ceb9 crypto: Clean up the method to check if a device is verified. 2021-06-29 12:56:28 +02:00
Johannes Becker f454d407af appservice: Drop actix 2021-06-29 12:16:48 +02:00
Jonas Platte df71de5af2 crypto: Store key::verification::start::SasV1Content
… instead of SasV1ContentInit
2021-06-25 12:04:20 +02:00
Jonas Platte 52fd551890 appservice: Reexport ruma entirely 2021-06-23 16:12:23 +02:00
Jonas Platte 4d5768111d Simplify ruma identifier imports 2021-06-23 16:12:23 +02:00
Jonas Platte aabda60e9f Fix unused import warnings for wasm 2021-06-23 16:12:22 +02:00
Jonas Platte 089ab20e7c Re-format wasm_command_bot 2021-06-23 16:12:22 +02:00
Jonas Platte 6e29251886 Remove matrix_sdk_base::Error re-export
It's not part of the public API.
2021-06-23 16:12:22 +02:00
Jonas Platte 4a7010bab1 Reexport independent external crates entirely
… instead of reexporting individual items.
2021-06-23 16:12:22 +02:00
Jonas Platte b181125e6f Remove nesting of matrix_sdk_base::Error in matrix_sdk::Error
There is no useful distinction between the same error variants on
matrix_sdk::Error directly vs matrix_sdk::MatrixError.
2021-06-23 12:50:37 +02:00
Jonas Platte c4e4830f32 Add missing doc(cfg) attrs 2021-06-23 11:52:19 +02:00
Fisher Darling 4cc7237db3 remove getting every state event and add getters to room 2021-06-17 23:34:26 -06:00
Fisher Darling cb6269d5ec add more state event getters to store 2021-06-14 20:59:53 -06:00
369 changed files with 60012 additions and 25972 deletions
+41
View File
@@ -0,0 +1,41 @@
# Pass the rustflags specified to host dependencies (build scripts, proc-macros)
# when a `--target` is passed to Cargo. Historically this was not the case, and
# because of that, cross-compilation would not set the rustflags configured
# below in `target.'cfg(all())'` for them, resulting in cache invalidation.
#
# Since this is an unstable feature (enabled at the bottom of the file), this
# setting is unfortunately ignored on stable toolchains, but it's still better
# to have it apply on nightly than using the old behavior for all toolchains.
target-applies-to-host = false
[alias]
xtask = "run --package xtask --"
[doc.extern-map.registries]
crates-io = "https://docs.rs/"
[target.'cfg(all())']
rustflags = [
"-Wrust_2018_idioms",
"-Wsemicolon_in_expressions_from_macros",
"-Wunused_extern_crates",
"-Wunused_import_braces",
"-Wunused_qualifications",
"-Wtrivial_casts",
"-Wtrivial_numeric_casts",
"-Wclippy::cloned_instead_of_copied",
"-Wclippy::dbg_macro",
"-Wclippy::inefficient_to_string",
"-Wclippy::macro_use_imports",
"-Wclippy::mut_mut",
"-Wclippy::needless_borrow",
"-Wclippy::nonstandard_macro_braces",
"-Wclippy::str_to_string",
"-Wclippy::todo",
]
# activate the target-applies-to-host feature.
# Required for `target-applies-to-host` at the top to take effect.
[unstable]
rustdoc-map = true
target-applies-to-host = true
+54
View File
@@ -0,0 +1,54 @@
name: AppService
on:
push:
branches: [main]
pull_request:
branches: [main]
types:
- opened
- reopened
- synchronize
- ready_for_review
env:
CARGO_TERM_COLOR: always
jobs:
test-appservice:
if: github.event_name == 'push' || !github.event.pull_request.draft
name: ${{ matrix.os-name }} [m]-appservice
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
include:
- os: ubuntu-latest
os-name: 🐧
- os: macos-latest
os-name: 🍏
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Load cache
uses: Swatinem/rust-cache@v1
- name: Install nextest
uses: taiki-e/install-action@nextest
- name: Run checks
uses: actions-rs/cargo@v1
with:
command: run
args: -p xtask -- ci test-appservice
+13
View File
@@ -0,0 +1,13 @@
name: Security audit
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions-rs/audit-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
+56
View File
@@ -0,0 +1,56 @@
name: Benchmarks
on:
workflow_dispatch:
jobs:
benchmarks:
name: Run Benchmarks
runs-on: ubuntu-latest
environment: matrix-rust-bot
if: github.event_name == 'push' || !github.event.pull_request.draft
steps:
- name: Checkout the repo
uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
components: rustfmt
profile: minimal
override: true
- name: Run Benchmarks
run: cargo bench | tee benchmark-output.txt
- name: Check benchmark result for PR
if: github.event_name == 'pull_request'
uses: benchmark-action/github-action-benchmark@v1
with:
name: Rust Benchmark
tool: 'cargo'
output-file-path: benchmark-output.txt
auto-push: false
# comment to alert the user this has gone bad
github-token: ${{ secrets.MRB_ACCESS_TOKEN }}
alert-threshold: '120%'
comment-on-alert: true
fail-threshold: '150%'
fail-on-alert: true
- name: Store benchmark result
if: github.event_name != 'pull_request'
uses: benchmark-action/github-action-benchmark@v1
with:
name: Rust Benchmark
tool: 'cargo'
output-file-path: benchmark-output.txt
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: true
# Show alert with commit comment on detecting possible performance regression
alert-threshold: '150%'
comment-on-alert: true
fail-on-alert: true
alert-comment-cc-users: '@gnunicornBen,@jplatte,@poljar'
+173
View File
@@ -0,0 +1,173 @@
name: Bindings tests
on:
workflow_dispatch:
push:
branches: [main]
pull_request:
branches: [main]
types:
- opened
- reopened
- synchronize
- ready_for_review
env:
CARGO_TERM_COLOR: always
MATRIX_SDK_CRYPTO_NODEJS_PATH: bindings/matrix-sdk-crypto-nodejs
MATRIX_SDK_CRYPTO_JS_PATH: bindings/matrix-sdk-crypto-js
jobs:
test-matrix-sdk-crypto-nodejs:
name: ${{ matrix.os-name }} [m]-crypto-nodejs, v${{ matrix.node-version }}
if: github.event_name == 'push' || !github.event.pull_request.draft
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
os: [ubuntu-latest, macos-latest]
node-version: [14.0, 16.0, 18.0]
include:
- os: ubuntu-latest
os-name: 🐧
- os: macos-latest
os-name: 🍏
- node-version: 18.0
build-doc: true
steps:
- name: Checkout the repo
uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Load cache
uses: Swatinem/rust-cache@v1
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: Install NPM dependencies
working-directory: ${{ env.MATRIX_SDK_CRYPTO_NODEJS_PATH }}
run: npm install
- name: Build the Node.js binding
working-directory: ${{ env.MATRIX_SDK_CRYPTO_NODEJS_PATH }}
run: npm run release-build
- name: Test the Node.js binding
working-directory: ${{ env.MATRIX_SDK_CRYPTO_NODEJS_PATH }}
run: npm run test
# Building in dev-mode and copy lib in failure case
- name: Build the Node.js binding in non-release
if: failure()
working-directory: ${{ env.MATRIX_SDK_CRYPTO_NODEJS_PATH }}
run: |
cp *.node release-mode-lib.node
npm run build
- uses: actions/upload-artifact@v3
if: failure()
with:
name: Failure Files
path: |
bindings/matrix-sdk-crypto-nodejs/*.node
/var/crash/*.crash
- if: ${{ matrix.build-doc }}
name: Build the documentation
working-directory: ${{ env.MATRIX_SDK_CRYPTO_NODEJS_PATH }}
run: npm run doc
test-matrix-sdk-crypto-js:
name: 🕸 [m]-crypto-js
if: github.event_name == 'push' || !github.event.pull_request.draft
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: wasm32-unknown-unknown
profile: minimal
override: true
- name: Load cache
uses: Swatinem/rust-cache@v1
- name: Install Node.js
uses: actions/setup-node@v3
- name: Install NPM dependencies
working-directory: ${{ env.MATRIX_SDK_CRYPTO_JS_PATH }}
run: npm install
- name: Build the WebAssembly + JavaScript binding
working-directory: ${{ env.MATRIX_SDK_CRYPTO_JS_PATH }}
run: npm run build
- name: Test the JavaScript binding
working-directory: ${{ env.MATRIX_SDK_CRYPTO_JS_PATH }}
run: npm run test
- name: Build the documentation
working-directory: ${{ env.MATRIX_SDK_CRYPTO_JS_PATH }}
run: npm run doc
test-apple:
name: matrix-rust-components-swift
runs-on: macos-12
if: github.event_name == 'push' || !github.event.pull_request.draft
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
profile: minimal
override: true
- name: Install targets
run: |
rustup target add aarch64-apple-ios-sim --toolchain nightly
rustup target add x86_64-apple-ios --toolchain nightly
- name: Load cache
uses: Swatinem/rust-cache@v1
- name: Install Uniffi
uses: actions-rs/cargo@v1
with:
command: install
# keep in sync with uniffi dependency in Cargo.toml's
args: uniffi_bindgen --version ^0.18
- name: Generate .xcframework
run: sh bindings/apple/debug_build_xcframework.sh ci
- name: Run XCTests
run: |
xcodebuild test \
-project bindings/apple/MatrixRustSDK.xcodeproj \
-scheme MatrixRustSDK \
-sdk iphonesimulator \
-destination 'platform=iOS Simulator,name=iPhone 13,OS=15.4'
+151 -200
View File
@@ -1,258 +1,209 @@
name: CI
name: Rust tests
on:
workflow_dispatch:
push:
branches: [main]
pull_request:
branches: [ master ]
branches: [main]
types:
- opened
- reopened
- synchronize
- ready_for_review
env:
CARGO_TERM_COLOR: always
jobs:
style:
name: Check style
test-matrix-sdk-features:
name: 🐧 [m], ${{ matrix.name }}
if: github.event_name == 'push' || !github.event.pull_request.draft
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
uses: actions/checkout@v2
- name: Install rust
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
components: rustfmt
profile: minimal
override: true
- name: Cargo fmt
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
clippy:
name: Run clippy
needs: [style]
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
uses: actions/checkout@v2
- name: Install rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
components: clippy
profile: minimal
override: true
- name: Clippy
uses: actions-rs/cargo@v1
with:
command: clippy
args: --all-targets -- -D warnings
- name: Clippy without default features
uses: actions-rs/cargo@v1
with:
command: clippy
# TODO: add `--all-targets` once all warnings in examples are resolved
args: --no-default-features --features native-tls,warp -- -D warnings
check-wasm:
name: linux / WASM
needs: [clippy]
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
uses: actions/checkout@v2
- name: Install rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: wasm32-unknown-unknown
profile: minimal
override: true
- name: Install emscripten
uses: mymindstorm/setup-emsdk@v7
- name: Check
run: |
cd matrix_sdk/examples/wasm_command_bot
cargo check --target wasm32-unknown-unknown
test-appservice:
name: ${{ matrix.name }}
needs: [clippy]
runs-on: ${{ matrix.os || 'ubuntu-latest' }}
strategy:
fail-fast: true
matrix:
name:
- linux / appservice / stable / actix
- macOS / appservice / stable / actix
- linux / appservice / stable / warp
- macOS / appservice / stable / warp
include:
- name: linux / appservice / stable / actix
cargo_args: --no-default-features --features actix
- name: macOS / appservice / stable / actix
os: macOS-latest
cargo_args: --no-default-features --features actix
- name: linux / appservice / stable / warp
cargo_args: --features warp
- name: macOS / appservice / stable / warp
os: macOS-latest
cargo_args: --features warp
- no-encryption
- no-sled
- no-encryption-and-sled
- sled-cryptostore
- rustls-tls
- markdown
- socks
- sso-login
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Install rust
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust || 'stable' }}
target: ${{ matrix.target }}
toolchain: stable
profile: minimal
override: true
- name: Clippy
uses: actions-rs/cargo@v1
with:
command: clippy
args: --manifest-path matrix_sdk_appservice/Cargo.toml ${{ matrix.cargo_args }} -- -D warnings
- name: Load cache
uses: Swatinem/rust-cache@v1
- name: Build
uses: actions-rs/cargo@v1
with:
command: build
args: --manifest-path matrix_sdk_appservice/Cargo.toml ${{ matrix.cargo_args }}
- name: Install nextest
uses: taiki-e/install-action@nextest
- name: Test
uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path matrix_sdk_appservice/Cargo.toml ${{ matrix.cargo_args }}
command: run
args: -p xtask -- ci test-features ${{ matrix.name }}
test-features:
name: ${{ matrix.name }}
needs: [clippy]
runs-on: ${{ matrix.os || 'ubuntu-latest' }}
strategy:
matrix:
name:
- linux / features-no-encryption
- linux / features-no-sled
- linux / features-no-encryption-and-sled
- linux / features-sled_cryptostore
- linux / features-rustls-tls
- linux / features-markdown
- linux / features-socks
- linux / features-sso_login
- linux / features-require_auth_for_profile_requests
include:
- name: linux / features-no-encryption
cargo_args: --no-default-features --features "sled_state_store, native-tls"
- name: linux / features-no-sled
cargo_args: --no-default-features --features "encryption, native-tls"
- name: linux / features-no-encryption-and-sled
cargo_args: --no-default-features --features "native-tls"
- name: linux / features-sled_cryptostore
cargo_args: --no-default-features --features "encryption, sled_cryptostore, native-tls"
- name: linux / features-rustls-tls
cargo_args: --no-default-features --features rustls-tls
- name: linux / features-require_auth_for_profile_requests
cargo_args: --no-default-features --features "require_auth_for_profile_requests, native-tls"
- name: linux / features-markdown
cargo_args: --features markdown
- name: linux / features-socks
cargo_args: --features socks
- name: linux / features-sso_login
cargo_args: --features sso_login
test-matrix-sdk-crypto:
name: 🐧 [m]-crypto
runs-on: ubuntu-latest
if: github.event_name == 'push' || !github.event.pull_request.draft
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Checkout the repo
uses: actions/checkout@v2
- name: Install rust
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust || 'stable' }}
target: ${{ matrix.target }}
profile: minimal
override: true
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Check
uses: actions-rs/cargo@v1
with:
command: check
args: --manifest-path matrix_sdk/Cargo.toml ${{ matrix.cargo_args }}
- name: Load cache
uses: Swatinem/rust-cache@v1
- name: Test
uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path matrix_sdk/Cargo.toml ${{ matrix.cargo_args }}
- name: Install nextest
uses: taiki-e/install-action@nextest
test:
- name: Test
uses: actions-rs/cargo@v1
with:
command: run
args: -p xtask -- ci test-crypto
test-all-crates:
name: ${{ matrix.name }}
needs: [clippy]
if: github.event_name == 'push' || !github.event.pull_request.draft
runs-on: ${{ matrix.os || 'ubuntu-latest' }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
name:
- linux / stable
- linux / beta
- macOS / stable
include:
- name: linux / stable
- name: 🐧 all crates, 🦀 stable
rust: stable
os: ubuntu-latest
- name: linux / beta
- name: 🐧 all crates, 🦀 beta
rust: beta
os: ubuntu-latest
- name: macOS / stable
os: macOS-latest
- name: 🍏 all crates, 🦀 stable
rust: stable
os: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Install rust
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust || 'stable' }}
target: ${{ matrix.target }}
toolchain: ${{ matrix.rust }}
profile: minimal
override: true
- name: Build
uses: actions-rs/cargo@v1
with:
command: build
- name: Load cache
uses: Swatinem/rust-cache@v1
- name: Install nextest
uses: taiki-e/install-action@nextest
- name: Test
uses: actions-rs/cargo@v1
with:
command: nextest
args: run --workspace
- name: Test documentation
uses: actions-rs/cargo@v1
with:
command: test
args: --doc
test-wasm:
name: 🕸️ ${{ matrix.name }}
if: github.event_name == 'push' || !github.event.pull_request.draft
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
include:
- name: '[m]-qrcode'
cmd: matrix-sdk-qrcode
- name: '[m]-base'
cmd: matrix-sdk-base
- name: '[m]-common'
cmd: matrix-sdk-common
- name: '[m]-indexeddb, no crypto'
cmd: indexeddb-no-crypto
- name: '[m]-indexeddb, with crypto'
cmd: indexeddb-with-crypto
- name: '[m], no-default, wasm-flags'
cmd: matrix-sdk-no-default
- name: '[m], indexeddb stores'
cmd: matrix-sdk-indexeddb-stores
- name: '[m], indexeddb stores, no crypto'
cmd: matrix-sdk-indexeddb-stores-no-crypto
- name: '[m], wasm-example'
cmd: matrix-sdk-command-bot
steps:
- name: Checkout the repo
uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: wasm32-unknown-unknown
components: clippy
profile: minimal
override: true
- name: Install wasm-pack
uses: jetli/wasm-pack-action@v0.3.0
with:
version: latest
- name: Load cache
uses: Swatinem/rust-cache@v1
- name: Install nextest
uses: taiki-e/install-action@nextest
- name: Rust Check
uses: actions-rs/cargo@v1
with:
command: run
args: -p xtask -- ci wasm ${{ matrix.cmd }}
- name: Wasm-Pack test
uses: actions-rs/cargo@v1
with:
command: run
args: -p xtask -- ci wasm-pack ${{ matrix.cmd }}
+11 -5
View File
@@ -2,7 +2,9 @@ name: Code coverage
on:
push:
branches: [ master ]
branches: [main]
pull_request:
branches: [main]
env:
CARGO_TERM_COLOR: always
@@ -11,29 +13,33 @@ jobs:
code_coverage:
name: Code Coverage
runs-on: "ubuntu-latest"
if: github.event_name == 'push' || !github.event.pull_request.draft
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Install stable toolchain
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Load cache
uses: Swatinem/rust-cache@v1
- name: Install tarpaulin
uses: actions-rs/cargo@v1
with:
command: install
args: cargo-tarpaulin -f
args: cargo-tarpaulin
- name: Run tarpaulin
uses: actions-rs/cargo@v1
with:
command: tarpaulin
args: --ignore-config --exclude-files "matrix_sdk/examples/*,matrix_sdk_common,matrix_sdk_test" --out Xml
args: --out Xml
- name: Upload to codecov.io
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v3
-37
View File
@@ -1,37 +0,0 @@
name: docs
on:
push:
branches: [master]
pull_request:
jobs:
docs:
name: docs
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
override: true
- name: Build docs
uses: actions-rs/cargo@v1
env:
RUSTDOCFLAGS: "--enable-index-page -Zunstable-options"
with:
command: doc
args: --no-deps --workspace --features docs
- name: Deploy docs
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./target/doc/
+45
View File
@@ -0,0 +1,45 @@
name: Documentation
on:
push:
branches: [main]
pull_request:
jobs:
docs:
name: All crates
runs-on: ubuntu-latest
if: github.event_name == 'push' || !github.event.pull_request.draft
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
override: true
- name: Load cache
uses: Swatinem/rust-cache@v1
# Keep in sync with xtask docs
- name: Build documentation
uses: actions-rs/cargo@v1
env:
# Work around https://github.com/rust-lang/cargo/issues/10744
CARGO_TARGET_APPLIES_TO_HOST: "true"
RUSTDOCFLAGS: "--enable-index-page -Zunstable-options --cfg docsrs -Dwarnings"
with:
command: doc
args: --no-deps --workspace --features docsrs
- name: Deploy documentation
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./target/doc/
force_orphan: true
@@ -0,0 +1,109 @@
name: Prepare Crypto-Node.js Release
#
# This is a helper workflow to craft a new Node.js release, trigger this via
# the Github Workflow UI by dispatching it manually. Provide the version, the
# matrix-sdk-crypto-nodejs npm package should be set to, and a optionally the
# old version (as used in the git tag) this release should be compared to.
#
# This will then:
# 1. bump the npm version to the one you specified
# 2. commit that change together with the changelog (if it changed, see below)
# 3. create the appropriate tag on that commit
# 4. create the Github draft release, including the changes (if given, see below)
# 5. push these to a new branch, including tag, triggering the `release-crypto-nodejs` workflow
# 6. create a PR to merge these back into `main`
#
# Additionally, if you provide a tag to comapare this tag to, this will:
# 1. create a changelog between the two releases, used for the github release
# 2. update the Changelog.md and include it in the commit
#
# The remaining tasks are done by the release-crypto-nodejs workflow.
on:
workflow_dispatch:
inputs:
version:
description: 'New Node.js SemVer version to create'
required: true
type: string
previous_version:
description: 'Create the changelog by comparing to this old SemVer Version (as used in the tag) '
type: string
env:
PKG_PATH: "bindings/matrix-sdk-crypto-nodejs"
TAG_PREFIX: "matrix-sdk-crypto-nodejs-v"
jobs:
prepare-release:
name: "Preparing crypto-nodejs release tag"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
# Generate changelog since last tag, if given
- name: Generate a changelog for upload
if: inputs.previous_version
uses: orhun/git-cliff-action@v1
with:
config: "${{ env.PKG_PATH }}/cliff.toml"
args: --strip header "${{env.TAG_PREFIX}}${{ inputs.previous_version }}..HEAD"
env:
GIT_CLIFF_TAG: "Changes ${{ inputs.previous_version }} -> ${{ inputs.version }}"
GIT_CLIFF_OUTPUT: "${{ env.PKG_PATH }}/CHANGES-${{ inputs.version }}.md"
# Update changelog since last tag, if given
- name: Update existing Changelog
if: inputs.previous_version
uses: orhun/git-cliff-action@v1
with:
config: "${{ env.PKG_PATH }}/cliff.toml"
args: "${{ inputs.previous_version }}..HEAD"
env:
GIT_CLIFF_TAG: "${{ inputs.version }}"
GIT_CLIFF_PREPEND: "${{ env.PKG_PATH }}/CHANGELOG.md"
- name: Set version
id: package_version
working-directory: ${{ env.PKG_PATH }}
run: npm version ${{ inputs.version }}
- uses: EndBug/add-and-commit@v9
with:
default_author: github_actions
message: "Tagging Crypto-Node.js for release"
tag: "${{env.TAG_PREFIX}}${{ inputs.version }}"
new_branch: "gh-action/release-${{ env.TAG_PREFIX }}${{ inputs.version }}"
push: true
add: |
${{ env.PKG_PATH }}/package.json
${{ env.PKG_PATH }}/CHANGELOG.md
# if we have generated changes
- name: Update Github Release notes
if: inputs.previous_version
uses: softprops/action-gh-release@v1
with:
draft: true
tag_name: ${{ env.TAG_PREFIX }}${{ inputs.version }}
body_path: "${{ env.PKG_PATH }}/CHANGES-${{ inputs.version }}.md"
# no changes, use the default changelog for the body
- name: Update Github Release notes
if: ${{!inputs.previous_version}}
uses: softprops/action-gh-release@v1
with:
draft: true
tag_name: ${{ env.TAG_PREFIX }}${{ inputs.version }}
body_path: "${{ env.PKG_PATH }}/CHANGELOG.md"
# finally, let's create a PR for all this, too
- name: Create Pull Request
uses: peter-evans/create-pull-request@v4
with:
branch: "gh-action/release-${{ env.TAG_PREFIX }}${{ inputs.version }}"
base: "main"
title: "Preparing Release ${{ env.TAG_PREFIX }}${{ inputs.version }}"
body: |
Automatic Pull-Request to merge release ${{ env.TAG_PREFIX }}${{ inputs.version }} back into main
+117
View File
@@ -0,0 +1,117 @@
name: Release Crypto-Node.js
#
# This workflow releases the crypto-bindings for nodejs
#
# It is triggered when seeing a tag prefixed matching `matrix-sdk-crypto-nodejs-v[0-9]+.*`,
# which then build the native bindings for linux, mac and windows via the CI and uploads
# them to the corresponding Github Release tag. Once they are finished, this workflow will
# package the npm tar.gz and uploads that to the Github Release tag as well, before publishing
# it to npmjs.com automatically.
#
# The usual way to trigger this is by manually triggering the `prep-crypto-nodejs-release`
# workflow. See its documentation for instructions how to use it.
env:
PKG_PATH: "bindings/matrix-sdk-crypto-nodejs"
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: 'aarch64-linux-gnu-gcc'
CARGO_TARGET_I686_UNKNOWN_LINUX_GNU_LINKER: 'i686-linux-gnu-gcc'
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER: 'arm-linux-gnueabihf-gcc'
on:
push:
tags:
- matrix-sdk-crypto-nodejs-v[0-9]+.*
jobs:
upload-assets:
name: "Upload prebuilt libraries"
strategy:
fail-fast: false
matrix:
include:
# ----------------------------------- Linux
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
- target: i686-unknown-linux-gnu
apt_install: gcc-i686-linux-gnu g++-i686-linux-gnu
os: ubuntu-latest
- target: aarch64-unknown-linux-gnu
os: ubuntu-latest
apt_install: gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
- target: arm-unknown-linux-gnueabihf
os: ubuntu-latest
apt_install: gcc-arm-linux-gnueabihf
- target: x86_64-unknown-linux-musl
os: ubuntu-latest
# ----------------------------------- macOS
- target: aarch64-apple-darwin
os: macos-latest
- target: x86_64-apple-darwin
os: macos-latest
# ----------------------------------- Windows
- target: x86_64-pc-windows-msvc
os: windows-latest
- target: i686-pc-windows-msvc
os: windows-latest
- target: aarch64-pc-windows-msvc
os: windows-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
profile: minimal
target: ${{ matrix.target }}
override: true
- name: Install Node.js
uses: actions/setup-node@v3
- name: Load cache
uses: Swatinem/rust-cache@v1
- if: ${{ matrix.apt_install }}
run: |
sudo apt-get update
sudo apt-get install -y ${{ matrix.apt_install }}
- name: Build lib
working-directory: ${{env.PKG_PATH}}
run: |
npm install --ignore-scripts
npx napi build --platform --release --strip --target ${{ matrix.target }}
- name: Upload artifacts to release
uses: softprops/action-gh-release@v1
with:
draft: true
files: ${{env.PKG_PATH}}/*.node
publish-nodejs-package:
name: "Package nodejs package"
runs-on: ubuntu-latest
needs:
- upload-assets
steps:
- uses: actions/checkout@v3
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
profile: minimal
override: true
- name: Install Node.js
uses: actions/setup-node@v3
- name: Build lib
working-directory: ${{env.PKG_PATH}}
run: |
npm install --ignore-scripts
npm run build
npm pack
- name: Upload npm package to release
uses: softprops/action-gh-release@v1
with:
draft: true
files: ${{env.PKG_PATH}}/*tgz
- name: Publish to npmjs.com
uses: JS-DevTools/npm-publish@v1
with:
package: ${{env.PKG_PATH}}/package.json
token: ${{ secrets.NPM_TOKEN }}
+105
View File
@@ -0,0 +1,105 @@
name: Style
on:
workflow_dispatch:
push:
branches: [main]
pull_request:
branches: [main]
types:
- opened
- reopened
- synchronize
- ready_for_review
env:
CARGO_TERM_COLOR: always
jobs:
style:
name: Check Formatting
runs-on: ubuntu-latest
if: github.event_name == 'push' || !github.event.pull_request.draft
steps:
- name: Checkout the repo
uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
components: rustfmt
profile: minimal
override: true
- name: Cargo fmt
uses: actions-rs/cargo@v1
with:
command: fmt
args: -- --check
pre-commit-styles:
name: Check Style
if: github.event_name == 'push' || !github.event.pull_request.draft
runs-on: ubuntu-latest
steps:
- name: Checkout Actions Repository
uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
components: clippy
profile: minimal
override: true
- name: Setup Python Env
uses: actions/setup-python@v2
- name: Check Styles with pre-commit
uses: pre-commit/action@v2.0.3
with:
# only run `commit`-hooks, excludes typos, clippy, etc
extra_args: --show-diff-on-failure --hook-stage commit
typos:
name: Spell Check with Typos
needs: [style]
runs-on: ubuntu-latest
if: github.event_name == 'push' || !github.event.pull_request.draft
steps:
- name: Checkout Actions Repository
uses: actions/checkout@v2
- name: Check the spelling of the files in our repo
uses: crate-ci/typos@master
clippy:
name: Run clippy
needs: [style]
runs-on: ubuntu-latest
if: github.event_name == 'push' || !github.event.pull_request.draft
steps:
- name: Checkout the repo
uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
components: clippy
profile: minimal
override: true
- name: Load cache
uses: Swatinem/rust-cache@v1
- name: Clippy
uses: actions-rs/cargo@v1
with:
command: run
args: -p xtask -- ci clippy
+10 -1
View File
@@ -1,4 +1,13 @@
Cargo.lock
target
generated
master.zip
emsdk-*
emsdk-*
.idea/
## User settings
xcuserdata/
.vscode/
## OS garbage
.DS_Store
+13 -1
View File
@@ -1,10 +1,13 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.2.3
rev: v4.2.0
hooks:
- id: check-yaml
- id: check-toml
- id: end-of-file-fixer
- id: trailing-whitespace
- id: check-merge-conflict
- id: mixed-line-ending
- repo: local
hooks:
@@ -16,6 +19,7 @@ repos:
- id: clippy
name: clippy
stages: [push]
language: system
types: [file, rust]
entry: cargo clippy --all-targets --all
@@ -23,7 +27,15 @@ repos:
- id: test
name: test
stages: [push]
language: system
files: '\.rs$'
entry: cargo test --lib
pass_filenames: false
- id: typos
name: typos
stages: [push]
language: system
entry: typos
pass_filenames: false
+1
View File
@@ -1,3 +1,4 @@
edition = "2018"
max_width = 100
comment_width = 80
wrap_comments = true
+11
View File
@@ -0,0 +1,11 @@
[default.extend-words]
# Remove this once base64 gets correctly ignored by typos
# Or if we're able to ignore certain lines.
Fo = "Fo"
BA = "BA"
UE = "UE"
[files]
# Our json files contain a bunch of base64 encoded ed25519 keys which aren't
# automatically ignored, we ignore them here.
extend-exclude = ["*.json"]
+20 -8
View File
@@ -1,11 +1,23 @@
[workspace]
members = [
"matrix_sdk",
"matrix_qrcode",
"matrix_sdk_base",
"matrix_sdk_test",
"matrix_sdk_test_macros",
"matrix_sdk_crypto",
"matrix_sdk_common",
"matrix_sdk_appservice"
"benchmarks",
"bindings/matrix-sdk-crypto-ffi",
"bindings/matrix-sdk-crypto-js",
"bindings/matrix-sdk-crypto-nodejs",
"bindings/matrix-sdk-ffi",
"crates/*",
"labs/*",
"xtask",
]
# xtask, labs and the bindings should only be built when invoked explicitly.
default-members = ["benchmarks", "crates/*"]
resolver = "2"
[profile.release]
lto = true
[profile.dev.package]
# Optimize quote even in debug mode. Speeds up proc-macros enough to account
# for the extra time of optimizing it for a clean build of matrix-sdk-ffi.
quote = { opt-level = 2 }
sha2 = { opt-level = 2 }
-17
View File
@@ -1,17 +0,0 @@
all: build
build:
cargo build
test:
cargo test
coverage:
cargo tarpaulin -v
clean:
cargo clean
format:
cargo fmt
.PHONY: clean test coverage
+12 -2
View File
@@ -1,8 +1,8 @@
![Build Status](https://img.shields.io/github/workflow/status/matrix-org/matrix-rust-sdk/CI?style=flat-square)
[![codecov](https://img.shields.io/codecov/c/github/matrix-org/matrix-rust-sdk/master.svg?style=flat-square)](https://codecov.io/gh/matrix-org/matrix-rust-sdk)
[![codecov](https://img.shields.io/codecov/c/github/matrix-org/matrix-rust-sdk/main.svg?style=flat-square)](https://codecov.io/gh/matrix-org/matrix-rust-sdk)
[![License](https://img.shields.io/badge/License-Apache%202.0-yellowgreen.svg?style=flat-square)](https://opensource.org/licenses/Apache-2.0)
[![#matrix-rust-sdk](https://img.shields.io/badge/matrix-%23matrix--rust--sdk-blue?style=flat-square)](https://matrix.to/#/#matrix-rust-sdk:matrix.org)
[![Docs - Master](https://img.shields.io/badge/docs-master-blue.svg?style=flat-square)](https://matrix-org.github.io/matrix-rust-sdk/)
[![Docs - Main](https://img.shields.io/badge/docs-main-blue.svg?style=flat-square)](https://matrix-org.github.io/matrix-rust-sdk/matrix_sdk/)
[![Docs - Stable](https://img.shields.io/crates/v/matrix-sdk?color=blue&label=docs&style=flat-square)](https://docs.rs/matrix-sdk)
# matrix-rust-sdk
@@ -24,6 +24,10 @@ The rust-sdk consists of multiple crates that can be picked at your convenience:
- **matrix-sdk-crypto** - No (network) IO encryption state machine that can be
used to add Matrix E2EE support to your client or client library.
## Minimum Supported Rust Version (MSRV)
These crates are built with the Rust language version 2021 and require a minimum compiler version of `1.60`
## Status
The library is in an alpha state, things that are implemented generally work but
@@ -32,6 +36,12 @@ the API will change in breaking ways.
If you are interested in using the matrix-sdk now is the time to try it out and
provide feedback.
## Bindings
Some crates of the **matrix-rust-sdk** can be embedded inside other
environments, like Swift, Kotlin, JavaScript, Node.js etc. Please,
explore the [`bindings/`](./bindings/) directory to learn more.
## License
[Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0)
+43
View File
@@ -0,0 +1,43 @@
# SDK 0.5 - stores and native crypto
The @matrix-org/rust team is happy to present to the wider public version 0.5 of the [`matrix-rust-sdk`][sdk], now available on crates.io for your convenience. This marks an important milestone after over half a year of work since the latest release (0.4) and with many new team members working on it. It comes with many bug fixes, improvements and updates, but a few we'd like to highlight here:
## Better, safer, native-er crypto
One of the biggest improvements under the hood is the replacement of the former crypto core written in C, libolm, with the fully rustic, fully audited [Vodozemac][vodozemac]. [Vodozemac][vodozemac] is a much more robust new implementation of the olm crypto primitives and engines with all the learning included and pitfalls from the previous C implementation avoided in a freshly baked, very robust library. With this release both matrix-sdk-crypto and matrix-sdk (when the `e2e-encryption` is enabled, which it is by default) use vodozemac to handle all crypto needs.
## Stores, stores, stores
This release has also seen a major refactoring around the state and crypto store primitives and implementations. From this release forward, the implementation of the storage layer is truly modular and pluggable, with the default implementation (based on `sled`) even being a separate crate. Furthermore this release has also additional support for the [`indexeddb`-storage][indexeddb] layer for in-browser WASM needs. As before, the base still ships with an in-memory store, but if none of them fits your needs, you are very much invited to build your own - we recommend looking at the implementation of the existing [`matrix-sdk-sled`][sled] to understand what is needed.
We've further extended and cleaned up the storage API and hardened the two existing implementations: both `sled` and `indexeddb` will now encrypt _all metadata_, including all keys, if a passphrase is given. Even a core dump of a database won't show any strings or other identifiable data. Both implementation also hold a database version string now, allowing future migrations of the database schema while we move forward.
## WebAssembly
It already came through in the previous paragraph: we now fully support `wasm` as a primary target for the main sdk and its dependencies (browser for now). While it was already possible to build the SDK for wasm before, if you were lucky and had the specific emscripten setup, even crypto didn't always fail to compile, our move to vodozemac frees us from these problems and our CI now makes sure all our PRs will continue to build on WebAssembly, too. And with the `indexeddb`-store, we also have a fully persistent storage layer implementation for all your in-browser matrix needs built in.
## More features
Of course a lot more has happened over the last few months as we've ramped up our work on the SDK. Most notably, you can now check whether a room has been created as a `space`, and we offer nice automatic thumbnailing and resizing support if you enable `image`. Additionally, there is a very early event-timeline API behind the `experimental-timeline`-feature-flag. Just to name a few. We really recommend you migrate from the older version to this one.
## Process and Workflow
We've also ramped up our CI, parallelized it a lot, while adding more tests. In general we don't merge anything breaking the tests, thus our `main` can also be considered `stable` to build again, though things might be changed without prior notice. We recommend keeping an eye out in our [team chat][chat] to stay current.
### Versions
This and all future releases of matrix-sdk adhere to [semver][semver] and we do our best to stick to it for the default-feature-set. As you will see only the main crate `matrix-sdk` is actually versioned at `0.5`, while other crates - especially newer ones - have different versions attached. We recommend to sticking to the high-level matrix-sdk-crate wherever reasonable as lower level crates might change more often, also in breaking fashion.
With this release all our crates are build with `rust v2021` and need a rust compiler of at least `1.60` (due to our need for weak-dependencies).
### Conventional Commit
We also want to make it easier for external parties to follow changes and stay up to date with what's-what, so, with this release, we are implementing the [conventional commits][cc] standard for our commits and will start putting in automatic changelog generation. Which makes it easier for us to create comprehensive changelogs for releases, but also for anyone following `main` to figure out what changed.
[sdk]: https://crates.io/crates/matrix-sdk/
[vodozemac]: https://github.com/matrix-org/vodozemac
[sled]: https://crates.io/crates/matrix-sdk-sled/
[indexeddb]: https://crates.io/crates/matrix-sdk-indexeddb/
[chat]: https://matrix.to/#/#matrix-rust-sdk:matrix.org
[semver]: https://semver.org/
[cc]: http://conventionalcommits.org/
+25
View File
@@ -0,0 +1,25 @@
[package]
name = "benchmarks"
description = "Matrix SDK benchmarks"
edition = "2021"
license = "Apache-2.0"
rust-version = "1.56"
version = "1.0.0"
publish = false
[dependencies]
criterion = { version = "0.3.5", features = ["async", "async_tokio", "html_reports"] }
matrix-sdk-crypto = { path = "../crates/matrix-sdk-crypto", version = "0.5.0" }
matrix-sdk-sled = { path = "../crates/matrix-sdk-sled", version = "0.1.0", default-features = false, features = ["crypto-store"] }
matrix-sdk-test = { path = "../crates/matrix-sdk-test", version = "0.5.0" }
ruma = { git = "https://github.com/ruma/ruma", rev = "96155915f" }
serde_json = "1.0.79"
tempfile = "3.3.0"
tokio = { version = "1.17.0", default-features = false, features = ["rt-multi-thread"] }
[target.'cfg(target_os = "linux")'.dependencies]
pprof = { version = "0.8.0", features = ["flamegraph", "criterion"] }
[[bench]]
name = "crypto_bench"
harness = false
+80
View File
@@ -0,0 +1,80 @@
# Benchmarks for the rust-sdk crypto layer
This directory contains various benchmarks that test critical functionality in
the crypto layer in the rust-sdk.
We're using [Criterion] for the benchmarks, the full documentation for Criterion
can be found [here](https://bheisler.github.io/criterion.rs/book/criterion_rs.html).
## Running the benchmarks
The benchmark can be simply run by using the `bench` command of `cargo`:
```bash
$ cargo bench
```
This will work from the workspace directory of the rust-sdk.
If you want to pass options to the benchmark [you'll need to specify the name of
the benchmark](https://bheisler.github.io/criterion.rs/book/faq.html#cargo-bench-gives-unrecognized-option-errors-for-valid-command-line-options):
```bash
$ cargo bench --bench crypto_bench -- # Your options go here
```
If you want to run only a specific benchmark, simply pass the name of the
benchmark as an argument:
```bash
$ cargo bench --bench crypto_bench "Room key sharing/"
```
After the benchmarks are done, a HTML report can be found in `target/criterion/report/index.html`.
### Using a baseline for the benchmark
The benchmarks will by default compare the results to the previous run of the
benchmark. If you are improving the performance of a specific feature and run
the benchmark many times, it may be useful to store a baseline to compare
against instead.
The `--save-baseline` switch can be used to create a baseline for the benchmark.
```bash
$ cargo bench --bench crypto_bench -- --save-baseline libolm
```
After you make your changes you can use the baseline to compare the results like
so:
```bash
$ cargo bench --bench crypto_bench -- --baseline libolm
```
### Generating Flame Graphs for the benchmarks
The benchmarks support profiling and generating [Flame Graphs] while they run in
profiling mode using [pprof].
Profiling usually requires root permissions, to avoid the need for root
permissions you can adjust the value of `perf_event_paranoid`, e.g. the most
permisive value is `-1`:
```bash
$ echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid
```
To generate flame graphs feature simply enable the profiling mode using the
`--profile-time` command line flag:
```bash
$ cargo bench --bench crypto_bench -- --profile-time=5
```
After the benchmarks are done, a flame graph for each individual benchmark can be
found in `target/criterion/<name-of-benchmark>/profile/flamegraph.svg`.
[pprof]: https://docs.rs/pprof/0.5.0/pprof/index.html#
[Criterion]: https://docs.rs/criterion/0.3.5/criterion/
[Flame Graphs]: https://www.brendangregg.com/flamegraphs.html
@@ -1,60 +1,59 @@
#[cfg(target_os = "linux")]
mod perf;
use std::sync::Arc;
use std::{ops::Deref, sync::Arc};
use criterion::*;
use matrix_sdk_common::uuid::Uuid;
use matrix_sdk_crypto::{EncryptionSettings, OlmMachine};
use matrix_sdk_sled::CryptoStore as SledCryptoStore;
use matrix_sdk_test::response_from_file;
use ruma::{
api::{
client::r0::{
client::{
keys::{claim_keys, get_keys},
to_device::send_event_to_device::Response as ToDeviceResponse,
to_device::send_event_to_device::v3::Response as ToDeviceResponse,
},
IncomingResponse,
},
room_id, user_id, DeviceIdBox, UserId,
device_id, room_id, user_id, DeviceId, OwnedUserId, TransactionId, UserId,
};
use serde_json::Value;
use tokio::runtime::Builder;
fn alice_id() -> UserId {
fn alice_id() -> &'static UserId {
user_id!("@alice:example.org")
}
fn alice_device_id() -> DeviceIdBox {
"JLAFKJWSCS".into()
fn alice_device_id() -> &'static DeviceId {
device_id!("JLAFKJWSCS")
}
fn keys_query_response() -> get_keys::Response {
let data = include_bytes!("./keys_query.json");
fn keys_query_response() -> get_keys::v3::Response {
let data = include_bytes!("crypto_bench/keys_query.json");
let data: Value = serde_json::from_slice(data).unwrap();
let data = response_from_file(&data);
get_keys::Response::try_from_http_response(data).expect("Can't parse the keys upload response")
}
fn keys_claim_response() -> claim_keys::Response {
let data = include_bytes!("./keys_claim.json");
let data: Value = serde_json::from_slice(data).unwrap();
let data = response_from_file(&data);
claim_keys::Response::try_from_http_response(data)
get_keys::v3::Response::try_from_http_response(data)
.expect("Can't parse the keys upload response")
}
fn huge_keys_query_resopnse() -> get_keys::Response {
let data = include_bytes!("./keys_query_2000_members.json");
fn keys_claim_response() -> claim_keys::v3::Response {
let data = include_bytes!("crypto_bench/keys_claim.json");
let data: Value = serde_json::from_slice(data).unwrap();
let data = response_from_file(&data);
get_keys::Response::try_from_http_response(data).expect("Can't parse the keys query response")
claim_keys::v3::Response::try_from_http_response(data)
.expect("Can't parse the keys upload response")
}
fn huge_keys_query_response() -> get_keys::v3::Response {
let data = include_bytes!("crypto_bench/keys_query_2000_members.json");
let data: Value = serde_json::from_slice(data).unwrap();
let data = response_from_file(&data);
get_keys::v3::Response::try_from_http_response(data)
.expect("Can't parse the keys query response")
}
pub fn keys_query(c: &mut Criterion) {
let runtime = Builder::new_multi_thread().build().expect("Can't create runtime");
let machine = OlmMachine::new(&alice_id(), &alice_device_id());
let machine = runtime.block_on(OlmMachine::new(alice_id(), alice_device_id()));
let response = keys_query_response();
let uuid = Uuid::new_v4();
let txn_id = TransactionId::new();
let count = response.device_keys.values().fold(0, |acc, d| acc + d.len())
+ response.master_keys.len()
@@ -68,32 +67,27 @@ pub fn keys_query(c: &mut Criterion) {
group.bench_with_input(BenchmarkId::new("memory store", &name), &response, |b, response| {
b.to_async(&runtime)
.iter(|| async { machine.mark_request_as_sent(&uuid, response).await.unwrap() })
.iter(|| async { machine.mark_request_as_sent(&txn_id, response).await.unwrap() })
});
let dir = tempfile::tempdir().unwrap();
let machine = runtime
.block_on(OlmMachine::new_with_default_store(
&alice_id(),
&alice_device_id(),
dir.path(),
None,
))
.unwrap();
let store = Arc::new(SledCryptoStore::open_with_passphrase(dir.path(), None).unwrap());
let machine =
runtime.block_on(OlmMachine::with_store(alice_id(), alice_device_id(), store)).unwrap();
group.bench_with_input(BenchmarkId::new("sled store", &name), &response, |b, response| {
b.to_async(&runtime)
.iter(|| async { machine.mark_request_as_sent(&uuid, response).await.unwrap() })
.iter(|| async { machine.mark_request_as_sent(&txn_id, response).await.unwrap() })
});
group.finish()
}
pub fn keys_claiming(c: &mut Criterion) {
let runtime = Arc::new(Builder::new_multi_thread().build().expect("Can't create runtime"));
let runtime = Builder::new_multi_thread().build().expect("Can't create runtime");
let keys_query_response = keys_query_response();
let uuid = Uuid::new_v4();
let txn_id = TransactionId::new();
let response = keys_claim_response();
@@ -107,14 +101,14 @@ pub fn keys_claiming(c: &mut Criterion) {
group.bench_with_input(BenchmarkId::new("memory store", &name), &response, |b, response| {
b.iter_batched(
|| {
let machine = OlmMachine::new(&alice_id(), &alice_device_id());
let machine = runtime.block_on(OlmMachine::new(alice_id(), alice_device_id()));
runtime
.block_on(machine.mark_request_as_sent(&uuid, &keys_query_response))
.block_on(machine.mark_request_as_sent(&txn_id, &keys_query_response))
.unwrap();
(machine, runtime.clone())
(machine, &runtime, &txn_id)
},
move |(machine, runtime)| {
runtime.block_on(machine.mark_request_as_sent(&uuid, response)).unwrap()
move |(machine, runtime, txn_id)| {
runtime.block_on(machine.mark_request_as_sent(txn_id, response)).unwrap()
},
BatchSize::SmallInput,
)
@@ -124,21 +118,19 @@ pub fn keys_claiming(c: &mut Criterion) {
b.iter_batched(
|| {
let dir = tempfile::tempdir().unwrap();
let store =
Arc::new(SledCryptoStore::open_with_passphrase(dir.path(), None).unwrap());
let machine = runtime
.block_on(OlmMachine::new_with_default_store(
&alice_id(),
&alice_device_id(),
dir.path(),
None,
))
.block_on(OlmMachine::with_store(alice_id(), alice_device_id(), store))
.unwrap();
runtime
.block_on(machine.mark_request_as_sent(&uuid, &keys_query_response))
.block_on(machine.mark_request_as_sent(&txn_id, &keys_query_response))
.unwrap();
(machine, runtime.clone())
(machine, &runtime, &txn_id)
},
move |(machine, runtime)| {
runtime.block_on(machine.mark_request_as_sent(&uuid, response)).unwrap()
move |(machine, runtime, txn_id)| {
runtime.block_on(machine.mark_request_as_sent(txn_id, response)).unwrap()
},
BatchSize::SmallInput,
)
@@ -151,18 +143,18 @@ pub fn room_key_sharing(c: &mut Criterion) {
let runtime = Builder::new_multi_thread().build().expect("Can't create runtime");
let keys_query_response = keys_query_response();
let uuid = Uuid::new_v4();
let txn_id = TransactionId::new();
let response = keys_claim_response();
let room_id = room_id!("!test:localhost");
let to_device_response = ToDeviceResponse::new();
let users: Vec<UserId> = keys_query_response.device_keys.keys().cloned().collect();
let users: Vec<OwnedUserId> = keys_query_response.device_keys.keys().cloned().collect();
let count = response.one_time_keys.values().fold(0, |acc, d| acc + d.len());
let machine = OlmMachine::new(&alice_id(), &alice_device_id());
runtime.block_on(machine.mark_request_as_sent(&uuid, &keys_query_response)).unwrap();
runtime.block_on(machine.mark_request_as_sent(&uuid, &response)).unwrap();
let machine = runtime.block_on(OlmMachine::new(alice_id(), alice_device_id()));
runtime.block_on(machine.mark_request_as_sent(&txn_id, &keys_query_response)).unwrap();
runtime.block_on(machine.mark_request_as_sent(&txn_id, &response)).unwrap();
let mut group = c.benchmark_group("Room key sharing");
group.throughput(Throughput::Elements(count as u64));
@@ -171,7 +163,11 @@ pub fn room_key_sharing(c: &mut Criterion) {
group.bench_function(BenchmarkId::new("memory store", &name), |b| {
b.to_async(&runtime).iter(|| async {
let requests = machine
.share_group_session(&room_id, users.iter(), EncryptionSettings::default())
.share_room_key(
room_id,
users.iter().map(Deref::deref),
EncryptionSettings::default(),
)
.await
.unwrap();
@@ -181,26 +177,25 @@ pub fn room_key_sharing(c: &mut Criterion) {
machine.mark_request_as_sent(&request.txn_id, &to_device_response).await.unwrap();
}
machine.invalidate_group_session(&room_id).await.unwrap();
machine.invalidate_group_session(room_id).await.unwrap();
})
});
let dir = tempfile::tempdir().unwrap();
let machine = runtime
.block_on(OlmMachine::new_with_default_store(
&alice_id(),
&alice_device_id(),
dir.path(),
None,
))
.unwrap();
runtime.block_on(machine.mark_request_as_sent(&uuid, &keys_query_response)).unwrap();
runtime.block_on(machine.mark_request_as_sent(&uuid, &response)).unwrap();
let store = Arc::new(SledCryptoStore::open_with_passphrase(dir.path(), None).unwrap());
let machine =
runtime.block_on(OlmMachine::with_store(alice_id(), alice_device_id(), store)).unwrap();
runtime.block_on(machine.mark_request_as_sent(&txn_id, &keys_query_response)).unwrap();
runtime.block_on(machine.mark_request_as_sent(&txn_id, &response)).unwrap();
group.bench_function(BenchmarkId::new("sled store", &name), |b| {
b.to_async(&runtime).iter(|| async {
let requests = machine
.share_group_session(&room_id, users.iter(), EncryptionSettings::default())
.share_room_key(
room_id,
users.iter().map(Deref::deref),
EncryptionSettings::default(),
)
.await
.unwrap();
@@ -210,7 +205,7 @@ pub fn room_key_sharing(c: &mut Criterion) {
machine.mark_request_as_sent(&request.txn_id, &to_device_response).await.unwrap();
}
machine.invalidate_group_session(&room_id).await.unwrap();
machine.invalidate_group_session(room_id).await.unwrap();
})
});
@@ -220,10 +215,10 @@ pub fn room_key_sharing(c: &mut Criterion) {
pub fn devices_missing_sessions_collecting(c: &mut Criterion) {
let runtime = Builder::new_multi_thread().build().expect("Can't create runtime");
let machine = OlmMachine::new(&alice_id(), &alice_device_id());
let response = huge_keys_query_resopnse();
let uuid = Uuid::new_v4();
let users: Vec<UserId> = response.device_keys.keys().cloned().collect();
let machine = runtime.block_on(OlmMachine::new(alice_id(), alice_device_id()));
let response = huge_keys_query_response();
let txn_id = TransactionId::new();
let users: Vec<OwnedUserId> = response.device_keys.keys().cloned().collect();
let count = response.device_keys.values().fold(0, |acc, d| acc + d.len());
@@ -232,29 +227,26 @@ pub fn devices_missing_sessions_collecting(c: &mut Criterion) {
let name = format!("{} devices", count);
runtime.block_on(machine.mark_request_as_sent(&uuid, &response)).unwrap();
runtime.block_on(machine.mark_request_as_sent(&txn_id, &response)).unwrap();
group.bench_function(BenchmarkId::new("memory store", &name), |b| {
b.to_async(&runtime).iter_with_large_drop(|| async {
machine.get_missing_sessions(users.iter()).await.unwrap()
machine.get_missing_sessions(users.iter().map(Deref::deref)).await.unwrap()
})
});
let dir = tempfile::tempdir().unwrap();
let machine = runtime
.block_on(OlmMachine::new_with_default_store(
&alice_id(),
&alice_device_id(),
dir.path(),
None,
))
.unwrap();
let store = Arc::new(SledCryptoStore::open_with_passphrase(dir.path(), None).unwrap());
runtime.block_on(machine.mark_request_as_sent(&uuid, &response)).unwrap();
let machine =
runtime.block_on(OlmMachine::with_store(alice_id(), alice_device_id(), store)).unwrap();
runtime.block_on(machine.mark_request_as_sent(&txn_id, &response)).unwrap();
group.bench_function(BenchmarkId::new("sled store", &name), |b| {
b.to_async(&runtime)
.iter(|| async { machine.get_missing_sessions(users.iter()).await.unwrap() })
b.to_async(&runtime).iter(|| async {
machine.get_missing_sessions(users.iter().map(Deref::deref)).await.unwrap()
})
});
group.finish()
@@ -262,7 +254,10 @@ pub fn devices_missing_sessions_collecting(c: &mut Criterion) {
fn criterion() -> Criterion {
#[cfg(target_os = "linux")]
let criterion = Criterion::default().with_profiler(perf::FlamegraphProfiler::new(100));
let criterion = Criterion::default().with_profiler(pprof::criterion::PProfProfiler::new(
100,
pprof::criterion::Output::Flamegraph(None),
));
#[cfg(not(target_os = "linux"))]
let criterion = Criterion::default();
+22
View File
@@ -0,0 +1,22 @@
# Matrix Rust SDK bindings
In this directory, one can find bindings to the Rust SDK that are
maintained by the owners of the Matrix Rust SDK project.
* [`apple`] or `matrix-rust-components-swift`, Swift bindings of the
[`matrix-sdk`] crate via [`matrix-sdk-ffi`],
* [`matrix-sdk-crypto-ffi`], bindings of the [`matrix-sdk-crypto`]
crate,
* [`matrix-sdk-crypto-js`], JavaScript bindings of the
[`matrix-sdk-crypto`] crate,
* [`matrix-sdk-crypto-nodejs`], Node.js bindings of the
[`matrix-sdk-crypto`] crate,
* [`matrix-sdk-ffi`], bindings of the [`matrix-sdk`] crate,
[`apple`]: ./apple
[`matrix-sdk-crypto-ffi`]: ./matrix-sdk-crypto-ffi
[`matrix-sdk-crypto-js`]: ../crates/matrix-sdk-crypto
[`matrix-sdk-crypto-nodejs`]: ../crates/matrix-sdk-crypto
[`matrix-sdk-crypto`]: ../crates/matrix-sdk-crypto
[`matrix-sdk-ffi`]: ./matrix-sdk-ffi
[`matrix-sdk`]: ../crates/matrix-sdk
@@ -0,0 +1,513 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 55;
objects = {
/* Begin PBXBuildFile section */
181AA19B27B52AB40005F102 /* MatrixSDKFFI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 181AA19A27B52AB40005F102 /* MatrixSDKFFI.xcframework */; };
181AA19C27B52AB40005F102 /* MatrixSDKFFI.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 181AA19A27B52AB40005F102 /* MatrixSDKFFI.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
189A89BA27B40BBF0048B0A5 /* sdk.swift in Sources */ = {isa = PBXBuildFile; fileRef = 189A89B927B40BBF0048B0A5 /* sdk.swift */; };
18CE89D827B2939900CA89E1 /* MatrixRustSDKApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18CE89D727B2939900CA89E1 /* MatrixRustSDKApp.swift */; };
18CE89DA27B2939900CA89E1 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18CE89D927B2939900CA89E1 /* ContentView.swift */; };
18CE89DC27B2939A00CA89E1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 18CE89DB27B2939A00CA89E1 /* Assets.xcassets */; };
18CE89E927B2939A00CA89E1 /* MatrixRustSDKTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18CE89E827B2939A00CA89E1 /* MatrixRustSDKTests.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
18CE89E527B2939A00CA89E1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 18CE89CC27B2939900CA89E1 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 18CE89D327B2939900CA89E1;
remoteInfo = MatrixRustSDK;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
18CE8A1F27B2941600CA89E1 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
181AA19C27B52AB40005F102 /* MatrixSDKFFI.xcframework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
181AA19927B52AA60005F102 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
181AA19A27B52AB40005F102 /* MatrixSDKFFI.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = MatrixSDKFFI.xcframework; path = ../../generated/MatrixSDKFFI.xcframework; sourceTree = "<group>"; };
189A89B927B40BBF0048B0A5 /* sdk.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = sdk.swift; path = ../../../generated/swift/sdk.swift; sourceTree = "<group>"; };
189A89C327B417CA0048B0A5 /* MatrixRustSDK-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MatrixRustSDK-Bridging-Header.h"; sourceTree = "<group>"; };
18CE89D427B2939900CA89E1 /* MatrixRustSDK.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MatrixRustSDK.app; sourceTree = BUILT_PRODUCTS_DIR; };
18CE89D727B2939900CA89E1 /* MatrixRustSDKApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixRustSDKApp.swift; sourceTree = "<group>"; };
18CE89D927B2939900CA89E1 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
18CE89DB27B2939A00CA89E1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
18CE89E427B2939A00CA89E1 /* MatrixRustSDKTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MatrixRustSDKTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
18CE89E827B2939A00CA89E1 /* MatrixRustSDKTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixRustSDKTests.swift; sourceTree = "<group>"; };
18CE8A0127B293A900CA89E1 /* MatrixRustSDK.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MatrixRustSDK.entitlements; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
18CE89D127B2939900CA89E1 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
181AA19B27B52AB40005F102 /* MatrixSDKFFI.xcframework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
18CE89E127B2939A00CA89E1 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
189A89AB27B2E16B0048B0A5 /* Frameworks */ = {
isa = PBXGroup;
children = (
181AA19A27B52AB40005F102 /* MatrixSDKFFI.xcframework */,
);
name = Frameworks;
sourceTree = "<group>";
};
189A89B827B40BB10048B0A5 /* Generated */ = {
isa = PBXGroup;
children = (
189A89B927B40BBF0048B0A5 /* sdk.swift */,
);
name = Generated;
sourceTree = "<group>";
};
18CE89CB27B2939900CA89E1 = {
isa = PBXGroup;
children = (
18CE89D627B2939900CA89E1 /* MatrixRustSDK */,
18CE89E727B2939A00CA89E1 /* MatrixRustSDKTests */,
18CE89D527B2939900CA89E1 /* Products */,
189A89AB27B2E16B0048B0A5 /* Frameworks */,
);
sourceTree = "<group>";
};
18CE89D527B2939900CA89E1 /* Products */ = {
isa = PBXGroup;
children = (
18CE89D427B2939900CA89E1 /* MatrixRustSDK.app */,
18CE89E427B2939A00CA89E1 /* MatrixRustSDKTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
18CE89D627B2939900CA89E1 /* MatrixRustSDK */ = {
isa = PBXGroup;
children = (
181AA19927B52AA60005F102 /* Info.plist */,
189A89B827B40BB10048B0A5 /* Generated */,
18CE89D727B2939900CA89E1 /* MatrixRustSDKApp.swift */,
18CE89D927B2939900CA89E1 /* ContentView.swift */,
18CE8A0127B293A900CA89E1 /* MatrixRustSDK.entitlements */,
18CE89DB27B2939A00CA89E1 /* Assets.xcassets */,
189A89C327B417CA0048B0A5 /* MatrixRustSDK-Bridging-Header.h */,
);
path = MatrixRustSDK;
sourceTree = "<group>";
};
18CE89E727B2939A00CA89E1 /* MatrixRustSDKTests */ = {
isa = PBXGroup;
children = (
18CE89E827B2939A00CA89E1 /* MatrixRustSDKTests.swift */,
);
path = MatrixRustSDKTests;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
18CE89D327B2939900CA89E1 /* MatrixRustSDK */ = {
isa = PBXNativeTarget;
buildConfigurationList = 18CE89F827B2939A00CA89E1 /* Build configuration list for PBXNativeTarget "MatrixRustSDK" */;
buildPhases = (
18CE89D027B2939900CA89E1 /* Sources */,
18CE89D127B2939900CA89E1 /* Frameworks */,
18CE89D227B2939900CA89E1 /* Resources */,
18CE8A1F27B2941600CA89E1 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = MatrixRustSDK;
productName = MatrixRustSDK;
productReference = 18CE89D427B2939900CA89E1 /* MatrixRustSDK.app */;
productType = "com.apple.product-type.application";
};
18CE89E327B2939A00CA89E1 /* MatrixRustSDKTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 18CE89FB27B2939A00CA89E1 /* Build configuration list for PBXNativeTarget "MatrixRustSDKTests" */;
buildPhases = (
18CE89E027B2939A00CA89E1 /* Sources */,
18CE89E127B2939A00CA89E1 /* Frameworks */,
18CE89E227B2939A00CA89E1 /* Resources */,
);
buildRules = (
);
dependencies = (
18CE89E627B2939A00CA89E1 /* PBXTargetDependency */,
);
name = MatrixRustSDKTests;
productName = MatrixRustSDKTests;
productReference = 18CE89E427B2939A00CA89E1 /* MatrixRustSDKTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
18CE89CC27B2939900CA89E1 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1320;
LastUpgradeCheck = 1320;
TargetAttributes = {
18CE89D327B2939900CA89E1 = {
CreatedOnToolsVersion = 13.2.1;
LastSwiftMigration = 1320;
};
18CE89E327B2939A00CA89E1 = {
CreatedOnToolsVersion = 13.2.1;
TestTargetID = 18CE89D327B2939900CA89E1;
};
};
};
buildConfigurationList = 18CE89CF27B2939900CA89E1 /* Build configuration list for PBXProject "MatrixRustSDK" */;
compatibilityVersion = "Xcode 13.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 18CE89CB27B2939900CA89E1;
productRefGroup = 18CE89D527B2939900CA89E1 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
18CE89D327B2939900CA89E1 /* MatrixRustSDK */,
18CE89E327B2939A00CA89E1 /* MatrixRustSDKTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
18CE89D227B2939900CA89E1 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
18CE89DC27B2939A00CA89E1 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
18CE89E227B2939A00CA89E1 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
18CE89D027B2939900CA89E1 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
18CE89DA27B2939900CA89E1 /* ContentView.swift in Sources */,
189A89BA27B40BBF0048B0A5 /* sdk.swift in Sources */,
18CE89D827B2939900CA89E1 /* MatrixRustSDKApp.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
18CE89E027B2939A00CA89E1 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
18CE89E927B2939A00CA89E1 /* MatrixRustSDKTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
18CE89E627B2939A00CA89E1 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 18CE89D327B2939900CA89E1 /* MatrixRustSDK */;
targetProxy = 18CE89E527B2939A00CA89E1 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
18CE89F627B2939A00CA89E1 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.2;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
18CE89F727B2939A00CA89E1 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.2;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
18CE89F927B2939A00CA89E1 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = MatrixRustSDK/MatrixRustSDK.entitlements;
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = MatrixRustSDK/Info.plist;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = org.matrix.MatrixRustSDK;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_MACCATALYST = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "MatrixRustSDK/MatrixRustSDK-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
18CE89FA27B2939A00CA89E1 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = MatrixRustSDK/MatrixRustSDK.entitlements;
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = MatrixRustSDK/Info.plist;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = org.matrix.MatrixRustSDK;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_MACCATALYST = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "MatrixRustSDK/MatrixRustSDK-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
18CE89FC27B2939A00CA89E1 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.2;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = org.matrix.MatrixRustSDKTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MatrixRustSDK.app/MatrixRustSDK";
};
name = Debug;
};
18CE89FD27B2939A00CA89E1 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.2;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = org.matrix.MatrixRustSDKTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MatrixRustSDK.app/MatrixRustSDK";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
18CE89CF27B2939900CA89E1 /* Build configuration list for PBXProject "MatrixRustSDK" */ = {
isa = XCConfigurationList;
buildConfigurations = (
18CE89F627B2939A00CA89E1 /* Debug */,
18CE89F727B2939A00CA89E1 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
18CE89F827B2939A00CA89E1 /* Build configuration list for PBXNativeTarget "MatrixRustSDK" */ = {
isa = XCConfigurationList;
buildConfigurations = (
18CE89F927B2939A00CA89E1 /* Debug */,
18CE89FA27B2939A00CA89E1 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
18CE89FB27B2939A00CA89E1 /* Build configuration list for PBXNativeTarget "MatrixRustSDKTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
18CE89FC27B2939A00CA89E1 /* Debug */,
18CE89FD27B2939A00CA89E1 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 18CE89CC27B2939900CA89E1 /* Project object */;
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1320"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "18CE89D327B2939900CA89E1"
BuildableName = "MatrixRustSDK.app"
BlueprintName = "MatrixRustSDK"
ReferencedContainer = "container:MatrixRustSDK.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "18CE89E327B2939A00CA89E1"
BuildableName = "MatrixRustSDKTests.xctest"
BlueprintName = "MatrixRustSDKTests"
ReferencedContainer = "container:MatrixRustSDK.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "18CE89ED27B2939A00CA89E1"
BuildableName = "MatrixRustSDKUITests.xctest"
BlueprintName = "MatrixRustSDKUITests"
ReferencedContainer = "container:MatrixRustSDK.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "18CE89D327B2939900CA89E1"
BuildableName = "MatrixRustSDK.app"
BlueprintName = "MatrixRustSDK"
ReferencedContainer = "container:MatrixRustSDK.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "18CE89D327B2939900CA89E1"
BuildableName = "MatrixRustSDK.app"
BlueprintName = "MatrixRustSDK"
ReferencedContainer = "container:MatrixRustSDK.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,98 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,21 @@
//
// ContentView.swift
// MatrixRustSDK
//
// Created by Stefan Ceriu on 08.02.2022.
//
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Hello, Rust!")
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
</plist>
@@ -0,0 +1,5 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "sdkFFI.h"
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,17 @@
//
// MatrixRustSDKApp.swift
// MatrixRustSDK
//
// Created by Stefan Ceriu on 08.02.2022.
//
import SwiftUI
@main
struct MatrixRustSDKApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
@@ -0,0 +1,39 @@
//
// MatrixRustSDKTests.swift
// MatrixRustSDKTests
//
// Created by Stefan Ceriu on 08.02.2022.
//
import XCTest
@testable import MatrixRustSDK
class MatrixRustSDKTests: XCTestCase {
func testReadOnlyFileSystemError() {
do {
let client = try ClientBuilder()
.basePath(path: "")
.username(username: "@test:domain")
.build()
try client.login(username: "@test:domain", password: "test")
} catch ClientError.Generic(let message) {
XCTAssertNotNil(message.range(of: "Read-only file system"))
} catch {
XCTFail("Not expecting any other kind of exception")
}
}
// MARK: - Private
static private var basePath: String {
guard let url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else {
fatalError("Should always be able to retrieve the caches directory")
}
try? FileManager.default.createDirectory(at: url, withIntermediateDirectories: false, attributes: nil)
return url.path
}
}
+17
View File
@@ -0,0 +1,17 @@
Pod::Spec.new do |s|
s.name = "MatrixSDKCrypto"
s.version = "0.1.0"
s.summary = "Uniffi based bindings for the Rust SDK crypto crate."
s.homepage = "https://github.com/matrix-org/matrix-rust-sdk"
s.license = { :type => "Apache License, Version 2.0", :file => "LICENSE" }
s.author = { "matrix.org" => "support@matrix.org" }
s.ios.deployment_target = "11.0"
s.swift_versions = ['5.0']
s.source = { :http => "https://github.com/matrix-org/matrix-rust-sdk/releases/download/matrix-sdk-crypto-ffi-#{s.version}/MatrixSDKCryptoFFI.zip" }
s.vendored_frameworks = "MatrixSDKCryptoFFI.xcframework"
s.source_files = "Sources/**/*.{swift}"
end
+53
View File
@@ -0,0 +1,53 @@
# Apple platforms support
This project and build script demonstrate how to create an XCFramework that can be imported into an Xcode project and run on Apple platforms. It can compile and bundle an [entire SDK](#Building-the-SDK), or only a smaller [Crypto module](#Building-only-the-Crypto-SDK) that provides end-to-end encryption for clients that already depend on an SDK (e.g. [Matrix iOS SDK](https://github.com/matrix-org/matrix-ios-sdk))
## Prerequisites for building universal frameworks
* the Rust toolchain
* UniFFI - `cargo install uniffi_bindgen`
* Apple targets (e.g. `rustup target add aarch64-apple-ios`)
* `xcodebuild` command line tool from [Apple](https://developer.apple.com/library/archive/technotes/tn2339/_index.html)
* `lipo` for creating the fat static libs
## Building the SDK
```
sh build_xcframework.sh
```
The `build_xcframework.sh` script will go through all the steps required to generate a fully usable `.xcframework`:
1. compile `matrix-sdk-ffi` libraries for iOS, the iOS simulator, MacOS, and Mac Catalyst under `/target`. Some targets are not part of the standard library and they will be built using the nightly toolchain.
2. `lipo` together the libraries for the same platform under `/generated`
3. run `uniffi` and generate the C header, module map and swift files
4. `xcodebuild` an `xcframework` from the fat static libs and the original iOS one, and add the header and module map to it under `generated/MatrixSDKFFI.xcframework`
5. cleanup and delete the generated files except the .xcframework and the swift sources (that aren't part of the framework)
## Building only the Crypto SDK
```
sh build_crypto_xcframework.sh
```
The `build_crypto_xcframework.sh` script will go through all the steps required to generate a fully usable `.xcframework`:
1. compile `matrix-sdk-crypto-ffi` libraries for iOS and the iOS simulator under `/target`
2. `lipo` together the libraries for the same platform under `/generated`
3. run `uniffi` and generate the C header, module map and swift files
4. `xcodebuild` an `xcframework` from the fat static libs and the original iOS one, and add the header and module map to it under `generated/MatrixSDKCryptoFFI.xcframework`
5. cleanup and delete the generated files except the .xcframework and the swift sources (that aren't part of the framework)
## Running the Xcode project
The Xcode project is meant to provide a simple example on how to integrate everything together but also a place to run unit and integration tests from.
It's pre-configured to link to the generated .xcframework and .swift files so successfully running the script first is necessary for it to compile.
It makes the compiled code available to swift by importing the C header through its bridging header.
Once all the generated components are available running it should be as easy as choosing a platform and clicking run.
## Distribution
The generated framework and Swift code can be distributed and integrated directly but in order to make things simpler we bundle them together as a Swift package available [TBD](here) in the case of SDK, and as CocoaPods podspec in the case of Crypto SDK.
+73
View File
@@ -0,0 +1,73 @@
#!/usr/bin/env bash
set -eEu
cd "$(dirname "$0")"
# Path to the repo root
SRC_ROOT=../..
TARGET_DIR="${SRC_ROOT}/target"
GENERATED_DIR="${SRC_ROOT}/generated"
if [ -d "${GENERATED_DIR}" ]; then rm -rf "${GENERATED_DIR}"; fi
mkdir -p ${GENERATED_DIR}
REL_FLAG="--release"
REL_TYPE_DIR="release"
TARGET_CRATE=matrix-sdk-crypto-ffi
# Build static libs for all the different architectures
# iOS
cargo build -p ${TARGET_CRATE} ${REL_FLAG} --target "aarch64-apple-ios"
# iOS Simulator
cargo build -p ${TARGET_CRATE} ${REL_FLAG} --target "aarch64-apple-ios-sim"
cargo build -p ${TARGET_CRATE} ${REL_FLAG} --target "x86_64-apple-ios"
# Lipo together the libraries for the same platform
# iOS Simulator
lipo -create \
"${TARGET_DIR}/x86_64-apple-ios/${REL_TYPE_DIR}/libmatrix_crypto_ffi.a" \
"${TARGET_DIR}/aarch64-apple-ios-sim/${REL_TYPE_DIR}/libmatrix_crypto_ffi.a" \
-output "${GENERATED_DIR}/libmatrix_crypto_ffi.a"
# Generate uniffi files
uniffi-bindgen generate "${SRC_ROOT}/bindings/${TARGET_CRATE}/src/olm.udl" --language swift --config "${SRC_ROOT}/bindings/${TARGET_CRATE}/uniffi.toml" --out-dir ${GENERATED_DIR}
# Move headers to the right place
HEADERS_DIR=${GENERATED_DIR}/headers
mkdir -p ${HEADERS_DIR}
mv ${GENERATED_DIR}/*.h ${HEADERS_DIR}
# Rename and move modulemap to the right place
mv ${GENERATED_DIR}/*.modulemap ${HEADERS_DIR}/module.modulemap
# Move source files to the right place
SWIFT_DIR="${GENERATED_DIR}/Sources"
mkdir -p ${SWIFT_DIR}
mv ${GENERATED_DIR}/*.swift ${SWIFT_DIR}
# Build the xcframework
if [ -d "${GENERATED_DIR}/MatrixSDKCryptoFFI.xcframework" ]; then rm -rf "${GENERATED_DIR}/MatrixSDKCryptoFFI.xcframework"; fi
xcodebuild -create-xcframework \
-library "${TARGET_DIR}/aarch64-apple-ios/${REL_TYPE_DIR}/libmatrix_crypto_ffi.a" \
-headers ${HEADERS_DIR} \
-library "${GENERATED_DIR}/libmatrix_crypto_ffi.a" \
-headers ${HEADERS_DIR} \
-output "${GENERATED_DIR}/MatrixSDKCryptoFFI.xcframework"
# Cleanup
if [ -f "${TARGET_DIR}/aarch64-apple-ios-sim/${REL_TYPE_DIR}/libmatrix_crypto_ffi.a" ]; then rm -rf "${TARGET_DIR}/aarch64-apple-ios-sim/${REL_TYPE_DIR}/libmatrix_crypto_ffi.a"; fi
if [ -f "${GENERATED_DIR}/libmatrix_crypto_ffi.a" ]; then rm -rf "${GENERATED_DIR}/libmatrix_crypto_ffi.a"; fi
if [ -d ${HEADERS_DIR} ]; then rm -rf ${HEADERS_DIR}; fi
# Zip up framework, sources and LICENSE, ready to be uploaded to GitHub Releases and used by MatrixSDKCrypto.podspec
cp ${SRC_ROOT}/LICENSE $GENERATED_DIR
cd $GENERATED_DIR
zip -r MatrixSDKCryptoFFI.zip MatrixSDKCryptoFFI.xcframework Sources LICENSE
+89
View File
@@ -0,0 +1,89 @@
#!/usr/bin/env bash
set -eEu
cd "$(dirname "$0")"
# Path to the repo root
SRC_ROOT=../..
TARGET_DIR="${SRC_ROOT}/target"
GENERATED_DIR="${SRC_ROOT}/generated"
mkdir -p ${GENERATED_DIR}
REL_FLAG="--release"
REL_TYPE_DIR="release"
# Build static libs for all the different architectures
# iOS
cargo build -p matrix-sdk-ffi ${REL_FLAG} --target "aarch64-apple-ios"
# MacOS
cargo build -p matrix-sdk-ffi ${REL_FLAG} --target "aarch64-apple-darwin"
cargo build -p matrix-sdk-ffi ${REL_FLAG} --target "x86_64-apple-darwin"
# iOS Simulator
cargo build -p matrix-sdk-ffi ${REL_FLAG} --target "aarch64-apple-ios-sim"
cargo build -p matrix-sdk-ffi ${REL_FLAG} --target "x86_64-apple-ios"
# Mac Catalyst
cargo +nightly build -Z build-std -p matrix-sdk-ffi ${REL_FLAG} --target "aarch64-apple-ios-macabi"
cargo +nightly build -Z build-std -p matrix-sdk-ffi ${REL_FLAG} --target "x86_64-apple-ios-macabi"
# Lipo together the libraries for the same platform
# MacOS
lipo -create \
"${TARGET_DIR}/x86_64-apple-darwin/${REL_TYPE_DIR}/libmatrix_sdk_ffi.a" \
"${TARGET_DIR}/aarch64-apple-darwin/${REL_TYPE_DIR}/libmatrix_sdk_ffi.a" \
-output "${GENERATED_DIR}/libmatrix_sdk_ffi_macos.a"
# iOS Simulator
lipo -create \
"${TARGET_DIR}/x86_64-apple-ios/${REL_TYPE_DIR}/libmatrix_sdk_ffi.a" \
"${TARGET_DIR}/aarch64-apple-ios-sim/${REL_TYPE_DIR}/libmatrix_sdk_ffi.a" \
-output "${GENERATED_DIR}/libmatrix_sdk_ffi_iossimulator.a"
# Mac Catalyst
lipo -create \
"${TARGET_DIR}/x86_64-apple-ios-macabi/${REL_TYPE_DIR}/libmatrix_sdk_ffi.a" \
"${TARGET_DIR}/aarch64-apple-ios-macabi/${REL_TYPE_DIR}/libmatrix_sdk_ffi.a" \
-output "${GENERATED_DIR}/libmatrix_sdk_ffi_maccatalyst.a"
# Generate uniffi files
uniffi-bindgen generate "${SRC_ROOT}/bindings/matrix-sdk-ffi/src/api.udl" --language swift --out-dir ${GENERATED_DIR}
# Move them to the right place
HEADERS_DIR=${GENERATED_DIR}/headers
mkdir -p ${HEADERS_DIR}
mv ${GENERATED_DIR}/*.h ${GENERATED_DIR}/*.modulemap ${HEADERS_DIR}
SWIFT_DIR="${GENERATED_DIR}/swift"
mkdir -p ${SWIFT_DIR}
mv ${GENERATED_DIR}/*.swift ${SWIFT_DIR}
# Build the xcframework
if [ -d "${GENERATED_DIR}/MatrixSDKFFI.xcframework" ]; then rm -rf "${GENERATED_DIR}/MatrixSDKFFI.xcframework"; fi
xcodebuild -create-xcframework \
-library "${GENERATED_DIR}/libmatrix_sdk_ffi_macos.a" \
-headers ${HEADERS_DIR} \
-library "${GENERATED_DIR}/libmatrix_sdk_ffi_iossimulator.a" \
-headers ${HEADERS_DIR} \
-library "${GENERATED_DIR}/libmatrix_sdk_ffi_maccatalyst.a" \
-headers ${HEADERS_DIR} \
-library "${TARGET_DIR}/aarch64-apple-ios/${REL_TYPE_DIR}/libmatrix_sdk_ffi.a" \
-headers ${HEADERS_DIR} \
-output "${GENERATED_DIR}/MatrixSDKFFI.xcframework"
# Cleanup
if [ -f "${GENERATED_DIR}/libmatrix_sdk_ffi_macos.a" ]; then rm -rf "${GENERATED_DIR}/libmatrix_sdk_ffi_macos.a"; fi
if [ -f "${GENERATED_DIR}/libmatrix_sdk_ffi_iossimulator.a" ]; then rm -rf "${GENERATED_DIR}/libmatrix_sdk_ffi_iossimulator.a"; fi
if [ -f "${GENERATED_DIR}/libmatrix_sdk_ffi_maccatalyst.a" ]; then rm -rf "${GENERATED_DIR}/libmatrix_sdk_ffi_maccatalyst.a"; fi
if [ -d ${HEADERS_DIR} ]; then rm -rf ${HEADERS_DIR}; fi
+71
View File
@@ -0,0 +1,71 @@
#!/usr/bin/env bash
set -eEu
cd "$(dirname "$0")"
IS_CI=false
if [ $# -eq 1 ]; then
IS_CI=true
echo "Running CI build"
else
echo "Running debug build"
fi
# Path to the repo root
SRC_ROOT=../..
TARGET_DIR="${SRC_ROOT}/target"
GENERATED_DIR="${SRC_ROOT}/generated"
mkdir -p ${GENERATED_DIR}
REL_FLAG=""
REL_TYPE_DIR="debug"
# iOS Simulator
cargo +nightly build -p matrix-sdk-ffi ${REL_FLAG} --target "aarch64-apple-ios-sim"
cargo +nightly build -p matrix-sdk-ffi ${REL_FLAG} --target "x86_64-apple-ios"
lipo -create \
"${TARGET_DIR}/x86_64-apple-ios/${REL_TYPE_DIR}/libmatrix_sdk_ffi.a" \
"${TARGET_DIR}/aarch64-apple-ios-sim/${REL_TYPE_DIR}/libmatrix_sdk_ffi.a" \
-output "${GENERATED_DIR}/libmatrix_sdk_ffi_iossimulator.a"
# Generate uniffi files
uniffi-bindgen generate "${SRC_ROOT}/bindings/matrix-sdk-ffi/src/api.udl" --language swift --out-dir ${GENERATED_DIR}
# Move them to the right place
HEADERS_DIR=${GENERATED_DIR}/headers
mkdir -p ${HEADERS_DIR}
mv ${GENERATED_DIR}/*.h ${GENERATED_DIR}/*.modulemap ${HEADERS_DIR}
SWIFT_DIR="${GENERATED_DIR}/swift"
mkdir -p ${SWIFT_DIR}
mv ${GENERATED_DIR}/*.swift ${SWIFT_DIR}
# Build the xcframework
if [ -d "${GENERATED_DIR}/MatrixSDKFFI.xcframework" ]; then rm -rf "${GENERATED_DIR}/MatrixSDKFFI.xcframework"; fi
xcodebuild -create-xcframework \
-library "${GENERATED_DIR}/libmatrix_sdk_ffi_iossimulator.a" \
-headers ${HEADERS_DIR} \
-output "${GENERATED_DIR}/MatrixSDKFFI.xcframework"
# Cleanup
# if [ -f "${GENERATED_DIR}/libmatrix_sdk_ffi_iossimulator.a" ]; then rm -rf "${GENERATED_DIR}/libmatrix_sdk_ffi_iossimulator.a"; fi
# if [ -d ${HEADERS_DIR} ]; then rm -rf ${HEADERS_DIR}; fi
if [ "$IS_CI" = false ] ; then
echo "Preparing matrix-rust-components-swift"
# Debug -> Copy generated files over to ../../../matrix-rust-components-swift
echo "$(printf "import MatrixSDKFFIWrapper\n\n"; cat "${SWIFT_DIR}/sdk.swift")" > "${SWIFT_DIR}/sdk.swift"
rsync -a --delete "${GENERATED_DIR}/MatrixSDKFFI.xcframework" "${SRC_ROOT}/../matrix-rust-components-swift/"
rsync -a --delete "${GENERATED_DIR}/swift/" "${SRC_ROOT}/../matrix-rust-components-swift/Sources/MatrixRustSDK"
fi
+66
View File
@@ -0,0 +1,66 @@
[package]
name = "matrix-sdk-crypto-ffi"
version = "0.1.0"
authors = ["Damir Jelić <poljar@termina.org.uk>"]
edition = "2018"
rust-version = "1.60"
description = "Uniffi based bindings for the Rust SDK crypto crate"
repository = "https://github.com/matrix-org/matrix-rust-sdk"
license = "Apache-2.0"
publish = false
[lib]
crate-type = ["cdylib", "staticlib"]
name = "matrix_crypto_ffi"
[dependencies]
anyhow = "1.0.57"
base64 = "0.13.0"
hmac = "0.12.1"
http = "0.2.6"
pbkdf2 = "0.11.0"
rand = "0.8.5"
ruma = { git = "https://github.com/ruma/ruma", rev = "96155915f", features = ["client-api-c"] }
serde = "1.0.136"
serde_json = "1.0.79"
sha2 = "0.10.2"
thiserror = "1.0.30"
tracing = "0.1.34"
tracing-subscriber = { version = "0.3.11", features = ["env-filter"] }
# keep in sync with uniffi dependency in matrix-sdk-ffi, and uniffi_bindgen in ffi CI job
uniffi = "0.18.0"
zeroize = { version = "1.3.0", features = ["zeroize_derive"] }
[dependencies.js_int]
version = "0.2.2"
features = ["lax_deserialize"]
[dependencies.matrix-sdk-common]
path = "../../crates/matrix-sdk-common"
version = "0.5.0"
[dependencies.matrix-sdk-crypto]
path = "../../crates/matrix-sdk-crypto"
version = "0.5.0"
features = ["qrcode", "backups_v1"]
[dependencies.matrix-sdk-sled]
path = "../../crates/matrix-sdk-sled"
version = "0.1.0"
default_features = false
features = ["crypto-store"]
[dependencies.tokio]
version = "1.17.0"
default_features = false
features = ["rt-multi-thread"]
[dependencies.vodozemac]
git = "https://github.com/matrix-org/vodozemac/"
rev = "2404f83f7d3a3779c1f518e4d949f7da9677c3dd"
[build-dependencies]
uniffi_build = { version = "0.18.0", features = ["builtin-bindgen"] }
[dev-dependencies]
tempfile = "3.3.0"
+84
View File
@@ -0,0 +1,84 @@
# Uniffi based bindings for the Rust SDK crypto crate.
This crate contains Uniffi based bindings for the `matrix-sdk-crypto` crate. The
README mainly describes how to build and integrate the bindings into a Kotlin
based Android project, but the Android specific bits can be skipped if you are
targeting an x86 Linux project.
## Prerequisites
### Rust
To build the bindings [Rust] will be needed it can be either installed using an
OS specific package manager or directly with the provided [installer](https://rustup.rs/).
### Android NDK
The Android NDK will be required as well, it can be installed either through
Android Studio or directly using an [installer](https://developer.android.com/ndk/downloads).
### Configuring Rust for cross compilation
First we'll need to install the Rust target for our desired Android architecture,
for example:
```
# rustup target add aarch64-linux-android
```
This will add support to cross-compile for the aarch64-linux-android target,
Rust supports many different [targets], you'll have to make sure to pick the
right one for your device or emulator.
After this is done, we'll have to configure [Cargo] to use the correct linker
for our target. Cargo is configured using a TOML file that will be found in
`%USERPROFILE%\.cargo\config.toml` on Windows or `$HOME/.cargo/config` on Unix
platforms. More details and configuration options for Cargo can be found in the
official docs over [here](https://doc.rust-lang.org/cargo/reference/config.html).
```
[target.aarch64-linux-android]
ar = "NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/ar"
linker = "NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang"
```
## Building
To enable cross compilation for `olm-sys` which builds our `libolm` C library
we'll need to set the `ANDROID_NDK` environment variable to the location of our
Android NDK installation.
```
$ export ANDROID_NDK=$HOME/Android/Sdk/ndk/22.0.7026061/
```
### Building for a target
The bindings can built for the `aarch64` target with:
```
$ cargo build --target aarch64-linux-android
```
After that, a dynamic library can be found in the `target/aarch64-linux-android/debug` directory.
The library will be called `libmatrix_crypto.so` and needs to be renamed and
copied into the `jniLibs` directory of your Android project, for Element Android:
```
$ cp ../../target/aarch64-linux-android/debug/libmatrix_crypto.so \
/home/example/matrix-sdk-android/src/main/jniLibs/aarch64/libuniffi_olm.so
```
## Minimum Supported Rust Version (MSRV)
These crates are built with the Rust language version 2021 and require a minimum compiler version of `1.60`.
## License
[Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0)
[Rust]: https://www.rust-lang.org/
[installer]: https://rustup.rs/
[targets]: https://doc.rust-lang.org/nightly/rustc/platform-support.html
[Cargo]: https://doc.rust-lang.org/cargo/
[uniffi]: https://github.com/mozilla/uniffi-rs/
+3
View File
@@ -0,0 +1,3 @@
fn main() {
uniffi_build::generate_scaffolding("./src/olm.udl").unwrap();
}
@@ -0,0 +1,157 @@
use std::{collections::HashMap, iter, ops::DerefMut};
use hmac::Hmac;
use matrix_sdk_crypto::{
backups::OlmPkDecryptionError,
store::{CryptoStoreError as InnerStoreError, RecoveryKey},
};
use pbkdf2::pbkdf2;
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use sha2::Sha512;
use thiserror::Error;
use zeroize::Zeroize;
/// The private part of the backup key, the one used for recovery.
pub struct BackupRecoveryKey {
pub(crate) inner: RecoveryKey,
pub(crate) passphrase_info: Option<PassphraseInfo>,
}
/// Error type for the decryption of backed up room keys.
#[derive(Debug, Error)]
pub enum PkDecryptionError {
/// An internal libolm error happened during decryption.
#[error("Error decryption a PkMessage {0}")]
Olm(#[from] OlmPkDecryptionError),
}
/// Error type for the decoding and storing of the backup key.
#[derive(Debug, Error)]
pub enum DecodeError {
/// An error happened while decoding the recovery key.
#[error(transparent)]
Decode(#[from] matrix_sdk_crypto::backups::DecodeError),
/// An error happened in the storage layer while trying to save the
/// decoded recovery key.
#[error(transparent)]
CryptoStore(#[from] InnerStoreError),
}
/// Struct containing info about the way the backup key got derived from a
/// passphrase.
#[derive(Debug, Clone)]
pub struct PassphraseInfo {
/// The salt that was used during key derivation.
pub private_key_salt: String,
/// The number of PBKDF rounds that were used for key derivation.
pub private_key_iterations: i32,
}
/// The public part of the backup key.
pub struct MegolmV1BackupKey {
/// The actual base64 encoded public key.
pub public_key: String,
/// Signatures that have signed our backup key.
pub signatures: HashMap<String, HashMap<String, String>>,
/// The passphrase info, if the key was derived from one.
pub passphrase_info: Option<PassphraseInfo>,
/// Get the full name of the backup algorithm this backup key supports.
pub backup_algorithm: String,
}
impl BackupRecoveryKey {
const KEY_SIZE: usize = 32;
const SALT_SIZE: usize = 32;
const PBKDF_ROUNDS: i32 = 500_000;
/// Create a new random [`BackupRecoveryKey`].
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
Self {
inner: RecoveryKey::new()
.expect("Can't gather enough randomness to create a recovery key"),
passphrase_info: None,
}
}
/// Try to create a [`BackupRecoveryKey`] from a base 64 encoded string.
pub fn from_base64(key: String) -> Result<Self, DecodeError> {
Ok(Self { inner: RecoveryKey::from_base64(&key)?, passphrase_info: None })
}
/// Try to create a [`BackupRecoveryKey`] from a base 58 encoded string.
pub fn from_base58(key: String) -> Result<Self, DecodeError> {
Ok(Self { inner: RecoveryKey::from_base58(&key)?, passphrase_info: None })
}
/// Create a new [`BackupRecoveryKey`] from the given passphrase.
pub fn new_from_passphrase(passphrase: String) -> Self {
let mut rng = thread_rng();
let salt: String = iter::repeat(())
.map(|()| rng.sample(Alphanumeric))
.map(char::from)
.take(Self::SALT_SIZE)
.collect();
Self::from_passphrase(passphrase, salt, Self::PBKDF_ROUNDS)
}
/// Restore a [`BackupRecoveryKey`] from the given passphrase.
pub fn from_passphrase(passphrase: String, salt: String, rounds: i32) -> Self {
let mut key = Box::new([0u8; Self::KEY_SIZE]);
let rounds = rounds as u32;
pbkdf2::<Hmac<Sha512>>(passphrase.as_bytes(), salt.as_bytes(), rounds, key.deref_mut());
let recovery_key = RecoveryKey::from_bytes(&key);
key.zeroize();
Self {
inner: recovery_key,
passphrase_info: Some(PassphraseInfo {
private_key_salt: salt,
private_key_iterations: rounds as i32,
}),
}
}
/// Get the public part of the backup key.
pub fn megolm_v1_public_key(&self) -> MegolmV1BackupKey {
let public_key = self.inner.megolm_v1_public_key();
let signatures: HashMap<String, HashMap<String, String>> = public_key
.signatures()
.into_iter()
.map(|(k, v)| (k.to_string(), v.into_iter().map(|(k, v)| (k.to_string(), v)).collect()))
.collect();
MegolmV1BackupKey {
public_key: public_key.to_base64(),
signatures,
passphrase_info: self.passphrase_info.clone(),
backup_algorithm: public_key.backup_algorithm().to_owned(),
}
}
/// Convert the recovery key to a base 58 encoded string.
pub fn to_base58(&self) -> String {
self.inner.to_base58()
}
/// Convert the recovery key to a base 64 encoded string.
pub fn to_base64(&self) -> String {
self.inner.to_base64()
}
/// Try to decrypt a message that was encrypted using the public part of the
/// backup key.
pub fn decrypt_v1(
&self,
ephemeral_key: String,
mac: String,
ciphertext: String,
) -> Result<String, PkDecryptionError> {
self.inner.decrypt_v1(ephemeral_key, mac, ciphertext).map_err(|e| e.into())
}
}
@@ -0,0 +1,42 @@
use std::collections::HashMap;
use matrix_sdk_crypto::Device as InnerDevice;
/// An E2EE capable Matrix device.
pub struct Device {
/// The device owner.
pub user_id: String,
/// The unique ID of the device.
pub device_id: String,
/// The published public identity keys of the devices
///
/// A map from the key type (e.g. curve25519) to the base64 encoded key.
pub keys: HashMap<String, String>,
/// The supported algorithms of the device.
pub algorithms: Vec<String>,
/// The human readable name of the device.
pub display_name: Option<String>,
/// A flag indicating if the device has been blocked, blocked devices don't
/// receive any room keys from us.
pub is_blocked: bool,
/// Is the device locally trusted
pub locally_trusted: bool,
/// Is our cross signing identity trusted and does the identity trust the
/// device.
pub cross_signing_trusted: bool,
}
impl From<InnerDevice> for Device {
fn from(d: InnerDevice) -> Self {
Device {
user_id: d.user_id().to_string(),
device_id: d.device_id().to_string(),
keys: d.keys().iter().map(|(k, v)| (k.to_string(), v.to_base64())).collect(),
algorithms: d.algorithms().iter().map(|a| a.to_string()).collect(),
display_name: d.display_name().map(|d| d.to_owned()),
is_blocked: d.is_blacklisted(),
locally_trusted: d.is_locally_trusted(),
cross_signing_trusted: d.is_cross_signing_trusted(),
}
}
}
@@ -0,0 +1,63 @@
#![allow(missing_docs)]
use matrix_sdk_crypto::{
store::CryptoStoreError as InnerStoreError, KeyExportError, MegolmError, OlmError,
SecretImportError as RustSecretImportError, SignatureError as InnerSignatureError,
};
use ruma::{IdParseError, OwnedUserId};
#[derive(Debug, thiserror::Error)]
pub enum KeyImportError {
#[error(transparent)]
Export(#[from] KeyExportError),
#[error(transparent)]
CryptoStore(#[from] InnerStoreError),
#[error(transparent)]
Json(#[from] serde_json::Error),
}
#[derive(Debug, thiserror::Error)]
pub enum SecretImportError {
#[error(transparent)]
CryptoStore(#[from] InnerStoreError),
#[error(transparent)]
Import(#[from] RustSecretImportError),
}
#[derive(Debug, thiserror::Error)]
pub enum SignatureError {
#[error(transparent)]
Signature(#[from] InnerSignatureError),
#[error(transparent)]
Identifier(#[from] IdParseError),
#[error(transparent)]
CryptoStore(#[from] InnerStoreError),
#[error("Unknown device {0} {1}")]
UnknownDevice(OwnedUserId, String),
#[error("Unknown user identity {0}")]
UnknownUserIdentity(String),
}
#[derive(Debug, thiserror::Error)]
pub enum CryptoStoreError {
#[error(transparent)]
CryptoStore(#[from] InnerStoreError),
#[error(transparent)]
OlmError(#[from] OlmError),
#[error(transparent)]
Serialization(#[from] serde_json::Error),
#[error("The given string is not a valid user ID: source {0}, error {1}")]
InvalidUserId(String, IdParseError),
#[error(transparent)]
Identifier(#[from] IdParseError),
}
#[derive(Debug, thiserror::Error)]
pub enum DecryptionError {
#[error(transparent)]
Serialization(#[from] serde_json::Error),
#[error(transparent)]
Identifier(#[from] IdParseError),
#[error(transparent)]
Megolm(#[from] MegolmError),
}
+591
View File
@@ -0,0 +1,591 @@
//! Uniffi based bindings for the `matrix-sdk-crypto` crate.
//!
//! This crate can be used to introduce E2EE support into an existing Matrix
//! client or client library in any of the language targets Uniffi supports.
#![warn(missing_docs)]
mod backup_recovery_key;
mod device;
mod error;
mod logger;
mod machine;
mod responses;
mod users;
mod verification;
use std::{borrow::Borrow, collections::HashMap, convert::TryFrom, str::FromStr, sync::Arc};
pub use backup_recovery_key::{
BackupRecoveryKey, DecodeError, MegolmV1BackupKey, PassphraseInfo, PkDecryptionError,
};
pub use device::Device;
pub use error::{
CryptoStoreError, DecryptionError, KeyImportError, SecretImportError, SignatureError,
};
use js_int::UInt;
pub use logger::{set_logger, Logger};
pub use machine::{KeyRequestPair, OlmMachine};
pub use responses::{
BootstrapCrossSigningResult, DeviceLists, KeysImportResult, OutgoingVerificationRequest,
Request, RequestType, SignatureUploadRequest, UploadSigningKeysRequest,
};
use ruma::{DeviceId, DeviceKeyAlgorithm, OwnedUserId, RoomId, SecondsSinceUnixEpoch, UserId};
use serde::{Deserialize, Serialize};
pub use users::UserIdentity;
pub use verification::{
CancelInfo, ConfirmVerificationResult, QrCode, RequestVerificationResult, Sas, ScanResult,
StartSasResult, Verification, VerificationRequest,
};
/// Struct collecting data that is important to migrate to the rust-sdk
#[derive(Deserialize, Serialize)]
pub struct MigrationData {
/// The pickled version of the Olm Account
account: PickledAccount,
/// The list of pickleds Olm Sessions.
sessions: Vec<PickledSession>,
/// The list of Megolm inbound group sessions.
inbound_group_sessions: Vec<PickledInboundGroupSession>,
/// The Olm pickle key that was used to pickle all the Olm objects.
pickle_key: Vec<u8>,
/// The backup version that is currently active.
backup_version: Option<String>,
// The backup recovery key, as a base58 encoded string.
backup_recovery_key: Option<String>,
/// The private cross signing keys.
cross_signing: CrossSigningKeyExport,
/// The list of users that the Rust SDK should track.
tracked_users: Vec<String>,
}
/// A pickled version of an `Account`.
///
/// Holds all the information that needs to be stored in a database to restore
/// an account.
#[derive(Debug, Deserialize, Serialize)]
pub struct PickledAccount {
/// The user id of the account owner.
pub user_id: String,
/// The device ID of the account owner.
pub device_id: String,
/// The pickled version of the Olm account.
pub pickle: String,
/// Was the account shared.
pub shared: bool,
/// The number of uploaded one-time keys we have on the server.
pub uploaded_signed_key_count: i64,
}
/// A pickled version of a `Session`.
///
/// Holds all the information that needs to be stored in a database to restore
/// a Session.
#[derive(Debug, Deserialize, Serialize)]
pub struct PickledSession {
/// The pickle string holding the Olm Session.
pub pickle: String,
/// The curve25519 key of the other user that we share this session with.
pub sender_key: String,
/// Was the session created using a fallback key.
pub created_using_fallback_key: bool,
/// The Unix timestamp when the session was created.
pub creation_time: String,
/// The Unix timestamp when the session was last used.
pub last_use_time: String,
}
/// A pickled version of an `InboundGroupSession`.
///
/// Holds all the information that needs to be stored in a database to restore
/// an InboundGroupSession.
#[derive(Debug, Deserialize, Serialize)]
pub struct PickledInboundGroupSession {
/// The pickle string holding the InboundGroupSession.
pub pickle: String,
/// The public curve25519 key of the account that sent us the session
pub sender_key: String,
/// The public ed25519 key of the account that sent us the session.
pub signing_key: HashMap<String, String>,
/// The id of the room that the session is used in.
pub room_id: String,
/// The list of claimed ed25519 that forwarded us this key. Will be empty if
/// we directly received this session.
pub forwarding_chains: Vec<String>,
/// Flag remembering if the session was directly sent to us by the sender
/// or if it was imported.
pub imported: bool,
/// Flag remembering if the session has been backed up.
pub backed_up: bool,
}
/// Error type for the migration process.
#[derive(thiserror::Error, Debug)]
pub enum MigrationError {
/// Generic catch all error variant.
#[error("error migrating database: {error_message}")]
Generic {
/// The error message
error_message: String,
},
}
impl From<anyhow::Error> for MigrationError {
fn from(e: anyhow::Error) -> MigrationError {
MigrationError::Generic { error_message: e.to_string() }
}
}
/// Migrate a libolm based setup to a vodozemac based setup stored in a Sled
/// store.
///
/// # Arguments
///
/// * `data` - The data that should be migrated over to the Sled store.
///
/// * `path` - The path where the Sled store should be created.
///
/// * `passphrase` - The passphrase that should be used to encrypt the data at
/// rest in the Sled store. **Warning**, if no passphrase is given, the store
/// and all its data will remain unencrypted.
///
/// * `progress_listener` - A callback that can be used to introspect the
/// progress of the migration.
pub fn migrate(
mut data: MigrationData,
path: &str,
passphrase: Option<String>,
progress_listener: Box<dyn ProgressListener>,
) -> anyhow::Result<()> {
use matrix_sdk_crypto::{
olm::PrivateCrossSigningIdentity,
store::{Changes as RustChanges, CryptoStore, RecoveryKey},
};
use matrix_sdk_sled::CryptoStore as SledStore;
use tokio::runtime::Runtime;
use vodozemac::{
megolm::InboundGroupSession,
olm::{Account, Session},
Curve25519PublicKey,
};
use zeroize::Zeroize;
// The total steps here include all the sessions/inbound group sessions and
// additionally some static number of steps:
//
// 1. opening the store
// 2. the Account
// 3. the cross signing keys
// 4. the tracked users
// 5. the final save operation
let total_steps = 5 + data.sessions.len() + data.inbound_group_sessions.len();
let mut processed_steps = 0;
let listener = |progress: usize, total: usize| {
progress_listener.on_progress(progress as i32, total as i32)
};
let store = SledStore::open_with_passphrase(path, passphrase.as_deref())?;
let runtime = Runtime::new()?;
processed_steps += 1;
listener(processed_steps, total_steps);
let user_id: Arc<UserId> = {
let user_id: OwnedUserId = parse_user_id(&data.account.user_id)?;
let user_id: &UserId = user_id.borrow();
user_id.into()
};
let device_id: Box<DeviceId> = data.account.device_id.into();
let device_id: Arc<DeviceId> = device_id.into();
let account = Account::from_libolm_pickle(&data.account.pickle, &data.pickle_key)?;
let pickle = account.pickle();
let identity_keys = Arc::new(account.identity_keys());
let pickled_account = matrix_sdk_crypto::olm::PickledAccount {
user_id: parse_user_id(&data.account.user_id)?,
device_id: device_id.as_ref().to_owned(),
pickle,
shared: data.account.shared,
uploaded_signed_key_count: data.account.uploaded_signed_key_count as u64,
};
let account = matrix_sdk_crypto::olm::ReadOnlyAccount::from_pickle(pickled_account)?;
processed_steps += 1;
listener(processed_steps, total_steps);
let mut sessions = Vec::new();
for session_pickle in data.sessions {
let pickle =
Session::from_libolm_pickle(&session_pickle.pickle, &data.pickle_key)?.pickle();
let creation_time = SecondsSinceUnixEpoch(UInt::from_str(&session_pickle.creation_time)?);
let last_use_time = SecondsSinceUnixEpoch(UInt::from_str(&session_pickle.last_use_time)?);
let pickle = matrix_sdk_crypto::olm::PickledSession {
pickle,
sender_key: Curve25519PublicKey::from_base64(&session_pickle.sender_key)?,
created_using_fallback_key: session_pickle.created_using_fallback_key,
creation_time,
last_use_time,
};
let session = matrix_sdk_crypto::olm::Session::from_pickle(
user_id.clone(),
device_id.clone(),
identity_keys.clone(),
pickle,
);
sessions.push(session);
processed_steps += 1;
listener(processed_steps, total_steps);
}
let mut inbound_group_sessions = Vec::new();
for session in data.inbound_group_sessions {
let pickle =
InboundGroupSession::from_libolm_pickle(&session.pickle, &data.pickle_key)?.pickle();
let pickle = matrix_sdk_crypto::olm::PickledInboundGroupSession {
pickle,
sender_key: session.sender_key,
signing_key: session
.signing_key
.into_iter()
.map(|(k, v)| Ok((DeviceKeyAlgorithm::try_from(k)?, v)))
.collect::<anyhow::Result<_>>()?,
room_id: RoomId::parse(session.room_id)?,
forwarding_chains: session.forwarding_chains,
imported: session.imported,
backed_up: session.backed_up,
history_visibility: None,
};
let session = matrix_sdk_crypto::olm::InboundGroupSession::from_pickle(pickle)?;
inbound_group_sessions.push(session);
processed_steps += 1;
listener(processed_steps, total_steps);
}
let recovery_key =
data.backup_recovery_key.map(|k| RecoveryKey::from_base58(k.as_str())).transpose()?;
let cross_signing = PrivateCrossSigningIdentity::empty((*user_id).into());
runtime.block_on(cross_signing.import_secrets_unchecked(
data.cross_signing.master_key.as_deref(),
data.cross_signing.self_signing_key.as_deref(),
data.cross_signing.user_signing_key.as_deref(),
))?;
data.cross_signing.master_key.zeroize();
data.cross_signing.self_signing_key.zeroize();
data.cross_signing.user_signing_key.zeroize();
processed_steps += 1;
listener(processed_steps, total_steps);
let tracked_users: Vec<_> = data
.tracked_users
.into_iter()
.map(|u| Ok(((parse_user_id(&u)?), true)))
.collect::<anyhow::Result<_>>()?;
let tracked_users: Vec<_> = tracked_users.iter().map(|(u, d)| (&**u, *d)).collect();
runtime.block_on(store.save_tracked_users(tracked_users.as_slice()))?;
processed_steps += 1;
listener(processed_steps, total_steps);
let changes = RustChanges {
account: Some(account),
private_identity: Some(cross_signing),
sessions,
inbound_group_sessions,
recovery_key,
backup_version: data.backup_version,
..Default::default()
};
runtime.block_on(store.save_changes(changes))?;
processed_steps += 1;
listener(processed_steps, total_steps);
Ok(())
}
/// Callback that will be passed over the FFI to report progress
pub trait ProgressListener {
/// The callback that should be called on the Rust side
///
/// # Arguments
///
/// * `progress` - The current number of items that have been handled
///
/// * `total` - The total number of items that will be handled
fn on_progress(&self, progress: i32, total: i32);
}
impl<T: Fn(i32, i32)> ProgressListener for T {
fn on_progress(&self, progress: i32, total: i32) {
self(progress, total)
}
}
/// An event that was successfully decrypted.
pub struct DecryptedEvent {
/// The decrypted version of the event.
pub clear_event: String,
/// The claimed curve25519 key of the sender.
pub sender_curve25519_key: String,
/// The claimed ed25519 key of the sender.
pub claimed_ed25519_key: Option<String>,
/// The curve25519 chain of the senders that forwarded the Megolm decryption
/// key to us. Is empty if the key came directly from the sender of the
/// event.
pub forwarding_curve25519_chain: Vec<String>,
}
/// Struct representing the state of our private cross signing keys, it shows
/// which private cross signing keys we have locally stored.
#[derive(Debug, Clone)]
pub struct CrossSigningStatus {
/// Do we have the master key.
pub has_master: bool,
/// Do we have the self signing key, this one is necessary to sign our own
/// devices.
pub has_self_signing: bool,
/// Do we have the user signing key, this one is necessary to sign other
/// users.
pub has_user_signing: bool,
}
/// A struct containing private cross signing keys that can be backed up or
/// uploaded to the secret store.
#[derive(Deserialize, Serialize)]
pub struct CrossSigningKeyExport {
/// The seed of the master key encoded as unpadded base64.
pub master_key: Option<String>,
/// The seed of the self signing key encoded as unpadded base64.
pub self_signing_key: Option<String>,
/// The seed of the user signing key encoded as unpadded base64.
pub user_signing_key: Option<String>,
}
/// Struct holding the number of room keys we have.
pub struct RoomKeyCounts {
/// The total number of room keys.
pub total: i64,
/// The number of backed up room keys.
pub backed_up: i64,
}
/// Backup keys and information we load from the store.
pub struct BackupKeys {
/// The recovery key as a base64 encoded string.
recovery_key: Arc<BackupRecoveryKey>,
/// The version that is used with the recovery key.
backup_version: String,
}
impl BackupKeys {
/// Get the recovery key that we're holding on to.
pub fn recovery_key(&self) -> Arc<BackupRecoveryKey> {
self.recovery_key.clone()
}
/// Get the backups version that we're holding on to.
pub fn backup_version(&self) -> String {
self.backup_version.to_owned()
}
}
impl TryFrom<matrix_sdk_crypto::store::BackupKeys> for BackupKeys {
type Error = ();
fn try_from(keys: matrix_sdk_crypto::store::BackupKeys) -> Result<Self, Self::Error> {
Ok(Self {
recovery_key: BackupRecoveryKey {
inner: keys.recovery_key.ok_or(())?,
passphrase_info: None,
}
.into(),
backup_version: keys.backup_version.ok_or(())?,
})
}
}
impl From<matrix_sdk_crypto::store::RoomKeyCounts> for RoomKeyCounts {
fn from(count: matrix_sdk_crypto::store::RoomKeyCounts) -> Self {
Self { total: count.total as i64, backed_up: count.backed_up as i64 }
}
}
impl From<matrix_sdk_crypto::CrossSigningKeyExport> for CrossSigningKeyExport {
fn from(e: matrix_sdk_crypto::CrossSigningKeyExport) -> Self {
Self {
master_key: e.master_key.clone(),
self_signing_key: e.self_signing_key.clone(),
user_signing_key: e.user_signing_key.clone(),
}
}
}
impl From<CrossSigningKeyExport> for matrix_sdk_crypto::CrossSigningKeyExport {
fn from(e: CrossSigningKeyExport) -> Self {
matrix_sdk_crypto::CrossSigningKeyExport {
master_key: e.master_key,
self_signing_key: e.self_signing_key,
user_signing_key: e.user_signing_key,
}
}
}
impl From<matrix_sdk_crypto::CrossSigningStatus> for CrossSigningStatus {
fn from(s: matrix_sdk_crypto::CrossSigningStatus) -> Self {
Self {
has_master: s.has_master,
has_self_signing: s.has_self_signing,
has_user_signing: s.has_user_signing,
}
}
}
fn parse_user_id(user_id: &str) -> Result<OwnedUserId, CryptoStoreError> {
ruma::UserId::parse(user_id).map_err(|e| CryptoStoreError::InvalidUserId(user_id.to_owned(), e))
}
#[allow(warnings)]
mod generated {
use super::*;
include!(concat!(env!("OUT_DIR"), "/olm.uniffi.rs"));
}
pub use generated::*;
#[cfg(test)]
mod test {
use anyhow::Result;
use serde_json::{json, Value};
use tempfile::tempdir;
use super::MigrationData;
use crate::{migrate, OlmMachine};
#[test]
fn android_migration() -> Result<()> {
let data: Value = json!({
"account":{
"user_id":"@ganfra146:matrix.org",
"device_id":"DEWRCMENGS",
"pickle":"FFGTGho89T3Xgd56l+EedOPV37s09RR8aYnS9305qPKF66LG+ly29YpCibjJOvkwm0dZwN9A2bOH/z7WscriqwZn/p0GE6YSNwLzffCy5iROzYzpYzFe0HtiyJmCQWCezvLc5lHV8YsfD00C1pKGX2R9M1wwp3/n4/3VjtTyPsdnmtwAPu4WdcPSkisCaQ3a6JaSKqv8zYzUjnpzgcpXHvPUR5d5+TzXgrVz3BeCOe8NEOWIW6xYUxFtGteYP0BczOkkJ22t7Css0tSMSrYgCll4zZUGNrd6D9b/z7KwcDnb978epsZ16DcZ/aaTxPdM5uDIkHgF/qHWerfxcaqsqs4EQfJdSgOTeqhjHBw1k0uWF2bByJLK+n7sGkYXEAuTzc4+0XvSFvu3Qp+1bHZuT7QejngRZzyxznORyBxd8la3/JjeJlehSK80OL7zSmohoYZD59S6i3tFWfopjQThJ0/eIyVOhEN/c3tfIcVr3lFEQeokgpCRNOVldhPcQWq994NHaL7jtb6yhUqT1gShY4zYayFL/VRz6nBSXXYwzrC9jho67knqXSri3lIKYevP9aOi384IvzbkinQdumc804dYwiCbs5hZppfEnfhfgiDDm+kVrJ9WaPRF4SySCTlS8jdGmBeL2CfCQ5IcZ5nK6X7tZM3tmtYwva0RuQiTNltp3XTfbMa0EoaEBximv25165hFTpzrWgoszBTpZPfgsMuWENWBcIX4AcLSk0CJ0qzPDeUwvmRcFStstGYV4drs5u5HEqovFSI48CoHPSEZfwwERCI4c/0efZ0CVEfnm8VcMv3AbnAfedD7v3QNdVwWOEhz/fGR76BQi2WjZP4MWvYRJ/vsLO5hcVWUvaJGQs5kANUFZMWuJQeJv3DmkV9kKKXnyfFUerlQ4Uk/5tp2mXiG+adHjuRp/Eeh5V/biCcIaX3rNuIY6MJaPz6SOwlFe79MMBaNwaS3j4Kh/Aq9BRw0QXdjO4CqMI4p2xCE1N5QTPdeaRTHTZ3r7mLkHX3FpZMxitc8vDl9L2FRoSOMMh/sRD1boBCkjrsty9rvTUGYY3li05jBuTXnYMjA4zj79dC9TGo4g+/wi+h537EhtP5+170LwqnIzfHt8yfjbsMMC7iwLpC1C57sTwxpMkNo3nQEvZOfqCxjq+ihiGuL9iN5lSstu9/C4qP2tQll86ASXf1axxRZQlUB0hlLHbEW6/7O7xOU6FTs4yXAZC04souRkggmfhDzZ9kQmN/zRTbqlATFI7l9/0VGxwLOVnCMUhgiDX5yL8CYK9I4ENMLf5zOuO6P3GbYISjEoHC7fUOzQ6OwGgLyI0wCEVdSJzQcdKh+W15VV+eDjhE/qEJHQWx024hTQFTKYHlDn95+lMmRI9BJLP1HU2JW6onVWsTsE5zSYu9jLj739EKfV4gS/pWzoQDRa7a9ZG6+m+RrwyJhCso3gkUekDNobhFlDX6YeH+Btj91N0uS3F9qr8lbo491s/z2fNV42zT4NYObzgrAYDQAV/2WYF8tXtxLV/Jzk8AMmyr/cfNaT2dXxVJKWq+nN2BYHBmg9CCWPJ2aB/1WWIcHfcDOlngtH991gP6246f/DEaVC/Ayxz7bPtSH5tlZ4Xbpc2P4BYxaRp/yxhhQ2C9H2I/PTt3mnNNgky/t8PZrN3W5+eiSVE9sONF8G3mYsa4XFqM+KxfbPUqsrEnrRBmvmJ250hpTPkFcIF775RvvRRKALXdlTKs+S4HKDW7KoP0Dm9+r4RlO0UHpWND9w0WSMItvWQyo0VViXJgZfBjYtWDoO0Ud+Kc7PLWNX6RUKY7RlDjXadJTC4adH6CN3UBC/ouqqfTrYvPOkyd2oKf4RLjEVcFAUIftFbLy+WBcWv8072nnAFJIlm3CxGq++80TyjqFR45P+qfIJavxQNIt5zhHPfMgHjX27OA3+l7rHDxqfMLBPxhtARwlyF+qx1IJiSWbmlHkdz2ylD9unoLSpf+DmmFvvgTj+3EEP4bY2jA/t91XFeG3uaTQSy3ryDvhbX21U7G2HGOEl9rCkmz+hG0YRB/6KxZZ0eMIDr7OWfpPEuHV8oYwDNYbsT9zCGsR1hHxBJtdo60b36mjMemtf761DhJ/oQZ4eU738yzx1hvVS3aCJsfyp70H5u+pUjgrA565uG2lEMNLu4T4NFVw0UdrVudyrhmT8P7vF4v+mR4pp+OzRbLf8AtZrKmHlMqRst+/wOHUHug/Tpz6EwZPDWGiQyFyPUkjHWW7ACouegBFOWFabsk+zCDhyxoSNrSMCtdB1L+qK72jRPGOvXk8p/1kBOIJfAjaK1ZWz8hTc30hOSWYxkRP296zPHiQF0ibNYSPNZ9tNxgq9nV/cEQ68TsNr3SULfDr0TSjCPf4AfmJ0k1k5xphSYv/TtGIbjg/9yGVFqclg4Y/6rrfkApbx36PQEBNxLiRsZ4hGpCfVU6h0jOekk8TV6CAguXVX/G31UqsAEa4sOD2g10Ir+5JD7bdd3JE/999kHGdiCqc0DNcgSqWYbq2QYwrN/mb+mMUbiQSNMcc34kK1n+7dGxppnt7YN7UsJqBWJdH0Lw1Epxi11ViTeVma9bqioJYXi6N5exdpZTT7KmcGYFsoTqO958EX6AppgcML7N9oP3TO8qSgCpV3Bbbemq4bvjV43aM6Rdx17pC4GZo0jjU97p4K8jE4PvgoHlYkuPwSJDOSAdnYPh+Inq/vCk48UfIlup0ATJFVUXD7uf84v9roZSwZPXZ5j/88+MkHBIJwPv8cugmz5uN2EuBW5IScMuEqG7Cmk72SU3/QA39G79S0Gpw7iPhTos5LXxhfvohGcnSaNEvfNeecQf7fpVciTdHwuvcgqJizUKpSFg2P+LDBiO44mJD15RNAaT37Rrj5P06YITO4PDj+FMdc6gx+JQUFbcSRhScE/0gfsVm0P1BYIH5q0k/QDgEVoerf/n19lITTzPib1F2OHP4hyF3BEq1pd9NwuPhhsVVqTVTK5MzFwFIOH7cwJyY7aBykmsWBavdb2J7UA5wjKqMHl1auUGPlNL+lZjqG4tw05bchtFAF+PGWQXJhJCtRSkkzTOCrLRyYyyI9mWYEjoc23cGLanlIs7WA1Nd0Jz+5RSNlf9Gtnd65yQp/W1eqY6yzURPHUUa7FrynyORmjaR9adT9utSQkXy8++IeDNzhMtFr+SqQ/gKECLe0GeuyTs6E5bImUtqpN+xopBXnEeq8wp+bvLf76d98qPE5ibTRwlsSyCE4c1Y7vrJrlc15Yc2R9ciIuKUS8rUKLSdGBFe/TD4R3cPhCKAnnRLGWnJiPPgxoTVwHVZMISdsAjNaWblBmiAOzFcu7443d3PCLyXVcfR9xgvW51HTumo91t5Qyx4HIXGoZxayZYFm2hrhSlieUqLnDL2j2gYgGU5NGoQl4OnEY2QqobpRUF4xJ4HhLzYbLrBeXmTDPvj0MasC3kKsRlm/HrsRRWZ2iPSMw9601tLvDfyjG53ddPISiVNnkdXcaAN5np7dwipdBOC1s4a0sEmKakNbkkDb8LsGBNte/g6UYs5yYaKr0bnXlDjMCznHQa7pypBjE7S55T3UeRpwo3IvZ1tfIGdb+z9RIA/PDvUksxJ3Xq3lqtZzkZJF5aeedfIOekGS/G0LiCSYsELgRceH5veknHqoGoL6xi4Q6/VjmfpZVXT19bDcTNtaR9Dlaq4LDjpQl9rl5C3O/X1hgADvJUuINCiLrD114sLY1DG/TDXE0sp+TK7utnjLAoHuAuj+6anY5vN66CSbwyUNmvo+m8li/AMkRYdtSDoPWkV7Y1ixMBPcua0Llwn2HSKKwnCjvhDIDIIVwbWwb1s6b9cztH81WF5RWUgFujewPvTElM1Sy10y7BcZohKw28uLRFVsKunc9yX2PiQoTSB4PHBHRA4U5dEQV3GHQJ93nee7VT3oeQPMVebWhuhOhi34Z33LQajzpCF3OjIbJb0tOPP6L6N/ODqkNsYViI3kgCnkNhexadOuGFWIqen2Q8iv2uOZWbPirt0YEeKZIk2dpND07L8Q3OsoQCk2rjpnw9LuFrjgu7gN9gFyPq25HJRBn7PM/lS60DF+xVkJq94PwN+CiZWC43SVcBGx65DFZIs/N78MZCUzZbFlsS7FsIrDJt878cp9eZdq/Ai4LZhL8QYHpVUrQxRxZGSqooA755N6nOxw66JkA1VPnjECCMgoNNtWox0JzhMe8PBdh2ZliXf8yQ6/eTvsG6FD84F+49pc7m0L99pfWHb9ClyO3KRHscp/MOIC1MJmqoB4dNxV20U+z8/lSTIvcmM8DiaAZj/yxlst90drlGydlyPjQzYd/XtIYcO5gHoeD1KUCZRapE5dkyk5vh97WZJn/JkR8hsslU3D6x3rNGwJbQVRu0IiA3PpeAQNZBNAJHHfv8IzIYxPhMJdYq0YqLIGSUYu87D04cDOxJY7hgawYs+ExOWb7XkbpuRoITQd8zpwVDFlSCS+wFO+qah3Vn8RBTc6cXHO5xRWfUNj+NrEtPdVmax+9EXqXtHQyFpxaauvL96RH+mGwpKHOk3aisXbZ6gLE2mF4egGjjJOIJdHyb2ZR+kj+4GIvkoBwipDgUfr4UBXY8pvFxQOxRgtI4LgOY9Z1Aco7Mwp6qi1KoMFJW8d+gJwsgM3cMsyEeYH1n/mdpJW6VDbIWzOHkP5n+OKKNm2vJTkQFFwF9eOtGy9fNBtS4qo4jvOUJnnAPsrPbGMbBYd1dMC3daHLEwvIKCAVBn7q1Z2c4zAD5eEoY0EwZj/j8x8lGQ8TswFT81ZotW7ZBDai/YtV8mkGfuaWJRI5yHc/bV7GWLF+yrMji/jicBF5jy2UoqwxseqjgTut49FRgBH3h1qwnfYbXD3FvQljyAAgBCiZV726pFRG+sZv0FjDbq0iCKILVSEUDZgmQ",
"shared":true,
"uploaded_signed_key_count":50
},
"sessions":[
{
"pickle":"cryZlFaQv0hwWe6tTgv75RExFKGnC8tMHBXJYMHOw4s+SdrKUYAMUdGcYD7QukrPklEOy7fJho9YGK/jV04QdA8JABiOfD+ngJTR4V8eZdmDuG08+Q5EL79V81hQwU2fKndP0y/9nAXPUIADYq0Zrg4EsOnXz7aE+hAeBAm0IBog1s8RYUvynZ15uwjbd/OTLP+gpqpX33DwVg2leiBkQetiUSpOpZCuQ8CcZwIA0MoGCqvaT7h76VHX9JxJx+2fCMhsJMx1nhd99WJH1W9ge5CtdbC4KUP92OSxIrPOnMrNcOPJPp/paZP+HFNQ3PDL+z8pGKXmCnrXGSbd7iPHurPYESrVkBzr",
"sender_key":"WJ6Ce7U67a6jqkHYHd8o0+5H4bqdi9hInZdk0+swuXs",
"created_using_fallback_key":false,
"creation_time":"1649425011424",
"last_use_time":"1649425011424"
},
{
"pickle":"cryZlFaQv0hwWe6tTgv75RExFKGnC8tMHBXJYMHOw4t2W/lowyrV6SXVZp+uG59im0AAfNSKjhjZuiOpQlX7MS+AOJkCNvyujJ2g3KSjLZ94IkoHxkBDHLWSjwaLPu40rfOzJPDpm0XZsR6bQrsxKOmXLGEw2qw5jOTouzMVL2gvuuTix97nSYSU8j3XvTMRUoh0AF/tUpRLcvEFZeGrdUYmTMlyTv4na+FVUalUZ+jrk8t1/sM99JNq3SY1IBSjrBq/0rCOHieiippz0sw2fe2b87id4rqj1g3R9w2MWTWEdOz3ugjMGYF1YDBQZA1tJZ/hmgppk2AU2xKQXE2X3DgSC6fC66D4",
"sender_key":"RzRROfmHNlBfzxnNCUYBfn/5oZNQ11XYjDg59hS+mV0",
"created_using_fallback_key":false,
"creation_time":"1649425011503",
"last_use_time":"1649425011503"
},
{
"pickle":"cryZlFaQv0hwWe6tTgv75RExFKGnC8tMHBXJYMHOw4titbL3SS12PYHpcBPJc6hXnOnZXqrjtjYOD545fck+3utEo8cqqwWubc9tsvxGW3tOWPttLBdAW30Vn8V1M8ebqVCNVWEAb1GKjV4ni8xG7G9SlEcCjLjnF4lJpddSZkqVMFoN0ITr9aSz/eJwXpc3HLreUFXwc8LuQp7krQ4Vt1e5EE/klduqsdurZf5V14RHsmWz2lKjt7nVgtIz/dhtF5F/sGJdg8kCGaHIMSbGAPuPPpa4/Laicb/5otrYt4pg4W4KdFpSGJIcvUQNjXaOZMx3cu/RPJIOyNhx7whG1QiYAUBqAJvr",
"sender_key":"IXSZugAHig1v8MowE1jxi2wDDDfuZBeJynHlegJVwUc",
"created_using_fallback_key":false,
"creation_time":"1649425011566",
"last_use_time":"1649425011566"
},
{
"pickle":"SmkDiFZjNukiarQ7XHQo25FILHsuhNOnxy56cMSQU/Y71jaGbJes4YrvN4Dfy4RSONfejEDXDkbW2JudlHHRP/rWEmnfJiGbK6ArbrG2puqIZgOecPnOUgPfCisr49p1Gmf36dPaO5lm/ZSrngfSoxahoeJJE/CcJN98sYM15XytRk2LBwc+CyYDqr4V1qxfsBt6tzJ4+tsAZeRdD0UtipQgysgH56o8N7nKTCkaZz5lfpYCl3FEgwXpLJ0MGQvtQmbORFvOLqR1jZ/EbmNGKiqDDIYsqG0sf78ii1jqfpLDBXLuYDccsg",
"sender_key":"EB9SC4jVAydKhM6/GcwMc9biKwVNywqW3TerNTrtb1M",
"created_using_fallback_key":false,
"creation_time":"1649542063182",
"last_use_time":"1649542063182"
}
],
"inbound_group_sessions":[
{
"pickle":"KoA0sxDNQ7lz0vylU9zlmar0VCVQRMCfRrIfTh1bdMhlAgy8/D2ToT+oKRaKy1HiW6H862bzdpgxprlseSjmip9OfLbIuyd2YZcEinwc2666oEI/hpk4oTlE61uE1M+ThfdFf41yGCmaAP7mhjwF234ZrZ6i/F/qx42TLQ8Unc30wDJaJgyheO5eW85SD/0g0cdg2WnEKrx2/wl7Vg/YijT3JMDZ+OsdfJfSZtxBNjlG+PQ/9D31qb1eHfaovc8vFZh5QLfAFg/5rBrF1PhRsC7xOAZbUNdrTbvypNfMM4mznf84C2SzZRSMeAfg5v/YticM3Keg4eHuEj1WO9DrmRXYl6b/pITdf1xuk5euVT0pyxJpXmq41AoAZKAo1l94HGy1LG1RpruD1uQPhiponh5PGHSOf43Q",
"sender_key":"vJfH7wiYmGos3C8U1XcJ//YWSmkueAYqrmUA6/ukfAM",
"signing_key":{
"ed25519":"JGgPQRuYj3ScMdPS+A0P+k/1qS9Hr3qeKXLscI+hS78"
},
"room_id":"!AZkqtjvtwPAuyNOXEt:matrix.org",
"forwarding_chains":[
],
"imported":true,
"backed_up":true
},
{
"pickle":"9RF6GBu9CvjZZx2hxIlw2gMdKs36LFhXhLTHAPrLSjT2OTbeE/jK263+iiFdSpF7Cblp/lXzljPKJN6sL8JGzoT7ssYh56nI0kKsp7/y88z+tTOH/5NYYTmZzHYw6yy4Cmaxh0pdHDs+RQpSSIe9jhF/EJJna5jcKYXxDY52m8H4LECQzVuDlYfblCr9zoYWhQrVhiRDGy7eLhk4X6Rp0Yoek4YUKcCQArDfZ/Vf43qfHUpOJgRpm5Oyj42HA/j4xZBb5U0Fmo6YHRPt0/KuWrDfpgJSGiN0zza7641IfADg8f3WdhlPAWMyri7k4vOZMBjlwFNcMpc0wM2TaTmbi2zqXEKZy9Oh/eJqBapFx0oNWaQ1VQ++iXxGUbZhwy7x2vd6UkqUTwYeym+aP23ee3TCtnNWN0aC",
"sender_key":"EB9SC4jVAydKhM6/GcwMc9biKwVNywqW3TerNTrtb1M",
"signing_key":{
"ed25519":"1NXa5GyJ+p2ruAClEque+TL1VktrBzMW4dZFNfNGrvc"
},
"room_id":"!CWLUCoEWXSFyTCOtfL:matrix.org",
"forwarding_chains":[],
"imported":true,
"backed_up":true
}
],
"pickle_key": [17, 36, 120, 74, 95, 78, 56, 36, 62, 123, 5, 105, 74,
111, 70, 48, 51, 101, 66, 86, 116, 14, 114, 85, 85,
92, 44, 71, 89, 99, 55, 74],
"backup_version":"3",
"backup_recovery_key":"EsTHScmRV5oT1WBhe2mj2Gn3odeYantZ4NEk7L51p6L8hrmB",
"cross_signing":{
"master_key":"trnK/dBv/M2x2zZt8lnORHQqmFHWvjYE6rdlAONRUPY",
"self_signing_key":"SJhsj9jXC4hxhqS/1B3RZ65zWMHuF+1fUjWHrzVRh6w",
"user_signing_key":"LPYrV11T9Prm4ZIUxrq2a8Y/F64R1+NaGNyo6GlXjGg"
},
"tracked_users":[
"@ganfra146:matrix.org",
"@this-is-me:matrix.org",
"@Amandine:matrix.org",
"@ganfra:matrix.org"
]
});
let migration_data: MigrationData = serde_json::from_value(data)?;
let dir = tempdir()?;
let path =
dir.path().to_str().expect("Creating a string from the tempdir path should not fail");
migrate(migration_data, path, None, Box::new(|_, _| {}))?;
let machine = OlmMachine::new("@ganfra146:matrix.org", "DEWRCMENGS", path, None)?;
assert_eq!(
machine.identity_keys()["ed25519"],
"JGgPQRuYj3ScMdPS+A0P+k/1qS9Hr3qeKXLscI+hS78"
);
let room_keys = machine.runtime.block_on(machine.inner.export_keys(|_| true))?;
assert_eq!(room_keys.len(), 2);
let cross_signing_status = machine.cross_signing_status();
assert!(cross_signing_status.has_master);
assert!(cross_signing_status.has_user_signing);
assert!(cross_signing_status.has_self_signing);
let backup_keys = machine.get_backup_keys()?;
assert!(backup_keys.is_some());
Ok(())
}
}
@@ -0,0 +1,56 @@
use std::{
io::{Result, Write},
sync::{Arc, Mutex},
};
use tracing_subscriber::{fmt::MakeWriter, EnvFilter};
/// Trait that can be used to forward Rust logs over FFI to a language specific
/// logger.
pub trait Logger: Send {
/// Called every time the Rust side wants to post a log line.
fn log(&self, log_line: String);
// TODO add support for different log levels, do this by adding more methods
// to the trait.
}
impl Write for LoggerWrapper {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
let data = String::from_utf8_lossy(buf).to_string();
self.inner.lock().unwrap().log(data);
Ok(buf.len())
}
fn flush(&mut self) -> Result<()> {
Ok(())
}
}
impl MakeWriter<'_> for LoggerWrapper {
type Writer = LoggerWrapper;
fn make_writer(&self) -> Self::Writer {
self.clone()
}
}
#[derive(Clone)]
pub struct LoggerWrapper {
inner: Arc<Mutex<Box<dyn Logger>>>,
}
/// Set the logger that should be used to forward Rust logs over FFI.
pub fn set_logger(logger: Box<dyn Logger>) {
let logger = LoggerWrapper { inner: Arc::new(Mutex::new(logger)) };
let filter = EnvFilter::from_default_env().add_directive(
"matrix_sdk_crypto=trace".parse().expect("Can't parse logging filter directive"),
);
let _ = tracing_subscriber::fmt()
.with_writer(logger)
.with_env_filter(filter)
.without_time()
.try_init();
}
File diff suppressed because it is too large Load Diff
+483
View File
@@ -0,0 +1,483 @@
namespace olm {
void set_logger(Logger logger);
[Throws=MigrationError]
void migrate(
MigrationData data,
[ByRef] string path,
string? passphrase,
ProgressListener progress_listener
);
};
[Error]
interface MigrationError {
Generic(string error_message);
};
callback interface Logger {
void log(string logLine);
};
callback interface ProgressListener {
void on_progress(i32 progress, i32 total);
};
[Error]
enum PkDecryptionError {
"Olm",
};
[Error]
enum KeyImportError {
"Export",
"CryptoStore",
"Json",
};
[Error]
enum SignatureError {
"Signature",
"Identifier",
"CryptoStore",
"UnknownDevice",
"UnknownUserIdentity",
};
[Error]
enum SecretImportError {
"Import",
"CryptoStore",
};
[Error]
enum CryptoStoreError {
"CryptoStore",
"OlmError",
"Serialization",
"Identifier",
"InvalidUserId",
};
[Error]
enum DecryptionError {
"Identifier",
"Serialization",
"Megolm",
};
dictionary DeviceLists {
sequence<string> changed;
sequence<string> left;
};
dictionary KeysImportResult {
i64 imported;
i64 total;
record<DOMString, record<DOMString, sequence<string>>> keys;
};
dictionary DecryptedEvent {
string clear_event;
string sender_curve25519_key;
string? claimed_ed25519_key;
sequence<string> forwarding_curve25519_chain;
};
dictionary Device {
string user_id;
string device_id;
record<DOMString, string> keys;
sequence<string> algorithms;
string? display_name;
boolean is_blocked;
boolean locally_trusted;
boolean cross_signing_trusted;
};
[Enum]
interface UserIdentity {
Own(
string user_id,
boolean trusts_our_own_device,
string master_key,
string self_signing_key,
string user_signing_key
);
Other(
string user_id,
string master_key,
string self_signing_key
);
};
dictionary CrossSigningStatus {
boolean has_master;
boolean has_self_signing;
boolean has_user_signing;
};
dictionary CrossSigningKeyExport {
string? master_key;
string? self_signing_key;
string? user_signing_key;
};
dictionary UploadSigningKeysRequest {
string master_key;
string self_signing_key;
string user_signing_key;
};
dictionary BootstrapCrossSigningResult {
UploadSigningKeysRequest upload_signing_keys_request;
SignatureUploadRequest signature_request;
};
dictionary CancelInfo {
string cancel_code;
string reason;
boolean cancelled_by_us;
};
dictionary StartSasResult {
Sas sas;
OutgoingVerificationRequest request;
};
dictionary Sas {
string other_user_id;
string other_device_id;
string flow_id;
string? room_id;
boolean we_started;
boolean has_been_accepted;
boolean can_be_presented;
boolean supports_emoji;
boolean have_we_confirmed;
boolean is_done;
boolean is_cancelled;
CancelInfo? cancel_info;
};
dictionary ScanResult {
QrCode qr;
OutgoingVerificationRequest request;
};
dictionary QrCode {
string other_user_id;
string other_device_id;
string flow_id;
string? room_id;
boolean we_started;
boolean other_side_scanned;
boolean has_been_confirmed;
boolean reciprocated;
boolean is_done;
boolean is_cancelled;
CancelInfo? cancel_info;
};
dictionary VerificationRequest {
string other_user_id;
string? other_device_id;
string flow_id;
string? room_id;
boolean we_started;
boolean is_ready;
boolean is_passive;
boolean is_done;
boolean is_cancelled;
CancelInfo? cancel_info;
sequence<string>? their_methods;
sequence<string>? our_methods;
};
dictionary RequestVerificationResult {
VerificationRequest verification;
OutgoingVerificationRequest request;
};
dictionary ConfirmVerificationResult {
sequence<OutgoingVerificationRequest> requests;
SignatureUploadRequest? signature_request;
};
[Enum]
interface Verification {
SasV1(Sas sas);
QrCodeV1(QrCode qrcode);
};
dictionary KeyRequestPair {
Request? cancellation;
Request key_request;
};
[Enum]
interface OutgoingVerificationRequest {
ToDevice(string request_id, string event_type, string body);
InRoom(string request_id, string room_id, string event_type, string content);
};
[Enum]
interface Request {
ToDevice(string request_id, string event_type, string body);
KeysUpload(string request_id, string body);
KeysQuery(string request_id, sequence<string> users);
KeysClaim(string request_id, record<DOMString, record<DOMString, string>> one_time_keys);
KeysBackup(string request_id, string version, string rooms);
RoomMessage(string request_id, string room_id, string event_type, string content);
SignatureUpload(string request_id, string body);
};
dictionary SignatureUploadRequest {
string body;
};
enum RequestType {
"KeysQuery",
"KeysClaim",
"KeysUpload",
"ToDevice",
"SignatureUpload",
"KeysBackup",
"RoomMessage",
};
interface OlmMachine {
[Throws=CryptoStoreError]
constructor(
[ByRef] string user_id,
[ByRef] string device_id,
[ByRef] string path,
string? passphrase
);
record<DOMString, string> identity_keys();
string user_id();
string device_id();
[Throws=CryptoStoreError]
string receive_sync_changes([ByRef] string events,
DeviceLists device_changes,
record<DOMString, i32> key_counts,
sequence<string>? unused_fallback_keys);
[Throws=CryptoStoreError]
sequence<Request> outgoing_requests();
[Throws=CryptoStoreError]
void mark_request_as_sent(
[ByRef] string request_id,
RequestType request_type,
[ByRef] string response
);
[Throws=DecryptionError]
DecryptedEvent decrypt_room_event([ByRef] string event, [ByRef] string room_id);
[Throws=CryptoStoreError]
string encrypt([ByRef] string room_id, [ByRef] string event_type, [ByRef] string content);
[Throws=CryptoStoreError]
UserIdentity? get_identity([ByRef] string user_id, u32 timeout);
[Throws=SignatureError]
SignatureUploadRequest verify_identity([ByRef] string user_id);
[Throws=CryptoStoreError]
Device? get_device([ByRef] string user_id, [ByRef] string device_id, u32 timeout);
[Throws=CryptoStoreError]
void mark_device_as_trusted([ByRef] string user_id, [ByRef] string device_id);
[Throws=SignatureError]
SignatureUploadRequest verify_device([ByRef] string user_id, [ByRef] string device_id);
[Throws=CryptoStoreError]
sequence<Device> get_user_devices([ByRef] string user_id, u32 timeout);
[Throws=CryptoStoreError]
boolean is_user_tracked([ByRef] string user_id);
void update_tracked_users(sequence<string> users);
[Throws=CryptoStoreError]
Request? get_missing_sessions(sequence<string> users);
[Throws=CryptoStoreError]
sequence<Request> share_room_key([ByRef] string room_id, sequence<string> users);
[Throws=CryptoStoreError]
void receive_unencrypted_verification_event([ByRef] string event, [ByRef] string room_id);
sequence<VerificationRequest> get_verification_requests([ByRef] string user_id);
VerificationRequest? get_verification_request([ByRef] string user_id, [ByRef] string flow_id);
Verification? get_verification([ByRef] string user_id, [ByRef] string flow_id);
[Throws=CryptoStoreError]
VerificationRequest? request_verification(
[ByRef] string user_id,
[ByRef] string room_id,
[ByRef] string event_id,
sequence<string> methods
);
[Throws=CryptoStoreError]
string? verification_request_content(
[ByRef] string user_id,
sequence<string> methods
);
[Throws=CryptoStoreError]
RequestVerificationResult? request_self_verification(sequence<string> methods);
[Throws=CryptoStoreError]
RequestVerificationResult? request_verification_with_device(
[ByRef] string user_id,
[ByRef] string device_id,
sequence<string> methods
);
OutgoingVerificationRequest? accept_verification_request(
[ByRef] string user_id,
[ByRef] string flow_id,
sequence<string> methods
);
[Throws=CryptoStoreError]
ConfirmVerificationResult? confirm_verification([ByRef] string user_id, [ByRef] string flow_id);
OutgoingVerificationRequest? cancel_verification(
[ByRef] string user_id,
[ByRef] string flow_id,
[ByRef] string cancel_code
);
[Throws=CryptoStoreError]
StartSasResult? start_sas_with_device([ByRef] string user_id, [ByRef] string device_id);
[Throws=CryptoStoreError]
StartSasResult? start_sas_verification([ByRef] string user_id, [ByRef] string flow_id);
OutgoingVerificationRequest? accept_sas_verification([ByRef] string user_id, [ByRef] string flow_id);
sequence<i32>? get_emoji_index([ByRef] string user_id, [ByRef] string flow_id);
sequence<i32>? get_decimals([ByRef] string user_id, [ByRef] string flow_id);
[Throws=CryptoStoreError]
QrCode? start_qr_verification([ByRef] string user_id, [ByRef] string flow_id);
ScanResult? scan_qr_code([ByRef] string user_id, [ByRef] string flow_id, [ByRef] string data);
string? generate_qr_code([ByRef] string user_id, [ByRef] string flow_id);
[Throws=DecryptionError]
KeyRequestPair request_room_key([ByRef] string event, [ByRef] string room_id);
[Throws=CryptoStoreError]
string export_keys([ByRef] string passphrase, i32 rounds);
[Throws=KeyImportError]
KeysImportResult import_keys(
[ByRef] string keys,
[ByRef] string passphrase,
ProgressListener progress_listener
);
[Throws=KeyImportError]
KeysImportResult import_decrypted_keys(
[ByRef] string keys,
ProgressListener progress_listener
);
[Throws=CryptoStoreError]
void discard_room_key([ByRef] string room_id);
CrossSigningStatus cross_signing_status();
[Throws=CryptoStoreError]
BootstrapCrossSigningResult bootstrap_cross_signing();
CrossSigningKeyExport? export_cross_signing_keys();
[Throws=SecretImportError]
void import_cross_signing_keys(CrossSigningKeyExport export);
[Throws=CryptoStoreError]
boolean is_identity_verified([ByRef] string user_id);
record<DOMString, record<DOMString, string>> sign([ByRef] string message);
[Throws=DecodeError]
void enable_backup_v1(MegolmV1BackupKey key, string version);
[Throws=CryptoStoreError]
void disable_backup();
[Throws=CryptoStoreError]
Request? backup_room_keys();
[Throws=CryptoStoreError]
void save_recovery_key(BackupRecoveryKey? key, string? version);
[Throws=CryptoStoreError]
RoomKeyCounts room_key_counts();
[Throws=CryptoStoreError]
BackupKeys? get_backup_keys();
boolean backup_enabled();
[Throws=CryptoStoreError]
boolean verify_backup([ByRef] string auth_data);
};
dictionary PassphraseInfo {
string private_key_salt;
i32 private_key_iterations;
};
dictionary MegolmV1BackupKey {
string public_key;
record<DOMString, record<DOMString, string>> signatures;
PassphraseInfo? passphrase_info;
string backup_algorithm;
};
interface BackupKeys {
BackupRecoveryKey recovery_key();
string backup_version();
};
dictionary RoomKeyCounts {
i64 total;
i64 backed_up;
};
[Error]
enum DecodeError {
"Decode",
"CryptoStore",
};
interface BackupRecoveryKey {
constructor();
[Name=from_passphrase]
constructor(string passphrase, string salt, i32 rounds);
[Name=new_from_passphrase]
constructor(string passphrase);
[Name=from_base64, Throws=DecodeError]
constructor(string key);
[Name=from_base58, Throws=DecodeError]
constructor(string key);
string to_base58();
string to_base64();
MegolmV1BackupKey megolm_v1_public_key();
[Throws=PkDecryptionError]
string decrypt_v1(string ephemeral_key, string mac, string ciphertext);
};
dictionary MigrationData {
PickledAccount account;
sequence<PickledSession> sessions;
sequence<PickledInboundGroupSession> inbound_group_sessions;
string? backup_version;
string? backup_recovery_key;
sequence<u8> pickle_key;
CrossSigningKeyExport cross_signing;
sequence<string> tracked_users;
};
dictionary PickledAccount {
string user_id;
string device_id;
string pickle;
boolean shared;
i64 uploaded_signed_key_count;
};
dictionary PickledSession {
string pickle;
string sender_key;
boolean created_using_fallback_key;
string creation_time;
string last_use_time;
};
dictionary PickledInboundGroupSession {
string pickle;
string sender_key;
record<DOMString, string> signing_key;
string room_id;
sequence<string> forwarding_chains;
boolean imported;
boolean backed_up;
};
@@ -0,0 +1,332 @@
#![allow(missing_docs)]
use std::collections::HashMap;
use http::Response;
use matrix_sdk_crypto::{
IncomingResponse, OutgoingRequest, OutgoingVerificationRequest as SdkVerificationRequest,
RoomMessageRequest, ToDeviceRequest, UploadSigningKeysRequest as RustUploadSigningKeysRequest,
};
use ruma::{
api::client::{
backup::add_backup_keys::v3::Response as KeysBackupResponse,
keys::{
claim_keys::v3::{Request as KeysClaimRequest, Response as KeysClaimResponse},
get_keys::v3::Response as KeysQueryResponse,
upload_keys::v3::Response as KeysUploadResponse,
upload_signatures::v3::{
Request as RustSignatureUploadRequest, Response as SignatureUploadResponse,
},
},
message::send_message_event::v3::Response as RoomMessageResponse,
sync::sync_events::v3::DeviceLists as RumaDeviceLists,
to_device::send_event_to_device::v3::Response as ToDeviceResponse,
},
assign,
events::EventContent,
OwnedTransactionId, UserId,
};
use serde_json::json;
pub struct SignatureUploadRequest {
pub body: String,
}
impl From<RustSignatureUploadRequest> for SignatureUploadRequest {
fn from(r: RustSignatureUploadRequest) -> Self {
Self {
body: serde_json::to_string(&r.signed_keys)
.expect("Can't serialize signature upload request"),
}
}
}
pub struct UploadSigningKeysRequest {
pub master_key: String,
pub self_signing_key: String,
pub user_signing_key: String,
}
impl From<RustUploadSigningKeysRequest> for UploadSigningKeysRequest {
fn from(r: RustUploadSigningKeysRequest) -> Self {
Self {
master_key: serde_json::to_string(
&r.master_key.expect("Request didn't contain a master key"),
)
.expect("Can't serialize cross signing master key"),
self_signing_key: serde_json::to_string(
&r.self_signing_key.expect("Request didn't contain a self-signing key"),
)
.expect("Can't serialize cross signing self-signing key"),
user_signing_key: serde_json::to_string(
&r.user_signing_key.expect("Request didn't contain a user-signing key"),
)
.expect("Can't serialize cross signing user-signing key"),
}
}
}
pub struct BootstrapCrossSigningResult {
pub upload_signing_keys_request: UploadSigningKeysRequest,
pub signature_request: SignatureUploadRequest,
}
impl From<(RustUploadSigningKeysRequest, RustSignatureUploadRequest)>
for BootstrapCrossSigningResult
{
fn from(requests: (RustUploadSigningKeysRequest, RustSignatureUploadRequest)) -> Self {
Self {
upload_signing_keys_request: requests.0.into(),
signature_request: requests.1.into(),
}
}
}
pub enum OutgoingVerificationRequest {
ToDevice { request_id: String, event_type: String, body: String },
InRoom { request_id: String, room_id: String, event_type: String, content: String },
}
impl From<SdkVerificationRequest> for OutgoingVerificationRequest {
fn from(r: SdkVerificationRequest) -> Self {
match r {
SdkVerificationRequest::ToDevice(r) => r.into(),
SdkVerificationRequest::InRoom(r) => Self::InRoom {
request_id: r.txn_id.to_string(),
room_id: r.room_id.to_string(),
content: serde_json::to_string(&r.content)
.expect("Can't serialize message content"),
event_type: r.content.event_type().to_string(),
},
}
}
}
impl From<ToDeviceRequest> for OutgoingVerificationRequest {
fn from(r: ToDeviceRequest) -> Self {
Self::ToDevice {
request_id: r.txn_id.to_string(),
event_type: r.event_type.to_string(),
body: serde_json::to_string(&r.messages).expect("Can't serialize to-device body"),
}
}
}
#[derive(Debug)]
pub enum Request {
ToDevice { request_id: String, event_type: String, body: String },
KeysUpload { request_id: String, body: String },
KeysQuery { request_id: String, users: Vec<String> },
KeysClaim { request_id: String, one_time_keys: HashMap<String, HashMap<String, String>> },
RoomMessage { request_id: String, room_id: String, event_type: String, content: String },
SignatureUpload { request_id: String, body: String },
KeysBackup { request_id: String, version: String, rooms: String },
}
impl From<OutgoingRequest> for Request {
fn from(r: OutgoingRequest) -> Self {
use matrix_sdk_crypto::OutgoingRequests::*;
match r.request() {
KeysUpload(u) => {
let body = json!({
"device_keys": u.device_keys,
"one_time_keys": u.one_time_keys,
"fallback_keys": u.fallback_keys,
});
Request::KeysUpload {
request_id: r.request_id().to_string(),
body: serde_json::to_string(&body)
.expect("Can't serialize keys upload request"),
}
}
KeysQuery(k) => {
let users: Vec<String> = k.device_keys.keys().map(|u| u.to_string()).collect();
Request::KeysQuery { request_id: r.request_id().to_string(), users }
}
ToDeviceRequest(t) => Request::from(t),
SignatureUpload(t) => Request::SignatureUpload {
request_id: r.request_id().to_string(),
body: serde_json::to_string(&t.signed_keys)
.expect("Can't serialize signature upload request"),
},
RoomMessage(r) => Request::from(r),
KeysClaim(c) => (r.request_id().to_owned(), c.clone()).into(),
KeysBackup(b) => Request::KeysBackup {
request_id: r.request_id().to_string(),
version: b.version.to_owned(),
rooms: serde_json::to_string(&b.rooms)
.expect("Can't serialize keys backup request"),
},
}
}
}
impl From<ToDeviceRequest> for Request {
fn from(r: ToDeviceRequest) -> Self {
Request::ToDevice {
request_id: r.txn_id.to_string(),
event_type: r.event_type.to_string(),
body: serde_json::to_string(&r.messages).expect("Can't serialize to-device body"),
}
}
}
impl From<(OwnedTransactionId, KeysClaimRequest)> for Request {
fn from(request_tuple: (OwnedTransactionId, KeysClaimRequest)) -> Self {
let (request_id, request) = request_tuple;
Request::KeysClaim {
request_id: request_id.to_string(),
one_time_keys: request
.one_time_keys
.into_iter()
.map(|(u, d)| {
(
u.to_string(),
d.into_iter().map(|(k, v)| (k.to_string(), v.to_string())).collect(),
)
})
.collect(),
}
}
}
impl From<&ToDeviceRequest> for Request {
fn from(r: &ToDeviceRequest) -> Self {
Request::ToDevice {
request_id: r.txn_id.to_string(),
event_type: r.event_type.to_string(),
body: serde_json::to_string(&r.messages).expect("Can't serialize to-device body"),
}
}
}
impl From<&RoomMessageRequest> for Request {
fn from(r: &RoomMessageRequest) -> Self {
Self::RoomMessage {
request_id: r.txn_id.to_string(),
room_id: r.room_id.to_string(),
event_type: r.content.event_type().to_string(),
content: serde_json::to_string(&r.content).expect("Can't serialize message content"),
}
}
}
pub(crate) fn response_from_string(body: &str) -> Response<Vec<u8>> {
Response::builder()
.status(200)
.body(body.as_bytes().to_vec())
.expect("Can't create HTTP response")
}
pub enum RequestType {
KeysQuery,
KeysClaim,
KeysUpload,
ToDevice,
SignatureUpload,
KeysBackup,
RoomMessage,
}
pub struct DeviceLists {
pub changed: Vec<String>,
pub left: Vec<String>,
}
impl From<DeviceLists> for RumaDeviceLists {
fn from(d: DeviceLists) -> Self {
assign!(RumaDeviceLists::new(), {
changed: d
.changed
.into_iter()
.filter_map(|u| UserId::parse(u).ok())
.collect(),
left: d
.left
.into_iter()
.filter_map(|u| UserId::parse(u).ok())
.collect(),
})
}
}
pub struct KeysImportResult {
/// The number of room keys that were imported.
pub imported: i64,
/// The total number of room keys that were found in the export.
pub total: i64,
/// The map of keys that were imported.
///
/// It's a map from room id to a map of the sender key to a list of session
/// ids.
pub keys: HashMap<String, HashMap<String, Vec<String>>>,
}
pub(crate) enum OwnedResponse {
KeysClaim(KeysClaimResponse),
KeysUpload(KeysUploadResponse),
KeysQuery(KeysQueryResponse),
ToDevice(ToDeviceResponse),
SignatureUpload(SignatureUploadResponse),
KeysBackup(KeysBackupResponse),
RoomMessage(RoomMessageResponse),
}
impl From<KeysClaimResponse> for OwnedResponse {
fn from(response: KeysClaimResponse) -> Self {
OwnedResponse::KeysClaim(response)
}
}
impl From<KeysQueryResponse> for OwnedResponse {
fn from(response: KeysQueryResponse) -> Self {
OwnedResponse::KeysQuery(response)
}
}
impl From<KeysUploadResponse> for OwnedResponse {
fn from(response: KeysUploadResponse) -> Self {
OwnedResponse::KeysUpload(response)
}
}
impl From<ToDeviceResponse> for OwnedResponse {
fn from(response: ToDeviceResponse) -> Self {
OwnedResponse::ToDevice(response)
}
}
impl From<SignatureUploadResponse> for OwnedResponse {
fn from(response: SignatureUploadResponse) -> Self {
Self::SignatureUpload(response)
}
}
impl From<KeysBackupResponse> for OwnedResponse {
fn from(r: KeysBackupResponse) -> Self {
Self::KeysBackup(r)
}
}
impl From<RoomMessageResponse> for OwnedResponse {
fn from(response: RoomMessageResponse) -> Self {
OwnedResponse::RoomMessage(response)
}
}
impl<'a> From<&'a OwnedResponse> for IncomingResponse<'a> {
fn from(r: &'a OwnedResponse) -> Self {
match r {
OwnedResponse::KeysClaim(r) => IncomingResponse::KeysClaim(r),
OwnedResponse::KeysQuery(r) => IncomingResponse::KeysQuery(r),
OwnedResponse::KeysUpload(r) => IncomingResponse::KeysUpload(r),
OwnedResponse::ToDevice(r) => IncomingResponse::ToDevice(r),
OwnedResponse::SignatureUpload(r) => IncomingResponse::SignatureUpload(r),
OwnedResponse::KeysBackup(r) => IncomingResponse::KeysBackup(r),
OwnedResponse::RoomMessage(r) => IncomingResponse::RoomMessage(r),
}
}
}
@@ -0,0 +1,60 @@
use matrix_sdk_crypto::{types::CrossSigningKey, UserIdentities};
use crate::CryptoStoreError;
/// Enum representing cross signing identities of our own user or some other
/// user.
pub enum UserIdentity {
/// Our own user identity.
Own {
/// The unique id of our own user.
user_id: String,
/// Does our own user identity trust our own device.
trusts_our_own_device: bool,
/// The public master key of our identity.
master_key: String,
/// The public user-signing key of our identity.
user_signing_key: String,
/// The public self-signing key of our identity.
self_signing_key: String,
},
/// The user identity of other users.
Other {
/// The unique id of the user.
user_id: String,
/// The public master key of the identity.
master_key: String,
/// The public self-signing key of our identity.
self_signing_key: String,
},
}
impl UserIdentity {
pub(crate) async fn from_rust(i: UserIdentities) -> Result<Self, CryptoStoreError> {
Ok(match i {
UserIdentities::Own(i) => {
let master: CrossSigningKey = i.master_key().as_ref().to_owned();
let user_signing: CrossSigningKey = i.user_signing_key().as_ref().to_owned();
let self_signing: CrossSigningKey = i.self_signing_key().as_ref().to_owned();
UserIdentity::Own {
user_id: i.user_id().to_string(),
trusts_our_own_device: i.trusts_our_own_device().await?,
master_key: serde_json::to_string(&master)?,
user_signing_key: serde_json::to_string(&user_signing)?,
self_signing_key: serde_json::to_string(&self_signing)?,
}
}
UserIdentities::Other(i) => {
let master: CrossSigningKey = i.master_key().as_ref().to_owned();
let self_signing: CrossSigningKey = i.self_signing_key().as_ref().to_owned();
UserIdentity::Other {
user_id: i.user_id().to_string(),
master_key: serde_json::to_string(&master)?,
self_signing_key: serde_json::to_string(&self_signing)?,
}
}
})
}
}
@@ -0,0 +1,232 @@
use matrix_sdk_crypto::{
CancelInfo as RustCancelInfo, QrVerification as InnerQr, Sas as InnerSas,
VerificationRequest as InnerVerificationRequest,
};
use crate::{OutgoingVerificationRequest, SignatureUploadRequest};
/// Enum representing the different verification flows we support.
pub enum Verification {
/// The `m.sas.v1` verification flow.
SasV1 {
#[allow(missing_docs)]
sas: Sas,
},
/// The `m.qr_code.scan.v1`, `m.qr_code.show.v1`, and `m.reciprocate.v1`
/// verification flow.
QrCodeV1 {
#[allow(missing_docs)]
qrcode: QrCode,
},
}
/// The `m.sas.v1` verification flow.
pub struct Sas {
/// The other user that is participating in the verification flow
pub other_user_id: String,
/// The other user's device that is participating in the verification flow
pub other_device_id: String,
/// The unique ID of this verification flow, will be a random string for
/// to-device events or a event ID for in-room events.
pub flow_id: String,
/// The room ID where this verification is happening, will be `None` if the
/// verification is going through to-device messages
pub room_id: Option<String>,
/// Did we initiate the verification flow
pub we_started: bool,
/// Has the non-initiating side accepted the verification flow
pub has_been_accepted: bool,
/// Can the short auth string be presented
pub can_be_presented: bool,
/// Does the flow support the emoji representation of the short auth string
pub supports_emoji: bool,
/// Have we confirmed that the short auth strings match
pub have_we_confirmed: bool,
/// Has the verification completed successfully
pub is_done: bool,
/// Has the flow been cancelled
pub is_cancelled: bool,
/// Information about the cancellation of the flow, will be `None` if the
/// flow hasn't been cancelled
pub cancel_info: Option<CancelInfo>,
}
/// The `m.qr_code.scan.v1`, `m.qr_code.show.v1`, and `m.reciprocate.v1`
/// verification flow.
pub struct QrCode {
/// The other user that is participating in the verification flow
pub other_user_id: String,
/// The other user's device that is participating in the verification flow
pub other_device_id: String,
/// The unique ID of this verification flow, will be a random string for
/// to-device events or a event ID for in-room events.
pub flow_id: String,
/// The room ID where this verification is happening, will be `None` if the
/// verification is going through to-device messages
pub room_id: Option<String>,
/// Did we initiate the verification flow
pub we_started: bool,
/// Has the QR code been scanned by the other side
pub other_side_scanned: bool,
/// Has the scanning of the QR code been confirmed by us
pub has_been_confirmed: bool,
/// Did we scan the QR code and sent out a reciprocation
pub reciprocated: bool,
/// Has the verification completed successfully
pub is_done: bool,
/// Has the flow been cancelled
pub is_cancelled: bool,
/// Information about the cancellation of the flow, will be `None` if the
/// flow hasn't been cancelled
pub cancel_info: Option<CancelInfo>,
}
impl From<InnerQr> for QrCode {
fn from(qr: InnerQr) -> Self {
Self {
other_user_id: qr.other_user_id().to_string(),
flow_id: qr.flow_id().as_str().to_owned(),
is_cancelled: qr.is_cancelled(),
is_done: qr.is_done(),
cancel_info: qr.cancel_info().map(|c| c.into()),
reciprocated: qr.reciprocated(),
we_started: qr.we_started(),
other_side_scanned: qr.has_been_scanned(),
has_been_confirmed: qr.has_been_confirmed(),
other_device_id: qr.other_device_id().to_string(),
room_id: qr.room_id().map(|r| r.to_string()),
}
}
}
/// Information on why a verification flow has been cancelled and by whom.
pub struct CancelInfo {
/// The textual representation of the cancel reason
pub reason: String,
/// The code describing the cancel reason
pub cancel_code: String,
/// Was the verification flow cancelled by us
pub cancelled_by_us: bool,
}
impl From<RustCancelInfo> for CancelInfo {
fn from(c: RustCancelInfo) -> Self {
Self {
reason: c.reason().to_owned(),
cancel_code: c.cancel_code().to_string(),
cancelled_by_us: c.cancelled_by_us(),
}
}
}
/// A result type for starting SAS verifications.
pub struct StartSasResult {
/// The SAS verification object that got created.
pub sas: Sas,
/// The request that needs to be sent out to notify the other side that a
/// SAS verification should start.
pub request: OutgoingVerificationRequest,
}
/// A result type for scanning QR codes.
pub struct ScanResult {
/// The QR code verification object that got created.
pub qr: QrCode,
/// The request that needs to be sent out to notify the other side that a
/// QR code verification should start.
pub request: OutgoingVerificationRequest,
}
impl From<InnerSas> for Sas {
fn from(sas: InnerSas) -> Self {
Self {
other_user_id: sas.other_user_id().to_string(),
other_device_id: sas.other_device_id().to_string(),
flow_id: sas.flow_id().as_str().to_owned(),
is_cancelled: sas.is_cancelled(),
is_done: sas.is_done(),
can_be_presented: sas.can_be_presented(),
supports_emoji: sas.supports_emoji(),
have_we_confirmed: sas.have_we_confirmed(),
we_started: sas.we_started(),
room_id: sas.room_id().map(|r| r.to_string()),
has_been_accepted: sas.has_been_accepted(),
cancel_info: sas.cancel_info().map(|c| c.into()),
}
}
}
/// A result type for requesting verifications.
pub struct RequestVerificationResult {
/// The verification request object that got created.
pub verification: VerificationRequest,
/// The request that needs to be sent out to notify the other side that
/// we're requesting verification to begin.
pub request: OutgoingVerificationRequest,
}
/// A result type for confirming verifications.
pub struct ConfirmVerificationResult {
/// The requests that needs to be sent out to notify the other side that we
/// confirmed the verification.
pub requests: Vec<OutgoingVerificationRequest>,
/// A request that will upload signatures of the verified device or user, if
/// the verification is completed and we're able to sign devices or users
pub signature_request: Option<SignatureUploadRequest>,
}
/// The verificatoin request object which then can transition into some concrete
/// verification method
pub struct VerificationRequest {
/// The other user that is participating in the verification flow
pub other_user_id: String,
/// The other user's device that is participating in the verification flow
pub other_device_id: Option<String>,
/// The unique ID of this verification flow, will be a random string for
/// to-device events or a event ID for in-room events.
pub flow_id: String,
/// The room ID where this verification is happening, will be `None` if the
/// verification is going through to-device messages
pub room_id: Option<String>,
/// Did we initiate the verification flow
pub we_started: bool,
/// Did both parties aggree to verification
pub is_ready: bool,
/// Did another device respond to the verification request
pub is_passive: bool,
/// Has the verification completed successfully
pub is_done: bool,
/// Has the flow been cancelled
pub is_cancelled: bool,
/// The list of verification methods that the other side advertised as
/// supported
pub their_methods: Option<Vec<String>>,
/// The list of verification methods that we advertised as supported
pub our_methods: Option<Vec<String>>,
/// Information about the cancellation of the flow, will be `None` if the
/// flow hasn't been cancelled
pub cancel_info: Option<CancelInfo>,
}
impl From<InnerVerificationRequest> for VerificationRequest {
fn from(v: InnerVerificationRequest) -> Self {
Self {
other_user_id: v.other_user().to_string(),
other_device_id: v.other_device_id().map(|d| d.to_string()),
flow_id: v.flow_id().as_str().to_owned(),
is_cancelled: v.is_cancelled(),
is_done: v.is_done(),
is_ready: v.is_ready(),
room_id: v.room_id().map(|r| r.to_string()),
we_started: v.we_started(),
is_passive: v.is_passive(),
cancel_info: v.cancel_info().map(|c| c.into()),
their_methods: v
.their_supported_methods()
.map(|v| v.into_iter().map(|m| m.to_string()).collect()),
our_methods: v
.our_supported_methods()
.map(|v| v.into_iter().map(|m| m.to_string()).collect()),
}
}
}
@@ -0,0 +1,2 @@
[bindings.swift]
module_name = "MatrixSDKCrypto"
@@ -0,0 +1,2 @@
[build]
target = "wasm32-unknown-unknown"
+3
View File
@@ -0,0 +1,3 @@
/docs
/node_modules
/package-lock.json
+39
View File
@@ -0,0 +1,39 @@
[package]
authors = ["Ivan Enderlin <ivane@element.io>"]
description = "Matrix encryption library, for JavaScript"
edition = "2021"
homepage = "https://github.com/matrix-org/matrix-rust-sdk"
keywords = ["matrix", "chat", "messaging", "ruma", "nio"]
license = "Apache-2.0"
name = "matrix-sdk-crypto-js"
readme = "README.md"
repository = "https://github.com/matrix-org/matrix-rust-sdk"
rust-version = "1.60"
version = "0.5.0"
[package.metadata.docs.rs]
features = ["docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.wasm-pack.profile.release]
wasm-opt = ['-Oz']
[lib]
crate-type = ["cdylib"]
[features]
default = []
qrcode = ["matrix-sdk-crypto/qrcode"]
docsrs = []
[dependencies]
matrix-sdk-common = { version = "0.5.0", path = "../../crates/matrix-sdk-common" }
matrix-sdk-crypto = { version = "0.5.0", path = "../../crates/matrix-sdk-crypto" }
ruma = { git = "https://github.com/ruma/ruma", rev = "96155915f", features = ["client-api-c", "js", "rand", "unstable-msc2676", "unstable-msc2677"] }
vodozemac = { git = "https://github.com/matrix-org/vodozemac/", rev = "2404f83f7d3a3779c1f518e4d949f7da9677c3dd", features = ["js"] }
wasm-bindgen = "0.2.80"
wasm-bindgen-futures = "0.4.30"
js-sys = "0.3.49"
serde_json = "1.0.79"
http = "0.2.6"
anyhow = "1.0"
+55
View File
@@ -0,0 +1,55 @@
# `matrix-sdk-crypto-js`
Welcome to the [WebAssembly] + JavaScript binding for the Rust
[`matrix-sdk-crypto`] library! WebAssembly can run anywhere, but these
bindings are designed to run on a JavaScript host. These bindings are
part of the [`matrix-rust-sdk`] project, which is a library
implementation of a [Matrix] client-server.
`matrix-sdk-crypto` is a no-network-IO implementation of a state
machine, named `OlmMachine`, that handles E2EE ([End-to-End
Encryption](https://en.wikipedia.org/wiki/End-to-end_encryption)) for
[Matrix] clients.
## Usage
These WebAssembly bindings are written in [Rust]. To build them, you
need to install the Rust compiler, see [the Install Rust
Page](https://www.rust-lang.org/tools/install). Then, the workflow is
pretty classical by using [npm], see [the Downloading and installing
Node.js and npm
Page](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm).
Once the Rust compiler, Node.js and npm are installed, you can run the
following commands:
```sh
$ npm install
$ npm run build
$ npm run test
```
A `matrix_sdk_crypto.js`, `matrix_sdk_crypto.d.ts` and a
`matrix_sdk_crypto_bg.wasm` files should be generated in the `pkg/`
directory.
TBD
## Documentation
To generate the documentation, please run the following command:
```sh
$ npm run doc
```
The documentation is generated in the `./docs` directory.
[WebAssembly]: https://webassembly.org/
[`matrix-sdk-crypto`]: https://github.com/matrix-org/matrix-rust-sdk/tree/main/crates/matrix-sdk-crypto
[`matrix-rust-sdk`]: https://github.com/matrix-org/matrix-rust-sdk
[Matrix]: https://matrix.org/
[Rust]: https://www.rust-lang.org/
[npm]: https://www.npmjs.com/
@@ -0,0 +1,41 @@
{
"name": "@matrix-org/matrix-sdk-crypto-js",
"version": "0.5.0",
"homepage": "https://github.com/matrix-org/matrix-rust-sdk",
"description": "Matrix encryption library, for JavaScript",
"license": "Apache-2.0",
"collaborators": [
"Ivan Enderlin <ivane@element.io>"
],
"repository": {
"type": "git",
"url": "https://github.com/matrix-org/matrix-rust-sdk"
},
"keywords": [
"matrix",
"chat",
"messaging",
"ruma",
"nio"
],
"main": "matrix_sdk_crypto.js",
"types": "pkg/matrix_sdk_crypto.d.ts",
"files": [
"pkg/matrix_sdk_crypto_bg.wasm",
"pkg/matrix_sdk_crypto.js",
"pkg/matrix_sdk_crypto.d.ts"
],
"devDependencies": {
"wasm-pack": "^0.10.2",
"jest": "^28.1.0",
"typedoc": "^0.22.17"
},
"engines": {
"node": ">= 10"
},
"scripts": {
"build": "RUSTFLAGS='-C opt-level=z' wasm-pack build --release --target nodejs --out-name matrix_sdk_crypto --out-dir ./pkg",
"test": "jest --verbose",
"doc": "typedoc --tsconfig ."
}
}
@@ -0,0 +1,126 @@
//! Encryption types & siblings.
use std::time::Duration;
use wasm_bindgen::prelude::*;
use crate::events;
/// Settings for an encrypted room.
///
/// This determines the algorithm and rotation periods of a group
/// session.
#[wasm_bindgen(getter_with_clone)]
#[derive(Debug, Clone)]
pub struct EncryptionSettings {
/// The encryption algorithm that should be used in the room.
pub algorithm: EncryptionAlgorithm,
/// How long the session should be used before changing it,
/// expressed in microseconds.
#[wasm_bindgen(js_name = "rotationPeriod")]
pub rotation_period: u64,
/// How many messages should be sent before changing the session.
#[wasm_bindgen(js_name = "rotationPeriodMessages")]
pub rotation_period_messages: u64,
/// The history visibility of the room when the session was
/// created.
#[wasm_bindgen(js_name = "historyVisibility")]
pub history_visibility: events::HistoryVisibility,
}
impl Default for EncryptionSettings {
fn default() -> Self {
let default = matrix_sdk_crypto::olm::EncryptionSettings::default();
Self {
algorithm: default.algorithm.into(),
rotation_period: default.rotation_period.as_micros().try_into().unwrap(),
rotation_period_messages: default.rotation_period_msgs,
history_visibility: default.history_visibility.into(),
}
}
}
#[wasm_bindgen]
impl EncryptionSettings {
/// Create a new `EncryptionSettings` with default values.
#[wasm_bindgen(constructor)]
pub fn new() -> EncryptionSettings {
Self::default()
}
}
impl From<&EncryptionSettings> for matrix_sdk_crypto::olm::EncryptionSettings {
fn from(value: &EncryptionSettings) -> Self {
Self {
algorithm: value.algorithm.clone().into(),
rotation_period: Duration::from_micros(value.rotation_period),
rotation_period_msgs: value.rotation_period_messages,
history_visibility: value.history_visibility.clone().into(),
}
}
}
/// An encryption algorithm to be used to encrypt messages sent to a
/// room.
#[wasm_bindgen]
#[derive(Debug, Clone)]
pub enum EncryptionAlgorithm {
/// Olm version 1 using Curve25519, AES-256, and SHA-256.
OlmV1Curve25519AesSha2,
/// Megolm version 1 using AES-256 and SHA-256.
MegolmV1AesSha2,
}
impl From<EncryptionAlgorithm> for ruma::EventEncryptionAlgorithm {
fn from(value: EncryptionAlgorithm) -> Self {
use EncryptionAlgorithm::*;
match value {
OlmV1Curve25519AesSha2 => Self::OlmV1Curve25519AesSha2,
MegolmV1AesSha2 => Self::MegolmV1AesSha2,
}
}
}
impl From<ruma::EventEncryptionAlgorithm> for EncryptionAlgorithm {
fn from(value: ruma::EventEncryptionAlgorithm) -> Self {
use ruma::EventEncryptionAlgorithm::*;
match value {
OlmV1Curve25519AesSha2 => Self::OlmV1Curve25519AesSha2,
MegolmV1AesSha2 => Self::MegolmV1AesSha2,
_ => unreachable!("Unknown variant"),
}
}
}
/// The verification state of the device that sent an event to us.
#[wasm_bindgen]
#[derive(Debug)]
pub enum VerificationState {
/// The device is trusted.
Trusted,
/// The device is not trusted.
Untrusted,
/// The device is not known to us.
UnknownDevice,
}
impl From<&matrix_sdk_common::deserialized_responses::VerificationState> for VerificationState {
fn from(value: &matrix_sdk_common::deserialized_responses::VerificationState) -> Self {
use matrix_sdk_common::deserialized_responses::VerificationState::*;
match value {
Trusted => Self::Trusted,
Untrusted => Self::Untrusted,
UnknownDevice => Self::UnknownDevice,
}
}
}
@@ -0,0 +1,61 @@
//! Types related to events.
use ruma::events::room::history_visibility::HistoryVisibility as RumaHistoryVisibility;
use wasm_bindgen::prelude::*;
/// Who can see a room's history.
#[wasm_bindgen]
#[derive(Debug, Clone)]
pub enum HistoryVisibility {
/// Previous events are accessible to newly joined members from
/// the point they were invited onwards.
///
/// Events stop being accessible when the member's state changes
/// to something other than *invite* or *join*.
Invited,
/// Previous events are accessible to newly joined members from
/// the point they joined the room onwards.
///
/// Events stop being accessible when the member's state changes
/// to something other than *join*.
Joined,
/// Previous events are always accessible to newly joined members.
///
/// All events in the room are accessible, even those sent when
/// the member was not a part of the room.
Shared,
/// All events while this is the `HistoryVisibility` value may be
/// shared by any participating homeserver with anyone, regardless
/// of whether they have ever joined the room.
WorldReadable,
}
impl From<HistoryVisibility> for RumaHistoryVisibility {
fn from(value: HistoryVisibility) -> Self {
use HistoryVisibility::*;
match value {
Invited => Self::Invited,
Joined => Self::Joined,
Shared => Self::Shared,
WorldReadable => Self::WorldReadable,
}
}
}
impl From<RumaHistoryVisibility> for HistoryVisibility {
fn from(value: RumaHistoryVisibility) -> Self {
use RumaHistoryVisibility::*;
match value {
Invited => Self::Invited,
Joined => Self::Joined,
Shared => Self::Shared,
WorldReadable => Self::WorldReadable,
_ => unreachable!("Unknown variant"),
}
}
}
@@ -0,0 +1,26 @@
use std::future::Future;
use js_sys::Promise;
use wasm_bindgen::{JsValue, UnwrapThrowExt};
use wasm_bindgen_futures::spawn_local;
pub(crate) fn future_to_promise<F, T>(future: F) -> Promise
where
F: Future<Output = Result<T, anyhow::Error>> + 'static,
T: Into<JsValue>,
{
let mut future = Some(future);
Promise::new(&mut |resolve, reject| {
let future = future.take().unwrap_throw();
spawn_local(async move {
match future.await {
Ok(value) => resolve.call1(&JsValue::UNDEFINED, &value.into()).unwrap_throw(),
Err(value) => {
reject.call1(&JsValue::UNDEFINED, &value.to_string().into()).unwrap_throw()
}
};
});
})
}
@@ -0,0 +1,175 @@
//! Types for [Matrix](https://matrix.org/) identifiers for devices,
//! events, keys, rooms, servers, users and URIs.
use wasm_bindgen::prelude::*;
/// A Matrix [user ID].
///
/// [user ID]: https://spec.matrix.org/v1.2/appendices/#user-identifiers
#[wasm_bindgen]
#[derive(Debug, Clone)]
pub struct UserId {
pub(crate) inner: ruma::OwnedUserId,
}
impl From<ruma::OwnedUserId> for UserId {
fn from(inner: ruma::OwnedUserId) -> Self {
Self { inner }
}
}
#[wasm_bindgen]
impl UserId {
/// Parse/validate and create a new `UserId`.
#[wasm_bindgen(constructor)]
pub fn new(id: &str) -> Result<UserId, JsError> {
Ok(Self::from(ruma::UserId::parse(id)?))
}
/// Returns the user's localpart.
#[wasm_bindgen(getter)]
pub fn localpart(&self) -> String {
self.inner.localpart().to_owned()
}
/// Returns the server name of the user ID.
#[wasm_bindgen(getter, js_name = "serverName")]
pub fn server_name(&self) -> ServerName {
ServerName { inner: self.inner.server_name().to_owned() }
}
/// Whether this user ID is a historical one.
///
/// A historical user ID is one that doesn't conform to the latest
/// specification of the user ID grammar but is still accepted
/// because it was previously allowed.
#[wasm_bindgen(js_name = "isHistorical")]
pub fn is_historical(&self) -> bool {
self.inner.is_historical()
}
/// Return the user ID as a string.
#[wasm_bindgen(js_name = "toString")]
#[allow(clippy::inherent_to_string)]
pub fn to_string(&self) -> String {
self.inner.as_str().to_owned()
}
}
/// A Matrix key ID.
///
/// Device identifiers in Matrix are completely opaque character
/// sequences. This type is provided simply for its semantic value.
#[wasm_bindgen]
#[derive(Debug, Clone)]
pub struct DeviceId {
pub(crate) inner: ruma::OwnedDeviceId,
}
impl From<ruma::OwnedDeviceId> for DeviceId {
fn from(inner: ruma::OwnedDeviceId) -> Self {
Self { inner }
}
}
#[wasm_bindgen]
impl DeviceId {
/// Create a new `DeviceId`.
#[wasm_bindgen(constructor)]
pub fn new(id: &str) -> DeviceId {
Self::from(ruma::OwnedDeviceId::from(id))
}
/// Return the device ID as a string.
#[wasm_bindgen(js_name = "toString")]
#[allow(clippy::inherent_to_string)]
pub fn to_string(&self) -> String {
self.inner.as_str().to_owned()
}
}
/// A Matrix [room ID].
///
/// [room ID]: https://spec.matrix.org/v1.2/appendices/#room-ids-and-event-ids
#[wasm_bindgen]
#[derive(Debug, Clone)]
pub struct RoomId {
pub(crate) inner: ruma::OwnedRoomId,
}
impl From<ruma::OwnedRoomId> for RoomId {
fn from(inner: ruma::OwnedRoomId) -> Self {
Self { inner }
}
}
#[wasm_bindgen]
impl RoomId {
/// Parse/validate and create a new `RoomId`.
#[wasm_bindgen(constructor)]
pub fn new(id: &str) -> Result<RoomId, JsError> {
Ok(Self::from(ruma::RoomId::parse(id)?))
}
/// Returns the user's localpart.
#[wasm_bindgen(getter)]
pub fn localpart(&self) -> String {
self.inner.localpart().to_owned()
}
/// Returns the server name of the room ID.
#[wasm_bindgen(getter, js_name = "serverName")]
pub fn server_name(&self) -> ServerName {
ServerName { inner: self.inner.server_name().to_owned() }
}
/// Return the room ID as a string.
#[wasm_bindgen(js_name = "toString")]
#[allow(clippy::inherent_to_string)]
pub fn to_string(&self) -> String {
self.inner.as_str().to_owned()
}
}
/// A Matrix-spec compliant [server name].
///
/// It consists of a host and an optional port (separated by a colon if
/// present).
///
/// [server name]: https://spec.matrix.org/v1.2/appendices/#server-name
#[wasm_bindgen]
#[derive(Debug)]
pub struct ServerName {
inner: ruma::OwnedServerName,
}
#[wasm_bindgen]
impl ServerName {
/// Parse/validate and create a new `ServerName`.
#[wasm_bindgen(constructor)]
pub fn new(name: &str) -> Result<ServerName, JsError> {
Ok(Self { inner: ruma::ServerName::parse(name)? })
}
/// Returns the host of the server name.
///
/// That is: Return the part of the server before `:<port>` or the
/// full server name if there is no port.
#[wasm_bindgen(getter)]
pub fn host(&self) -> String {
self.inner.host().to_owned()
}
/// Returns the port of the server name if any.
#[wasm_bindgen(getter)]
pub fn port(&self) -> Option<u16> {
self.inner.port()
}
/// Returns true if and only if the server name is an IPv4 or IPv6
/// address.
#[wasm_bindgen(js_name = "isIpLiteral")]
pub fn is_ip_literal(&self) -> bool {
self.inner.is_ip_literal()
}
}
+58
View File
@@ -0,0 +1,58 @@
// Copyright 2022 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.
#![doc = include_str!("../README.md")]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![warn(missing_docs, missing_debug_implementations)]
#![allow(clippy::drop_non_drop)] // triggered by wasm_bindgen code
pub mod encryption;
pub mod events;
mod future;
pub mod identifiers;
pub mod machine;
pub mod requests;
pub mod responses;
pub mod sync_events;
use js_sys::{Object, Reflect};
use wasm_bindgen::{convert::RefFromWasmAbi, prelude::*};
/// A really hacky and dirty code to downcast a `JsValue` to `T:
/// RefFromWasmAbi`, inspired by
/// https://github.com/rustwasm/wasm-bindgen/issues/2231#issuecomment-656293288.
///
/// The returned value is likely to be a `wasm_bindgen::__ref::Ref<T>`.
fn downcast<T>(value: &JsValue, classname: &str) -> Result<T::Anchor, JsError>
where
T: RefFromWasmAbi<Abi = u32>,
{
let constructor_name = Object::get_prototype_of(value).constructor().name();
if constructor_name == classname {
let pointer = Reflect::get(value, &JsValue::from_str("ptr"))
.map_err(|_| JsError::new("Failed to read the `JsValue` pointer"))?;
let pointer = pointer
.as_f64()
.ok_or_else(|| JsError::new("Failed to read the `JsValue` pointer as a `f64`"))?
as u32;
Ok(unsafe { T::ref_from_abi(pointer) })
} else {
Err(JsError::new(&format!(
"Expect an `{}` instance, received `{}` instead",
classname, constructor_name,
)))
}
}
@@ -0,0 +1,446 @@
//! The crypto specific Olm objects.
use std::collections::BTreeMap;
use js_sys::{Array, Map, Promise, Set};
use ruma::{
events::room::encrypted::OriginalSyncRoomEncryptedEvent, DeviceKeyAlgorithm,
OwnedTransactionId, UInt,
};
use serde_json::Value as JsonValue;
use wasm_bindgen::prelude::*;
use crate::{
downcast, encryption,
future::future_to_promise,
identifiers, requests,
requests::OutgoingRequest,
responses::{self, response_from_string},
sync_events,
};
/// State machine implementation of the Olm/Megolm encryption protocol
/// used for Matrix end to end encryption.
#[wasm_bindgen]
#[derive(Debug, Clone)]
pub struct OlmMachine {
inner: matrix_sdk_crypto::OlmMachine,
}
#[wasm_bindgen]
impl OlmMachine {
/// Create a new memory based `OlmMachine`.
///
/// The created machine will keep the encryption keys only in
/// memory and once the objects is dropped, the keys will be lost.
///
/// `user_id` represents the unique ID of the user that owns this
/// machine. `device_id` represents the unique ID of the device
/// that owns this machine.
#[wasm_bindgen(constructor)]
#[allow(clippy::new_ret_no_self)]
pub fn new(user_id: &identifiers::UserId, device_id: &identifiers::DeviceId) -> Promise {
let user_id = user_id.inner.clone();
let device_id = device_id.inner.clone();
future_to_promise(async move {
Ok(OlmMachine {
inner: matrix_sdk_crypto::OlmMachine::new(user_id.as_ref(), device_id.as_ref())
.await,
})
})
}
/// The unique user ID that owns this `OlmMachine` instance.
#[wasm_bindgen(getter, js_name = "userId")]
pub fn user_id(&self) -> identifiers::UserId {
identifiers::UserId::from(self.inner.user_id().to_owned())
}
/// The unique device ID that identifies this `OlmMachine`.
#[wasm_bindgen(getter, js_name = "deviceId")]
pub fn device_id(&self) -> identifiers::DeviceId {
identifiers::DeviceId::from(self.inner.device_id().to_owned())
}
/// Get the public parts of our Olm identity keys.
#[wasm_bindgen(getter, js_name = "identityKeys")]
pub fn identity_keys(&self) -> IdentityKeys {
self.inner.identity_keys().into()
}
/// Get the display name of our own device.
#[wasm_bindgen(getter, js_name = "displayName")]
pub fn display_name(&self) -> Promise {
let me = self.inner.clone();
future_to_promise(async move { Ok(me.display_name().await?) })
}
/// Get all the tracked users of our own device.
///
/// Returns a `Set<UserId>`.
#[wasm_bindgen(js_name = "trackedUsers")]
pub fn tracked_users(&self) -> Set {
let set = Set::new(&JsValue::UNDEFINED);
for user in self.inner.tracked_users() {
set.add(&identifiers::UserId::from(user).into());
}
set
}
/// Update the tracked users.
///
/// `users` is an iterator over user IDs that should be marked for
/// tracking.
///
/// This will mark users that weren't seen before for a key query
/// and tracking.
///
/// If the user is already known to the Olm machine, it will not
/// be considered for a key query.
#[wasm_bindgen(js_name = "updateTrackedUsers")]
pub fn update_tracked_users(&self, users: &Array) -> Result<Promise, JsError> {
let users = users
.iter()
.map(|user| Ok(downcast::<identifiers::UserId>(&user, "UserId")?.inner.clone()))
.collect::<Result<Vec<ruma::OwnedUserId>, JsError>>()?;
let me = self.inner.clone();
Ok(future_to_promise(async move {
me.update_tracked_users(users.iter().map(AsRef::as_ref)).await;
Ok(JsValue::UNDEFINED)
}))
}
/// Handle to-device events and one-time key counts from a sync
/// response.
///
/// This will decrypt and handle to-device events returning the
/// decrypted versions of them.
///
/// To decrypt an event from the room timeline call
/// `decrypt_room_event`.
#[wasm_bindgen(js_name = "receiveSyncChanges")]
pub fn receive_sync_changes(
&self,
to_device_events: &str,
changed_devices: &sync_events::DeviceLists,
one_time_key_counts: &Map,
unused_fallback_keys: &Set,
) -> Result<Promise, JsError> {
let to_device_events = serde_json::from_str(to_device_events)?;
let changed_devices = changed_devices.inner.clone();
let one_time_key_counts: BTreeMap<DeviceKeyAlgorithm, UInt> = one_time_key_counts
.entries()
.into_iter()
.filter_map(|js_value| {
let pair = Array::from(&js_value.ok()?);
let (key, value) = (
DeviceKeyAlgorithm::from(pair.at(0).as_string()?),
UInt::new(pair.at(1).as_f64()? as u64)?,
);
Some((key, value))
})
.collect();
let unused_fallback_keys: Option<Vec<DeviceKeyAlgorithm>> = Some(
unused_fallback_keys
.values()
.into_iter()
.filter_map(|js_value| Some(DeviceKeyAlgorithm::from(js_value.ok()?.as_string()?)))
.collect(),
);
let me = self.inner.clone();
Ok(future_to_promise(async move {
Ok(serde_json::to_string(
&me.receive_sync_changes(
to_device_events,
&changed_devices,
&one_time_key_counts,
unused_fallback_keys.as_deref(),
)
.await?,
)?)
}))
}
/// Get the outgoing requests that need to be sent out.
///
/// This returns a list of `JsValue` to represent either:
/// * `KeysUploadRequest`,
/// * `KeysQueryRequest`,
/// * `KeysClaimRequest`,
/// * `ToDeviceRequest`,
/// * `SignatureUploadRequest`,
/// * `RoomMessageRequest` or
/// * `KeysBackupRequest`.
///
/// Those requests need to be sent out to the server and the
/// responses need to be passed back to the state machine using
/// `mark_request_as_sent`.
#[wasm_bindgen(js_name = "outgoingRequests")]
pub fn outgoing_requests(&self) -> Promise {
let me = self.inner.clone();
future_to_promise(async move {
Ok(me
.outgoing_requests()
.await?
.into_iter()
.map(OutgoingRequest)
.map(TryFrom::try_from)
.collect::<Result<Vec<JsValue>, _>>()?
.into_iter()
.collect::<Array>())
})
}
/// Mark the request with the given request ID as sent (see
/// `outgoing_requests`).
///
/// Arguments are:
///
/// * `request_id` represents the unique ID of the request that was sent
/// out. This is needed to couple the response with the now sent out
/// request.
/// * `response_type` represents the type of the request that was sent out.
/// * `response` represents the response that was received from the server
/// after the outgoing request was sent out.
#[wasm_bindgen(js_name = "markRequestAsSent")]
pub fn mark_request_as_sent(
&self,
request_id: &str,
request_type: requests::RequestType,
response: &str,
) -> Result<Promise, JsError> {
let transaction_id = OwnedTransactionId::from(request_id);
let response = response_from_string(response)?;
let incoming_response = responses::OwnedResponse::try_from((request_type, response))?;
let me = self.inner.clone();
Ok(future_to_promise(async move {
Ok(me.mark_request_as_sent(&transaction_id, &incoming_response).await.map(|_| true)?)
}))
}
/// Encrypt a room message for the given room.
///
/// Beware that a room key needs to be shared before this
/// method can be called using the `share_room_key` method.
///
/// `room_id` is the ID of the room for which the message should
/// be encrypted. `event_type` is the type of the event. `content`
/// is the plaintext content of the message that should be
/// encrypted.
///
/// # Panics
///
/// Panics if a group session for the given room wasn't shared
/// beforehand.
#[wasm_bindgen(js_name = "encryptRoomEvent")]
pub fn encrypt_room_event(
&self,
room_id: &identifiers::RoomId,
event_type: String,
content: &str,
) -> Result<Promise, JsError> {
let room_id = room_id.inner.clone();
let content: JsonValue = serde_json::from_str(content)?;
let me = self.inner.clone();
Ok(future_to_promise(async move {
Ok(serde_json::to_string(
&me.encrypt_room_event_raw(&room_id, content, event_type.as_ref()).await?,
)?)
}))
}
/// Decrypt an event from a room timeline.
///
/// # Arguments
///
/// * `event`, the event that should be decrypted.
/// * `room_id`, the ID of the room where the event was sent to.
#[wasm_bindgen(js_name = "decryptRoomEvent")]
pub fn decrypt_room_event(
&self,
event: &str,
room_id: &identifiers::RoomId,
) -> Result<Promise, JsError> {
let event: OriginalSyncRoomEncryptedEvent = serde_json::from_str(event)?;
let room_id = room_id.inner.clone();
let me = self.inner.clone();
Ok(future_to_promise(async move {
let room_event = me.decrypt_room_event(&event, room_id.as_ref()).await?;
Ok(responses::DecryptedRoomEvent::from(room_event))
}))
}
/// Invalidate the currently active outbound group session for the
/// given room.
///
/// Returns true if a session was invalidated, false if there was
/// no session to invalidate.
#[wasm_bindgen(js_name = "invalidateGroupSession")]
pub fn invalidate_group_session(&self, room_id: &identifiers::RoomId) -> Promise {
let room_id = room_id.inner.clone();
let me = self.inner.clone();
future_to_promise(async move { Ok(me.invalidate_group_session(&room_id).await?) })
}
/// Get to-device requests to share a room key with users in a room.
///
/// `room_id` is the room ID. `users` is an array of `UserId`
/// objects. `encryption_settings` are an `EncryptionSettings`
/// object.
#[wasm_bindgen(js_name = "shareRoomKey")]
pub fn share_room_key(
&self,
room_id: &identifiers::RoomId,
users: &Array,
encryption_settings: &encryption::EncryptionSettings,
) -> Result<Promise, JsError> {
let room_id = room_id.inner.clone();
let users = users
.iter()
.map(|user| Ok(downcast::<identifiers::UserId>(&user, "UserId")?.inner.clone()))
.collect::<Result<Vec<ruma::OwnedUserId>, JsError>>()?;
let encryption_settings =
matrix_sdk_crypto::olm::EncryptionSettings::from(encryption_settings);
let me = self.inner.clone();
Ok(future_to_promise(async move {
Ok(serde_json::to_string(
&me.share_room_key(&room_id, users.iter().map(AsRef::as_ref), encryption_settings)
.await?,
)?)
}))
}
/// Get the a key claiming request for the user/device pairs that
/// we are missing Olm sessions for.
///
/// Returns `NULL` if no key claiming request needs to be sent
/// out, otherwise it returns an `Array` where the first key is
/// the transaction ID as a string, and the second key is the keys
/// claim request serialized to JSON.
///
/// Sessions need to be established between devices so group
/// sessions for a room can be shared with them.
///
/// This should be called every time a group session needs to be
/// shared as well as between sync calls. After a sync some
/// devices may request room keys without us having a valid Olm
/// session with them, making it impossible to server the room key
/// request, thus its necessary to check for missing sessions
/// between sync as well.
///
/// Note: Care should be taken that only one such request at a
/// time is in flight, e.g. using a lock.
///
/// The response of a successful key claiming requests needs to be
/// passed to the `OlmMachine` with the `mark_request_as_sent`.
///
/// `users` represents the list of users that we should check if
/// we lack a session with one of their devices. This can be an
/// empty iterator when calling this method between sync requests.
#[wasm_bindgen(js_name = "getMissingSessions")]
pub fn get_missing_sessions(&self, users: &Array) -> Result<Promise, JsError> {
let users = users
.iter()
.map(|user| Ok(downcast::<identifiers::UserId>(&user, "UserId")?.inner.clone()))
.collect::<Result<Vec<ruma::OwnedUserId>, JsError>>()?;
let me = self.inner.clone();
Ok(future_to_promise(async move {
match me.get_missing_sessions(users.iter().map(AsRef::as_ref)).await? {
Some((transaction_id, keys_claim_request)) => {
Ok(JsValue::from(requests::KeysClaimRequest::try_from((
transaction_id.to_string(),
&keys_claim_request,
))?))
}
None => Ok(JsValue::NULL),
}
}))
}
}
/// An Ed25519 public key, used to verify digital signatures.
#[wasm_bindgen]
#[derive(Debug, Clone)]
pub struct Ed25519PublicKey {
inner: vodozemac::Ed25519PublicKey,
}
#[wasm_bindgen]
impl Ed25519PublicKey {
/// The number of bytes an Ed25519 public key has.
#[wasm_bindgen(getter)]
pub fn length(&self) -> usize {
vodozemac::Ed25519PublicKey::LENGTH
}
/// Serialize an Ed25519 public key to an unpadded base64
/// representation.
#[wasm_bindgen(js_name = "toBase64")]
pub fn to_base64(&self) -> String {
self.inner.to_base64()
}
}
/// A Curve25519 public key.
#[wasm_bindgen]
#[derive(Debug, Clone)]
pub struct Curve25519PublicKey {
inner: vodozemac::Curve25519PublicKey,
}
#[wasm_bindgen]
impl Curve25519PublicKey {
/// The number of bytes a Curve25519 public key has.
#[wasm_bindgen(getter)]
pub fn length(&self) -> usize {
vodozemac::Curve25519PublicKey::LENGTH
}
/// Serialize an Curve25519 public key to an unpadded base64
/// representation.
#[wasm_bindgen(js_name = "toBase64")]
pub fn to_base64(&self) -> String {
self.inner.to_base64()
}
}
/// Struct holding the two public identity keys of an account.
#[wasm_bindgen(getter_with_clone)]
#[derive(Debug)]
pub struct IdentityKeys {
/// The Ed25519 public key, used for signing.
pub ed25519: Ed25519PublicKey,
/// The Curve25519 public key, used for establish shared secrets.
pub curve25519: Curve25519PublicKey,
}
impl From<matrix_sdk_crypto::olm::IdentityKeys> for IdentityKeys {
fn from(value: matrix_sdk_crypto::olm::IdentityKeys) -> Self {
Self {
ed25519: Ed25519PublicKey { inner: value.ed25519 },
curve25519: Curve25519PublicKey { inner: value.curve25519 },
}
}
}
@@ -0,0 +1,372 @@
//! Types to handle requests.
use js_sys::JsString;
use matrix_sdk_crypto::{
requests::{
KeysBackupRequest as RumaKeysBackupRequest, KeysQueryRequest as RumaKeysQueryRequest,
RoomMessageRequest as RumaRoomMessageRequest, ToDeviceRequest as RumaToDeviceRequest,
},
OutgoingRequests,
};
use ruma::api::client::keys::{
claim_keys::v3::Request as RumaKeysClaimRequest,
upload_keys::v3::Request as RumaKeysUploadRequest,
upload_signatures::v3::Request as RumaSignatureUploadRequest,
};
use wasm_bindgen::prelude::*;
/// Data for a request to the `/keys/upload` API endpoint
/// ([specification]).
///
/// Publishes end-to-end encryption keys for the device.
///
/// [specification]: https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3keysupload
#[derive(Debug)]
#[wasm_bindgen(getter_with_clone)]
pub struct KeysUploadRequest {
/// The request ID.
#[wasm_bindgen(readonly)]
pub id: JsString,
/// A JSON-encoded object of form:
///
/// ```json
/// {"device_keys": …, "one_time_keys": …, "fallback_keys": …}
/// ```
#[wasm_bindgen(readonly)]
pub body: JsString,
}
#[wasm_bindgen]
impl KeysUploadRequest {
/// Create a new `KeysUploadRequest`.
#[wasm_bindgen(constructor)]
pub fn new(id: JsString, body: JsString) -> KeysUploadRequest {
Self { id, body }
}
/// Get its request type.
#[wasm_bindgen(getter, js_name = "type")]
pub fn request_type(&self) -> RequestType {
RequestType::KeysUpload
}
}
/// Data for a request to the `/keys/query` API endpoint
/// ([specification]).
///
/// Returns the current devices and identity keys for the given users.
///
/// [specification]: https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3keysquery
#[derive(Debug)]
#[wasm_bindgen(getter_with_clone)]
pub struct KeysQueryRequest {
/// The request ID.
#[wasm_bindgen(readonly)]
pub id: JsString,
/// A JSON-encoded object of form:
///
/// ```json
/// {"timeout": …, "device_keys": …, "token": …}
/// ```
#[wasm_bindgen(readonly)]
pub body: JsString,
}
#[wasm_bindgen]
impl KeysQueryRequest {
/// Create a new `KeysQueryRequest`.
#[wasm_bindgen(constructor)]
pub fn new(id: JsString, body: JsString) -> KeysQueryRequest {
Self { id, body }
}
/// Get its request type.
#[wasm_bindgen(getter, js_name = "type")]
pub fn request_type(&self) -> RequestType {
RequestType::KeysQuery
}
}
/// Data for a request to the `/keys/claim` API endpoint
/// ([specification]).
///
/// Claims one-time keys that can be used to establish 1-to-1 E2EE
/// sessions.
///
/// [specification]: https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3keysclaim
#[derive(Debug)]
#[wasm_bindgen(getter_with_clone)]
pub struct KeysClaimRequest {
/// The request ID.
#[wasm_bindgen(readonly)]
pub id: JsString,
/// A JSON-encoded object of form:
///
/// ```json
/// {"timeout": …, "one_time_keys": …}
/// ```
#[wasm_bindgen(readonly)]
pub body: JsString,
}
#[wasm_bindgen]
impl KeysClaimRequest {
/// Create a new `KeysClaimRequest`.
#[wasm_bindgen(constructor)]
pub fn new(id: JsString, body: JsString) -> KeysClaimRequest {
Self { id, body }
}
/// Get its request type.
#[wasm_bindgen(getter, js_name = "type")]
pub fn request_type(&self) -> RequestType {
RequestType::KeysClaim
}
}
/// Data for a request to the `/sendToDevice` API endpoint
/// ([specification]).
///
/// Send an event to a single device or to a group of devices.
///
/// [specification]: https://spec.matrix.org/unstable/client-server-api/#put_matrixclientv3sendtodeviceeventtypetxnid
#[derive(Debug)]
#[wasm_bindgen(getter_with_clone)]
pub struct ToDeviceRequest {
/// The request ID.
#[wasm_bindgen(readonly)]
pub id: JsString,
/// A JSON-encoded object of form:
///
/// ```json
/// {"event_type": …, "txn_id": …, "messages": …}
/// ```
#[wasm_bindgen(readonly)]
pub body: JsString,
}
#[wasm_bindgen]
impl ToDeviceRequest {
/// Create a new `ToDeviceRequest`.
#[wasm_bindgen(constructor)]
pub fn new(id: JsString, body: JsString) -> ToDeviceRequest {
Self { id, body }
}
/// Get its request type.
#[wasm_bindgen(getter, js_name = "type")]
pub fn request_type(&self) -> RequestType {
RequestType::ToDevice
}
}
/// Data for a request to the `/keys/signatures/upload` API endpoint
/// ([specification]).
///
/// Publishes cross-signing signatures for the user.
///
/// [specification]: https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3keyssignaturesupload
#[derive(Debug)]
#[wasm_bindgen(getter_with_clone)]
pub struct SignatureUploadRequest {
/// The request ID.
#[wasm_bindgen(readonly)]
pub id: JsString,
/// A JSON-encoded object of form:
///
/// ```json
/// {"signed_keys": …, "txn_id": …, "messages": …}
/// ```
#[wasm_bindgen(readonly)]
pub body: JsString,
}
#[wasm_bindgen]
impl SignatureUploadRequest {
/// Create a new `SignatureUploadRequest`.
#[wasm_bindgen(constructor)]
pub fn new(id: JsString, body: JsString) -> SignatureUploadRequest {
Self { id, body }
}
/// Get its request type.
#[wasm_bindgen(getter, js_name = "type")]
pub fn request_type(&self) -> RequestType {
RequestType::SignatureUpload
}
}
/// A customized owned request type for sending out room messages
/// ([specification]).
///
/// [specification]: https://spec.matrix.org/unstable/client-server-api/#put_matrixclientv3roomsroomidsendeventtypetxnid
#[derive(Debug)]
#[wasm_bindgen(getter_with_clone)]
pub struct RoomMessageRequest {
/// The request ID.
#[wasm_bindgen(readonly)]
pub id: JsString,
/// A JSON-encoded object of form:
///
/// ```json
/// {"room_id": …, "txn_id": …, "content": …}
/// ```
#[wasm_bindgen(readonly)]
pub body: JsString,
}
#[wasm_bindgen]
impl RoomMessageRequest {
/// Create a new `RoomMessageRequest`.
#[wasm_bindgen(constructor)]
pub fn new(id: JsString, body: JsString) -> RoomMessageRequest {
Self { id, body }
}
/// Get its request type.
#[wasm_bindgen(getter, js_name = "type")]
pub fn request_type(&self) -> RequestType {
RequestType::RoomMessage
}
}
/// A request that will back up a batch of room keys to the server
/// ([specification]).
///
/// [specification]: https://spec.matrix.org/unstable/client-server-api/#put_matrixclientv3room_keyskeys
#[derive(Debug)]
#[wasm_bindgen(getter_with_clone)]
pub struct KeysBackupRequest {
/// The request ID.
#[wasm_bindgen(readonly)]
pub id: JsString,
/// A JSON-encoded object of form:
///
/// ```json
/// {"rooms": …}
/// ```
#[wasm_bindgen(readonly)]
pub body: JsString,
}
#[wasm_bindgen]
impl KeysBackupRequest {
/// Create a new `KeysBackupRequest`.
#[wasm_bindgen(constructor)]
pub fn new(id: JsString, body: JsString) -> KeysBackupRequest {
Self { id, body }
}
/// Get its request type.
#[wasm_bindgen(getter, js_name = "type")]
pub fn request_type(&self) -> RequestType {
RequestType::KeysBackup
}
}
macro_rules! request {
($request:ident from $ruma_request:ident maps fields $( $field:ident ),+ $(,)? ) => {
impl TryFrom<(String, &$ruma_request)> for $request {
type Error = serde_json::Error;
fn try_from(
(request_id, request): (String, &$ruma_request),
) -> Result<Self, Self::Error> {
let mut map = serde_json::Map::new();
$(
map.insert(stringify!($field).to_owned(), serde_json::to_value(&request.$field).unwrap());
)+
let value = serde_json::Value::Object(map);
Ok($request {
id: request_id.into(),
body: serde_json::to_string(&value)?.into(),
})
}
}
};
}
request!(KeysUploadRequest from RumaKeysUploadRequest maps fields device_keys, one_time_keys, fallback_keys);
request!(KeysQueryRequest from RumaKeysQueryRequest maps fields timeout, device_keys, token);
request!(KeysClaimRequest from RumaKeysClaimRequest maps fields timeout, one_time_keys);
request!(ToDeviceRequest from RumaToDeviceRequest maps fields event_type, txn_id, messages);
request!(SignatureUploadRequest from RumaSignatureUploadRequest maps fields signed_keys);
request!(RoomMessageRequest from RumaRoomMessageRequest maps fields room_id, txn_id, content);
request!(KeysBackupRequest from RumaKeysBackupRequest maps fields rooms);
// JavaScript has no complex enums like Rust. To return structs of
// different types, we have no choice that hiding everything behind a
// `JsValue`.
pub(crate) struct OutgoingRequest(pub(crate) matrix_sdk_crypto::OutgoingRequest);
impl TryFrom<OutgoingRequest> for JsValue {
type Error = serde_json::Error;
fn try_from(outgoing_request: OutgoingRequest) -> Result<Self, Self::Error> {
let request_id = outgoing_request.0.request_id().to_string();
Ok(match outgoing_request.0.request() {
OutgoingRequests::KeysUpload(request) => {
JsValue::from(KeysUploadRequest::try_from((request_id, request))?)
}
OutgoingRequests::KeysQuery(request) => {
JsValue::from(KeysQueryRequest::try_from((request_id, request))?)
}
OutgoingRequests::KeysClaim(request) => {
JsValue::from(KeysClaimRequest::try_from((request_id, request))?)
}
OutgoingRequests::ToDeviceRequest(request) => {
JsValue::from(ToDeviceRequest::try_from((request_id, request))?)
}
OutgoingRequests::SignatureUpload(request) => {
JsValue::from(SignatureUploadRequest::try_from((request_id, request))?)
}
OutgoingRequests::RoomMessage(request) => {
JsValue::from(RoomMessageRequest::try_from((request_id, request))?)
}
OutgoingRequests::KeysBackup(request) => {
JsValue::from(KeysBackupRequest::try_from((request_id, request))?)
}
})
}
}
/// Represent the type of a request.
#[wasm_bindgen]
#[derive(Debug)]
pub enum RequestType {
/// Represents a `KeysUploadRequest`.
KeysUpload,
/// Represents a `KeysQueryRequest`.
KeysQuery,
/// Represents a `KeysClaimRequest`.
KeysClaim,
/// Represents a `ToDeviceRequest`.
ToDevice,
/// Represents a `SignatureUploadRequest`.
SignatureUpload,
/// Represents a `RoomMessageRequest`.
RoomMessage,
/// Represents a `KeysBackupRequest`.
KeysBackup,
}
@@ -0,0 +1,210 @@
//! Types related to responses.
use std::borrow::Borrow;
use js_sys::{Array, JsString};
use matrix_sdk_common::deserialized_responses::{AlgorithmInfo, EncryptionInfo};
use matrix_sdk_crypto::IncomingResponse;
pub(crate) use ruma::api::client::{
backup::add_backup_keys::v3::Response as KeysBackupResponse,
keys::{
claim_keys::v3::Response as KeysClaimResponse, get_keys::v3::Response as KeysQueryResponse,
upload_keys::v3::Response as KeysUploadResponse,
upload_signatures::v3::Response as SignatureUploadResponse,
},
message::send_message_event::v3::Response as RoomMessageResponse,
to_device::send_event_to_device::v3::Response as ToDeviceResponse,
};
use ruma::api::IncomingResponse as RumaIncomingResponse;
use wasm_bindgen::prelude::*;
use crate::{encryption, identifiers, requests::RequestType};
pub(crate) fn response_from_string(body: &str) -> http::Result<http::Response<Vec<u8>>> {
http::Response::builder().status(200).body(body.as_bytes().to_vec())
}
/// Intermediate private type to store an incoming owned response,
/// without the need to manage lifetime.
pub(crate) enum OwnedResponse {
KeysUpload(KeysUploadResponse),
KeysQuery(KeysQueryResponse),
KeysClaim(KeysClaimResponse),
ToDevice(ToDeviceResponse),
SignatureUpload(SignatureUploadResponse),
RoomMessage(RoomMessageResponse),
KeysBackup(KeysBackupResponse),
}
impl From<KeysUploadResponse> for OwnedResponse {
fn from(response: KeysUploadResponse) -> Self {
OwnedResponse::KeysUpload(response)
}
}
impl From<KeysQueryResponse> for OwnedResponse {
fn from(response: KeysQueryResponse) -> Self {
OwnedResponse::KeysQuery(response)
}
}
impl From<KeysClaimResponse> for OwnedResponse {
fn from(response: KeysClaimResponse) -> Self {
OwnedResponse::KeysClaim(response)
}
}
impl From<ToDeviceResponse> for OwnedResponse {
fn from(response: ToDeviceResponse) -> Self {
OwnedResponse::ToDevice(response)
}
}
impl From<SignatureUploadResponse> for OwnedResponse {
fn from(response: SignatureUploadResponse) -> Self {
Self::SignatureUpload(response)
}
}
impl From<RoomMessageResponse> for OwnedResponse {
fn from(response: RoomMessageResponse) -> Self {
OwnedResponse::RoomMessage(response)
}
}
impl From<KeysBackupResponse> for OwnedResponse {
fn from(r: KeysBackupResponse) -> Self {
Self::KeysBackup(r)
}
}
impl TryFrom<(RequestType, http::Response<Vec<u8>>)> for OwnedResponse {
type Error = JsError;
fn try_from(
(request_type, response): (RequestType, http::Response<Vec<u8>>),
) -> Result<Self, Self::Error> {
match request_type {
RequestType::KeysUpload => {
KeysUploadResponse::try_from_http_response(response).map(Into::into)
}
RequestType::KeysQuery => {
KeysQueryResponse::try_from_http_response(response).map(Into::into)
}
RequestType::KeysClaim => {
KeysClaimResponse::try_from_http_response(response).map(Into::into)
}
RequestType::ToDevice => {
ToDeviceResponse::try_from_http_response(response).map(Into::into)
}
RequestType::SignatureUpload => {
SignatureUploadResponse::try_from_http_response(response).map(Into::into)
}
RequestType::RoomMessage => {
RoomMessageResponse::try_from_http_response(response).map(Into::into)
}
RequestType::KeysBackup => {
KeysBackupResponse::try_from_http_response(response).map(Into::into)
}
}
.map_err(JsError::from)
}
}
impl<'a> From<&'a OwnedResponse> for IncomingResponse<'a> {
fn from(response: &'a OwnedResponse) -> Self {
match response {
OwnedResponse::KeysUpload(response) => IncomingResponse::KeysUpload(response),
OwnedResponse::KeysQuery(response) => IncomingResponse::KeysQuery(response),
OwnedResponse::KeysClaim(response) => IncomingResponse::KeysClaim(response),
OwnedResponse::ToDevice(response) => IncomingResponse::ToDevice(response),
OwnedResponse::SignatureUpload(response) => IncomingResponse::SignatureUpload(response),
OwnedResponse::RoomMessage(response) => IncomingResponse::RoomMessage(response),
OwnedResponse::KeysBackup(response) => IncomingResponse::KeysBackup(response),
}
}
}
/// A decrypted room event.
#[wasm_bindgen(getter_with_clone)]
#[derive(Debug)]
pub struct DecryptedRoomEvent {
/// The JSON-encoded decrypted event.
#[wasm_bindgen(readonly)]
pub event: JsString,
encryption_info: Option<EncryptionInfo>,
}
#[wasm_bindgen]
impl DecryptedRoomEvent {
/// The user ID of the event sender, note this is untrusted data
/// unless the `verification_state` is as well trusted.
#[wasm_bindgen(getter)]
pub fn sender(&self) -> Option<identifiers::UserId> {
Some(identifiers::UserId::from(self.encryption_info.as_ref()?.sender.clone()))
}
/// The device ID of the device that sent us the event, note this
/// is untrusted data unless `verification_state` is as well
/// trusted.
#[wasm_bindgen(getter, js_name = "senderDevice")]
pub fn sender_device(&self) -> Option<identifiers::DeviceId> {
Some(identifiers::DeviceId::from(self.encryption_info.as_ref()?.sender_device.clone()))
}
/// The Curve25519 key of the device that created the megolm
/// decryption key originally.
#[wasm_bindgen(getter, js_name = "senderCurve25519Key")]
pub fn sender_curve25519_key(&self) -> Option<JsString> {
Some(match &self.encryption_info.as_ref()?.algorithm_info {
AlgorithmInfo::MegolmV1AesSha2 { curve25519_key, .. } => curve25519_key.clone().into(),
})
}
/// The signing Ed25519 key that have created the megolm key that
/// was used to decrypt this session.
#[wasm_bindgen(getter, js_name = "senderClaimedEd25519Key")]
pub fn sender_claimed_ed25519_key(&self) -> Option<JsString> {
match &self.encryption_info.as_ref()?.algorithm_info {
AlgorithmInfo::MegolmV1AesSha2 { sender_claimed_keys, .. } => {
sender_claimed_keys.get(&ruma::DeviceKeyAlgorithm::Ed25519).cloned().map(Into::into)
}
}
}
/// Chain of Curve25519 keys through which this session was
/// forwarded, via `m.forwarded_room_key` events.
#[wasm_bindgen(getter, js_name = "forwardingCurve25519KeyChain")]
pub fn forwarding_curve25519_key_chain(&self) -> Option<Array> {
Some(match &self.encryption_info.as_ref()?.algorithm_info {
AlgorithmInfo::MegolmV1AesSha2 { forwarding_curve25519_key_chain, .. } => {
forwarding_curve25519_key_chain.iter().map(JsValue::from).collect()
}
})
}
/// The verification state of the device that sent us the event,
/// note this is the state of the device at the time of
/// decryption. It may change in the future if a device gets
/// verified or deleted.
#[wasm_bindgen(getter, js_name = "verificationState")]
pub fn verification_state(&self) -> Option<encryption::VerificationState> {
Some((self.encryption_info.as_ref()?.verification_state.borrow()).into())
}
}
impl From<matrix_sdk_common::deserialized_responses::RoomEvent> for DecryptedRoomEvent {
fn from(value: matrix_sdk_common::deserialized_responses::RoomEvent) -> Self {
Self {
event: value.event.json().get().to_owned().into(),
encryption_info: value.encryption_info,
}
}
}
@@ -0,0 +1,69 @@
//! `GET /_matrix/client/*/sync`
use js_sys::Array;
use wasm_bindgen::prelude::*;
use crate::{downcast, identifiers};
/// Information on E2E device updates.
#[wasm_bindgen]
#[derive(Debug)]
pub struct DeviceLists {
pub(crate) inner: ruma::api::client::sync::sync_events::v3::DeviceLists,
}
#[wasm_bindgen]
impl DeviceLists {
/// Create an empty `DeviceLists`.
///
/// `changed` and `left` must be an array of `UserId`.
#[wasm_bindgen(constructor)]
pub fn new(changed: Option<Array>, left: Option<Array>) -> Result<DeviceLists, JsError> {
let mut inner = ruma::api::client::sync::sync_events::v3::DeviceLists::default();
inner.changed = changed
.unwrap_or_default()
.iter()
.map(|user| Ok(downcast::<identifiers::UserId>(&user, "UserId")?.inner.clone()))
.collect::<Result<Vec<ruma::OwnedUserId>, JsError>>()?;
inner.left = left
.unwrap_or_default()
.iter()
.map(|user| Ok(downcast::<identifiers::UserId>(&user, "UserId")?.inner.clone()))
.collect::<Result<Vec<ruma::OwnedUserId>, JsError>>()?;
Ok(Self { inner })
}
/// Returns true if there are no device list updates.
#[wasm_bindgen(js_name = "isEmpty")]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
/// List of users who have updated their device identity keys or
/// who now share an encrypted room with the client since the
/// previous sync
#[wasm_bindgen(getter)]
pub fn changed(&self) -> Array {
self.inner
.changed
.iter()
.map(|user| identifiers::UserId::from(user.clone()))
.map(JsValue::from)
.collect()
}
/// List of users who no longer share encrypted rooms since the
/// previous sync response.
#[wasm_bindgen(getter)]
pub fn left(&self) -> Array {
self.inner
.left
.iter()
.map(|user| identifiers::UserId::from(user.clone()))
.map(JsValue::from)
.collect()
}
}
@@ -0,0 +1,36 @@
const { EncryptionAlgorithm, EncryptionSettings, HistoryVisibility, VerificationState } = require('../pkg/matrix_sdk_crypto');
describe('EncryptionAlgorithm', () => {
test('has the correct variant values', () => {
expect(EncryptionAlgorithm.OlmV1Curve25519AesSha2).toStrictEqual(0);
expect(EncryptionAlgorithm.MegolmV1AesSha2).toStrictEqual(1);
});
});
describe(EncryptionSettings.name, () => {
test('can be instantiated with default values', () => {
const es = new EncryptionSettings();
expect(es.algorithm).toStrictEqual(EncryptionAlgorithm.MegolmV1AesSha2);
expect(es.rotationPeriod).toStrictEqual(604800000000n);
expect(es.rotationPeriodMessages).toStrictEqual(100n);
expect(es.historyVisibility).toStrictEqual(HistoryVisibility.Shared);
});
test('checks the history visibility values', () => {
const es = new EncryptionSettings();
es.historyVisibility = HistoryVisibility.Invited;
expect(es.historyVisibility).toStrictEqual(HistoryVisibility.Invited);
expect(() => { es.historyVisibility = 42 }).toThrow();
});
});
describe('VerificationState', () => {
test('has the correct variant values', () => {
expect(VerificationState.Trusted).toStrictEqual(0);
expect(VerificationState.Untrusted).toStrictEqual(1);
expect(VerificationState.UnknownDevice).toStrictEqual(2);
});
});
@@ -0,0 +1,10 @@
const { HistoryVisibility } = require('../pkg/matrix_sdk_crypto');
describe('HistoryVisibility', () => {
test('has the correct variant values', () => {
expect(HistoryVisibility.Invited).toStrictEqual(0);
expect(HistoryVisibility.Joined).toStrictEqual(1);
expect(HistoryVisibility.Shared).toStrictEqual(2);
expect(HistoryVisibility.WorldReadable).toStrictEqual(3);
});
});
@@ -0,0 +1,72 @@
const { UserId, DeviceId, RoomId, ServerName } = require('../pkg/matrix_sdk_crypto');
describe(UserId.name, () => {
test('cannot be invalid', () => {
expect(() => { new UserId('@foobar') }).toThrow();
});
const user = new UserId('@foo:bar.org');
test('localpart is present', () => {
expect(user.localpart).toStrictEqual('foo');
});
test('server name is present', () => {
expect(user.serverName).toBeInstanceOf(ServerName);
});
test('user ID is not historical', () => {
expect(user.isHistorical()).toStrictEqual(false);
});
test('can read the user ID as a string', () => {
expect(user.toString()).toStrictEqual('@foo:bar.org');
})
});
describe(DeviceId.name, () => {
const device = new DeviceId('foo');
test('can read the device ID as a string', () => {
expect(device.toString()).toStrictEqual('foo');
})
});
describe(RoomId.name, () => {
test('cannot be invalid', () => {
expect(() => { new RoomId('!foo') }).toThrow();
});
const room = new RoomId('!foo:bar.org');
test('localpart is present', () => {
expect(room.localpart).toStrictEqual('foo');
});
test('server name is present', () => {
expect(room.serverName).toBeInstanceOf(ServerName);
});
test('can read the room ID as string', () => {
expect(room.toString()).toStrictEqual('!foo:bar.org');
});
});
describe(ServerName.name, () => {
test('cannot be invalid', () => {
expect(() => { new ServerName('@foobar') }).toThrow()
});
test('host is present', () => {
expect(new ServerName('foo.org').host).toStrictEqual('foo.org');
});
test('port can be optional', () => {
expect(new ServerName('foo.org').port).toStrictEqual(undefined);
expect(new ServerName('foo.org:1234').port).toStrictEqual(1234);
});
test('server is not an IP literal', () => {
expect(new ServerName('foo.org').isIpLiteral()).toStrictEqual(false);
});
});
@@ -0,0 +1,341 @@
const { OlmMachine, UserId, DeviceId, RoomId, DeviceLists, RequestType, KeysUploadRequest, KeysQueryRequest, KeysClaimRequest, EncryptionSettings, DecryptedRoomEvent, VerificationState } = require('../pkg/matrix_sdk_crypto');
describe(OlmMachine.name, () => {
test('can be instantiated with the async initializer', async () => {
expect(await new OlmMachine(new UserId('@foo:bar.org'), new DeviceId('baz'))).toBeInstanceOf(OlmMachine);
});
const user = new UserId('@alice:example.org');
const device = new DeviceId('foobar');
const room = new RoomId('!baz:matrix.org');
function machine(new_user, new_device) {
return new OlmMachine(new_user || user, new_device || device);
}
test('can read user ID', async () => {
expect((await machine()).userId.toString()).toStrictEqual(user.toString());
});
test('can read device ID', async () => {
expect((await machine()).deviceId.toString()).toStrictEqual(device.toString());
});
test('can read identity keys', async () => {
const identityKeys = (await machine()).identityKeys;
expect(identityKeys.ed25519.toBase64()).toMatch(/^[A-Za-z0-9+/]+$/);
expect(identityKeys.curve25519.toBase64()).toMatch(/^[A-Za-z0-9+/]+$/);
});
test('can read display name', async () => {
expect(await machine().displayName).toBeUndefined();
});
test('can read tracked users', async () => {
const trackedUsers = (await machine()).trackedUsers();
expect(trackedUsers).toBeInstanceOf(Set);
expect(trackedUsers.size).toStrictEqual(0);
});
test('can update tracked users', async () => {
const m = await machine();
expect(await m.updateTrackedUsers([user])).toStrictEqual(undefined);
});
test('can receive sync changes', async () => {
const m = await machine();
const toDeviceEvents = JSON.stringify({});
const changedDevices = new DeviceLists();
const oneTimeKeyCounts = new Map();
const unusedFallbackKeys = new Set();
const receiveSyncChanges = JSON.parse(await m.receiveSyncChanges(toDeviceEvents, changedDevices, oneTimeKeyCounts, unusedFallbackKeys));
expect(receiveSyncChanges).toEqual({});
});
test('can get the outgoing requests that need to be send out', async () => {
const m = await machine();
const toDeviceEvents = JSON.stringify({});
const changedDevices = new DeviceLists();
const oneTimeKeyCounts = new Map();
const unusedFallbackKeys = new Set();
const receiveSyncChanges = JSON.parse(await m.receiveSyncChanges(toDeviceEvents, changedDevices, oneTimeKeyCounts, unusedFallbackKeys));
expect(receiveSyncChanges).toEqual({});
const outgoingRequests = await m.outgoingRequests();
expect(outgoingRequests).toHaveLength(2);
{
expect(outgoingRequests[0]).toBeInstanceOf(KeysUploadRequest);
expect(outgoingRequests[0].id).toBeDefined();
expect(outgoingRequests[0].type).toStrictEqual(RequestType.KeysUpload);
const body = JSON.parse(outgoingRequests[0].body);
expect(body.device_keys).toBeDefined();
expect(body.one_time_keys).toBeDefined();
}
{
expect(outgoingRequests[1]).toBeInstanceOf(KeysQueryRequest);
expect(outgoingRequests[1].id).toBeDefined();
expect(outgoingRequests[1].type).toStrictEqual(RequestType.KeysQuery);
const body = JSON.parse(outgoingRequests[1].body);
expect(body.timeout).toBeDefined();
expect(body.device_keys).toBeDefined();
expect(body.token).toBeDefined();
}
});
describe('setup workflow to mark requests as sent', () => {
let m;
let ougoingRequests;
beforeAll(async () => {
m = await machine(new UserId('@alice:example.org'), new DeviceId('DEVICEID'));
const toDeviceEvents = JSON.stringify({});
const changedDevices = new DeviceLists();
const oneTimeKeyCounts = new Map();
const unusedFallbackKeys = new Set();
const receiveSyncChanges = await m.receiveSyncChanges(toDeviceEvents, changedDevices, oneTimeKeyCounts, unusedFallbackKeys);
outgoingRequests = await m.outgoingRequests();
expect(outgoingRequests).toHaveLength(2);
});
test('can mark requests as sent', async () => {
{
const request = outgoingRequests[0];
expect(request).toBeInstanceOf(KeysUploadRequest);
// https://spec.matrix.org/v1.2/client-server-api/#post_matrixclientv3keysupload
const hypothetical_response = JSON.stringify({
"one_time_key_counts": {
"curve25519": 10,
"signed_curve25519": 20
}
});
const marked = await m.markRequestAsSent(request.id, request.type, hypothetical_response);
expect(marked).toStrictEqual(true);
}
{
const request = outgoingRequests[1];
expect(request).toBeInstanceOf(KeysQueryRequest);
// https://spec.matrix.org/v1.2/client-server-api/#post_matrixclientv3keysquery
const hypothetical_response = JSON.stringify({
"device_keys": {
"@alice:example.org": {
"JLAFKJWSCS": {
"algorithms": [
"m.olm.v1.curve25519-aes-sha2",
"m.megolm.v1.aes-sha2"
],
"device_id": "JLAFKJWSCS",
"keys": {
"curve25519:JLAFKJWSCS": "wjLpTLRqbqBzLs63aYaEv2Boi6cFEbbM/sSRQ2oAKk4",
"ed25519:JLAFKJWSCS": "nE6W2fCblxDcOFmeEtCHNl8/l8bXcu7GKyAswA4r3mM"
},
"signatures": {
"@alice:example.org": {
"ed25519:JLAFKJWSCS": "m53Wkbh2HXkc3vFApZvCrfXcX3AI51GsDHustMhKwlv3TuOJMj4wistcOTM8q2+e/Ro7rWFUb9ZfnNbwptSUBA"
}
},
"unsigned": {
"device_display_name": "Alice's mobile phone"
},
"user_id": "@alice:example.org"
}
}
},
"failures": {}
});
const marked = await m.markRequestAsSent(request.id, request.type, hypothetical_response);
expect(marked).toStrictEqual(true);
}
});
});
describe('setup workflow to encrypt/decrypt events', () => {
let m;
const user = new UserId('@alice:example.org');
const device = new DeviceId('JLAFKJWSCS');
const room = new RoomId('!test:localhost');
beforeAll(async () => {
m = await machine(user, device);
});
test('can pass keysquery and keysclaim requests directly', async () => {
{
// derived from https://github.com/matrix-org/matrix-rust-sdk/blob/7f49618d350fab66b7e1dc4eaf64ec25ceafd658/benchmarks/benches/crypto_bench/keys_query.json
const hypothetical_response = JSON.stringify({
"device_keys": {
"@example:localhost": {
"AFGUOBTZWM": {
"algorithms": [
"m.olm.v1.curve25519-aes-sha2",
"m.megolm.v1.aes-sha2"
],
"device_id": "AFGUOBTZWM",
"keys": {
"curve25519:AFGUOBTZWM": "boYjDpaC+7NkECQEeMh5dC+I1+AfriX0VXG2UV7EUQo",
"ed25519:AFGUOBTZWM": "NayrMQ33ObqMRqz6R9GosmHdT6HQ6b/RX/3QlZ2yiec"
},
"signatures": {
"@example:localhost": {
"ed25519:AFGUOBTZWM": "RoSWvru1jj6fs2arnTedWsyIyBmKHMdOu7r9gDi0BZ61h9SbCK2zLXzuJ9ZFLao2VvA0yEd7CASCmDHDLYpXCA"
}
},
"user_id": "@example:localhost",
"unsigned": {
"device_display_name": "rust-sdk"
}
},
}
},
"failures": {},
"master_keys": {
"@example:localhost": {
"user_id": "@example:localhost",
"usage": [
"master"
],
"keys": {
"ed25519:n2lpJGx0LiKnuNE1IucZP3QExrD4SeRP0veBHPe3XUU": "n2lpJGx0LiKnuNE1IucZP3QExrD4SeRP0veBHPe3XUU"
},
"signatures": {
"@example:localhost": {
"ed25519:TCSJXPWGVS": "+j9G3L41I1fe0++wwusTTQvbboYW0yDtRWUEujhwZz4MAltjLSfJvY0hxhnz+wHHmuEXvQDen39XOpr1p29sAg"
}
}
}
},
"self_signing_keys": {
"@example:localhost": {
"user_id": "@example:localhost",
"usage": [
"self_signing"
],
"keys": {
"ed25519:kQXOuy639Yt47mvNTdrIluoC6DMvfbZLYbxAmwiDyhI": "kQXOuy639Yt47mvNTdrIluoC6DMvfbZLYbxAmwiDyhI"
},
"signatures": {
"@example:localhost": {
"ed25519:n2lpJGx0LiKnuNE1IucZP3QExrD4SeRP0veBHPe3XUU": "q32ifix/qyRpvmegw2BEJklwoBCAJldDNkcX+fp+lBA4Rpyqtycxge6BA4hcJdxYsy3oV0IHRuugS8rJMMFyAA"
}
}
}
},
"user_signing_keys": {
"@example:localhost": {
"user_id": "@example:localhost",
"usage": [
"user_signing"
],
"keys": {
"ed25519:g4ED07Fnqf3GzVWNN1pZ0IFrPQVdqQf+PYoJNH4eE0s": "g4ED07Fnqf3GzVWNN1pZ0IFrPQVdqQf+PYoJNH4eE0s"
},
"signatures": {
"@example:localhost": {
"ed25519:n2lpJGx0LiKnuNE1IucZP3QExrD4SeRP0veBHPe3XUU": "nKQu8alQKDefNbZz9luYPcNj+Z+ouQSot4fU/A23ELl1xrI06QVBku/SmDx0sIW1ytso0Cqwy1a+3PzCa1XABg"
}
}
}
}
});
const marked = await m.markRequestAsSent('foo', RequestType.KeysQuery, hypothetical_response);
}
{
// derived from https://github.com/matrix-org/matrix-rust-sdk/blob/7f49618d350fab66b7e1dc4eaf64ec25ceafd658/benchmarks/benches/crypto_bench/keys_claim.json
const hypothetical_response = JSON.stringify({
"one_time_keys": {
"@example:localhost": {
"AFGUOBTZWM": {
"signed_curve25519:AAAABQ": {
"key": "9IGouMnkB6c6HOd4xUsNv4i3Dulb4IS96TzDordzOws",
"signatures": {
"@example:localhost": {
"ed25519:AFGUOBTZWM": "2bvUbbmJegrV0eVP/vcJKuIWC3kud+V8+C0dZtg4dVovOSJdTP/iF36tQn2bh5+rb9xLlSeztXBdhy4c+LiOAg"
}
}
}
},
}
},
"failures": {}
});
const marked = await m.markRequestAsSent('bar', RequestType.KeysClaim, hypothetical_response);
}
});
test('can share a room key', async () => {
const other_users = [new UserId('@example:localhost')];
const requests = JSON.parse(await m.shareRoomKey(room, other_users, new EncryptionSettings()));
expect(requests).toHaveLength(1);
expect(requests[0].event_type).toBeDefined();
expect(requests[0].txn_id).toBeDefined();
expect(requests[0].messages).toBeDefined();
expect(requests[0].messages['@example:localhost']).toBeDefined();
});
let encrypted;
test('can encrypt an event', async () => {
encrypted = JSON.parse(await m.encryptRoomEvent(
room,
'm.room.message',
JSON.stringify({
"hello": "world"
}),
));
expect(encrypted.algorithm).toBeDefined();
expect(encrypted.ciphertext).toBeDefined();
expect(encrypted.sender_key).toBeDefined();
expect(encrypted.device_id).toStrictEqual(device.toString());
expect(encrypted.session_id).toBeDefined();
});
test('can decrypt an event', async () => {
const decrypted = await m.decryptRoomEvent(
JSON.stringify({
"type": "m.room.encrypted",
"event_id": "$xxxxx:example.org",
"origin_server_ts": Date.now(),
"sender": user.toString(),
content: encrypted,
unsigned: {
"age": 1234
}
}),
room,
);
expect(decrypted).toBeInstanceOf(DecryptedRoomEvent);
const event = JSON.parse(decrypted.event);
expect(event.content.hello).toStrictEqual("world");
expect(decrypted.sender.toString()).toStrictEqual(user.toString());
expect(decrypted.senderDevice.toString()).toStrictEqual(device.toString());
expect(decrypted.senderCurve25519Key).toBeDefined();
expect(decrypted.senderClaimedEd25519Key).toBeDefined();
expect(decrypted.forwardingCurve25519KeyChain).toHaveLength(0);
expect(decrypted.verificationState).toStrictEqual(VerificationState.Trusted);
});
});
});
@@ -0,0 +1,35 @@
const { RequestType, KeysUploadRequest, KeysQueryRequest, KeysClaimRequest, ToDeviceRequest, SignatureUploadRequest, RoomMessageRequest, KeysBackupRequest } = require('../pkg/matrix_sdk_crypto');
describe('RequestType', () => {
test('has the correct variant values', () => {
expect(RequestType.KeysUpload).toStrictEqual(0);
expect(RequestType.KeysQuery).toStrictEqual(1);
expect(RequestType.KeysClaim).toStrictEqual(2);
expect(RequestType.ToDevice).toStrictEqual(3);
expect(RequestType.SignatureUpload).toStrictEqual(4);
expect(RequestType.RoomMessage).toStrictEqual(5);
expect(RequestType.KeysBackup).toStrictEqual(6);
});
});
for (const [request, request_type] of [
[KeysUploadRequest, RequestType.KeysUpload],
[KeysQueryRequest, RequestType.KeysQuery],
[KeysClaimRequest, RequestType.KeysClaim],
[ToDeviceRequest, RequestType.ToDevice],
[SignatureUploadRequest, RequestType.SignatureUpload],
[RoomMessageRequest, RequestType.RoomMessage],
[KeysBackupRequest, RequestType.KeysBackup],
]) {
describe(request.name, () => {
test('can be instantiated', () => {
const r = new (request)('foo', '{"bar": "baz"}');
expect(r).toBeInstanceOf(request);
expect(r.id).toStrictEqual('foo');
expect(r.body).toStrictEqual('{"bar": "baz"}');
expect(r.type).toStrictEqual(request_type);
});
})
}
@@ -0,0 +1,31 @@
const { DeviceLists, UserId } = require('../pkg/matrix_sdk_crypto');
describe(DeviceLists.name, () => {
test('can be empty', () => {
const empty = new DeviceLists();
expect(empty.isEmpty()).toStrictEqual(true);
expect(empty.changed).toHaveLength(0);
expect(empty.left).toHaveLength(0);
});
test('can be coerced empty', () => {
const empty = new DeviceLists([], []);
expect(empty.isEmpty()).toStrictEqual(true);
expect(empty.changed).toHaveLength(0);
expect(empty.left).toHaveLength(0);
});
test('returns the correct `changed` and `left`', () => {
const list = new DeviceLists([new UserId('@foo:bar.org')], [new UserId('@baz:qux.org')]);
expect(list.isEmpty()).toStrictEqual(false);
expect(list.changed).toHaveLength(1);
expect(list.changed[0].toString()).toStrictEqual('@foo:bar.org');
expect(list.left).toHaveLength(1);
expect(list.left[0].toString()).toStrictEqual('@baz:qux.org');
});
});
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"strict": true
},
"typedocOptions": {
"entryPoints": ["pkg/matrix_sdk_crypto.d.ts"],
"out": "docs",
"readme": "README.md",
}
}
@@ -0,0 +1,7 @@
/node_modules
/package-lock.json
/index.js
/index.d.ts
/matrix-sdk-crypto.*.node
/docs/*
*.tgz
@@ -0,0 +1,8 @@
src/
tests/
Cargo.toml
build.rs
*.node
*.tgz
tsconfig.json
cliff.toml
@@ -0,0 +1,28 @@
# Matrix-Rust-SDK Node.js Bindings
## 0.1.0-beta.0 - 2022-07-21
Welcome to the first release of `matrix-sdk-crypto-nodejs`. This is a
Node.js binding for the Rust `matrix-sdk-crypto` library. This is a
no-network-IO implementation of a state machine, named `OlmMachine`,
that handles E2EE (End-to-End Encryption) for Matrix clients.
The goal of this binding is _not_ to cover the entirety of the
`matrix-sdk-crypto` API, but only what's required to build Matrix bots
or Matrix bridges (i.e. to connect different networks together via the
Matrix protocol).
This project replaces and deprecates a previous project, with the same
name and same goals, inside [the `matrix-rust-sdk-bindings`
repository](https://github.com/matrix-org/matrix-rust-sdk-bindings),
with the NPM package name `@turt2live/matrix-sdk-crypto-nodejs`. The
The new official package name is
`@matrix-org/matrix-sdk-crypto-nodejs`.
Note: All bindings are now part of [the `matrix-rust-sdk`
repository](https://github.com/matrix-org/matrix-rust-sdk) (see the
`bindings/` root directory).
[A documentation is available inside the new
`matrix-sdk-crypto-nodejs`
project](https://github.com/matrix-org/matrix-rust-sdk/tree/0bde5ccf38f8cda3865297a2d12ddcdaf4b80ca7/bindings/matrix-sdk-crypto-nodejs).
@@ -0,0 +1,41 @@
[package]
authors = ["Ivan Enderlin <ivane@element.io>"]
description = "Matrix encryption library, for NodeJS"
edition = "2021"
homepage = "https://github.com/matrix-org/matrix-rust-sdk"
keywords = ["matrix", "chat", "messaging", "ruma", "nio"]
license = "Apache-2.0"
name = "matrix-sdk-crypto-nodejs"
readme = "README.md"
repository = "https://github.com/matrix-org/matrix-rust-sdk"
rust-version = "1.60"
version = "0.5.0"
[package.metadata.docs.rs]
features = ["docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
[lib]
crate-type = ["cdylib"]
[features]
default = []
qrcode = ["matrix-sdk-crypto/qrcode"]
docsrs = []
tracing = ["tracing-subscriber"]
[dependencies]
matrix-sdk-crypto = { version = "0.5.0", path = "../../crates/matrix-sdk-crypto" }
matrix-sdk-common = { version = "0.5.0", path = "../../crates/matrix-sdk-common" }
matrix-sdk-sled = { version = "0.1.0", path = "../../crates/matrix-sdk-sled", default-features = false, features = ["crypto-store"] }
ruma = { git = "https://github.com/ruma/ruma", rev = "96155915f", features = ["client-api-c", "rand", "unstable-msc2676", "unstable-msc2677"] }
vodozemac = { git = "https://github.com/matrix-org/vodozemac/", rev = "2404f83f7d3a3779c1f518e4d949f7da9677c3dd" }
napi = { git = "https://github.com/Hywan/napi-rs", branch = "fix-napi-strict-on-t-and-ref-t", default-features = false, features = ["napi6", "tokio_rt"] }
napi-derive = { git = "https://github.com/Hywan/napi-rs", branch = "fix-napi-strict-on-t-and-ref-t" }
serde_json = "1.0.79"
http = "0.2.6"
zeroize = "1.3.0"
tracing-subscriber = { version = "0.3", default-features = false, features = ["tracing-log", "time", "smallvec", "fmt", "env-filter"], optional = true }
[build-dependencies]
napi-build = "2.0.0"
+204
View File
@@ -0,0 +1,204 @@
# `matrix-sdk-crypto-nodejs`
Welcome to the [Node.js] binding for the Rust [`matrix-sdk-crypto`]
library! This binding is part of the [`matrix-rust-sdk`] project,
which is a library implementation of a [Matrix] client-server.
`matrix-sdk-crypto-nodejs` is a no-network-IO implementation of a
state machine, named `OlmMachine`, that handles E2EE ([End-to-End
Encryption](https://en.wikipedia.org/wiki/End-to-end_encryption)) for
[Matrix] clients.
## Usage
Just add the latest release to your `package.json`:
```sh
$ npm install --save matrix-sdk-crypto
```
When installing, NPM will download the corresponding prebuilt Rust library for your current host system. The following are supported:
<table>
<thead>
<tr>
<th>Platform</th>
<th>Architecture</th>
<th>Triple</th>
<th>Prebuilt available</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="5">Linux</td>
<td rowspan="2"><code>aarch</code></td>
<td><code>aarch64-unknown-linux-gnu</code></td>
<td>✅</td>
</tr>
<tr>
<td><code>arm-unknown-linux-gnueabihf</code></td>
<td>✅</td>
</tr>
<tr>
<td rowspan="3"><code>amd</code></td>
<td><code>x86_64-unknown-linux-gnu</code></td>
<td>✅</td>
</tr>
<tr>
<td><code>x86_64-unknown-linux-musl</code></td>
<td>✅</td>
</tr>
<tr>
<td><code>i686-unknown-linux-gnu</code></td>
<td>✅</td>
</tr>
<tr>
<td rowspan="2">macOS</td>
<td><code>aarch</code></td>
<td><code>arch64-apple-darwin</code></td>
<td>✅</td>
</tr>
<tr>
<td><code>amd</code></td>
<td><code>x86_64-apple-darwin</code></td>
<td>✅</td>
</tr>
<tr>
<td rowspan="3">Windows</td>
<td><code>aarch</code></td>
<td><code>aarch64-pc-windows-msvc</code></td>
<td>✅</td>
</tr>
<tr>
<td rowspan="2"><code>amd</code></td>
<td><code>x86_64-pc-windows-msvc</code></td>
<td>✅</td>
</tr>
<tr>
<td><code>i686-pc-windows-msvc</code></td>
<td>✅</td>
</tr>
</tbody>
</table>
## Development
This Node.js binding is written in [Rust]. To build this binding, you
need to install the Rust compiler, see [the Install Rust
Page](https://www.rust-lang.org/tools/install). Then, the workflow is
pretty classical by using [npm], see [the Downloading and installing
Node.js and npm
Page](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm).
The binding is compatible with, and tested against, the Node.js
versions that are in “current”, “active” or “maintenance” states,
according to [the Node.js Releases
Page](https://nodejs.org/en/about/releases/), _and_ which are
compatible with [NAPI v6 (Node.js
API)](https://nodejs.org/api/n-api.html#node-api-version-matrix). It
means that this binding will work with the following versions: 14.0.0,
16.0.0 and 18.0.0.
Once the Rust compiler, Node.js and npm are installed, you can run the
following commands:
```sh
$ npm install --ignore-scripts
$ npm run build
$ npm run test
```
An `index.js`, `index.d.ts` and a `*.node` files should be
generated. At the same level of those files, you can edit a file and
try this:
```javascript
const { OlmMachine } = require('./index.js');
// Let's see what we can do.
```
The `OlmMachine` state machine works in a push/pull manner:
* You push state changes and events retrieved from a Matrix homeserver
`/sync` response, into the state machine,
* You pull requests that you will need to send back to the homeserver
out of the state machine.
```javascript
const { OlmMachine, UserId, DeviceId, RoomId, DeviceLists } = require('./index.js');
async function main() {
// Define a user ID.
const alice = new UserId('@alice:example.org');
// Define a device ID.
const device = new DeviceId('DEVICEID');
// Let's create the `OlmMachine` state machine.
const machine = await OlmMachine.initialize(alice, device);
// Let's pretend we have received changes and events from a
// `/sync` endpoint of a Matrix homeserver, …
const toDeviceEvents = "{}"; // JSON-encoded
const changedDevices = new DeviceLists();
const oneTimeKeyCounts = {};
const unusedFallbackKeys = [];
// … and push them into the state machine.
const decryptedToDevice = await machine.receiveSyncChanges(
toDeviceEvents,
changedDevices,
oneTimeKeyCounts,
unusedFallbackKeys,
);
// Now, let's pull requests that we need to send out to the Matrix
// homeserver.
const outgoingRequests = await machine.outgoingRequests();
// To complete the workflow, send the requests here out and call
// `machine.markRequestAsSent`.
}
main();
```
### With tracing (experimental)
If you want to enable [tracing](https://tracing.rs), i.e. to get the
logs, you should re-compile the extension with the `tracing` feature
turned on:
```sh
$ npm run build -- --features tracing
```
Now, you can use the `MATRIX_LOG` environment variable to tweak the log filtering, such as:
```sh
$ MATRIX_LOG=debug npm run test
```
See
[`tracing-subscriber`](https://tracing.rs/tracing_subscriber/index.html)
to learn more about the `RUST_LOG`/`MATRIX_LOG` environment variable.
## Documentation
To generate the documentation, please run the following command:
```sh
$ npm run doc
```
The documentation is generated in the `./docs` directory.
[Node.js]: https://nodejs.org/
[`matrix-sdk-crypto`]: https://github.com/matrix-org/matrix-rust-sdk/tree/main/crates/matrix-sdk-crypto
[`matrix-rust-sdk`]: https://github.com/matrix-org/matrix-rust-sdk
[Matrix]: https://matrix.org/
[Rust]: https://www.rust-lang.org/
[npm]: https://www.npmjs.com/
@@ -0,0 +1,3 @@
fn main() {
napi_build::setup();
}
@@ -0,0 +1,59 @@
# configuration file for git-cliff (0.1.0)
[changelog]
# changelog header
header = """
# Matrix SDK Crypto Node.js Changelog\n
All notable changes to this project will be documented in this file.\n
"""
# template for the changelog body
# https://tera.netlify.app/docs/#introduction
body = """
{% if version %}\
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
## [unreleased]
{% endif %}\
{% for group, commits in commits | filter(attribute="scope", value="crypto-nodejs") | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits %}
- {{ commit.id | truncate(length=7, end="") }}{% if commit.breaking %} [**breaking**] {% endif %}: {{ commit.message | upper_first }}\
{% endfor %}
{% endfor %}\n
"""
# remove the leading and trailing whitespace from the template
trim = true
# changelog footer
footer = """
"""
[git]
# parse the commits based on https://www.conventionalcommits.org
conventional_commits = true
# filter out the commits that are not conventional
filter_unconventional = true
# regex for preprocessing the commit messages
commit_preprocessors = [
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](https://github.com/matrix-org/matrix-rust-sdk/issues/${2}))"},
]
# regex for parsing and grouping commits
commit_parsers = [
{ message = "^feat", group = "Features"},
{ message = "^fix", group = "Bug Fixes"},
{ message = "^doc", group = "Documentation"},
{ message = "^perf", group = "Performance"},
{ message = "^test", group = "Testing"},
{ body = ".*security", group = "Security"},
]
# filter out the commits that are not matched by commit parsers
filter_commits = true
# glob pattern for matching git tags
tag_pattern = "v[0-9]*"
# regex for skipping tags
skip_tags = "v0.1.0-beta.1"
# regex for ignoring tags
ignore_tags = ""
# sort the tags chronologically
date_order = false
# sort the commits inside sections by oldest/newest order
sort_commits = "oldest"
@@ -0,0 +1,113 @@
const { DownloaderHelper } = require('node-downloader-helper');
const { version } = require("./package.json");
const { platform, arch } = process
const DOWNLOADS_BASE_URL = "https://github.com/matrix-org/matrix-rust-sdk/releases/download";
const CURRENT_VERSION = `matrix-sdk-crypto-nodejs-${version}`;
const byteHelper = function (value) {
if (value === 0) {
return '0 b';
}
const units = ['b', 'kB', 'MB', 'GB', 'TB'];
const number = Math.floor(Math.log(value) / Math.log(1024));
return (value / Math.pow(1024, Math.floor(number))).toFixed(1) + ' ' +
units[number];
};
function download_lib(libname) {
let startTime = new Date();
const url = `${DOWNLOADS_BASE_URL}/${CURRENT_VERSION}/${libname}`;
console.info(`Downloading lib ${libname} from ${url}`);
const dl = new DownloaderHelper(url, __dirname, {
override: true,
});
dl.on('end', () => console.info('Download Completed'));
dl.on('error', (err) => console.info('Download Failed', err));
dl.on('progress', stats => {
const progress = stats.progress.toFixed(1);
const speed = byteHelper(stats.speed);
const downloaded = byteHelper(stats.downloaded);
const total = byteHelper(stats.total);
// print every one second (`progress.throttled` can be used instead)
const currentTime = new Date();
const elaspsedTime = currentTime - startTime;
if (elaspsedTime > 1000) {
startTime = currentTime;
console.info(`${speed}/s - ${progress}% [${downloaded}/${total}]`);
}
});
dl.start().catch(err => console.error(err));
}
function isMusl() {
// For Node 10
if (!process.report || typeof process.report.getReport !== 'function') {
try {
return readFileSync('/usr/bin/ldd', 'utf8').includes('musl')
} catch (e) {
return true
}
} else {
const { glibcVersionRuntime } = process.report.getReport().header
return !glibcVersionRuntime
}
}
switch (platform) {
case 'win32':
switch (arch) {
case 'x64':
download_lib('matrix-sdk-crypto.win32-x64-msvc.node')
break
case 'ia32':
download_lib('matrix-sdk-crypto.win32-ia32-msvc.node')
break
case 'arm64':
download_lib('matrix-sdk-crypto.win32-arm64-msvc.node')
break
default:
throw new Error(`Unsupported architecture on Windows: ${arch}`)
}
break
case 'darwin':
switch (arch) {
case 'x64':
download_lib('matrix-sdk-crypto.darwin-x64.node')
break
case 'arm64':
download_lib('matrix-sdk-crypto.darwin-arm64.node')
break
default:
throw new Error(`Unsupported architecture on macOS: ${arch}`)
}
break
case 'linux':
switch (arch) {
case 'x64':
if (isMusl()) {
download_lib('matrix-sdk-crypto.linux-x64-musl.node')
} else {
download_lib('matrix-sdk-crypto.linux-x64-gnu.node')
}
break
case 'arm64':
if (isMusl()) {
throw new Error('Linux for arm64 musl isn\'t support at the moment')
} else {
download_lib('matrix-sdk-crypto.linux-arm64-gnu.node')
}
break
case 'arm':
download_lib('matrix-sdk-crypto.linux-arm-gnueabihf.node')
break
default:
throw new Error(`Unsupported architecture on Linux: ${arch}`)
}
break
default:
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
}
@@ -0,0 +1,33 @@
{
"name": "@matrix-org/matrix-sdk-crypto-nodejs",
"version": "0.1.0-beta.0",
"main": "index.js",
"types": "index.d.ts",
"napi": {
"name": "matrix-sdk-crypto",
"triples": {
"additional": [
"aarch64-apple-darwin"
]
}
},
"license": "Apache-2.0",
"devDependencies": {
"@napi-rs/cli": "^2.9.0",
"jest": "^28.1.0",
"typedoc": "^0.22.17"
},
"engines": {
"node": ">= 14"
},
"scripts": {
"release-build": "napi build --platform --release --strip",
"build": "napi build --platform",
"postinstall": "node download-lib.js",
"test": "jest --verbose --testTimeout 10000",
"doc": "typedoc --tsconfig ."
},
"dependencies": {
"node-downloader-helper": "^2.1.1"
}
}
@@ -0,0 +1,126 @@
use std::{
io::{Cursor, Read},
ops::Deref,
};
use napi::bindgen_prelude::Uint8Array;
use napi_derive::*;
use crate::into_err;
/// A type to encrypt and to decrypt anything that can fit in an
/// `Uint8Array`, usually big buffer.
#[napi]
pub struct Attachment;
#[napi]
impl Attachment {
/// Encrypt the content of the `Uint8Array`.
///
/// It produces an `EncryptedAttachment`, we can be used to
/// retrieve the media encryption information, or the encrypted
/// data.
#[napi]
pub fn encrypt(array: Uint8Array) -> napi::Result<EncryptedAttachment> {
let buffer: &[u8] = array.deref();
let mut cursor = Cursor::new(buffer);
let mut encryptor = matrix_sdk_crypto::AttachmentEncryptor::new(&mut cursor);
let mut encrypted_data = Vec::new();
encryptor.read_to_end(&mut encrypted_data).map_err(into_err)?;
let media_encryption_info = Some(encryptor.finish());
Ok(EncryptedAttachment {
encrypted_data: Uint8Array::new(encrypted_data),
media_encryption_info,
})
}
/// Decrypt an `EncryptedAttachment`.
///
/// The encrypted attachment can be created manually, or from the
/// `encrypt` method.
///
/// **Warning**: The encrypted attachment can be used only
/// **once**! The encrypted data will still be present, but the
/// media encryption info (which contain secrets) will be
/// destroyed. It is still possible to get a JSON-encoded backup
/// by calling `EncryptedAttachment.mediaEncryptionInfo`.
#[napi]
pub fn decrypt(attachment: &mut EncryptedAttachment) -> napi::Result<Uint8Array> {
let media_encryption_info = match attachment.media_encryption_info.take() {
Some(media_encryption_info) => media_encryption_info,
None => {
return Err(napi::Error::from_reason(
"The media encryption info are absent from the given encrypted attachment"
.to_string(),
))
}
};
let encrypted_data: &[u8] = attachment.encrypted_data.deref();
let mut cursor = Cursor::new(encrypted_data);
let mut decryptor =
matrix_sdk_crypto::AttachmentDecryptor::new(&mut cursor, media_encryption_info)
.map_err(into_err)?;
let mut decrypted_data = Vec::new();
decryptor.read_to_end(&mut decrypted_data).map_err(into_err)?;
Ok(Uint8Array::new(decrypted_data))
}
}
/// An encrypted attachment, usually created from `Attachment.encrypt`.
#[napi]
pub struct EncryptedAttachment {
media_encryption_info: Option<matrix_sdk_crypto::MediaEncryptionInfo>,
/// The actual encrypted data.
pub encrypted_data: Uint8Array,
}
#[napi]
impl EncryptedAttachment {
/// Create a new encrypted attachment manually.
///
/// It needs encrypted data, stored in an `Uint8Array`, and a
/// [media encryption
/// information](https://docs.rs/matrix-sdk-crypto/latest/matrix_sdk_crypto/struct.MediaEncryptionInfo.html),
/// as a JSON-encoded string.
///
/// The media encryption information aren't stored as a string:
/// they are parsed, validated and fully deserialized.
///
/// See [the specification to learn
/// more](https://spec.matrix.org/unstable/client-server-api/#extensions-to-mroommessage-msgtypes).
#[napi(constructor)]
pub fn new(encrypted_data: Uint8Array, media_encryption_info: String) -> napi::Result<Self> {
Ok(Self {
encrypted_data,
media_encryption_info: Some(
serde_json::from_str(media_encryption_info.as_str()).map_err(into_err)?,
),
})
}
/// Return the media encryption info as a JSON-encoded string. The
/// structure is fully valid.
///
/// If the media encryption info have been consumed already, it
/// will return `null`.
#[napi(getter)]
pub fn media_encryption_info(&self) -> Option<String> {
serde_json::to_string(self.media_encryption_info.as_ref()?).ok()
}
/// Check whether the media encryption info has been consumed by
/// `Attachment.decrypt` already.
#[napi(getter)]
pub fn has_media_encryption_info_been_consumed(&self) -> bool {
self.media_encryption_info.is_none()
}
}
@@ -0,0 +1,127 @@
use std::time::Duration;
use napi::bindgen_prelude::{BigInt, ToNapiValue};
use napi_derive::*;
use crate::events;
/// An encryption algorithm to be used to encrypt messages sent to a
/// room.
#[napi]
pub enum EncryptionAlgorithm {
/// Olm version 1 using Curve25519, AES-256, and SHA-256.
OlmV1Curve25519AesSha2,
/// Megolm version 1 using AES-256 and SHA-256.
MegolmV1AesSha2,
}
impl From<EncryptionAlgorithm> for ruma::EventEncryptionAlgorithm {
fn from(value: EncryptionAlgorithm) -> Self {
use EncryptionAlgorithm::*;
match value {
OlmV1Curve25519AesSha2 => Self::OlmV1Curve25519AesSha2,
MegolmV1AesSha2 => Self::MegolmV1AesSha2,
}
}
}
impl From<ruma::EventEncryptionAlgorithm> for EncryptionAlgorithm {
fn from(value: ruma::EventEncryptionAlgorithm) -> Self {
use ruma::EventEncryptionAlgorithm::*;
match value {
OlmV1Curve25519AesSha2 => Self::OlmV1Curve25519AesSha2,
MegolmV1AesSha2 => Self::MegolmV1AesSha2,
_ => unreachable!("Unknown variant"),
}
}
}
/// Settings for an encrypted room.
///
/// This determines the algorithm and rotation periods of a group
/// session.
#[napi]
pub struct EncryptionSettings {
/// The encryption algorithm that should be used in the room.
pub algorithm: EncryptionAlgorithm,
/// How long the session should be used before changing it,
/// expressed in microseconds.
pub rotation_period: BigInt,
/// How many messages should be sent before changing the session.
pub rotation_period_messages: BigInt,
/// The history visibility of the room when the session was
/// created.
pub history_visibility: events::HistoryVisibility,
}
impl Default for EncryptionSettings {
fn default() -> Self {
let default = matrix_sdk_crypto::olm::EncryptionSettings::default();
Self {
algorithm: default.algorithm.into(),
rotation_period: {
let n: u64 = default.rotation_period.as_micros().try_into().unwrap();
n.into()
},
rotation_period_messages: {
let n = default.rotation_period_msgs;
n.into()
},
history_visibility: default.history_visibility.into(),
}
}
}
#[napi]
impl EncryptionSettings {
/// Create a new `EncryptionSettings` with default values.
#[napi(constructor)]
pub fn new() -> EncryptionSettings {
Self::default()
}
}
impl From<&EncryptionSettings> for matrix_sdk_crypto::olm::EncryptionSettings {
fn from(value: &EncryptionSettings) -> Self {
Self {
algorithm: value.algorithm.into(),
rotation_period: Duration::from_micros(value.rotation_period.get_u64().1),
rotation_period_msgs: value.rotation_period_messages.get_u64().1,
history_visibility: value.history_visibility.into(),
}
}
}
/// The verification state of the device that sent an event to us.
#[napi]
pub enum VerificationState {
/// The device is trusted.
Trusted,
/// The device is not trusted.
Untrusted,
/// The device is not known to us.
UnknownDevice,
}
impl From<&matrix_sdk_common::deserialized_responses::VerificationState> for VerificationState {
fn from(value: &matrix_sdk_common::deserialized_responses::VerificationState) -> Self {
use matrix_sdk_common::deserialized_responses::VerificationState::*;
match value {
Trusted => Self::Trusted,
Untrusted => Self::Untrusted,
UnknownDevice => Self::UnknownDevice,
}
}
}
@@ -0,0 +1,28 @@
/// Generic error wrapping `napi::Error`.
#[derive(Debug)]
pub struct Error(napi::Error);
impl<E> From<E> for Error
where
E: std::error::Error,
{
fn from(error: E) -> Self {
Self(napi::Error::from_reason(error.to_string()))
}
}
impl From<Error> for napi::Error {
#[inline]
fn from(value: Error) -> Self {
value.0
}
}
/// Helper to replace the `E` to `Error` to `napi::Error` conversion.
#[inline]
pub fn into_err<E>(error: E) -> napi::Error
where
E: std::error::Error,
{
Error::from(error).into()
}
@@ -0,0 +1,62 @@
//! Types related to events.
use napi::bindgen_prelude::ToNapiValue;
use napi_derive::*;
use ruma::events::room::history_visibility::HistoryVisibility as RumaHistoryVisibility;
/// Who can see a room's history.
#[napi]
#[derive(Debug)]
pub enum HistoryVisibility {
/// Previous events are accessible to newly joined members from
/// the point they were invited onwards.
///
/// Events stop being accessible when the member's state changes
/// to something other than *invite* or *join*.
Invited,
/// Previous events are accessible to newly joined members from
/// the point they joined the room onwards.
///
/// Events stop being accessible when the member's state changes
/// to something other than *join*.
Joined,
/// Previous events are always accessible to newly joined members.
///
/// All events in the room are accessible, even those sent when
/// the member was not a part of the room.
Shared,
/// All events while this is the `HistoryVisibility` value may be
/// shared by any participating homeserver with anyone, regardless
/// of whether they have ever joined the room.
WorldReadable,
}
impl From<HistoryVisibility> for RumaHistoryVisibility {
fn from(value: HistoryVisibility) -> Self {
use HistoryVisibility::*;
match value {
Invited => Self::Invited,
Joined => Self::Joined,
Shared => Self::Shared,
WorldReadable => Self::WorldReadable,
}
}
}
impl From<RumaHistoryVisibility> for HistoryVisibility {
fn from(value: RumaHistoryVisibility) -> Self {
use RumaHistoryVisibility::*;
match value {
Invited => Self::Invited,
Joined => Self::Joined,
Shared => Self::Shared,
WorldReadable => Self::WorldReadable,
_ => unreachable!("Unknown variant"),
}
}
}
@@ -0,0 +1,281 @@
//! Types for [Matrix](https://matrix.org/) identifiers for devices,
//! events, keys, rooms, servers, users and URIs.
use napi::bindgen_prelude::ToNapiValue;
use napi_derive::*;
use crate::into_err;
/// A Matrix [user ID].
///
/// [user ID]: https://spec.matrix.org/v1.2/appendices/#user-identifiers
#[napi]
#[derive(Debug, Clone)]
pub struct UserId {
pub(crate) inner: ruma::OwnedUserId,
}
impl From<ruma::OwnedUserId> for UserId {
fn from(inner: ruma::OwnedUserId) -> Self {
Self { inner }
}
}
#[napi]
impl UserId {
/// Parse/validate and create a new `UserId`.
#[napi(constructor, strict)]
pub fn new(id: String) -> napi::Result<Self> {
Ok(Self::from(ruma::UserId::parse(id.as_str()).map_err(into_err)?))
}
/// Returns the user's localpart.
#[napi(getter)]
pub fn localpart(&self) -> String {
self.inner.localpart().to_owned()
}
/// Returns the server name of the user ID.
#[napi(getter)]
pub fn server_name(&self) -> ServerName {
ServerName { inner: self.inner.server_name().to_owned() }
}
/// Whether this user ID is a historical one.
///
/// A historical user ID is one that doesn't conform to the latest
/// specification of the user ID grammar but is still accepted
/// because it was previously allowed.
#[napi]
pub fn is_historical(&self) -> bool {
self.inner.is_historical()
}
/// Return the user ID as a string.
#[napi]
#[allow(clippy::inherent_to_string)]
pub fn to_string(&self) -> String {
self.inner.as_str().to_owned()
}
}
/// A Matrix device ID.
///
/// Device identifiers in Matrix are completely opaque character
/// sequences. This type is provided simply for its semantic value.
#[napi]
#[derive(Debug, Clone)]
pub struct DeviceId {
pub(crate) inner: ruma::OwnedDeviceId,
}
impl From<ruma::OwnedDeviceId> for DeviceId {
fn from(inner: ruma::OwnedDeviceId) -> Self {
Self { inner }
}
}
#[napi]
impl DeviceId {
/// Create a new `DeviceId`.
#[napi(constructor, strict)]
pub fn new(id: String) -> Self {
Self::from(Into::<ruma::OwnedDeviceId>::into(id))
}
/// Return the device ID as a string.
#[napi]
#[allow(clippy::inherent_to_string)]
pub fn to_string(&self) -> String {
self.inner.as_str().to_owned()
}
}
/// A Matrix device key ID.
///
/// A key algorithm and a device ID, combined with a :.
#[napi]
#[derive(Debug, Clone)]
pub struct DeviceKeyId {
pub(crate) inner: ruma::OwnedDeviceKeyId,
}
impl From<ruma::OwnedDeviceKeyId> for DeviceKeyId {
fn from(inner: ruma::OwnedDeviceKeyId) -> Self {
Self { inner }
}
}
#[napi]
impl DeviceKeyId {
/// Parse/validate and create a new `DeviceKeyId`.
#[napi(constructor, strict)]
pub fn new(id: String) -> napi::Result<Self> {
Ok(Self::from(ruma::DeviceKeyId::parse(id.as_str()).map_err(into_err)?))
}
/// Returns key algorithm of the device key ID.
#[napi(getter)]
pub fn algorithm(&self) -> DeviceKeyAlgorithm {
self.inner.algorithm().into()
}
/// Returns device ID of the device key ID.
#[napi(getter)]
pub fn device_id(&self) -> DeviceId {
self.inner.device_id().to_owned().into()
}
/// Return the device key ID as a string.
#[napi]
#[allow(clippy::inherent_to_string)]
pub fn to_string(&self) -> String {
self.inner.to_string()
}
}
/// The basic key algorithms in the specification.
#[napi]
pub struct DeviceKeyAlgorithm {
inner: ruma::DeviceKeyAlgorithm,
}
impl From<ruma::DeviceKeyAlgorithm> for DeviceKeyAlgorithm {
fn from(inner: ruma::DeviceKeyAlgorithm) -> Self {
Self { inner }
}
}
#[napi]
impl DeviceKeyAlgorithm {
/// Read the device key algorithm's name. If the name is
/// `Unknown`, one may be interested by the `to_string` method to
/// read the original name.
#[napi(getter)]
pub fn name(&self) -> DeviceKeyAlgorithmName {
self.inner.clone().into()
}
/// Return the device key algorithm as a string.
#[napi]
#[allow(clippy::inherent_to_string)]
pub fn to_string(&self) -> String {
self.inner.to_string()
}
}
/// The basic key algorithm names in the specification.
#[napi]
pub enum DeviceKeyAlgorithmName {
/// The Ed25519 signature algorithm.
Ed25519,
/// The Curve25519 ECDH algorithm.
Curve25519,
/// The Curve25519 ECDH algorithm, but the key also contains
/// signatures.
SignedCurve25519,
/// An unknown device key algorithm.
Unknown,
}
impl From<ruma::DeviceKeyAlgorithm> for DeviceKeyAlgorithmName {
fn from(value: ruma::DeviceKeyAlgorithm) -> Self {
use ruma::DeviceKeyAlgorithm::*;
match value {
Ed25519 => Self::Ed25519,
Curve25519 => Self::Curve25519,
SignedCurve25519 => Self::SignedCurve25519,
_ => Self::Unknown,
}
}
}
/// A Matrix [room ID].
///
/// [room ID]: https://spec.matrix.org/v1.2/appendices/#room-ids-and-event-ids
#[napi]
#[derive(Debug, Clone)]
pub struct RoomId {
pub(crate) inner: ruma::OwnedRoomId,
}
impl From<ruma::OwnedRoomId> for RoomId {
fn from(inner: ruma::OwnedRoomId) -> Self {
Self { inner }
}
}
#[napi]
impl RoomId {
/// Parse/validate and create a new `RoomId`.
#[napi(constructor, strict)]
pub fn new(id: String) -> napi::Result<Self> {
Ok(Self::from(ruma::RoomId::parse(id).map_err(into_err)?))
}
/// Returns the user's localpart.
#[napi(getter)]
pub fn localpart(&self) -> String {
self.inner.localpart().to_owned()
}
/// Returns the server name of the room ID.
#[napi(getter)]
pub fn server_name(&self) -> ServerName {
ServerName { inner: self.inner.server_name().to_owned() }
}
/// Return the room ID as a string.
#[napi]
#[allow(clippy::inherent_to_string)]
pub fn to_string(&self) -> String {
self.inner.as_str().to_owned()
}
}
/// A Matrix-spec compliant [server name].
///
/// It consists of a host and an optional port (separated by a colon if
/// present).
///
/// [server name]: https://spec.matrix.org/v1.2/appendices/#server-name
#[napi]
#[derive(Debug)]
pub struct ServerName {
inner: ruma::OwnedServerName,
}
#[napi]
impl ServerName {
/// Parse/validate and create a new `ServerName`.
#[napi(constructor, strict)]
pub fn new(name: String) -> napi::Result<Self> {
Ok(Self { inner: ruma::ServerName::parse(name).map_err(into_err)? })
}
/// Returns the host of the server name.
///
/// That is: Return the part of the server before `:<port>` or the
/// full server name if there is no port.
#[napi(getter)]
pub fn host(&self) -> String {
self.inner.host().to_owned()
}
/// Returns the port of the server name if any.
#[napi(getter)]
pub fn port(&self) -> Option<u16> {
self.inner.port()
}
/// Returns true if and only if the server name is an IPv4 or IPv6
/// address.
#[napi]
pub fn is_ip_literal(&self) -> bool {
self.inner.is_ip_literal()
}
}
@@ -0,0 +1,34 @@
// Copyright 2022 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.
#![doc = include_str!("../README.md")]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
//#![warn(missing_docs, missing_debug_implementations)]
pub mod attachment;
pub mod encryption;
mod errors;
pub mod events;
pub mod identifiers;
pub mod machine;
pub mod olm;
pub mod requests;
pub mod responses;
pub mod sync_events;
#[cfg(feature = "tracing")]
pub mod tracing;
pub mod types;
pub mod vodozemac;
use crate::errors::into_err;
@@ -0,0 +1,416 @@
//! The crypto specific Olm objects.
use std::{
collections::{BTreeMap, HashMap},
sync::Arc,
};
use napi::bindgen_prelude::Either7;
use napi_derive::*;
use ruma::{
events::room::encrypted::OriginalSyncRoomEncryptedEvent, DeviceKeyAlgorithm,
OwnedTransactionId, UInt,
};
use serde_json::Value as JsonValue;
use zeroize::Zeroize;
use crate::{
encryption, identifiers, into_err, olm, requests, responses, responses::response_from_string,
sync_events, types, vodozemac,
};
/// State machine implementation of the Olm/Megolm encryption protocol
/// used for Matrix end to end encryption.
#[napi]
pub struct OlmMachine {
inner: matrix_sdk_crypto::OlmMachine,
}
#[napi]
impl OlmMachine {
// JavaScript doesn't support asynchronous constructor. So let's
// use a factory pattern, where the constructor cannot be used (it
// returns an error), and a new method is provided to construct
// the object. napi provides `#[napi(factory)]` to address those
// needs automatically. Unfortunately, it doesn't support
// asynchronous factory methods.
//
// So let's do this manually. The `initialize` async method _is_
// the factory function. We also manually implement the
// constructor to raise an error when called.
/// Create a new memory-based `OlmMachine` asynchronously.
///
/// The persistence of the encryption keys and all the inner
/// objects are controlled by the `store_path` argument.
///
/// # Arguments
///
/// * `user_id`, the unique ID of the user that owns this machine.
/// * `device_id`, the unique id of the device that owns this machine.
/// * `store_path`, the path to a directory where the state of the machine
/// should be persisted; if not set, the created machine will keep the
/// encryption keys only in memory, and once the object is dropped, the
/// keys will be lost.
/// * `store_passphrase`, the passphrase that should be used to encrypt the
/// data at rest in the store. **Warning**, if no passphrase is given, the
/// store and all its data will remain unencrypted. This argument is
/// ignored if `store_path` is not set.
#[napi(strict)]
pub async fn initialize(
user_id: &identifiers::UserId,
device_id: &identifiers::DeviceId,
store_path: Option<String>,
mut store_passphrase: Option<String>,
) -> napi::Result<OlmMachine> {
let user_id = user_id.clone();
let device_id = device_id.clone();
let store = store_path
.map(|store_path| {
matrix_sdk_sled::CryptoStore::open_with_passphrase(
store_path,
store_passphrase.as_deref(),
)
.map(Arc::new)
.map_err(into_err)
})
.transpose()?;
store_passphrase.zeroize();
Ok(OlmMachine {
inner: match store {
Some(store) => matrix_sdk_crypto::OlmMachine::with_store(
user_id.inner.as_ref(),
device_id.inner.as_ref(),
store,
)
.await
.map_err(into_err)?,
None => {
matrix_sdk_crypto::OlmMachine::new(
user_id.inner.as_ref(),
device_id.inner.as_ref(),
)
.await
}
},
})
}
/// It's not possible to construct an `OlmMachine` with its
/// constructor because building an `OlmMachine` is
/// asynchronous. Please use the `finalize` method.
#[napi(constructor)]
#[allow(clippy::new_ret_no_self)]
pub fn new() -> napi::Result<()> {
Err(napi::Error::from_reason(
"To build an `OldMachine`, please use the `initialize` method",
))
}
/// The unique user ID that owns this `OlmMachine` instance.
#[napi(getter)]
pub fn user_id(&self) -> identifiers::UserId {
identifiers::UserId::from(self.inner.user_id().to_owned())
}
/// The unique device ID that identifies this `OlmMachine`.
#[napi(getter)]
pub fn device_id(&self) -> identifiers::DeviceId {
identifiers::DeviceId::from(self.inner.device_id().to_owned())
}
/// Get the public parts of our Olm identity keys.
#[napi(getter)]
pub fn identity_keys(&self) -> vodozemac::IdentityKeys {
self.inner.identity_keys().into()
}
/// Handle a to-device and one-time key counts from a sync response.
///
/// This will decrypt and handle to-device events returning the
/// decrypted versions of them, as a JSON-encoded string.
///
/// To decrypt an event from the room timeline, please use
/// `decrypt_room_event`.
///
/// # Arguments
///
/// * `to_device_events`, thhe to-device events of the current sync
/// response.
/// * `changed_devices`, the list of devices that changed in this sync
/// response.
/// * `one_time_keys_count`, the current one-time keys counts that the sync
/// response returned.
#[napi(strict)]
pub async fn receive_sync_changes(
&self,
to_device_events: String,
changed_devices: &sync_events::DeviceLists,
one_time_key_counts: HashMap<String, u32>,
unused_fallback_keys: Vec<String>,
) -> napi::Result<String> {
let to_device_events = serde_json::from_str(to_device_events.as_ref()).map_err(into_err)?;
let changed_devices = changed_devices.inner.clone();
let one_time_key_counts = one_time_key_counts
.iter()
.map(|(key, value)| (DeviceKeyAlgorithm::from(key.as_str()), UInt::from(*value)))
.collect::<BTreeMap<_, _>>();
let unused_fallback_keys = Some(
unused_fallback_keys
.into_iter()
.map(|key| DeviceKeyAlgorithm::from(key.as_str()))
.collect::<Vec<_>>(),
);
serde_json::to_string(
&self
.inner
.receive_sync_changes(
to_device_events,
&changed_devices,
&one_time_key_counts,
unused_fallback_keys.as_deref(),
)
.await
.map_err(into_err)?,
)
.map_err(into_err)
}
/// Get the outgoing requests that need to be sent out.
///
/// This returns a list of `KeysUploadRequest`, or
/// `KeysQueryRequest`, or `KeysClaimRequest`, or
/// `ToDeviceRequest`, or `SignatureUploadRequest`, or
/// `RoomMessageRequest`, or `KeysBackupRequest`. Those requests
/// need to be sent out to the server and the responses need to be
/// passed back to the state machine using `mark_request_as_sent`.
#[napi]
pub async fn outgoing_requests(
&self,
) -> napi::Result<
Vec<
// We could be tempted to use `requests::OutgoingRequests` as its
// a type alias for this giant `Either7`. But `napi` won't unfold
// it properly into a valid TypeScript definition, so… let's
// copy-paste :-(.
Either7<
requests::KeysUploadRequest,
requests::KeysQueryRequest,
requests::KeysClaimRequest,
requests::ToDeviceRequest,
requests::SignatureUploadRequest,
requests::RoomMessageRequest,
requests::KeysBackupRequest,
>,
>,
> {
self.inner
.outgoing_requests()
.await
.map_err(into_err)?
.into_iter()
.map(requests::OutgoingRequest)
.map(TryFrom::try_from)
.collect()
}
/// Mark the request with the given request ID as sent.
///
/// # Arguments
///
/// * `request_id`, the unique ID of the request that was sent out. This is
/// needed to couple the response with the now sent out request.
/// * `request_type`, the request type associated to the request ID.
/// * `response`, the response that was received from the server after the
/// outgoing request was sent out.
#[napi(strict)]
pub async fn mark_request_as_sent(
&self,
request_id: String,
request_type: requests::RequestType,
response: String,
) -> napi::Result<bool> {
let transaction_id = OwnedTransactionId::from(request_id);
let response = response_from_string(response.as_str()).map_err(into_err)?;
let incoming_response = responses::OwnedResponse::try_from((request_type, response))?;
self.inner
.mark_request_as_sent(&transaction_id, &incoming_response)
.await
.map(|_| true)
.map_err(into_err)
}
/// Get the a key claiming request for the user/device pairs that
/// we are missing Olm sessions for.
///
/// Returns `null` if no key claiming request needs to be sent
/// out.
///
/// Sessions need to be established between devices so group
/// sessions for a room can be shared with them.
///
/// This should be called every time a group session needs to be
/// shared as well as between sync calls. After a sync some
/// devices may request room keys without us having a valid Olm
/// session with them, making it impossible to server the room key
/// request, thus its necessary to check for missing sessions
/// between sync as well.
///
/// Note: Care should be taken that only one such request at a
/// time is in flight, e.g. using a lock.
///
/// The response of a successful key claiming requests needs to be
/// passed to the `OlmMachine` with the `mark_request_as_sent`.
///
/// # Arguments
///
/// * `users`, the list of users that we should check if we lack a session
/// with one of their devices. This can be an empty array or `null` when
/// calling this method between sync requests.
#[napi(strict)]
pub async fn get_missing_sessions(
&self,
users: Option<Vec<&identifiers::UserId>>,
) -> napi::Result<Option<requests::KeysClaimRequest>> {
let users = users
.unwrap_or_default()
.into_iter()
.map(|user| user.inner.clone())
.collect::<Vec<_>>();
match self
.inner
.get_missing_sessions(users.iter().map(AsRef::as_ref))
.await
.map_err(into_err)?
{
Some((transaction_id, keys_claim_request)) => Ok(Some(
requests::KeysClaimRequest::try_from((
transaction_id.to_string(),
&keys_claim_request,
))
.map_err(into_err)?,
)),
None => Ok(None),
}
}
/// Update the tracked users.
///
/// This will mark users that werent seen before for a key query
/// and tracking.
///
/// If the user is already known to the Olm machine it will not be
/// considered for a key query.
///
/// # Arguments
///
/// * `users`, an array over user IDs that should be marked for tracking.
#[napi(strict)]
pub async fn update_tracked_users(&self, users: Vec<&identifiers::UserId>) {
let users = users.into_iter().map(|user| user.inner.clone()).collect::<Vec<_>>();
self.inner.update_tracked_users(users.iter().map(AsRef::as_ref)).await;
}
/// Get to-device requests to share a room key with users in a room.
///
/// # Arguments
///
/// * `room_id`, the room ID of the room where the room key will be used.
/// * `users`, the list of users that should receive the room key.
/// * `encryption_settings`, the encryption settings.
#[napi(strict)]
pub async fn share_room_key(
&self,
room_id: &identifiers::RoomId,
users: Vec<&identifiers::UserId>,
encryption_settings: &encryption::EncryptionSettings,
) -> napi::Result<String> {
let room_id = room_id.inner.clone();
let users = users.into_iter().map(|user| user.inner.clone()).collect::<Vec<_>>();
let encryption_settings =
matrix_sdk_crypto::olm::EncryptionSettings::from(encryption_settings);
serde_json::to_string(
&self
.inner
.share_room_key(&room_id, users.iter().map(AsRef::as_ref), encryption_settings)
.await
.map_err(into_err)?,
)
.map_err(into_err)
}
/// Encrypt a JSON-encoded content for the given room.
///
/// # Arguments
///
/// * `room_id`, the ID of the room for which the message should be
/// encrypted.
/// * `event_type`, the plaintext type of the event.
/// * `content`, the JSON-encoded content of the message that should be
/// encrypted.
#[napi(strict)]
pub async fn encrypt_room_event(
&self,
room_id: &identifiers::RoomId,
event_type: String,
content: String,
) -> napi::Result<String> {
let room_id = room_id.inner.clone();
let content: JsonValue = serde_json::from_str(content.as_str()).map_err(into_err)?;
serde_json::to_string(
&self
.inner
.encrypt_room_event_raw(&room_id, content, event_type.as_ref())
.await
.map_err(into_err)?,
)
.map_err(into_err)
}
/// Decrypt an event from a room timeline.
///
/// # Arguments
///
/// * `event`, the event that should be decrypted.
/// * `room_id`, the ID of the room where the event was sent to.
#[napi(strict)]
pub async fn decrypt_room_event(
&self,
event: String,
room_id: &identifiers::RoomId,
) -> napi::Result<responses::DecryptedRoomEvent> {
let event: OriginalSyncRoomEncryptedEvent =
serde_json::from_str(event.as_str()).map_err(into_err)?;
let room_id = room_id.inner.clone();
let room_event = self.inner.decrypt_room_event(&event, &room_id).await.map_err(into_err)?;
Ok(room_event.into())
}
/// Get the status of the private cross signing keys.
///
/// This can be used to check which private cross signing keys we
/// have stored locally.
#[napi]
pub async fn cross_signing_status(&self) -> olm::CrossSigningStatus {
self.inner.cross_signing_status().await.into()
}
/// Sign the given message using our device key and if available
/// cross-signing master key.
#[napi(strict)]
pub async fn sign(&self, message: String) -> types::Signatures {
self.inner.sign(message.as_str()).await.into()
}
}
@@ -0,0 +1,40 @@
//! Olm types.
use napi_derive::*;
/// Struct representing the state of our private cross signing keys,
/// it shows which private cross signing keys we have locally stored.
#[napi]
#[derive(Debug)]
pub struct CrossSigningStatus {
inner: matrix_sdk_crypto::olm::CrossSigningStatus,
}
impl From<matrix_sdk_crypto::olm::CrossSigningStatus> for CrossSigningStatus {
fn from(inner: matrix_sdk_crypto::olm::CrossSigningStatus) -> Self {
Self { inner }
}
}
#[napi]
impl CrossSigningStatus {
/// Do we have the master key.
#[napi(getter)]
pub fn has_master(&self) -> bool {
self.inner.has_master
}
/// Do we have the self signing key, this one is necessary to sign
/// our own devices.
#[napi(getter)]
pub fn has_self_signing(&self) -> bool {
self.inner.has_self_signing
}
/// Do we have the user signing key, this one is necessary to sign
/// other users.
#[napi(getter)]
pub fn has_user_signing(&self) -> bool {
self.inner.has_user_signing
}
}
@@ -0,0 +1,338 @@
//! Types to handle requests.
use std::time::Duration;
use matrix_sdk_crypto::requests::{
KeysBackupRequest as RumaKeysBackupRequest, KeysQueryRequest as RumaKeysQueryRequest,
RoomMessageRequest as RumaRoomMessageRequest, ToDeviceRequest as RumaToDeviceRequest,
};
use napi::bindgen_prelude::{Either7, ToNapiValue};
use napi_derive::*;
use ruma::api::client::keys::{
claim_keys::v3::Request as RumaKeysClaimRequest,
upload_keys::v3::Request as RumaKeysUploadRequest,
upload_signatures::v3::Request as RumaSignatureUploadRequest,
};
use crate::into_err;
/// Data for a request to the `/keys/upload` API endpoint
/// ([specification]).
///
/// Publishes end-to-end encryption keys for the device.
///
/// [specification]: https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3keysupload
#[napi]
pub struct KeysUploadRequest {
/// The request ID.
#[napi(readonly)]
pub id: String,
/// A JSON-encoded object of form:
///
/// ```json
/// {"device_keys": …, "one_time_keys": …, "fallback_keys": …}
/// ```
#[napi(readonly)]
pub body: String,
}
#[napi]
impl KeysUploadRequest {
/// Get its request type.
#[napi(getter, js_name = "type")]
pub fn request_type(&self) -> RequestType {
RequestType::KeysUpload
}
}
/// Data for a request to the `/keys/query` API endpoint
/// ([specification]).
///
/// Returns the current devices and identity keys for the given users.
///
/// [specification]: https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3keysquery
#[napi]
pub struct KeysQueryRequest {
/// The request ID.
#[napi(readonly)]
pub id: String,
/// A JSON-encoded object of form:
///
/// ```json
/// {"timeout": …, "device_keys": …, "token": …}
/// ```
#[napi(readonly)]
pub body: String,
}
#[napi]
impl KeysQueryRequest {
/// Get its request type.
#[napi(getter, js_name = "type")]
pub fn request_type(&self) -> RequestType {
RequestType::KeysQuery
}
}
/// Data for a request to the `/keys/claim` API endpoint
/// ([specification]).
///
/// Claims one-time keys that can be used to establish 1-to-1 E2EE
/// sessions.
///
/// [specification]: https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3keysclaim
#[napi]
pub struct KeysClaimRequest {
/// The request ID.
#[napi(readonly)]
pub id: String,
/// A JSON-encoded object of form:
///
/// ```json
/// {"timeout": …, "one_time_keys": …}
/// ```
#[napi(readonly)]
pub body: String,
}
#[napi]
impl KeysClaimRequest {
/// Get its request type.
#[napi(getter, js_name = "type")]
pub fn request_type(&self) -> RequestType {
RequestType::KeysClaim
}
}
/// Data for a request to the `/sendToDevice` API endpoint
/// ([specification]).
///
/// Send an event to a single device or to a group of devices.
///
/// [specification]: https://spec.matrix.org/unstable/client-server-api/#put_matrixclientv3sendtodeviceeventtypetxnid
#[napi]
pub struct ToDeviceRequest {
/// The request ID.
#[napi(readonly)]
pub id: String,
/// A JSON-encoded object of form:
///
/// ```json
/// {"event_type": …, "txn_id": …, "messages": …}
/// ```
#[napi(readonly)]
pub body: String,
}
#[napi]
impl ToDeviceRequest {
/// Get its request type.
#[napi(getter, js_name = "type")]
pub fn request_type(&self) -> RequestType {
RequestType::ToDevice
}
}
/// Data for a request to the `/keys/signatures/upload` API endpoint
/// ([specification]).
///
/// Publishes cross-signing signatures for the user.
///
/// [specification]: https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3keyssignaturesupload
#[napi]
pub struct SignatureUploadRequest {
/// The request ID.
#[napi(readonly)]
pub id: String,
/// A JSON-encoded object of form:
///
/// ```json
/// {"signed_keys": …, "txn_id": …, "messages": …}
/// ```
#[napi(readonly)]
pub body: String,
}
#[napi]
impl SignatureUploadRequest {
/// Get its request type.
#[napi(getter, js_name = "type")]
pub fn request_type(&self) -> RequestType {
RequestType::SignatureUpload
}
}
/// A customized owned request type for sending out room messages
/// ([specification]).
///
/// [specification]: https://spec.matrix.org/unstable/client-server-api/#put_matrixclientv3roomsroomidsendeventtypetxnid
#[napi]
pub struct RoomMessageRequest {
/// The request ID.
#[napi(readonly)]
pub id: String,
/// A JSON-encoded object of form:
///
/// ```json
/// {"room_id": …, "txn_id": …, "content": …}
/// ```
#[napi(readonly)]
pub body: String,
}
#[napi]
impl RoomMessageRequest {
/// Get its request type.
#[napi(getter, js_name = "type")]
pub fn request_type(&self) -> RequestType {
RequestType::RoomMessage
}
}
/// A request that will back up a batch of room keys to the server
/// ([specification]).
///
/// [specification]: https://spec.matrix.org/unstable/client-server-api/#put_matrixclientv3room_keyskeys
#[napi]
pub struct KeysBackupRequest {
/// The request ID.
#[napi(readonly)]
pub id: String,
/// A JSON-encoded object of form:
///
/// ```json
/// {"rooms": …}
/// ```
#[napi(readonly)]
pub body: String,
}
#[napi]
impl KeysBackupRequest {
/// Get its request type.
#[napi(getter, js_name = "type")]
pub fn request_type(&self) -> RequestType {
RequestType::KeysBackup
}
}
macro_rules! request {
($request:ident from $ruma_request:ident maps fields $( $field:ident $( { $transformation:expr } )? ),+ $(,)? ) => {
impl TryFrom<(String, &$ruma_request)> for $request {
type Error = napi::Error;
fn try_from(
(request_id, request): (String, &$ruma_request),
) -> Result<Self, Self::Error> {
let mut map = serde_json::Map::new();
$(
let field = &request.$field;
$(
let field = {
let $field = field;
$transformation
};
)?
map.insert(stringify!($field).to_owned(), serde_json::to_value(field).map_err(into_err)?);
)+
let value = serde_json::Value::Object(map);
Ok($request {
id: request_id,
body: serde_json::to_string(&value).map_err(into_err)?.into(),
})
}
}
};
}
request!(KeysUploadRequest from RumaKeysUploadRequest maps fields device_keys, one_time_keys, fallback_keys);
request!(KeysQueryRequest from RumaKeysQueryRequest maps fields timeout { timeout.as_ref().map(Duration::as_millis).map(u64::try_from).transpose().map_err(into_err)? }, device_keys, token);
request!(KeysClaimRequest from RumaKeysClaimRequest maps fields timeout { timeout.as_ref().map(Duration::as_millis).map(u64::try_from).transpose().map_err(into_err)? }, one_time_keys);
request!(ToDeviceRequest from RumaToDeviceRequest maps fields event_type, txn_id, messages);
request!(SignatureUploadRequest from RumaSignatureUploadRequest maps fields signed_keys);
request!(RoomMessageRequest from RumaRoomMessageRequest maps fields room_id, txn_id, content);
request!(KeysBackupRequest from RumaKeysBackupRequest maps fields rooms);
pub type OutgoingRequests = Either7<
KeysUploadRequest,
KeysQueryRequest,
KeysClaimRequest,
ToDeviceRequest,
SignatureUploadRequest,
RoomMessageRequest,
KeysBackupRequest,
>;
pub(crate) struct OutgoingRequest(pub(crate) matrix_sdk_crypto::OutgoingRequest);
impl TryFrom<OutgoingRequest> for OutgoingRequests {
type Error = napi::Error;
fn try_from(outgoing_request: OutgoingRequest) -> Result<Self, Self::Error> {
let request_id = outgoing_request.0.request_id().to_string();
Ok(match outgoing_request.0.request() {
matrix_sdk_crypto::OutgoingRequests::KeysUpload(request) => {
Either7::A(KeysUploadRequest::try_from((request_id, request))?)
}
matrix_sdk_crypto::OutgoingRequests::KeysQuery(request) => {
Either7::B(KeysQueryRequest::try_from((request_id, request))?)
}
matrix_sdk_crypto::OutgoingRequests::KeysClaim(request) => {
Either7::C(KeysClaimRequest::try_from((request_id, request))?)
}
matrix_sdk_crypto::OutgoingRequests::ToDeviceRequest(request) => {
Either7::D(ToDeviceRequest::try_from((request_id, request))?)
}
matrix_sdk_crypto::OutgoingRequests::SignatureUpload(request) => {
Either7::E(SignatureUploadRequest::try_from((request_id, request))?)
}
matrix_sdk_crypto::OutgoingRequests::RoomMessage(request) => {
Either7::F(RoomMessageRequest::try_from((request_id, request))?)
}
matrix_sdk_crypto::OutgoingRequests::KeysBackup(request) => {
Either7::G(KeysBackupRequest::try_from((request_id, request))?)
}
})
}
}
/// Represent the type of a request.
#[napi]
pub enum RequestType {
/// Represents a `KeysUploadRequest`.
KeysUpload,
/// Represents a `KeysQueryRequest`.
KeysQuery,
/// Represents a `KeysClaimRequest`.
KeysClaim,
/// Represents a `ToDeviceRequest`.
ToDevice,
/// Represents a `SignatureUploadRequest`.
SignatureUpload,
/// Represents a `RoomMessageRequest`.
RoomMessage,
/// Represents a `KeysBackupRequest`.
KeysBackup,
}
@@ -0,0 +1,203 @@
use std::borrow::Borrow;
use matrix_sdk_common::deserialized_responses::{AlgorithmInfo, EncryptionInfo};
use matrix_sdk_crypto::IncomingResponse;
use napi_derive::*;
pub(crate) use ruma::api::client::{
backup::add_backup_keys::v3::Response as KeysBackupResponse,
keys::{
claim_keys::v3::Response as KeysClaimResponse, get_keys::v3::Response as KeysQueryResponse,
upload_keys::v3::Response as KeysUploadResponse,
upload_signatures::v3::Response as SignatureUploadResponse,
},
message::send_message_event::v3::Response as RoomMessageResponse,
to_device::send_event_to_device::v3::Response as ToDeviceResponse,
};
use ruma::api::IncomingResponse as RumaIncomingResponse;
use crate::{encryption, identifiers, into_err, requests::RequestType};
pub(crate) fn response_from_string(body: &str) -> http::Result<http::Response<Vec<u8>>> {
http::Response::builder().status(200).body(body.as_bytes().to_vec())
}
/// Intermediate private type to store an incoming owned response,
/// without the need to manage lifetime.
pub(crate) enum OwnedResponse {
KeysUpload(KeysUploadResponse),
KeysQuery(KeysQueryResponse),
KeysClaim(KeysClaimResponse),
ToDevice(ToDeviceResponse),
SignatureUpload(SignatureUploadResponse),
RoomMessage(RoomMessageResponse),
KeysBackup(KeysBackupResponse),
}
impl From<KeysUploadResponse> for OwnedResponse {
fn from(response: KeysUploadResponse) -> Self {
OwnedResponse::KeysUpload(response)
}
}
impl From<KeysQueryResponse> for OwnedResponse {
fn from(response: KeysQueryResponse) -> Self {
OwnedResponse::KeysQuery(response)
}
}
impl From<KeysClaimResponse> for OwnedResponse {
fn from(response: KeysClaimResponse) -> Self {
OwnedResponse::KeysClaim(response)
}
}
impl From<ToDeviceResponse> for OwnedResponse {
fn from(response: ToDeviceResponse) -> Self {
OwnedResponse::ToDevice(response)
}
}
impl From<SignatureUploadResponse> for OwnedResponse {
fn from(response: SignatureUploadResponse) -> Self {
Self::SignatureUpload(response)
}
}
impl From<RoomMessageResponse> for OwnedResponse {
fn from(response: RoomMessageResponse) -> Self {
OwnedResponse::RoomMessage(response)
}
}
impl From<KeysBackupResponse> for OwnedResponse {
fn from(r: KeysBackupResponse) -> Self {
Self::KeysBackup(r)
}
}
impl TryFrom<(RequestType, http::Response<Vec<u8>>)> for OwnedResponse {
type Error = napi::Error;
fn try_from(
(request_type, response): (RequestType, http::Response<Vec<u8>>),
) -> Result<Self, Self::Error> {
match request_type {
RequestType::KeysUpload => {
KeysUploadResponse::try_from_http_response(response).map(Into::into)
}
RequestType::KeysQuery => {
KeysQueryResponse::try_from_http_response(response).map(Into::into)
}
RequestType::KeysClaim => {
KeysClaimResponse::try_from_http_response(response).map(Into::into)
}
RequestType::ToDevice => {
ToDeviceResponse::try_from_http_response(response).map(Into::into)
}
RequestType::SignatureUpload => {
SignatureUploadResponse::try_from_http_response(response).map(Into::into)
}
RequestType::RoomMessage => {
RoomMessageResponse::try_from_http_response(response).map(Into::into)
}
RequestType::KeysBackup => {
KeysBackupResponse::try_from_http_response(response).map(Into::into)
}
}
.map_err(into_err)
}
}
impl<'a> From<&'a OwnedResponse> for IncomingResponse<'a> {
fn from(response: &'a OwnedResponse) -> Self {
match response {
OwnedResponse::KeysUpload(response) => IncomingResponse::KeysUpload(response),
OwnedResponse::KeysQuery(response) => IncomingResponse::KeysQuery(response),
OwnedResponse::KeysClaim(response) => IncomingResponse::KeysClaim(response),
OwnedResponse::ToDevice(response) => IncomingResponse::ToDevice(response),
OwnedResponse::SignatureUpload(response) => IncomingResponse::SignatureUpload(response),
OwnedResponse::RoomMessage(response) => IncomingResponse::RoomMessage(response),
OwnedResponse::KeysBackup(response) => IncomingResponse::KeysBackup(response),
}
}
}
/// A decrypted room event.
#[napi]
pub struct DecryptedRoomEvent {
/// The JSON-encoded decrypted event.
#[napi(readonly)]
pub event: String,
encryption_info: Option<EncryptionInfo>,
}
#[napi]
impl DecryptedRoomEvent {
/// The user ID of the event sender, note this is untrusted data
/// unless the `verification_state` is as well trusted.
#[napi(getter)]
pub fn sender(&self) -> Option<identifiers::UserId> {
Some(identifiers::UserId::from(self.encryption_info.as_ref()?.sender.clone()))
}
/// The device ID of the device that sent us the event, note this
/// is untrusted data unless `verification_state` is as well
/// trusted.
#[napi(getter)]
pub fn sender_device(&self) -> Option<identifiers::DeviceId> {
Some(identifiers::DeviceId::from(self.encryption_info.as_ref()?.sender_device.clone()))
}
/// The Curve25519 key of the device that created the megolm
/// decryption key originally.
#[napi(getter)]
pub fn sender_curve25519_key(&self) -> Option<String> {
Some(match &self.encryption_info.as_ref()?.algorithm_info {
AlgorithmInfo::MegolmV1AesSha2 { curve25519_key, .. } => curve25519_key.clone(),
})
}
/// The signing Ed25519 key that have created the megolm key that
/// was used to decrypt this session.
#[napi(getter)]
pub fn sender_claimed_ed25519_key(&self) -> Option<String> {
match &self.encryption_info.as_ref()?.algorithm_info {
AlgorithmInfo::MegolmV1AesSha2 { sender_claimed_keys, .. } => {
sender_claimed_keys.get(&ruma::DeviceKeyAlgorithm::Ed25519).cloned()
}
}
}
/// Chain of Curve25519 keys through which this session was
/// forwarded, via `m.forwarded_room_key` events.
#[napi(getter)]
pub fn forwarding_curve25519_key_chain(&self) -> Option<Vec<String>> {
Some(match &self.encryption_info.as_ref()?.algorithm_info {
AlgorithmInfo::MegolmV1AesSha2 { forwarding_curve25519_key_chain, .. } => {
forwarding_curve25519_key_chain.clone()
}
})
}
/// The verification state of the device that sent us the event,
/// note this is the state of the device at the time of
/// decryption. It may change in the future if a device gets
/// verified or deleted.
#[napi(getter)]
pub fn verification_state(&self) -> Option<encryption::VerificationState> {
Some(self.encryption_info.as_ref()?.verification_state.borrow().into())
}
}
impl From<matrix_sdk_common::deserialized_responses::RoomEvent> for DecryptedRoomEvent {
fn from(value: matrix_sdk_common::deserialized_responses::RoomEvent) -> Self {
Self { event: value.event.json().get().to_owned(), encryption_info: value.encryption_info }
}
}
@@ -0,0 +1,49 @@
//! `GET /_matrix/client/*/sync`.
use napi_derive::*;
use crate::identifiers;
/// Information on E2E device updates.
#[napi]
pub struct DeviceLists {
pub(crate) inner: ruma::api::client::sync::sync_events::v3::DeviceLists,
}
#[napi]
impl DeviceLists {
/// Create an empty `DeviceLists`.
#[napi(constructor, strict)]
pub fn new(
changed: Option<Vec<&identifiers::UserId>>,
left: Option<Vec<&identifiers::UserId>>,
) -> Self {
let mut inner = ruma::api::client::sync::sync_events::v3::DeviceLists::default();
inner.changed = changed.into_iter().flatten().map(|user| user.inner.clone()).collect();
inner.left = left.into_iter().flatten().map(|user| user.inner.clone()).collect();
Self { inner }
}
/// Returns true if there are no device list updates.
#[napi]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
/// List of users who have updated their device identity keys or
/// who now share an encrypted room with the client since the
/// previous sync.
#[napi(getter)]
pub fn changed(&self) -> Vec<identifiers::UserId> {
self.inner.changed.iter().map(|user| identifiers::UserId::from(user.to_owned())).collect()
}
/// List of users who no longer share encrypted rooms since the
/// previous sync response.
#[napi(getter)]
pub fn left(&self) -> Vec<identifiers::UserId> {
self.inner.left.iter().map(|user| identifiers::UserId::from(user.to_owned())).collect()
}
}

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