From 420ca26bf57766c8ffcaefcc94960962ac9b2701 Mon Sep 17 00:00:00 2001 From: Johannes Becker Date: Tue, 12 Jul 2022 10:44:56 +0200 Subject: [PATCH 01/73] fix(sdk): Can't assert identity without session --- crates/matrix-sdk/src/client/builder.rs | 7 +++++-- crates/matrix-sdk/src/http_client.rs | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/crates/matrix-sdk/src/client/builder.rs b/crates/matrix-sdk/src/client/builder.rs index 77e5c639f..fa9b17c1f 100644 --- a/crates/matrix-sdk/src/client/builder.rs +++ b/crates/matrix-sdk/src/client/builder.rs @@ -239,8 +239,11 @@ impl ClientBuilder { /// All outgoing http requests will have a GET query key-value appended with /// `user_id` being the key and the `user_id` from the `Session` being - /// the value. Will error if there's no `Session`. This is called - /// [identity assertion] in the Matrix Application Service Spec + /// the value. This is called [identity assertion] in the + /// Matrix Application Service Spec. + /// + /// Requests that don't require authentication might not do identity + /// assertion. /// /// [identity assertion]: https://spec.matrix.org/unstable/application-service-api/#identity-assertion #[doc(hidden)] diff --git a/crates/matrix-sdk/src/http_client.rs b/crates/matrix-sdk/src/http_client.rs index 0d70eeb26..13b4fe25f 100644 --- a/crates/matrix-sdk/src/http_client.rs +++ b/crates/matrix-sdk/src/http_client.rs @@ -125,7 +125,8 @@ impl HttpClient { } trace!("Serializing request"); - let request = if !config.assert_identity { + // We can't assert the identity without a session. + let request = if !config.assert_identity || session.is_none() { let send_access_token = if auth_scheme == AuthScheme::None && !config.force_auth { // Small optimization: Don't take the session lock if we know the auth token // isn't going to be used anyways. From 94b635c07443454c48ccab0a0fdb88270176715f Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Tue, 12 Jul 2022 16:05:57 +0200 Subject: [PATCH 02/73] 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 * 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 --- .github/workflows/bindings_ci.yml | 1 + .github/workflows/coverage.yml | 1 + .../workflows/prep-crypto-nodejs-release.yml | 108 ++++++++++++++++ .github/workflows/release-crypto-nodejs.yml | 117 ++++++++++++++++++ bindings/matrix-sdk-crypto-js/package.json | 2 +- bindings/matrix-sdk-crypto-nodejs/.gitignore | 1 + bindings/matrix-sdk-crypto-nodejs/.npmignore | 8 ++ .../matrix-sdk-crypto-nodejs/CHANGELOG.md | 3 + bindings/matrix-sdk-crypto-nodejs/README.md | 73 ++++++++++- bindings/matrix-sdk-crypto-nodejs/cliff.toml | 59 +++++++++ .../matrix-sdk-crypto-nodejs/download-lib.js | 113 +++++++++++++++++ .../matrix-sdk-crypto-nodejs/package.json | 8 +- 12 files changed, 490 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/prep-crypto-nodejs-release.yml create mode 100644 .github/workflows/release-crypto-nodejs.yml create mode 100644 bindings/matrix-sdk-crypto-nodejs/.npmignore create mode 100644 bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md create mode 100644 bindings/matrix-sdk-crypto-nodejs/cliff.toml create mode 100644 bindings/matrix-sdk-crypto-nodejs/download-lib.js diff --git a/.github/workflows/bindings_ci.yml b/.github/workflows/bindings_ci.yml index a3cb09f8e..30fcefc11 100644 --- a/.github/workflows/bindings_ci.yml +++ b/.github/workflows/bindings_ci.yml @@ -133,6 +133,7 @@ jobs: test-apple: name: matrix-rust-components-swift runs-on: macos-12 + if: github.event_name == 'push' || !github.event.pull_request.draft steps: - name: Checkout diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 7ce0a58ba..0e30d443f 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -13,6 +13,7 @@ jobs: code_coverage: name: Code Coverage runs-on: "ubuntu-latest" + if: github.event_name == 'push' || !github.event.pull_request.draft steps: - name: Checkout repository diff --git a/.github/workflows/prep-crypto-nodejs-release.yml b/.github/workflows/prep-crypto-nodejs-release.yml new file mode 100644 index 000000000..d1865fdf6 --- /dev/null +++ b/.github/workflows/prep-crypto-nodejs-release.yml @@ -0,0 +1,108 @@ +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: "Package nodejs package" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@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 + uses: KageKirin/set-node-package-version@v0 + with: + 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_banch: "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 }}" + title: "Preparing Release ${{ env.TAG_PREFIX }}${{ inputs.version }}" + body: | + Automatic Pull-Request to merge release ${{ env.TAG_PREFIX }}${{ inputs.version }} back into main diff --git a/.github/workflows/release-crypto-nodejs.yml b/.github/workflows/release-crypto-nodejs.yml new file mode 100644 index 000000000..0efe7b28a --- /dev/null +++ b/.github/workflows/release-crypto-nodejs.yml @@ -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 + environment: NPM + 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: + token: ${{ secrets.NPM_TOKEN }} \ No newline at end of file diff --git a/bindings/matrix-sdk-crypto-js/package.json b/bindings/matrix-sdk-crypto-js/package.json index 3328f325d..d6905cb80 100644 --- a/bindings/matrix-sdk-crypto-js/package.json +++ b/bindings/matrix-sdk-crypto-js/package.json @@ -1,5 +1,5 @@ { - "name": "matrix-sdk-crypto-js", + "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", diff --git a/bindings/matrix-sdk-crypto-nodejs/.gitignore b/bindings/matrix-sdk-crypto-nodejs/.gitignore index aece07f69..f1fbf26ec 100644 --- a/bindings/matrix-sdk-crypto-nodejs/.gitignore +++ b/bindings/matrix-sdk-crypto-nodejs/.gitignore @@ -4,3 +4,4 @@ /index.d.ts /matrix-sdk-crypto.*.node /docs/* +*.tgz \ No newline at end of file diff --git a/bindings/matrix-sdk-crypto-nodejs/.npmignore b/bindings/matrix-sdk-crypto-nodejs/.npmignore new file mode 100644 index 000000000..3e3d54025 --- /dev/null +++ b/bindings/matrix-sdk-crypto-nodejs/.npmignore @@ -0,0 +1,8 @@ +src/ +tests/ +Cargo.toml +build.rs +*.node +*.tgz +tsconfig.json +cliff.toml \ No newline at end of file diff --git a/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md b/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md new file mode 100644 index 000000000..fa95abc2a --- /dev/null +++ b/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md @@ -0,0 +1,3 @@ +# Matrix-Rust-SDK NodeJS Bindings + +-- Changelog Test -- \ No newline at end of file diff --git a/bindings/matrix-sdk-crypto-nodejs/README.md b/bindings/matrix-sdk-crypto-nodejs/README.md index 10a6d321a..cf3daa20f 100644 --- a/bindings/matrix-sdk-crypto-nodejs/README.md +++ b/bindings/matrix-sdk-crypto-nodejs/README.md @@ -11,6 +11,77 @@ Encryption](https://en.wikipedia.org/wiki/End-to-end_encryption)) for ## 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: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PlatformArchitectureTriplePrebuilt available
Linuxaarchaarch64-unknown-linux-gnu
arm-unknown-linux-gnueabihf
amdx86_64-unknown-linux-gnu
x86_64-unknown-linux-musl
i686-unknown-linux-gnu
macOSaarcharch64-apple-darwin
amdx86_64-apple-darwin
Windowsaarchaarch64-pc-windows-msvc
amdx86_64-pc-windows-msvc
i686-pc-windows-msvc
+ +## 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 @@ -31,7 +102,7 @@ Once the Rust compiler, Node.js and npm are installed, you can run the following commands: ```sh -$ npm install +$ npm install --ignore-scripts $ npm run build $ npm run test ``` diff --git a/bindings/matrix-sdk-crypto-nodejs/cliff.toml b/bindings/matrix-sdk-crypto-nodejs/cliff.toml new file mode 100644 index 000000000..e9fb2cf3b --- /dev/null +++ b/bindings/matrix-sdk-crypto-nodejs/cliff.toml @@ -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" diff --git a/bindings/matrix-sdk-crypto-nodejs/download-lib.js b/bindings/matrix-sdk-crypto-nodejs/download-lib.js new file mode 100644 index 000000000..7a12e172f --- /dev/null +++ b/bindings/matrix-sdk-crypto-nodejs/download-lib.js @@ -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}`) +} diff --git a/bindings/matrix-sdk-crypto-nodejs/package.json b/bindings/matrix-sdk-crypto-nodejs/package.json index 46b18cbcd..3f8e56c4d 100644 --- a/bindings/matrix-sdk-crypto-nodejs/package.json +++ b/bindings/matrix-sdk-crypto-nodejs/package.json @@ -1,6 +1,6 @@ { - "name": "@matrix-org/matrix-sdk-crypto", - "version": "0.5.0", + "name": "@matrix-org/matrix-sdk-crypto-nodejs", + "version": "0.1.0", "main": "index.js", "types": "index.d.ts", "napi": { @@ -23,7 +23,11 @@ "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" } } From 0bde5ccf38f8cda3865297a2d12ddcdaf4b80ca7 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 12 Jul 2022 16:24:24 +0200 Subject: [PATCH 03/73] 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. --- bindings/matrix-sdk-crypto-nodejs/Cargo.toml | 4 ++-- .../src/identifiers.rs | 10 +++++----- .../matrix-sdk-crypto-nodejs/src/machine.rs | 18 +++++++++--------- .../src/sync_events.rs | 2 +- bindings/matrix-sdk-crypto-nodejs/src/types.rs | 6 +++--- .../matrix-sdk-crypto-nodejs/src/vodozemac.rs | 2 +- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/bindings/matrix-sdk-crypto-nodejs/Cargo.toml b/bindings/matrix-sdk-crypto-nodejs/Cargo.toml index ee16a92b0..8fc02a806 100644 --- a/bindings/matrix-sdk-crypto-nodejs/Cargo.toml +++ b/bindings/matrix-sdk-crypto-nodejs/Cargo.toml @@ -30,8 +30,8 @@ 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 = { version = "2.6.1", default-features = false, features = ["napi6", "tokio_rt"] } -napi-derive = "2.6.0" +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" diff --git a/bindings/matrix-sdk-crypto-nodejs/src/identifiers.rs b/bindings/matrix-sdk-crypto-nodejs/src/identifiers.rs index eb45873b8..f5b6c4b55 100644 --- a/bindings/matrix-sdk-crypto-nodejs/src/identifiers.rs +++ b/bindings/matrix-sdk-crypto-nodejs/src/identifiers.rs @@ -24,7 +24,7 @@ impl From for UserId { #[napi] impl UserId { /// Parse/validate and create a new `UserId`. - #[napi(constructor)] + #[napi(constructor, strict)] pub fn new(id: String) -> napi::Result { Ok(Self::from(ruma::UserId::parse(id.as_str()).map_err(into_err)?)) } @@ -78,7 +78,7 @@ impl From for DeviceId { #[napi] impl DeviceId { /// Create a new `DeviceId`. - #[napi(constructor)] + #[napi(constructor, strict)] pub fn new(id: String) -> Self { Self::from(Into::::into(id)) } @@ -109,7 +109,7 @@ impl From for DeviceKeyId { #[napi] impl DeviceKeyId { /// Parse/validate and create a new `DeviceKeyId`. - #[napi(constructor)] + #[napi(constructor, strict)] pub fn new(id: String) -> napi::Result { Ok(Self::from(ruma::DeviceKeyId::parse(id.as_str()).map_err(into_err)?)) } @@ -212,7 +212,7 @@ impl From for RoomId { #[napi] impl RoomId { /// Parse/validate and create a new `RoomId`. - #[napi(constructor)] + #[napi(constructor, strict)] pub fn new(id: String) -> napi::Result { Ok(Self::from(ruma::RoomId::parse(id).map_err(into_err)?)) } @@ -252,7 +252,7 @@ pub struct ServerName { #[napi] impl ServerName { /// Parse/validate and create a new `ServerName`. - #[napi(constructor)] + #[napi(constructor, strict)] pub fn new(name: String) -> napi::Result { Ok(Self { inner: ruma::ServerName::parse(name).map_err(into_err)? }) } diff --git a/bindings/matrix-sdk-crypto-nodejs/src/machine.rs b/bindings/matrix-sdk-crypto-nodejs/src/machine.rs index 9128f2f4f..5348ad54a 100644 --- a/bindings/matrix-sdk-crypto-nodejs/src/machine.rs +++ b/bindings/matrix-sdk-crypto-nodejs/src/machine.rs @@ -56,7 +56,7 @@ impl OlmMachine { /// 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] + #[napi(strict)] pub async fn initialize( user_id: &identifiers::UserId, device_id: &identifiers::DeviceId, @@ -144,7 +144,7 @@ impl OlmMachine { /// response. /// * `one_time_keys_count`, the current one-time keys counts that the sync /// response returned. - #[napi] + #[napi(strict)] pub async fn receive_sync_changes( &self, to_device_events: String, @@ -227,7 +227,7 @@ impl OlmMachine { /// * `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] + #[napi(strict)] pub async fn mark_request_as_sent( &self, request_id: String, @@ -272,7 +272,7 @@ impl OlmMachine { /// * `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] + #[napi(strict)] pub async fn get_missing_sessions( &self, users: Option>, @@ -312,7 +312,7 @@ impl OlmMachine { /// # Arguments /// /// * `users`, an array over user IDs that should be marked for tracking. - #[napi] + #[napi(strict)] pub async fn update_tracked_users(&self, users: Vec<&identifiers::UserId>) { let users = users.into_iter().map(|user| user.inner.clone()).collect::>(); @@ -326,7 +326,7 @@ impl OlmMachine { /// * `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] + #[napi(strict)] pub async fn share_room_key( &self, room_id: &identifiers::RoomId, @@ -357,7 +357,7 @@ impl OlmMachine { /// * `event_type`, the plaintext type of the event. /// * `content`, the JSON-encoded content of the message that should be /// encrypted. - #[napi] + #[napi(strict)] pub async fn encrypt_room_event( &self, room_id: &identifiers::RoomId, @@ -383,7 +383,7 @@ impl OlmMachine { /// /// * `event`, the event that should be decrypted. /// * `room_id`, the ID of the room where the event was sent to. - #[napi] + #[napi(strict)] pub async fn decrypt_room_event( &self, event: String, @@ -409,7 +409,7 @@ impl OlmMachine { /// Sign the given message using our device key and if available /// cross-signing master key. - #[napi] + #[napi(strict)] pub async fn sign(&self, message: String) -> types::Signatures { self.inner.sign(message.as_str()).await.into() } diff --git a/bindings/matrix-sdk-crypto-nodejs/src/sync_events.rs b/bindings/matrix-sdk-crypto-nodejs/src/sync_events.rs index 1f7f1619e..63e017021 100644 --- a/bindings/matrix-sdk-crypto-nodejs/src/sync_events.rs +++ b/bindings/matrix-sdk-crypto-nodejs/src/sync_events.rs @@ -13,7 +13,7 @@ pub struct DeviceLists { #[napi] impl DeviceLists { /// Create an empty `DeviceLists`. - #[napi(constructor)] + #[napi(constructor, strict)] pub fn new( changed: Option>, left: Option>, diff --git a/bindings/matrix-sdk-crypto-nodejs/src/types.rs b/bindings/matrix-sdk-crypto-nodejs/src/types.rs index ca68adab4..89d1027d5 100644 --- a/bindings/matrix-sdk-crypto-nodejs/src/types.rs +++ b/bindings/matrix-sdk-crypto-nodejs/src/types.rs @@ -29,7 +29,7 @@ impl Signatures { /// Add the given signature from the given signer and the given key ID to /// the collection. - #[napi] + #[napi(strict)] pub fn add_signature( &mut self, signer: &UserId, @@ -43,13 +43,13 @@ impl Signatures { /// Try to find an Ed25519 signature from the given signer with /// the given key ID. - #[napi] + #[napi(strict)] pub fn get_signature(&self, signer: &UserId, key_id: &DeviceKeyId) -> Option { self.inner.get_signature(signer.inner.as_ref(), key_id.inner.as_ref()).map(Into::into) } /// Get the map of signatures that belong to the given user. - #[napi] + #[napi(strict)] pub fn get(&self, signer: &UserId) -> Option> { self.inner.get(signer.inner.as_ref()).map(|map| { map.iter() diff --git a/bindings/matrix-sdk-crypto-nodejs/src/vodozemac.rs b/bindings/matrix-sdk-crypto-nodejs/src/vodozemac.rs index eacc15196..f2ecfc06b 100644 --- a/bindings/matrix-sdk-crypto-nodejs/src/vodozemac.rs +++ b/bindings/matrix-sdk-crypto-nodejs/src/vodozemac.rs @@ -42,7 +42,7 @@ impl From for Ed25519Signature { impl Ed25519Signature { /// Try to create an Ed25519 signature from an unpadded base64 /// representation. - #[napi(constructor)] + #[napi(constructor, strict)] pub fn new(signature: String) -> napi::Result { Ok(Self { inner: vodozemac::Ed25519Signature::from_base64(signature.as_str()) From 9a4532568380b728a2bf5dab8b671a1e20577818 Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Tue, 12 Jul 2022 17:00:44 +0200 Subject: [PATCH 04/73] ci(crypto-nodejs): use org-wide secrets (#835) --- .github/workflows/release-crypto-nodejs.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/release-crypto-nodejs.yml b/.github/workflows/release-crypto-nodejs.yml index 0efe7b28a..6a65dbaf1 100644 --- a/.github/workflows/release-crypto-nodejs.yml +++ b/.github/workflows/release-crypto-nodejs.yml @@ -87,7 +87,6 @@ jobs: publish-nodejs-package: name: "Package nodejs package" runs-on: ubuntu-latest - environment: NPM needs: - upload-assets steps: @@ -114,4 +113,4 @@ jobs: - name: Publish to npmjs.com uses: JS-DevTools/npm-publish@v1 with: - token: ${{ secrets.NPM_TOKEN }} \ No newline at end of file + token: ${{ secrets.NPM_TOKEN }} From c5796991e818c266670820a10ce831416337e41e Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Tue, 12 Jul 2022 17:05:40 +0200 Subject: [PATCH 05/73] chore(crypto-nodejs): Adding changelog --- .../matrix-sdk-crypto-nodejs/CHANGELOG.md | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md b/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md index fa95abc2a..de1db1374 100644 --- a/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md +++ b/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md @@ -1,3 +1,28 @@ -# Matrix-Rust-SDK NodeJS Bindings +# Matrix-Rust-SDK Node.js Bindings --- Changelog Test -- \ No newline at end of file +## 0.5.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). From 13a6825af70ea53831c42143ab5c7ed4b29e63f8 Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Tue, 12 Jul 2022 17:07:49 +0200 Subject: [PATCH 06/73] ci(crypto-nodejs): Fix workflow syntax error --- .github/workflows/prep-crypto-nodejs-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prep-crypto-nodejs-release.yml b/.github/workflows/prep-crypto-nodejs-release.yml index d1865fdf6..f9575c2cf 100644 --- a/.github/workflows/prep-crypto-nodejs-release.yml +++ b/.github/workflows/prep-crypto-nodejs-release.yml @@ -91,7 +91,7 @@ jobs: # no changes, use the default changelog for the body - name: Update Github Release notes - if: !inputs.previous_version + if: ${{!inputs.previous_version}} uses: softprops/action-gh-release@v1 with: draft: true From 9bc605a76d227cd064bd930b98ec433997bd17db Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Tue, 12 Jul 2022 17:11:20 +0200 Subject: [PATCH 07/73] ci(crypto-nodejs): FIxing name and directory for action --- .github/workflows/prep-crypto-nodejs-release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/prep-crypto-nodejs-release.yml b/.github/workflows/prep-crypto-nodejs-release.yml index f9575c2cf..7fbfef310 100644 --- a/.github/workflows/prep-crypto-nodejs-release.yml +++ b/.github/workflows/prep-crypto-nodejs-release.yml @@ -36,7 +36,7 @@ env: jobs: prepare-release: - name: "Package nodejs package" + name: "Preparing crypto-nodejs release tag" runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -66,6 +66,7 @@ jobs: - name: Set version id: package_version uses: KageKirin/set-node-package-version@v0 + working-directory: ${{ env.PKG_PATH }} with: version: ${{ inputs.version }} From 36f62ce67fb8483e3db33166b5971f892886db8b Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Tue, 12 Jul 2022 17:14:15 +0200 Subject: [PATCH 08/73] ci(crypto-nodejs): Use regular npm version to set version --- .github/workflows/prep-crypto-nodejs-release.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/prep-crypto-nodejs-release.yml b/.github/workflows/prep-crypto-nodejs-release.yml index 7fbfef310..95fd12ce4 100644 --- a/.github/workflows/prep-crypto-nodejs-release.yml +++ b/.github/workflows/prep-crypto-nodejs-release.yml @@ -40,6 +40,7 @@ jobs: 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 @@ -65,10 +66,8 @@ jobs: - name: Set version id: package_version - uses: KageKirin/set-node-package-version@v0 working-directory: ${{ env.PKG_PATH }} - with: - version: ${{ inputs.version }} + run: npm version ${{ inputs.version }} - uses: EndBug/add-and-commit@v9 with: From 703b3a35619084fc06453223d837dcd341a95525 Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Tue, 12 Jul 2022 17:18:54 +0200 Subject: [PATCH 09/73] ci(crypto-nodejs): Fixing typo in workflow --- .github/workflows/prep-crypto-nodejs-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prep-crypto-nodejs-release.yml b/.github/workflows/prep-crypto-nodejs-release.yml index 95fd12ce4..d9354ecaa 100644 --- a/.github/workflows/prep-crypto-nodejs-release.yml +++ b/.github/workflows/prep-crypto-nodejs-release.yml @@ -74,7 +74,7 @@ jobs: default_author: github_actions message: "Tagging Crypto-Node.js for release" tag: "${{env.TAG_PREFIX}}${{ inputs.version }}" - new_banch: "gh-action/release-${{ env.TAG_PREFIX }}${{ inputs.version }}" + new_branch: "gh-action/release-${{ env.TAG_PREFIX }}${{ inputs.version }}" push: true add: | ${{ env.PKG_PATH }}/package.json From bcab2a6d8c3f643f9af2c53a72379bc28feb0372 Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Tue, 12 Jul 2022 17:24:34 +0200 Subject: [PATCH 10/73] ci(crypto-nodejs): setting base branch --- .github/workflows/prep-crypto-nodejs-release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/prep-crypto-nodejs-release.yml b/.github/workflows/prep-crypto-nodejs-release.yml index d9354ecaa..3bed3c853 100644 --- a/.github/workflows/prep-crypto-nodejs-release.yml +++ b/.github/workflows/prep-crypto-nodejs-release.yml @@ -103,6 +103,7 @@ jobs: 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 From 2a1bc372fcf78c8e5a58c9264561bb3499a19a60 Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Tue, 12 Jul 2022 17:35:46 +0200 Subject: [PATCH 11/73] chore(crypto-nodejs): setting version --- bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md | 2 +- bindings/matrix-sdk-crypto-nodejs/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md b/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md index de1db1374..d056255c1 100644 --- a/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md +++ b/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md @@ -1,6 +1,6 @@ # Matrix-Rust-SDK Node.js Bindings -## 0.5.0-beta.0 - 2022-07-21 +## 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 diff --git a/bindings/matrix-sdk-crypto-nodejs/package.json b/bindings/matrix-sdk-crypto-nodejs/package.json index 3f8e56c4d..ee0cc2840 100644 --- a/bindings/matrix-sdk-crypto-nodejs/package.json +++ b/bindings/matrix-sdk-crypto-nodejs/package.json @@ -1,6 +1,6 @@ { "name": "@matrix-org/matrix-sdk-crypto-nodejs", - "version": "0.1.0", + "version": "0.1.0-beta.0", "main": "index.js", "types": "index.d.ts", "napi": { From 402d061d42565dda1e55052656425996a326a14f Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Tue, 12 Jul 2022 18:02:59 +0200 Subject: [PATCH 12/73] ci(crypto-nodejs): fixing path to npm package for publishing --- .github/workflows/release-crypto-nodejs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release-crypto-nodejs.yml b/.github/workflows/release-crypto-nodejs.yml index 6a65dbaf1..fd77dcd9a 100644 --- a/.github/workflows/release-crypto-nodejs.yml +++ b/.github/workflows/release-crypto-nodejs.yml @@ -113,4 +113,5 @@ jobs: - name: Publish to npmjs.com uses: JS-DevTools/npm-publish@v1 with: + package: ${{env.PKG_PATH}}/package.json token: ${{ secrets.NPM_TOKEN }} From a4f1c404f677569bc87938a4555053248c3c9dad Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Tue, 12 Jul 2022 19:28:59 +0200 Subject: [PATCH 13/73] ci(crypto-nodejs): set npm publish level to public --- .github/workflows/release-crypto-nodejs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release-crypto-nodejs.yml b/.github/workflows/release-crypto-nodejs.yml index fd77dcd9a..c18170a53 100644 --- a/.github/workflows/release-crypto-nodejs.yml +++ b/.github/workflows/release-crypto-nodejs.yml @@ -114,4 +114,5 @@ jobs: uses: JS-DevTools/npm-publish@v1 with: package: ${{env.PKG_PATH}}/package.json + access: public token: ${{ secrets.NPM_TOKEN }} From ec00af0bca5989741fd31b91e6e4ff610ed6cf99 Mon Sep 17 00:00:00 2001 From: Johannes Becker Date: Wed, 13 Jul 2022 10:11:43 +0200 Subject: [PATCH 14/73] refactor(appservice)!: Improve API and cleanup docs --- .../examples/appservice_autojoin.rs | 8 +- .../src/event_handler.rs | 14 + crates/matrix-sdk-appservice/src/lib.rs | 494 ++++-------------- .../matrix-sdk-appservice/src/registration.rs | 124 +++++ .../matrix-sdk-appservice/src/virtual_user.rs | 149 ++++++ crates/matrix-sdk-appservice/tests/tests.rs | 15 +- 6 files changed, 396 insertions(+), 408 deletions(-) create mode 100644 crates/matrix-sdk-appservice/src/registration.rs create mode 100644 crates/matrix-sdk-appservice/src/virtual_user.rs diff --git a/crates/matrix-sdk-appservice/examples/appservice_autojoin.rs b/crates/matrix-sdk-appservice/examples/appservice_autojoin.rs index 0964ef528..e1c295af6 100644 --- a/crates/matrix-sdk-appservice/examples/appservice_autojoin.rs +++ b/crates/matrix-sdk-appservice/examples/appservice_autojoin.rs @@ -31,7 +31,7 @@ pub async fn handle_room_member( error_if_user_not_in_use(error)?; } - let client = appservice.virtual_user_client(user_id.localpart()).await?; + let client = appservice.virtual_user(Some(user_id.localpart())).await?; client.join_room_by_id(room.room_id()).await?; } @@ -61,7 +61,9 @@ pub async fn main() -> Result<(), Box> { let appservice = AppService::new(homeserver_url, server_name, registration).await?; appservice.register_user_query(Box::new(|_, _| Box::pin(async { true }))).await; appservice - .register_event_handler_context(appservice.clone())? + .virtual_user(None) + .await? + .register_event_handler_context(appservice.clone()) .register_event_handler( move |event: OriginalSyncRoomMemberEvent, room: Room, @@ -69,7 +71,7 @@ pub async fn main() -> Result<(), Box> { handle_room_member(appservice, room, event) }, ) - .await?; + .await; let (host, port) = appservice.registration().get_host_and_port()?; appservice.run(host, port).await?; diff --git a/crates/matrix-sdk-appservice/src/event_handler.rs b/crates/matrix-sdk-appservice/src/event_handler.rs index 0e1d1a73c..7d86a5331 100644 --- a/crates/matrix-sdk-appservice/src/event_handler.rs +++ b/crates/matrix-sdk-appservice/src/event_handler.rs @@ -1,3 +1,17 @@ +// Copyright 2022 Famedly GmbH +// +// 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. + use std::{future::Future, pin::Pin, sync::Arc}; use matrix_sdk::locks::Mutex; diff --git a/crates/matrix-sdk-appservice/src/lib.rs b/crates/matrix-sdk-appservice/src/lib.rs index 5060f2b8e..f84e9ce70 100644 --- a/crates/matrix-sdk-appservice/src/lib.rs +++ b/crates/matrix-sdk-appservice/src/lib.rs @@ -17,12 +17,13 @@ //! The appservice crate aims to provide a batteries-included experience by //! being a thin wrapper around the [`matrix_sdk`]. That means that we //! -//! * ship with functionality to configure your webserver crate or simply run -//! the webserver for you -//! * receive and validate requests from the homeserver correctly -//! * allow calling the homeserver with proper virtual user identity assertion -//! * have consistent room state by leveraging matrix-sdk's state store -//! * provide E2EE support by leveraging matrix-sdk's crypto store +//! - [x] ship with functionality to configure your webserver crate or simply +//! run the webserver for you +//! - [x] receive and validate requests from the homeserver correctly +//! - [x] allow calling the homeserver with proper virtual user identity +//! assertion +//! - [x] have consistent room state by leveraging matrix-sdk's state store +//! - [ ] provide E2EE support by leveraging matrix-sdk's crypto store //! //! # Status //! @@ -31,10 +32,10 @@ //! //! # Registration //! -//! The crate relies on the registration being always in sync with the actual -//! registration used by the homeserver. That's because it's required for the -//! access tokens and because membership states for virtual users are determined -//! based on the registered namespace. +//! The crate relies on the appservice registration being always in sync with +//! the actual registration used by the homeserver. That's because it's required +//! for the access tokens and because membership states for virtual users are +//! determined based on the registered namespaces. //! //! **Note:** Non-exclusive registration namespaces are not yet supported and //! hence might lead to undefined behavior. @@ -65,9 +66,13 @@ //! ")?; //! //! let mut appservice = AppService::new(homeserver_url, server_name, registration).await?; -//! appservice.register_event_handler(|_ev: SyncRoomMemberEvent| async { -//! // do stuff -//! }); +//! appservice +//! .virtual_user(None) +//! .await? +//! .register_event_handler(|_ev: SyncRoomMemberEvent| async { +//! // do stuff +//! }) +//! .await; //! //! let (host, port) = appservice.registration().get_host_and_port()?; //! appservice.run(host, port).await?; @@ -80,285 +85,50 @@ //! //! [Application Service]: https://matrix.org/docs/spec/application_service/r0.1.2 //! [matrix-org/matrix-rust-sdk#228]: https://github.com/matrix-org/matrix-rust-sdk/issues/228 -//! [examples directory]: https://github.com/matrix-org/matrix-rust-sdk/tree/main/crates/matrix-sdk-appservice/examples +//! [examples directory]: https://github.com/matrix-org/matrix-rust-sdk/tree/master/matrix_sdk_appservice/examples -use std::{ - convert::{TryFrom, TryInto}, - fs::File, - future::Future, - ops::Deref, - path::PathBuf, - sync::Arc, -}; +use std::{convert::TryInto, sync::Arc}; use dashmap::DashMap; pub use error::Error; use event_handler::AppserviceFn; -use http::Uri; pub use matrix_sdk; #[doc(no_inline)] pub use matrix_sdk::ruma; -use matrix_sdk::{ - bytes::Bytes, - config::RequestConfig, - event_handler::{EventHandler, EventHandlerResult, SyncEvent}, - reqwest::Url, - Client, ClientBuildError, ClientBuilder, Session, -}; -use regex::Regex; +use matrix_sdk::{bytes::Bytes, reqwest::Url, Client, ClientBuilder}; use ruma::{ api::{ appservice::{ event::push_events, query::{query_room_alias::v1 as query_room, query_user_id::v1 as query_user}, - Registration, }, - client::{account::register, session::login, sync::sync_events, uiaa::UserIdentifier}, + client::{account::register, sync::sync_events}, }, assign, events::{room::member::MembershipState, AnyRoomEvent, AnyStateEvent}, - DeviceId, IdParseError, OwnedDeviceId, OwnedRoomId, OwnedServerName, UserId, + IdParseError, OwnedRoomId, OwnedServerName, }; -use serde::{de::DeserializeOwned, Deserialize}; +use serde::Deserialize; use tokio::task::JoinHandle; use tracing::{debug, info, warn}; mod error; pub mod event_handler; +pub mod registration; +pub mod virtual_user; mod webserver; +pub use registration::AppServiceRegistration; +use registration::NamespaceCache; +pub use virtual_user::VirtualUserBuilder; + pub type Result = std::result::Result; -pub type Host = String; -pub type Port = u16; const USER_KEY: &[u8] = b"appservice.users."; pub const USER_MEMBER: &[u8] = b"appservice.users.membership."; -/// Builder for a virtual user -#[derive(Debug)] -pub struct VirtualUserBuilder<'a> { - appservice: &'a AppService, - localpart: &'a str, - device_id: Option, - client_builder: ClientBuilder, - log_in: bool, - restored_session: Option, -} - -impl<'a> VirtualUserBuilder<'a> { - /// Create a new virtual user builder - /// # Arguments - /// - /// * `localpart` - The localpart of the virtual user - pub fn new(appservice: &'a AppService, localpart: &'a str) -> Self { - Self { - appservice, - localpart, - device_id: None, - client_builder: Client::builder(), - log_in: false, - restored_session: None, - } - } - - /// Set the device ID of the virtual user - pub fn device_id(mut self, device_id: Option) -> Self { - self.device_id = device_id; - self - } - - /// Sets the client builder to use for the virtual user - pub fn client_builder(mut self, client_builder: ClientBuilder) -> Self { - self.client_builder = client_builder; - self - } - - /// Log in as the virtual user - /// - /// In some cases it is necessary to log in as the virtual user, such as to - /// upload device keys - pub fn login(mut self) -> Self { - self.log_in = true; - self - } - - /// Restore a persisted session - /// - /// This is primarily useful if you enable - /// [`VirtualUserBuilder::login()`] and want to restore a session - /// from a previous run. - pub fn restored_session(mut self, session: Session) -> Self { - self.restored_session = Some(session); - self - } - - /// Build the virtual user - /// - /// # Errors - /// This function returns an error if an invalid localpart is provided. - pub async fn build(self) -> Result { - if let Some(client) = self.appservice.clients.get(self.localpart) { - return Ok(client.clone()); - } - - let user_id = UserId::parse_with_server_name(self.localpart, &self.appservice.server_name)?; - if !(self.appservice.user_id_is_in_namespace(&user_id) - || self.localpart == self.appservice.registration.sender_localpart) - { - warn!("Virtual client id '{user_id}' is not in the namespace") - } - - let mut builder = self.client_builder; - - if !self.log_in && self.localpart != self.appservice.registration.sender_localpart { - builder = builder.assert_identity(); - } - - let client = builder - .homeserver_url(self.appservice.homeserver_url.clone()) - .appservice_mode() - .build() - .await - .map_err(ClientBuildError::assert_valid_builder_args)?; - - let session = if let Some(session) = self.restored_session { - session - } else if self.log_in && self.localpart != self.appservice.registration.sender_localpart { - self.appservice - .create_session(self.localpart, self.device_id.as_ref().map(|v| v.as_ref()), None) - .await? - } else { - // Don’t log in - Session { - access_token: self.appservice.registration.as_token.clone(), - user_id: user_id.clone(), - device_id: self.device_id.unwrap_or_else(DeviceId::new), - } - }; - - client.restore_login(session).await?; - - self.appservice.clients.insert(self.localpart.to_owned(), client.clone()); - - Ok(client) - } -} - -/// AppService Registration -/// -/// Wrapper around [`Registration`] -#[derive(Debug, Clone)] -pub struct AppServiceRegistration { - inner: Registration, -} - -impl AppServiceRegistration { - /// Try to load registration from yaml string - /// - /// See the fields of [`Registration`] for the required format - pub fn try_from_yaml_str(value: impl AsRef) -> Result { - Ok(Self { inner: serde_yaml::from_str(value.as_ref())? }) - } - - /// Try to load registration from yaml file - /// - /// See the fields of [`Registration`] for the required format - pub fn try_from_yaml_file(path: impl Into) -> Result { - let file = File::open(path.into())?; - - Ok(Self { inner: serde_yaml::from_reader(file)? }) - } - - /// Get the host and port from the registration URL - /// - /// If no port is found it falls back to scheme defaults: 80 for http and - /// 443 for https - pub fn get_host_and_port(&self) -> Result<(Host, Port)> { - let uri = Uri::try_from(&self.inner.url)?; - - let host = uri.host().ok_or(Error::MissingRegistrationHost)?.to_owned(); - let port = match uri.port() { - Some(port) => Ok(port.as_u16()), - None => match uri.scheme_str() { - Some("http") => Ok(80), - Some("https") => Ok(443), - _ => Err(Error::MissingRegistrationPort), - }, - }?; - - Ok((host, port)) - } -} - -impl From for AppServiceRegistration { - fn from(value: Registration) -> Self { - Self { inner: value } - } -} - -impl Deref for AppServiceRegistration { - type Target = Registration; - - fn deref(&self) -> &Self::Target { - &self.inner - } -} - -/// Cache data for the registration namespaces. -#[derive(Debug, Clone)] -pub struct NamespaceCache { - /// List of user regexes in our namespace - users: Vec, - /// List of alias regexes in our namespace - #[allow(dead_code)] - aliases: Vec, - /// List of room id regexes in our namespace - #[allow(dead_code)] - rooms: Vec, -} - -impl NamespaceCache { - /// Creates a new registration cache from a [`Registration`] value - pub fn from_registration(registration: &Registration) -> Result { - let users = registration - .namespaces - .users - .iter() - .map(|user| Regex::new(&user.regex)) - .collect::, _>>()?; - let aliases = registration - .namespaces - .aliases - .iter() - .map(|user| Regex::new(&user.regex)) - .collect::, _>>()?; - let rooms = registration - .namespaces - .rooms - .iter() - .map(|user| Regex::new(&user.regex)) - .collect::, _>>()?; - Ok(NamespaceCache { users, aliases, rooms }) - } -} - type Localpart = String; -/// The `localpart` of the user associated with the application service via -/// `sender_localpart` in [`AppServiceRegistration`]. -/// -/// Dummy type for shared documentation -#[allow(dead_code)] -pub type MainUser = (); - -/// The application service may specify the virtual user to act as through use -/// of a user_id query string parameter on the request. The user specified in -/// the query string must be covered by one of the [`AppServiceRegistration`]'s -/// `users` namespaces. -/// -/// Dummy type for shared documentation -pub type VirtualUser = (); - /// AppService #[derive(Debug, Clone)] pub struct AppService { @@ -371,11 +141,13 @@ pub struct AppService { } impl AppService { - /// Create new AppService + /// Create a new AppService. /// - /// Also creates and caches a [`Client`] for the [`MainUser`]. - /// A default [`ClientBuilder`] is used, if you want to customize it - /// use [`with_client_builder()`][Self::with_client_builder] instead. + /// This will also construct a [`virtual_user()`][Self::virtual_user] for + /// the `sender_localpart` of the given registration. This virtual user can + /// be used to register an event handler for all incoming events. Other + /// virtual users only receive events if they're known to be a member of a + /// room. /// /// # Arguments /// @@ -399,7 +171,7 @@ impl AppService { } /// Same as [`new()`][Self::new] but lets you provide a [`ClientBuilder`] - /// for the [`Client`] + /// for the virtual user that gets constructed for the `sender_localpart`. pub async fn with_client_builder( homeserver_url: impl TryInto, server_name: impl TryInto, @@ -423,143 +195,56 @@ impl AppService { event_handler, }; - // we create and cache the [`MainUser`] by default appservice.virtual_user_builder(&sender_localpart).client_builder(builder).build().await?; Ok(appservice) } - /// Create a [`Client`] for the given [`VirtualUser`]'s `localpart` + /// Create a virtual user client. /// - /// Will create and return a [`Client`] that's configured to [assert the - /// identity] on all outgoing homeserver requests if `localpart` is - /// given. + /// Will create and return a client that's configured to [assert the + /// identity] on outgoing homeserver requests that need authentication. /// /// This method is a singleton that saves the client internally for re-use - /// based on the `localpart`. The cached [`Client`] can be retrieved either - /// by calling this method again or by calling - /// [`get_cached_client()`][Self::get_cached_client] which is non-async - /// convenience wrapper. + /// based on the `localpart`. The cached client can be retrieved by calling + /// this method again. /// /// Note that if you want to do actions like joining rooms with a virtual - /// user it needs to be registered first. `Self::register_virtual_user()` - /// can be used for that purpose. + /// user it needs to be registered first. + /// [`register_virtual_user()`][Self::register_virtual_user] can be used + /// for that purpose. /// /// # Arguments /// - /// * `localpart` - The localpart of the user we want assert our identity to + /// * `localpart` - Used for constructing the accordingly. If `None` is + /// given it uses the `sender_localpart` from the registration. /// /// [registration]: https://matrix.org/docs/spec/application_service/r0.1.2#registration /// [assert the identity]: https://matrix.org/docs/spec/application_service/r0.1.2#identity-assertion - pub async fn virtual_user_client(&self, localpart: impl AsRef) -> Result { - self.virtual_user_builder(localpart.as_ref()).build().await + pub async fn virtual_user(&self, localpart: Option<&str>) -> Result { + let localpart = localpart.unwrap_or_else(|| self.registration.sender_localpart.as_ref()); + self.virtual_user_builder(localpart).build().await } - /// Same as [`virtual_user_client()`][Self::virtual_user_client] but with - /// the ability to pass in a [`ClientBuilder`] + /// Same as [`virtual_user()`][Self::virtual_user] but with + /// the ability to pass in a [`ClientBuilder`]. /// /// Since this method is a singleton follow-up calls with different /// [`ClientBuilder`]s will be ignored. - pub async fn virtual_user_client_with_client_builder( + pub async fn virtual_user_with_client_builder( &self, - localpart: impl AsRef, + localpart: Option<&str>, builder: ClientBuilder, ) -> Result { - self.virtual_user_builder(localpart.as_ref()).client_builder(builder).build().await + let localpart = localpart.unwrap_or_else(|| self.registration.sender_localpart.as_ref()); + self.virtual_user_builder(localpart).client_builder(builder).build().await } + /// Create a new virtual user builder for the given `localpart`. pub fn virtual_user_builder<'a>(&'a self, localpart: &'a str) -> VirtualUserBuilder<'a> { VirtualUserBuilder::new(self, localpart) } - /// Create a session using appservice login for a virtual user. - async fn create_session( - &self, - user: impl AsRef, - device_id: Option<&str>, - initial_device_display_name: Option<&str>, - ) -> Result { - let homeserver = self.homeserver_url.clone(); - info!(homeserver = homeserver.as_str(), user = user.as_ref(), "Logging in as virtual user"); - - let login_info = login::v3::LoginInfo::ApplicationService( - login::v3::ApplicationService::new(UserIdentifier::UserIdOrLocalpart(user.as_ref())), - ); - - let request = assign!(login::v3::Request::new(login_info), { - device_id: device_id.map(|d| d.into()), - initial_device_display_name - }); - - let response = self - .get_cached_client(None)? - .send(request, Some(RequestConfig::short_retry().force_auth())) - .await?; - - Ok(Session { - access_token: response.access_token, - user_id: response.user_id, - device_id: response.device_id, - }) - } - - /// Get cached [`Client`] - /// - /// Will return the client for the given `localpart` if previously - /// constructed with [`virtual_user_client()`][Self::virtual_user_client] or - /// [`virtual_user_client_with_config()`][Self:: - /// virtual_user_client_with_client_builder]. - /// - /// If no `localpart` is given it assumes the [`MainUser`]'s `localpart`. If - /// no client for `localpart` is found it will return an Error. - pub fn get_cached_client(&self, localpart: Option<&str>) -> Result { - let localpart = localpart.unwrap_or_else(|| self.registration.sender_localpart.as_ref()); - - let entry = self.clients.get(localpart).ok_or(Error::NoClientForLocalpart)?; - - Ok(entry.value().clone()) - } - - /// Convenience wrapper around [`Client::register_event_handler()`] that - /// attaches the event handler to the [`MainUser`]'s [`Client`] - /// - /// Note that the event handler in the [`AppService`] context only triggers - /// [`join` room `timeline` events], so no state events or events from the - /// `invite`, `knock` or `leave` scope. The rationale behind that is - /// that incoming AppService transactions from the homeserver are not - /// necessarily bound to a specific user but can cover a multitude of - /// namespaces, and as such the AppService basically only "observes - /// joined rooms". Also currently homeservers only push PDUs to appservices, - /// no EDUs. There's the open [MSC2409] regarding supporting EDUs in the - /// future, though it seems to be planned to put EDUs into a different - /// JSON key than `events` to stay backwards compatible. - /// - /// [`join` room `timeline` events]: https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0sync - /// [MSC2409]: https://github.com/matrix-org/matrix-doc/pull/2409 - pub async fn register_event_handler(&self, handler: H) -> Result<&Self> - where - Ev: SyncEvent + DeserializeOwned + Send + 'static, - H: EventHandler, - ::Output: EventHandlerResult, - { - let client = self.get_cached_client(None)?; - client.register_event_handler(handler).await; - - Ok(self) - } - - /// Convenience wrapper around [`Client::register_event_handler_context`] - /// attaches the event handler context to the [`MainUser`]'s [`Client`]. - pub fn register_event_handler_context(&self, ctx: T) -> Result<&Self> - where - T: Clone + Send + Sync + 'static, - { - let client = self.get_cached_client(None)?; - client.register_event_handler_context(ctx); - - Ok(self) - } - /// Register a responder for queries about the existence of a user with a /// given mxid. /// @@ -605,12 +290,12 @@ impl AppService { } /// Register a virtual user by sending a [`register::v3::Request`] to the - /// homeserver + /// homeserver. /// /// # Arguments /// /// * `localpart` - The localpart of the user to register. Must be covered - /// by the namespaces in the [`Registration`] in order to succeed. + /// by the namespaces in the registration in order to succeed. /// /// # Returns /// This function may return a UIAA response, which should be checked for @@ -624,7 +309,7 @@ impl AppService { login_type: Some(®ister::LoginType::ApplicationService), }); - let client = self.get_cached_client(None)?; + let client = self.virtual_user(None).await?; client.register(request).await?; self.set_user_registered(localpart.as_ref()).await?; @@ -633,7 +318,7 @@ impl AppService { /// Add the given localpart to the database of registered localparts. async fn set_user_registered(&self, localpart: impl AsRef) -> Result<()> { - let client = self.get_cached_client(None)?; + let client = self.virtual_user(None).await?; client .store() .set_custom_value( @@ -646,7 +331,7 @@ impl AppService { /// Get whether a localpart is listed in the database as registered. async fn is_user_registered(&self, localpart: impl AsRef) -> Result { - let client = self.get_cached_client(None)?; + let client = self.virtual_user(None).await?; let key = [USER_KEY, localpart.as_ref().as_bytes()].concat(); let store = client.store().get_custom_value(&key).await?; let registered = @@ -654,14 +339,12 @@ impl AppService { Ok(registered) } - /// Get the AppService [registration] - /// - /// [registration]: https://matrix.org/docs/spec/application_service/r0.1.2#registration + /// Get the [`AppServiceRegistration`]. pub fn registration(&self) -> &AppServiceRegistration { &self.registration } - /// Compare the given `hs_token` against `registration.hs_token` + /// Compare the given `hs_token` against the registration's `hs_token`. /// /// Returns `true` if the tokens match, `false` otherwise. pub fn compare_hs_token(&self, hs_token: impl AsRef) -> bool { @@ -680,12 +363,16 @@ impl AppService { false } - /// Returns a [`warp::Filter`] to be used as [`warp::serve()`] route + /// Returns a [`warp::Filter`] to be used as [`warp::serve()`] route. /// /// Note that if you handle any of the [application-service-specific /// routes], including the legacy routes, you will break the appservice /// functionality. /// + /// Hint: [`warp::Filter`]s can be converted to an `hyper::Service` using + /// [`warp::service`], which allows using it with tower-compatible + /// frameworks such as axum. + /// /// [application-service-specific routes]: https://spec.matrix.org/unstable/application-service-api/#legacy-routes pub fn warp_filter(&self) -> warp::filters::BoxedFilter<(impl warp::Reply,)> { webserver::warp_filter(self.clone()) @@ -699,7 +386,7 @@ impl AppService { &self, transaction: push_events::v1::IncomingRequest, ) -> Result<()> { - let client = self.get_cached_client(None)?; + let sender_localpart_client = self.virtual_user(None).await?; // Find membership events affecting members in our namespace, and update // membership accordingly @@ -712,7 +399,7 @@ impl AppService { continue; } let localpart = event.state_key().localpart(); - client + sender_localpart_client .store() .set_custom_value( &[USER_MEMBER, event.room_id().as_bytes(), b".", localpart.as_bytes()].concat(), @@ -730,24 +417,27 @@ impl AppService { // Spawn a task for each client that constructs and pushes a sync event let mut tasks: Vec> = Vec::new(); let transaction = Arc::new(transaction); - for virt_client in self.clients.iter() { - let client = client.clone(); - let virt_client = virt_client.clone(); + for virtual_user_client in self.clients.iter() { + let client = sender_localpart_client.clone(); + let virtual_user_client = virtual_user_client.clone(); let transaction = transaction.clone(); - let appserv_uid = self.registration.sender_localpart.clone(); + let sender_localpart = self.registration.sender_localpart.clone(); let task = tokio::spawn(async move { - let user_id = match virt_client.user_id() { + let virtual_user_localpart = match virtual_user_client.user_id() { Some(user_id) => user_id.localpart(), // The client is not logged in, skipping None => return Ok(()), }; let mut response = sync_events::v3::Response::new(transaction.txn_id.to_string()); - // Clients expect events to be grouped per room, where the group also denotes - // what the client's membership of the given room is. We take the - // all the events in the transaction and sort them into appropriate - // groups, falling back to a membership of "join" if it's unknown. + // Clients expect events to be grouped per room, where the + // group also denotes what the client's membership of the given + // room is. We take all the events in the transaction and sort + // them into appropriate groups. + // + // We special-case the `sender_localpart` user which receives all events and + // by falling back to a membership of "join" if it's unknown. for raw_event in &transaction.events { let room_id = match raw_event.deserialize_as::()?.room_id { Some(room_id) => room_id, @@ -756,11 +446,15 @@ impl AppService { continue; } }; - let key = &[USER_MEMBER, room_id.as_bytes(), b".", user_id.as_bytes()].concat(); + let key = + &[USER_MEMBER, room_id.as_bytes(), b".", virtual_user_localpart.as_bytes()] + .concat(); let membership = match client.store().get_custom_value(key).await? { Some(value) => String::from_utf8(value).ok().map(MembershipState::from), - // Assume the appservice is in every known room - None if user_id == appserv_uid => Some(MembershipState::Join), + // Assume the `sender_localpart` user is in every known room + None if virtual_user_localpart == sender_localpart => { + Some(MembershipState::Join) + } None => None, }; @@ -780,10 +474,10 @@ impl AppService { response.rooms.invite.entry(room_id).or_default(); } Some(unknown) => debug!("Unknown membership type: {unknown}"), - None => debug!("Assuming {user_id} is not in {room_id}"), + None => debug!("Assuming {virtual_user_localpart} is not in {room_id}"), } } - virt_client.receive_transaction(&transaction.txn_id, response).await?; + virtual_user_client.receive_transaction(&transaction.txn_id, response).await?; Ok::<_, Error>(()) }); @@ -798,10 +492,10 @@ impl AppService { } /// Convenience method that runs an http server depending on the selected - /// server feature + /// server feature. /// /// This is a blocking call that tries to listen on the provided host and - /// port + /// port. pub async fn run(&self, host: impl Into, port: impl Into) -> Result<()> { let host = host.into(); let port = port.into(); diff --git a/crates/matrix-sdk-appservice/src/registration.rs b/crates/matrix-sdk-appservice/src/registration.rs new file mode 100644 index 000000000..2c581d28f --- /dev/null +++ b/crates/matrix-sdk-appservice/src/registration.rs @@ -0,0 +1,124 @@ +// Copyright 2022 Famedly GmbH +// +// 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. + +//! AppService Registration. + +use std::{convert::TryFrom, fs::File, ops::Deref, path::PathBuf}; + +use http::Uri; +use regex::Regex; +use ruma::api::appservice::Registration; + +use crate::{Error, Result}; + +pub type Host = String; +pub type Port = u16; + +/// AppService Registration +/// +/// Wrapper around [`Registration`]. See also . +#[derive(Debug, Clone)] +pub struct AppServiceRegistration { + inner: Registration, +} + +impl AppServiceRegistration { + /// Try to load registration from yaml string + /// + /// See the fields of [`Registration`] for the required format + pub fn try_from_yaml_str(value: impl AsRef) -> Result { + Ok(Self { inner: serde_yaml::from_str(value.as_ref())? }) + } + + /// Try to load registration from yaml file + /// + /// See the fields of [`Registration`] for the required format + pub fn try_from_yaml_file(path: impl Into) -> Result { + let file = File::open(path.into())?; + + Ok(Self { inner: serde_yaml::from_reader(file)? }) + } + + /// Get the host and port from the registration URL + /// + /// If no port is found it falls back to scheme defaults: 80 for http and + /// 443 for https + pub fn get_host_and_port(&self) -> Result<(Host, Port)> { + let uri = Uri::try_from(&self.inner.url)?; + + let host = uri.host().ok_or(Error::MissingRegistrationHost)?.to_owned(); + let port = match uri.port() { + Some(port) => Ok(port.as_u16()), + None => match uri.scheme_str() { + Some("http") => Ok(80), + Some("https") => Ok(443), + _ => Err(Error::MissingRegistrationPort), + }, + }?; + + Ok((host, port)) + } +} + +impl From for AppServiceRegistration { + fn from(value: Registration) -> Self { + Self { inner: value } + } +} + +impl Deref for AppServiceRegistration { + type Target = Registration; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +/// Cache data for the registration namespaces. +#[derive(Debug, Clone)] +pub struct NamespaceCache { + /// List of user regexes in our namespace + pub(crate) users: Vec, + /// List of alias regexes in our namespace + #[allow(dead_code)] + aliases: Vec, + /// List of room id regexes in our namespace + #[allow(dead_code)] + rooms: Vec, +} + +impl NamespaceCache { + /// Creates a new registration cache from a [`Registration`] value + pub fn from_registration(registration: &Registration) -> Result { + let users = registration + .namespaces + .users + .iter() + .map(|user| Regex::new(&user.regex)) + .collect::, _>>()?; + let aliases = registration + .namespaces + .aliases + .iter() + .map(|user| Regex::new(&user.regex)) + .collect::, _>>()?; + let rooms = registration + .namespaces + .rooms + .iter() + .map(|user| Regex::new(&user.regex)) + .collect::, _>>()?; + Ok(NamespaceCache { users, aliases, rooms }) + } +} diff --git a/crates/matrix-sdk-appservice/src/virtual_user.rs b/crates/matrix-sdk-appservice/src/virtual_user.rs new file mode 100644 index 000000000..ec49e61c9 --- /dev/null +++ b/crates/matrix-sdk-appservice/src/virtual_user.rs @@ -0,0 +1,149 @@ +// Copyright 2022 Famedly GmbH +// +// 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. + +//! Virtual users. + +use matrix_sdk::{config::RequestConfig, Client, ClientBuildError, ClientBuilder, Session}; +use ruma::{ + api::client::{session::login, uiaa::UserIdentifier}, + assign, DeviceId, OwnedDeviceId, UserId, +}; +use tracing::warn; + +use crate::{AppService, Result}; + +/// Builder for a virtual user +#[derive(Debug)] +pub struct VirtualUserBuilder<'a> { + appservice: &'a AppService, + localpart: &'a str, + device_id: Option, + client_builder: ClientBuilder, + log_in: bool, + restored_session: Option, +} + +impl<'a> VirtualUserBuilder<'a> { + /// Create a new virtual user builder + /// # Arguments + /// + /// * `localpart` - The localpart of the virtual user + pub fn new(appservice: &'a AppService, localpart: &'a str) -> Self { + Self { + appservice, + localpart, + device_id: None, + client_builder: Client::builder(), + log_in: false, + restored_session: None, + } + } + + /// Set the device ID of the virtual user + pub fn device_id(mut self, device_id: Option) -> Self { + self.device_id = device_id; + self + } + + /// Sets the client builder to use for the virtual user + pub fn client_builder(mut self, client_builder: ClientBuilder) -> Self { + self.client_builder = client_builder; + self + } + + /// Log in as the virtual user + /// + /// In some cases it is necessary to log in as the virtual user, such as to + /// upload device keys + pub fn login(mut self) -> Self { + self.log_in = true; + self + } + + /// Restore a persisted session + /// + /// This is primarily useful if you enable + /// [`VirtualUserBuilder::login()`] and want to restore a session + /// from a previous run. + pub fn restored_session(mut self, session: Session) -> Self { + self.restored_session = Some(session); + self + } + + /// Build the virtual user + /// + /// # Errors + /// This function returns an error if an invalid localpart is provided. + pub async fn build(self) -> Result { + if let Some(client) = self.appservice.clients.get(self.localpart) { + return Ok(client.clone()); + } + + let user_id = UserId::parse_with_server_name(self.localpart, &self.appservice.server_name)?; + if !(self.appservice.user_id_is_in_namespace(&user_id) + || self.localpart == self.appservice.registration.sender_localpart) + { + warn!("Virtual client id '{user_id}' is not in the namespace") + } + + let mut builder = self.client_builder; + + if !self.log_in && self.localpart != self.appservice.registration.sender_localpart { + builder = builder.assert_identity(); + } + + let client = builder + .homeserver_url(self.appservice.homeserver_url.clone()) + .appservice_mode() + .build() + .await + .map_err(ClientBuildError::assert_valid_builder_args)?; + + let session = if let Some(session) = self.restored_session { + session + } else if self.log_in && self.localpart != self.appservice.registration.sender_localpart { + let login_info = + login::v3::LoginInfo::ApplicationService(login::v3::ApplicationService::new( + UserIdentifier::UserIdOrLocalpart(self.localpart), + )); + + let request = assign!(login::v3::Request::new(login_info), { + device_id: self.device_id.as_ref().map(|v| v.as_ref()), + initial_device_display_name: None, + }); + + let response = + client.send(request, Some(RequestConfig::short_retry().force_auth())).await?; + + Session { + access_token: response.access_token, + user_id: response.user_id, + device_id: response.device_id, + } + } else { + // Don’t log in + Session { + access_token: self.appservice.registration.as_token.clone(), + user_id: user_id.clone(), + device_id: self.device_id.unwrap_or_else(DeviceId::new), + } + }; + + client.restore_login(session).await?; + + self.appservice.clients.insert(self.localpart.to_owned(), client.clone()); + + Ok(client) + } +} diff --git a/crates/matrix-sdk-appservice/tests/tests.rs b/crates/matrix-sdk-appservice/tests/tests.rs index 61180ed97..fc74555a5 100644 --- a/crates/matrix-sdk-appservice/tests/tests.rs +++ b/crates/matrix-sdk-appservice/tests/tests.rs @@ -125,6 +125,8 @@ async fn test_put_transaction_with_repeating_txn_id() -> Result<()> { #[allow(clippy::mutex_atomic)] let on_state_member = Arc::new(Mutex::new(false)); appservice + .virtual_user(None) + .await? .register_event_handler({ let on_state_member = on_state_member.clone(); move |_ev: OriginalSyncRoomMemberEvent| { @@ -132,7 +134,7 @@ async fn test_put_transaction_with_repeating_txn_id() -> Result<()> { future::ready(()) } }) - .await?; + .await; let status = warp::test::request() .method("PUT") @@ -279,6 +281,8 @@ async fn test_event_handler() -> Result<()> { #[allow(clippy::mutex_atomic)] let on_state_member = Arc::new(Mutex::new(false)); appservice + .virtual_user(None) + .await? .register_event_handler({ let on_state_member = on_state_member.clone(); move |_ev: OriginalSyncRoomMemberEvent| { @@ -286,7 +290,7 @@ async fn test_event_handler() -> Result<()> { future::ready(()) } }) - .await?; + .await; let uri = "/_matrix/app/v1/transactions/1?access_token=hs_token"; @@ -365,7 +369,8 @@ async fn test_appservice_on_sub_path() -> Result<()> { }; let members = appservice - .get_cached_client(None)? + .virtual_user(None) + .await? .get_room(room_id) .expect("Expected room to be available") .members_no_sync() @@ -455,8 +460,8 @@ async fn test_receive_transaction() -> Result<()> { ]; let appservice = appservice(None, None).await?; - let alice = appservice.virtual_user_client("_appservice_alice").await?; - let bob = appservice.virtual_user_client("_appservice_bob").await?; + let alice = appservice.virtual_user(Some("_appservice_alice")).await?; + let bob = appservice.virtual_user(Some("_appservice_bob")).await?; appservice .receive_transaction(push_events::v1::IncomingRequest::new("dontcare".into(), json)) .await?; From c10961f06847fa315bc6c00170e26afb94a48d71 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Thu, 30 Jun 2022 17:29:35 +0300 Subject: [PATCH 15/73] chore: sdk-ffi apple - remove mac catalyst target support --- bindings/apple/build_xcframework.sh | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/bindings/apple/build_xcframework.sh b/bindings/apple/build_xcframework.sh index c0d2919e9..0199fceef 100755 --- a/bindings/apple/build_xcframework.sh +++ b/bindings/apple/build_xcframework.sh @@ -27,10 +27,6 @@ cargo build -p matrix-sdk-ffi ${REL_FLAG} --target "x86_64-apple-darwin" 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 @@ -45,12 +41,6 @@ lipo -create \ "${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} @@ -75,8 +65,6 @@ xcodebuild -create-xcframework \ -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" @@ -85,5 +73,4 @@ xcodebuild -create-xcframework \ 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 From a73b104c59d31a6915766cf7dbfe0d1f9e43e0f5 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Thu, 30 Jun 2022 17:30:37 +0300 Subject: [PATCH 16/73] chore: sdk-ffi apple - rename `modulemap` to `module.modulemap` as per xcframework specifications --- bindings/apple/build_xcframework.sh | 5 ++++- bindings/apple/debug_build_xcframework.sh | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/bindings/apple/build_xcframework.sh b/bindings/apple/build_xcframework.sh index 0199fceef..d98438747 100755 --- a/bindings/apple/build_xcframework.sh +++ b/bindings/apple/build_xcframework.sh @@ -49,7 +49,10 @@ uniffi-bindgen generate "${SRC_ROOT}/bindings/matrix-sdk-ffi/src/api.udl" --lang HEADERS_DIR=${GENERATED_DIR}/headers mkdir -p ${HEADERS_DIR} -mv ${GENERATED_DIR}/*.h ${GENERATED_DIR}/*.modulemap ${HEADERS_DIR} +mv ${GENERATED_DIR}/*.h ${HEADERS_DIR} + +# Rename and move modulemap to the right place +mv ${GENERATED_DIR}/*.modulemap ${HEADERS_DIR}/module.modulemap SWIFT_DIR="${GENERATED_DIR}/swift" mkdir -p ${SWIFT_DIR} diff --git a/bindings/apple/debug_build_xcframework.sh b/bindings/apple/debug_build_xcframework.sh index 975e62cf7..9639b74a0 100755 --- a/bindings/apple/debug_build_xcframework.sh +++ b/bindings/apple/debug_build_xcframework.sh @@ -39,7 +39,10 @@ uniffi-bindgen generate "${SRC_ROOT}/bindings/matrix-sdk-ffi/src/api.udl" --lang HEADERS_DIR=${GENERATED_DIR}/headers mkdir -p ${HEADERS_DIR} -mv ${GENERATED_DIR}/*.h ${GENERATED_DIR}/*.modulemap ${HEADERS_DIR} +mv ${GENERATED_DIR}/*.h ${HEADERS_DIR} + +# Rename and move modulemap to the right place +mv ${GENERATED_DIR}/*.modulemap ${HEADERS_DIR}/module.modulemap SWIFT_DIR="${GENERATED_DIR}/swift" mkdir -p ${SWIFT_DIR} From c61dbb657ebeca2775ea383a90ba18117a5e67cd Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Thu, 30 Jun 2022 17:31:58 +0300 Subject: [PATCH 17/73] chore: sdk-ffi apple - drop sample project deployment target to iOS 15 and macOS 12, disable catalyst. --- bindings/apple/MatrixRustSDK.xcodeproj/project.pbxproj | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bindings/apple/MatrixRustSDK.xcodeproj/project.pbxproj b/bindings/apple/MatrixRustSDK.xcodeproj/project.pbxproj index 38cc51514..4021f5c5d 100644 --- a/bindings/apple/MatrixRustSDK.xcodeproj/project.pbxproj +++ b/bindings/apple/MatrixRustSDK.xcodeproj/project.pbxproj @@ -307,7 +307,8 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.2; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MACOSX_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -362,7 +363,8 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.2; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MACOSX_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; @@ -397,7 +399,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = org.matrix.MatrixRustSDK; PRODUCT_NAME = "$(TARGET_NAME)"; - SUPPORTS_MACCATALYST = YES; + SUPPORTS_MACCATALYST = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = "MatrixRustSDK/MatrixRustSDK-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -431,7 +433,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = org.matrix.MatrixRustSDK; PRODUCT_NAME = "$(TARGET_NAME)"; - SUPPORTS_MACCATALYST = YES; + SUPPORTS_MACCATALYST = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = "MatrixRustSDK/MatrixRustSDK-Bridging-Header.h"; SWIFT_VERSION = 5.0; From 399bbc25e990a565bfc1a67dbbc4e195dd6a5e88 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Thu, 30 Jun 2022 17:32:27 +0300 Subject: [PATCH 18/73] chore: sdk-ffi apple - run the CI build script from the Xcode project and only for the active architecture --- .github/workflows/bindings_ci.yml | 3 -- .../xcschemes/MatrixRustSDK.xcscheme | 30 ++++++++------ bindings/apple/debug_build_xcframework.sh | 39 +++++++++++++------ 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/.github/workflows/bindings_ci.yml b/.github/workflows/bindings_ci.yml index 30fcefc11..1768109a7 100644 --- a/.github/workflows/bindings_ci.yml +++ b/.github/workflows/bindings_ci.yml @@ -161,9 +161,6 @@ jobs: # 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 \ diff --git a/bindings/apple/MatrixRustSDK.xcodeproj/xcshareddata/xcschemes/MatrixRustSDK.xcscheme b/bindings/apple/MatrixRustSDK.xcodeproj/xcshareddata/xcschemes/MatrixRustSDK.xcscheme index 6644a0efe..9d3179964 100644 --- a/bindings/apple/MatrixRustSDK.xcodeproj/xcshareddata/xcschemes/MatrixRustSDK.xcscheme +++ b/bindings/apple/MatrixRustSDK.xcodeproj/xcshareddata/xcschemes/MatrixRustSDK.xcscheme @@ -1,10 +1,28 @@ + version = "1.7"> + + + + + + + + + + - - - - Date: Fri, 1 Jul 2022 07:39:01 +0300 Subject: [PATCH 19/73] chore: sdk-ffi apple - try building the framework on x86_64 outside of Xcode --- .github/workflows/bindings_ci.yml | 3 +++ .../xcshareddata/xcschemes/MatrixRustSDK.xcscheme | 2 +- bindings/apple/debug_build_xcframework.sh | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/bindings_ci.yml b/.github/workflows/bindings_ci.yml index 1768109a7..0798ef17c 100644 --- a/.github/workflows/bindings_ci.yml +++ b/.github/workflows/bindings_ci.yml @@ -161,6 +161,9 @@ jobs: # 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 x86_64 ci + - name: Run XCTests run: | xcodebuild test \ diff --git a/bindings/apple/MatrixRustSDK.xcodeproj/xcshareddata/xcschemes/MatrixRustSDK.xcscheme b/bindings/apple/MatrixRustSDK.xcodeproj/xcshareddata/xcschemes/MatrixRustSDK.xcscheme index 9d3179964..fe527d24f 100644 --- a/bindings/apple/MatrixRustSDK.xcodeproj/xcshareddata/xcschemes/MatrixRustSDK.xcscheme +++ b/bindings/apple/MatrixRustSDK.xcodeproj/xcshareddata/xcschemes/MatrixRustSDK.xcscheme @@ -10,7 +10,7 @@ ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction"> + scriptText = "#PATH=~/.cargo/bin:${PATH} echo $ARCHS #sh $PROJECT_DIR/debug_build_xcframework.sh "$ARCHS" CI "> Date: Wed, 13 Jul 2022 17:16:12 +0200 Subject: [PATCH 20/73] feat(appservice): Add method to get virtual user map --- crates/matrix-sdk-appservice/src/lib.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/crates/matrix-sdk-appservice/src/lib.rs b/crates/matrix-sdk-appservice/src/lib.rs index f84e9ce70..51592ec34 100644 --- a/crates/matrix-sdk-appservice/src/lib.rs +++ b/crates/matrix-sdk-appservice/src/lib.rs @@ -85,7 +85,7 @@ //! //! [Application Service]: https://matrix.org/docs/spec/application_service/r0.1.2 //! [matrix-org/matrix-rust-sdk#228]: https://github.com/matrix-org/matrix-rust-sdk/issues/228 -//! [examples directory]: https://github.com/matrix-org/matrix-rust-sdk/tree/master/matrix_sdk_appservice/examples +//! [examples directory]: https://github.com/matrix-org/matrix-rust-sdk/tree/main/crates/matrix-sdk-appservice/examples use std::{convert::TryInto, sync::Arc}; @@ -216,8 +216,8 @@ impl AppService { /// /// # Arguments /// - /// * `localpart` - Used for constructing the accordingly. If `None` is - /// given it uses the `sender_localpart` from the registration. + /// * `localpart` - Used for constructing the virtual user accordingly. If + /// `None` is given it uses the `sender_localpart` from the registration. /// /// [registration]: https://matrix.org/docs/spec/application_service/r0.1.2#registration /// [assert the identity]: https://matrix.org/docs/spec/application_service/r0.1.2#identity-assertion @@ -245,6 +245,11 @@ impl AppService { VirtualUserBuilder::new(self, localpart) } + /// Get the map containing all constructed virtual user clients. + pub fn virtual_users(&self) -> Arc> { + self.clients.clone() + } + /// Register a responder for queries about the existence of a user with a /// given mxid. /// @@ -491,8 +496,7 @@ impl AppService { Ok(()) } - /// Convenience method that runs an http server depending on the selected - /// server feature. + /// Convenience method that runs an http server. /// /// This is a blocking call that tries to listen on the provided host and /// port. From 529bdc8e0a63ff64090e5b501cc66b3892490fde Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Wed, 13 Jul 2022 18:23:42 +0200 Subject: [PATCH 21/73] refactor: Remove unused optional dependencies --- crates/matrix-sdk-base/Cargo.toml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/crates/matrix-sdk-base/Cargo.toml b/crates/matrix-sdk-base/Cargo.toml index 7c6834753..ef9bd65f7 100644 --- a/crates/matrix-sdk-base/Cargo.toml +++ b/crates/matrix-sdk-base/Cargo.toml @@ -27,22 +27,17 @@ testing = ["http"] [dependencies] async-stream = "0.3.3" async-trait = "0.1.53" -chacha20poly1305 = { version = "0.9.0", optional = true } dashmap = "5.2.0" futures-channel = "0.3.21" futures-core = "0.3.21" futures-util = { version = "0.3.21", default-features = false } -hmac = { version = "0.12.1", optional = true } http = { version = "0.2.6", optional = true } lru = "0.7.5" matrix-sdk-common = { version = "0.5.0", path = "../matrix-sdk-common" } matrix-sdk-crypto = { version = "0.5.0", path = "../matrix-sdk-crypto", optional = true } once_cell = "1.10.0" -pbkdf2 = { version = "0.11.0", default-features = false, optional = true } -rand = { version = "0.8.5", optional = true } serde = { version = "1.0.136", features = ["rc"] } serde_json = "1.0.79" -sha2 = { version = "0.10.2", optional = true } thiserror = "1.0.30" tracing = "0.1.34" zeroize = { version = "1.3.0", features = ["zeroize_derive"] } From 3c5f30d41e850dad7e00caadf9e2d64e9c8eb2e5 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Wed, 13 Jul 2022 18:08:03 +0200 Subject: [PATCH 22/73] refactor: Remove implicit features for optional dependencies Consistently use `dep:` syntax for optional dependencies so they don't implicitly act as features of their own. --- bindings/matrix-sdk-crypto-nodejs/Cargo.toml | 2 +- crates/matrix-sdk-base/Cargo.toml | 6 +++--- crates/matrix-sdk-crypto/Cargo.toml | 6 +++--- crates/matrix-sdk-indexeddb/Cargo.toml | 2 +- crates/matrix-sdk-qrcode/Cargo.toml | 2 +- crates/matrix-sdk-sled/Cargo.toml | 12 ++++++++---- crates/matrix-sdk-store-encryption/Cargo.toml | 2 +- crates/matrix-sdk/Cargo.toml | 10 +++++----- 8 files changed, 23 insertions(+), 19 deletions(-) diff --git a/bindings/matrix-sdk-crypto-nodejs/Cargo.toml b/bindings/matrix-sdk-crypto-nodejs/Cargo.toml index 8fc02a806..bfe122f7e 100644 --- a/bindings/matrix-sdk-crypto-nodejs/Cargo.toml +++ b/bindings/matrix-sdk-crypto-nodejs/Cargo.toml @@ -22,7 +22,7 @@ crate-type = ["cdylib"] default = [] qrcode = ["matrix-sdk-crypto/qrcode"] docsrs = [] -tracing = ["tracing-subscriber"] +tracing = ["dep:tracing-subscriber"] [dependencies] matrix-sdk-crypto = { version = "0.5.0", path = "../../crates/matrix-sdk-crypto" } diff --git a/crates/matrix-sdk-base/Cargo.toml b/crates/matrix-sdk-base/Cargo.toml index ef9bd65f7..df9f29462 100644 --- a/crates/matrix-sdk-base/Cargo.toml +++ b/crates/matrix-sdk-base/Cargo.toml @@ -17,12 +17,12 @@ rustdoc-args = ["--cfg", "docsrs"] [features] default = [] -e2e-encryption = ["matrix-sdk-crypto"] -qrcode = ["matrix-sdk-crypto/qrcode"] +e2e-encryption = ["dep:matrix-sdk-crypto"] +qrcode = ["matrix-sdk-crypto?/qrcode"] experimental-timeline = [] # helpers for testing features build upon this -testing = ["http"] +testing = ["dep:http"] [dependencies] async-stream = "0.3.3" diff --git a/crates/matrix-sdk-crypto/Cargo.toml b/crates/matrix-sdk-crypto/Cargo.toml index 03221c856..21672e48f 100644 --- a/crates/matrix-sdk-crypto/Cargo.toml +++ b/crates/matrix-sdk-crypto/Cargo.toml @@ -17,12 +17,12 @@ rustdoc-args = ["--cfg", "docsrs"] [features] default = [] -qrcode = ["matrix-sdk-qrcode"] -backups_v1 = ["olm-rs", "bs58"] +qrcode = ["dep:matrix-sdk-qrcode"] +backups_v1 = ["dep:olm-rs", "dep:bs58"] docsrs = [] # Testing helpers for implementations based upon this -testing = ["http"] +testing = ["dep:http"] [dependencies] aes = "0.8.1" diff --git a/crates/matrix-sdk-indexeddb/Cargo.toml b/crates/matrix-sdk-indexeddb/Cargo.toml index ab70fa6af..5703b5816 100644 --- a/crates/matrix-sdk-indexeddb/Cargo.toml +++ b/crates/matrix-sdk-indexeddb/Cargo.toml @@ -15,7 +15,7 @@ rustdoc-args = ["--cfg", "docsrs"] [features] default = ["e2e-encryption"] -e2e-encryption = ["matrix-sdk-base/e2e-encryption", "matrix-sdk-crypto"] +e2e-encryption = ["matrix-sdk-base/e2e-encryption", "dep:matrix-sdk-crypto"] experimental-timeline = ["matrix-sdk-base/experimental-timeline"] diff --git a/crates/matrix-sdk-qrcode/Cargo.toml b/crates/matrix-sdk-qrcode/Cargo.toml index 8823bff77..350ebd05d 100644 --- a/crates/matrix-sdk-qrcode/Cargo.toml +++ b/crates/matrix-sdk-qrcode/Cargo.toml @@ -17,7 +17,7 @@ rustdoc-args = ["--cfg", "docsrs"] [features] default = ["decode_image"] -decode_image = ["image", "rqrr", "qrcode/image", "qrcode/svg"] +decode_image = ["dep:image", "dep:rqrr", "qrcode/image", "qrcode/svg"] [dependencies] base64 = "0.13.0" diff --git a/crates/matrix-sdk-sled/Cargo.toml b/crates/matrix-sdk-sled/Cargo.toml index 90097c2ed..0ba6814b1 100644 --- a/crates/matrix-sdk-sled/Cargo.toml +++ b/crates/matrix-sdk-sled/Cargo.toml @@ -16,12 +16,16 @@ rustdoc-args = ["--cfg", "docsrs"] [features] default = ["state-store"] -state-store = ["matrix-sdk-base"] +state-store = ["dep:matrix-sdk-base"] crypto-store = [ - "matrix-sdk-crypto", - "matrix-sdk-base/e2e-encryption", + "dep:matrix-sdk-base", + "dep:matrix-sdk-crypto", + "matrix-sdk-base?/e2e-encryption", +] +experimental-timeline = [ + "dep:matrix-sdk-base", + "matrix-sdk-base?/experimental-timeline", ] -experimental-timeline = ["matrix-sdk-base/experimental-timeline"] [dependencies] async-stream = "0.3.3" diff --git a/crates/matrix-sdk-store-encryption/Cargo.toml b/crates/matrix-sdk-store-encryption/Cargo.toml index 935999454..9bc333224 100644 --- a/crates/matrix-sdk-store-encryption/Cargo.toml +++ b/crates/matrix-sdk-store-encryption/Cargo.toml @@ -11,7 +11,7 @@ rust-version = "1.60" rustdoc-args = ["--cfg", "docsrs"] [features] -js = ["getrandom/js"] +js = ["dep:getrandom", "getrandom?/js"] [dependencies] blake3 = "1.3.1" diff --git a/crates/matrix-sdk/Cargo.toml b/crates/matrix-sdk/Cargo.toml index b8421c629..7c2c6fe05 100644 --- a/crates/matrix-sdk/Cargo.toml +++ b/crates/matrix-sdk/Cargo.toml @@ -28,18 +28,18 @@ e2e-encryption = [ "matrix-sdk-indexeddb?/e2e-encryption", # activate on indexeddb if given ] -sled = ["matrix-sdk-sled/state-store"] -indexeddb = ["matrix-sdk-indexeddb"] +sled = ["dep:matrix-sdk-sled", "matrix-sdk-sled?/state-store"] +indexeddb = ["dep:matrix-sdk-indexeddb"] qrcode = ["e2e-encryption", "matrix-sdk-base/qrcode"] markdown = ["ruma/markdown"] native-tls = ["reqwest/native-tls"] rustls-tls = ["reqwest/rustls-tls"] socks = ["reqwest/socks"] -sso-login = ["warp", "rand", "tokio-stream"] +sso-login = ["warp", "dep:rand", "dep:tokio-stream"] appservice = ["ruma/appservice-api-s"] -image-proc = ["image"] -image-rayon = ["image-proc", "image/jpeg_rayon"] +image-proc = ["dep:image"] +image-rayon = ["image-proc", "image?/jpeg_rayon"] experimental-timeline = [ "matrix-sdk-base/experimental-timeline", From 4f1718e587f1a158a077e1f3d506aa46a0e3047d Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 13 Jul 2022 13:45:07 -0600 Subject: [PATCH 23/73] Fix package name in readme for nodejs bindings --- bindings/matrix-sdk-crypto-nodejs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/matrix-sdk-crypto-nodejs/README.md b/bindings/matrix-sdk-crypto-nodejs/README.md index cf3daa20f..cb795dc1c 100644 --- a/bindings/matrix-sdk-crypto-nodejs/README.md +++ b/bindings/matrix-sdk-crypto-nodejs/README.md @@ -13,7 +13,7 @@ Encryption](https://en.wikipedia.org/wiki/End-to-end_encryption)) for Just add the latest release to your `package.json`: ```sh -$ npm install --save matrix-sdk-crypto +$ npm install --save @matrix-org/matrix-sdk-crypto-nodejs ``` When installing, NPM will download the corresponding prebuilt Rust library for your current host system. The following are supported: From 65b1dfef6f752619f6dfe1033668d1186918c2b3 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 14 Jul 2022 08:14:45 +0200 Subject: [PATCH 24/73] fix(bindings/crypto-nodejs): Fix pre-built download link. --- bindings/matrix-sdk-crypto-nodejs/download-lib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/matrix-sdk-crypto-nodejs/download-lib.js b/bindings/matrix-sdk-crypto-nodejs/download-lib.js index 7a12e172f..ec7c157e3 100644 --- a/bindings/matrix-sdk-crypto-nodejs/download-lib.js +++ b/bindings/matrix-sdk-crypto-nodejs/download-lib.js @@ -3,7 +3,7 @@ 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 CURRENT_VERSION = `matrix-sdk-crypto-nodejs-v${version}`; const byteHelper = function (value) { if (value === 0) { From 3567d19359fd1f94652dc9cbf1becd9644bddc9b Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 14 Jul 2022 08:26:57 +0200 Subject: [PATCH 25/73] fix(bindings/crypto-js): Use `cross-env` to pass envvar on Windows. --- bindings/matrix-sdk-crypto-js/package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/package.json b/bindings/matrix-sdk-crypto-js/package.json index d6905cb80..45e7d85d2 100644 --- a/bindings/matrix-sdk-crypto-js/package.json +++ b/bindings/matrix-sdk-crypto-js/package.json @@ -28,13 +28,14 @@ "devDependencies": { "wasm-pack": "^0.10.2", "jest": "^28.1.0", - "typedoc": "^0.22.17" + "typedoc": "^0.22.17", + "cross-env": "^7.0.3" }, "engines": { "node": ">= 10" }, "scripts": { - "build": "RUSTFLAGS='-C opt-level=z' wasm-pack build --release --target nodejs --out-name matrix_sdk_crypto --out-dir ./pkg", + "build": "cross-env 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 ." } From 8f8bd40e8d870028ba299bf124ed45530da50954 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 12 Jul 2022 10:15:25 +0200 Subject: [PATCH 26/73] feat(bindings/crypto-js): Redirect Rust panics to JavaScript console. --- bindings/matrix-sdk-crypto-js/Cargo.toml | 1 + bindings/matrix-sdk-crypto-js/src/lib.rs | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/bindings/matrix-sdk-crypto-js/Cargo.toml b/bindings/matrix-sdk-crypto-js/Cargo.toml index 94d14468c..b5cbe56af 100644 --- a/bindings/matrix-sdk-crypto-js/Cargo.toml +++ b/bindings/matrix-sdk-crypto-js/Cargo.toml @@ -34,6 +34,7 @@ vodozemac = { git = "https://github.com/matrix-org/vodozemac/", rev = "2404f83f7 wasm-bindgen = "0.2.80" wasm-bindgen-futures = "0.4.30" js-sys = "0.3.49" +console_error_panic_hook = "0.1.7" serde_json = "1.0.79" http = "0.2.6" anyhow = "1.0" diff --git a/bindings/matrix-sdk-crypto-js/src/lib.rs b/bindings/matrix-sdk-crypto-js/src/lib.rs index a9b59426f..a985e4138 100644 --- a/bindings/matrix-sdk-crypto-js/src/lib.rs +++ b/bindings/matrix-sdk-crypto-js/src/lib.rs @@ -29,6 +29,16 @@ pub mod sync_events; use js_sys::{Object, Reflect}; use wasm_bindgen::{convert::RefFromWasmAbi, prelude::*}; +/// Run some stuff when the Wasm module is instantiated. +/// +/// Right now, it does the following: +/// +/// * Redirect Rust panics to JavaScript console. +#[wasm_bindgen(start)] +pub fn start() { + console_error_panic_hook::set_once(); +} + /// 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. From 70561f9649088c6387ee787116fa4bb8fbb2c5b1 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 12 Jul 2022 11:54:28 +0200 Subject: [PATCH 27/73] feat(bindings/crypto-js): Add the `userLogger` function to enable logging into `Console`. --- bindings/matrix-sdk-crypto-js/Cargo.toml | 14 +- bindings/matrix-sdk-crypto-js/src/lib.rs | 1 + bindings/matrix-sdk-crypto-js/src/logger.rs | 162 ++++++++++++++++++++ 3 files changed, 171 insertions(+), 6 deletions(-) create mode 100644 bindings/matrix-sdk-crypto-js/src/logger.rs diff --git a/bindings/matrix-sdk-crypto-js/Cargo.toml b/bindings/matrix-sdk-crypto-js/Cargo.toml index b5cbe56af..0f7f0fa0c 100644 --- a/bindings/matrix-sdk-crypto-js/Cargo.toml +++ b/bindings/matrix-sdk-crypto-js/Cargo.toml @@ -31,10 +31,12 @@ 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" -console_error_panic_hook = "0.1.7" -serde_json = "1.0.79" -http = "0.2.6" +wasm-bindgen = "0.2" +wasm-bindgen-futures = "0.4" +js-sys = "0.3" +console_error_panic_hook = "0.1" +serde_json = "1.0" +http = "0.2" anyhow = "1.0" +tracing = { version = "0.1", default-features = false, features = ["attributes"] } +tracing-subscriber = { version = "0.3", default-features = false, features = ["registry", "std"] } diff --git a/bindings/matrix-sdk-crypto-js/src/lib.rs b/bindings/matrix-sdk-crypto-js/src/lib.rs index a985e4138..18b9714a7 100644 --- a/bindings/matrix-sdk-crypto-js/src/lib.rs +++ b/bindings/matrix-sdk-crypto-js/src/lib.rs @@ -21,6 +21,7 @@ pub mod encryption; pub mod events; mod future; pub mod identifiers; +mod logger; pub mod machine; pub mod requests; pub mod responses; diff --git a/bindings/matrix-sdk-crypto-js/src/logger.rs b/bindings/matrix-sdk-crypto-js/src/logger.rs new file mode 100644 index 000000000..a3d0a756f --- /dev/null +++ b/bindings/matrix-sdk-crypto-js/src/logger.rs @@ -0,0 +1,162 @@ +use std::fmt::{self, Write as _}; + +use tracing::{ + field::{Field, Visit}, + Event, Id, Level, Metadata, Subscriber, +}; +use tracing_subscriber::{ + layer::{Context, Layer as TracingLayer}, + prelude::*, +}; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +#[derive(Debug)] +pub enum LoggerLevel { + Debug, + Info, + Warn, + Trace, + Error, +} + +impl From for Level { + fn from(value: LoggerLevel) -> Self { + use LoggerLevel::*; + + match value { + Debug => Self::DEBUG, + Info => Self::INFO, + Warn => Self::WARN, + Trace => Self::TRACE, + Error => Self::ERROR, + } + } +} + +#[wasm_bindgen(js_name = "useLogger")] +pub fn use_logger(level: LoggerLevel) { + tracing_subscriber::registry().with(Layer::new(level)).init(); +} + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_namespace = console, js_name = "debug")] + fn log_debug(message: String); + + #[wasm_bindgen(js_namespace = console, js_name = "info")] + fn log_info(message: String); + + #[wasm_bindgen(js_namespace = console, js_name = "warn")] + fn log_warn(message: String); + + #[wasm_bindgen(js_namespace = console, js_name = "trace")] + fn log_trace(message: String); + + #[wasm_bindgen(js_namespace = console, js_name = "log")] + fn log(message: String); + + #[wasm_bindgen(js_namespace = console, js_name= "group")] + fn log_group_open(label: String); + + #[wasm_bindgen(js_namespace = console, js_name= "groupEnd")] + fn log_group_close(); +} + +struct Layer { + level: Level, +} + +impl Layer { + fn new(level: L) -> Self + where + L: Into, + { + Self { level: level.into() } + } +} + +impl TracingLayer for Layer +where + S: Subscriber, +{ + fn enabled(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool { + metadata.level() >= &self.level + } + + fn on_enter(&self, id: &Id, _: Context<'_, S>) { + log_group_open(format!("t{:x}", id.into_u64())); + } + + fn on_exit(&self, _: &Id, _: Context<'_, S>) { + log_group_close(); + } + + fn on_event(&self, event: &Event<'_>, _: Context<'_, S>) { + let mut recorder = StringVisitor::new(); + event.record(&mut recorder); + let metadata = event.metadata(); + let level = metadata.level(); + + let origin = metadata + .file() + .and_then(|file| metadata.line().map(|ln| format!("{}:{}", file, ln))) + .unwrap_or_default(); + + let message = format!("{level} {origin} {recorder}"); + + match *level { + Level::DEBUG => log_debug(message), + Level::INFO => log_info(message), + Level::WARN => log_warn(message), + Level::TRACE => log_trace(message), + Level::ERROR => log(message), + } + } +} + +struct StringVisitor { + string: String, + displaying_arguments: bool, +} + +impl StringVisitor { + fn new() -> Self { + Self { string: String::new(), displaying_arguments: false } + } +} + +impl Visit for StringVisitor { + fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { + match field.name() { + "message" => { + if !self.string.is_empty() { + self.string.push('\n'); + } + + let _ = write!(self.string, "{:?}", value); + } + + field_name => { + if self.displaying_arguments { + self.string.push('\n'); + } else { + self.string.push(' '); + self.displaying_arguments = true; + } + + let _ = write!(self.string, "{} = {:?}", field_name, value); + } + } + } +} + +impl fmt::Display for StringVisitor { + fn fmt(&self, mut f: &mut fmt::Formatter<'_>) -> fmt::Result { + if !self.string.is_empty() { + write!(&mut f, " {}", self.string) + } else { + Ok(()) + } + } +} From e7d0ee4379f6222249c701b53e1c3ef244b51b8f Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 12 Jul 2022 12:21:38 +0200 Subject: [PATCH 28/73] !fixup --- bindings/matrix-sdk-crypto-js/Cargo.toml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/Cargo.toml b/bindings/matrix-sdk-crypto-js/Cargo.toml index 0f7f0fa0c..af864acd7 100644 --- a/bindings/matrix-sdk-crypto-js/Cargo.toml +++ b/bindings/matrix-sdk-crypto-js/Cargo.toml @@ -31,12 +31,12 @@ 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" -wasm-bindgen-futures = "0.4" -js-sys = "0.3" -console_error_panic_hook = "0.1" -serde_json = "1.0" -http = "0.2" -anyhow = "1.0" -tracing = { version = "0.1", default-features = false, features = ["attributes"] } -tracing-subscriber = { version = "0.3", default-features = false, features = ["registry", "std"] } +wasm-bindgen = "0.2.80" +wasm-bindgen-futures = "0.4.30" +js-sys = "0.3.49" +console_error_panic_hook = "0.1.7" +serde_json = "1.0.79" +http = "0.2.6" +anyhow = "1.0.58" +tracing = { version = "0.1.35", default-features = false, features = ["attributes"] } +tracing-subscriber = { version = "0.3.14", default-features = false, features = ["registry", "std"] } From f5016dbb97c3d7f545e479674412d9f719f63d3e Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 12 Jul 2022 12:41:53 +0200 Subject: [PATCH 29/73] feat(bindings/crypto-js): Define `Layer.max_level_hint`. --- bindings/matrix-sdk-crypto-js/src/logger.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/src/logger.rs b/bindings/matrix-sdk-crypto-js/src/logger.rs index a3d0a756f..44c483539 100644 --- a/bindings/matrix-sdk-crypto-js/src/logger.rs +++ b/bindings/matrix-sdk-crypto-js/src/logger.rs @@ -2,6 +2,7 @@ use std::fmt::{self, Write as _}; use tracing::{ field::{Field, Visit}, + metadata::LevelFilter, Event, Id, Level, Metadata, Subscriber, }; use tracing_subscriber::{ @@ -35,8 +36,8 @@ impl From for Level { } #[wasm_bindgen(js_name = "useLogger")] -pub fn use_logger(level: LoggerLevel) { - tracing_subscriber::registry().with(Layer::new(level)).init(); +pub fn use_logger(max_level: LoggerLevel) { + tracing_subscriber::registry().with(Layer::new(max_level)).init(); } #[wasm_bindgen] @@ -64,15 +65,15 @@ extern "C" { } struct Layer { - level: Level, + max_level: Level, } impl Layer { - fn new(level: L) -> Self + fn new(max_level: L) -> Self where L: Into, { - Self { level: level.into() } + Self { max_level: max_level.into() } } } @@ -81,7 +82,11 @@ where S: Subscriber, { fn enabled(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool { - metadata.level() >= &self.level + metadata.level() <= &self.max_level + } + + fn max_level_hint(&self) -> Option { + Some(LevelFilter::from_level(self.max_level)) } fn on_enter(&self, id: &Id, _: Context<'_, S>) { From d39baf129547e818455dbd20c9f3a8f110f67171 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 12 Jul 2022 13:01:07 +0200 Subject: [PATCH 30/73] test(bindings/crypto-js): Encrypt and decrypt a valid message. --- bindings/matrix-sdk-crypto-js/src/{logger.rs => tracing.rs} | 0 bindings/matrix-sdk-crypto-js/tests/machine.test.js | 6 ++++-- 2 files changed, 4 insertions(+), 2 deletions(-) rename bindings/matrix-sdk-crypto-js/src/{logger.rs => tracing.rs} (100%) diff --git a/bindings/matrix-sdk-crypto-js/src/logger.rs b/bindings/matrix-sdk-crypto-js/src/tracing.rs similarity index 100% rename from bindings/matrix-sdk-crypto-js/src/logger.rs rename to bindings/matrix-sdk-crypto-js/src/tracing.rs diff --git a/bindings/matrix-sdk-crypto-js/tests/machine.test.js b/bindings/matrix-sdk-crypto-js/tests/machine.test.js index 7a851dc4c..dd759f1b8 100644 --- a/bindings/matrix-sdk-crypto-js/tests/machine.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/machine.test.js @@ -299,7 +299,8 @@ describe(OlmMachine.name, () => { room, 'm.room.message', JSON.stringify({ - "hello": "world" + "msgtype": "m.text", + "body": "Hello, World!" }), )); @@ -328,7 +329,8 @@ describe(OlmMachine.name, () => { expect(decrypted).toBeInstanceOf(DecryptedRoomEvent); const event = JSON.parse(decrypted.event); - expect(event.content.hello).toStrictEqual("world"); + expect(event.content.msgtype).toStrictEqual("m.text"); + expect(event.content.body).toStrictEqual("Hello, World!"); expect(decrypted.sender.toString()).toStrictEqual(user.toString()); expect(decrypted.senderDevice.toString()).toStrictEqual(device.toString()); From bb631f2f7945a4c55c2f079b87305453779e9e6b Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 12 Jul 2022 16:00:41 +0200 Subject: [PATCH 31/73] feat(bindings/crypto-js): Add ability to turn `Tracing` on and off, and change logger min level. The patch updates the code to use `tracing_subscriber::reload`, so that we get a `Handle` that can be used to modify the tracing at runtime. This patch also adds a new `tracing` feature. This patch finally adds a test suite for the `Tracing` API. --- bindings/matrix-sdk-crypto-js/Cargo.toml | 3 +- bindings/matrix-sdk-crypto-js/src/lib.rs | 2 +- bindings/matrix-sdk-crypto-js/src/tracing.rs | 161 ++++++++++++++---- .../tests/requests.test.js | 4 +- .../tests/tracing.test.js | 78 +++++++++ 5 files changed, 213 insertions(+), 35 deletions(-) create mode 100644 bindings/matrix-sdk-crypto-js/tests/tracing.test.js diff --git a/bindings/matrix-sdk-crypto-js/Cargo.toml b/bindings/matrix-sdk-crypto-js/Cargo.toml index af864acd7..dfe0f83c8 100644 --- a/bindings/matrix-sdk-crypto-js/Cargo.toml +++ b/bindings/matrix-sdk-crypto-js/Cargo.toml @@ -22,9 +22,10 @@ wasm-opt = ['-Oz'] crate-type = ["cdylib"] [features] -default = [] +default = ["tracing"] qrcode = ["matrix-sdk-crypto/qrcode"] docsrs = [] +tracing = [] [dependencies] matrix-sdk-common = { version = "0.5.0", path = "../../crates/matrix-sdk-common" } diff --git a/bindings/matrix-sdk-crypto-js/src/lib.rs b/bindings/matrix-sdk-crypto-js/src/lib.rs index 18b9714a7..b927fedca 100644 --- a/bindings/matrix-sdk-crypto-js/src/lib.rs +++ b/bindings/matrix-sdk-crypto-js/src/lib.rs @@ -21,11 +21,11 @@ pub mod encryption; pub mod events; mod future; pub mod identifiers; -mod logger; pub mod machine; pub mod requests; pub mod responses; pub mod sync_events; +mod tracing; use js_sys::{Object, Reflect}; use wasm_bindgen::{convert::RefFromWasmAbi, prelude::*}; diff --git a/bindings/matrix-sdk-crypto-js/src/tracing.rs b/bindings/matrix-sdk-crypto-js/src/tracing.rs index 44c483539..dcdb07ae1 100644 --- a/bindings/matrix-sdk-crypto-js/src/tracing.rs +++ b/bindings/matrix-sdk-crypto-js/src/tracing.rs @@ -1,47 +1,137 @@ -use std::fmt::{self, Write as _}; +use std::fmt; +#[cfg(feature = "tracing")] +use std::fmt::Write as _; +#[cfg(feature = "tracing")] use tracing::{ field::{Field, Visit}, metadata::LevelFilter, Event, Id, Level, Metadata, Subscriber, }; +#[cfg(feature = "tracing")] use tracing_subscriber::{ layer::{Context, Layer as TracingLayer}, prelude::*, + reload, Registry, }; use wasm_bindgen::prelude::*; +/// Type to install and to manipulate the tracing layer. #[wasm_bindgen] -#[derive(Debug)] +pub struct Tracing { + #[cfg(feature = "tracing")] + handle: reload::Handle, +} + +impl fmt::Debug for Tracing { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Tracing").finish_non_exhaustive() + } +} + +#[wasm_bindgen] +impl Tracing { + /// Check whether the `tracing` feature has been enabled. + #[wasm_bindgen(js_name = "isAvailable")] + pub fn is_available() -> bool { + cfg!(feature = "tracing") + } + + /// Install the tracing layer. + /// + /// **Warning**: It must be installed only **once**, otherwise a + /// runtime error will be raised. + pub fn install(_min_level: LoggerLevel) -> Option { + #[cfg(not(feature = "tracing"))] + { + None + } + + #[cfg(feature = "tracing")] + { + let (filter, reload_handle) = reload::Layer::new(Layer::new(_min_level)); + + tracing_subscriber::registry().with(filter).init(); + + Some(Self { handle: reload_handle }) + } + } + + /// Re-define the minimum logger level. + #[cfg(feature = "tracing")] + #[wasm_bindgen(setter, js_name = "minLevel")] + pub fn min_level(&self, min_level: LoggerLevel) { + let _ = self.handle.modify(|layer| layer.min_level = min_level.into()); + } + + /// Turn the logger on, i.e. it emits logs again if it was turned + /// off. + #[cfg(feature = "tracing")] + #[wasm_bindgen(js_name = "turnOn")] + pub fn turn_on(&self) { + let _ = self.handle.modify(|layer| layer.turn_on()); + } + + /// Turn the logger off, i.e. it no long emits logs. + #[cfg(feature = "tracing")] + #[wasm_bindgen(js_name = "turnOff")] + pub fn turn_off(&self) { + let _ = self.handle.modify(|layer| layer.turn_off()); + } +} + +/// Logger level. +#[wasm_bindgen] +#[derive(Debug, Clone)] pub enum LoggerLevel { - Debug, - Info, - Warn, + /// `TRACE` level. + /// + /// Designate very low priority, often extremely verbose, + /// information. Trace, + + /// `DEBUG` level. + /// + /// Designate lower priority information. + Debug, + + /// `INFO` level. + /// + /// Designate useful information. + Info, + + /// `WARN` level. + /// + /// Designate hazardous situations. + Warn, + + /// `ERROR` level. + /// + /// Designate very serious errors. Error, } +#[cfg(feature = "tracing")] impl From for Level { fn from(value: LoggerLevel) -> Self { use LoggerLevel::*; match value { + Trace => Self::TRACE, Debug => Self::DEBUG, Info => Self::INFO, Warn => Self::WARN, - Trace => Self::TRACE, Error => Self::ERROR, } } } -#[wasm_bindgen(js_name = "useLogger")] -pub fn use_logger(max_level: LoggerLevel) { - tracing_subscriber::registry().with(Layer::new(max_level)).init(); -} - +#[cfg(feature = "tracing")] #[wasm_bindgen] extern "C" { + #[wasm_bindgen(js_namespace = console, js_name = "trace")] + fn log_trace(message: String); + #[wasm_bindgen(js_namespace = console, js_name = "debug")] fn log_debug(message: String); @@ -51,9 +141,6 @@ extern "C" { #[wasm_bindgen(js_namespace = console, js_name = "warn")] fn log_warn(message: String); - #[wasm_bindgen(js_namespace = console, js_name = "trace")] - fn log_trace(message: String); - #[wasm_bindgen(js_namespace = console, js_name = "log")] fn log(message: String); @@ -64,29 +151,45 @@ extern "C" { fn log_group_close(); } +#[cfg(feature = "tracing")] struct Layer { - max_level: Level, + min_level: Level, + enabled: bool, } +#[cfg(feature = "tracing")] impl Layer { - fn new(max_level: L) -> Self + fn new(min_level: L) -> Self where L: Into, { - Self { max_level: max_level.into() } + Self { min_level: min_level.into(), enabled: true } + } + + fn turn_on(&mut self) { + self.enabled = true; + } + + fn turn_off(&mut self) { + self.enabled = false; } } +#[cfg(feature = "tracing")] impl TracingLayer for Layer where S: Subscriber, { fn enabled(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool { - metadata.level() <= &self.max_level + self.enabled && metadata.level() <= &self.min_level } fn max_level_hint(&self) -> Option { - Some(LevelFilter::from_level(self.max_level)) + if !self.enabled { + Some(LevelFilter::OFF) + } else { + Some(LevelFilter::from_level(self.min_level)) + } } fn on_enter(&self, id: &Id, _: Context<'_, S>) { @@ -108,29 +211,31 @@ where .and_then(|file| metadata.line().map(|ln| format!("{}:{}", file, ln))) .unwrap_or_default(); - let message = format!("{level} {origin} {recorder}"); + let message = format!("{level} {origin}{recorder}"); match *level { + Level::TRACE => log_trace(message), Level::DEBUG => log_debug(message), Level::INFO => log_info(message), Level::WARN => log_warn(message), - Level::TRACE => log_trace(message), Level::ERROR => log(message), } } } +#[cfg(feature = "tracing")] struct StringVisitor { string: String, - displaying_arguments: bool, } +#[cfg(feature = "tracing")] impl StringVisitor { fn new() -> Self { - Self { string: String::new(), displaying_arguments: false } + Self { string: String::new() } } } +#[cfg(feature = "tracing")] impl Visit for StringVisitor { fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { match field.name() { @@ -143,19 +248,13 @@ impl Visit for StringVisitor { } field_name => { - if self.displaying_arguments { - self.string.push('\n'); - } else { - self.string.push(' '); - self.displaying_arguments = true; - } - - let _ = write!(self.string, "{} = {:?}", field_name, value); + let _ = write!(self.string, "\n{} = {:?}", field_name, value); } } } } +#[cfg(feature = "tracing")] impl fmt::Display for StringVisitor { fn fmt(&self, mut f: &mut fmt::Formatter<'_>) -> fmt::Result { if !self.string.is_empty() { diff --git a/bindings/matrix-sdk-crypto-js/tests/requests.test.js b/bindings/matrix-sdk-crypto-js/tests/requests.test.js index 1f806f4ae..b23a2d31e 100644 --- a/bindings/matrix-sdk-crypto-js/tests/requests.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/requests.test.js @@ -12,7 +12,7 @@ describe('RequestType', () => { }); }); -for (const [request, request_type] of [ +for (const [request, requestType] of [ [KeysUploadRequest, RequestType.KeysUpload], [KeysQueryRequest, RequestType.KeysQuery], [KeysClaimRequest, RequestType.KeysClaim], @@ -28,7 +28,7 @@ for (const [request, request_type] of [ expect(r).toBeInstanceOf(request); expect(r.id).toStrictEqual('foo'); expect(r.body).toStrictEqual('{"bar": "baz"}'); - expect(r.type).toStrictEqual(request_type); + expect(r.type).toStrictEqual(requestType); }); }) diff --git a/bindings/matrix-sdk-crypto-js/tests/tracing.test.js b/bindings/matrix-sdk-crypto-js/tests/tracing.test.js new file mode 100644 index 000000000..89fbce2bb --- /dev/null +++ b/bindings/matrix-sdk-crypto-js/tests/tracing.test.js @@ -0,0 +1,78 @@ +const { Tracing, LoggerLevel, OlmMachine, UserId, DeviceId } = require('../pkg/matrix_sdk_crypto'); + +describe('LoggerLevel', () => { + test('has the correct variant values', () => { + expect(LoggerLevel.Trace).toStrictEqual(0); + expect(LoggerLevel.Debug).toStrictEqual(1); + expect(LoggerLevel.Info).toStrictEqual(2); + expect(LoggerLevel.Warn).toStrictEqual(3); + expect(LoggerLevel.Error).toStrictEqual(4); + }); +}); + +describe(Tracing.name, () => { + if (Tracing.isAvailable()) { + let tracing = Tracing.install(LoggerLevel.Debug); + + const originalConsoleDebug = console.debug; + + for (const [testName, testPreState, testPostState, expectedGotcha] of [ + [ + 'can log something', + () => {}, + () => {}, + true, + ], + [ + 'can change the logger level', + () => { tracing.minLevel = LoggerLevel.Warn }, + () => { tracing.minLevel = LoggerLevel.Debug }, + false, + ], + [ + 'can be turned off', + () => { tracing.turnOff() }, + () => {}, + false, + ], + [ + 'can be turned on', + () => { tracing.turnOn() }, + () => {}, + true, + ], + + // This one *must* be the last. We are turning tracing off + // again for the other tests. + [ + 'can be turned off', + () => { tracing.turnOff() }, + () => {}, + false, + ], + ]) { + test(testName, async () => { + testPreState(); + + let gotcha = false; + + console.debug = (msg) => { + gotcha = true; + expect(msg).not.toHaveLength(0); + }; + + // Do something that emits a `DEBUG` log. + await new OlmMachine(new UserId('@alice:example.org'), new DeviceId('foo')); + + console.debug = originalConsoleDebug; + testPostState(); + + expect(gotcha).toStrictEqual(expectedGotcha); + }); + } + } else { + test('cannot be constructed', () => { + expect(Tracing.install(LoggerLevel.Error)).toBeUndefined(); + }); + } +}); From 283c5ff51e039dcb2ae7c3bcce07c72e2ee1d05f Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 14 Jul 2022 09:04:44 +0200 Subject: [PATCH 32/73] fix(bindings/crypto-js): Let's not deal with `Console.group`. Events and spans from `tracing` can happen asynchronously, and could mess the `Console.group` structure. --- bindings/matrix-sdk-crypto-js/src/tracing.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/src/tracing.rs b/bindings/matrix-sdk-crypto-js/src/tracing.rs index dcdb07ae1..1fea6d91c 100644 --- a/bindings/matrix-sdk-crypto-js/src/tracing.rs +++ b/bindings/matrix-sdk-crypto-js/src/tracing.rs @@ -143,12 +143,6 @@ extern "C" { #[wasm_bindgen(js_namespace = console, js_name = "log")] fn log(message: String); - - #[wasm_bindgen(js_namespace = console, js_name= "group")] - fn log_group_open(label: String); - - #[wasm_bindgen(js_namespace = console, js_name= "groupEnd")] - fn log_group_close(); } #[cfg(feature = "tracing")] @@ -192,14 +186,6 @@ where } } - fn on_enter(&self, id: &Id, _: Context<'_, S>) { - log_group_open(format!("t{:x}", id.into_u64())); - } - - fn on_exit(&self, _: &Id, _: Context<'_, S>) { - log_group_close(); - } - fn on_event(&self, event: &Event<'_>, _: Context<'_, S>) { let mut recorder = StringVisitor::new(); event.record(&mut recorder); From 0112396c998fabca420aa8475b83f6bc4cad5acf Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Thu, 14 Jul 2022 11:55:53 +0200 Subject: [PATCH 33/73] ci(crypto-nodejs): trigger build for new tag --- .../workflows/prep-crypto-nodejs-release.yml | 16 +++++++++---- .github/workflows/release-crypto-nodejs.yml | 23 ++++++++++++++++++- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/.github/workflows/prep-crypto-nodejs-release.yml b/.github/workflows/prep-crypto-nodejs-release.yml index 3bed3c853..3a7db0b58 100644 --- a/.github/workflows/prep-crypto-nodejs-release.yml +++ b/.github/workflows/prep-crypto-nodejs-release.yml @@ -38,6 +38,8 @@ jobs: prepare-release: name: "Preparing crypto-nodejs release tag" runs-on: ubuntu-latest + outputs: + tag: "${{ env.TAG_PREFIX }}${{ inputs.version }}" steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 @@ -98,12 +100,18 @@ jobs: tag_name: ${{ env.TAG_PREFIX }}${{ inputs.version }} body_path: "${{ env.PKG_PATH }}/CHANGELOG.md" - # finally, let's create a PR for all this, too + # 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 + Automatic Pull-Request to merge release ${{ env.TAG_PREFIX }}${{ inputs.version }} + + trigger-release: + # and trigger the tagging release workflow + uses: matrix-org/matrix-rust-sdk/.github/workflows/release-crypto-nodejs.yml@ben-release-crypto-nodes-beta0 + needs: ['prepare-release'] + name: "Trigger release Workflow" + with: + tag: ${{needs.prepare-release.outputs.tag}} diff --git a/.github/workflows/release-crypto-nodejs.yml b/.github/workflows/release-crypto-nodejs.yml index c18170a53..19e6fcd73 100644 --- a/.github/workflows/release-crypto-nodejs.yml +++ b/.github/workflows/release-crypto-nodejs.yml @@ -21,7 +21,12 @@ on: push: tags: - matrix-sdk-crypto-nodejs-v[0-9]+.* - + workflow_call: + inputs: + tag: + description: "The tag to build with" + required: true + type: string jobs: upload-assets: name: "Upload prebuilt libraries" @@ -57,7 +62,15 @@ jobs: os: windows-latest runs-on: ${{ matrix.os }} steps: + # use the given tag - uses: actions/checkout@v3 + name: "Checking out ${{ inputs.tag }}" + if: "${{ inputs.tag }}" + with: + ref: ${{ inputs.tag }} + # use the default + - uses: actions/checkout@v3 + if: "${{ !inputs.tag }}" - name: Install Rust uses: actions-rs/toolchain@v1 with: @@ -90,7 +103,15 @@ jobs: needs: - upload-assets steps: + # use the given tag - uses: actions/checkout@v3 + name: "Checking out ${{ inputs.tag }}" + if: "${{ inputs.tag }}" + with: + ref: ${{ inputs.tag }} + # use the default + - uses: actions/checkout@v3 + if: "${{ !inputs.tag }}" - name: Install Rust uses: actions-rs/toolchain@v1 with: From ebfa235dabaa211875e77107cd86e57036974e28 Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Thu, 14 Jul 2022 11:56:16 +0200 Subject: [PATCH 34/73] chore(crypto-nodejs): Update changelog for beta.1 --- bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md b/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md index d056255c1..2d83a8260 100644 --- a/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md +++ b/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md @@ -1,6 +1,10 @@ # Matrix-Rust-SDK Node.js Bindings -## 0.1.0-beta.0 - 2022-07-21 +## 0.1.0-beta.1 - 2022-07-14 + +- Fixing broken download link, [#842](https://github.com/matrix-org/matrix-rust-sdk/issues/842) + +## 0.1.0-beta.0 - 2022-07-12 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 From 163ce948065677314895b05f9c143909ae04708b Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 14 Jul 2022 10:40:57 +0000 Subject: [PATCH 35/73] Tagging Crypto-Node.js for release --- bindings/matrix-sdk-crypto-nodejs/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/matrix-sdk-crypto-nodejs/package.json b/bindings/matrix-sdk-crypto-nodejs/package.json index ee0cc2840..9699a89c7 100644 --- a/bindings/matrix-sdk-crypto-nodejs/package.json +++ b/bindings/matrix-sdk-crypto-nodejs/package.json @@ -1,6 +1,6 @@ { "name": "@matrix-org/matrix-sdk-crypto-nodejs", - "version": "0.1.0-beta.0", + "version": "0.1.0-beta.1", "main": "index.js", "types": "index.d.ts", "napi": { From 09c56ea0575c95b43f348d62bc3138d6bf61238d Mon Sep 17 00:00:00 2001 From: Johannes Becker Date: Thu, 14 Jul 2022 15:06:45 +0200 Subject: [PATCH 36/73] feat(appservice)!: Allow specifying device id for registration --- .../examples/appservice_autojoin.rs | 2 +- crates/matrix-sdk-appservice/src/lib.rs | 15 ++++++++++----- crates/matrix-sdk-appservice/tests/tests.rs | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/crates/matrix-sdk-appservice/examples/appservice_autojoin.rs b/crates/matrix-sdk-appservice/examples/appservice_autojoin.rs index e1c295af6..8835449e4 100644 --- a/crates/matrix-sdk-appservice/examples/appservice_autojoin.rs +++ b/crates/matrix-sdk-appservice/examples/appservice_autojoin.rs @@ -27,7 +27,7 @@ pub async fn handle_room_member( trace!("not an appservice user: {}", event.state_key); } else if let MembershipState::Invite = event.content.membership { let user_id = UserId::parse(event.state_key.as_str())?; - if let Err(error) = appservice.register_virtual_user(user_id.localpart()).await { + if let Err(error) = appservice.register_virtual_user(user_id.localpart(), None).await { error_if_user_not_in_use(error)?; } diff --git a/crates/matrix-sdk-appservice/src/lib.rs b/crates/matrix-sdk-appservice/src/lib.rs index 51592ec34..10b612c2c 100644 --- a/crates/matrix-sdk-appservice/src/lib.rs +++ b/crates/matrix-sdk-appservice/src/lib.rs @@ -106,7 +106,7 @@ use ruma::{ }, assign, events::{room::member::MembershipState, AnyRoomEvent, AnyStateEvent}, - IdParseError, OwnedRoomId, OwnedServerName, + DeviceId, IdParseError, OwnedRoomId, OwnedServerName, }; use serde::Deserialize; use tokio::task::JoinHandle; @@ -305,18 +305,23 @@ impl AppService { /// # Returns /// This function may return a UIAA response, which should be checked for /// with [`Error::uiaa_response()`]. - pub async fn register_virtual_user(&self, localpart: impl AsRef) -> Result<()> { - if self.is_user_registered(localpart.as_ref()).await? { + pub async fn register_virtual_user<'a>( + &self, + localpart: &'a str, + device_id: Option<&'a DeviceId>, + ) -> Result<()> { + if self.is_user_registered(localpart).await? { return Ok(()); } let request = assign!(register::v3::Request::new(), { - username: Some(localpart.as_ref()), + username: Some(localpart), login_type: Some(®ister::LoginType::ApplicationService), + device_id, }); let client = self.virtual_user(None).await?; client.register(request).await?; - self.set_user_registered(localpart.as_ref()).await?; + self.set_user_registered(localpart).await?; Ok(()) } diff --git a/crates/matrix-sdk-appservice/tests/tests.rs b/crates/matrix-sdk-appservice/tests/tests.rs index fc74555a5..5dd10d24c 100644 --- a/crates/matrix-sdk-appservice/tests/tests.rs +++ b/crates/matrix-sdk-appservice/tests/tests.rs @@ -82,7 +82,7 @@ async fn test_register_virtual_user() -> Result<()> { .mount(&server) .await; - appservice.register_virtual_user(localpart).await?; + appservice.register_virtual_user(localpart, None).await?; Ok(()) } From c763ce3f4177b71ffa1935569583582599142670 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 18 Jul 2022 09:23:37 +0200 Subject: [PATCH 37/73] feat(bindings/crypto-js): `Tracing` can be installed more than once. --- bindings/matrix-sdk-crypto-js/src/tracing.rs | 41 +++++++++++++++---- .../tests/tracing.test.js | 6 +++ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/src/tracing.rs b/bindings/matrix-sdk-crypto-js/src/tracing.rs index 1fea6d91c..d7ed61d5b 100644 --- a/bindings/matrix-sdk-crypto-js/src/tracing.rs +++ b/bindings/matrix-sdk-crypto-js/src/tracing.rs @@ -1,12 +1,12 @@ -use std::fmt; +use std::{fmt, sync::Arc}; #[cfg(feature = "tracing")] -use std::fmt::Write as _; +use std::{fmt::Write as _, sync::Once}; #[cfg(feature = "tracing")] use tracing::{ field::{Field, Visit}, metadata::LevelFilter, - Event, Id, Level, Metadata, Subscriber, + Event, Level, Metadata, Subscriber, }; #[cfg(feature = "tracing")] use tracing_subscriber::{ @@ -16,11 +16,13 @@ use tracing_subscriber::{ }; use wasm_bindgen::prelude::*; +type TracingInner = Arc>; + /// Type to install and to manipulate the tracing layer. #[wasm_bindgen] pub struct Tracing { #[cfg(feature = "tracing")] - handle: reload::Handle, + handle: TracingInner, } impl fmt::Debug for Tracing { @@ -39,8 +41,12 @@ impl Tracing { /// Install the tracing layer. /// - /// **Warning**: It must be installed only **once**, otherwise a - /// runtime error will be raised. + /// `Tracing` is a singleton. Once it is installed, consecutive + /// calls to `install` will construct a new `Tracing` object but + /// with the exact same inner state. Calling `install` with a new + /// `min_level` will just update the `min_level` parameter; in + /// that regard, it is similar to calling the `min_level` method + /// on an existing `Tracing` object. pub fn install(_min_level: LoggerLevel) -> Option { #[cfg(not(feature = "tracing"))] { @@ -49,11 +55,28 @@ impl Tracing { #[cfg(feature = "tracing")] { - let (filter, reload_handle) = reload::Layer::new(Layer::new(_min_level)); + static mut INSTALL: Option = None; + static INSTALLED: Once = Once::new(); - tracing_subscriber::registry().with(filter).init(); + INSTALLED.call_once(|| { + let (filter, reload_handle) = reload::Layer::new(Layer::new(_min_level.clone())); - Some(Self { handle: reload_handle }) + tracing_subscriber::registry().with(filter).init(); + + unsafe { INSTALL = Some(Arc::new(reload_handle)) }; + }); + + let tracing = Tracing { + handle: unsafe { INSTALL.as_ref() } + .cloned() + .expect("`Tracing` has not been installed correctly"), + }; + + // If it's not the first call to `install`, the + // `min_level` can be different. Let's update it. + tracing.min_level(_min_level); + + Some(tracing) } } diff --git a/bindings/matrix-sdk-crypto-js/tests/tracing.test.js b/bindings/matrix-sdk-crypto-js/tests/tracing.test.js index 89fbce2bb..0ce28cc6f 100644 --- a/bindings/matrix-sdk-crypto-js/tests/tracing.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/tracing.test.js @@ -14,6 +14,12 @@ describe(Tracing.name, () => { if (Tracing.isAvailable()) { let tracing = Tracing.install(LoggerLevel.Debug); + test('can installed several times', () => { + Tracing.install(LoggerLevel.Debug); + Tracing.install(LoggerLevel.Warn); + Tracing.install(LoggerLevel.Debug); + }); + const originalConsoleDebug = console.debug; for (const [testName, testPreState, testPostState, expectedGotcha] of [ From decd3fcb430d2d40b4ba4ff1f438cbd1e8471479 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 18 Jul 2022 09:44:42 +0200 Subject: [PATCH 38/73] feat(bindings/crypto-js) Simplify code for `feature = "tracing"`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch creates one `inner` module for when `feature = "tracing"`, and one for when `no(feature = "tracing")`. Then, let's expose everything from `inner::*`. This patch also replaces `Tracing.install` by `new Tracing`. In case of `not(feature = "tracing")`, `new Tracing` raises an error. The goal is to remove all the `#[cfg(…)]` annotations everywhere. Now there is only 2 of them. --- bindings/matrix-sdk-crypto-js/src/tracing.rs | 423 +++++++++--------- .../tests/tracing.test.js | 10 +- 2 files changed, 223 insertions(+), 210 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/src/tracing.rs b/bindings/matrix-sdk-crypto-js/src/tracing.rs index d7ed61d5b..cf1f98d63 100644 --- a/bindings/matrix-sdk-crypto-js/src/tracing.rs +++ b/bindings/matrix-sdk-crypto-js/src/tracing.rs @@ -1,108 +1,5 @@ -use std::{fmt, sync::Arc}; -#[cfg(feature = "tracing")] -use std::{fmt::Write as _, sync::Once}; - -#[cfg(feature = "tracing")] -use tracing::{ - field::{Field, Visit}, - metadata::LevelFilter, - Event, Level, Metadata, Subscriber, -}; -#[cfg(feature = "tracing")] -use tracing_subscriber::{ - layer::{Context, Layer as TracingLayer}, - prelude::*, - reload, Registry, -}; use wasm_bindgen::prelude::*; -type TracingInner = Arc>; - -/// Type to install and to manipulate the tracing layer. -#[wasm_bindgen] -pub struct Tracing { - #[cfg(feature = "tracing")] - handle: TracingInner, -} - -impl fmt::Debug for Tracing { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Tracing").finish_non_exhaustive() - } -} - -#[wasm_bindgen] -impl Tracing { - /// Check whether the `tracing` feature has been enabled. - #[wasm_bindgen(js_name = "isAvailable")] - pub fn is_available() -> bool { - cfg!(feature = "tracing") - } - - /// Install the tracing layer. - /// - /// `Tracing` is a singleton. Once it is installed, consecutive - /// calls to `install` will construct a new `Tracing` object but - /// with the exact same inner state. Calling `install` with a new - /// `min_level` will just update the `min_level` parameter; in - /// that regard, it is similar to calling the `min_level` method - /// on an existing `Tracing` object. - pub fn install(_min_level: LoggerLevel) -> Option { - #[cfg(not(feature = "tracing"))] - { - None - } - - #[cfg(feature = "tracing")] - { - static mut INSTALL: Option = None; - static INSTALLED: Once = Once::new(); - - INSTALLED.call_once(|| { - let (filter, reload_handle) = reload::Layer::new(Layer::new(_min_level.clone())); - - tracing_subscriber::registry().with(filter).init(); - - unsafe { INSTALL = Some(Arc::new(reload_handle)) }; - }); - - let tracing = Tracing { - handle: unsafe { INSTALL.as_ref() } - .cloned() - .expect("`Tracing` has not been installed correctly"), - }; - - // If it's not the first call to `install`, the - // `min_level` can be different. Let's update it. - tracing.min_level(_min_level); - - Some(tracing) - } - } - - /// Re-define the minimum logger level. - #[cfg(feature = "tracing")] - #[wasm_bindgen(setter, js_name = "minLevel")] - pub fn min_level(&self, min_level: LoggerLevel) { - let _ = self.handle.modify(|layer| layer.min_level = min_level.into()); - } - - /// Turn the logger on, i.e. it emits logs again if it was turned - /// off. - #[cfg(feature = "tracing")] - #[wasm_bindgen(js_name = "turnOn")] - pub fn turn_on(&self) { - let _ = self.handle.modify(|layer| layer.turn_on()); - } - - /// Turn the logger off, i.e. it no long emits logs. - #[cfg(feature = "tracing")] - #[wasm_bindgen(js_name = "turnOff")] - pub fn turn_off(&self) { - let _ = self.handle.modify(|layer| layer.turn_off()); - } -} - /// Logger level. #[wasm_bindgen] #[derive(Debug, Clone)] @@ -135,141 +32,257 @@ pub enum LoggerLevel { } #[cfg(feature = "tracing")] -impl From for Level { - fn from(value: LoggerLevel) -> Self { - use LoggerLevel::*; +mod inner { + use std::{ + fmt, + fmt::Write as _, + sync::{Arc, Once}, + }; - match value { - Trace => Self::TRACE, - Debug => Self::DEBUG, - Info => Self::INFO, - Warn => Self::WARN, - Error => Self::ERROR, + use super::*; + use tracing::{ + field::{Field, Visit}, + metadata::LevelFilter, + Event, Level, Metadata, Subscriber, + }; + use tracing_subscriber::{ + layer::{Context, Layer as TracingLayer}, + prelude::*, + reload, Registry, + }; + + type TracingInner = Arc>; + + /// Type to install and to manipulate the tracing layer. + #[wasm_bindgen] + pub struct Tracing { + handle: TracingInner, + } + + impl fmt::Debug for Tracing { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Tracing").finish_non_exhaustive() } } -} -#[cfg(feature = "tracing")] -#[wasm_bindgen] -extern "C" { - #[wasm_bindgen(js_namespace = console, js_name = "trace")] - fn log_trace(message: String); + #[wasm_bindgen] + impl Tracing { + /// Check whether the `tracing` feature has been enabled. + #[wasm_bindgen(js_name = "isAvailable")] + pub fn is_available() -> bool { + true + } - #[wasm_bindgen(js_namespace = console, js_name = "debug")] - fn log_debug(message: String); + /// Install the tracing layer. + /// + /// `Tracing` is a singleton. Once it is installed, consecutive + /// calls to `install` will construct a new `Tracing` object but + /// with the exact same inner state. Calling `install` with a new + /// `min_level` will just update the `min_level` parameter; in + /// that regard, it is similar to calling the `min_level` method + /// on an existing `Tracing` object. + #[wasm_bindgen(constructor)] + pub fn new(min_level: LoggerLevel) -> Result { + static mut INSTALL: Option = None; + static INSTALLED: Once = Once::new(); - #[wasm_bindgen(js_namespace = console, js_name = "info")] - fn log_info(message: String); + INSTALLED.call_once(|| { + let (filter, reload_handle) = reload::Layer::new(Layer::new(min_level.clone())); - #[wasm_bindgen(js_namespace = console, js_name = "warn")] - fn log_warn(message: String); + tracing_subscriber::registry().with(filter).init(); - #[wasm_bindgen(js_namespace = console, js_name = "log")] - fn log(message: String); -} + unsafe { INSTALL = Some(Arc::new(reload_handle)) }; + }); -#[cfg(feature = "tracing")] -struct Layer { - min_level: Level, - enabled: bool, -} + let tracing = Tracing { + handle: unsafe { INSTALL.as_ref() } + .cloned() + .expect("`Tracing` has not been installed correctly"), + }; -#[cfg(feature = "tracing")] -impl Layer { - fn new(min_level: L) -> Self + // If it's not the first call to `install`, the + // `min_level` can be different. Let's update it. + tracing.min_level(min_level); + + Ok(tracing) + } + + /// Re-define the minimum logger level. + #[wasm_bindgen(setter, js_name = "minLevel")] + pub fn min_level(&self, min_level: LoggerLevel) { + let _ = self.handle.modify(|layer| layer.min_level = min_level.into()); + } + + /// Turn the logger on, i.e. it emits logs again if it was turned + /// off. + #[wasm_bindgen(js_name = "turnOn")] + pub fn turn_on(&self) { + let _ = self.handle.modify(|layer| layer.turn_on()); + } + + /// Turn the logger off, i.e. it no long emits logs. + #[wasm_bindgen(js_name = "turnOff")] + pub fn turn_off(&self) { + let _ = self.handle.modify(|layer| layer.turn_off()); + } + } + + impl From for Level { + fn from(value: LoggerLevel) -> Self { + use LoggerLevel::*; + + match value { + Trace => Self::TRACE, + Debug => Self::DEBUG, + Info => Self::INFO, + Warn => Self::WARN, + Error => Self::ERROR, + } + } + } + + #[wasm_bindgen] + extern "C" { + #[wasm_bindgen(js_namespace = console, js_name = "trace")] + fn log_trace(message: String); + + #[wasm_bindgen(js_namespace = console, js_name = "debug")] + fn log_debug(message: String); + + #[wasm_bindgen(js_namespace = console, js_name = "info")] + fn log_info(message: String); + + #[wasm_bindgen(js_namespace = console, js_name = "warn")] + fn log_warn(message: String); + + #[wasm_bindgen(js_namespace = console, js_name = "log")] + fn log(message: String); + } + + struct Layer { + min_level: Level, + enabled: bool, + } + + impl Layer { + fn new(min_level: L) -> Self + where + L: Into, + { + Self { min_level: min_level.into(), enabled: true } + } + + fn turn_on(&mut self) { + self.enabled = true; + } + + fn turn_off(&mut self) { + self.enabled = false; + } + } + + impl TracingLayer for Layer where - L: Into, + S: Subscriber, { - Self { min_level: min_level.into(), enabled: true } - } + fn enabled(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool { + self.enabled && metadata.level() <= &self.min_level + } - fn turn_on(&mut self) { - self.enabled = true; - } + fn max_level_hint(&self) -> Option { + if !self.enabled { + Some(LevelFilter::OFF) + } else { + Some(LevelFilter::from_level(self.min_level)) + } + } - fn turn_off(&mut self) { - self.enabled = false; - } -} + fn on_event(&self, event: &Event<'_>, _: Context<'_, S>) { + let mut recorder = StringVisitor::new(); + event.record(&mut recorder); + let metadata = event.metadata(); + let level = metadata.level(); -#[cfg(feature = "tracing")] -impl TracingLayer for Layer -where - S: Subscriber, -{ - fn enabled(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool { - self.enabled && metadata.level() <= &self.min_level - } + let origin = metadata + .file() + .and_then(|file| metadata.line().map(|ln| format!("{}:{}", file, ln))) + .unwrap_or_default(); - fn max_level_hint(&self) -> Option { - if !self.enabled { - Some(LevelFilter::OFF) - } else { - Some(LevelFilter::from_level(self.min_level)) + let message = format!("{level} {origin}{recorder}"); + + match *level { + Level::TRACE => log_trace(message), + Level::DEBUG => log_debug(message), + Level::INFO => log_info(message), + Level::WARN => log_warn(message), + Level::ERROR => log(message), + } } } - fn on_event(&self, event: &Event<'_>, _: Context<'_, S>) { - let mut recorder = StringVisitor::new(); - event.record(&mut recorder); - let metadata = event.metadata(); - let level = metadata.level(); + struct StringVisitor { + string: String, + } - let origin = metadata - .file() - .and_then(|file| metadata.line().map(|ln| format!("{}:{}", file, ln))) - .unwrap_or_default(); - - let message = format!("{level} {origin}{recorder}"); - - match *level { - Level::TRACE => log_trace(message), - Level::DEBUG => log_debug(message), - Level::INFO => log_info(message), - Level::WARN => log_warn(message), - Level::ERROR => log(message), + impl StringVisitor { + fn new() -> Self { + Self { string: String::new() } } } -} -#[cfg(feature = "tracing")] -struct StringVisitor { - string: String, -} + impl Visit for StringVisitor { + fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { + match field.name() { + "message" => { + if !self.string.is_empty() { + self.string.push('\n'); + } -#[cfg(feature = "tracing")] -impl StringVisitor { - fn new() -> Self { - Self { string: String::new() } - } -} - -#[cfg(feature = "tracing")] -impl Visit for StringVisitor { - fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { - match field.name() { - "message" => { - if !self.string.is_empty() { - self.string.push('\n'); + let _ = write!(self.string, "{:?}", value); } - let _ = write!(self.string, "{:?}", value); + field_name => { + let _ = write!(self.string, "\n{} = {:?}", field_name, value); + } } + } + } - field_name => { - let _ = write!(self.string, "\n{} = {:?}", field_name, value); + impl fmt::Display for StringVisitor { + fn fmt(&self, mut f: &mut fmt::Formatter<'_>) -> fmt::Result { + if !self.string.is_empty() { + write!(&mut f, " {}", self.string) + } else { + Ok(()) } } } } -#[cfg(feature = "tracing")] -impl fmt::Display for StringVisitor { - fn fmt(&self, mut f: &mut fmt::Formatter<'_>) -> fmt::Result { - if !self.string.is_empty() { - write!(&mut f, " {}", self.string) - } else { - Ok(()) +#[cfg(not(feature = "tracing"))] +mod inner { + use super::*; + + /// Type to install and to manipulate the tracing layer. + #[wasm_bindgen] + #[derive(Debug)] + pub struct Tracing; + + #[wasm_bindgen] + impl Tracing { + /// Check whether the `tracing` feature has been enabled. + #[wasm_bindgen(js_name = "isAvailable")] + pub fn is_available() -> bool { + false + } + + /// The `tracing` feature is not enabled, so this constructor + /// will raise an error. + #[wasm_bindgen(constructor)] + pub fn new(_min_level: LoggerLevel) -> Result { + Err(JsError::new("The `tracing` feature is disabled. Check `Tracing.isAvailable` before constructing `Tracing`")) } } } + +pub use inner::*; diff --git a/bindings/matrix-sdk-crypto-js/tests/tracing.test.js b/bindings/matrix-sdk-crypto-js/tests/tracing.test.js index 0ce28cc6f..bf27431ee 100644 --- a/bindings/matrix-sdk-crypto-js/tests/tracing.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/tracing.test.js @@ -12,12 +12,12 @@ describe('LoggerLevel', () => { describe(Tracing.name, () => { if (Tracing.isAvailable()) { - let tracing = Tracing.install(LoggerLevel.Debug); + let tracing = new Tracing(LoggerLevel.Debug); test('can installed several times', () => { - Tracing.install(LoggerLevel.Debug); - Tracing.install(LoggerLevel.Warn); - Tracing.install(LoggerLevel.Debug); + new Tracing(LoggerLevel.Debug); + new Tracing(LoggerLevel.Warn); + new Tracing(LoggerLevel.Debug); }); const originalConsoleDebug = console.debug; @@ -78,7 +78,7 @@ describe(Tracing.name, () => { } } else { test('cannot be constructed', () => { - expect(Tracing.install(LoggerLevel.Error)).toBeUndefined(); + expect(() => { new Tracing(LoggerLevel.Error) }).toThrow(); }); } }); From 3d1c96fbecf4c77f1abb0406fec42f8cd92a600d Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 18 Jul 2022 09:51:44 +0200 Subject: [PATCH 39/73] feat(bindings/crypto-js): Redirect errors to `console.error`. --- bindings/matrix-sdk-crypto-js/src/tracing.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/src/tracing.rs b/bindings/matrix-sdk-crypto-js/src/tracing.rs index cf1f98d63..98599dd36 100644 --- a/bindings/matrix-sdk-crypto-js/src/tracing.rs +++ b/bindings/matrix-sdk-crypto-js/src/tracing.rs @@ -155,8 +155,8 @@ mod inner { #[wasm_bindgen(js_namespace = console, js_name = "warn")] fn log_warn(message: String); - #[wasm_bindgen(js_namespace = console, js_name = "log")] - fn log(message: String); + #[wasm_bindgen(js_namespace = console, js_name = "error")] + fn log_error(message: String); } struct Layer { @@ -215,7 +215,7 @@ mod inner { Level::DEBUG => log_debug(message), Level::INFO => log_info(message), Level::WARN => log_warn(message), - Level::ERROR => log(message), + Level::ERROR => log_error(message), } } } From daa0fc02069afb837a90babfac97ae54c51d3f1f Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 18 Jul 2022 10:05:05 +0200 Subject: [PATCH 40/73] doc(bindings/crypto-js): Fix typos. --- bindings/matrix-sdk-crypto-js/src/tracing.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/bindings/matrix-sdk-crypto-js/src/tracing.rs b/bindings/matrix-sdk-crypto-js/src/tracing.rs index 98599dd36..ac0196c24 100644 --- a/bindings/matrix-sdk-crypto-js/src/tracing.rs +++ b/bindings/matrix-sdk-crypto-js/src/tracing.rs @@ -75,12 +75,13 @@ mod inner { /// Install the tracing layer. /// - /// `Tracing` is a singleton. Once it is installed, consecutive - /// calls to `install` will construct a new `Tracing` object but - /// with the exact same inner state. Calling `install` with a new - /// `min_level` will just update the `min_level` parameter; in - /// that regard, it is similar to calling the `min_level` method - /// on an existing `Tracing` object. + /// `Tracing` is a singleton. Once it is installed, + /// consecutive calls to the constructor will construct a new + /// `Tracing` object but with the exact same inner + /// state. Calling the constructor with a new `min_level` will + /// just update the `min_level` parameter; in that regard, it + /// is similar to calling the `min_level` method on an + /// existing `Tracing` object. #[wasm_bindgen(constructor)] pub fn new(min_level: LoggerLevel) -> Result { static mut INSTALL: Option = None; From 5d916e4a67be741f5e8eb9974136904bffa14d50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= Date: Sun, 17 Jul 2022 14:09:53 +0200 Subject: [PATCH 41/73] test: Expose default room ID used in sync JSON responses --- crates/matrix-sdk-appservice/tests/tests.rs | 4 +-- .../src/store/integration_tests.rs | 2 +- crates/matrix-sdk-test/src/appservice.rs | 5 ++- crates/matrix-sdk-test/src/lib.rs | 5 ++- crates/matrix-sdk-test/src/test_json/mod.rs | 4 +-- crates/matrix-sdk-test/src/test_json/sync.rs | 5 +++ crates/matrix-sdk/src/client/mod.rs | 4 +-- crates/matrix-sdk/src/encryption/mod.rs | 5 ++- crates/matrix-sdk/tests/integration/client.rs | 4 +-- .../tests/integration/room/common.rs | 12 +++---- .../tests/integration/room/joined.rs | 32 +++++++++---------- .../matrix-sdk/tests/integration/room/left.rs | 3 +- 12 files changed, 43 insertions(+), 42 deletions(-) diff --git a/crates/matrix-sdk-appservice/tests/tests.rs b/crates/matrix-sdk-appservice/tests/tests.rs index 5dd10d24c..6286333bf 100644 --- a/crates/matrix-sdk-appservice/tests/tests.rs +++ b/crates/matrix-sdk-appservice/tests/tests.rs @@ -9,7 +9,7 @@ use matrix_sdk::{ Client, }; use matrix_sdk_appservice::*; -use matrix_sdk_test::{appservice::TransactionBuilder, async_test, EventsJson}; +use matrix_sdk_test::{appservice::TransactionBuilder, async_test, test_json, EventsJson}; use ruma::{ api::{appservice::event::push_events, MatrixVersion}, events::AnyRoomEvent, @@ -338,7 +338,7 @@ async fn test_unrelated_path() -> Result<()> { #[async_test] async fn test_appservice_on_sub_path() -> Result<()> { - let room_id = room_id!("!SVkFJHzfwvuaIEawgC:localhost"); + let room_id = &test_json::DEFAULT_SYNC_ROOM_ID; let uri_1 = "/sub_path/_matrix/app/v1/transactions/1?access_token=hs_token"; let uri_2 = "/sub_path/_matrix/app/v1/transactions/2?access_token=hs_token"; diff --git a/crates/matrix-sdk-base/src/store/integration_tests.rs b/crates/matrix-sdk-base/src/store/integration_tests.rs index 4960110b7..6721a8ad9 100644 --- a/crates/matrix-sdk-base/src/store/integration_tests.rs +++ b/crates/matrix-sdk-base/src/store/integration_tests.rs @@ -641,7 +641,7 @@ macro_rules! statestore_integration_tests { async fn test_room_timeline() { let store = get_store().await.unwrap(); let mut stored_events = Vec::new(); - let room_id = room_id!("!SVkFJHzfwvuaIEawgC:localhost"); + let room_id = *test_json::DEFAULT_SYNC_ROOM_ID; // Before the first sync the timeline should be empty assert!(store.room_timeline(room_id).await.expect("failed to read timeline").is_none(), "TL wasn't empty"); diff --git a/crates/matrix-sdk-test/src/appservice.rs b/crates/matrix-sdk-test/src/appservice.rs index a7712e327..4182667c1 100644 --- a/crates/matrix-sdk-test/src/appservice.rs +++ b/crates/matrix-sdk-test/src/appservice.rs @@ -1,6 +1,6 @@ use std::convert::TryFrom; -use ruma::{events::AnyRoomEvent, room_id, serde::Raw}; +use ruma::{events::AnyRoomEvent, serde::Raw}; use serde_json::Value; use crate::{test_json, EventsJson}; @@ -12,8 +12,7 @@ use crate::{test_json, EventsJson}; /// issue #15701 for more information" pub fn value_with_room_id(value: &Value) -> Value { let mut val = value.clone(); - let room_id = - Value::try_from(room_id!("!SVkFJHzfwvuaIEawgC:localhost").to_string()).expect("room_id"); + let room_id = Value::try_from(test_json::DEFAULT_SYNC_ROOM_ID.to_string()).expect("room_id"); val.as_object_mut().expect("mutable test_json").insert("room_id".to_owned(), room_id); val diff --git a/crates/matrix-sdk-test/src/lib.rs b/crates/matrix-sdk-test/src/lib.rs index 40a1de7c3..9098ae4cf 100644 --- a/crates/matrix-sdk-test/src/lib.rs +++ b/crates/matrix-sdk-test/src/lib.rs @@ -8,7 +8,6 @@ use ruma::{ presence::PresenceEvent, AnyGlobalAccountDataEvent, AnySyncEphemeralRoomEvent, AnySyncRoomEvent, AnySyncStateEvent, }, - room_id, serde::Raw, OwnedRoomId, RoomId, }; @@ -151,7 +150,7 @@ impl EventBuilder { let event = serde_json::from_value(val.clone()).unwrap(); - self.add_joined_event(room_id!("!SVkFJHzfwvuaIEawgC:localhost"), event); + self.add_joined_event(*test_json::DEFAULT_SYNC_ROOM_ID, event); self } @@ -229,7 +228,7 @@ impl EventBuilder { /// [build_sync_response()](#method.build_sync_response) if you need a typed /// response. pub fn build_json_sync_response(&mut self) -> JsonValue { - let main_room_id = room_id!("!SVkFJHzfwvuaIEawgC:localhost"); + let main_room_id = *test_json::DEFAULT_SYNC_ROOM_ID; // First time building a sync response, so initialize the `prev_batch` to a // default one. diff --git a/crates/matrix-sdk-test/src/test_json/mod.rs b/crates/matrix-sdk-test/src/test_json/mod.rs index c05d7f3b7..54ff95bb7 100644 --- a/crates/matrix-sdk-test/src/test_json/mod.rs +++ b/crates/matrix-sdk-test/src/test_json/mod.rs @@ -21,8 +21,8 @@ pub use events::{ }; pub use members::MEMBERS; pub use sync::{ - DEFAULT_SYNC_SUMMARY, INVITE_SYNC, LEAVE_SYNC, LEAVE_SYNC_EVENT, MORE_SYNC, MORE_SYNC_2, SYNC, - VOIP_SYNC, + DEFAULT_SYNC_ROOM_ID, DEFAULT_SYNC_SUMMARY, INVITE_SYNC, LEAVE_SYNC, LEAVE_SYNC_EVENT, + MORE_SYNC, MORE_SYNC_2, SYNC, VOIP_SYNC, }; pub static DEVICES: Lazy = Lazy::new(|| { diff --git a/crates/matrix-sdk-test/src/test_json/sync.rs b/crates/matrix-sdk-test/src/test_json/sync.rs index 265534359..5eee2e23d 100644 --- a/crates/matrix-sdk-test/src/test_json/sync.rs +++ b/crates/matrix-sdk-test/src/test_json/sync.rs @@ -1,6 +1,11 @@ use once_cell::sync::Lazy; +use ruma::{room_id, RoomId}; use serde_json::{json, Value as JsonValue}; +/// The default room ID where sync events are added. +pub static DEFAULT_SYNC_ROOM_ID: Lazy<&RoomId> = + Lazy::new(|| room_id!("!SVkFJHzfwvuaIEawgC:localhost")); + pub static SYNC: Lazy = Lazy::new(|| { json!({ "device_one_time_keys_count": {}, diff --git a/crates/matrix-sdk/src/client/mod.rs b/crates/matrix-sdk/src/client/mod.rs index 57d312382..9e57be3aa 100644 --- a/crates/matrix-sdk/src/client/mod.rs +++ b/crates/matrix-sdk/src/client/mod.rs @@ -2210,7 +2210,7 @@ pub(crate) mod tests { #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); - use ruma::{api::MatrixVersion, device_id, room_id, user_id, UserId}; + use ruma::{api::MatrixVersion, device_id, user_id, UserId}; use url::Url; use wiremock::{ matchers::{header, method, path}, @@ -2321,7 +2321,7 @@ pub(crate) mod tests { .build_sync_response(); client.inner.base_client.receive_sync_response(response).await.unwrap(); - let room_id = room_id!("!SVkFJHzfwvuaIEawgC:localhost"); + let room_id = &test_json::DEFAULT_SYNC_ROOM_ID; assert_eq!(client.homeserver().await, Url::parse(&server.uri()).unwrap()); diff --git a/crates/matrix-sdk/src/encryption/mod.rs b/crates/matrix-sdk/src/encryption/mod.rs index a76ec8d19..e2f26b147 100644 --- a/crates/matrix-sdk/src/encryption/mod.rs +++ b/crates/matrix-sdk/src/encryption/mod.rs @@ -872,11 +872,10 @@ impl Encryption { #[cfg(all(test, not(target_arch = "wasm32")))] mod tests { - use matrix_sdk_test::{async_test, EventBuilder, EventsJson}; + use matrix_sdk_test::{async_test, test_json, EventBuilder, EventsJson}; use ruma::{ event_id, events::reaction::{ReactionEventContent, Relation}, - room_id, }; use serde_json::json; use wiremock::{ @@ -892,7 +891,7 @@ mod tests { let client = logged_in_client(Some(server.uri())).await; let event_id = event_id!("$2:example.org"); - let room_id = room_id!("!SVkFJHzfwvuaIEawgC:localhost"); + let room_id = &test_json::DEFAULT_SYNC_ROOM_ID; Mock::given(method("PUT")) .and(path_regex(r"^/_matrix/client/r0/rooms/.*/send/m%2Ereaction/.*".to_owned())) diff --git a/crates/matrix-sdk/tests/integration/client.rs b/crates/matrix-sdk/tests/integration/client.rs index f82e9ea52..c5c7b4cd0 100644 --- a/crates/matrix-sdk/tests/integration/client.rs +++ b/crates/matrix-sdk/tests/integration/client.rs @@ -365,7 +365,7 @@ async fn resolve_room_alias() { #[async_test] async fn join_leave_room() { - let room_id = room_id!("!SVkFJHzfwvuaIEawgC:localhost"); + let room_id = &test_json::DEFAULT_SYNC_ROOM_ID; let (client, server) = logged_in_client().await; mock_sync(&server, &*test_json::SYNC, None).await; @@ -501,7 +501,7 @@ async fn left_rooms() { assert!(!client.left_rooms().is_empty()); assert!(client.invited_rooms().is_empty()); - assert!(client.get_left_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).is_some()) + assert!(client.get_left_room(&test_json::DEFAULT_SYNC_ROOM_ID).is_some()) } #[async_test] diff --git a/crates/matrix-sdk/tests/integration/room/common.rs b/crates/matrix-sdk/tests/integration/room/common.rs index c9c9bd177..ba5045483 100644 --- a/crates/matrix-sdk/tests/integration/room/common.rs +++ b/crates/matrix-sdk/tests/integration/room/common.rs @@ -32,7 +32,7 @@ async fn user_presence() { let _response = client.sync_once(sync_settings).await.unwrap(); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); let members: Vec = room.active_members().await.unwrap(); assert_eq!(2, members.len()); @@ -47,7 +47,7 @@ async fn calculate_room_names_from_summary() { let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); let _response = client.sync_once(sync_settings).await.unwrap(); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); assert_eq!(DisplayName::Calculated("example2".to_owned()), room.display_name().await.unwrap()); } @@ -63,7 +63,7 @@ async fn room_names() { let _response = client.sync_once(sync_settings).await.unwrap(); assert_eq!(client.rooms().len(), 1); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); assert_eq!(DisplayName::Aliased("tutorial".to_owned()), room.display_name().await.unwrap()); @@ -83,7 +83,7 @@ async fn room_names() { #[async_test] async fn test_state_event_getting() { - let room_id = room_id!("!SVkFJHzfwvuaIEawgC:localhost"); + let room_id = &test_json::DEFAULT_SYNC_ROOM_ID; let (client, server) = logged_in_client().await; @@ -187,7 +187,7 @@ async fn room_timeline_with_remove() { let _ = client.sync_once(sync_settings).await.unwrap(); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); let (forward_stream, backward_stream) = room.timeline().await.unwrap(); // these two syncs lead to the store removing its existing timeline @@ -288,7 +288,7 @@ async fn room_timeline() { let _ = client.sync_once(sync_settings).await.unwrap(); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); let (forward_stream, backward_stream) = room.timeline().await.unwrap(); let sync_token = client.sync_token().await.unwrap(); diff --git a/crates/matrix-sdk/tests/integration/room/joined.rs b/crates/matrix-sdk/tests/integration/room/joined.rs index 06b46aaf8..78d00a239 100644 --- a/crates/matrix-sdk/tests/integration/room/joined.rs +++ b/crates/matrix-sdk/tests/integration/room/joined.rs @@ -10,7 +10,7 @@ use matrix_sdk::{ use matrix_sdk_test::{async_test, test_json}; use ruma::{ api::client::membership::Invite3pidInit, assign, event_id, - events::room::message::RoomMessageEventContent, mxc_uri, room_id, thirdparty, uint, user_id, + events::room::message::RoomMessageEventContent, mxc_uri, thirdparty, uint, user_id, TransactionId, }; use serde_json::json; @@ -39,7 +39,7 @@ async fn invite_user_by_id() { let _response = client.sync_once(sync_settings).await.unwrap(); let user = user_id!("@example:localhost"); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); room.invite_user_by_id(user).await.unwrap(); } @@ -61,7 +61,7 @@ async fn invite_user_by_3pid() { let _response = client.sync_once(sync_settings).await.unwrap(); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); room.invite_user_by_3pid( Invite3pidInit { @@ -93,7 +93,7 @@ async fn leave_room() { let _response = client.sync_once(sync_settings).await.unwrap(); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); room.leave().await.unwrap(); } @@ -116,7 +116,7 @@ async fn ban_user() { let _response = client.sync_once(sync_settings).await.unwrap(); let user = user_id!("@example:localhost"); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); room.ban_user(user, None).await.unwrap(); } @@ -139,7 +139,7 @@ async fn kick_user() { let _response = client.sync_once(sync_settings).await.unwrap(); let user = user_id!("@example:localhost"); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); room.kick_user(user, None).await.unwrap(); } @@ -162,7 +162,7 @@ async fn read_receipt() { let _response = client.sync_once(sync_settings).await.unwrap(); let event_id = event_id!("$xxxxxx:example.org"); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); room.read_receipt(event_id).await.unwrap(); } @@ -185,7 +185,7 @@ async fn read_marker() { let _response = client.sync_once(sync_settings).await.unwrap(); let event_id = event_id!("$xxxxxx:example.org"); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); room.read_marker(event_id, None).await.unwrap(); } @@ -207,7 +207,7 @@ async fn typing_notice() { let _response = client.sync_once(sync_settings).await.unwrap(); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); room.typing_notice(true).await.unwrap(); } @@ -231,7 +231,7 @@ async fn room_state_event_send() { let _response = client.sync_once(sync_settings).await.unwrap(); - let room_id = room_id!("!SVkFJHzfwvuaIEawgC:localhost"); + let room_id = &test_json::DEFAULT_SYNC_ROOM_ID; let room = client.get_joined_room(room_id).unwrap(); @@ -260,7 +260,7 @@ async fn room_message_send() { let _response = client.sync_once(sync_settings).await.unwrap(); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); let content = RoomMessageEventContent::text_plain("Hello world"); let txn_id = TransactionId::new(); @@ -301,7 +301,7 @@ async fn room_attachment_send() { let _response = client.sync_once(sync_settings).await.unwrap(); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); let mut media = Cursor::new("Hello world"); @@ -347,7 +347,7 @@ async fn room_attachment_send_info() { let _response = client.sync_once(sync_settings).await.unwrap(); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); let mut media = Cursor::new("Hello world"); @@ -398,7 +398,7 @@ async fn room_attachment_send_wrong_info() { let _response = client.sync_once(sync_settings).await.unwrap(); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); let mut media = Cursor::new("Hello world"); @@ -457,7 +457,7 @@ async fn room_attachment_send_info_thumbnail() { let _response = client.sync_once(sync_settings).await.unwrap(); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); let mut media = Cursor::new("Hello world"); @@ -502,7 +502,7 @@ async fn room_redact() { let _response = client.sync_once(sync_settings).await.unwrap(); - let room = client.get_joined_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_joined_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); let event_id = event_id!("$xxxxxxxx:example.com"); diff --git a/crates/matrix-sdk/tests/integration/room/left.rs b/crates/matrix-sdk/tests/integration/room/left.rs index 2614db150..6e422608f 100644 --- a/crates/matrix-sdk/tests/integration/room/left.rs +++ b/crates/matrix-sdk/tests/integration/room/left.rs @@ -2,7 +2,6 @@ use std::time::Duration; use matrix_sdk::config::SyncSettings; use matrix_sdk_test::{async_test, test_json}; -use ruma::room_id; use wiremock::{ matchers::{header, method, path_regex}, Mock, ResponseTemplate, @@ -27,7 +26,7 @@ async fn forget_room() { let _response = client.sync_once(sync_settings).await.unwrap(); - let room = client.get_left_room(room_id!("!SVkFJHzfwvuaIEawgC:localhost")).unwrap(); + let room = client.get_left_room(&test_json::DEFAULT_SYNC_ROOM_ID).unwrap(); room.forget().await.unwrap(); } From 45ecd8938758600e2be39c08a369a289e54f12be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= Date: Sun, 17 Jul 2022 17:54:54 +0200 Subject: [PATCH 42/73] test: Build sync response per room and event type Allow to have more customizable and complete responses --- crates/matrix-sdk-appservice/tests/tests.rs | 16 +- crates/matrix-sdk-base/src/client.rs | 23 +- crates/matrix-sdk-test/src/appservice.rs | 21 +- .../src/event_builder/invited_room.rs | 31 ++ .../src/event_builder/joined_room.rs | 74 ++++ .../src/event_builder/left_room.rs | 55 +++ .../matrix-sdk-test/src/event_builder/mod.rs | 228 +++++++++++ .../src/event_builder/test_event.rs | 235 +++++++++++ crates/matrix-sdk-test/src/lib.rs | 378 +----------------- crates/matrix-sdk/src/client/mod.rs | 9 +- crates/matrix-sdk/src/encryption/mod.rs | 11 +- crates/matrix-sdk/src/event_handler.rs | 86 ++-- 12 files changed, 716 insertions(+), 451 deletions(-) create mode 100644 crates/matrix-sdk-test/src/event_builder/invited_room.rs create mode 100644 crates/matrix-sdk-test/src/event_builder/joined_room.rs create mode 100644 crates/matrix-sdk-test/src/event_builder/left_room.rs create mode 100644 crates/matrix-sdk-test/src/event_builder/mod.rs create mode 100644 crates/matrix-sdk-test/src/event_builder/test_event.rs diff --git a/crates/matrix-sdk-appservice/tests/tests.rs b/crates/matrix-sdk-appservice/tests/tests.rs index 6286333bf..fbebc9670 100644 --- a/crates/matrix-sdk-appservice/tests/tests.rs +++ b/crates/matrix-sdk-appservice/tests/tests.rs @@ -9,7 +9,7 @@ use matrix_sdk::{ Client, }; use matrix_sdk_appservice::*; -use matrix_sdk_test::{appservice::TransactionBuilder, async_test, test_json, EventsJson}; +use matrix_sdk_test::{appservice::TransactionBuilder, async_test, test_json, TimelineTestEvent}; use ruma::{ api::{appservice::event::push_events, MatrixVersion}, events::AnyRoomEvent, @@ -92,7 +92,7 @@ async fn test_put_transaction() -> Result<()> { let uri = "/_matrix/app/v1/transactions/1?access_token=hs_token"; let mut transaction_builder = TransactionBuilder::new(); - transaction_builder.add_room_event(EventsJson::Member); + transaction_builder.add_room_event(TimelineTestEvent::Member); let transaction = transaction_builder.build_json_transaction(); let appservice = appservice(None, None).await?; @@ -117,7 +117,7 @@ async fn test_put_transaction_with_repeating_txn_id() -> Result<()> { let uri = "/_matrix/app/v1/transactions/1?access_token=hs_token"; let mut transaction_builder = TransactionBuilder::new(); - transaction_builder.add_room_event(EventsJson::Member); + transaction_builder.add_room_event(TimelineTestEvent::Member); let transaction = transaction_builder.build_json_transaction(); let appservice = appservice(None, None).await?; @@ -228,7 +228,7 @@ async fn test_invalid_access_token() -> Result<()> { let mut transaction_builder = TransactionBuilder::new(); let transaction = - transaction_builder.add_room_event(EventsJson::Member).build_json_transaction(); + transaction_builder.add_room_event(TimelineTestEvent::Member).build_json_transaction(); let appservice = appservice(None, None).await?; @@ -252,7 +252,7 @@ async fn test_no_access_token() -> Result<()> { let uri = "/_matrix/app/v1/transactions/1"; let mut transaction_builder = TransactionBuilder::new(); - transaction_builder.add_room_event(EventsJson::Member); + transaction_builder.add_room_event(TimelineTestEvent::Member); let transaction = transaction_builder.build_json_transaction(); let appservice = appservice(None, None).await?; @@ -295,7 +295,7 @@ async fn test_event_handler() -> Result<()> { let uri = "/_matrix/app/v1/transactions/1?access_token=hs_token"; let mut transaction_builder = TransactionBuilder::new(); - transaction_builder.add_room_event(EventsJson::Member); + transaction_builder.add_room_event(TimelineTestEvent::Member); let transaction = transaction_builder.build_json_transaction(); warp::test::request() @@ -343,11 +343,11 @@ async fn test_appservice_on_sub_path() -> Result<()> { let uri_2 = "/sub_path/_matrix/app/v1/transactions/2?access_token=hs_token"; let mut transaction_builder = TransactionBuilder::new(); - transaction_builder.add_room_event(EventsJson::Member); + transaction_builder.add_room_event(TimelineTestEvent::Member); let transaction_1 = transaction_builder.build_json_transaction(); let mut transaction_builder = TransactionBuilder::new(); - transaction_builder.add_room_event(EventsJson::MemberNameChange); + transaction_builder.add_room_event(TimelineTestEvent::MemberNameChange); let transaction_2 = transaction_builder.build_json_transaction(); let appservice = appservice(None, None).await?; diff --git a/crates/matrix-sdk-base/src/client.rs b/crates/matrix-sdk-base/src/client.rs index 5741a9ef0..e7efca697 100644 --- a/crates/matrix-sdk-base/src/client.rs +++ b/crates/matrix-sdk-base/src/client.rs @@ -1105,7 +1105,10 @@ impl Default for BaseClient { #[cfg(test)] mod tests { - use matrix_sdk_test::{async_test, response_from_file, EventBuilder}; + use matrix_sdk_test::{ + async_test, response_from_file, EventBuilder, InvitedRoomBuilder, LeftRoomBuilder, + StrippedStateTestEvent, TimelineTestEvent, + }; use ruma::{ api::{client as api, IncomingResponse}, room_id, user_id, @@ -1133,9 +1136,8 @@ mod tests { let mut ev_builder = EventBuilder::new(); let response = ev_builder - .add_custom_left_event( - room_id, - json!({ + .add_left_room(LeftRoomBuilder::new(room_id).add_timeline_event( + TimelineTestEvent::Custom(json!({ "content": { "displayname": "Alice", "membership": "left", @@ -1145,16 +1147,15 @@ mod tests { "sender": user_id, "state_key": user_id, "type": "m.room.member", - }), - ) + })), + )) .build_sync_response(); client.receive_sync_response(response).await.unwrap(); assert_eq!(client.get_room(room_id).unwrap().room_type(), RoomType::Left); let response = ev_builder - .add_custom_invited_event( - room_id, - json!({ + .add_invited_room(InvitedRoomBuilder::new(room_id).add_state_event( + StrippedStateTestEvent::Custom(json!({ "content": { "displayname": "Alice", "membership": "invite", @@ -1164,8 +1165,8 @@ mod tests { "sender": "@example:example.org", "state_key": user_id, "type": "m.room.member", - }), - ) + })), + )) .build_sync_response(); client.receive_sync_response(response).await.unwrap(); assert_eq!(client.get_room(room_id).unwrap().room_type(), RoomType::Invited); diff --git a/crates/matrix-sdk-test/src/appservice.rs b/crates/matrix-sdk-test/src/appservice.rs index 4182667c1..29244f00f 100644 --- a/crates/matrix-sdk-test/src/appservice.rs +++ b/crates/matrix-sdk-test/src/appservice.rs @@ -3,19 +3,16 @@ use std::convert::TryFrom; use ruma::{events::AnyRoomEvent, serde::Raw}; use serde_json::Value; -use crate::{test_json, EventsJson}; +use crate::{event_builder::TimelineTestEvent, test_json}; /// Clones the given [`Value`] and adds a `room_id` to it /// /// Adding the `room_id` conditionally with `cfg` directly to the lazy_static /// test_json values is blocked by "experimental attributes on expressions, see /// issue #15701 for more information" -pub fn value_with_room_id(value: &Value) -> Value { - let mut val = value.clone(); +pub fn value_with_room_id(value: &mut Value) { let room_id = Value::try_from(test_json::DEFAULT_SYNC_ROOM_ID.to_string()).expect("room_id"); - val.as_object_mut().expect("mutable test_json").insert("room_id".to_owned(), room_id); - - val + value.as_object_mut().expect("mutable test_json").insert("room_id".to_owned(), room_id); } /// The `TransactionBuilder` struct can be used to easily generate valid @@ -33,15 +30,9 @@ impl TransactionBuilder { } /// Add a room event. - pub fn add_room_event(&mut self, json: EventsJson) -> &mut Self { - let val: &Value = match json { - EventsJson::Member => &test_json::MEMBER, - EventsJson::MemberNameChange => &test_json::MEMBER_NAME_CHANGE, - EventsJson::PowerLevels => &test_json::POWER_LEVELS, - _ => panic!("unknown event json {:?}", json), - }; - - let val = value_with_room_id(val); + pub fn add_room_event(&mut self, event: TimelineTestEvent) -> &mut Self { + let mut val = event.into_json_value(); + value_with_room_id(&mut val); let event = serde_json::from_value(val).unwrap(); diff --git a/crates/matrix-sdk-test/src/event_builder/invited_room.rs b/crates/matrix-sdk-test/src/event_builder/invited_room.rs new file mode 100644 index 000000000..6c1c7238a --- /dev/null +++ b/crates/matrix-sdk-test/src/event_builder/invited_room.rs @@ -0,0 +1,31 @@ +use ruma::{api::client::sync::sync_events::v3::InvitedRoom, OwnedRoomId}; + +use super::StrippedStateTestEvent; +use crate::test_json; + +pub struct InvitedRoomBuilder { + pub(super) room_id: OwnedRoomId, + pub(super) inner: InvitedRoom, +} + +impl InvitedRoomBuilder { + /// Create a new `InvitedRoomBuilder` for the given room ID. + /// + /// If the room ID is [`test_json::DEFAULT_SYNC_ROOM_ID`], + /// [`InvitedRoomBuilder::default()`] can be used instead. + pub fn new(room_id: impl Into) -> Self { + Self { room_id: room_id.into(), inner: Default::default() } + } + + /// Add an event to the state. + pub fn add_state_event(mut self, event: StrippedStateTestEvent) -> Self { + self.inner.invite_state.events.push(event.into_raw_event()); + self + } +} + +impl Default for InvitedRoomBuilder { + fn default() -> Self { + Self::new(test_json::DEFAULT_SYNC_ROOM_ID.to_owned()) + } +} diff --git a/crates/matrix-sdk-test/src/event_builder/joined_room.rs b/crates/matrix-sdk-test/src/event_builder/joined_room.rs new file mode 100644 index 000000000..09839024f --- /dev/null +++ b/crates/matrix-sdk-test/src/event_builder/joined_room.rs @@ -0,0 +1,74 @@ +use ruma::{api::client::sync::sync_events::v3::JoinedRoom, OwnedRoomId}; +use serde_json::{from_value as from_json_value, Value as JsonValue}; + +use super::{EphemeralTestEvent, RoomAccountDataTestEvent, StateTestEvent, TimelineTestEvent}; +use crate::test_json; + +pub struct JoinedRoomBuilder { + pub(super) room_id: OwnedRoomId, + pub(super) inner: JoinedRoom, +} + +impl JoinedRoomBuilder { + /// Create a new `JoinedRoomBuilder` for the given room ID. + /// + /// If the room ID is [`test_json::DEFAULT_SYNC_ROOM_ID`], + /// [`JoinedRoomBuilder::default()`] can be used instead. + pub fn new(room_id: impl Into) -> Self { + Self { room_id: room_id.into(), inner: Default::default() } + } + + /// Add an event to the timeline. + pub fn add_timeline_event(mut self, event: TimelineTestEvent) -> Self { + self.inner.timeline.events.push(event.into_raw_event()); + self + } + + /// Set the timeline as limited. + pub fn set_timeline_limited(mut self) -> Self { + self.inner.timeline.limited = true; + self + } + + /// Set the `prev_batch` of the timeline. + pub fn set_timeline_prev_batch(mut self, prev_batch: String) -> Self { + self.inner.timeline.prev_batch = Some(prev_batch); + self + } + + /// Add an event to the state. + pub fn add_state_event(mut self, event: StateTestEvent) -> Self { + self.inner.state.events.push(event.into_raw_event()); + self + } + + /// Add an ephemeral event. + pub fn add_ephemeral_event(mut self, event: EphemeralTestEvent) -> Self { + self.inner.ephemeral.events.push(event.into_raw_event()); + self + } + + /// Add room account data. + pub fn add_account_data(mut self, event: RoomAccountDataTestEvent) -> Self { + self.inner.account_data.events.push(event.into_raw_event()); + self + } + + /// Set the room summary. + pub fn set_room_summary(mut self, summary: JsonValue) -> Self { + self.inner.summary = from_json_value(summary).unwrap(); + self + } + + /// Set the unread notifications count. + pub fn set_unread_notifications_count(mut self, unread_notifications: JsonValue) -> Self { + self.inner.unread_notifications = from_json_value(unread_notifications).unwrap(); + self + } +} + +impl Default for JoinedRoomBuilder { + fn default() -> Self { + Self::new(test_json::DEFAULT_SYNC_ROOM_ID.to_owned()) + } +} diff --git a/crates/matrix-sdk-test/src/event_builder/left_room.rs b/crates/matrix-sdk-test/src/event_builder/left_room.rs new file mode 100644 index 000000000..57710392e --- /dev/null +++ b/crates/matrix-sdk-test/src/event_builder/left_room.rs @@ -0,0 +1,55 @@ +use ruma::{api::client::sync::sync_events::v3::LeftRoom, OwnedRoomId}; + +use super::{RoomAccountDataTestEvent, StateTestEvent, TimelineTestEvent}; +use crate::test_json; + +pub struct LeftRoomBuilder { + pub(super) room_id: OwnedRoomId, + pub(super) inner: LeftRoom, +} + +impl LeftRoomBuilder { + /// Create a new `LeftRoomBuilder` for the given room ID. + /// + /// If the room ID is [`test_json::DEFAULT_SYNC_ROOM_ID`], + /// [`LeftRoomBuilder::default()`] can be used instead. + pub fn new(room_id: impl Into) -> Self { + Self { room_id: room_id.into(), inner: Default::default() } + } + + /// Add an event to the timeline. + pub fn add_timeline_event(mut self, event: TimelineTestEvent) -> Self { + self.inner.timeline.events.push(event.into_raw_event()); + self + } + + /// Set the timeline as limited. + pub fn set_timeline_limited(mut self) -> Self { + self.inner.timeline.limited = true; + self + } + + /// Set the `prev_batch` of the timeline. + pub fn set_timeline_prev_batch(mut self, prev_batch: String) -> Self { + self.inner.timeline.prev_batch = Some(prev_batch); + self + } + + /// Add an event to the state. + pub fn add_state_event(mut self, event: StateTestEvent) -> Self { + self.inner.state.events.push(event.into_raw_event()); + self + } + + /// Add room account data. + pub fn add_account_data(mut self, event: RoomAccountDataTestEvent) -> Self { + self.inner.account_data.events.push(event.into_raw_event()); + self + } +} + +impl Default for LeftRoomBuilder { + fn default() -> Self { + Self::new(test_json::DEFAULT_SYNC_ROOM_ID.to_owned()) + } +} diff --git a/crates/matrix-sdk-test/src/event_builder/mod.rs b/crates/matrix-sdk-test/src/event_builder/mod.rs new file mode 100644 index 000000000..21fd9619a --- /dev/null +++ b/crates/matrix-sdk-test/src/event_builder/mod.rs @@ -0,0 +1,228 @@ +use std::collections::HashMap; + +use http::Response; +use ruma::{ + api::{ + client::sync::sync_events::v3::{ + InvitedRoom, JoinedRoom, LeftRoom, Response as SyncResponse, + }, + IncomingResponse, + }, + events::{presence::PresenceEvent, AnyGlobalAccountDataEvent}, + serde::Raw, + OwnedRoomId, +}; +use serde_json::{from_value as from_json_value, json, Value as JsonValue}; + +use super::test_json; + +mod invited_room; +mod joined_room; +mod left_room; +mod test_event; + +pub use invited_room::InvitedRoomBuilder; +pub use joined_room::JoinedRoomBuilder; +pub use left_room::LeftRoomBuilder; +pub use test_event::{ + EphemeralTestEvent, GlobalAccountDataTestEvent, PresenceTestEvent, RoomAccountDataTestEvent, + StateTestEvent, StrippedStateTestEvent, TimelineTestEvent, +}; + +/// The `EventBuilder` struct can be used to easily generate valid sync +/// responses for testing. These can be then fed into either `Client` or `Room`. +/// +/// It supports generated a number of canned events, such as a member entering a +/// room, his power level and display name changing and similar. It also +/// supports insertion of custom events in the form of `EventsJson` values. +/// +/// **Important** You *must* use the *same* builder when sending multiple sync +/// responses to a single client. Otherwise, the subsequent responses will be +/// *ignored* by the client because the `next_batch` sync token will not be +/// rotated properly. +/// +/// # Example usage +/// +/// ```rust +/// use matrix_sdk_test::{EventBuilder, JoinedRoomBuilder, TimelineTestEvent}; +/// +/// let mut builder = EventBuilder::new(); +/// +/// // response1 now contains events that add an example member to the room and change their power +/// // level +/// let response1 = builder +/// .add_joined_room( +/// JoinedRoomBuilder::default() +/// .add_timeline_event(TimelineTestEvent::Member) +/// .add_timeline_event(TimelineTestEvent::PowerLevels) +/// ) +/// .build_sync_response(); +/// +/// // response2 is now empty (nothing changed) +/// let response2 = builder.build_sync_response(); +/// +/// // response3 contains a display name change for member example +/// let response3 = builder +/// .add_joined_room( +/// JoinedRoomBuilder::default() +/// .add_timeline_event(TimelineTestEvent::MemberNameChange) +/// .add_timeline_event(TimelineTestEvent::PowerLevels) +/// ) +/// .build_sync_response(); +/// ``` +#[derive(Default)] +pub struct EventBuilder { + /// Updates to joined `Room`s. + joined_rooms: HashMap, + /// Updates to invited `Room`s. + invited_rooms: HashMap, + /// Updates to left `Room`s. + left_rooms: HashMap, + /// Events that determine the presence state of a user. + presence: Vec>, + /// Global account data events. + account_data: Vec>, + /// Internal counter to enable the `prev_batch` and `next_batch` of each + /// sync response to vary. + batch_counter: i64, +} + +impl EventBuilder { + pub fn new() -> Self { + Self::default() + } + + /// Add a joined room to the next sync response. + /// + /// If a room with the same room ID already exists, it is replaced by this + /// one. + pub fn add_joined_room(&mut self, room: JoinedRoomBuilder) -> &mut Self { + self.invited_rooms.remove(&room.room_id); + self.left_rooms.remove(&room.room_id); + self.joined_rooms.insert(room.room_id, room.inner); + self + } + + /// Add an invited room to the next sync response. + /// + /// If a room with the same room ID already exists, it is replaced by this + /// one. + pub fn add_invited_room(&mut self, room: InvitedRoomBuilder) -> &mut Self { + self.joined_rooms.remove(&room.room_id); + self.left_rooms.remove(&room.room_id); + self.invited_rooms.insert(room.room_id, room.inner); + self + } + + /// Add a left room to the next sync response. + /// + /// If a room with the same room ID already exists, it is replaced by this + /// one. + pub fn add_left_room(&mut self, room: LeftRoomBuilder) -> &mut Self { + self.joined_rooms.remove(&room.room_id); + self.invited_rooms.remove(&room.room_id); + self.left_rooms.insert(room.room_id, room.inner); + self + } + + /// Add a presence event. + pub fn add_presence_event(&mut self, event: PresenceTestEvent) -> &mut Self { + let val = match event { + PresenceTestEvent::Presence => test_json::PRESENCE.to_owned(), + PresenceTestEvent::Custom(json) => json, + }; + + self.presence.push(from_json_value(val).unwrap()); + self + } + + /// Add global account data. + pub fn add_global_account_data_event( + &mut self, + event: GlobalAccountDataTestEvent, + ) -> &mut Self { + let val = match event { + GlobalAccountDataTestEvent::PushRules => test_json::PUSH_RULES.to_owned(), + GlobalAccountDataTestEvent::Tags => test_json::TAG.to_owned(), + GlobalAccountDataTestEvent::Custom(json) => json, + }; + + self.account_data.push(from_json_value(val).unwrap()); + self + } + + /// Builds a sync response as a JSON Value containing the events we queued + /// so far. + /// + /// The next response returned by `build_sync_response` will then be empty + /// if no further events were queued. + /// + /// This method is raw JSON equivalent to + /// [build_sync_response()](#method.build_sync_response), use + /// [build_sync_response()](#method.build_sync_response) if you need a typed + /// response. + pub fn build_json_sync_response(&mut self) -> JsonValue { + self.batch_counter += 1; + let next_batch = self.generate_sync_token(); + + let body = json! { + { + "device_one_time_keys_count": {}, + "next_batch": next_batch, + "device_lists": { + "changed": [], + "left": [], + }, + "rooms": { + "invite": self.invited_rooms, + "join": self.joined_rooms, + "leave": self.left_rooms, + }, + "to_device": { + "events": [] + }, + "presence": { + "events": self.presence, + }, + "account_data": { + "events": self.account_data, + }, + } + }; + + // Clear state so that the next sync response will be empty if nothing + // was added. + self.clear(); + + body + } + + /// Builds a `SyncResponse` containing the events we queued so far. + /// + /// The next response returned by `build_sync_response` will then be empty + /// if no further events were queued. + /// + /// This method is high level and typed equivalent to + /// [build_json_sync_response()](#method.build_json_sync_response), use + /// [build_json_sync_response()](#method.build_json_sync_response) if you + /// need an untyped response. + pub fn build_sync_response(&mut self) -> SyncResponse { + let body = self.build_json_sync_response(); + + let response = Response::builder().body(serde_json::to_vec(&body).unwrap()).unwrap(); + + SyncResponse::try_from_http_response(response).unwrap() + } + + fn generate_sync_token(&self) -> String { + format!("t392-516_47314_0_7_1_1_1_11444_{}", self.batch_counter) + } + + pub fn clear(&mut self) { + self.account_data.clear(); + self.invited_rooms.clear(); + self.joined_rooms.clear(); + self.left_rooms.clear(); + self.presence.clear(); + } +} diff --git a/crates/matrix-sdk-test/src/event_builder/test_event.rs b/crates/matrix-sdk-test/src/event_builder/test_event.rs new file mode 100644 index 000000000..577a8e35c --- /dev/null +++ b/crates/matrix-sdk-test/src/event_builder/test_event.rs @@ -0,0 +1,235 @@ +use ruma::{ + events::{ + presence::PresenceEvent, AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, + AnyStrippedStateEvent, AnySyncEphemeralRoomEvent, AnySyncRoomEvent, AnySyncStateEvent, + }, + serde::Raw, +}; +use serde_json::{from_value as from_json_value, Value as JsonValue}; + +use crate::test_json; + +/// Test events that can be added to the timeline. +pub enum TimelineTestEvent { + Alias, + Aliases, + Create, + Encryption, + HistoryVisibility, + JoinRules, + Member, + MemberInvite, + MemberNameChange, + MessageEdit, + MessageEmote, + MessageNotice, + MessageText, + PowerLevels, + Reaction, + RedactedInvalid, + RedactedMessage, + RedactedState, + Redaction, + RoomAvatar, + RoomName, + RoomTopic, + Custom(JsonValue), +} + +impl TimelineTestEvent { + /// Get the JSON representation of this test event. + pub fn into_json_value(self) -> JsonValue { + match self { + Self::Alias => test_json::events::ALIAS.to_owned(), + Self::Aliases => test_json::events::ALIASES.to_owned(), + Self::Create => test_json::events::CREATE.to_owned(), + Self::Encryption => test_json::events::ENCRYPTION.to_owned(), + Self::HistoryVisibility => test_json::events::HISTORY_VISIBILITY.to_owned(), + Self::JoinRules => test_json::events::JOIN_RULES.to_owned(), + Self::Member => test_json::events::MEMBER.to_owned(), + Self::MemberInvite => test_json::events::MEMBER_INVITE.to_owned(), + Self::MemberNameChange => test_json::events::MEMBER_NAME_CHANGE.to_owned(), + Self::MessageEdit => test_json::events::MESSAGE_EDIT.to_owned(), + Self::MessageEmote => test_json::events::MESSAGE_EMOTE.to_owned(), + Self::MessageNotice => test_json::events::MESSAGE_NOTICE.to_owned(), + Self::MessageText => test_json::events::MESSAGE_TEXT.to_owned(), + Self::PowerLevels => test_json::events::POWER_LEVELS.to_owned(), + Self::Reaction => test_json::events::REACTION.to_owned(), + Self::RedactedInvalid => test_json::events::REDACTED_INVALID.to_owned(), + Self::RedactedMessage => test_json::events::REDACTED.to_owned(), + Self::RedactedState => test_json::events::REDACTED_STATE.to_owned(), + Self::Redaction => test_json::events::REDACTION.to_owned(), + Self::RoomAvatar => test_json::events::ROOM_AVATAR.to_owned(), + Self::RoomName => test_json::events::NAME.to_owned(), + Self::RoomTopic => test_json::events::TOPIC.to_owned(), + Self::Custom(json) => json, + } + } + + /// Get the typed JSON representation of this test event. + pub fn into_raw_event(self) -> Raw { + from_json_value(self.into_json_value()).unwrap() + } +} + +/// Test events that can be added to the state. +pub enum StateTestEvent { + Alias, + Aliases, + Create, + Encryption, + HistoryVisibility, + JoinRules, + Member, + MemberInvite, + MemberNameChange, + PowerLevels, + RedactedInvalid, + RedactedState, + RoomAvatar, + RoomName, + RoomTopic, + Custom(JsonValue), +} + +impl StateTestEvent { + /// Get the JSON representation of this test event. + pub fn into_json_value(self) -> JsonValue { + match self { + Self::Alias => test_json::events::ALIAS.to_owned(), + Self::Aliases => test_json::events::ALIASES.to_owned(), + Self::Create => test_json::events::CREATE.to_owned(), + Self::Encryption => test_json::events::ENCRYPTION.to_owned(), + Self::HistoryVisibility => test_json::events::HISTORY_VISIBILITY.to_owned(), + Self::JoinRules => test_json::events::JOIN_RULES.to_owned(), + Self::Member => test_json::events::MEMBER.to_owned(), + Self::MemberInvite => test_json::events::MEMBER_INVITE.to_owned(), + Self::MemberNameChange => test_json::events::MEMBER_NAME_CHANGE.to_owned(), + Self::PowerLevels => test_json::events::POWER_LEVELS.to_owned(), + Self::RedactedInvalid => test_json::events::REDACTED_INVALID.to_owned(), + Self::RedactedState => test_json::events::REDACTED_STATE.to_owned(), + Self::RoomAvatar => test_json::events::ROOM_AVATAR.to_owned(), + Self::RoomName => test_json::events::NAME.to_owned(), + Self::RoomTopic => test_json::events::TOPIC.to_owned(), + Self::Custom(json) => json, + } + } + + /// Get the typed JSON representation of this test event. + pub fn into_raw_event(self) -> Raw { + from_json_value(self.into_json_value()).unwrap() + } +} + +/// Test events that can be added to the stripped state. +pub enum StrippedStateTestEvent { + Member, + RoomName, + Custom(JsonValue), +} + +impl StrippedStateTestEvent { + /// Get the JSON representation of this test event. + pub fn into_json_value(self) -> JsonValue { + match self { + Self::Member => test_json::events::MEMBER_STRIPPED.to_owned(), + Self::RoomName => test_json::events::NAME_STRIPPED.to_owned(), + Self::Custom(json) => json, + } + } + + /// Get the typed JSON representation of this test event. + pub fn into_raw_event(self) -> Raw { + from_json_value(self.into_json_value()).unwrap() + } +} + +/// Test events that can be added to the room account data. +pub enum RoomAccountDataTestEvent { + FullyRead, + Custom(JsonValue), +} + +impl RoomAccountDataTestEvent { + /// Get the JSON representation of this test event. + pub fn into_json_value(self) -> JsonValue { + match self { + Self::FullyRead => test_json::events::FULLY_READ.to_owned(), + Self::Custom(json) => json, + } + } + + /// Get the typed JSON representation of this test event. + pub fn into_raw_event(self) -> Raw { + from_json_value(self.into_json_value()).unwrap() + } +} + +/// Test events that can be added to the ephemeral events. +pub enum EphemeralTestEvent { + ReadReceipt, + ReadReceiptOther, + Typing, + Custom(JsonValue), +} + +impl EphemeralTestEvent { + /// Get the JSON representation of this test event. + pub fn into_json_value(self) -> JsonValue { + match self { + Self::ReadReceipt => test_json::events::READ_RECEIPT.to_owned(), + Self::ReadReceiptOther => test_json::events::READ_RECEIPT_OTHER.to_owned(), + Self::Typing => test_json::events::TYPING.to_owned(), + Self::Custom(json) => json, + } + } + + /// Get the typed JSON representation of this test event. + pub fn into_raw_event(self) -> Raw { + from_json_value(self.into_json_value()).unwrap() + } +} + +/// Test events that can be added to the presence events. +pub enum PresenceTestEvent { + Presence, + Custom(JsonValue), +} + +impl PresenceTestEvent { + /// Get the JSON representation of this test event. + pub fn into_json_value(self) -> JsonValue { + match self { + Self::Presence => test_json::events::PRESENCE.to_owned(), + Self::Custom(json) => json, + } + } + + /// Get the typed JSON representation of this test event. + pub fn into_raw_event(self) -> Raw { + from_json_value(self.into_json_value()).unwrap() + } +} + +/// Test events that can be added to the global account data. +pub enum GlobalAccountDataTestEvent { + PushRules, + Tags, + Custom(JsonValue), +} + +impl GlobalAccountDataTestEvent { + /// Get the JSON representation of this test event. + pub fn into_json_value(self) -> JsonValue { + match self { + Self::PushRules => test_json::events::PUSH_RULES.to_owned(), + Self::Tags => test_json::events::TAG.to_owned(), + Self::Custom(json) => json, + } + } + + /// Get the typed JSON representation of this test event. + pub fn into_raw_event(self) -> Raw { + from_json_value(self.into_json_value()).unwrap() + } +} diff --git a/crates/matrix-sdk-test/src/lib.rs b/crates/matrix-sdk-test/src/lib.rs index 9098ae4cf..cc3cb6b6c 100644 --- a/crates/matrix-sdk-test/src/lib.rs +++ b/crates/matrix-sdk-test/src/lib.rs @@ -1,380 +1,18 @@ -use std::{collections::HashMap, panic}; - use http::Response; pub use matrix_sdk_test_macros::async_test; -use ruma::{ - api::{client::sync::sync_events::v3::Response as SyncResponse, IncomingResponse}, - events::{ - presence::PresenceEvent, AnyGlobalAccountDataEvent, AnySyncEphemeralRoomEvent, - AnySyncRoomEvent, AnySyncStateEvent, - }, - serde::Raw, - OwnedRoomId, RoomId, -}; +use ruma::api::{client::sync::sync_events::v3::Response as SyncResponse, IncomingResponse}; use serde_json::Value as JsonValue; #[cfg(feature = "appservice")] pub mod appservice; +mod event_builder; pub mod test_json; -/// Embedded event files -#[derive(Debug)] -pub enum EventsJson { - Alias, - Aliases, - Create, - Encryption, - FullyRead, - HistoryVisibility, - JoinRules, - Member, - MemberInvite, - MemberNameChange, - MessageEmote, - MessageNotice, - MessageText, - Name, - PowerLevels, - PushRules, - Presence, - ReadReceipt, - ReadReceiptOther, - RedactedInvalid, - RedactedState, - Redacted, - Redaction, - RoomAvatar, - Tag, - Topic, - Typing, -} - -/// The `EventBuilder` struct can be used to easily generate valid sync -/// responses for testing. These can be then fed into either `Client` or `Room`. -/// -/// It supports generated a number of canned events, such as a member entering a -/// room, his power level and display name changing and similar. It also -/// supports insertion of custom events in the form of `EventsJson` values. -/// -/// **Important** You *must* use the *same* builder when sending multiple sync -/// responses to a single client. Otherwise, the subsequent responses will be -/// *ignored* by the client because the `next_batch` sync token will not be -/// rotated properly. -/// -/// # Example usage -/// -/// ```rust -/// use matrix_sdk_test::{EventBuilder, EventsJson}; -/// -/// let mut builder = EventBuilder::new(); -/// -/// // response1 now contains events that add an example member to the room and change their power -/// // level -/// let response1 = builder -/// .add_room_event(EventsJson::Member) -/// .add_room_event(EventsJson::PowerLevels) -/// .build_sync_response(); -/// -/// // response2 is now empty (nothing changed) -/// let response2 = builder.build_sync_response(); -/// -/// // response3 contains a display name change for member example -/// let response3 = builder -/// .add_room_event(EventsJson::MemberNameChange) -/// .build_sync_response(); -/// ``` - -#[derive(Default)] -pub struct EventBuilder { - /// The events that determine the state of a `Room`. - joined_room_events: HashMap>>, - /// The events that determine the state of a `Room`. - invited_room_events: HashMap>>, - /// The events that determine the state of a `Room`. - left_room_events: HashMap>>, - /// The presence events that determine the presence state of a `RoomMember`. - presence_events: Vec, - /// The state events that determine the state of a `Room`. - state_events: Vec>, - /// The ephemeral room events that determine the state of a `Room`. - ephemeral: Vec>, - /// The account data events that determine the state of a `Room`. - account_data: Vec>, - /// Internal counter to enable the `prev_batch` and `next_batch` of each - /// sync response to vary. - batch_counter: i64, -} - -impl EventBuilder { - pub fn new() -> Self { - let builder: EventBuilder = Default::default(); - builder - } - - /// Add an event to the room events `Vec`. - pub fn add_ephemeral(&mut self, json: EventsJson) -> &mut Self { - let val: &JsonValue = match json { - EventsJson::ReadReceipt => &test_json::READ_RECEIPT, - EventsJson::ReadReceiptOther => &test_json::READ_RECEIPT_OTHER, - EventsJson::Typing => &test_json::TYPING, - _ => panic!("unknown ephemeral event {:?}", json), - }; - - let event = serde_json::from_value(val.clone()).unwrap(); - self.ephemeral.push(event); - self - } - - /// Add an event to the room events `Vec`. - #[allow(unused)] - pub fn add_account(&mut self, json: EventsJson) -> &mut Self { - let val: &JsonValue = match json { - EventsJson::PushRules => &test_json::PUSH_RULES, - _ => panic!("unknown account event {:?}", json), - }; - - let event = serde_json::from_value(val.clone()).unwrap(); - self.account_data.push(event); - self - } - - /// Add an event to the room events `Vec`. - pub fn add_room_event(&mut self, json: EventsJson) -> &mut Self { - let val: &JsonValue = match json { - EventsJson::Member => &test_json::MEMBER, - EventsJson::MemberInvite => &test_json::MEMBER_INVITE, - EventsJson::MemberNameChange => &test_json::MEMBER_NAME_CHANGE, - EventsJson::PowerLevels => &test_json::POWER_LEVELS, - _ => panic!("unknown room event json {:?}", json), - }; - - let event = serde_json::from_value(val.clone()).unwrap(); - - self.add_joined_event(*test_json::DEFAULT_SYNC_ROOM_ID, event); - self - } - - pub fn add_custom_joined_event( - &mut self, - room_id: &RoomId, - event: serde_json::Value, - ) -> &mut Self { - let event = serde_json::from_value(event).unwrap(); - self.add_joined_event(room_id, event); - self - } - - fn add_joined_event(&mut self, room_id: &RoomId, event: Raw) { - self.joined_room_events.entry(room_id.to_owned()).or_default().push(event); - } - - pub fn add_custom_invited_event( - &mut self, - room_id: &RoomId, - event: serde_json::Value, - ) -> &mut Self { - let event = serde_json::from_value(event).unwrap(); - self.invited_room_events.entry(room_id.to_owned()).or_default().push(event); - self - } - - pub fn add_custom_left_event( - &mut self, - room_id: &RoomId, - event: serde_json::Value, - ) -> &mut Self { - let event = serde_json::from_value(event).unwrap(); - self.left_room_events.entry(room_id.to_owned()).or_default().push(event); - self - } - - /// Add a state event to the state events `Vec`. - pub fn add_state_event(&mut self, json: EventsJson) -> &mut Self { - let val: &JsonValue = match json { - EventsJson::Alias => &test_json::ALIAS, - EventsJson::Aliases => &test_json::ALIASES, - EventsJson::Name => &test_json::NAME, - EventsJson::Member => &test_json::MEMBER, - EventsJson::PowerLevels => &test_json::POWER_LEVELS, - EventsJson::Encryption => &test_json::ENCRYPTION, - _ => panic!("unknown state event {:?}", json), - }; - - let event = serde_json::from_value(val.clone()).unwrap(); - self.state_events.push(event); - self - } - - /// Add an presence event to the presence events `Vec`. - pub fn add_presence_event(&mut self, json: EventsJson) -> &mut Self { - let val: &JsonValue = match json { - EventsJson::Presence => &test_json::PRESENCE, - _ => panic!("unknown presence event {:?}", json), - }; - - let event = serde_json::from_value::(val.clone()).unwrap(); - self.presence_events.push(event); - self - } - - /// Builds a sync response as a JSON Value containing the events we queued - /// so far. - /// - /// The next response returned by `build_sync_response` will then be empty - /// if no further events were queued. - /// - /// This method is raw JSON equivalent to - /// [build_sync_response()](#method.build_sync_response), use - /// [build_sync_response()](#method.build_sync_response) if you need a typed - /// response. - pub fn build_json_sync_response(&mut self) -> JsonValue { - let main_room_id = *test_json::DEFAULT_SYNC_ROOM_ID; - - // First time building a sync response, so initialize the `prev_batch` to a - // default one. - let prev_batch = self.generate_sync_token(); - self.batch_counter += 1; - let next_batch = self.generate_sync_token(); - - // TODO generalize this. - let joined_room = serde_json::json!({ - "summary": {}, - "account_data": { - "events": self.account_data - }, - "ephemeral": { - "events": self.ephemeral - }, - "state": { - "events": self.state_events - }, - "timeline": { - "events": self.joined_room_events.remove(main_room_id).unwrap_or_default(), - "limited": true, - "prev_batch": prev_batch - }, - "unread_notifications": { - "highlight_count": 0, - "notification_count": 11 - } - }); - - let mut joined_rooms = HashMap::new(); - - joined_rooms.insert(main_room_id.to_owned(), joined_room); - - for (room_id, events) in self.joined_room_events.drain() { - let joined_room = serde_json::json!({ - "summary": {}, - "account_data": { - "events": [], - }, - "ephemeral": { - "events": [], - }, - "state": { - "events": [], - }, - "timeline": { - "events": events, - "limited": true, - "prev_batch": prev_batch - }, - "unread_notifications": { - "highlight_count": 0, - "notification_count": 11 - } - }); - joined_rooms.insert(room_id, joined_room); - } - - let mut left_rooms = HashMap::new(); - - for (room_id, events) in self.left_room_events.drain() { - let room = serde_json::json!({ - "state": { - "events": [], - }, - "timeline": { - "events": events, - "limited": false, - "prev_batch": prev_batch - }, - }); - left_rooms.insert(room_id, room); - } - - let mut invited_rooms = HashMap::new(); - - for (room_id, events) in self.invited_room_events.drain() { - let room = serde_json::json!({ - "invite_state": { - "events": events, - }, - }); - invited_rooms.insert(room_id, room); - } - - let body = serde_json::json! { - { - "device_one_time_keys_count": {}, - "next_batch": next_batch, - "device_lists": { - "changed": [], - "left": [] - }, - "rooms": { - "invite": invited_rooms, - "join": joined_rooms, - "leave": left_rooms, - }, - "to_device": { - "events": [] - }, - "presence": { - "events": [] - } - } - }; - - // Clear state so that the next sync response will be empty if nothing - // was added. - self.clear(); - - body - } - - /// Builds a `SyncResponse` containing the events we queued so far. - /// - /// The next response returned by `build_sync_response` will then be empty - /// if no further events were queued. - /// - /// This method is high level and typed equivalent to - /// [build_json_sync_response()](#method.build_json_sync_response), use - /// [build_json_sync_response()](#method.build_json_sync_response) if you - /// need an untyped response. - pub fn build_sync_response(&mut self) -> SyncResponse { - let body = self.build_json_sync_response(); - - let response = Response::builder().body(serde_json::to_vec(&body).unwrap()).unwrap(); - - SyncResponse::try_from_http_response(response).unwrap() - } - - fn generate_sync_token(&self) -> String { - format!("t392-516_47314_0_7_1_1_1_11444_{}", self.batch_counter) - } - - pub fn clear(&mut self) { - self.account_data.clear(); - self.ephemeral.clear(); - self.invited_room_events.clear(); - self.joined_room_events.clear(); - self.left_room_events.clear(); - self.presence_events.clear(); - self.state_events.clear(); - } -} +pub use event_builder::{ + EphemeralTestEvent, EventBuilder, GlobalAccountDataTestEvent, InvitedRoomBuilder, + JoinedRoomBuilder, LeftRoomBuilder, PresenceTestEvent, RoomAccountDataTestEvent, + StateTestEvent, StrippedStateTestEvent, TimelineTestEvent, +}; /// Embedded sync response files pub enum SyncResponseFile { @@ -401,6 +39,6 @@ pub fn sync_response(kind: SyncResponseFile) -> SyncResponse { SyncResponse::try_from_http_response(response).unwrap() } -pub fn response_from_file(json: &serde_json::Value) -> Response> { +pub fn response_from_file(json: &JsonValue) -> Response> { Response::builder().status(200).body(json.to_string().as_bytes().to_vec()).unwrap() } diff --git a/crates/matrix-sdk/src/client/mod.rs b/crates/matrix-sdk/src/client/mod.rs index 9e57be3aa..b3776d9bf 100644 --- a/crates/matrix-sdk/src/client/mod.rs +++ b/crates/matrix-sdk/src/client/mod.rs @@ -2206,7 +2206,7 @@ impl Client { pub(crate) mod tests { use std::time::Duration; - use matrix_sdk_test::{async_test, test_json, EventBuilder, EventsJson}; + use matrix_sdk_test::{async_test, test_json, EventBuilder, JoinedRoomBuilder, StateTestEvent}; #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); @@ -2316,8 +2316,11 @@ pub(crate) mod tests { let client = logged_in_client(Some(server.uri())).await; let response = EventBuilder::default() - .add_state_event(EventsJson::Member) - .add_state_event(EventsJson::PowerLevels) + .add_joined_room( + JoinedRoomBuilder::default() + .add_state_event(StateTestEvent::Member) + .add_state_event(StateTestEvent::PowerLevels), + ) .build_sync_response(); client.inner.base_client.receive_sync_response(response).await.unwrap(); diff --git a/crates/matrix-sdk/src/encryption/mod.rs b/crates/matrix-sdk/src/encryption/mod.rs index e2f26b147..fd597437b 100644 --- a/crates/matrix-sdk/src/encryption/mod.rs +++ b/crates/matrix-sdk/src/encryption/mod.rs @@ -872,7 +872,7 @@ impl Encryption { #[cfg(all(test, not(target_arch = "wasm32")))] mod tests { - use matrix_sdk_test::{async_test, test_json, EventBuilder, EventsJson}; + use matrix_sdk_test::{async_test, test_json, EventBuilder, JoinedRoomBuilder, StateTestEvent}; use ruma::{ event_id, events::reaction::{ReactionEventContent, Relation}, @@ -902,9 +902,12 @@ mod tests { .await; let response = EventBuilder::default() - .add_state_event(EventsJson::Member) - .add_state_event(EventsJson::PowerLevels) - .add_state_event(EventsJson::Encryption) + .add_joined_room( + JoinedRoomBuilder::default() + .add_state_event(StateTestEvent::Member) + .add_state_event(StateTestEvent::PowerLevels) + .add_state_event(StateTestEvent::Encryption), + ) .build_sync_response(); client.inner.base_client.receive_sync_response(response).await.unwrap(); diff --git a/crates/matrix-sdk/src/event_handler.rs b/crates/matrix-sdk/src/event_handler.rs index 49718a089..fec80128d 100644 --- a/crates/matrix-sdk/src/event_handler.rs +++ b/crates/matrix-sdk/src/event_handler.rs @@ -558,12 +558,14 @@ mod static_events { #[cfg(all(test, not(target_arch = "wasm32")))] mod tests { - use matrix_sdk_test::async_test; + use matrix_sdk_test::{async_test, InvitedRoomBuilder, JoinedRoomBuilder}; #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); use std::{future, sync::Arc}; - use matrix_sdk_test::{EventBuilder, EventsJson}; + use matrix_sdk_test::{ + EphemeralTestEvent, EventBuilder, StateTestEvent, StrippedStateTestEvent, TimelineTestEvent, + }; use ruma::{ events::room::member::{OriginalSyncRoomMemberEvent, StrippedRoomMemberEvent}, room_id, @@ -618,45 +620,49 @@ mod tests { .await; let response = EventBuilder::default() - .add_room_event(EventsJson::Member) - .add_ephemeral(EventsJson::Typing) - .add_state_event(EventsJson::PowerLevels) - .add_custom_invited_event( - room_id!("!test_invited:example.org"), - json!({ - "content": { - "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", - "displayname": "Alice", - "membership": "invite", - }, - "event_id": "$143273582443PhrSn:example.org", - "origin_server_ts": 1432735824653u64, - "room_id": "!jEsUZKDJdhlrceRyVU:example.org", - "sender": "@example:example.org", - "state_key": "@alice:example.org", - "type": "m.room.member", - "unsigned": { - "age": 1234, - "invite_room_state": [ - { - "content": { - "name": "Example Room" + .add_joined_room( + JoinedRoomBuilder::default() + .add_timeline_event(TimelineTestEvent::Member) + .add_ephemeral_event(EphemeralTestEvent::Typing) + .add_state_event(StateTestEvent::PowerLevels), + ) + .add_invited_room( + InvitedRoomBuilder::new(room_id!("!test_invited:example.org")).add_state_event( + StrippedStateTestEvent::Custom(json!({ + "content": { + "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", + "displayname": "Alice", + "membership": "invite", + }, + "event_id": "$143273582443PhrSn:example.org", + "origin_server_ts": 1432735824653u64, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "state_key": "@alice:example.org", + "type": "m.room.member", + "unsigned": { + "age": 1234, + "invite_room_state": [ + { + "content": { + "name": "Example Room" + }, + "sender": "@bob:example.org", + "state_key": "", + "type": "m.room.name" }, - "sender": "@bob:example.org", - "state_key": "", - "type": "m.room.name" - }, - { - "content": { - "join_rule": "invite" - }, - "sender": "@bob:example.org", - "state_key": "", - "type": "m.room.join_rules" - } - ] - } - }), + { + "content": { + "join_rule": "invite" + }, + "sender": "@bob:example.org", + "state_key": "", + "type": "m.room.join_rules" + } + ] + } + })), + ), ) .build_sync_response(); client.process_sync(response).await?; From 37eb058dac1a0b871db289e976db7fc399e7b87d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= Date: Sun, 17 Jul 2022 18:34:13 +0200 Subject: [PATCH 43/73] test: Reorganize JSON responses and events --- .../src/store/integration_tests.rs | 4 +- .../src/event_builder/test_event.rs | 92 +++--- .../src/test_json/api_responses.rs | 213 +++++++++++++ .../matrix-sdk-test/src/test_json/members.rs | 2 + .../matrix-sdk-test/src/test_json/messages.rs | 149 +++++++++ crates/matrix-sdk-test/src/test_json/mod.rs | 86 ++---- crates/matrix-sdk-test/src/test_json/sync.rs | 2 + .../test_json/{events.rs => sync_events.rs} | 292 +----------------- .../tests/integration/room/common.rs | 16 +- 9 files changed, 442 insertions(+), 414 deletions(-) create mode 100644 crates/matrix-sdk-test/src/test_json/api_responses.rs create mode 100644 crates/matrix-sdk-test/src/test_json/messages.rs rename crates/matrix-sdk-test/src/test_json/{events.rs => sync_events.rs} (73%) diff --git a/crates/matrix-sdk-base/src/store/integration_tests.rs b/crates/matrix-sdk-base/src/store/integration_tests.rs index 6721a8ad9..b1950bf29 100644 --- a/crates/matrix-sdk-base/src/store/integration_tests.rs +++ b/crates/matrix-sdk-base/src/store/integration_tests.rs @@ -674,7 +674,7 @@ macro_rules! statestore_integration_tests { // Add message response let messages = MessageResponse::try_from_http_response( Response::builder() - .body(serde_json::to_vec(&*test_json::SYNC_ROOM_MESSAGES_BATCH_1).expect("Parsing SYNC_ROOM_MESSAGES_BATCH_1 failed")) + .body(serde_json::to_vec(&*test_json::ROOM_MESSAGES_BATCH_1).expect("Parsing ROOM_MESSAGES_BATCH_1 failed")) .unwrap(), ) .unwrap(); @@ -699,7 +699,7 @@ macro_rules! statestore_integration_tests { // Add second message response let messages = MessageResponse::try_from_http_response( Response::builder() - .body(serde_json::to_vec(&*test_json::SYNC_ROOM_MESSAGES_BATCH_2).expect("Parsing SYNC_ROOM_MESSAGES_BATCH_2 failed")) + .body(serde_json::to_vec(&*test_json::ROOM_MESSAGES_BATCH_2).expect("Parsing ROOM_MESSAGES_BATCH_2 failed")) .unwrap(), ) .unwrap(); diff --git a/crates/matrix-sdk-test/src/event_builder/test_event.rs b/crates/matrix-sdk-test/src/event_builder/test_event.rs index 577a8e35c..2ca6eea6a 100644 --- a/crates/matrix-sdk-test/src/event_builder/test_event.rs +++ b/crates/matrix-sdk-test/src/event_builder/test_event.rs @@ -40,28 +40,28 @@ impl TimelineTestEvent { /// Get the JSON representation of this test event. pub fn into_json_value(self) -> JsonValue { match self { - Self::Alias => test_json::events::ALIAS.to_owned(), - Self::Aliases => test_json::events::ALIASES.to_owned(), - Self::Create => test_json::events::CREATE.to_owned(), - Self::Encryption => test_json::events::ENCRYPTION.to_owned(), - Self::HistoryVisibility => test_json::events::HISTORY_VISIBILITY.to_owned(), - Self::JoinRules => test_json::events::JOIN_RULES.to_owned(), - Self::Member => test_json::events::MEMBER.to_owned(), - Self::MemberInvite => test_json::events::MEMBER_INVITE.to_owned(), - Self::MemberNameChange => test_json::events::MEMBER_NAME_CHANGE.to_owned(), - Self::MessageEdit => test_json::events::MESSAGE_EDIT.to_owned(), - Self::MessageEmote => test_json::events::MESSAGE_EMOTE.to_owned(), - Self::MessageNotice => test_json::events::MESSAGE_NOTICE.to_owned(), - Self::MessageText => test_json::events::MESSAGE_TEXT.to_owned(), - Self::PowerLevels => test_json::events::POWER_LEVELS.to_owned(), - Self::Reaction => test_json::events::REACTION.to_owned(), - Self::RedactedInvalid => test_json::events::REDACTED_INVALID.to_owned(), - Self::RedactedMessage => test_json::events::REDACTED.to_owned(), - Self::RedactedState => test_json::events::REDACTED_STATE.to_owned(), - Self::Redaction => test_json::events::REDACTION.to_owned(), - Self::RoomAvatar => test_json::events::ROOM_AVATAR.to_owned(), - Self::RoomName => test_json::events::NAME.to_owned(), - Self::RoomTopic => test_json::events::TOPIC.to_owned(), + Self::Alias => test_json::sync_events::ALIAS.to_owned(), + Self::Aliases => test_json::sync_events::ALIASES.to_owned(), + Self::Create => test_json::sync_events::CREATE.to_owned(), + Self::Encryption => test_json::sync_events::ENCRYPTION.to_owned(), + Self::HistoryVisibility => test_json::sync_events::HISTORY_VISIBILITY.to_owned(), + Self::JoinRules => test_json::sync_events::JOIN_RULES.to_owned(), + Self::Member => test_json::sync_events::MEMBER.to_owned(), + Self::MemberInvite => test_json::sync_events::MEMBER_INVITE.to_owned(), + Self::MemberNameChange => test_json::sync_events::MEMBER_NAME_CHANGE.to_owned(), + Self::MessageEdit => test_json::sync_events::MESSAGE_EDIT.to_owned(), + Self::MessageEmote => test_json::sync_events::MESSAGE_EMOTE.to_owned(), + Self::MessageNotice => test_json::sync_events::MESSAGE_NOTICE.to_owned(), + Self::MessageText => test_json::sync_events::MESSAGE_TEXT.to_owned(), + Self::PowerLevels => test_json::sync_events::POWER_LEVELS.to_owned(), + Self::Reaction => test_json::sync_events::REACTION.to_owned(), + Self::RedactedInvalid => test_json::sync_events::REDACTED_INVALID.to_owned(), + Self::RedactedMessage => test_json::sync_events::REDACTED.to_owned(), + Self::RedactedState => test_json::sync_events::REDACTED_STATE.to_owned(), + Self::Redaction => test_json::sync_events::REDACTION.to_owned(), + Self::RoomAvatar => test_json::sync_events::ROOM_AVATAR.to_owned(), + Self::RoomName => test_json::sync_events::NAME.to_owned(), + Self::RoomTopic => test_json::sync_events::TOPIC.to_owned(), Self::Custom(json) => json, } } @@ -96,21 +96,21 @@ impl StateTestEvent { /// Get the JSON representation of this test event. pub fn into_json_value(self) -> JsonValue { match self { - Self::Alias => test_json::events::ALIAS.to_owned(), - Self::Aliases => test_json::events::ALIASES.to_owned(), - Self::Create => test_json::events::CREATE.to_owned(), - Self::Encryption => test_json::events::ENCRYPTION.to_owned(), - Self::HistoryVisibility => test_json::events::HISTORY_VISIBILITY.to_owned(), - Self::JoinRules => test_json::events::JOIN_RULES.to_owned(), - Self::Member => test_json::events::MEMBER.to_owned(), - Self::MemberInvite => test_json::events::MEMBER_INVITE.to_owned(), - Self::MemberNameChange => test_json::events::MEMBER_NAME_CHANGE.to_owned(), - Self::PowerLevels => test_json::events::POWER_LEVELS.to_owned(), - Self::RedactedInvalid => test_json::events::REDACTED_INVALID.to_owned(), - Self::RedactedState => test_json::events::REDACTED_STATE.to_owned(), - Self::RoomAvatar => test_json::events::ROOM_AVATAR.to_owned(), - Self::RoomName => test_json::events::NAME.to_owned(), - Self::RoomTopic => test_json::events::TOPIC.to_owned(), + Self::Alias => test_json::sync_events::ALIAS.to_owned(), + Self::Aliases => test_json::sync_events::ALIASES.to_owned(), + Self::Create => test_json::sync_events::CREATE.to_owned(), + Self::Encryption => test_json::sync_events::ENCRYPTION.to_owned(), + Self::HistoryVisibility => test_json::sync_events::HISTORY_VISIBILITY.to_owned(), + Self::JoinRules => test_json::sync_events::JOIN_RULES.to_owned(), + Self::Member => test_json::sync_events::MEMBER.to_owned(), + Self::MemberInvite => test_json::sync_events::MEMBER_INVITE.to_owned(), + Self::MemberNameChange => test_json::sync_events::MEMBER_NAME_CHANGE.to_owned(), + Self::PowerLevels => test_json::sync_events::POWER_LEVELS.to_owned(), + Self::RedactedInvalid => test_json::sync_events::REDACTED_INVALID.to_owned(), + Self::RedactedState => test_json::sync_events::REDACTED_STATE.to_owned(), + Self::RoomAvatar => test_json::sync_events::ROOM_AVATAR.to_owned(), + Self::RoomName => test_json::sync_events::NAME.to_owned(), + Self::RoomTopic => test_json::sync_events::TOPIC.to_owned(), Self::Custom(json) => json, } } @@ -132,8 +132,8 @@ impl StrippedStateTestEvent { /// Get the JSON representation of this test event. pub fn into_json_value(self) -> JsonValue { match self { - Self::Member => test_json::events::MEMBER_STRIPPED.to_owned(), - Self::RoomName => test_json::events::NAME_STRIPPED.to_owned(), + Self::Member => test_json::sync_events::MEMBER_STRIPPED.to_owned(), + Self::RoomName => test_json::sync_events::NAME_STRIPPED.to_owned(), Self::Custom(json) => json, } } @@ -154,7 +154,7 @@ impl RoomAccountDataTestEvent { /// Get the JSON representation of this test event. pub fn into_json_value(self) -> JsonValue { match self { - Self::FullyRead => test_json::events::FULLY_READ.to_owned(), + Self::FullyRead => test_json::sync_events::FULLY_READ.to_owned(), Self::Custom(json) => json, } } @@ -177,9 +177,9 @@ impl EphemeralTestEvent { /// Get the JSON representation of this test event. pub fn into_json_value(self) -> JsonValue { match self { - Self::ReadReceipt => test_json::events::READ_RECEIPT.to_owned(), - Self::ReadReceiptOther => test_json::events::READ_RECEIPT_OTHER.to_owned(), - Self::Typing => test_json::events::TYPING.to_owned(), + Self::ReadReceipt => test_json::sync_events::READ_RECEIPT.to_owned(), + Self::ReadReceiptOther => test_json::sync_events::READ_RECEIPT_OTHER.to_owned(), + Self::Typing => test_json::sync_events::TYPING.to_owned(), Self::Custom(json) => json, } } @@ -200,7 +200,7 @@ impl PresenceTestEvent { /// Get the JSON representation of this test event. pub fn into_json_value(self) -> JsonValue { match self { - Self::Presence => test_json::events::PRESENCE.to_owned(), + Self::Presence => test_json::sync_events::PRESENCE.to_owned(), Self::Custom(json) => json, } } @@ -222,8 +222,8 @@ impl GlobalAccountDataTestEvent { /// Get the JSON representation of this test event. pub fn into_json_value(self) -> JsonValue { match self { - Self::PushRules => test_json::events::PUSH_RULES.to_owned(), - Self::Tags => test_json::events::TAG.to_owned(), + Self::PushRules => test_json::sync_events::PUSH_RULES.to_owned(), + Self::Tags => test_json::sync_events::TAG.to_owned(), Self::Custom(json) => json, } } diff --git a/crates/matrix-sdk-test/src/test_json/api_responses.rs b/crates/matrix-sdk-test/src/test_json/api_responses.rs new file mode 100644 index 000000000..9007fe061 --- /dev/null +++ b/crates/matrix-sdk-test/src/test_json/api_responses.rs @@ -0,0 +1,213 @@ +//! Responses to client API calls. + +use once_cell::sync::Lazy; +use serde_json::{json, Value as JsonValue}; + +/// `GET /_matrix/client/v3/devices` +pub static DEVICES: Lazy = Lazy::new(|| { + json!({ + "devices": [ + { + "device_id": "BNYQQWUMXO", + "display_name": "Client 1", + "last_seen_ip": "-", + "last_seen_ts": 1596117733037u64, + "user_id": "@example:localhost" + }, + { + "device_id": "LEBKSEUSNR", + "display_name": "Client 2", + "last_seen_ip": "-", + "last_seen_ts": 1599057006985u64, + "user_id": "@example:localhost" + } + ] + }) +}); + +/// `GET /_matrix/client/v3/directory/room/{roomAlias}` +pub static GET_ALIAS: Lazy = Lazy::new(|| { + json!({ + "room_id": "!lUbmUPdxdXxEQurqOs:example.net", + "servers": [ + "example.org", + "example.net", + "matrix.org", + ] + }) +}); + +/// `POST /_matrix/client/v3/keys/query` +pub static KEYS_QUERY: Lazy = Lazy::new(|| { + json!({ + "device_keys": { + "@alice:example.org": { + "JLAFKJWSCS": { + "algorithms": [ + "m.olm.v1.curve25519-aes-sha2", + "m.megolm.v1.aes-sha2" + ], + "device_id": "JLAFKJWSCS", + "user_id": "@alice:example.org", + "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" + } + } + } + }, + "failures": {} + }) +}); + +/// `` +pub static KEYS_UPLOAD: Lazy = Lazy::new(|| { + json!({ + "one_time_key_counts": { + "curve25519": 10, + "signed_curve25519": 20 + } + }) +}); + +/// Successful call to `POST /_matrix/client/v3/login` without auto-discovery. +pub static LOGIN: Lazy = Lazy::new(|| { + json!({ + "access_token": "abc123", + "device_id": "GHTYAJCE", + "home_server": "matrix.org", + "user_id": "@cheeky_monkey:matrix.org" + }) +}); + +/// Successful call to `POST /_matrix/client/v3/login` with auto-discovery. +pub static LOGIN_WITH_DISCOVERY: Lazy = Lazy::new(|| { + json!({ + "access_token": "abc123", + "device_id": "GHTYAJCE", + "home_server": "matrix.org", + "user_id": "@cheeky_monkey:matrix.org", + "well_known": { + "m.homeserver": { + "base_url": "https://example.org" + }, + "m.identity_server": { + "base_url": "https://id.example.org" + } + } + }) +}); + +/// Failed call to `POST /_matrix/client/v3/login` +pub static LOGIN_RESPONSE_ERR: Lazy = Lazy::new(|| { + json!({ + "errcode": "M_FORBIDDEN", + "error": "Invalid password" + }) +}); + +/// `GET /_matrix/client/v3/login` +pub static LOGIN_TYPES: Lazy = Lazy::new(|| { + json!({ + "flows": [ + { + "type": "m.login.password" + }, + { + "type": "m.login.sso" + }, + { + "type": "m.login.token" + } + ] + }) +}); + +/// `GET /_matrix/client/v3/publicRooms` +pub static PUBLIC_ROOMS: Lazy = Lazy::new(|| { + json!({ + "chunk": [ + { + "aliases": [ + "#murrays:cheese.bar" + ], + "avatar_url": "mxc://bleeker.street/CHEDDARandBRIE", + "guest_can_join": false, + "name": "CHEESE", + "num_joined_members": 37, + "room_id": "!ol19s:bleecker.street", + "topic": "Tasty tasty cheese", + "world_readable": true + } + ], + "next_batch": "p190q", + "prev_batch": "p1902", + "total_room_count_estimate": 115 + }) +}); + +/// Failed call to `POST /_matrix/client/v3/register` +pub static REGISTRATION_RESPONSE_ERR: Lazy = Lazy::new(|| { + json!({ + "errcode": "M_FORBIDDEN", + "error": "Invalid password", + "completed": ["example.type.foo"], + "flows": [ + { + "stages": ["example.type.foo", "example.type.bar"] + }, + { + "stages": ["example.type.foo", "example.type.baz"] + } + ], + "params": { + "example.type.baz": { + "example_key": "foobar" + } + }, + "session": "xxxxxx" + }) +}); + +/// `GET /_matrix/client/versions` +pub static VERSIONS: Lazy = Lazy::new(|| { + json!({ + "versions": [ + "r0.0.1", + "r0.1.0", + "r0.2.0", + "r0.3.0", + "r0.4.0", + "r0.5.0", + "r0.6.0" + ], + "unstable_features": { + "org.matrix.label_based_filtering":true, + "org.matrix.e2e_cross_signing":true + } + }) +}); + +/// `GET /.well-known/matrix/client` +pub static WELL_KNOWN: Lazy = Lazy::new(|| { + json!({ + "m.homeserver": { + "base_url": "HOMESERVER_URL" + } + }) +}); + +/// `GET /_matrix/client/v3/account/whoami` +pub static WHOAMI: Lazy = Lazy::new(|| { + json!({ + "user_id": "@joe:example.org" + }) +}); diff --git a/crates/matrix-sdk-test/src/test_json/members.rs b/crates/matrix-sdk-test/src/test_json/members.rs index 94bc7df7e..e875047ef 100644 --- a/crates/matrix-sdk-test/src/test_json/members.rs +++ b/crates/matrix-sdk-test/src/test_json/members.rs @@ -1,3 +1,5 @@ +//! Example responses to `GET /_matrix/client/v3/rooms/{roomId}/members` + use once_cell::sync::Lazy; use serde_json::{json, Value as JsonValue}; diff --git a/crates/matrix-sdk-test/src/test_json/messages.rs b/crates/matrix-sdk-test/src/test_json/messages.rs new file mode 100644 index 000000000..a86238033 --- /dev/null +++ b/crates/matrix-sdk-test/src/test_json/messages.rs @@ -0,0 +1,149 @@ +//! Example responses from calls to `GET +//! /_matrix/client/v3/rooms/{roomId}/messages`. + +use once_cell::sync::Lazy; +use serde_json::{json, Value as JsonValue}; + +pub static ROOM_MESSAGES: Lazy = Lazy::new(|| { + json!({ + "chunk": [ + { + "age": 1042, + "content": { + "body": "hello world", + "msgtype": "m.text" + }, + "event_id": "$1444812213350496Caaaa:example.com", + "origin_server_ts": 1444812213737i64, + "room_id": "!Xq3620DUiqCaoxq:example.com", + "sender": "@alice:example.com", + "type": "m.room.message" + }, + { + "age": 20123, + "content": { + "body": "the world is big", + "msgtype": "m.text" + }, + "event_id": "$1444812213350496Cbbbb:example.com", + "origin_server_ts": 1444812194656i64, + "room_id": "!Xq3620DUiqCaoxq:example.com", + "sender": "@bob:example.com", + "type": "m.room.message" + }, + { + "age": 50789, + "content": { + "name": "New room name" + }, + "event_id": "$1444812213350496Ccccc:example.com", + "origin_server_ts": 1444812163990i64, + "prev_content": { + "name": "Old room name" + }, + "room_id": "!Xq3620DUiqCaoxq:example.com", + "sender": "@bob:example.com", + "state_key": "", + "type": "m.room.name" + } + ], + "end": "t47409-4357353_219380_26003_2265", + "start": "t47429-4392820_219380_26003_2265" + }) +}); + +pub static ROOM_MESSAGES_BATCH_1: Lazy = Lazy::new(|| { + json!({ + "chunk": [ + { + "age": 1042, + "content": { + "body": "hello world", + "msgtype": "m.text" + }, + "event_id": "$1444812213350496Caaaf:example.com", + "origin_server_ts": 1444812213737i64, + "room_id": "!Xq3620DUiqCaoxq:example.com", + "sender": "@alice:example.com", + "type": "m.room.message" + }, + { + "age": 20123, + "content": { + "body": "the world is big", + "msgtype": "m.text" + }, + "event_id": "$1444812213350496Cbbbf:example.com", + "origin_server_ts": 1444812194656i64, + "room_id": "!Xq3620DUiqCaoxq:example.com", + "sender": "@bob:example.com", + "type": "m.room.message" + }, + { + "age": 50789, + "content": { + "name": "New room name" + }, + "event_id": "$1444812213350496Ccccf:example.com", + "origin_server_ts": 1444812163990i64, + "prev_content": { + "name": "Old room name" + }, + "room_id": "!Xq3620DUiqCaoxq:example.com", + "sender": "@bob:example.com", + "state_key": "", + "type": "m.room.name" + } + ], + "end": "t47409-4357353_219380_26003_2269", + "start": "t392-516_47314_0_7_1_1_1_11444_1" + }) +}); + +pub static ROOM_MESSAGES_BATCH_2: Lazy = Lazy::new(|| { + json!({ + "chunk": [ + { + "age": 1042, + "content": { + "body": "hello world", + "msgtype": "m.text" + }, + "event_id": "$1444812213350496Caaak:example.com", + "origin_server_ts": 1444812213737i64, + "room_id": "!Xq3620DUiqCaoxq:example.com", + "sender": "@alice:example.com", + "type": "m.room.message" + }, + { + "age": 20123, + "content": { + "body": "the world is big", + "msgtype": "m.text" + }, + "event_id": "$1444812213350496Cbbbk:example.com", + "origin_server_ts": 1444812194656i64, + "room_id": "!Xq3620DUiqCaoxq:example.com", + "sender": "@bob:example.com", + "type": "m.room.message" + }, + { + "age": 50789, + "content": { + "name": "New room name" + }, + "event_id": "$1444812213350496Cccck:example.com", + "origin_server_ts": 1444812163990i64, + "prev_content": { + "name": "Old room name" + }, + "room_id": "!Xq3620DUiqCaoxq:example.com", + "sender": "@bob:example.com", + "state_key": "", + "type": "m.room.name" + } + ], + "end": "t47409-4357353_219380_26003_2270", + "start": "t47409-4357353_219380_26003_2269" + }) +}); diff --git a/crates/matrix-sdk-test/src/test_json/mod.rs b/crates/matrix-sdk-test/src/test_json/mod.rs index 54ff95bb7..bf469e94c 100644 --- a/crates/matrix-sdk-test/src/test_json/mod.rs +++ b/crates/matrix-sdk-test/src/test_json/mod.rs @@ -7,84 +7,42 @@ use once_cell::sync::Lazy; use serde_json::{json, Value as JsonValue}; -pub mod events; +pub mod api_responses; pub mod members; +pub mod messages; pub mod sync; +pub mod sync_events; -pub use events::{ - ALIAS, ALIASES, EMPTY, ENCRYPTION, EVENT_ID, KEYS_QUERY, KEYS_UPLOAD, LOGIN, - LOGIN_RESPONSE_ERR, LOGIN_TYPES, LOGIN_WITH_DISCOVERY, MEMBER, MEMBER_INVITE, - MEMBER_NAME_CHANGE, MEMBER_STRIPPED, MESSAGE_EDIT, MESSAGE_TEXT, NAME, NAME_STRIPPED, - POWER_LEVELS, PRESENCE, PUBLIC_ROOMS, PUSH_RULES, REACTION, READ_RECEIPT, READ_RECEIPT_OTHER, - REDACTED, REDACTED_INVALID, REDACTED_STATE, REDACTION, REGISTRATION_RESPONSE_ERR, ROOM_ID, - ROOM_MESSAGES, SYNC_ROOM_MESSAGES_BATCH_1, SYNC_ROOM_MESSAGES_BATCH_2, TAG, TOPIC, TYPING, +pub use api_responses::{ + DEVICES, GET_ALIAS, KEYS_QUERY, KEYS_UPLOAD, LOGIN, LOGIN_RESPONSE_ERR, LOGIN_TYPES, + LOGIN_WITH_DISCOVERY, PUBLIC_ROOMS, REGISTRATION_RESPONSE_ERR, VERSIONS, WELL_KNOWN, WHOAMI, }; pub use members::MEMBERS; +pub use messages::{ROOM_MESSAGES, ROOM_MESSAGES_BATCH_1, ROOM_MESSAGES_BATCH_2}; pub use sync::{ DEFAULT_SYNC_ROOM_ID, DEFAULT_SYNC_SUMMARY, INVITE_SYNC, LEAVE_SYNC, LEAVE_SYNC_EVENT, MORE_SYNC, MORE_SYNC_2, SYNC, VOIP_SYNC, }; +pub use sync_events::{ + ALIAS, ALIASES, ENCRYPTION, MEMBER, MEMBER_INVITE, MEMBER_NAME_CHANGE, MEMBER_STRIPPED, + MESSAGE_EDIT, MESSAGE_TEXT, NAME, NAME_STRIPPED, POWER_LEVELS, PRESENCE, PUSH_RULES, REACTION, + READ_RECEIPT, READ_RECEIPT_OTHER, REDACTED, REDACTED_INVALID, REDACTED_STATE, REDACTION, TAG, + TOPIC, TYPING, +}; -pub static DEVICES: Lazy = Lazy::new(|| { +/// An empty response. +pub static EMPTY: Lazy = Lazy::new(|| json!({})); + +/// A response with only an event ID. +pub static EVENT_ID: Lazy = Lazy::new(|| { json!({ - "devices": [ - { - "device_id": "BNYQQWUMXO", - "display_name": "Client 1", - "last_seen_ip": "-", - "last_seen_ts": 1596117733037u64, - "user_id": "@example:localhost" - }, - { - "device_id": "LEBKSEUSNR", - "display_name": "Client 2", - "last_seen_ip": "-", - "last_seen_ts": 1599057006985u64, - "user_id": "@example:localhost" - } - ] + "event_id": "$h29iv0s8:example.com" }) }); -pub static GET_ALIAS: Lazy = Lazy::new(|| { +/// A response with only a room ID. +pub static ROOM_ID: Lazy = Lazy::new(|| { json!({ - "room_id": "!lUbmUPdxdXxEQurqOs:example.net", - "servers": [ - "example.org", - "example.net", - "matrix.org", - ] - }) -}); - -pub static WELL_KNOWN: Lazy = Lazy::new(|| { - json!({ - "m.homeserver": { - "base_url": "HOMESERVER_URL" - } - }) -}); - -pub static VERSIONS: Lazy = Lazy::new(|| { - json!({ - "versions": [ - "r0.0.1", - "r0.1.0", - "r0.2.0", - "r0.3.0", - "r0.4.0", - "r0.5.0", - "r0.6.0" - ], - "unstable_features": { - "org.matrix.label_based_filtering":true, - "org.matrix.e2e_cross_signing":true - } - }) -}); - -pub static WHOAMI: Lazy = Lazy::new(|| { - json!({ - "user_id": "@joe:example.org" + "room_id": "!testroom:example.org" }) }); diff --git a/crates/matrix-sdk-test/src/test_json/sync.rs b/crates/matrix-sdk-test/src/test_json/sync.rs index 5eee2e23d..fdf4c9cf3 100644 --- a/crates/matrix-sdk-test/src/test_json/sync.rs +++ b/crates/matrix-sdk-test/src/test_json/sync.rs @@ -1,3 +1,5 @@ +//! Complete sync responses. + use once_cell::sync::Lazy; use ruma::{room_id, RoomId}; use serde_json::{json, Value as JsonValue}; diff --git a/crates/matrix-sdk-test/src/test_json/events.rs b/crates/matrix-sdk-test/src/test_json/sync_events.rs similarity index 73% rename from crates/matrix-sdk-test/src/test_json/events.rs rename to crates/matrix-sdk-test/src/test_json/sync_events.rs index 5bb5a4d99..04eab8456 100644 --- a/crates/matrix-sdk-test/src/test_json/events.rs +++ b/crates/matrix-sdk-test/src/test_json/sync_events.rs @@ -1,3 +1,5 @@ +//! Discrete events found in a sync response. + use once_cell::sync::Lazy; use serde_json::{json, Value as JsonValue}; @@ -95,246 +97,6 @@ pub static JOIN_RULES: Lazy = Lazy::new(|| { }) }); -pub static ROOM_MESSAGES: Lazy = Lazy::new(|| { - json!({ - "chunk": [ - { - "age": 1042, - "content": { - "body": "hello world", - "msgtype": "m.text" - }, - "event_id": "$1444812213350496Caaaa:example.com", - "origin_server_ts": 1444812213737i64, - "room_id": "!Xq3620DUiqCaoxq:example.com", - "sender": "@alice:example.com", - "type": "m.room.message" - }, - { - "age": 20123, - "content": { - "body": "the world is big", - "msgtype": "m.text" - }, - "event_id": "$1444812213350496Cbbbb:example.com", - "origin_server_ts": 1444812194656i64, - "room_id": "!Xq3620DUiqCaoxq:example.com", - "sender": "@bob:example.com", - "type": "m.room.message" - }, - { - "age": 50789, - "content": { - "name": "New room name" - }, - "event_id": "$1444812213350496Ccccc:example.com", - "origin_server_ts": 1444812163990i64, - "prev_content": { - "name": "Old room name" - }, - "room_id": "!Xq3620DUiqCaoxq:example.com", - "sender": "@bob:example.com", - "state_key": "", - "type": "m.room.name" - } - ], - "end": "t47409-4357353_219380_26003_2265", - "start": "t47429-4392820_219380_26003_2265" - }) -}); - -pub static SYNC_ROOM_MESSAGES_BATCH_1: Lazy = Lazy::new(|| { - json!({ - "chunk": [ - { - "age": 1042, - "content": { - "body": "hello world", - "msgtype": "m.text" - }, - "event_id": "$1444812213350496Caaaf:example.com", - "origin_server_ts": 1444812213737i64, - "room_id": "!Xq3620DUiqCaoxq:example.com", - "sender": "@alice:example.com", - "type": "m.room.message" - }, - { - "age": 20123, - "content": { - "body": "the world is big", - "msgtype": "m.text" - }, - "event_id": "$1444812213350496Cbbbf:example.com", - "origin_server_ts": 1444812194656i64, - "room_id": "!Xq3620DUiqCaoxq:example.com", - "sender": "@bob:example.com", - "type": "m.room.message" - }, - { - "age": 50789, - "content": { - "name": "New room name" - }, - "event_id": "$1444812213350496Ccccf:example.com", - "origin_server_ts": 1444812163990i64, - "prev_content": { - "name": "Old room name" - }, - "room_id": "!Xq3620DUiqCaoxq:example.com", - "sender": "@bob:example.com", - "state_key": "", - "type": "m.room.name" - } - ], - "end": "t47409-4357353_219380_26003_2269", - "start": "t392-516_47314_0_7_1_1_1_11444_1" - }) -}); - -pub static SYNC_ROOM_MESSAGES_BATCH_2: Lazy = Lazy::new(|| { - json!({ - "chunk": [ - { - "age": 1042, - "content": { - "body": "hello world", - "msgtype": "m.text" - }, - "event_id": "$1444812213350496Caaak:example.com", - "origin_server_ts": 1444812213737i64, - "room_id": "!Xq3620DUiqCaoxq:example.com", - "sender": "@alice:example.com", - "type": "m.room.message" - }, - { - "age": 20123, - "content": { - "body": "the world is big", - "msgtype": "m.text" - }, - "event_id": "$1444812213350496Cbbbk:example.com", - "origin_server_ts": 1444812194656i64, - "room_id": "!Xq3620DUiqCaoxq:example.com", - "sender": "@bob:example.com", - "type": "m.room.message" - }, - { - "age": 50789, - "content": { - "name": "New room name" - }, - "event_id": "$1444812213350496Cccck:example.com", - "origin_server_ts": 1444812163990i64, - "prev_content": { - "name": "Old room name" - }, - "room_id": "!Xq3620DUiqCaoxq:example.com", - "sender": "@bob:example.com", - "state_key": "", - "type": "m.room.name" - } - ], - "end": "t47409-4357353_219380_26003_2270", - "start": "t47409-4357353_219380_26003_2269" - }) -}); - -pub static KEYS_QUERY: Lazy = Lazy::new(|| { - json!({ - "device_keys": { - "@alice:example.org": { - "JLAFKJWSCS": { - "algorithms": [ - "m.olm.v1.curve25519-aes-sha2", - "m.megolm.v1.aes-sha2" - ], - "device_id": "JLAFKJWSCS", - "user_id": "@alice:example.org", - "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" - } - } - } - }, - "failures": {} - }) -}); - -pub static KEYS_UPLOAD: Lazy = Lazy::new(|| { - json!({ - "one_time_key_counts": { - "curve25519": 10, - "signed_curve25519": 20 - } - }) -}); - -pub static LOGIN: Lazy = Lazy::new(|| { - json!({ - "access_token": "abc123", - "device_id": "GHTYAJCE", - "home_server": "matrix.org", - "user_id": "@cheeky_monkey:matrix.org" - }) -}); - -pub static LOGIN_WITH_DISCOVERY: Lazy = Lazy::new(|| { - json!({ - "access_token": "abc123", - "device_id": "GHTYAJCE", - "home_server": "matrix.org", - "user_id": "@cheeky_monkey:matrix.org", - "well_known": { - "m.homeserver": { - "base_url": "https://example.org" - }, - "m.identity_server": { - "base_url": "https://id.example.org" - } - } - }) -}); - -pub static LOGIN_RESPONSE_ERR: Lazy = Lazy::new(|| { - json!({ - "errcode": "M_FORBIDDEN", - "error": "Invalid password" - }) -}); - -pub static LOGIN_TYPES: Lazy = Lazy::new(|| { - json!({ - "flows": [ - { - "type": "m.login.password" - }, - { - "type": "m.login.sso" - }, - { - "type": "m.login.token" - } - ] - }) -}); - -pub static EMPTY: Lazy = Lazy::new(|| json!({})); - -pub static EVENT_ID: Lazy = Lazy::new(|| { - json!({ - "event_id": "$h29iv0s8:example.com" - }) -}); - pub static ENCRYPTION: Lazy = Lazy::new(|| { json!({ "content": { @@ -609,28 +371,6 @@ pub static PRESENCE: Lazy = Lazy::new(|| { }) }); -pub static PUBLIC_ROOMS: Lazy = Lazy::new(|| { - json!({ - "chunk": [ - { - "aliases": [ - "#murrays:cheese.bar" - ], - "avatar_url": "mxc://bleeker.street/CHEDDARandBRIE", - "guest_can_join": false, - "name": "CHEESE", - "num_joined_members": 37, - "room_id": "!ol19s:bleecker.street", - "topic": "Tasty tasty cheese", - "world_readable": true - } - ], - "next_batch": "p190q", - "prev_batch": "p1902", - "total_room_count_estimate": 115 - }) -}); - pub static PUSH_RULES: Lazy = Lazy::new(|| { json!({ "content": { @@ -830,28 +570,6 @@ pub static PUSH_RULES: Lazy = Lazy::new(|| { }) }); -pub static REGISTRATION_RESPONSE_ERR: Lazy = Lazy::new(|| { - json!({ - "errcode": "M_FORBIDDEN", - "error": "Invalid password", - "completed": ["example.type.foo"], - "flows": [ - { - "stages": ["example.type.foo", "example.type.bar"] - }, - { - "stages": ["example.type.foo", "example.type.baz"] - } - ], - "params": { - "example.type.baz": { - "example_key": "foobar" - } - }, - "session": "xxxxxx" - }) -}); - pub static REACTION: Lazy = Lazy::new(|| { json!({ "content": { @@ -998,12 +716,6 @@ pub static ROOM_AVATAR: Lazy = Lazy::new(|| { }) }); -pub static ROOM_ID: Lazy = Lazy::new(|| { - json!({ - "room_id": "!testroom:example.org" - }) -}); - pub static TAG: Lazy = Lazy::new(|| { json!({ "content": { diff --git a/crates/matrix-sdk/tests/integration/room/common.rs b/crates/matrix-sdk/tests/integration/room/common.rs index ba5045483..aa8505fa8 100644 --- a/crates/matrix-sdk/tests/integration/room/common.rs +++ b/crates/matrix-sdk/tests/integration/room/common.rs @@ -201,9 +201,7 @@ async fn room_timeline_with_remove() { .and(path_regex(r"^/_matrix/client/r0/rooms/.*/messages$")) .and(header("authorization", "Bearer 1234")) .and(query_param("from", "t392-516_47314_0_7_1_1_1_11444_1")) - .respond_with( - ResponseTemplate::new(200).set_body_json(&*test_json::SYNC_ROOM_MESSAGES_BATCH_1), - ) + .respond_with(ResponseTemplate::new(200).set_body_json(&*test_json::ROOM_MESSAGES_BATCH_1)) .expect(1) .named("messages_batch_1") .mount(&server) @@ -213,9 +211,7 @@ async fn room_timeline_with_remove() { .and(path_regex(r"^/_matrix/client/r0/rooms/.*/messages$")) .and(header("authorization", "Bearer 1234")) .and(query_param("from", "t47409-4357353_219380_26003_2269")) - .respond_with( - ResponseTemplate::new(200).set_body_json(&*test_json::SYNC_ROOM_MESSAGES_BATCH_2), - ) + .respond_with(ResponseTemplate::new(200).set_body_json(&*test_json::ROOM_MESSAGES_BATCH_2)) .expect(1) .named("messages_batch_2") .mount(&server) @@ -299,9 +295,7 @@ async fn room_timeline() { .and(path_regex(r"^/_matrix/client/r0/rooms/.*/messages$")) .and(header("authorization", "Bearer 1234")) .and(query_param("from", "t392-516_47314_0_7_1_1_1_11444_1")) - .respond_with( - ResponseTemplate::new(200).set_body_json(&*test_json::SYNC_ROOM_MESSAGES_BATCH_1), - ) + .respond_with(ResponseTemplate::new(200).set_body_json(&*test_json::ROOM_MESSAGES_BATCH_1)) .expect(1) .named("messages_batch_1") .mount(&server) @@ -311,9 +305,7 @@ async fn room_timeline() { .and(path_regex(r"^/_matrix/client/r0/rooms/.*/messages$")) .and(header("authorization", "Bearer 1234")) .and(query_param("from", "t47409-4357353_219380_26003_2269")) - .respond_with( - ResponseTemplate::new(200).set_body_json(&*test_json::SYNC_ROOM_MESSAGES_BATCH_2), - ) + .respond_with(ResponseTemplate::new(200).set_body_json(&*test_json::ROOM_MESSAGES_BATCH_2)) .expect(1) .named("messages_batch_2") .mount(&server) From d571ca718d9468ac81e1eb36e2e1390bfefa2e60 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Mon, 18 Jul 2022 12:59:59 +0300 Subject: [PATCH 44/73] fix(bindings/apple): Allow any platform OS simulator to run the Apple specific unit tests. --- .github/workflows/bindings_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/bindings_ci.yml b/.github/workflows/bindings_ci.yml index 0798ef17c..658142e17 100644 --- a/.github/workflows/bindings_ci.yml +++ b/.github/workflows/bindings_ci.yml @@ -170,4 +170,4 @@ jobs: -project bindings/apple/MatrixRustSDK.xcodeproj \ -scheme MatrixRustSDK \ -sdk iphonesimulator \ - -destination 'platform=iOS Simulator,name=iPhone 13,OS=15.4' + -destination 'platform=iOS Simulator,name=iPhone 13' From f215c92d0b572a4d444a0e63441607ee3c897ad7 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Mon, 18 Jul 2022 13:37:44 +0300 Subject: [PATCH 45/73] fix(bindings/apple): Remove briding header as no longer needed after corectly naming the module map --- bindings/apple/MatrixRustSDK.xcodeproj/project.pbxproj | 4 ---- bindings/apple/MatrixRustSDK/MatrixRustSDK-Bridging-Header.h | 5 ----- 2 files changed, 9 deletions(-) delete mode 100644 bindings/apple/MatrixRustSDK/MatrixRustSDK-Bridging-Header.h diff --git a/bindings/apple/MatrixRustSDK.xcodeproj/project.pbxproj b/bindings/apple/MatrixRustSDK.xcodeproj/project.pbxproj index 4021f5c5d..026ad1cf2 100644 --- a/bindings/apple/MatrixRustSDK.xcodeproj/project.pbxproj +++ b/bindings/apple/MatrixRustSDK.xcodeproj/project.pbxproj @@ -44,7 +44,6 @@ 181AA19927B52AA60005F102 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 181AA19A27B52AB40005F102 /* MatrixSDKFFI.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = MatrixSDKFFI.xcframework; path = ../../generated/MatrixSDKFFI.xcframework; sourceTree = ""; }; 189A89B927B40BBF0048B0A5 /* sdk.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = sdk.swift; path = ../../../generated/swift/sdk.swift; sourceTree = ""; }; - 189A89C327B417CA0048B0A5 /* MatrixRustSDK-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MatrixRustSDK-Bridging-Header.h"; sourceTree = ""; }; 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 = ""; }; 18CE89D927B2939900CA89E1 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -117,7 +116,6 @@ 18CE89D927B2939900CA89E1 /* ContentView.swift */, 18CE8A0127B293A900CA89E1 /* MatrixRustSDK.entitlements */, 18CE89DB27B2939A00CA89E1 /* Assets.xcassets */, - 189A89C327B417CA0048B0A5 /* MatrixRustSDK-Bridging-Header.h */, ); path = MatrixRustSDK; sourceTree = ""; @@ -401,7 +399,6 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_MACCATALYST = NO; 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"; @@ -435,7 +432,6 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTS_MACCATALYST = NO; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "MatrixRustSDK/MatrixRustSDK-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; diff --git a/bindings/apple/MatrixRustSDK/MatrixRustSDK-Bridging-Header.h b/bindings/apple/MatrixRustSDK/MatrixRustSDK-Bridging-Header.h deleted file mode 100644 index 7cd6f6ea3..000000000 --- a/bindings/apple/MatrixRustSDK/MatrixRustSDK-Bridging-Header.h +++ /dev/null @@ -1,5 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// - -#import "sdkFFI.h" From 66c5d5311ef3b4720ef604f31cbe55b457144543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= Date: Mon, 18 Jul 2022 12:30:44 +0200 Subject: [PATCH 46/73] test: Add methods to add events in bulk --- .../src/event_builder/invited_room.rs | 14 ++++- .../src/event_builder/joined_room.rs | 57 ++++++++++++++++++- .../src/event_builder/left_room.rs | 46 ++++++++++++++- .../matrix-sdk-test/src/event_builder/mod.rs | 18 ++++++ 4 files changed, 132 insertions(+), 3 deletions(-) diff --git a/crates/matrix-sdk-test/src/event_builder/invited_room.rs b/crates/matrix-sdk-test/src/event_builder/invited_room.rs index 6c1c7238a..649dc2385 100644 --- a/crates/matrix-sdk-test/src/event_builder/invited_room.rs +++ b/crates/matrix-sdk-test/src/event_builder/invited_room.rs @@ -1,4 +1,7 @@ -use ruma::{api::client::sync::sync_events::v3::InvitedRoom, OwnedRoomId}; +use ruma::{ + api::client::sync::sync_events::v3::InvitedRoom, events::AnyStrippedStateEvent, serde::Raw, + OwnedRoomId, +}; use super::StrippedStateTestEvent; use crate::test_json; @@ -22,6 +25,15 @@ impl InvitedRoomBuilder { self.inner.invite_state.events.push(event.into_raw_event()); self } + + /// Add events to the state in bulk. + pub fn add_state_bulk(mut self, events: I) -> Self + where + I: IntoIterator>, + { + self.inner.invite_state.events.extend(events); + self + } } impl Default for InvitedRoomBuilder { diff --git a/crates/matrix-sdk-test/src/event_builder/joined_room.rs b/crates/matrix-sdk-test/src/event_builder/joined_room.rs index 09839024f..5539243c9 100644 --- a/crates/matrix-sdk-test/src/event_builder/joined_room.rs +++ b/crates/matrix-sdk-test/src/event_builder/joined_room.rs @@ -1,4 +1,11 @@ -use ruma::{api::client::sync::sync_events::v3::JoinedRoom, OwnedRoomId}; +use ruma::{ + api::client::sync::sync_events::v3::JoinedRoom, + events::{ + AnyRoomAccountDataEvent, AnySyncEphemeralRoomEvent, AnySyncRoomEvent, AnySyncStateEvent, + }, + serde::Raw, + OwnedRoomId, +}; use serde_json::{from_value as from_json_value, Value as JsonValue}; use super::{EphemeralTestEvent, RoomAccountDataTestEvent, StateTestEvent, TimelineTestEvent}; @@ -24,6 +31,27 @@ impl JoinedRoomBuilder { self } + /// Add events in bulk to the timeline. + pub fn add_timeline_bulk(mut self, events: I) -> Self + where + I: IntoIterator>, + { + self.inner.timeline.events.extend(events); + self + } + + /// Add state events in bulk to the timeline. + /// + /// This is a convenience method that casts `Raw` to + /// `Raw` and calls `JoinedRoom::add_timeline_bulk()`. + pub fn add_timeline_state_bulk(self, events: I) -> Self + where + I: IntoIterator>, + { + let events = events.into_iter().map(|event| event.cast()); + self.add_timeline_bulk(events) + } + /// Set the timeline as limited. pub fn set_timeline_limited(mut self) -> Self { self.inner.timeline.limited = true; @@ -42,18 +70,45 @@ impl JoinedRoomBuilder { self } + /// Add events in bulk to the state. + pub fn add_state_bulk(mut self, events: I) -> Self + where + I: IntoIterator>, + { + self.inner.state.events.extend(events); + self + } + /// Add an ephemeral event. pub fn add_ephemeral_event(mut self, event: EphemeralTestEvent) -> Self { self.inner.ephemeral.events.push(event.into_raw_event()); self } + /// Add ephemeral events in bulk. + pub fn add_ephemeral_bulk(mut self, events: I) -> Self + where + I: IntoIterator>, + { + self.inner.ephemeral.events.extend(events); + self + } + /// Add room account data. pub fn add_account_data(mut self, event: RoomAccountDataTestEvent) -> Self { self.inner.account_data.events.push(event.into_raw_event()); self } + /// Add room account data in bulk. + pub fn add_account_data_bulk(mut self, events: I) -> Self + where + I: IntoIterator>, + { + self.inner.account_data.events.extend(events); + self + } + /// Set the room summary. pub fn set_room_summary(mut self, summary: JsonValue) -> Self { self.inner.summary = from_json_value(summary).unwrap(); diff --git a/crates/matrix-sdk-test/src/event_builder/left_room.rs b/crates/matrix-sdk-test/src/event_builder/left_room.rs index 57710392e..13c7e4d70 100644 --- a/crates/matrix-sdk-test/src/event_builder/left_room.rs +++ b/crates/matrix-sdk-test/src/event_builder/left_room.rs @@ -1,4 +1,9 @@ -use ruma::{api::client::sync::sync_events::v3::LeftRoom, OwnedRoomId}; +use ruma::{ + api::client::sync::sync_events::v3::LeftRoom, + events::{AnyRoomAccountDataEvent, AnySyncRoomEvent, AnySyncStateEvent}, + serde::Raw, + OwnedRoomId, +}; use super::{RoomAccountDataTestEvent, StateTestEvent, TimelineTestEvent}; use crate::test_json; @@ -23,6 +28,27 @@ impl LeftRoomBuilder { self } + /// Add events in bulk to the timeline. + pub fn add_timeline_bulk(mut self, events: I) -> Self + where + I: IntoIterator>, + { + self.inner.timeline.events.extend(events); + self + } + + /// Add state events in bulk to the timeline. + /// + /// This is a convenience method that casts `Raw` to + /// `Raw` and calls `LeftRoom::add_timeline_bulk()`. + pub fn add_timeline_state_bulk(self, events: I) -> Self + where + I: IntoIterator>, + { + let events = events.into_iter().map(|event| event.cast()); + self.add_timeline_bulk(events) + } + /// Set the timeline as limited. pub fn set_timeline_limited(mut self) -> Self { self.inner.timeline.limited = true; @@ -41,11 +67,29 @@ impl LeftRoomBuilder { self } + /// Add events in bulk to the state. + pub fn add_state_bulk(mut self, events: I) -> Self + where + I: IntoIterator>, + { + self.inner.state.events.extend(events); + self + } + /// Add room account data. pub fn add_account_data(mut self, event: RoomAccountDataTestEvent) -> Self { self.inner.account_data.events.push(event.into_raw_event()); self } + + /// Add room account data in bulk. + pub fn add_account_data_bulk(mut self, events: I) -> Self + where + I: IntoIterator>, + { + self.inner.account_data.events.extend(events); + self + } } impl Default for LeftRoomBuilder { diff --git a/crates/matrix-sdk-test/src/event_builder/mod.rs b/crates/matrix-sdk-test/src/event_builder/mod.rs index 21fd9619a..6484d3989 100644 --- a/crates/matrix-sdk-test/src/event_builder/mod.rs +++ b/crates/matrix-sdk-test/src/event_builder/mod.rs @@ -136,6 +136,15 @@ impl EventBuilder { self } + /// Add presence in bulk. + pub fn add_presence_bulk(&mut self, events: I) -> &mut Self + where + I: IntoIterator>, + { + self.presence.extend(events); + self + } + /// Add global account data. pub fn add_global_account_data_event( &mut self, @@ -151,6 +160,15 @@ impl EventBuilder { self } + /// Add global account data in bulk. + pub fn add_global_account_data_bulk(&mut self, events: I) -> &mut Self + where + I: IntoIterator>, + { + self.account_data.extend(events); + self + } + /// Builds a sync response as a JSON Value containing the events we queued /// so far. /// From c0a7b1732499885c6f1cbee4b808471269426613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= Date: Mon, 18 Jul 2022 12:31:35 +0200 Subject: [PATCH 47/73] test: Add method to create room member events in bulk --- .../matrix-sdk-test/src/event_builder/bulk.rs | 43 +++++++++++++++++++ .../matrix-sdk-test/src/event_builder/mod.rs | 2 + crates/matrix-sdk-test/src/lib.rs | 6 +-- 3 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 crates/matrix-sdk-test/src/event_builder/bulk.rs diff --git a/crates/matrix-sdk-test/src/event_builder/bulk.rs b/crates/matrix-sdk-test/src/event_builder/bulk.rs new file mode 100644 index 000000000..5ddf10d56 --- /dev/null +++ b/crates/matrix-sdk-test/src/event_builder/bulk.rs @@ -0,0 +1,43 @@ +use std::ops::Range; + +use ruma::{ + events::{room::member::MembershipState, AnySyncStateEvent}, + serde::Raw, +}; +use serde_json::{from_value as from_json_value, json}; + +/// Create `m.room.member` events in the given range. +/// +/// The user IDs are generated as `@user_{idx}:{server}`, with `idx` being the +/// current value in `range`, so providing the same range in several method +/// calls will create events that replace the previous state. +/// +/// The event IDs are generated as `$roommember_{batch}_{idx}` so it's important +/// to increment `batch` between method calls to avoid having two events with +/// the same event ID. +/// +/// This method can be used as input for room builders with +/// `add_timeline_state_bulk()` or `add_state_bulk()`. +pub fn bulk_room_members<'a>( + batch: usize, + range: Range, + server: &'a str, + membership: &'a MembershipState, +) -> impl Iterator> + 'a { + range.map(move |idx| { + let user_id = format!("@user_{idx}:{server}"); + let event_id = format!("$roommember_{batch}_{idx}"); + let ts = 151800000 + batch * 100 + idx; + from_json_value(json!({ + "content": { + "membership": membership, + }, + "event_id": event_id, + "origin_server_ts": ts, + "sender": user_id, + "state_key": user_id, + "type": "m.room.member", + })) + .unwrap() + }) +} diff --git a/crates/matrix-sdk-test/src/event_builder/mod.rs b/crates/matrix-sdk-test/src/event_builder/mod.rs index 6484d3989..4af354fe2 100644 --- a/crates/matrix-sdk-test/src/event_builder/mod.rs +++ b/crates/matrix-sdk-test/src/event_builder/mod.rs @@ -16,11 +16,13 @@ use serde_json::{from_value as from_json_value, json, Value as JsonValue}; use super::test_json; +mod bulk; mod invited_room; mod joined_room; mod left_room; mod test_event; +pub use bulk::bulk_room_members; pub use invited_room::InvitedRoomBuilder; pub use joined_room::JoinedRoomBuilder; pub use left_room::LeftRoomBuilder; diff --git a/crates/matrix-sdk-test/src/lib.rs b/crates/matrix-sdk-test/src/lib.rs index cc3cb6b6c..cbef86c99 100644 --- a/crates/matrix-sdk-test/src/lib.rs +++ b/crates/matrix-sdk-test/src/lib.rs @@ -9,9 +9,9 @@ mod event_builder; pub mod test_json; pub use event_builder::{ - EphemeralTestEvent, EventBuilder, GlobalAccountDataTestEvent, InvitedRoomBuilder, - JoinedRoomBuilder, LeftRoomBuilder, PresenceTestEvent, RoomAccountDataTestEvent, - StateTestEvent, StrippedStateTestEvent, TimelineTestEvent, + bulk_room_members, EphemeralTestEvent, EventBuilder, GlobalAccountDataTestEvent, + InvitedRoomBuilder, JoinedRoomBuilder, LeftRoomBuilder, PresenceTestEvent, + RoomAccountDataTestEvent, StateTestEvent, StrippedStateTestEvent, TimelineTestEvent, }; /// Embedded sync response files From b98e3d80a0006b508043a28e8ac0c2669ecd6437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= Date: Mon, 18 Jul 2022 13:38:30 +0200 Subject: [PATCH 48/73] test(sdk): Split tests for permalinks --- .../tests/integration/room/common.rs | 400 +++++++++--------- 1 file changed, 189 insertions(+), 211 deletions(-) diff --git a/crates/matrix-sdk/tests/integration/room/common.rs b/crates/matrix-sdk/tests/integration/room/common.rs index aa8505fa8..ac855e524 100644 --- a/crates/matrix-sdk/tests/integration/room/common.rs +++ b/crates/matrix-sdk/tests/integration/room/common.rs @@ -1,13 +1,15 @@ use std::time::Duration; use matrix_sdk::{config::SyncSettings, DisplayName, RoomMember}; -use matrix_sdk_test::{async_test, test_json}; +use matrix_sdk_test::{ + async_test, bulk_room_members, test_json, EventBuilder, JoinedRoomBuilder, TimelineTestEvent, +}; use ruma::{ event_id, - events::{AnySyncStateEvent, StateEventType}, + events::{room::member::MembershipState, AnySyncStateEvent, StateEventType}, room_id, }; -use serde_json::{json, Value as JsonValue}; +use serde_json::json; use wiremock::{ matchers::{header, method, path_regex}, Mock, ResponseTemplate, @@ -361,92 +363,26 @@ async fn room_timeline() { } #[async_test] -async fn room_permalink() { - fn sync_response(index: u8, room_timeline_events: &[JsonValue]) -> JsonValue { - json!({ - "device_one_time_keys_count": {}, - "next_batch": format!("s526_47314_0_7_1_1_1_11444_{}", index + 1), - "device_lists": { - "changed": [], - "left": [] - }, - "account_data": { - "events": [] - }, - "rooms": { - "invite": {}, - "join": { - "!test_room:127.0.0.1": { - "summary": {}, - "account_data": { - "events": [] - }, - "ephemeral": { - "events": [] - }, - "state": { - "events": [] - }, - "timeline": { - "events": room_timeline_events, - "limited": false, - "prev_batch": format!("s526_47314_0_7_1_1_1_11444_{}", index - 1), - }, - "unread_notifications": { - "highlight_count": 0, - "notification_count": 0, - } - } - }, - "leave": {} - }, - "to_device": { - "events": [] - }, - "presence": { - "events": [] - } - }) - } - - fn room_member_events(nb: usize, server: &str) -> Vec { - let mut events = Vec::with_capacity(nb); - for i in 0..nb { - let id = format!("${server}{i}"); - let user = format!("@user{i}:{server}"); - events.push(json!({ - "content": { - "membership": "join", - }, - "event_id": id, - "origin_server_ts": 151800140, - "sender": user, - "state_key": user, - "type": "m.room.member", - })) - } - events - } - +async fn room_route() { let (client, server) = logged_in_client().await; + let mut ev_builder = EventBuilder::new(); + let room_id = room_id!("!test_room:127.0.0.1"); // Without elligible server - let mut sync_index = 1; - let res = sync_response( - sync_index, - &[ - json!({ + ev_builder.add_joined_room( + JoinedRoomBuilder::new(room_id) + .add_timeline_event(TimelineTestEvent::Custom(json!({ "content": { "creator": "@creator:127.0.0.1", "room_version": "6", }, "event_id": "$151957878228ekrDs", "origin_server_ts": 15195787, - "sender": "@creator:localhost", + "sender": "@creator:127.0.0.1", "state_key": "", "type": "m.room.create", - }), - json!({ + }))) + .add_timeline_event(TimelineTestEvent::Custom(json!({ "content": { "membership": "join", }, @@ -455,110 +391,79 @@ async fn room_permalink() { "sender": "@creator:127.0.0.1", "state_key": "@creator:127.0.0.1", "type": "m.room.member", - }), - ], + }))), ); - mock_sync(&server, res, None).await; - client.sync_once(SyncSettings::new()).await.unwrap(); - let room = client.get_room(room_id!("!test_room:127.0.0.1")).unwrap(); - assert_eq!( - room.matrix_to_permalink().await.unwrap().to_string(), - "https://matrix.to/#/%21test_room%3A127.0.0.1" - ); - assert_eq!( - room.matrix_permalink(false).await.unwrap().to_string(), - "matrix:roomid/test_room:127.0.0.1" - ); - assert_eq!( - room.matrix_permalink(true).await.unwrap().to_string(), - "matrix:roomid/test_room:127.0.0.1?action=join" - ); + mock_sync(&server, ev_builder.build_json_sync_response(), None).await; + client.sync_once(SyncSettings::new()).await.unwrap(); + let room = client.get_room(room_id).unwrap(); + + let route = room.route().await.unwrap(); + assert_eq!(route.len(), 0); // With a single elligible server - sync_index += 1; - let res = sync_response( - sync_index, - &[json!({ - "content": { - "membership": "join", - }, - "event_id": "$151800140517rfvjc", - "origin_server_ts": 151800140, - "sender": "@example:localhost", - "state_key": "@example:localhost", - "type": "m.room.member", - })], - ); + let mut batch = 0; + ev_builder.add_joined_room(JoinedRoomBuilder::new(room_id).add_timeline_state_bulk( + bulk_room_members(batch, 0..1, "localhost", &MembershipState::Join), + )); let sync_token = client.sync_token().await.unwrap(); - mock_sync(&server, res, Some(sync_token.clone())).await; + mock_sync(&server, ev_builder.build_json_sync_response(), Some(sync_token.clone())).await; client.sync_once(SyncSettings::new().token(sync_token)).await.unwrap(); - assert_eq!( - room.matrix_to_permalink().await.unwrap().to_string(), - "https://matrix.to/#/%21test_room%3A127.0.0.1?via=localhost" - ); - assert_eq!( - room.matrix_permalink(false).await.unwrap().to_string(), - "matrix:roomid/test_room:127.0.0.1?via=localhost" - ); + let route = room.route().await.unwrap(); + assert_eq!(route.len(), 1); + assert_eq!(route[0], "localhost"); // With two elligible servers - sync_index += 1; - let res = sync_response(sync_index, &room_member_events(15, "notarealhs")); + batch += 1; + ev_builder.add_joined_room(JoinedRoomBuilder::new(room_id).add_timeline_state_bulk( + bulk_room_members(batch, 0..15, "notarealhs", &MembershipState::Join), + )); let sync_token = client.sync_token().await.unwrap(); - mock_sync(&server, res, Some(sync_token.clone())).await; + mock_sync(&server, ev_builder.build_json_sync_response(), Some(sync_token.clone())).await; client.sync_once(SyncSettings::new().token(sync_token)).await.unwrap(); - assert_eq!( - room.matrix_to_permalink().await.unwrap().to_string(), - "https://matrix.to/#/%21test_room%3A127.0.0.1?via=notarealhs&via=localhost" - ); - assert_eq!( - room.matrix_permalink(false).await.unwrap().to_string(), - "matrix:roomid/test_room:127.0.0.1?via=notarealhs&via=localhost" - ); + let route = room.route().await.unwrap(); + assert_eq!(route.len(), 2); + assert_eq!(route[0], "notarealhs"); + assert_eq!(route[1], "localhost"); // With three elligible servers - sync_index += 1; - let res = sync_response(sync_index, &room_member_events(5, "mymatrix")); + batch += 1; + ev_builder.add_joined_room(JoinedRoomBuilder::new(room_id).add_timeline_state_bulk( + bulk_room_members(batch, 0..5, "mymatrix", &MembershipState::Join), + )); let sync_token = client.sync_token().await.unwrap(); - mock_sync(&server, res, Some(sync_token.clone())).await; + mock_sync(&server, ev_builder.build_json_sync_response(), Some(sync_token.clone())).await; client.sync_once(SyncSettings::new().token(sync_token)).await.unwrap(); - assert_eq!( - room.matrix_to_permalink().await.unwrap().to_string(), - "https://matrix.to/#/%21test_room%3A127.0.0.1?via=notarealhs&via=mymatrix&via=localhost" - ); - assert_eq!( - room.matrix_permalink(false).await.unwrap().to_string(), - "matrix:roomid/test_room:127.0.0.1?via=notarealhs&via=mymatrix&via=localhost" - ); + let route = room.route().await.unwrap(); + assert_eq!(route.len(), 3); + assert_eq!(route[0], "notarealhs"); + assert_eq!(route[1], "mymatrix"); + assert_eq!(route[2], "localhost"); // With four elligible servers - sync_index += 1; - let res = sync_response(sync_index, &room_member_events(10, "yourmatrix")); + batch += 1; + ev_builder.add_joined_room(JoinedRoomBuilder::new(room_id).add_timeline_state_bulk( + bulk_room_members(batch, 0..10, "yourmatrix", &MembershipState::Join), + )); let sync_token = client.sync_token().await.unwrap(); - mock_sync(&server, res, Some(sync_token.clone())).await; + mock_sync(&server, ev_builder.build_json_sync_response(), Some(sync_token.clone())).await; client.sync_once(SyncSettings::new().token(sync_token)).await.unwrap(); - assert_eq!( - room.matrix_to_permalink().await.unwrap().to_string(), - "https://matrix.to/#/%21test_room%3A127.0.0.1?via=notarealhs&via=yourmatrix&via=mymatrix" - ); - assert_eq!( - room.matrix_permalink(false).await.unwrap().to_string(), - "matrix:roomid/test_room:127.0.0.1?via=notarealhs&via=yourmatrix&via=mymatrix" - ); + let route = room.route().await.unwrap(); + assert_eq!(route.len(), 3); + assert_eq!(route[0], "notarealhs"); + assert_eq!(route[1], "yourmatrix"); + assert_eq!(route[2], "mymatrix"); // With power levels - sync_index += 1; - let res = sync_response( - sync_index, - &[json!({ + ev_builder.add_joined_room(JoinedRoomBuilder::new(room_id).add_timeline_event( + TimelineTestEvent::Custom(json!({ "content": { "users": { - "@example:localhost": 50, + "@user_0:localhost": 50, }, }, "event_id": "$15139375512JaHAW", @@ -566,30 +471,25 @@ async fn room_permalink() { "sender": "@creator:127.0.0.1", "state_key": "", "type": "m.room.power_levels", - })], - ); + })), + )); let sync_token = client.sync_token().await.unwrap(); - mock_sync(&server, res, Some(sync_token.clone())).await; + mock_sync(&server, ev_builder.build_json_sync_response(), Some(sync_token.clone())).await; client.sync_once(SyncSettings::new().token(sync_token)).await.unwrap(); - assert_eq!( - room.matrix_to_permalink().await.unwrap().to_string(), - "https://matrix.to/#/%21test_room%3A127.0.0.1?via=localhost&via=notarealhs&via=yourmatrix" - ); - assert_eq!( - room.matrix_permalink(false).await.unwrap().to_string(), - "matrix:roomid/test_room:127.0.0.1?via=localhost&via=notarealhs&via=yourmatrix" - ); + let route = room.route().await.unwrap(); + assert_eq!(route.len(), 3); + assert_eq!(route[0], "localhost"); + assert_eq!(route[1], "notarealhs"); + assert_eq!(route[2], "yourmatrix"); // With higher power levels - sync_index += 1; - let res = sync_response( - sync_index, - &[json!({ + ev_builder.add_joined_room(JoinedRoomBuilder::new(room_id).add_timeline_event( + TimelineTestEvent::Custom(json!({ "content": { "users": { - "@example:localhost": 50, - "@user0:mymatrix": 70, + "@user_0:localhost": 50, + "@user_2:mymatrix": 70, }, }, "event_id": "$15139375512JaHAZ", @@ -597,26 +497,21 @@ async fn room_permalink() { "sender": "@creator:127.0.0.1", "state_key": "", "type": "m.room.power_levels", - })], - ); + })), + )); let sync_token = client.sync_token().await.unwrap(); - mock_sync(&server, res, Some(sync_token.clone())).await; + mock_sync(&server, ev_builder.build_json_sync_response(), Some(sync_token.clone())).await; client.sync_once(SyncSettings::new().token(sync_token)).await.unwrap(); - assert_eq!( - room.matrix_to_permalink().await.unwrap().to_string(), - "https://matrix.to/#/%21test_room%3A127.0.0.1?via=mymatrix&via=notarealhs&via=yourmatrix" - ); - assert_eq!( - room.matrix_permalink(false).await.unwrap().to_string(), - "matrix:roomid/test_room:127.0.0.1?via=mymatrix&via=notarealhs&via=yourmatrix" - ); + let route = room.route().await.unwrap(); + assert_eq!(route.len(), 3); + assert_eq!(route[0], "mymatrix"); + assert_eq!(route[1], "notarealhs"); + assert_eq!(route[2], "yourmatrix"); // With server ACLs - sync_index += 1; - let res = sync_response( - sync_index, - &[json!({ + ev_builder.add_joined_room(JoinedRoomBuilder::new(room_id).add_timeline_event( + TimelineTestEvent::Custom(json!({ "content": { "allow": ["*"], "allow_ip_literals": true, @@ -627,38 +522,69 @@ async fn room_permalink() { "sender": "@creator:127.0.0.1", "state_key": "", "type": "m.room.server_acl", - })], - ); + })), + )); let sync_token = client.sync_token().await.unwrap(); - mock_sync(&server, res, Some(sync_token.clone())).await; + mock_sync(&server, ev_builder.build_json_sync_response(), Some(sync_token.clone())).await; client.sync_once(SyncSettings::new().token(sync_token)).await.unwrap(); + let route = room.route().await.unwrap(); + assert_eq!(route.len(), 3); + assert_eq!(route[0], "mymatrix"); + assert_eq!(route[1], "yourmatrix"); + assert_eq!(route[2], "localhost"); +} + +#[async_test] +async fn room_permalink() { + let (client, server) = logged_in_client().await; + let mut ev_builder = EventBuilder::new(); + let room_id = room_id!("!test_room:127.0.0.1"); + + // Without aliases + ev_builder.add_joined_room( + JoinedRoomBuilder::new(room_id) + .add_timeline_state_bulk(bulk_room_members( + 0, + 0..1, + "localhost", + &MembershipState::Join, + )) + .add_timeline_state_bulk(bulk_room_members( + 1, + 0..5, + "notarealhs", + &MembershipState::Join, + )), + ); + mock_sync(&server, ev_builder.build_json_sync_response(), None).await; + client.sync_once(SyncSettings::new()).await.unwrap(); + let room = client.get_room(room_id).unwrap(); + assert_eq!( room.matrix_to_permalink().await.unwrap().to_string(), - "https://matrix.to/#/%21test_room%3A127.0.0.1?via=mymatrix&via=yourmatrix&via=localhost" + "https://matrix.to/#/%21test_room%3A127.0.0.1?via=notarealhs&via=localhost" ); assert_eq!( room.matrix_permalink(false).await.unwrap().to_string(), - "matrix:roomid/test_room:127.0.0.1?via=mymatrix&via=yourmatrix&via=localhost" + "matrix:roomid/test_room:127.0.0.1?via=notarealhs&via=localhost" ); // With an alternative alias - sync_index += 1; - let res = sync_response( - sync_index, - &[json!({ + ev_builder.add_joined_room(JoinedRoomBuilder::new(room_id).add_timeline_event( + TimelineTestEvent::Custom(json!({ "content": { "alt_aliases": ["#alias:localhost"], }, "event_id": "$15139375513VdeRF", "origin_server_ts": 151393755, - "sender": "@example:localhost", + "sender": "@user_0:localhost", "state_key": "", "type": "m.room.canonical_alias", - })], - ); + })), + )); let sync_token = client.sync_token().await.unwrap(); - mock_sync(&server, res, Some(sync_token.clone())).await; + mock_sync(&server, ev_builder.build_json_sync_response(), Some(sync_token.clone())).await; client.sync_once(SyncSettings::new().token(sync_token)).await.unwrap(); assert_eq!( @@ -668,23 +594,21 @@ async fn room_permalink() { assert_eq!(room.matrix_permalink(false).await.unwrap().to_string(), "matrix:r/alias:localhost"); // With a canonical alias - sync_index += 1; - let res = sync_response( - sync_index, - &[json!({ + ev_builder.add_joined_room(JoinedRoomBuilder::new(room_id).add_timeline_event( + TimelineTestEvent::Custom(json!({ "content": { "alias": "#canonical:localhost", "alt_aliases": ["#alias:localhost"], }, "event_id": "$15139375513VdeRF", "origin_server_ts": 151393755, - "sender": "@example:localhost", + "sender": "@user_0:localhost", "state_key": "", "type": "m.room.canonical_alias", - })], - ); + })), + )); let sync_token = client.sync_token().await.unwrap(); - mock_sync(&server, res, Some(sync_token.clone())).await; + mock_sync(&server, ev_builder.build_json_sync_response(), Some(sync_token.clone())).await; client.sync_once(SyncSettings::new().token(sync_token)).await.unwrap(); assert_eq!( @@ -699,14 +623,68 @@ async fn room_permalink() { room.matrix_permalink(true).await.unwrap().to_string(), "matrix:r/canonical:localhost?action=join" ); +} +#[async_test] +async fn room_event_permalink() { + let (client, server) = logged_in_client().await; + let mut ev_builder = EventBuilder::new(); + let room_id = room_id!("!test_room:127.0.0.1"); let event_id = event_id!("$15139375512JaHAW"); + + // Without aliases + ev_builder.add_joined_room( + JoinedRoomBuilder::new(room_id) + .add_timeline_state_bulk(bulk_room_members( + 0, + 0..1, + "localhost", + &MembershipState::Join, + )) + .add_timeline_state_bulk(bulk_room_members( + 1, + 0..5, + "notarealhs", + &MembershipState::Join, + )), + ); + mock_sync(&server, ev_builder.build_json_sync_response(), None).await; + client.sync_once(SyncSettings::new()).await.unwrap(); + let room = client.get_room(room_id).unwrap(); + assert_eq!( room.matrix_to_event_permalink(event_id).await.unwrap().to_string(), - "https://matrix.to/#/%21test_room%3A127.0.0.1/%2415139375512JaHAW?via=mymatrix&via=yourmatrix&via=localhost" + "https://matrix.to/#/%21test_room%3A127.0.0.1/%2415139375512JaHAW?via=notarealhs&via=localhost" ); assert_eq!( room.matrix_event_permalink(event_id).await.unwrap().to_string(), - "matrix:roomid/test_room:127.0.0.1/e/15139375512JaHAW?via=mymatrix&via=yourmatrix&via=localhost" + "matrix:roomid/test_room:127.0.0.1/e/15139375512JaHAW?via=notarealhs&via=localhost" + ); + + // Adding an alias doesn't change anything + ev_builder.add_joined_room(JoinedRoomBuilder::new(room_id).add_timeline_event( + TimelineTestEvent::Custom(json!({ + "content": { + "alias": "#canonical:localhost", + "alt_aliases": ["#alias:localhost"], + }, + "event_id": "$15139375513VdeRF", + "origin_server_ts": 151393755, + "sender": "@user_0:localhost", + "state_key": "", + "type": "m.room.canonical_alias", + })), + )); + let sync_token = client.sync_token().await.unwrap(); + mock_sync(&server, ev_builder.build_json_sync_response(), Some(sync_token.clone())).await; + client.sync_once(SyncSettings::new().token(sync_token)).await.unwrap(); + + assert_eq!( + room.matrix_to_event_permalink(event_id).await.unwrap().to_string(), + "https://matrix.to/#/%21test_room%3A127.0.0.1/%2415139375512JaHAW?via=notarealhs&via=localhost" + ); + assert_eq!( + room.matrix_event_permalink(event_id).await.unwrap().to_string(), + "matrix:roomid/test_room:127.0.0.1/e/15139375512JaHAW?via=notarealhs&via=localhost" ); } From c72ec36b3a63083b8b239f96f23339db197d5452 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 18 Jul 2022 14:39:39 +0200 Subject: [PATCH 49/73] chore(style) Make `cargo fmt` happy. --- bindings/matrix-sdk-crypto-js/src/tracing.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bindings/matrix-sdk-crypto-js/src/tracing.rs b/bindings/matrix-sdk-crypto-js/src/tracing.rs index ac0196c24..75a7801aa 100644 --- a/bindings/matrix-sdk-crypto-js/src/tracing.rs +++ b/bindings/matrix-sdk-crypto-js/src/tracing.rs @@ -39,7 +39,6 @@ mod inner { sync::{Arc, Once}, }; - use super::*; use tracing::{ field::{Field, Visit}, metadata::LevelFilter, @@ -51,6 +50,8 @@ mod inner { reload, Registry, }; + use super::*; + type TracingInner = Arc>; /// Type to install and to manipulate the tracing layer. From f937d8233673b723fb59bc99a22743c792c5ee0e Mon Sep 17 00:00:00 2001 From: Johannes Becker <66059836+johannescpk@users.noreply.github.com> Date: Mon, 18 Jul 2022 18:46:34 +0200 Subject: [PATCH 50/73] chore: Bump ruma --- benchmarks/Cargo.toml | 2 +- bindings/matrix-sdk-crypto-ffi/Cargo.toml | 2 +- bindings/matrix-sdk-crypto-js/Cargo.toml | 2 +- bindings/matrix-sdk-crypto-nodejs/Cargo.toml | 2 +- bindings/matrix-sdk-crypto-nodejs/src/attachment.rs | 2 +- crates/matrix-sdk-appservice/Cargo.toml | 2 +- crates/matrix-sdk-base/Cargo.toml | 4 ++-- crates/matrix-sdk-base/src/rooms/normal.rs | 3 +-- crates/matrix-sdk-base/src/store/integration_tests.rs | 2 +- crates/matrix-sdk-base/src/store/memory_store.rs | 3 +-- crates/matrix-sdk-base/src/store/mod.rs | 3 +-- crates/matrix-sdk-common/Cargo.toml | 2 +- crates/matrix-sdk-crypto/Cargo.toml | 4 ++-- crates/matrix-sdk-indexeddb/Cargo.toml | 2 +- crates/matrix-sdk-indexeddb/src/safe_encode.rs | 5 +++-- crates/matrix-sdk-indexeddb/src/state_store.rs | 3 +-- crates/matrix-sdk-qrcode/Cargo.toml | 2 +- crates/matrix-sdk-sled/Cargo.toml | 2 +- crates/matrix-sdk-sled/src/encode_key.rs | 5 ++--- crates/matrix-sdk-sled/src/state_store.rs | 3 +-- crates/matrix-sdk-test/Cargo.toml | 2 +- crates/matrix-sdk/Cargo.toml | 4 ++-- crates/matrix-sdk/src/room/common.rs | 10 +++++----- crates/matrix-sdk/src/room/joined.rs | 2 +- labs/sled-state-inspector/Cargo.toml | 2 +- 25 files changed, 35 insertions(+), 40 deletions(-) diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml index df6e400a8..8996f10c4 100644 --- a/benchmarks/Cargo.toml +++ b/benchmarks/Cargo.toml @@ -12,7 +12,7 @@ criterion = { version = "0.3.5", features = ["async", "async_tokio", "html_repor 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" } +ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae" } serde_json = "1.0.79" tempfile = "3.3.0" tokio = { version = "1.17.0", default-features = false, features = ["rt-multi-thread"] } diff --git a/bindings/matrix-sdk-crypto-ffi/Cargo.toml b/bindings/matrix-sdk-crypto-ffi/Cargo.toml index 6e18376c8..445fcbbc5 100644 --- a/bindings/matrix-sdk-crypto-ffi/Cargo.toml +++ b/bindings/matrix-sdk-crypto-ffi/Cargo.toml @@ -20,7 +20,7 @@ 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"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c"] } serde = "1.0.136" serde_json = "1.0.79" sha2 = "0.10.2" diff --git a/bindings/matrix-sdk-crypto-js/Cargo.toml b/bindings/matrix-sdk-crypto-js/Cargo.toml index dfe0f83c8..253619705 100644 --- a/bindings/matrix-sdk-crypto-js/Cargo.toml +++ b/bindings/matrix-sdk-crypto-js/Cargo.toml @@ -30,7 +30,7 @@ tracing = [] [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"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", 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" diff --git a/bindings/matrix-sdk-crypto-nodejs/Cargo.toml b/bindings/matrix-sdk-crypto-nodejs/Cargo.toml index bfe122f7e..3814efa31 100644 --- a/bindings/matrix-sdk-crypto-nodejs/Cargo.toml +++ b/bindings/matrix-sdk-crypto-nodejs/Cargo.toml @@ -28,7 +28,7 @@ tracing = ["dep:tracing-subscriber"] 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"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", 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" } diff --git a/bindings/matrix-sdk-crypto-nodejs/src/attachment.rs b/bindings/matrix-sdk-crypto-nodejs/src/attachment.rs index 9432c19b2..14b26b015 100644 --- a/bindings/matrix-sdk-crypto-nodejs/src/attachment.rs +++ b/bindings/matrix-sdk-crypto-nodejs/src/attachment.rs @@ -55,7 +55,7 @@ impl Attachment { None => { return Err(napi::Error::from_reason( "The media encryption info are absent from the given encrypted attachment" - .to_string(), + .to_owned(), )) } }; diff --git a/crates/matrix-sdk-appservice/Cargo.toml b/crates/matrix-sdk-appservice/Cargo.toml index d3f43ba66..0b9c3e981 100644 --- a/crates/matrix-sdk-appservice/Cargo.toml +++ b/crates/matrix-sdk-appservice/Cargo.toml @@ -34,7 +34,7 @@ http = "0.2.6" matrix-sdk = { version = "0.5.0", path = "../matrix-sdk", default-features = false, features = ["appservice"] } percent-encoding = "2.1.0" regex = "1.5.5" -ruma = { git = "https://github.com/ruma/ruma", rev = "96155915f", features = ["client-api-c", "appservice-api-s"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c", "appservice-api-s"] } serde = "1.0.136" serde_json = "1.0.79" serde_yaml = "0.8.23" diff --git a/crates/matrix-sdk-base/Cargo.toml b/crates/matrix-sdk-base/Cargo.toml index df9f29462..9836e0a8a 100644 --- a/crates/matrix-sdk-base/Cargo.toml +++ b/crates/matrix-sdk-base/Cargo.toml @@ -43,10 +43,10 @@ tracing = "0.1.34" zeroize = { version = "1.3.0", features = ["zeroize_derive"] } [target.'cfg(target_arch = "wasm32")'.dependencies] -ruma = { git = "https://github.com/ruma/ruma", rev = "96155915f", features = ["client-api-c", "js", "canonical-json"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c", "js", "canonical-json"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -ruma = { git = "https://github.com/ruma/ruma", rev = "96155915f", features = ["client-api-c", "canonical-json"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c", "canonical-json"] } [dev-dependencies] futures = { version = "0.3.21", default-features = false, features = ["executor"] } diff --git a/crates/matrix-sdk-base/src/rooms/normal.rs b/crates/matrix-sdk-base/src/rooms/normal.rs index 53156f060..39fe79c11 100644 --- a/crates/matrix-sdk-base/src/rooms/normal.rs +++ b/crates/matrix-sdk-base/src/rooms/normal.rs @@ -29,7 +29,7 @@ use matrix_sdk_common::locks::Mutex; use ruma::{ api::client::sync::sync_events::v3::RoomSummary as RumaSummary, events::{ - receipt::Receipt, + receipt::{Receipt, ReceiptType}, room::{ create::RoomCreateEventContent, encryption::RoomEncryptionEventContent, guest_access::GuestAccess, history_visibility::HistoryVisibility, join_rules::JoinRule, @@ -39,7 +39,6 @@ use ruma::{ AnyRoomAccountDataEvent, AnyStrippedStateEvent, AnySyncStateEvent, RoomAccountDataEventType, StateEventType, }, - receipt::ReceiptType, room::RoomType as CreateRoomType, EventId, OwnedEventId, OwnedMxcUri, OwnedRoomAliasId, OwnedUserId, RoomAliasId, RoomId, RoomVersionId, UserId, diff --git a/crates/matrix-sdk-base/src/store/integration_tests.rs b/crates/matrix-sdk-base/src/store/integration_tests.rs index b1950bf29..cf827374d 100644 --- a/crates/matrix-sdk-base/src/store/integration_tests.rs +++ b/crates/matrix-sdk-base/src/store/integration_tests.rs @@ -55,6 +55,7 @@ macro_rules! statestore_integration_tests { device_id, event_id, events::{ presence::PresenceEvent, + receipt::ReceiptType, room::{ member::{ MembershipState, OriginalSyncRoomMemberEvent, SyncRoomMemberEvent, @@ -69,7 +70,6 @@ macro_rules! statestore_integration_tests { StateEventType, StateUnsigned, }, mxc_uri, - receipt::ReceiptType, room_id, serde::Raw, uint, user_id, MilliSecondsSinceUnixEpoch, UserId, EventId, OwnedEventId, diff --git a/crates/matrix-sdk-base/src/store/memory_store.rs b/crates/matrix-sdk-base/src/store/memory_store.rs index 76bbf4108..a0321fad8 100644 --- a/crates/matrix-sdk-base/src/store/memory_store.rs +++ b/crates/matrix-sdk-base/src/store/memory_store.rs @@ -35,12 +35,11 @@ use ruma::{ use ruma::{ events::{ presence::PresenceEvent, - receipt::Receipt, + receipt::{Receipt, ReceiptType}, room::member::{MembershipState, StrippedRoomMemberEvent, SyncRoomMemberEvent}, AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, AnyStrippedStateEvent, AnySyncStateEvent, GlobalAccountDataEventType, RoomAccountDataEventType, StateEventType, }, - receipt::ReceiptType, serde::Raw, EventId, MxcUri, OwnedEventId, OwnedRoomId, OwnedUserId, RoomId, UserId, }; diff --git a/crates/matrix-sdk-base/src/store/mod.rs b/crates/matrix-sdk-base/src/store/mod.rs index c31926e69..acc0992f0 100644 --- a/crates/matrix-sdk-base/src/store/mod.rs +++ b/crates/matrix-sdk-base/src/store/mod.rs @@ -43,12 +43,11 @@ use ruma::{ api::client::push::get_notifications::v3::Notification, events::{ presence::PresenceEvent, - receipt::{Receipt, ReceiptEventContent}, + receipt::{Receipt, ReceiptEventContent, ReceiptType}, room::member::{StrippedRoomMemberEvent, SyncRoomMemberEvent}, AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, AnyStrippedStateEvent, AnySyncStateEvent, GlobalAccountDataEventType, RoomAccountDataEventType, StateEventType, }, - receipt::ReceiptType, serde::Raw, EventId, MxcUri, OwnedEventId, OwnedRoomId, OwnedUserId, RoomId, UserId, }; diff --git a/crates/matrix-sdk-common/Cargo.toml b/crates/matrix-sdk-common/Cargo.toml index f40bbce17..5256a7319 100644 --- a/crates/matrix-sdk-common/Cargo.toml +++ b/crates/matrix-sdk-common/Cargo.toml @@ -16,7 +16,7 @@ default-target = "x86_64-unknown-linux-gnu" targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"] [dependencies] -ruma = { git = "https://github.com/ruma/ruma", rev = "96155915f", features = ["client-api-c"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c"] } serde = "1.0.136" [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/crates/matrix-sdk-crypto/Cargo.toml b/crates/matrix-sdk-crypto/Cargo.toml index 21672e48f..298da5589 100644 --- a/crates/matrix-sdk-crypto/Cargo.toml +++ b/crates/matrix-sdk-crypto/Cargo.toml @@ -51,11 +51,11 @@ zeroize = { version = "1.3.0", features = ["zeroize_derive"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] tokio = { version = "1.18", default-features = false, features = ["time"] } -ruma = { git = "https://github.com/ruma/ruma", rev = "96155915f", features = ["client-api-c", "rand", "canonical-json", "unstable-msc2676", "unstable-msc2677"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c", "rand", "canonical-json", "unstable-msc2676", "unstable-msc2677"] } vodozemac = { git = "https://github.com/matrix-org/vodozemac/", rev = "2404f83f7d3a3779c1f518e4d949f7da9677c3dd" } [target.'cfg(target_arch = "wasm32")'.dependencies] -ruma = { git = "https://github.com/ruma/ruma", rev = "96155915f", features = ["client-api-c", "js", "rand", "canonical-json", "unstable-msc2676", "unstable-msc2677"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c", "js", "rand", "canonical-json", "unstable-msc2676", "unstable-msc2677"] } vodozemac = { git = "https://github.com/matrix-org/vodozemac/", rev = "2404f83f7d3a3779c1f518e4d949f7da9677c3dd", features = ["js"] } [dev-dependencies] diff --git a/crates/matrix-sdk-indexeddb/Cargo.toml b/crates/matrix-sdk-indexeddb/Cargo.toml index 5703b5816..2663796cb 100644 --- a/crates/matrix-sdk-indexeddb/Cargo.toml +++ b/crates/matrix-sdk-indexeddb/Cargo.toml @@ -29,7 +29,7 @@ indexed_db_futures = "0.2.3" matrix-sdk-base = { version = "0.5.0", path = "../matrix-sdk-base" } matrix-sdk-crypto = { version = "0.5.0", path = "../matrix-sdk-crypto", optional = true } matrix-sdk-store-encryption = { version = "0.1.0", path = "../matrix-sdk-store-encryption" } -ruma = { git = "https://github.com/ruma/ruma", rev = "96155915f" } +ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae" } serde = "1.0.136" serde_json = "1.0.79" thiserror = "1.0.30" diff --git a/crates/matrix-sdk-indexeddb/src/safe_encode.rs b/crates/matrix-sdk-indexeddb/src/safe_encode.rs index c6927e707..081c1a35a 100644 --- a/crates/matrix-sdk-indexeddb/src/safe_encode.rs +++ b/crates/matrix-sdk-indexeddb/src/safe_encode.rs @@ -2,8 +2,9 @@ use base64::{encode_config as base64_encode, STANDARD_NO_PAD}; use matrix_sdk_store_encryption::StoreCipher; use ruma::{ - events::{GlobalAccountDataEventType, RoomAccountDataEventType, StateEventType}, - receipt::ReceiptType, + events::{ + receipt::ReceiptType, GlobalAccountDataEventType, RoomAccountDataEventType, StateEventType, + }, DeviceId, EventId, MxcUri, OwnedEventId, OwnedRoomId, OwnedUserId, RoomId, TransactionId, UserId, }; diff --git a/crates/matrix-sdk-indexeddb/src/state_store.rs b/crates/matrix-sdk-indexeddb/src/state_store.rs index f30830d05..229dc7e53 100644 --- a/crates/matrix-sdk-indexeddb/src/state_store.rs +++ b/crates/matrix-sdk-indexeddb/src/state_store.rs @@ -31,12 +31,11 @@ use matrix_sdk_store_encryption::{Error as EncryptionError, StoreCipher}; use ruma::{ events::{ presence::PresenceEvent, - receipt::Receipt, + receipt::{Receipt, ReceiptType}, room::member::{MembershipState, RoomMemberEventContent}, AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, AnySyncStateEvent, GlobalAccountDataEventType, RoomAccountDataEventType, StateEventType, }, - receipt::ReceiptType, serde::Raw, EventId, MxcUri, OwnedEventId, OwnedUserId, RoomId, UserId, }; diff --git a/crates/matrix-sdk-qrcode/Cargo.toml b/crates/matrix-sdk-qrcode/Cargo.toml index 350ebd05d..552da61bd 100644 --- a/crates/matrix-sdk-qrcode/Cargo.toml +++ b/crates/matrix-sdk-qrcode/Cargo.toml @@ -25,7 +25,7 @@ byteorder = "1.4.3" image = { version = "0.23.0", optional = true } qrcode = { version = "0.12.0", default-features = false } rqrr = { version = "0.4.0", optional = true } -ruma-common = { git = "https://github.com/ruma/ruma", rev = "96155915f" } +ruma-common = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae" } thiserror = "1.0.30" [dependencies.vodozemac] diff --git a/crates/matrix-sdk-sled/Cargo.toml b/crates/matrix-sdk-sled/Cargo.toml index 0ba6814b1..32d33c1f8 100644 --- a/crates/matrix-sdk-sled/Cargo.toml +++ b/crates/matrix-sdk-sled/Cargo.toml @@ -37,7 +37,7 @@ matrix-sdk-base = { version = "0.5.0", path = "../matrix-sdk-base", optional = t matrix-sdk-common = { version = "0.5.0", path = "../matrix-sdk-common" } matrix-sdk-crypto = { version = "0.5.0", path = "../matrix-sdk-crypto", optional = true } matrix-sdk-store-encryption = { version = "0.1.0", path = "../matrix-sdk-store-encryption" } -ruma = { git = "https://github.com/ruma/ruma", rev = "96155915f" } +ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae" } serde = "1.0.136" serde_json = "1.0.79" sled = "0.34.7" diff --git a/crates/matrix-sdk-sled/src/encode_key.rs b/crates/matrix-sdk-sled/src/encode_key.rs index b36738713..91c06e09f 100644 --- a/crates/matrix-sdk-sled/src/encode_key.rs +++ b/crates/matrix-sdk-sled/src/encode_key.rs @@ -3,10 +3,9 @@ use std::{borrow::Cow, ops::Deref}; use matrix_sdk_store_encryption::StoreCipher; use ruma::{ events::{ - secret::request::SecretName, GlobalAccountDataEventType, RoomAccountDataEventType, - StateEventType, + receipt::ReceiptType, secret::request::SecretName, GlobalAccountDataEventType, + RoomAccountDataEventType, StateEventType, }, - receipt::ReceiptType, DeviceId, EventEncryptionAlgorithm, EventId, MxcUri, OwnedEventId, OwnedRoomId, OwnedUserId, RoomId, TransactionId, UserId, }; diff --git a/crates/matrix-sdk-sled/src/state_store.rs b/crates/matrix-sdk-sled/src/state_store.rs index 0f7501715..c7db5fb63 100644 --- a/crates/matrix-sdk-sled/src/state_store.rs +++ b/crates/matrix-sdk-sled/src/state_store.rs @@ -42,12 +42,11 @@ use ruma::{ use ruma::{ events::{ presence::PresenceEvent, - receipt::Receipt, + receipt::{Receipt, ReceiptType}, room::member::{MembershipState, RoomMemberEventContent}, AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, AnySyncStateEvent, GlobalAccountDataEventType, RoomAccountDataEventType, StateEventType, }, - receipt::ReceiptType, serde::Raw, EventId, IdParseError, MxcUri, OwnedEventId, OwnedUserId, RoomId, UserId, }; diff --git a/crates/matrix-sdk-test/Cargo.toml b/crates/matrix-sdk-test/Cargo.toml index 323888e79..c3b00f4dd 100644 --- a/crates/matrix-sdk-test/Cargo.toml +++ b/crates/matrix-sdk-test/Cargo.toml @@ -18,6 +18,6 @@ appservice = [] http = "0.2.6" matrix-sdk-test-macros = { version = "0.2.0", path = "../matrix-sdk-test-macros" } once_cell = "1.10.0" -ruma = { git = "https://github.com/ruma/ruma", rev = "96155915f", features = ["client-api-c"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c"] } serde = "1.0.136" serde_json = "1.0.79" diff --git a/crates/matrix-sdk/Cargo.toml b/crates/matrix-sdk/Cargo.toml index 7c2c6fe05..d247ed14a 100644 --- a/crates/matrix-sdk/Cargo.toml +++ b/crates/matrix-sdk/Cargo.toml @@ -110,12 +110,12 @@ default_features = false [dependencies.ruma] git = "https://github.com/ruma/ruma" -rev = "96155915f" +rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae" features = ["client-api-c", "compat", "rand", "unstable-msc2448"] [dependencies.ruma-client-api] git = "https://github.com/ruma/ruma" -rev = "96155915f" +rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae" features = ["unstable-msc2965"] [dependencies.tokio-stream] diff --git a/crates/matrix-sdk/src/room/common.rs b/crates/matrix-sdk/src/room/common.rs index d637ccb49..8be144f20 100644 --- a/crates/matrix-sdk/src/room/common.rs +++ b/crates/matrix-sdk/src/room/common.rs @@ -1003,7 +1003,7 @@ impl Common { } let via = self.route().await?; - Ok(self.room_id().matrix_to_uri(via)) + Ok(self.room_id().matrix_to_uri_via(via)) } /// Get a `matrix:` permalink to this room. @@ -1022,7 +1022,7 @@ impl Common { } let via = self.route().await?; - Ok(self.room_id().matrix_uri(via, join)) + Ok(self.room_id().matrix_uri_via(via, join)) } /// Get a `matrix.to` permalink to an event in this room. @@ -1045,7 +1045,7 @@ impl Common { // Don't use the alias because an event is tied to a room ID, but an // alias might point to another room, e.g. after a room upgrade. let via = self.route().await?; - Ok(self.room_id().matrix_to_event_uri(event_id, via)) + Ok(self.room_id().matrix_to_event_uri_via(event_id, via)) } /// Get a `matrix:` permalink to an event in this room. @@ -1068,7 +1068,7 @@ impl Common { // Don't use the alias because an event is tied to a room ID, but an // alias might point to another room, e.g. after a room upgrade. let via = self.route().await?; - Ok(self.room_id().matrix_event_uri(event_id, via)) + Ok(self.room_id().matrix_event_uri_via(event_id, via)) } } @@ -1125,7 +1125,7 @@ impl<'a> MessagesOptions<'a> { } fn into_request(self, room_id: &'a RoomId) -> get_message_events::v3::Request<'_> { - assign!(get_message_events::v3::Request::new(room_id, self.from, self.dir), { + assign!(get_message_events::v3::Request::new(room_id, Some(self.from), self.dir), { to: self.to, limit: self.limit, filter: self.filter, diff --git a/crates/matrix-sdk/src/room/joined.rs b/crates/matrix-sdk/src/room/joined.rs index cbf51c20b..184df9489 100644 --- a/crates/matrix-sdk/src/room/joined.rs +++ b/crates/matrix-sdk/src/room/joined.rs @@ -27,10 +27,10 @@ use ruma::{ }, assign, events::{room::message::RoomMessageEventContent, MessageLikeEventContent, StateEventContent}, - receipt::ReceiptType, serde::Raw, EventId, OwnedTransactionId, TransactionId, UserId, }; +use ruma_client_api::receipt::create_receipt::v3::ReceiptType; use serde_json::Value; use tracing::debug; #[cfg(feature = "e2e-encryption")] diff --git a/labs/sled-state-inspector/Cargo.toml b/labs/sled-state-inspector/Cargo.toml index d4996bb38..3255f6c0f 100644 --- a/labs/sled-state-inspector/Cargo.toml +++ b/labs/sled-state-inspector/Cargo.toml @@ -10,7 +10,7 @@ clap = "3.2.4" futures = { version = "0.3.21", default-features = false, features = ["executor"] } matrix-sdk-base = { path = "../../crates/matrix-sdk-base", version = "0.5.0" } matrix-sdk-sled = { path = "../../crates/matrix-sdk-sled", version = "0.1.0" } -ruma = { git = "https://github.com/ruma/ruma", rev = "96155915f" } +ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae" } rustyline = "9.1.2" rustyline-derive = "0.6.0" serde = "1.0.136" From aa8206d6c8ced45b0a454cb37c4fdda3cfaadacb Mon Sep 17 00:00:00 2001 From: Johannes Becker Date: Mon, 18 Jul 2022 19:32:16 +0200 Subject: [PATCH 51/73] chore: Bump ruma --- benchmarks/Cargo.toml | 2 +- bindings/matrix-sdk-crypto-ffi/Cargo.toml | 2 +- bindings/matrix-sdk-crypto-js/Cargo.toml | 2 +- bindings/matrix-sdk-crypto-nodejs/Cargo.toml | 2 +- crates/matrix-sdk-appservice/Cargo.toml | 2 +- crates/matrix-sdk-base/Cargo.toml | 4 ++-- crates/matrix-sdk-common/Cargo.toml | 2 +- crates/matrix-sdk-crypto/Cargo.toml | 4 ++-- crates/matrix-sdk-indexeddb/Cargo.toml | 2 +- crates/matrix-sdk-qrcode/Cargo.toml | 2 +- crates/matrix-sdk-sled/Cargo.toml | 2 +- crates/matrix-sdk-test/Cargo.toml | 2 +- crates/matrix-sdk/Cargo.toml | 4 ++-- labs/sled-state-inspector/Cargo.toml | 2 +- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml index 8996f10c4..f74e3e092 100644 --- a/benchmarks/Cargo.toml +++ b/benchmarks/Cargo.toml @@ -12,7 +12,7 @@ criterion = { version = "0.3.5", features = ["async", "async_tokio", "html_repor 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 = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae" } +ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94" } serde_json = "1.0.79" tempfile = "3.3.0" tokio = { version = "1.17.0", default-features = false, features = ["rt-multi-thread"] } diff --git a/bindings/matrix-sdk-crypto-ffi/Cargo.toml b/bindings/matrix-sdk-crypto-ffi/Cargo.toml index 445fcbbc5..bb7fc696f 100644 --- a/bindings/matrix-sdk-crypto-ffi/Cargo.toml +++ b/bindings/matrix-sdk-crypto-ffi/Cargo.toml @@ -20,7 +20,7 @@ hmac = "0.12.1" http = "0.2.6" pbkdf2 = "0.11.0" rand = "0.8.5" -ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c"] } serde = "1.0.136" serde_json = "1.0.79" sha2 = "0.10.2" diff --git a/bindings/matrix-sdk-crypto-js/Cargo.toml b/bindings/matrix-sdk-crypto-js/Cargo.toml index 253619705..1c8542856 100644 --- a/bindings/matrix-sdk-crypto-js/Cargo.toml +++ b/bindings/matrix-sdk-crypto-js/Cargo.toml @@ -30,7 +30,7 @@ tracing = [] [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 = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c", "js", "rand", "unstable-msc2676", "unstable-msc2677"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", 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" diff --git a/bindings/matrix-sdk-crypto-nodejs/Cargo.toml b/bindings/matrix-sdk-crypto-nodejs/Cargo.toml index 3814efa31..cf11d92a8 100644 --- a/bindings/matrix-sdk-crypto-nodejs/Cargo.toml +++ b/bindings/matrix-sdk-crypto-nodejs/Cargo.toml @@ -28,7 +28,7 @@ tracing = ["dep:tracing-subscriber"] 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 = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c", "rand", "unstable-msc2676", "unstable-msc2677"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", 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" } diff --git a/crates/matrix-sdk-appservice/Cargo.toml b/crates/matrix-sdk-appservice/Cargo.toml index 0b9c3e981..2e83abe34 100644 --- a/crates/matrix-sdk-appservice/Cargo.toml +++ b/crates/matrix-sdk-appservice/Cargo.toml @@ -34,7 +34,7 @@ http = "0.2.6" matrix-sdk = { version = "0.5.0", path = "../matrix-sdk", default-features = false, features = ["appservice"] } percent-encoding = "2.1.0" regex = "1.5.5" -ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c", "appservice-api-s"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c", "appservice-api-s"] } serde = "1.0.136" serde_json = "1.0.79" serde_yaml = "0.8.23" diff --git a/crates/matrix-sdk-base/Cargo.toml b/crates/matrix-sdk-base/Cargo.toml index 9836e0a8a..4ce3c1aba 100644 --- a/crates/matrix-sdk-base/Cargo.toml +++ b/crates/matrix-sdk-base/Cargo.toml @@ -43,10 +43,10 @@ tracing = "0.1.34" zeroize = { version = "1.3.0", features = ["zeroize_derive"] } [target.'cfg(target_arch = "wasm32")'.dependencies] -ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c", "js", "canonical-json"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c", "js", "canonical-json"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c", "canonical-json"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c", "canonical-json"] } [dev-dependencies] futures = { version = "0.3.21", default-features = false, features = ["executor"] } diff --git a/crates/matrix-sdk-common/Cargo.toml b/crates/matrix-sdk-common/Cargo.toml index 5256a7319..25df7cf46 100644 --- a/crates/matrix-sdk-common/Cargo.toml +++ b/crates/matrix-sdk-common/Cargo.toml @@ -16,7 +16,7 @@ default-target = "x86_64-unknown-linux-gnu" targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"] [dependencies] -ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c"] } serde = "1.0.136" [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/crates/matrix-sdk-crypto/Cargo.toml b/crates/matrix-sdk-crypto/Cargo.toml index 298da5589..7bcaad51a 100644 --- a/crates/matrix-sdk-crypto/Cargo.toml +++ b/crates/matrix-sdk-crypto/Cargo.toml @@ -51,11 +51,11 @@ zeroize = { version = "1.3.0", features = ["zeroize_derive"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] tokio = { version = "1.18", default-features = false, features = ["time"] } -ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c", "rand", "canonical-json", "unstable-msc2676", "unstable-msc2677"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c", "rand", "canonical-json", "unstable-msc2676", "unstable-msc2677"] } vodozemac = { git = "https://github.com/matrix-org/vodozemac/", rev = "2404f83f7d3a3779c1f518e4d949f7da9677c3dd" } [target.'cfg(target_arch = "wasm32")'.dependencies] -ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c", "js", "rand", "canonical-json", "unstable-msc2676", "unstable-msc2677"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c", "js", "rand", "canonical-json", "unstable-msc2676", "unstable-msc2677"] } vodozemac = { git = "https://github.com/matrix-org/vodozemac/", rev = "2404f83f7d3a3779c1f518e4d949f7da9677c3dd", features = ["js"] } [dev-dependencies] diff --git a/crates/matrix-sdk-indexeddb/Cargo.toml b/crates/matrix-sdk-indexeddb/Cargo.toml index 2663796cb..bb7dd577c 100644 --- a/crates/matrix-sdk-indexeddb/Cargo.toml +++ b/crates/matrix-sdk-indexeddb/Cargo.toml @@ -29,7 +29,7 @@ indexed_db_futures = "0.2.3" matrix-sdk-base = { version = "0.5.0", path = "../matrix-sdk-base" } matrix-sdk-crypto = { version = "0.5.0", path = "../matrix-sdk-crypto", optional = true } matrix-sdk-store-encryption = { version = "0.1.0", path = "../matrix-sdk-store-encryption" } -ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae" } +ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94" } serde = "1.0.136" serde_json = "1.0.79" thiserror = "1.0.30" diff --git a/crates/matrix-sdk-qrcode/Cargo.toml b/crates/matrix-sdk-qrcode/Cargo.toml index 552da61bd..5eebd52f7 100644 --- a/crates/matrix-sdk-qrcode/Cargo.toml +++ b/crates/matrix-sdk-qrcode/Cargo.toml @@ -25,7 +25,7 @@ byteorder = "1.4.3" image = { version = "0.23.0", optional = true } qrcode = { version = "0.12.0", default-features = false } rqrr = { version = "0.4.0", optional = true } -ruma-common = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae" } +ruma-common = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94" } thiserror = "1.0.30" [dependencies.vodozemac] diff --git a/crates/matrix-sdk-sled/Cargo.toml b/crates/matrix-sdk-sled/Cargo.toml index 32d33c1f8..b599f0c78 100644 --- a/crates/matrix-sdk-sled/Cargo.toml +++ b/crates/matrix-sdk-sled/Cargo.toml @@ -37,7 +37,7 @@ matrix-sdk-base = { version = "0.5.0", path = "../matrix-sdk-base", optional = t matrix-sdk-common = { version = "0.5.0", path = "../matrix-sdk-common" } matrix-sdk-crypto = { version = "0.5.0", path = "../matrix-sdk-crypto", optional = true } matrix-sdk-store-encryption = { version = "0.1.0", path = "../matrix-sdk-store-encryption" } -ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae" } +ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94" } serde = "1.0.136" serde_json = "1.0.79" sled = "0.34.7" diff --git a/crates/matrix-sdk-test/Cargo.toml b/crates/matrix-sdk-test/Cargo.toml index c3b00f4dd..0aa086062 100644 --- a/crates/matrix-sdk-test/Cargo.toml +++ b/crates/matrix-sdk-test/Cargo.toml @@ -18,6 +18,6 @@ appservice = [] http = "0.2.6" matrix-sdk-test-macros = { version = "0.2.0", path = "../matrix-sdk-test-macros" } once_cell = "1.10.0" -ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae", features = ["client-api-c"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c"] } serde = "1.0.136" serde_json = "1.0.79" diff --git a/crates/matrix-sdk/Cargo.toml b/crates/matrix-sdk/Cargo.toml index d247ed14a..83ff36d96 100644 --- a/crates/matrix-sdk/Cargo.toml +++ b/crates/matrix-sdk/Cargo.toml @@ -110,12 +110,12 @@ default_features = false [dependencies.ruma] git = "https://github.com/ruma/ruma" -rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae" +rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94" features = ["client-api-c", "compat", "rand", "unstable-msc2448"] [dependencies.ruma-client-api] git = "https://github.com/ruma/ruma" -rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae" +rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94" features = ["unstable-msc2965"] [dependencies.tokio-stream] diff --git a/labs/sled-state-inspector/Cargo.toml b/labs/sled-state-inspector/Cargo.toml index 3255f6c0f..69b330f8b 100644 --- a/labs/sled-state-inspector/Cargo.toml +++ b/labs/sled-state-inspector/Cargo.toml @@ -10,7 +10,7 @@ clap = "3.2.4" futures = { version = "0.3.21", default-features = false, features = ["executor"] } matrix-sdk-base = { path = "../../crates/matrix-sdk-base", version = "0.5.0" } matrix-sdk-sled = { path = "../../crates/matrix-sdk-sled", version = "0.1.0" } -ruma = { git = "https://github.com/ruma/ruma", rev = "7ec599e83d8ba6b2ace9e4fe184fc7560b0ff6ae" } +ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94" } rustyline = "9.1.2" rustyline-derive = "0.6.0" serde = "1.0.136" From 9318c2f1e83081ead8b9738646a6a0d8c8bc8afa Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Tue, 19 Jul 2022 11:36:30 +0200 Subject: [PATCH 52/73] ci(crypto-nodejs): switch to main branch --- .github/workflows/prep-crypto-nodejs-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prep-crypto-nodejs-release.yml b/.github/workflows/prep-crypto-nodejs-release.yml index 3a7db0b58..2edf2cdfc 100644 --- a/.github/workflows/prep-crypto-nodejs-release.yml +++ b/.github/workflows/prep-crypto-nodejs-release.yml @@ -110,7 +110,7 @@ jobs: trigger-release: # and trigger the tagging release workflow - uses: matrix-org/matrix-rust-sdk/.github/workflows/release-crypto-nodejs.yml@ben-release-crypto-nodes-beta0 + uses: matrix-org/matrix-rust-sdk/.github/workflows/release-crypto-nodejs.yml@main needs: ['prepare-release'] name: "Trigger release Workflow" with: From 1940ebefcbde4ff302dabf20cb0321d003646ce1 Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Tue, 19 Jul 2022 12:22:53 +0200 Subject: [PATCH 53/73] style(crypto): use matches for legibility --- crates/matrix-sdk-crypto/src/verification/requests.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/matrix-sdk-crypto/src/verification/requests.rs b/crates/matrix-sdk-crypto/src/verification/requests.rs index fd1450e16..ceb248a67 100644 --- a/crates/matrix-sdk-crypto/src/verification/requests.rs +++ b/crates/matrix-sdk-crypto/src/verification/requests.rs @@ -1098,12 +1098,10 @@ impl RequestState { // before the other side tried to do the same; ignore it if we did and // we're the lexicographically smaller user ID (or device ID if equal). use std::cmp::Ordering; - match (sender.cmp(own_user_id), device.device_id().cmp(own_device_id)) { - (Ordering::Greater, _) | (Ordering::Equal, Ordering::Greater) => { - false - } - _ => true, - } + !matches!( + (sender.cmp(own_user_id), device.device_id().cmp(own_device_id)), + (Ordering::Greater, _) | (Ordering::Equal, Ordering::Greater) + ) } else { true }; From a10a26a68d7870f421c93958925b8d326a2a6c19 Mon Sep 17 00:00:00 2001 From: Doug Date: Tue, 19 Jul 2022 11:36:34 +0100 Subject: [PATCH 54/73] Tidy up authentication service. Add HomeserverLoginDetails --- bindings/matrix-sdk-ffi/src/api.udl | 21 +++-- .../src/authentication_service.rs | 79 +++++++++++-------- 2 files changed, 57 insertions(+), 43 deletions(-) diff --git a/bindings/matrix-sdk-ffi/src/api.udl b/bindings/matrix-sdk-ffi/src/api.udl index 80a24aa20..5ccb81863 100644 --- a/bindings/matrix-sdk-ffi/src/api.udl +++ b/bindings/matrix-sdk-ffi/src/api.udl @@ -156,24 +156,21 @@ interface MediaSource { [Error] enum AuthenticationError { - "ClientMissing", - "Generic", + "ClientMissing", + "Generic", +}; + +interface HomeserverLoginDetails { + string url(); + string? authentication_issuer(); + boolean supports_password_login(); }; interface AuthenticationService { constructor(string base_path); [Throws=AuthenticationError] - string homeserver(); - - [Throws=AuthenticationError] - string? authentication_issuer(); - - [Throws=AuthenticationError] - boolean supports_password_login(); - - [Throws=AuthenticationError] - void use_server(string server_name); + HomeserverLoginDetails configure_homeserver(string server_name); [Throws=AuthenticationError] Client login(string username, string password); diff --git a/bindings/matrix-sdk-ffi/src/authentication_service.rs b/bindings/matrix-sdk-ffi/src/authentication_service.rs index 7ed148d82..da52f9fc1 100644 --- a/bindings/matrix-sdk-ffi/src/authentication_service.rs +++ b/bindings/matrix-sdk-ffi/src/authentication_service.rs @@ -23,42 +23,42 @@ impl From for AuthenticationError { } } +pub struct HomeserverLoginDetails { + url: String, + authentication_issuer: Option, + supports_password_login: bool, +} + +impl HomeserverLoginDetails { + /// The URL of the currently configured homeserver. + pub fn url(&self) -> String { + self.url.clone() + } + + /// The OIDC Provider that is trusted by the homeserver. `None` when + /// not configured. + pub fn authentication_issuer(&self) -> Option { + self.authentication_issuer.clone() + } + + /// Whether the current homeserver supports the password login flow. + pub fn supports_password_login(&self) -> bool { + self.supports_password_login + } +} + impl AuthenticationService { /// Creates a new service to authenticate a user with. pub fn new(base_path: String) -> Self { AuthenticationService { base_path, client: RwLock::new(None) } } - /// The currently configured homeserver. - pub fn homeserver(&self) -> Result { - self.client - .read() - .as_ref() - .ok_or(AuthenticationError::ClientMissing) - .map(|client| client.homeserver()) - } - - /// The OIDC Provider that is trusted by the homeserver. `None` when - /// not configured. - pub fn authentication_issuer(&self) -> Result, AuthenticationError> { - self.client - .read() - .as_ref() - .ok_or(AuthenticationError::ClientMissing) - .map(|client| client.authentication_issuer()) - } - - /// Whether the current homeserver supports the password login flow. - pub fn supports_password_login(&self) -> Result { - self.client - .read() - .as_ref() - .ok_or(AuthenticationError::ClientMissing) - .and_then(|client| client.supports_password_login().map_err(AuthenticationError::from)) - } - - /// Updates the server to authenticate with the specified homeserver. - pub fn use_server(&self, server_name: String) -> Result<(), AuthenticationError> { + /// Updates the service to authenticate with the homeserver for the + /// specified address. + pub fn configure_homeserver( + &self, + server_name: String, + ) -> Result, AuthenticationError> { // Construct a username as the builder currently requires one. let username = format!("@auth:{}", server_name); let client = Arc::new(ClientBuilder::new()) @@ -67,8 +67,10 @@ impl AuthenticationService { .build() .map_err(AuthenticationError::from)?; + let details = self.details_from_client(&client)?; + *self.client.write() = Some(client); - Ok(()) + Ok(Arc::new(details)) } /// Performs a password login using the current homeserver. @@ -97,4 +99,19 @@ impl AuthenticationService { None => Err(AuthenticationError::ClientMissing), } } + + fn details_from_client( + &self, + client: &Arc, + ) -> Result { + let homeserver = client.homeserver(); + let authentication_issuer = client.authentication_issuer(); + let supports_password_login = + client.supports_password_login().map_err(AuthenticationError::from)?; + Ok(HomeserverLoginDetails { + url: homeserver, + authentication_issuer, + supports_password_login, + }) + } } From a174d0f6694bccd7d11adb2a1ab76f8d098ee414 Mon Sep 17 00:00:00 2001 From: Johannes Becker Date: Tue, 19 Jul 2022 12:46:48 +0200 Subject: [PATCH 55/73] sdk: Make `from` in `MessageOptions` optional --- crates/matrix-sdk/src/room/common.rs | 41 ++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/crates/matrix-sdk/src/room/common.rs b/crates/matrix-sdk/src/room/common.rs index 8be144f20..4eb66082a 100644 --- a/crates/matrix-sdk/src/room/common.rs +++ b/crates/matrix-sdk/src/room/common.rs @@ -176,7 +176,7 @@ impl Common { /// # let homeserver = Url::parse("http://example.com").unwrap(); /// # use futures::executor::block_on; /// # block_on(async { - /// let request = MessagesOptions::backward("t47429-4392820_219380_26003_2265"); + /// let request = MessagesOptions::backward_from("t47429-4392820_219380_26003_2265"); /// /// let mut client = Client::new(homeserver).await.unwrap(); /// let room = client @@ -461,7 +461,7 @@ impl Common { let filter = assign!(RoomEventFilter::default(), { lazy_load_options: LazyLoadOptions::Enabled { include_redundant_members: false }, }); - let options = assign!(MessagesOptions::backward(token), { + let options = assign!(MessagesOptions::backward_from(token), { limit: uint!(10), filter, }); @@ -1074,7 +1074,7 @@ impl Common { /// Options for [`messages`][Common::messages]. /// -/// See that method for details. +/// See that method and for details. #[derive(Debug)] #[non_exhaustive] pub struct MessagesOptions<'a> { @@ -1083,7 +1083,11 @@ pub struct MessagesOptions<'a> { /// This token can be obtained from a `prev_batch` token returned for each /// room from the sync API, or from a start or end token returned by a /// previous `messages` call. - pub from: &'a str, + /// + /// If `from` isn't provided the homeserver shall return a list of messages + /// from the first or last (per the value of the dir parameter) visible + /// event in the room history for the requesting user. + pub from: Option<&'a str>, /// The token to stop returning events at. /// @@ -1105,27 +1109,40 @@ pub struct MessagesOptions<'a> { } impl<'a> MessagesOptions<'a> { - /// Creates `MessagesOptions` with the given start token and direction. + /// Creates `MessagesOptions` with the given direction. /// /// All other parameters will be defaulted. - pub fn new(from: &'a str, dir: Direction) -> Self { - Self { from, to: None, dir, limit: uint!(10), filter: RoomEventFilter::default() } + pub fn new(dir: Direction) -> Self { + Self { from: None, to: None, dir, limit: uint!(10), filter: RoomEventFilter::default() } + } + + /// Creates `MessagesOptions` with the given optional start token, and `dir` + /// set to `Backward`. + pub fn backward(from: Option<&'a str>) -> Self { + assign!(Self::new(Direction::Backward), { from }) } /// Creates `MessagesOptions` with the given start token, and `dir` set to /// `Backward`. - pub fn backward(from: &'a str) -> Self { - Self::new(from, Direction::Backward) + pub fn backward_from(from: &'a str) -> Self { + Self::backward(Some(from)) + } + + /// Creates `MessagesOptions` with the given optional start token, and `dir` + /// set to `Forward`. + pub fn forward(from: Option<&'a str>) -> Self { + assign!(Self::new(Direction::Forward), { from }) } /// Creates `MessagesOptions` with the given start token, and `dir` set to /// `Forward`. - pub fn forward(from: &'a str) -> Self { - Self::new(from, Direction::Forward) + pub fn forward_from(from: &'a str) -> Self { + Self::forward(Some(from)) } fn into_request(self, room_id: &'a RoomId) -> get_message_events::v3::Request<'_> { - assign!(get_message_events::v3::Request::new(room_id, Some(self.from), self.dir), { + assign!(get_message_events::v3::Request::new(room_id, self.dir), { + from: self.from, to: self.to, limit: self.limit, filter: self.filter, From 93d879f356a26b52975a86214e9d49b3b60d6972 Mon Sep 17 00:00:00 2001 From: Doug Date: Tue, 19 Jul 2022 12:22:14 +0100 Subject: [PATCH 56/73] Add homeserver_details property. --- bindings/matrix-sdk-ffi/src/api.udl | 4 +++- .../src/authentication_service.rs | 23 +++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/bindings/matrix-sdk-ffi/src/api.udl b/bindings/matrix-sdk-ffi/src/api.udl index 5ccb81863..2c705695f 100644 --- a/bindings/matrix-sdk-ffi/src/api.udl +++ b/bindings/matrix-sdk-ffi/src/api.udl @@ -169,8 +169,10 @@ interface HomeserverLoginDetails { interface AuthenticationService { constructor(string base_path); + HomeserverLoginDetails? homeserver_details(); + [Throws=AuthenticationError] - HomeserverLoginDetails configure_homeserver(string server_name); + void configure_homeserver(string server_name); [Throws=AuthenticationError] Client login(string username, string password); diff --git a/bindings/matrix-sdk-ffi/src/authentication_service.rs b/bindings/matrix-sdk-ffi/src/authentication_service.rs index da52f9fc1..afda831d3 100644 --- a/bindings/matrix-sdk-ffi/src/authentication_service.rs +++ b/bindings/matrix-sdk-ffi/src/authentication_service.rs @@ -7,6 +7,7 @@ use super::{client::Client, client_builder::ClientBuilder}; pub struct AuthenticationService { base_path: String, client: RwLock>>, + homeserver_details: RwLock>>, } #[derive(Debug, thiserror::Error)] @@ -50,15 +51,20 @@ impl HomeserverLoginDetails { impl AuthenticationService { /// Creates a new service to authenticate a user with. pub fn new(base_path: String) -> Self { - AuthenticationService { base_path, client: RwLock::new(None) } + AuthenticationService { + base_path, + client: RwLock::new(None), + homeserver_details: RwLock::new(None), + } + } + + pub fn homeserver_details(&self) -> Option> { + self.homeserver_details.read().clone() } /// Updates the service to authenticate with the homeserver for the /// specified address. - pub fn configure_homeserver( - &self, - server_name: String, - ) -> Result, AuthenticationError> { + pub fn configure_homeserver(&self, server_name: String) -> Result<(), AuthenticationError> { // Construct a username as the builder currently requires one. let username = format!("@auth:{}", server_name); let client = Arc::new(ClientBuilder::new()) @@ -67,10 +73,12 @@ impl AuthenticationService { .build() .map_err(AuthenticationError::from)?; - let details = self.details_from_client(&client)?; + let details = Arc::new(self.details_from_client(&client)?); *self.client.write() = Some(client); - Ok(Arc::new(details)) + *self.homeserver_details.write() = Some(details); + + Ok(()) } /// Performs a password login using the current homeserver. @@ -100,6 +108,7 @@ impl AuthenticationService { } } + /// Get the homeserver login details from a client. fn details_from_client( &self, client: &Arc, From 0360b13cdb0a943fc387a8616e9c8b69f3a057dd Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 19 Jul 2022 16:12:43 +0200 Subject: [PATCH 57/73] fix(bindings/crypto-nodejs): Rrrrr --- .github/workflows/prep-crypto-nodejs-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prep-crypto-nodejs-release.yml b/.github/workflows/prep-crypto-nodejs-release.yml index d1865fdf6..1319ca251 100644 --- a/.github/workflows/prep-crypto-nodejs-release.yml +++ b/.github/workflows/prep-crypto-nodejs-release.yml @@ -74,7 +74,7 @@ jobs: default_author: github_actions message: "Tagging Crypto-Node.js for release" tag: "${{env.TAG_PREFIX}}${{ inputs.version }}" - new_banch: "gh-action/release-${{ env.TAG_PREFIX }}${{ inputs.version }}" + new_branch: "gh-action/release-${{ env.TAG_PREFIX }}${{ inputs.version }}" push: true add: | ${{ env.PKG_PATH }}/package.json From 77f7dbbbc805e69c13e64dab1e93e01bbb12c7cb Mon Sep 17 00:00:00 2001 From: Doug Date: Tue, 19 Jul 2022 16:16:03 +0100 Subject: [PATCH 58/73] Support server URLs. Join homeserver details futures. --- .../src/authentication_service.rs | 50 +++++++++++-------- bindings/matrix-sdk-ffi/src/client.rs | 27 +++++----- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/bindings/matrix-sdk-ffi/src/authentication_service.rs b/bindings/matrix-sdk-ffi/src/authentication_service.rs index afda831d3..0c3df8f12 100644 --- a/bindings/matrix-sdk-ffi/src/authentication_service.rs +++ b/bindings/matrix-sdk-ffi/src/authentication_service.rs @@ -1,8 +1,9 @@ use std::sync::Arc; +use futures_util::future::join3; use parking_lot::RwLock; -use super::{client::Client, client_builder::ClientBuilder}; +use super::{client::Client, client_builder::ClientBuilder, RUNTIME}; pub struct AuthenticationService { base_path: String, @@ -67,18 +68,24 @@ impl AuthenticationService { pub fn configure_homeserver(&self, server_name: String) -> Result<(), AuthenticationError> { // Construct a username as the builder currently requires one. let username = format!("@auth:{}", server_name); - let client = Arc::new(ClientBuilder::new()) - .base_path(self.base_path.clone()) - .username(username) - .build() - .map_err(AuthenticationError::from)?; - let details = Arc::new(self.details_from_client(&client)?); + let mut builder = + Arc::new(ClientBuilder::new()).base_path(self.base_path.clone()).username(username); - *self.client.write() = Some(client); - *self.homeserver_details.write() = Some(details); + if server_name.starts_with("http://") || server_name.starts_with("https://") { + builder = builder.homeserver_url(server_name) + } - Ok(()) + let client = builder.build().map_err(AuthenticationError::from)?; + + RUNTIME.block_on(async move { + let details = Arc::new(self.details_from_client(&client).await?); + + *self.client.write() = Some(client); + *self.homeserver_details.write() = Some(details); + + Ok(()) + }) } /// Performs a password login using the current homeserver. @@ -109,18 +116,21 @@ impl AuthenticationService { } /// Get the homeserver login details from a client. - fn details_from_client( + async fn details_from_client( &self, client: &Arc, ) -> Result { - let homeserver = client.homeserver(); - let authentication_issuer = client.authentication_issuer(); - let supports_password_login = - client.supports_password_login().map_err(AuthenticationError::from)?; - Ok(HomeserverLoginDetails { - url: homeserver, - authentication_issuer, - supports_password_login, - }) + let login_details = join3( + client.async_homeserver(), + client.authentication_issuer(), + client.supports_password_login(), + ) + .await; + + let url = login_details.0; + let authentication_issuer = login_details.1; + let supports_password_login = login_details.2.map_err(AuthenticationError::from)?; + + Ok(HomeserverLoginDetails { url, authentication_issuer, supports_password_login }) } } diff --git a/bindings/matrix-sdk-ffi/src/client.rs b/bindings/matrix-sdk-ffi/src/client.rs index 0dda08d72..35538cb84 100644 --- a/bindings/matrix-sdk-ffi/src/client.rs +++ b/bindings/matrix-sdk-ffi/src/client.rs @@ -74,26 +74,27 @@ impl Client { /// The homeserver this client is configured to use. pub fn homeserver(&self) -> String { - RUNTIME.block_on(async move { self.client.homeserver().await.to_string() }) + RUNTIME.block_on(async move { self.async_homeserver().await }) + } + + pub async fn async_homeserver(&self) -> String { + self.client.homeserver().await.to_string() } /// The OIDC Provider that is trusted by the homeserver. `None` when /// not configured. - pub fn authentication_issuer(&self) -> Option { - RUNTIME.block_on(async move { - self.client.authentication_issuer().await.map(|server| server.to_string()) - }) + pub async fn authentication_issuer(&self) -> Option { + self.client.authentication_issuer().await.map(|server| server.to_string()) } /// Whether or not the client's homeserver supports the password login flow. - pub fn supports_password_login(&self) -> anyhow::Result { - RUNTIME.block_on(async move { - let login_types = self.client.get_login_types().await?; - let supports_password = login_types.flows.iter().any(|login_type| { - matches!(login_type, get_login_types::v3::LoginType::Password(_)) - }); - Ok(supports_password) - }) + pub async fn supports_password_login(&self) -> anyhow::Result { + let login_types = self.client.get_login_types().await?; + let supports_password = login_types + .flows + .iter() + .any(|login_type| matches!(login_type, get_login_types::v3::LoginType::Password(_))); + Ok(supports_password) } pub fn start_sync(&self) { From 1cd18f49aa91a271310fbb55c1e08d641d4ba637 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 20 Jul 2022 12:29:36 +0300 Subject: [PATCH 59/73] chore(bindings/apple): Remove now unnecessary debug script module import following module map rename --- bindings/apple/debug_build_xcframework.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/bindings/apple/debug_build_xcframework.sh b/bindings/apple/debug_build_xcframework.sh index 60625dd03..a34673059 100755 --- a/bindings/apple/debug_build_xcframework.sh +++ b/bindings/apple/debug_build_xcframework.sh @@ -84,8 +84,6 @@ 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 From f9bb86c52f62e9eadf0ddaecb4a029fff068300e Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 20 Jul 2022 12:56:42 +0300 Subject: [PATCH 60/73] feat(bindings/sdk-ffi): Allow ffi users to configure tracing and log levels --- bindings/matrix-sdk-ffi/Cargo.toml | 1 + bindings/matrix-sdk-ffi/src/api.udl | 10 ++++++++++ bindings/matrix-sdk-ffi/src/lib.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/bindings/matrix-sdk-ffi/Cargo.toml b/bindings/matrix-sdk-ffi/Cargo.toml index bc2f81bb1..04824f389 100644 --- a/bindings/matrix-sdk-ffi/Cargo.toml +++ b/bindings/matrix-sdk-ffi/Cargo.toml @@ -31,6 +31,7 @@ thiserror = "1.0.30" tokio = { version = "1", features = ["rt-multi-thread", "macros"] } tokio-stream = "0.1.8" tracing = "0.1.32" +tracing-subscriber = { version = "0.3", features = [ "env-filter" ]} # keep in sync with uniffi dependency in matrix-sdk-crypto-ffi, and uniffi_bindgen in ffi CI job uniffi = "0.18.0" uniffi_macros = "0.18.0" diff --git a/bindings/matrix-sdk-ffi/src/api.udl b/bindings/matrix-sdk-ffi/src/api.udl index 2c705695f..1db732a0f 100644 --- a/bindings/matrix-sdk-ffi/src/api.udl +++ b/bindings/matrix-sdk-ffi/src/api.udl @@ -1,9 +1,19 @@ namespace sdk { + void setup_tracing(LogLevel log_level); + MediaSource media_source_from_url(string url); MessageEventContent message_event_content_from_markdown(string md); string gen_transaction_id(); }; +enum LogLevel { + "Trace", + "Debug", + "Info", + "Warn", + "Error", +}; + [Error] interface ClientError { Generic(string msg); diff --git a/bindings/matrix-sdk-ffi/src/lib.rs b/bindings/matrix-sdk-ffi/src/lib.rs index 7fb23d268..f47405d7e 100644 --- a/bindings/matrix-sdk-ffi/src/lib.rs +++ b/bindings/matrix-sdk-ffi/src/lib.rs @@ -17,6 +17,7 @@ use matrix_sdk::Session; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; use tokio::runtime::Runtime; +use tracing_subscriber::{fmt, prelude::*, EnvFilter}; pub use uniffi_api::*; pub static RUNTIME: Lazy = @@ -55,3 +56,30 @@ impl From for ClientError { ClientError::Generic { msg: e.to_string() } } } + +pub enum LogLevel { + Trace, + Debug, + Info, + Warn, + Error, +} + +impl LogLevel { + fn as_str(&self) -> &'static str { + match self { + LogLevel::Trace => "trace", + LogLevel::Debug => "debug", + LogLevel::Info => "info", + LogLevel::Warn => "warn", + LogLevel::Error => "error", + } + } +} + +fn setup_tracing(log_level: LogLevel) { + tracing_subscriber::registry() + .with(EnvFilter::new(log_level.as_str())) + .with(fmt::layer().with_ansi(false)) + .init(); +} From 0043de4028744e97850960d391322952fa410ae6 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 20 Jul 2022 13:28:58 +0300 Subject: [PATCH 61/73] Update bindings/matrix-sdk-ffi/Cargo.toml Co-authored-by: Jonas Platte --- bindings/matrix-sdk-ffi/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/matrix-sdk-ffi/Cargo.toml b/bindings/matrix-sdk-ffi/Cargo.toml index 04824f389..a686272a9 100644 --- a/bindings/matrix-sdk-ffi/Cargo.toml +++ b/bindings/matrix-sdk-ffi/Cargo.toml @@ -31,7 +31,7 @@ thiserror = "1.0.30" tokio = { version = "1", features = ["rt-multi-thread", "macros"] } tokio-stream = "0.1.8" tracing = "0.1.32" -tracing-subscriber = { version = "0.3", features = [ "env-filter" ]} +tracing-subscriber = { version = "0.3", features = ["env-filter"] } # keep in sync with uniffi dependency in matrix-sdk-crypto-ffi, and uniffi_bindgen in ffi CI job uniffi = "0.18.0" uniffi_macros = "0.18.0" From 021bf5507400b97819acd518bdf2981075edd941 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 20 Jul 2022 13:39:15 +0300 Subject: [PATCH 62/73] feat(bindings/sdk-ffi): Expose full tracing configuration string through ffi. --- bindings/matrix-sdk-ffi/src/api.udl | 10 +--------- bindings/matrix-sdk-ffi/src/lib.rs | 24 ++---------------------- 2 files changed, 3 insertions(+), 31 deletions(-) diff --git a/bindings/matrix-sdk-ffi/src/api.udl b/bindings/matrix-sdk-ffi/src/api.udl index 1db732a0f..76d2ada9f 100644 --- a/bindings/matrix-sdk-ffi/src/api.udl +++ b/bindings/matrix-sdk-ffi/src/api.udl @@ -1,19 +1,11 @@ namespace sdk { - void setup_tracing(LogLevel log_level); + void setup_tracing(string configuration); MediaSource media_source_from_url(string url); MessageEventContent message_event_content_from_markdown(string md); string gen_transaction_id(); }; -enum LogLevel { - "Trace", - "Debug", - "Info", - "Warn", - "Error", -}; - [Error] interface ClientError { Generic(string msg); diff --git a/bindings/matrix-sdk-ffi/src/lib.rs b/bindings/matrix-sdk-ffi/src/lib.rs index f47405d7e..db2461303 100644 --- a/bindings/matrix-sdk-ffi/src/lib.rs +++ b/bindings/matrix-sdk-ffi/src/lib.rs @@ -57,29 +57,9 @@ impl From for ClientError { } } -pub enum LogLevel { - Trace, - Debug, - Info, - Warn, - Error, -} - -impl LogLevel { - fn as_str(&self) -> &'static str { - match self { - LogLevel::Trace => "trace", - LogLevel::Debug => "debug", - LogLevel::Info => "info", - LogLevel::Warn => "warn", - LogLevel::Error => "error", - } - } -} - -fn setup_tracing(log_level: LogLevel) { +fn setup_tracing(configuration: String) { tracing_subscriber::registry() - .with(EnvFilter::new(log_level.as_str())) + .with(EnvFilter::new(configuration)) .with(fmt::layer().with_ansi(false)) .init(); } From 5c53a5f6990a9364cb085919ec872d4ff50c2ac5 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 20 Jul 2022 14:53:00 +0300 Subject: [PATCH 63/73] chore(bindings/apple): Remove unnecessary +nightly flag from debug builds --- bindings/apple/debug_build_xcframework.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/apple/debug_build_xcframework.sh b/bindings/apple/debug_build_xcframework.sh index a34673059..ace17ec24 100755 --- a/bindings/apple/debug_build_xcframework.sh +++ b/bindings/apple/debug_build_xcframework.sh @@ -34,7 +34,7 @@ REL_TYPE_DIR="debug" # iOS Simulator arm64 if [ "$ACTIVE_ARCH" = "arm64" ]; then - cargo +nightly build -p matrix-sdk-ffi ${REL_FLAG} --target "aarch64-apple-ios-sim" + cargo build -p matrix-sdk-ffi ${REL_FLAG} --target "aarch64-apple-ios-sim" lipo -create \ "${TARGET_DIR}/aarch64-apple-ios-sim/${REL_TYPE_DIR}/libmatrix_sdk_ffi.a" \ @@ -42,7 +42,7 @@ if [ "$ACTIVE_ARCH" = "arm64" ]; then # iOS Simulator intel else - cargo +nightly build -p matrix-sdk-ffi ${REL_FLAG} --target "x86_64-apple-ios" + cargo 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" \ From a6bd7fc82f35dcdf4fa6a37c155c6be42836a5c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Wed, 20 Jul 2022 14:18:06 +0200 Subject: [PATCH 64/73] chore: Update Ruma --- benchmarks/Cargo.toml | 2 +- bindings/matrix-sdk-crypto-ffi/Cargo.toml | 2 +- bindings/matrix-sdk-crypto-js/Cargo.toml | 2 +- bindings/matrix-sdk-crypto-nodejs/Cargo.toml | 2 +- crates/matrix-sdk-appservice/Cargo.toml | 2 +- crates/matrix-sdk-base/Cargo.toml | 4 ++-- crates/matrix-sdk-common/Cargo.toml | 2 +- crates/matrix-sdk-crypto/Cargo.toml | 4 ++-- crates/matrix-sdk-indexeddb/Cargo.toml | 2 +- crates/matrix-sdk-qrcode/Cargo.toml | 2 +- crates/matrix-sdk-sled/Cargo.toml | 2 +- crates/matrix-sdk-test/Cargo.toml | 2 +- crates/matrix-sdk/Cargo.toml | 9 ++------- crates/matrix-sdk/src/room/joined.rs | 3 +-- labs/sled-state-inspector/Cargo.toml | 2 +- 15 files changed, 18 insertions(+), 24 deletions(-) diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml index f74e3e092..f9325a724 100644 --- a/benchmarks/Cargo.toml +++ b/benchmarks/Cargo.toml @@ -12,7 +12,7 @@ criterion = { version = "0.3.5", features = ["async", "async_tokio", "html_repor 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 = "da5def6731efd698c63fd2ffdef5f3e1836bff94" } +ruma = { git = "https://github.com/ruma/ruma", rev = "ca8c66c885241a7ba3805399604eda4a38979f6b" } serde_json = "1.0.79" tempfile = "3.3.0" tokio = { version = "1.17.0", default-features = false, features = ["rt-multi-thread"] } diff --git a/bindings/matrix-sdk-crypto-ffi/Cargo.toml b/bindings/matrix-sdk-crypto-ffi/Cargo.toml index bb7fc696f..3b200e82a 100644 --- a/bindings/matrix-sdk-crypto-ffi/Cargo.toml +++ b/bindings/matrix-sdk-crypto-ffi/Cargo.toml @@ -20,7 +20,7 @@ hmac = "0.12.1" http = "0.2.6" pbkdf2 = "0.11.0" rand = "0.8.5" -ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "ca8c66c885241a7ba3805399604eda4a38979f6b", features = ["client-api-c"] } serde = "1.0.136" serde_json = "1.0.79" sha2 = "0.10.2" diff --git a/bindings/matrix-sdk-crypto-js/Cargo.toml b/bindings/matrix-sdk-crypto-js/Cargo.toml index 1c8542856..2b91685a9 100644 --- a/bindings/matrix-sdk-crypto-js/Cargo.toml +++ b/bindings/matrix-sdk-crypto-js/Cargo.toml @@ -30,7 +30,7 @@ tracing = [] [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 = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c", "js", "rand", "unstable-msc2676", "unstable-msc2677"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "ca8c66c885241a7ba3805399604eda4a38979f6b", 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" diff --git a/bindings/matrix-sdk-crypto-nodejs/Cargo.toml b/bindings/matrix-sdk-crypto-nodejs/Cargo.toml index cf11d92a8..82a51626a 100644 --- a/bindings/matrix-sdk-crypto-nodejs/Cargo.toml +++ b/bindings/matrix-sdk-crypto-nodejs/Cargo.toml @@ -28,7 +28,7 @@ tracing = ["dep:tracing-subscriber"] 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 = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c", "rand", "unstable-msc2676", "unstable-msc2677"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "ca8c66c885241a7ba3805399604eda4a38979f6b", 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" } diff --git a/crates/matrix-sdk-appservice/Cargo.toml b/crates/matrix-sdk-appservice/Cargo.toml index 2e83abe34..258591231 100644 --- a/crates/matrix-sdk-appservice/Cargo.toml +++ b/crates/matrix-sdk-appservice/Cargo.toml @@ -34,7 +34,7 @@ http = "0.2.6" matrix-sdk = { version = "0.5.0", path = "../matrix-sdk", default-features = false, features = ["appservice"] } percent-encoding = "2.1.0" regex = "1.5.5" -ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c", "appservice-api-s"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "ca8c66c885241a7ba3805399604eda4a38979f6b", features = ["client-api-c", "appservice-api-s"] } serde = "1.0.136" serde_json = "1.0.79" serde_yaml = "0.8.23" diff --git a/crates/matrix-sdk-base/Cargo.toml b/crates/matrix-sdk-base/Cargo.toml index 4ce3c1aba..f4a3257ed 100644 --- a/crates/matrix-sdk-base/Cargo.toml +++ b/crates/matrix-sdk-base/Cargo.toml @@ -43,10 +43,10 @@ tracing = "0.1.34" zeroize = { version = "1.3.0", features = ["zeroize_derive"] } [target.'cfg(target_arch = "wasm32")'.dependencies] -ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c", "js", "canonical-json"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "ca8c66c885241a7ba3805399604eda4a38979f6b", features = ["client-api-c", "js", "canonical-json"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c", "canonical-json"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "ca8c66c885241a7ba3805399604eda4a38979f6b", features = ["client-api-c", "canonical-json"] } [dev-dependencies] futures = { version = "0.3.21", default-features = false, features = ["executor"] } diff --git a/crates/matrix-sdk-common/Cargo.toml b/crates/matrix-sdk-common/Cargo.toml index 25df7cf46..8c8d49de0 100644 --- a/crates/matrix-sdk-common/Cargo.toml +++ b/crates/matrix-sdk-common/Cargo.toml @@ -16,7 +16,7 @@ default-target = "x86_64-unknown-linux-gnu" targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"] [dependencies] -ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "ca8c66c885241a7ba3805399604eda4a38979f6b", features = ["client-api-c"] } serde = "1.0.136" [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/crates/matrix-sdk-crypto/Cargo.toml b/crates/matrix-sdk-crypto/Cargo.toml index 7bcaad51a..1721ca54d 100644 --- a/crates/matrix-sdk-crypto/Cargo.toml +++ b/crates/matrix-sdk-crypto/Cargo.toml @@ -51,11 +51,11 @@ zeroize = { version = "1.3.0", features = ["zeroize_derive"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] tokio = { version = "1.18", default-features = false, features = ["time"] } -ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c", "rand", "canonical-json", "unstable-msc2676", "unstable-msc2677"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "ca8c66c885241a7ba3805399604eda4a38979f6b", features = ["client-api-c", "rand", "canonical-json", "unstable-msc2676", "unstable-msc2677"] } vodozemac = { git = "https://github.com/matrix-org/vodozemac/", rev = "2404f83f7d3a3779c1f518e4d949f7da9677c3dd" } [target.'cfg(target_arch = "wasm32")'.dependencies] -ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c", "js", "rand", "canonical-json", "unstable-msc2676", "unstable-msc2677"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "ca8c66c885241a7ba3805399604eda4a38979f6b", features = ["client-api-c", "js", "rand", "canonical-json", "unstable-msc2676", "unstable-msc2677"] } vodozemac = { git = "https://github.com/matrix-org/vodozemac/", rev = "2404f83f7d3a3779c1f518e4d949f7da9677c3dd", features = ["js"] } [dev-dependencies] diff --git a/crates/matrix-sdk-indexeddb/Cargo.toml b/crates/matrix-sdk-indexeddb/Cargo.toml index bb7dd577c..2d3bfe45b 100644 --- a/crates/matrix-sdk-indexeddb/Cargo.toml +++ b/crates/matrix-sdk-indexeddb/Cargo.toml @@ -29,7 +29,7 @@ indexed_db_futures = "0.2.3" matrix-sdk-base = { version = "0.5.0", path = "../matrix-sdk-base" } matrix-sdk-crypto = { version = "0.5.0", path = "../matrix-sdk-crypto", optional = true } matrix-sdk-store-encryption = { version = "0.1.0", path = "../matrix-sdk-store-encryption" } -ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94" } +ruma = { git = "https://github.com/ruma/ruma", rev = "ca8c66c885241a7ba3805399604eda4a38979f6b" } serde = "1.0.136" serde_json = "1.0.79" thiserror = "1.0.30" diff --git a/crates/matrix-sdk-qrcode/Cargo.toml b/crates/matrix-sdk-qrcode/Cargo.toml index 5eebd52f7..4a05c2e75 100644 --- a/crates/matrix-sdk-qrcode/Cargo.toml +++ b/crates/matrix-sdk-qrcode/Cargo.toml @@ -25,7 +25,7 @@ byteorder = "1.4.3" image = { version = "0.23.0", optional = true } qrcode = { version = "0.12.0", default-features = false } rqrr = { version = "0.4.0", optional = true } -ruma-common = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94" } +ruma-common = { git = "https://github.com/ruma/ruma", rev = "ca8c66c885241a7ba3805399604eda4a38979f6b" } thiserror = "1.0.30" [dependencies.vodozemac] diff --git a/crates/matrix-sdk-sled/Cargo.toml b/crates/matrix-sdk-sled/Cargo.toml index b599f0c78..f5cebd4be 100644 --- a/crates/matrix-sdk-sled/Cargo.toml +++ b/crates/matrix-sdk-sled/Cargo.toml @@ -37,7 +37,7 @@ matrix-sdk-base = { version = "0.5.0", path = "../matrix-sdk-base", optional = t matrix-sdk-common = { version = "0.5.0", path = "../matrix-sdk-common" } matrix-sdk-crypto = { version = "0.5.0", path = "../matrix-sdk-crypto", optional = true } matrix-sdk-store-encryption = { version = "0.1.0", path = "../matrix-sdk-store-encryption" } -ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94" } +ruma = { git = "https://github.com/ruma/ruma", rev = "ca8c66c885241a7ba3805399604eda4a38979f6b" } serde = "1.0.136" serde_json = "1.0.79" sled = "0.34.7" diff --git a/crates/matrix-sdk-test/Cargo.toml b/crates/matrix-sdk-test/Cargo.toml index 0aa086062..d87a513b8 100644 --- a/crates/matrix-sdk-test/Cargo.toml +++ b/crates/matrix-sdk-test/Cargo.toml @@ -18,6 +18,6 @@ appservice = [] http = "0.2.6" matrix-sdk-test-macros = { version = "0.2.0", path = "../matrix-sdk-test-macros" } once_cell = "1.10.0" -ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94", features = ["client-api-c"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "ca8c66c885241a7ba3805399604eda4a38979f6b", features = ["client-api-c"] } serde = "1.0.136" serde_json = "1.0.79" diff --git a/crates/matrix-sdk/Cargo.toml b/crates/matrix-sdk/Cargo.toml index 83ff36d96..1b511b14b 100644 --- a/crates/matrix-sdk/Cargo.toml +++ b/crates/matrix-sdk/Cargo.toml @@ -110,13 +110,8 @@ default_features = false [dependencies.ruma] git = "https://github.com/ruma/ruma" -rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94" -features = ["client-api-c", "compat", "rand", "unstable-msc2448"] - -[dependencies.ruma-client-api] -git = "https://github.com/ruma/ruma" -rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94" -features = ["unstable-msc2965"] +rev = "ca8c66c885241a7ba3805399604eda4a38979f6b" +features = ["client-api-c", "compat", "rand", "unstable-msc2448", "unstable-msc2965"] [dependencies.tokio-stream] version = "0.1.8" diff --git a/crates/matrix-sdk/src/room/joined.rs b/crates/matrix-sdk/src/room/joined.rs index 184df9489..5ffad481e 100644 --- a/crates/matrix-sdk/src/room/joined.rs +++ b/crates/matrix-sdk/src/room/joined.rs @@ -20,7 +20,7 @@ use ruma::{ }, message::send_message_event, read_marker::set_read_marker, - receipt::create_receipt, + receipt::create_receipt::{self, v3::ReceiptType}, redact::redact_event, state::send_state_event, typing::create_typing_event::v3::{Request as TypingRequest, Typing}, @@ -30,7 +30,6 @@ use ruma::{ serde::Raw, EventId, OwnedTransactionId, TransactionId, UserId, }; -use ruma_client_api::receipt::create_receipt::v3::ReceiptType; use serde_json::Value; use tracing::debug; #[cfg(feature = "e2e-encryption")] diff --git a/labs/sled-state-inspector/Cargo.toml b/labs/sled-state-inspector/Cargo.toml index 69b330f8b..60a0366c7 100644 --- a/labs/sled-state-inspector/Cargo.toml +++ b/labs/sled-state-inspector/Cargo.toml @@ -10,7 +10,7 @@ clap = "3.2.4" futures = { version = "0.3.21", default-features = false, features = ["executor"] } matrix-sdk-base = { path = "../../crates/matrix-sdk-base", version = "0.5.0" } matrix-sdk-sled = { path = "../../crates/matrix-sdk-sled", version = "0.1.0" } -ruma = { git = "https://github.com/ruma/ruma", rev = "da5def6731efd698c63fd2ffdef5f3e1836bff94" } +ruma = { git = "https://github.com/ruma/ruma", rev = "ca8c66c885241a7ba3805399604eda4a38979f6b" } rustyline = "9.1.2" rustyline-derive = "0.6.0" serde = "1.0.136" From 5f7e91c2e7944d2524af0e46b32ca3be8be2cbe0 Mon Sep 17 00:00:00 2001 From: Johannes Becker Date: Wed, 20 Jul 2022 10:30:58 +0200 Subject: [PATCH 65/73] refactor(appservice)!: Cleanup --- crates/matrix-sdk-appservice/src/error.rs | 26 +- crates/matrix-sdk-appservice/src/lib.rs | 572 ++++++++++++++++-- crates/matrix-sdk-appservice/src/webserver.rs | 9 +- crates/matrix-sdk-appservice/tests/tests.rs | 513 ---------------- 4 files changed, 528 insertions(+), 592 deletions(-) delete mode 100644 crates/matrix-sdk-appservice/tests/tests.rs diff --git a/crates/matrix-sdk-appservice/src/error.rs b/crates/matrix-sdk-appservice/src/error.rs index de3d15ed2..68a863ed5 100644 --- a/crates/matrix-sdk-appservice/src/error.rs +++ b/crates/matrix-sdk-appservice/src/error.rs @@ -41,41 +41,41 @@ pub enum Error { #[error("uri path is unknown")] UriPathUnknown, - #[error(transparent)] - HttpRequest(#[from] ruma::api::error::FromHttpRequestError), + #[error("HTTP request parsing error: {0}")] + FromHttpRequest(#[from] ruma::api::error::FromHttpRequestError), - #[error(transparent)] + #[error("identifier failed to parse: {0}")] Identifier(#[from] ruma::IdParseError), - #[error(transparent)] + #[error("HTTP error: {0}")] Http(#[from] http::Error), - #[error(transparent)] + #[error("url parse error: {0}")] Url(#[from] url::ParseError), - #[error(transparent)] + #[error("deserialization error: {0}")] Serde(#[from] serde::de::value::Error), - #[error(transparent)] + #[error("I/O error: {0}")] Io(#[from] std::io::Error), - #[error(transparent)] + #[error("http uri invalid error: {0}")] InvalidUri(#[from] http::uri::InvalidUri), #[error(transparent)] Matrix(#[from] matrix_sdk::Error), - #[error(transparent)] + #[error("regex error: {0}")] Regex(#[from] regex::Error), - #[error(transparent)] + #[error("serde yaml error: {0}")] SerdeYaml(#[from] serde_yaml::Error), - #[error(transparent)] + #[error("serde json error: {0}")] SerdeJson(#[from] serde_json::Error), - #[error(transparent)] - Utf8Error(#[from] std::str::Utf8Error), + #[error("utf8 error: {0}")] + Utf8(#[from] std::str::Utf8Error), #[error("warp rejection: {0}")] WarpRejection(String), diff --git a/crates/matrix-sdk-appservice/src/lib.rs b/crates/matrix-sdk-appservice/src/lib.rs index 10b612c2c..7fb2519c8 100644 --- a/crates/matrix-sdk-appservice/src/lib.rs +++ b/crates/matrix-sdk-appservice/src/lib.rs @@ -37,9 +37,6 @@ //! for the access tokens and because membership states for virtual users are //! determined based on the registered namespaces. //! -//! **Note:** Non-exclusive registration namespaces are not yet supported and -//! hence might lead to undefined behavior. -//! //! # Quickstart //! //! ```no_run @@ -95,7 +92,7 @@ use event_handler::AppserviceFn; pub use matrix_sdk; #[doc(no_inline)] pub use matrix_sdk::ruma; -use matrix_sdk::{bytes::Bytes, reqwest::Url, Client, ClientBuilder}; +use matrix_sdk::{reqwest::Url, Client, ClientBuilder}; use ruma::{ api::{ appservice::{ @@ -392,7 +389,7 @@ impl AppService { /// active virtual clients. /// /// [transaction]: https://spec.matrix.org/v1.2/application-service-api/#put_matrixappv1transactionstxnid - pub async fn receive_transaction( + async fn receive_transaction( &self, transaction: push_events::v1::IncomingRequest, ) -> Result<()> { @@ -515,66 +512,517 @@ impl AppService { } } -/// Ruma always expects the path to start with `/_matrix`, so we transform -/// accordingly. Handles [legacy routes] and appservice being located on a sub -/// path. -/// -/// [legacy routes]: https://matrix.org/docs/spec/application_service/r0.1.2#legacy-routes -// TODO: consider ruma PR -pub(crate) fn transform_request_path( - mut request: http::Request, -) -> Result> { - let uri = request.uri(); - // remove trailing slash from path - let path = uri.path().trim_end_matches('/').to_owned(); +#[cfg(test)] +mod tests { + use std::{ + future, + sync::{Arc, Mutex}, + }; - if !path.starts_with("/_matrix/app/v1/") { - let path = match path { - // special-case paths without value at the end - _ if path.ends_with("/_matrix/app/unstable/thirdparty/user") => { - "/_matrix/app/v1/thirdparty/user".to_owned() - } - _ if path.ends_with("/_matrix/app/unstable/thirdparty/location") => { - "/_matrix/app/v1/thirdparty/location".to_owned() - } - // regular paths with values at the end - _ => { - let mut path = path.split('/').into_iter().rev(); - let value = match path.next() { - Some(value) => value, - None => return Err(Error::UriEmptyPath), - }; + use matrix_sdk::{ + config::RequestConfig, + ruma::{api::appservice::Registration, events::room::member::OriginalSyncRoomMemberEvent}, + Client, + }; + use matrix_sdk_test::{appservice::TransactionBuilder, async_test, TimelineTestEvent}; + use ruma::{ + api::{appservice::event::push_events, MatrixVersion}, + events::AnyRoomEvent, + room_id, + serde::Raw, + }; + use serde_json::json; + use warp::{Filter, Reply}; + use wiremock::{ + matchers::{body_json, header, method, path}, + Mock, MockServer, ResponseTemplate, + }; - let mut path = match path.next() { - Some(path_segment) - if ["transactions", "users", "rooms"].contains(&path_segment) => - { - format!("/_matrix/app/v1/{}/{}", path_segment, value) - } - Some(path_segment) => match path.next() { - Some(path_segment2) if path_segment2 == "thirdparty" => { - format!("/_matrix/app/v1/thirdparty/{}/{}", path_segment, value) - } - _ => return Err(Error::UriPathUnknown), - }, - None => return Err(Error::UriEmptyPath), - }; + use super::*; - if let Some(query) = uri.query() { - path.push('?'); - path.push_str(query); - } - - path - } - }; - - let mut parts = uri.clone().into_parts(); - parts.path_and_query = Some(path.parse()?); - - let uri = parts.try_into().map_err(http::Error::from)?; - *request.uri_mut() = uri; + fn registration_string() -> String { + include_str!("../tests/registration.yaml").to_owned() } - Ok(request) + async fn appservice( + homeserver_url: Option, + registration: Option, + ) -> Result { + let _ = tracing_subscriber::fmt::try_init(); + + let registration = match registration { + Some(registration) => registration.into(), + None => AppServiceRegistration::try_from_yaml_str(registration_string()).unwrap(), + }; + + let homeserver_url = homeserver_url.unwrap_or_else(|| "http://localhost:1234".to_owned()); + let server_name = "localhost"; + + let client_builder = Client::builder() + .request_config(RequestConfig::default().disable_retry()) + .server_versions([MatrixVersion::V1_0]); + + AppService::with_client_builder( + homeserver_url.as_ref(), + server_name, + registration, + client_builder, + ) + .await + } + + #[async_test] + async fn test_register_virtual_user() -> Result<()> { + let server = MockServer::start().await; + let appservice = appservice(Some(server.uri()), None).await?; + + let localpart = "someone"; + Mock::given(method("POST")) + .and(path("/_matrix/client/r0/register")) + .and(header( + "authorization", + format!("Bearer {}", appservice.registration().as_token).as_str(), + )) + .and(body_json(json!({ + "username": localpart.to_owned(), + "type": "m.login.application_service" + }))) + .respond_with(ResponseTemplate::new(200).set_body_json(json!({ + "access_token": "abc123", + "device_id": "GHTYAJCE", + "user_id": format!("@{localpart}:localhost"), + }))) + .mount(&server) + .await; + + appservice.register_virtual_user(localpart, None).await?; + + Ok(()) + } + + #[async_test] + async fn test_put_transaction() -> Result<()> { + let uri = "/_matrix/app/v1/transactions/1?access_token=hs_token"; + + let mut transaction_builder = TransactionBuilder::new(); + transaction_builder.add_room_event(TimelineTestEvent::Member); + let transaction = transaction_builder.build_json_transaction(); + + let appservice = appservice(None, None).await?; + + let status = warp::test::request() + .method("PUT") + .path(uri) + .json(&transaction) + .filter(&appservice.warp_filter()) + .await + .unwrap() + .into_response() + .status(); + + assert_eq!(status, 200); + + Ok(()) + } + + #[async_test] + async fn test_put_transaction_with_repeating_txn_id() -> Result<()> { + let uri = "/_matrix/app/v1/transactions/1?access_token=hs_token"; + + let mut transaction_builder = TransactionBuilder::new(); + transaction_builder.add_room_event(TimelineTestEvent::Member); + let transaction = transaction_builder.build_json_transaction(); + + let appservice = appservice(None, None).await?; + + #[allow(clippy::mutex_atomic)] + let on_state_member = Arc::new(Mutex::new(false)); + appservice + .virtual_user(None) + .await? + .register_event_handler({ + let on_state_member = on_state_member.clone(); + move |_ev: OriginalSyncRoomMemberEvent| { + *on_state_member.lock().unwrap() = true; + future::ready(()) + } + }) + .await; + + let status = warp::test::request() + .method("PUT") + .path(uri) + .json(&transaction) + .filter(&appservice.warp_filter()) + .await + .unwrap() + .into_response() + .status(); + + assert_eq!(status, 200); + { + let on_room_member_called = *on_state_member.lock().unwrap(); + assert!(on_room_member_called); + } + + // Reset this to check that next time it doesnt get called + { + let mut on_room_member_called = on_state_member.lock().unwrap(); + *on_room_member_called = false; + } + + let status = warp::test::request() + .method("PUT") + .path(uri) + .json(&transaction) + .filter(&appservice.warp_filter()) + .await + .unwrap() + .into_response() + .status(); + + // According to https://spec.matrix.org/v1.2/application-service-api/#pushing-events + // This should noop and return 200. + assert_eq!(status, 200); + { + let on_room_member_called = *on_state_member.lock().unwrap(); + // This time we should not have called the event handler. + assert!(!on_room_member_called); + } + + Ok(()) + } + + #[async_test] + async fn test_get_user() -> Result<()> { + let appservice = appservice(None, None).await?; + appservice.register_user_query(Box::new(|_, _| Box::pin(async move { true }))).await; + + let uri = "/_matrix/app/v1/users/%40_botty_1%3Adev.famedly.local?access_token=hs_token"; + + let status = warp::test::request() + .method("GET") + .path(uri) + .filter(&appservice.warp_filter()) + .await + .unwrap() + .into_response() + .status(); + + assert_eq!(status, 200); + + Ok(()) + } + + #[async_test] + async fn test_get_room() -> Result<()> { + let appservice = appservice(None, None).await?; + appservice.register_room_query(Box::new(|_, _| Box::pin(async move { true }))).await; + + let uri = "/_matrix/app/v1/rooms/%23magicforest%3Aexample.com?access_token=hs_token"; + + let status = warp::test::request() + .method("GET") + .path(uri) + .filter(&appservice.warp_filter()) + .await + .unwrap() + .into_response() + .status(); + + assert_eq!(status, 200); + + Ok(()) + } + + #[async_test] + async fn test_invalid_access_token() -> Result<()> { + let uri = "/_matrix/app/v1/transactions/1?access_token=invalid_token"; + + let mut transaction_builder = TransactionBuilder::new(); + let transaction = + transaction_builder.add_room_event(TimelineTestEvent::Member).build_json_transaction(); + + let appservice = appservice(None, None).await?; + + let status = warp::test::request() + .method("PUT") + .path(uri) + .json(&transaction) + .filter(&appservice.warp_filter()) + .await + .unwrap() + .into_response() + .status(); + + assert_eq!(status, 401); + + Ok(()) + } + + #[async_test] + async fn test_no_access_token() -> Result<()> { + let uri = "/_matrix/app/v1/transactions/1"; + + let mut transaction_builder = TransactionBuilder::new(); + transaction_builder.add_room_event(TimelineTestEvent::Member); + let transaction = transaction_builder.build_json_transaction(); + + let appservice = appservice(None, None).await?; + + { + let status = warp::test::request() + .method("PUT") + .path(uri) + .json(&transaction) + .filter(&appservice.warp_filter()) + .await + .unwrap() + .into_response() + .status(); + + assert_eq!(status, 401); + } + + Ok(()) + } + + #[async_test] + async fn test_event_handler() -> Result<()> { + let appservice = appservice(None, None).await?; + + #[allow(clippy::mutex_atomic)] + let on_state_member = Arc::new(Mutex::new(false)); + appservice + .virtual_user(None) + .await? + .register_event_handler({ + let on_state_member = on_state_member.clone(); + move |_ev: OriginalSyncRoomMemberEvent| { + *on_state_member.lock().unwrap() = true; + future::ready(()) + } + }) + .await; + + let uri = "/_matrix/app/v1/transactions/1?access_token=hs_token"; + + let mut transaction_builder = TransactionBuilder::new(); + transaction_builder.add_room_event(TimelineTestEvent::Member); + let transaction = transaction_builder.build_json_transaction(); + + warp::test::request() + .method("PUT") + .path(uri) + .json(&transaction) + .filter(&appservice.warp_filter()) + .await + .unwrap(); + + let on_room_member_called = *on_state_member.lock().unwrap(); + assert!(on_room_member_called); + + Ok(()) + } + + #[async_test] + async fn test_unrelated_path() -> Result<()> { + let appservice = appservice(None, None).await?; + + let status = { + let consumer_filter = warp::any() + .and(appservice.warp_filter()) + .or(warp::get().and(warp::path("unrelated").map(warp::reply))); + + let response = warp::test::request() + .method("GET") + .path("/unrelated") + .filter(&consumer_filter) + .await? + .into_response(); + + response.status() + }; + + assert_eq!(status, 200); + + Ok(()) + } + + #[async_test] + async fn test_appservice_on_sub_path() -> Result<()> { + let room_id = room_id!("!SVkFJHzfwvuaIEawgC:localhost"); + let uri_1 = "/sub_path/_matrix/app/v1/transactions/1?access_token=hs_token"; + let uri_2 = "/sub_path/_matrix/app/v1/transactions/2?access_token=hs_token"; + + let mut transaction_builder = TransactionBuilder::new(); + transaction_builder.add_room_event(TimelineTestEvent::Member); + let transaction_1 = transaction_builder.build_json_transaction(); + + let mut transaction_builder = TransactionBuilder::new(); + transaction_builder.add_room_event(TimelineTestEvent::MemberNameChange); + let transaction_2 = transaction_builder.build_json_transaction(); + + let appservice = appservice(None, None).await?; + + { + warp::test::request() + .method("PUT") + .path(uri_1) + .json(&transaction_1) + .filter(&warp::path("sub_path").and(appservice.warp_filter())) + .await?; + + warp::test::request() + .method("PUT") + .path(uri_2) + .json(&transaction_2) + .filter(&warp::path("sub_path").and(appservice.warp_filter())) + .await?; + }; + + let members = appservice + .virtual_user(None) + .await? + .get_room(room_id) + .expect("Expected room to be available") + .members_no_sync() + .await?; + + assert_eq!(members[0].display_name().unwrap(), "changed"); + + Ok(()) + } + + #[async_test] + async fn test_receive_transaction() -> Result<()> { + tracing_subscriber::fmt().try_init().ok(); + let json = vec![ + Raw::new(&json!({ + "content": { + "avatar_url": null, + "displayname": "Appservice", + "membership": "join" + }, + "event_id": "$151800140479rdvjg:localhost", + "membership": "join", + "origin_server_ts": 151800140, + "sender": "@_appservice:localhost", + "state_key": "@_appservice:localhost", + "type": "m.room.member", + "room_id": "!coolplace:localhost", + "unsigned": { + "age": 2970366 + } + }))? + .cast::(), + Raw::new(&json!({ + "content": { + "avatar_url": null, + "displayname": "Appservice", + "membership": "join" + }, + "event_id": "$151800140491rfbja:localhost", + "membership": "join", + "origin_server_ts": 151800140, + "sender": "@_appservice:localhost", + "state_key": "@_appservice:localhost", + "type": "m.room.member", + "room_id": "!boringplace:localhost", + "unsigned": { + "age": 2970366 + } + }))? + .cast::(), + Raw::new(&json!({ + "content": { + "avatar_url": null, + "displayname": "Alice", + "membership": "join" + }, + "event_id": "$151800140517rfvjc:localhost", + "membership": "join", + "origin_server_ts": 151800140, + "sender": "@_appservice_alice:localhost", + "state_key": "@_appservice_alice:localhost", + "type": "m.room.member", + "room_id": "!coolplace:localhost", + "unsigned": { + "age": 2970366 + } + }))? + .cast::(), + Raw::new(&json!({ + "content": { + "avatar_url": null, + "displayname": "Bob", + "membership": "invite" + }, + "event_id": "$151800140594rfvjc:localhost", + "membership": "invite", + "origin_server_ts": 151800174, + "sender": "@_appservice_bob:localhost", + "state_key": "@_appservice_bob:localhost", + "type": "m.room.member", + "room_id": "!boringplace:localhost", + "unsigned": { + "age": 2970366 + } + }))? + .cast::(), + ]; + let appservice = appservice(None, None).await?; + + let alice = appservice.virtual_user(Some("_appservice_alice")).await?; + let bob = appservice.virtual_user(Some("_appservice_bob")).await?; + appservice + .receive_transaction(push_events::v1::IncomingRequest::new("dontcare".into(), json)) + .await?; + let coolplace = room_id!("!coolplace:localhost"); + let boringplace = room_id!("!boringplace:localhost"); + assert!( + alice.get_joined_room(coolplace).is_some(), + "Alice's membership in coolplace should be join" + ); + assert!( + bob.get_invited_room(boringplace).is_some(), + "Bob's membership in boringplace should be invite" + ); + assert!(alice.get_room(boringplace).is_none(), "Alice should not know about boringplace"); + assert!(bob.get_room(coolplace).is_none(), "Bob should not know about coolplace"); + Ok(()) + } + + mod registration { + use super::*; + + #[test] + fn test_registration() -> Result<()> { + let registration: Registration = serde_yaml::from_str(®istration_string())?; + let registration: AppServiceRegistration = registration.into(); + + assert_eq!(registration.id, "appservice"); + + Ok(()) + } + + #[test] + fn test_registration_from_yaml_file() -> Result<()> { + let registration = + AppServiceRegistration::try_from_yaml_file("./tests/registration.yaml")?; + + assert_eq!(registration.id, "appservice"); + + Ok(()) + } + + #[test] + fn test_registration_from_yaml_str() -> Result<()> { + let registration = AppServiceRegistration::try_from_yaml_str(registration_string())?; + + assert_eq!(registration.id, "appservice"); + + Ok(()) + } + } } diff --git a/crates/matrix-sdk-appservice/src/webserver.rs b/crates/matrix-sdk-appservice/src/webserver.rs index e649b6f53..9e29a08a9 100644 --- a/crates/matrix-sdk-appservice/src/webserver.rs +++ b/crates/matrix-sdk-appservice/src/webserver.rs @@ -107,10 +107,11 @@ mod filters { warp::any() .and(valid_access_token(appservice.registration().hs_token.clone())) .map(move || appservice.clone()) - .and(http_request().and_then(|request| async move { - let request = crate::transform_request_path(request).map_err(Error::from)?; - Ok::, Rejection>(request) - })) + .and( + http_request().and_then(|request| async move { + Ok::, Rejection>(request) + }), + ) .boxed() } diff --git a/crates/matrix-sdk-appservice/tests/tests.rs b/crates/matrix-sdk-appservice/tests/tests.rs deleted file mode 100644 index fbebc9670..000000000 --- a/crates/matrix-sdk-appservice/tests/tests.rs +++ /dev/null @@ -1,513 +0,0 @@ -use std::{ - future, - sync::{Arc, Mutex}, -}; - -use matrix_sdk::{ - config::RequestConfig, - ruma::{api::appservice::Registration, events::room::member::OriginalSyncRoomMemberEvent}, - Client, -}; -use matrix_sdk_appservice::*; -use matrix_sdk_test::{appservice::TransactionBuilder, async_test, test_json, TimelineTestEvent}; -use ruma::{ - api::{appservice::event::push_events, MatrixVersion}, - events::AnyRoomEvent, - room_id, - serde::Raw, -}; -use serde_json::json; -use warp::{Filter, Reply}; -use wiremock::{ - matchers::{body_json, header, method, path}, - Mock, MockServer, ResponseTemplate, -}; - -fn registration_string() -> String { - include_str!("../tests/registration.yaml").to_owned() -} - -async fn appservice( - homeserver_url: Option, - registration: Option, -) -> Result { - // env::set_var( - // "RUST_LOG", - // "wiremock=debug,matrix_sdk=debug,ruma=debug,warp=debug", - // ); - let _ = tracing_subscriber::fmt::try_init(); - - let registration = match registration { - Some(registration) => registration.into(), - None => AppServiceRegistration::try_from_yaml_str(registration_string()).unwrap(), - }; - - let homeserver_url = homeserver_url.unwrap_or_else(|| "http://localhost:1234".to_owned()); - let server_name = "localhost"; - - let client_builder = Client::builder() - .request_config(RequestConfig::default().disable_retry()) - .server_versions([MatrixVersion::V1_0]); - - AppService::with_client_builder( - homeserver_url.as_ref(), - server_name, - registration, - client_builder, - ) - .await -} - -#[async_test] -async fn test_register_virtual_user() -> Result<()> { - let server = MockServer::start().await; - let appservice = appservice(Some(server.uri()), None).await?; - - let localpart = "someone"; - Mock::given(method("POST")) - .and(path("/_matrix/client/r0/register")) - .and(header( - "authorization", - format!("Bearer {}", appservice.registration().as_token).as_str(), - )) - .and(body_json(json!({ - "username": localpart.to_owned(), - "type": "m.login.application_service" - }))) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ - "access_token": "abc123", - "device_id": "GHTYAJCE", - "user_id": format!("@{localpart}:localhost"), - }))) - .mount(&server) - .await; - - appservice.register_virtual_user(localpart, None).await?; - - Ok(()) -} - -#[async_test] -async fn test_put_transaction() -> Result<()> { - let uri = "/_matrix/app/v1/transactions/1?access_token=hs_token"; - - let mut transaction_builder = TransactionBuilder::new(); - transaction_builder.add_room_event(TimelineTestEvent::Member); - let transaction = transaction_builder.build_json_transaction(); - - let appservice = appservice(None, None).await?; - - let status = warp::test::request() - .method("PUT") - .path(uri) - .json(&transaction) - .filter(&appservice.warp_filter()) - .await - .unwrap() - .into_response() - .status(); - - assert_eq!(status, 200); - - Ok(()) -} - -#[async_test] -async fn test_put_transaction_with_repeating_txn_id() -> Result<()> { - let uri = "/_matrix/app/v1/transactions/1?access_token=hs_token"; - - let mut transaction_builder = TransactionBuilder::new(); - transaction_builder.add_room_event(TimelineTestEvent::Member); - let transaction = transaction_builder.build_json_transaction(); - - let appservice = appservice(None, None).await?; - - #[allow(clippy::mutex_atomic)] - let on_state_member = Arc::new(Mutex::new(false)); - appservice - .virtual_user(None) - .await? - .register_event_handler({ - let on_state_member = on_state_member.clone(); - move |_ev: OriginalSyncRoomMemberEvent| { - *on_state_member.lock().unwrap() = true; - future::ready(()) - } - }) - .await; - - let status = warp::test::request() - .method("PUT") - .path(uri) - .json(&transaction) - .filter(&appservice.warp_filter()) - .await - .unwrap() - .into_response() - .status(); - - assert_eq!(status, 200); - { - let on_room_member_called = *on_state_member.lock().unwrap(); - assert!(on_room_member_called); - } - - // Reset this to check that next time it doesnt get called - { - let mut on_room_member_called = on_state_member.lock().unwrap(); - *on_room_member_called = false; - } - - let status = warp::test::request() - .method("PUT") - .path(uri) - .json(&transaction) - .filter(&appservice.warp_filter()) - .await - .unwrap() - .into_response() - .status(); - - // According to https://spec.matrix.org/v1.2/application-service-api/#pushing-events - // This should noop and return 200. - assert_eq!(status, 200); - { - let on_room_member_called = *on_state_member.lock().unwrap(); - // This time we should not have called the event handler. - assert!(!on_room_member_called); - } - - Ok(()) -} - -#[async_test] -async fn test_get_user() -> Result<()> { - let appservice = appservice(None, None).await?; - appservice.register_user_query(Box::new(|_, _| Box::pin(async move { true }))).await; - - let uri = "/_matrix/app/v1/users/%40_botty_1%3Adev.famedly.local?access_token=hs_token"; - - let status = warp::test::request() - .method("GET") - .path(uri) - .filter(&appservice.warp_filter()) - .await - .unwrap() - .into_response() - .status(); - - assert_eq!(status, 200); - - Ok(()) -} - -#[async_test] -async fn test_get_room() -> Result<()> { - let appservice = appservice(None, None).await?; - appservice.register_room_query(Box::new(|_, _| Box::pin(async move { true }))).await; - - let uri = "/_matrix/app/v1/rooms/%23magicforest%3Aexample.com?access_token=hs_token"; - - let status = warp::test::request() - .method("GET") - .path(uri) - .filter(&appservice.warp_filter()) - .await - .unwrap() - .into_response() - .status(); - - assert_eq!(status, 200); - - Ok(()) -} - -#[async_test] -async fn test_invalid_access_token() -> Result<()> { - let uri = "/_matrix/app/v1/transactions/1?access_token=invalid_token"; - - let mut transaction_builder = TransactionBuilder::new(); - let transaction = - transaction_builder.add_room_event(TimelineTestEvent::Member).build_json_transaction(); - - let appservice = appservice(None, None).await?; - - let status = warp::test::request() - .method("PUT") - .path(uri) - .json(&transaction) - .filter(&appservice.warp_filter()) - .await - .unwrap() - .into_response() - .status(); - - assert_eq!(status, 401); - - Ok(()) -} - -#[async_test] -async fn test_no_access_token() -> Result<()> { - let uri = "/_matrix/app/v1/transactions/1"; - - let mut transaction_builder = TransactionBuilder::new(); - transaction_builder.add_room_event(TimelineTestEvent::Member); - let transaction = transaction_builder.build_json_transaction(); - - let appservice = appservice(None, None).await?; - - { - let status = warp::test::request() - .method("PUT") - .path(uri) - .json(&transaction) - .filter(&appservice.warp_filter()) - .await - .unwrap() - .into_response() - .status(); - - assert_eq!(status, 401); - } - - Ok(()) -} - -#[async_test] -async fn test_event_handler() -> Result<()> { - let appservice = appservice(None, None).await?; - - #[allow(clippy::mutex_atomic)] - let on_state_member = Arc::new(Mutex::new(false)); - appservice - .virtual_user(None) - .await? - .register_event_handler({ - let on_state_member = on_state_member.clone(); - move |_ev: OriginalSyncRoomMemberEvent| { - *on_state_member.lock().unwrap() = true; - future::ready(()) - } - }) - .await; - - let uri = "/_matrix/app/v1/transactions/1?access_token=hs_token"; - - let mut transaction_builder = TransactionBuilder::new(); - transaction_builder.add_room_event(TimelineTestEvent::Member); - let transaction = transaction_builder.build_json_transaction(); - - warp::test::request() - .method("PUT") - .path(uri) - .json(&transaction) - .filter(&appservice.warp_filter()) - .await - .unwrap(); - - let on_room_member_called = *on_state_member.lock().unwrap(); - assert!(on_room_member_called); - - Ok(()) -} - -#[async_test] -async fn test_unrelated_path() -> Result<()> { - let appservice = appservice(None, None).await?; - - let status = { - let consumer_filter = warp::any() - .and(appservice.warp_filter()) - .or(warp::get().and(warp::path("unrelated").map(warp::reply))); - - let response = warp::test::request() - .method("GET") - .path("/unrelated") - .filter(&consumer_filter) - .await? - .into_response(); - - response.status() - }; - - assert_eq!(status, 200); - - Ok(()) -} - -#[async_test] -async fn test_appservice_on_sub_path() -> Result<()> { - let room_id = &test_json::DEFAULT_SYNC_ROOM_ID; - let uri_1 = "/sub_path/_matrix/app/v1/transactions/1?access_token=hs_token"; - let uri_2 = "/sub_path/_matrix/app/v1/transactions/2?access_token=hs_token"; - - let mut transaction_builder = TransactionBuilder::new(); - transaction_builder.add_room_event(TimelineTestEvent::Member); - let transaction_1 = transaction_builder.build_json_transaction(); - - let mut transaction_builder = TransactionBuilder::new(); - transaction_builder.add_room_event(TimelineTestEvent::MemberNameChange); - let transaction_2 = transaction_builder.build_json_transaction(); - - let appservice = appservice(None, None).await?; - - { - warp::test::request() - .method("PUT") - .path(uri_1) - .json(&transaction_1) - .filter(&warp::path("sub_path").and(appservice.warp_filter())) - .await?; - - warp::test::request() - .method("PUT") - .path(uri_2) - .json(&transaction_2) - .filter(&warp::path("sub_path").and(appservice.warp_filter())) - .await?; - }; - - let members = appservice - .virtual_user(None) - .await? - .get_room(room_id) - .expect("Expected room to be available") - .members_no_sync() - .await?; - - assert_eq!(members[0].display_name().unwrap(), "changed"); - - Ok(()) -} - -#[async_test] -async fn test_receive_transaction() -> Result<()> { - tracing_subscriber::fmt().try_init().ok(); - let json = vec![ - Raw::new(&json!({ - "content": { - "avatar_url": null, - "displayname": "Appservice", - "membership": "join" - }, - "event_id": "$151800140479rdvjg:localhost", - "membership": "join", - "origin_server_ts": 151800140, - "sender": "@_appservice:localhost", - "state_key": "@_appservice:localhost", - "type": "m.room.member", - "room_id": "!coolplace:localhost", - "unsigned": { - "age": 2970366 - } - }))? - .cast::(), - Raw::new(&json!({ - "content": { - "avatar_url": null, - "displayname": "Appservice", - "membership": "join" - }, - "event_id": "$151800140491rfbja:localhost", - "membership": "join", - "origin_server_ts": 151800140, - "sender": "@_appservice:localhost", - "state_key": "@_appservice:localhost", - "type": "m.room.member", - "room_id": "!boringplace:localhost", - "unsigned": { - "age": 2970366 - } - }))? - .cast::(), - Raw::new(&json!({ - "content": { - "avatar_url": null, - "displayname": "Alice", - "membership": "join" - }, - "event_id": "$151800140517rfvjc:localhost", - "membership": "join", - "origin_server_ts": 151800140, - "sender": "@_appservice_alice:localhost", - "state_key": "@_appservice_alice:localhost", - "type": "m.room.member", - "room_id": "!coolplace:localhost", - "unsigned": { - "age": 2970366 - } - }))? - .cast::(), - Raw::new(&json!({ - "content": { - "avatar_url": null, - "displayname": "Bob", - "membership": "invite" - }, - "event_id": "$151800140594rfvjc:localhost", - "membership": "invite", - "origin_server_ts": 151800174, - "sender": "@_appservice_bob:localhost", - "state_key": "@_appservice_bob:localhost", - "type": "m.room.member", - "room_id": "!boringplace:localhost", - "unsigned": { - "age": 2970366 - } - }))? - .cast::(), - ]; - let appservice = appservice(None, None).await?; - - let alice = appservice.virtual_user(Some("_appservice_alice")).await?; - let bob = appservice.virtual_user(Some("_appservice_bob")).await?; - appservice - .receive_transaction(push_events::v1::IncomingRequest::new("dontcare".into(), json)) - .await?; - let coolplace = room_id!("!coolplace:localhost"); - let boringplace = room_id!("!boringplace:localhost"); - assert!( - alice.get_joined_room(coolplace).is_some(), - "Alice's membership in coolplace should be join" - ); - assert!( - bob.get_invited_room(boringplace).is_some(), - "Bob's membership in boringplace should be invite" - ); - assert!(alice.get_room(boringplace).is_none(), "Alice should not know about boringplace"); - assert!(bob.get_room(coolplace).is_none(), "Bob should not know about coolplace"); - Ok(()) -} - -mod registration { - use super::*; - - #[test] - fn test_registration() -> Result<()> { - let registration: Registration = serde_yaml::from_str(®istration_string())?; - let registration: AppServiceRegistration = registration.into(); - - assert_eq!(registration.id, "appservice"); - - Ok(()) - } - - #[test] - fn test_registration_from_yaml_file() -> Result<()> { - let registration = AppServiceRegistration::try_from_yaml_file("./tests/registration.yaml")?; - - assert_eq!(registration.id, "appservice"); - - Ok(()) - } - - #[test] - fn test_registration_from_yaml_str() -> Result<()> { - let registration = AppServiceRegistration::try_from_yaml_str(registration_string())?; - - assert_eq!(registration.id, "appservice"); - - Ok(()) - } -} From 76fd9bd963a5a022c6e10725d12b4edc3a75d3ca Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Wed, 20 Jul 2022 13:12:44 +0200 Subject: [PATCH 66/73] fix(sdk): Call to-device handlers --- crates/matrix-sdk/src/sync.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/matrix-sdk/src/sync.rs b/crates/matrix-sdk/src/sync.rs index 6fa924b21..a580e56c5 100644 --- a/crates/matrix-sdk/src/sync.rs +++ b/crates/matrix-sdk/src/sync.rs @@ -22,7 +22,7 @@ impl Client { rooms, presence, account_data, - to_device: _, + to_device, device_lists: _, device_one_time_keys_count: _, ambiguity_changes: _, @@ -31,6 +31,7 @@ impl Client { self.handle_sync_events(EventKind::GlobalAccountData, &None, &account_data.events).await?; self.handle_sync_events(EventKind::Presence, &None, &presence.events).await?; + self.handle_sync_events(EventKind::ToDevice, &None, &to_device.events).await?; for (room_id, room_info) in &rooms.join { let room = self.get_room(room_id); From 5b66bed1f00b0881fcf093e3b0d37f9f168423b8 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Wed, 20 Jul 2022 14:41:59 +0200 Subject: [PATCH 67/73] chore: Remove unused imports from example --- crates/matrix-sdk/src/room/common.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/matrix-sdk/src/room/common.rs b/crates/matrix-sdk/src/room/common.rs index 4eb66082a..cd63fa595 100644 --- a/crates/matrix-sdk/src/room/common.rs +++ b/crates/matrix-sdk/src/room/common.rs @@ -264,7 +264,7 @@ impl Common { /// # Examples /// ```no_run /// # use std::convert::TryFrom; - /// use matrix_sdk::{room::MessagesOptions, Client}; + /// use matrix_sdk::Client; /// # use matrix_sdk::ruma::{ /// # api::client::filter::RoomEventFilter, /// # room_id, @@ -344,7 +344,7 @@ impl Common { /// # Examples /// ```no_run /// # use std::convert::TryFrom; - /// use matrix_sdk::{room::MessagesOptions, Client}; + /// use matrix_sdk::Client; /// # use matrix_sdk::ruma::{ /// # api::client::filter::RoomEventFilter, /// # room_id, @@ -403,7 +403,7 @@ impl Common { /// # Examples /// ```no_run /// # use std::convert::TryFrom; - /// use matrix_sdk::{room::MessagesOptions, Client}; + /// use matrix_sdk::Client; /// # use matrix_sdk::ruma::{ /// # api::client::filter::RoomEventFilter, /// # room_id, From cf8f3bf7cc7f1b09d84478e4c8c9a6c92330e9da Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Wed, 20 Jul 2022 14:56:59 +0200 Subject: [PATCH 68/73] refactor(sdk)!: Update MessageOptions API once again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … to match the latest changes in Ruma. --- crates/matrix-sdk/src/room/common.rs | 45 +++++++++++++++------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/crates/matrix-sdk/src/room/common.rs b/crates/matrix-sdk/src/room/common.rs index cd63fa595..9e740a9e2 100644 --- a/crates/matrix-sdk/src/room/common.rs +++ b/crates/matrix-sdk/src/room/common.rs @@ -176,13 +176,13 @@ impl Common { /// # let homeserver = Url::parse("http://example.com").unwrap(); /// # use futures::executor::block_on; /// # block_on(async { - /// let request = MessagesOptions::backward_from("t47429-4392820_219380_26003_2265"); + /// let options = MessagesOptions::backward().from("t47429-4392820_219380_26003_2265"); /// /// let mut client = Client::new(homeserver).await.unwrap(); /// let room = client /// .get_joined_room(room_id!("!roomid:example.com")) /// .unwrap(); - /// assert!(room.messages(request).await.is_ok()); + /// assert!(room.messages(options).await.is_ok()); /// # }); /// ``` pub async fn messages(&self, options: MessagesOptions<'_>) -> Result { @@ -461,7 +461,8 @@ impl Common { let filter = assign!(RoomEventFilter::default(), { lazy_load_options: LazyLoadOptions::Enabled { include_redundant_members: false }, }); - let options = assign!(MessagesOptions::backward_from(token), { + let options = assign!(MessagesOptions::backward(), { + from: Some(token), limit: uint!(10), filter, }); @@ -1116,28 +1117,30 @@ impl<'a> MessagesOptions<'a> { Self { from: None, to: None, dir, limit: uint!(10), filter: RoomEventFilter::default() } } - /// Creates `MessagesOptions` with the given optional start token, and `dir` - /// set to `Backward`. - pub fn backward(from: Option<&'a str>) -> Self { - assign!(Self::new(Direction::Backward), { from }) + /// Creates `MessagesOptions` with `dir` set to `Backward`. + /// + /// If no `from` token is set afterwards, pagination will start at the + /// end of (the accessible part of) the room timeline. + pub fn backward() -> Self { + Self::new(Direction::Backward) } - /// Creates `MessagesOptions` with the given start token, and `dir` set to - /// `Backward`. - pub fn backward_from(from: &'a str) -> Self { - Self::backward(Some(from)) + /// Creates `MessagesOptions` with `dir` set to `Forward`. + /// + /// If no `from` token is set afterwards, pagination will start at the + /// beginning of (the accessible part of) the room timeline. + pub fn forward() -> Self { + Self::new(Direction::Forward) } - /// Creates `MessagesOptions` with the given optional start token, and `dir` - /// set to `Forward`. - pub fn forward(from: Option<&'a str>) -> Self { - assign!(Self::new(Direction::Forward), { from }) - } - - /// Creates `MessagesOptions` with the given start token, and `dir` set to - /// `Forward`. - pub fn forward_from(from: &'a str) -> Self { - Self::forward(Some(from)) + /// Creates a new `MessagesOptions` from `self` with the `from` field set to + /// the given value. + /// + /// Since the field is public, you can also assign to it directly. This + /// method merely acts as a shorthand for that, because it is very + /// common to set this field. + pub fn from(self, from: impl Into>) -> Self { + Self { from: from.into(), ..self } } fn into_request(self, room_id: &'a RoomId) -> get_message_events::v3::Request<'_> { From 4187aa400f6f58d7f9b873e1c73efaba78622b6f Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Wed, 29 Jun 2022 12:24:57 +0200 Subject: [PATCH 69/73] refactor: Remove Store type usage from sled-state-inspector Requires using more explicit syntax for some calls because SledStore has methods of the same names with different (harder to use) signatures. --- labs/sled-state-inspector/src/main.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/labs/sled-state-inspector/src/main.rs b/labs/sled-state-inspector/src/main.rs index 5c088d7c7..2785345c3 100644 --- a/labs/sled-state-inspector/src/main.rs +++ b/labs/sled-state-inspector/src/main.rs @@ -3,7 +3,7 @@ use std::{convert::TryFrom, fmt::Debug, sync::Arc}; use atty::Stream; use clap::{Arg, ArgMatches, Command as Argparse}; use futures::executor::block_on; -use matrix_sdk_base::{RoomInfo, Store}; +use matrix_sdk_base::RoomInfo; use matrix_sdk_sled::StateStore; use ruma::{events::StateEventType, OwnedRoomId, OwnedUserId, RoomId}; use rustyline::{ @@ -26,13 +26,13 @@ use syntect::{ #[derive(Clone)] struct Inspector { - store: Store, + store: Arc, printer: Printer, } #[derive(Helper)] struct InspectorHelper { - store: Store, + store: Arc, _highlighter: MatchingBracketHighlighter, _validator: MatchingBracketValidator, _hinter: HistoryHinter, @@ -54,7 +54,7 @@ impl InspectorHelper { "m.room.topic", ]; - fn new(store: Store) -> Self { + fn new(store: Arc) -> Self { Self { store, _highlighter: MatchingBracketHighlighter::new(), @@ -72,7 +72,9 @@ impl InspectorHelper { } fn complete_rooms(&self, arg: Option<&&str>) -> Vec { - let rooms: Vec = block_on(async { self.store.get_room_infos().await.unwrap() }); + let rooms: Vec = block_on(async { + matrix_sdk_base::StateStore::get_room_infos(&*self.store).await.unwrap() + }); rooms .into_iter() @@ -200,9 +202,8 @@ impl Printer { impl Inspector { fn new(database_path: &str, json: bool, color: bool) -> Self { let printer = Printer::new(json, color); - let store = Store::new(Arc::new( - StateStore::open_with_path(database_path).expect("Can't open sled database"), - )); + let store = + Arc::new(StateStore::open_with_path(database_path).expect("Can't open sled database")); Self { store, printer } } @@ -237,7 +238,8 @@ impl Inspector { } async fn list_rooms(&self) { - let rooms: Vec = self.store.get_room_infos().await.unwrap(); + let rooms: Vec = + matrix_sdk_base::StateStore::get_room_infos(&*self.store).await.unwrap(); self.printer.pretty_print_struct(&rooms); } @@ -247,7 +249,8 @@ impl Inspector { } async fn get_profiles(&self, room_id: OwnedRoomId) { - let joined: Vec = self.store.get_joined_user_ids(&room_id).await.unwrap(); + let joined: Vec = + matrix_sdk_base::StateStore::get_joined_user_ids(&*self.store, &room_id).await.unwrap(); for member in joined { let event = self.store.get_profile(&room_id, &member).await.unwrap(); @@ -256,7 +259,8 @@ impl Inspector { } async fn get_members(&self, room_id: OwnedRoomId) { - let joined: Vec = self.store.get_joined_user_ids(&room_id).await.unwrap(); + let joined: Vec = + matrix_sdk_base::StateStore::get_joined_user_ids(&*self.store, &room_id).await.unwrap(); for member in joined { let event = self.store.get_member_event(&room_id, &member).await.unwrap(); From a43005dec287f15f4abd56e321dea559866631fb Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Wed, 29 Jun 2022 14:31:24 +0200 Subject: [PATCH 70/73] refactor(base): Add RoomInfo::new constructor --- crates/matrix-sdk-base/src/rooms/normal.rs | 23 ++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/crates/matrix-sdk-base/src/rooms/normal.rs b/crates/matrix-sdk-base/src/rooms/normal.rs index 39fe79c11..66c9c1117 100644 --- a/crates/matrix-sdk-base/src/rooms/normal.rs +++ b/crates/matrix-sdk-base/src/rooms/normal.rs @@ -103,16 +103,7 @@ impl Room { room_id: &RoomId, room_type: RoomType, ) -> Self { - let room_info = RoomInfo { - room_id: room_id.into(), - room_type, - notification_counts: Default::default(), - summary: Default::default(), - members_synced: false, - last_prev_batch: None, - base_info: BaseRoomInfo::new(), - }; - + let room_info = RoomInfo::new(room_id, room_type); Self::restore(own_user_id, store, room_info) } @@ -655,6 +646,18 @@ pub struct RoomInfo { } impl RoomInfo { + pub(crate) fn new(room_id: &RoomId, room_type: RoomType) -> Self { + Self { + room_id: room_id.into(), + room_type, + notification_counts: Default::default(), + summary: Default::default(), + members_synced: false, + last_prev_batch: None, + base_info: BaseRoomInfo::new(), + } + } + /// Mark this Room as joined pub fn mark_as_joined(&mut self) { self.room_type = RoomType::Joined; From 63d01dd20ed839150a033412cfa576690eed45c4 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Wed, 29 Jun 2022 14:26:46 +0200 Subject: [PATCH 71/73] refactor(base): Stop using Store type in store integration tests --- crates/matrix-sdk-base/src/rooms/normal.rs | 3 +- .../src/store/integration_tests.rs | 41 +++++++------------ 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/crates/matrix-sdk-base/src/rooms/normal.rs b/crates/matrix-sdk-base/src/rooms/normal.rs index 66c9c1117..fe286f965 100644 --- a/crates/matrix-sdk-base/src/rooms/normal.rs +++ b/crates/matrix-sdk-base/src/rooms/normal.rs @@ -646,7 +646,8 @@ pub struct RoomInfo { } impl RoomInfo { - pub(crate) fn new(room_id: &RoomId, room_type: RoomType) -> Self { + #[doc(hidden)] // used by store tests, otherwise it would be pub(crate) + pub fn new(room_id: &RoomId, room_type: RoomType) -> Self { Self { room_id: room_id.into(), room_type, diff --git a/crates/matrix-sdk-base/src/store/integration_tests.rs b/crates/matrix-sdk-base/src/store/integration_tests.rs index cf827374d..0af39b2b8 100644 --- a/crates/matrix-sdk-base/src/store/integration_tests.rs +++ b/crates/matrix-sdk-base/src/store/integration_tests.rs @@ -52,7 +52,7 @@ macro_rules! statestore_integration_tests { use matrix_sdk_test::{async_test, test_json}; use ruma::{ api::client::media::get_content_thumbnail::v3::Method, - device_id, event_id, + event_id, events::{ presence::PresenceEvent, receipt::ReceiptType, @@ -83,14 +83,13 @@ macro_rules! statestore_integration_tests { deserialized_responses::{ RoomEvent, SyncRoomEvent, TimelineSlice}, }; use $crate::{ - RoomType, Session, media::{MediaFormat, MediaRequest, MediaThumbnailSize}, store::{ - Store, StateStore, Result as StoreResult, StateChanges - } + }, + RoomInfo, RoomType, }; use super::get_store; @@ -115,22 +114,13 @@ macro_rules! statestore_integration_tests { } /// Populate the given `StateStore`. - pub(crate) async fn populated_store(inner: Arc) -> StoreResult { + pub async fn populate_store(store: Arc) -> StoreResult<()> { let mut changes = StateChanges::default(); - let store = Store::new(inner); let user_id = user_id(); let invited_user_id = invited_user_id(); let room_id = room_id(); let stripped_room_id = stripped_room_id(); - let device_id = device_id!("device"); - - let session = Session { - access_token: "token".to_owned(), - user_id: user_id.to_owned(), - device_id: device_id.to_owned(), - }; - store.restore_session(session).await.unwrap(); changes.sync_token = Some("t392-516_47314_0_7_1_1_1_11444_1".to_owned()); @@ -147,7 +137,7 @@ macro_rules! statestore_integration_tests { let pushrules_event = pushrules_raw.deserialize().unwrap(); changes.add_account_data(pushrules_event, pushrules_raw); - let mut room = store.get_or_create_room(room_id, RoomType::Joined).await.clone_info(); + let mut room = RoomInfo::new(room_id, RoomType::Joined); room.mark_as_left(); let tag_json: &JsonValue = &test_json::TAG; @@ -220,8 +210,7 @@ macro_rules! statestore_integration_tests { changes.members.insert(room_id.to_owned(), room_members); changes.add_room(room); - let mut stripped_room = - store.get_or_create_stripped_room(stripped_room_id).await.clone_info(); + let mut stripped_room = RoomInfo::new(stripped_room_id, RoomType::Invited); let stripped_name_json: &JsonValue = &test_json::NAME_STRIPPED; let stripped_name_raw = @@ -249,7 +238,7 @@ macro_rules! statestore_integration_tests { changes.add_stripped_member(stripped_room_id, stripped_member_event); store.save_changes(&changes).await?; - Ok(store) + Ok(()) } fn power_level_event() -> Raw { @@ -305,11 +294,12 @@ macro_rules! statestore_integration_tests { let user_id = user_id(); let inner_store = get_store().await?; - let store = populated_store(Arc::new(inner_store)).await?; + let store = Arc::new(inner_store); + populate_store(store.clone()).await?; assert!(store.get_sync_token().await?.is_some()); assert!(store.get_presence_event(user_id).await?.is_some()); - assert_eq!(store.get_room_infos().await?.len(), 1, "Expected to find 1 room info "); + assert_eq!(store.get_room_infos().await?.len(), 1, "Expected to find 1 room info"); assert_eq!(store.get_stripped_room_infos().await?.len(), 1, "Expected to find 1 stripped room info"); assert!(store.get_account_data_event(GlobalAccountDataEventType::PushRules).await?.is_some()); @@ -580,25 +570,24 @@ macro_rules! statestore_integration_tests { #[async_test] async fn test_persist_invited_room() -> StoreResult<()> { - let stripped_room_id = stripped_room_id(); let inner_store = get_store().await?; - let store = populated_store(Arc::new(inner_store)).await?; + let store = Arc::new(inner_store); + populate_store(store.clone()).await?; assert_eq!(store.get_stripped_room_infos().await?.len(), 1); - assert!(store.get_stripped_room(stripped_room_id).is_some()); - // populate rooom Ok(()) } #[async_test] - async fn test_room_removal() -> StoreResult<()> { + async fn test_room_removal() -> StoreResult<()> { let room_id = room_id(); let user_id = user_id(); let inner_store = get_store().await?; let stripped_room_id = stripped_room_id(); - let store = populated_store(Arc::new(inner_store)).await?; + let store = Arc::new(inner_store); + populate_store(store.clone()).await?; store.remove_room(room_id).await?; From 0b3b757120e87f365eb92bdd9a77da6557d9a8d6 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Wed, 29 Jun 2022 14:57:24 +0200 Subject: [PATCH 72/73] refactor: Make Store type internal to base crate --- crates/matrix-sdk-base/src/client.rs | 15 +++++++++++-- crates/matrix-sdk-base/src/lib.rs | 2 +- crates/matrix-sdk-base/src/store/mod.rs | 2 +- crates/matrix-sdk/src/client/mod.rs | 28 +++++++++++++------------ 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/crates/matrix-sdk-base/src/client.rs b/crates/matrix-sdk-base/src/client.rs index e7efca697..ac43bf78e 100644 --- a/crates/matrix-sdk-base/src/client.rs +++ b/crates/matrix-sdk-base/src/client.rs @@ -66,6 +66,7 @@ use crate::{ store::{ ambiguity_map::AmbiguityCache, Result as StoreResult, StateChanges, Store, StoreConfig, }, + StateStore, }; /// A no IO Client implementation. @@ -135,9 +136,19 @@ impl BaseClient { self.store.session() } + /// Get all the rooms this client knows about. + pub fn get_rooms(&self) -> Vec { + self.store.get_rooms() + } + + /// Get all the rooms this client knows about. + pub fn get_stripped_rooms(&self) -> Vec { + self.store.get_stripped_rooms() + } + /// Get a reference to the store. - pub fn store(&self) -> &Store { - &self.store + pub fn store(&self) -> &dyn StateStore { + &*self.store } /// Is the client logged in. diff --git a/crates/matrix-sdk-base/src/lib.rs b/crates/matrix-sdk-base/src/lib.rs index 3924d80b2..b7bbaeecb 100644 --- a/crates/matrix-sdk-base/src/lib.rs +++ b/crates/matrix-sdk-base/src/lib.rs @@ -43,7 +43,7 @@ pub use http; pub use matrix_sdk_crypto as crypto; pub use once_cell; pub use rooms::{DisplayName, Room, RoomInfo, RoomMember, RoomType}; -pub use store::{StateChanges, StateStore, Store, StoreError}; +pub use store::{StateChanges, StateStore, StoreError}; pub use utils::{ MinimalRoomMemberEvent, MinimalStateEvent, OriginalMinimalStateEvent, RedactedMinimalStateEvent, }; diff --git a/crates/matrix-sdk-base/src/store/mod.rs b/crates/matrix-sdk-base/src/store/mod.rs index acc0992f0..a135d782c 100644 --- a/crates/matrix-sdk-base/src/store/mod.rs +++ b/crates/matrix-sdk-base/src/store/mod.rs @@ -407,7 +407,7 @@ where /// This adds additional higher level store functionality on top of a /// `StateStore` implementation. #[derive(Debug, Clone)] -pub struct Store { +pub(crate) struct Store { pub(super) inner: Arc, session: Arc>, /// The current sync token that should be used for the next sync call. diff --git a/crates/matrix-sdk/src/client/mod.rs b/crates/matrix-sdk/src/client/mod.rs index b3776d9bf..61840003c 100644 --- a/crates/matrix-sdk/src/client/mod.rs +++ b/crates/matrix-sdk/src/client/mod.rs @@ -30,7 +30,7 @@ use futures_core::stream::Stream; use matrix_sdk_base::{ deserialized_responses::SyncResponse, media::{MediaEventContent, MediaFormat, MediaRequest, MediaThumbnailSize}, - BaseClient, Session, Store, + BaseClient, Session, StateStore, }; use matrix_sdk_common::{ instant::{Duration, Instant}, @@ -320,12 +320,12 @@ impl Client { /// Can be used with [`Client::restore_login`] to restore a previously /// logged-in session. pub fn session(&self) -> Option<&Session> { - self.store().session() + self.base_client().session() } - /// Get a reference to the store. - pub fn store(&self) -> &Store { - self.inner.base_client.store() + /// Get a reference to the state store. + pub fn store(&self) -> &dyn StateStore { + self.base_client().store() } /// Get the account of the current owner of the client. @@ -564,7 +564,7 @@ impl Client { /// /// This will return the list of joined, invited, and left rooms. pub fn rooms(&self) -> Vec { - self.store() + self.base_client() .get_rooms() .into_iter() .map(|room| room::Common::new(self.clone(), room).into()) @@ -573,7 +573,7 @@ impl Client { /// Returns the joined rooms this client knows about. pub fn joined_rooms(&self) -> Vec { - self.store() + self.base_client() .get_rooms() .into_iter() .filter_map(|room| room::Joined::new(self.clone(), room)) @@ -582,7 +582,7 @@ impl Client { /// Returns the invited rooms this client knows about. pub fn invited_rooms(&self) -> Vec { - self.store() + self.base_client() .get_stripped_rooms() .into_iter() .filter_map(|room| room::Invited::new(self.clone(), room)) @@ -591,7 +591,7 @@ impl Client { /// Returns the left rooms this client knows about. pub fn left_rooms(&self) -> Vec { - self.store() + self.base_client() .get_rooms() .into_iter() .filter_map(|room| room::Left::new(self.clone(), room)) @@ -604,7 +604,9 @@ impl Client { /// /// `room_id` - The unique id of the room that should be fetched. pub fn get_room(&self, room_id: &RoomId) -> Option { - self.store().get_room(room_id).map(|room| room::Common::new(self.clone(), room).into()) + self.base_client() + .get_room(room_id) + .map(|room| room::Common::new(self.clone(), room).into()) } /// Get a joined room with the given room id. @@ -613,7 +615,7 @@ impl Client { /// /// `room_id` - The unique id of the room that should be fetched. pub fn get_joined_room(&self, room_id: &RoomId) -> Option { - self.store().get_room(room_id).and_then(|room| room::Joined::new(self.clone(), room)) + self.base_client().get_room(room_id).and_then(|room| room::Joined::new(self.clone(), room)) } /// Get an invited room with the given room id. @@ -622,7 +624,7 @@ impl Client { /// /// `room_id` - The unique id of the room that should be fetched. pub fn get_invited_room(&self, room_id: &RoomId) -> Option { - self.store().get_room(room_id).and_then(|room| room::Invited::new(self.clone(), room)) + self.base_client().get_room(room_id).and_then(|room| room::Invited::new(self.clone(), room)) } /// Get a left room with the given room id. @@ -631,7 +633,7 @@ impl Client { /// /// `room_id` - The unique id of the room that should be fetched. pub fn get_left_room(&self, room_id: &RoomId) -> Option { - self.store().get_room(room_id).and_then(|room| room::Left::new(self.clone(), room)) + self.base_client().get_room(room_id).and_then(|room| room::Left::new(self.clone(), room)) } /// Resolve a room alias to a room id and a list of servers which know From 4e2bd14a2720b42399b9bf967d3a3b4395a7dc95 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Wed, 20 Jul 2022 11:39:15 +0200 Subject: [PATCH 73/73] chore: Silence buggy clippy lint --- crates/matrix-sdk-base/src/client.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/matrix-sdk-base/src/client.rs b/crates/matrix-sdk-base/src/client.rs index ac43bf78e..5d58c040a 100644 --- a/crates/matrix-sdk-base/src/client.rs +++ b/crates/matrix-sdk-base/src/client.rs @@ -147,6 +147,7 @@ impl BaseClient { } /// Get a reference to the store. + #[allow(unknown_lints, clippy::explicit_auto_deref)] pub fn store(&self) -> &dyn StateStore { &*self.store }