From 6e10eb9efb595f2f463022454d0af7d265dfb16b Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Wed, 12 Jul 2023 12:46:31 +0200 Subject: [PATCH] Remove matrix-sdk-crypto-js It now lives in its own repository at https://github.com/matrix-org/matrix-rust-sdk-crypto-nodejs --- .github/workflows/bindings_ci.yml | 88 +--- .github/workflows/documentation.yml | 8 - .../workflows/prep-crypto-nodejs-release.yml | 119 ----- .github/workflows/release-crypto-nodejs.yml | 139 ----- Cargo.lock | 102 ---- Cargo.toml | 1 - bindings/README.md | 15 +- bindings/matrix-sdk-crypto-nodejs/.gitignore | 7 - bindings/matrix-sdk-crypto-nodejs/.npmignore | 7 - .../matrix-sdk-crypto-nodejs/.prettierignore | 1 - .../matrix-sdk-crypto-nodejs/.prettierrc.js | 9 - .../matrix-sdk-crypto-nodejs/CHANGELOG.md | 32 -- bindings/matrix-sdk-crypto-nodejs/Cargo.toml | 45 -- bindings/matrix-sdk-crypto-nodejs/README.md | 220 -------- bindings/matrix-sdk-crypto-nodejs/build.rs | 3 - .../matrix-sdk-crypto-nodejs/download-lib.js | 121 ----- .../matrix-sdk-crypto-nodejs/package.json | 37 -- .../src/attachment.rs | 123 ----- .../src/encryption.rs | 140 ----- .../matrix-sdk-crypto-nodejs/src/errors.rs | 28 - .../matrix-sdk-crypto-nodejs/src/events.rs | 62 --- .../src/identifiers.rs | 281 ---------- bindings/matrix-sdk-crypto-nodejs/src/lib.rs | 57 --- .../matrix-sdk-crypto-nodejs/src/machine.rs | 479 ----------------- bindings/matrix-sdk-crypto-nodejs/src/olm.rs | 40 -- .../matrix-sdk-crypto-nodejs/src/requests.rs | 401 --------------- .../matrix-sdk-crypto-nodejs/src/responses.rs | 202 -------- .../src/sync_events.rs | 49 -- .../matrix-sdk-crypto-nodejs/src/tracing.rs | 11 - .../matrix-sdk-crypto-nodejs/src/types.rs | 156 ------ .../matrix-sdk-crypto-nodejs/src/vodozemac.rs | 113 ---- .../tests/attachment.test.js | 83 --- .../tests/encryption.test.js | 30 -- .../tests/events.test.js | 10 - .../tests/identifiers.test.js | 140 ----- .../tests/machine.test.js | 483 ------------------ .../tests/requests.test.js | 40 -- .../tests/responses.test.js | 9 - .../tests/sync_events.test.js | 31 -- .../matrix-sdk-crypto-nodejs/tsconfig.json | 10 - codecov.yaml | 1 - tarpaulin.toml | 1 - 42 files changed, 13 insertions(+), 3921 deletions(-) delete mode 100644 .github/workflows/prep-crypto-nodejs-release.yml delete mode 100644 .github/workflows/release-crypto-nodejs.yml delete mode 100644 bindings/matrix-sdk-crypto-nodejs/.gitignore delete mode 100644 bindings/matrix-sdk-crypto-nodejs/.npmignore delete mode 100644 bindings/matrix-sdk-crypto-nodejs/.prettierignore delete mode 100644 bindings/matrix-sdk-crypto-nodejs/.prettierrc.js delete mode 100644 bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md delete mode 100644 bindings/matrix-sdk-crypto-nodejs/Cargo.toml delete mode 100644 bindings/matrix-sdk-crypto-nodejs/README.md delete mode 100644 bindings/matrix-sdk-crypto-nodejs/build.rs delete mode 100644 bindings/matrix-sdk-crypto-nodejs/download-lib.js delete mode 100644 bindings/matrix-sdk-crypto-nodejs/package.json delete mode 100644 bindings/matrix-sdk-crypto-nodejs/src/attachment.rs delete mode 100644 bindings/matrix-sdk-crypto-nodejs/src/encryption.rs delete mode 100644 bindings/matrix-sdk-crypto-nodejs/src/errors.rs delete mode 100644 bindings/matrix-sdk-crypto-nodejs/src/events.rs delete mode 100644 bindings/matrix-sdk-crypto-nodejs/src/identifiers.rs delete mode 100644 bindings/matrix-sdk-crypto-nodejs/src/lib.rs delete mode 100644 bindings/matrix-sdk-crypto-nodejs/src/machine.rs delete mode 100644 bindings/matrix-sdk-crypto-nodejs/src/olm.rs delete mode 100644 bindings/matrix-sdk-crypto-nodejs/src/requests.rs delete mode 100644 bindings/matrix-sdk-crypto-nodejs/src/responses.rs delete mode 100644 bindings/matrix-sdk-crypto-nodejs/src/sync_events.rs delete mode 100644 bindings/matrix-sdk-crypto-nodejs/src/tracing.rs delete mode 100644 bindings/matrix-sdk-crypto-nodejs/src/types.rs delete mode 100644 bindings/matrix-sdk-crypto-nodejs/src/vodozemac.rs delete mode 100644 bindings/matrix-sdk-crypto-nodejs/tests/attachment.test.js delete mode 100644 bindings/matrix-sdk-crypto-nodejs/tests/encryption.test.js delete mode 100644 bindings/matrix-sdk-crypto-nodejs/tests/events.test.js delete mode 100644 bindings/matrix-sdk-crypto-nodejs/tests/identifiers.test.js delete mode 100644 bindings/matrix-sdk-crypto-nodejs/tests/machine.test.js delete mode 100644 bindings/matrix-sdk-crypto-nodejs/tests/requests.test.js delete mode 100644 bindings/matrix-sdk-crypto-nodejs/tests/responses.test.js delete mode 100644 bindings/matrix-sdk-crypto-nodejs/tests/sync_events.test.js delete mode 100644 bindings/matrix-sdk-crypto-nodejs/tsconfig.json diff --git a/.github/workflows/bindings_ci.yml b/.github/workflows/bindings_ci.yml index 401db957a..5f430f6b4 100644 --- a/.github/workflows/bindings_ci.yml +++ b/.github/workflows/bindings_ci.yml @@ -18,7 +18,6 @@ concurrency: env: CARGO_TERM_COLOR: always - MATRIX_SDK_CRYPTO_NODEJS_PATH: bindings/matrix-sdk-crypto-nodejs MATRIX_SDK_CRYPTO_JS_PATH: bindings/matrix-sdk-crypto-js jobs: @@ -59,16 +58,7 @@ jobs: run: target/debug/xtask ci bindings lint-js-bindings: - strategy: - fail-fast: true - matrix: - include: - - name: "[m]-crypto-nodejs" - path: "bindings/matrix-sdk-crypto-nodejs" - - name: "[m]-crypto-js" - path: "bindings/matrix-sdk-crypto-js" - - name: lint ${{ matrix.name }} + name: lint [m]-crypto-js runs-on: ubuntu-latest steps: @@ -79,85 +69,13 @@ jobs: uses: actions/setup-node@v3 - name: Install NPM dependencies - working-directory: ${{ matrix.path }} + working-directory: bindings/matrix-sdk-crypto-js run: npm install - name: run lint - working-directory: ${{ matrix.path }} + working-directory: bindings/matrix-sdk-crypto-js run: npm run lint - test-matrix-sdk-crypto-nodejs: - name: ${{ matrix.os-name }} [m]-crypto-nodejs, v${{ matrix.node-version }} - if: github.event_name == 'push' || !github.event.pull_request.draft - - runs-on: ${{ matrix.os }} - strategy: - fail-fast: true - matrix: - # Use Ubuntu LTS-1 for broader glibc compatibility. - os: [ubuntu-20.04] - node-version: [16.0, 18.0, 19.0, 20.0] - include: - - os: ubuntu-20.04 - os-name: 🐧 - - - os: macos-latest - os-name: 🍏 - node-version: 20.0 - - - node-version: 20.0 - build-doc: true - - steps: - - name: Checkout the repo - uses: actions/checkout@v3 - - - name: Install Rust - uses: dtolnay/rust-toolchain@stable - - - name: Load cache - uses: Swatinem/rust-cache@v2 - with: - save-if: ${{ github.ref == 'refs/head/main' }} - - - name: Install Node.js - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node-version }} - - - name: Install NPM dependencies - working-directory: ${{ env.MATRIX_SDK_CRYPTO_NODEJS_PATH }} - run: npm install - - - name: Build the Node.js binding - working-directory: ${{ env.MATRIX_SDK_CRYPTO_NODEJS_PATH }} - run: npm run release-build - - - name: Test the Node.js binding - working-directory: ${{ env.MATRIX_SDK_CRYPTO_NODEJS_PATH }} - run: npm run test - - # Building in dev-mode and copy lib in failure case - - name: Build the Node.js binding in non-release - if: failure() - working-directory: ${{ env.MATRIX_SDK_CRYPTO_NODEJS_PATH }} - run: | - cp *.node release-mode-lib.node - npm run build - - - uses: actions/upload-artifact@v3 - if: failure() - with: - name: Failure Files - path: | - bindings/matrix-sdk-crypto-nodejs/*.node - /var/crash/*.crash - - - if: ${{ matrix.build-doc }} - name: Build the documentation - working-directory: ${{ env.MATRIX_SDK_CRYPTO_NODEJS_PATH }} - run: npm run doc - test-matrix-sdk-crypto-js: name: 🕸 [m]-crypto-js if: github.event_name == 'push' || !github.event.pull_request.draft diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index d00aaf12c..34d128c01 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -48,12 +48,6 @@ jobs: run: cargo doc --no-deps --workspace --features docsrs - - name: Build `matrix-sdk-crypto-nodejs` doc - run: | - cd bindings/matrix-sdk-crypto-nodejs - npm install - npm run build && npm run doc - - name: Build `matrix-sdk-crypto-js` doc run: | cd bindings/matrix-sdk-crypto-js @@ -63,10 +57,8 @@ jobs: - name: Prepare the doc hierarchy shell: bash run: | - mkdir -p doc/bindings/matrix-sdk-crypto-nodejs/ mkdir -p doc/bindings/matrix-sdk-crypto-js/ mv target/doc/* doc/ - mv bindings/matrix-sdk-crypto-nodejs/docs/* doc/bindings/matrix-sdk-crypto-nodejs/ mv bindings/matrix-sdk-crypto-js/docs/* doc/bindings/matrix-sdk-crypto-js/ - name: Deploy documentation diff --git a/.github/workflows/prep-crypto-nodejs-release.yml b/.github/workflows/prep-crypto-nodejs-release.yml deleted file mode 100644 index d0e609994..000000000 --- a/.github/workflows/prep-crypto-nodejs-release.yml +++ /dev/null @@ -1,119 +0,0 @@ -name: Prepare Crypto-Node.js Release -# -# This is a helper workflow to craft a new Node.js release, trigger this via -# the Github Workflow UI by dispatching it manually. Provide the version, the -# matrix-sdk-crypto-nodejs npm package should be set to, and a optionally the -# old version (as used in the git tag) this release should be compared to. -# -# This will then: -# 1. bump the npm version to the one you specified -# 2. commit that change together with the changelog (if it changed, see below) -# 3. create the appropriate tag on that commit -# 4. create the Github draft release, including the changes (if given, see below) -# 5. push these to a new branch, including tag, triggering the `release-crypto-nodejs` workflow -# 6. create a PR to merge these back into `main` -# -# Additionally, if you provide a tag to comapare this tag to, this will: -# 1. create a changelog between the two releases, used for the github release -# 2. update the Changelog.md and include it in the commit -# -# The remaining tasks are done by the release-crypto-nodejs workflow. - -on: - workflow_dispatch: - inputs: - version: - description: 'New Node.js SemVer version to create' - required: true - type: string - previous_version: - description: 'Create the changelog by comparing to this old SemVer Version (as used in the tag) ' - type: string - -env: - PKG_PATH: "bindings/matrix-sdk-crypto-nodejs" - TAG_PREFIX: "matrix-sdk-crypto-nodejs-v" - -jobs: - prepare-release: - name: "Preparing crypto-nodejs release tag" - runs-on: ubuntu-latest - outputs: - tag: "${{ env.TAG_PREFIX }}${{ inputs.version }}" - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - - # Generate changelog since last tag, if given - - name: Generate a changelog for upload - if: inputs.previous_version - uses: orhun/git-cliff-action@v1 - with: - config: "${{ env.PKG_PATH }}/cliff.toml" - args: --strip header "${{env.TAG_PREFIX}}${{ inputs.previous_version }}..HEAD" - env: - GIT_CLIFF_TAG: "Changes ${{ inputs.previous_version }} -> ${{ inputs.version }}" - GIT_CLIFF_OUTPUT: "${{ env.PKG_PATH }}/CHANGES-${{ inputs.version }}.md" - - # Update changelog since last tag, if given - - name: Update existing Changelog - if: inputs.previous_version - uses: orhun/git-cliff-action@v1 - with: - config: "${{ env.PKG_PATH }}/cliff.toml" - args: "${{env.TAG_PREFIX}}${{ inputs.previous_version }}..HEAD" - env: - GIT_CLIFF_TAG: "${{ inputs.version }}" - GIT_CLIFF_PREPEND: "${{ env.PKG_PATH }}/CHANGELOG.md" - - - name: Set version - id: package_version - working-directory: ${{ env.PKG_PATH }} - run: npm version ${{ inputs.version }} - - - uses: EndBug/add-and-commit@v9 - with: - default_author: github_actions - message: "Tagging Crypto-Node.js for release" - tag: "${{env.TAG_PREFIX}}${{ inputs.version }}" - new_branch: "gh-action/release-${{ env.TAG_PREFIX }}${{ inputs.version }}" - push: true - add: | - ${{ env.PKG_PATH }}/package.json - ${{ env.PKG_PATH }}/CHANGELOG.md - - # if we have generated changes - - name: Update Github Release notes - if: inputs.previous_version - uses: softprops/action-gh-release@v1 - with: - draft: true - tag_name: ${{ env.TAG_PREFIX }}${{ inputs.version }} - body_path: "${{ env.PKG_PATH }}/CHANGES-${{ inputs.version }}.md" - - # no changes, use the default changelog for the body - - name: Update Github Release notes - if: ${{!inputs.previous_version}} - uses: softprops/action-gh-release@v1 - with: - draft: true - tag_name: ${{ env.TAG_PREFIX }}${{ inputs.version }} - body_path: "${{ env.PKG_PATH }}/CHANGELOG.md" - - # let's create a PR for all this, too - - name: Create Pull Request - uses: peter-evans/create-pull-request@v4 - with: - title: "Preparing Release ${{ env.TAG_PREFIX }}${{ inputs.version }}" - body: | - Automatic Pull-Request to merge release ${{ env.TAG_PREFIX }}${{ inputs.version }} - - trigger-release: - # and trigger the tagging release workflow - uses: ./.github/workflows/release-crypto-nodejs.yml - needs: ['prepare-release'] - name: "Trigger release Workflow" - with: - tag: ${{needs.prepare-release.outputs.tag}} - secrets: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/release-crypto-nodejs.yml b/.github/workflows/release-crypto-nodejs.yml deleted file mode 100644 index 8195b5402..000000000 --- a/.github/workflows/release-crypto-nodejs.yml +++ /dev/null @@ -1,139 +0,0 @@ -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]+.* - workflow_call: - inputs: - tag: - description: "The tag to build with" - required: true - type: string - secrets: - NPM_TOKEN: - required: true - -jobs: - upload-assets: - name: "Upload prebuilt libraries" - strategy: - fail-fast: false - matrix: - include: - # ----------------------------------- Linux - # Use Ubuntu LTS-1 for broader glibc compatibility. - - target: x86_64-unknown-linux-gnu - os: ubuntu-20.04 - - target: i686-unknown-linux-gnu - apt_install: gcc-i686-linux-gnu g++-i686-linux-gnu - os: ubuntu-20.04 - - target: aarch64-unknown-linux-gnu - os: ubuntu-20.04 - apt_install: gcc-aarch64-linux-gnu g++-aarch64-linux-gnu - - target: arm-unknown-linux-gnueabihf - os: ubuntu-20.04 - apt_install: gcc-arm-linux-gnueabihf - - target: x86_64-unknown-linux-musl - os: ubuntu-20.04 - apt_install: musl-tools - # ----------------------------------- 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: - # 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: dtolnay/rust-toolchain@master - with: - toolchain: nightly-2023-07-03 - targets: ${{ matrix.target }} - - name: Install Node.js - uses: actions/setup-node@v3 - - if: ${{ matrix.apt_install }} - run: | - sudo apt-get update - sudo apt-get install -y ${{ matrix.apt_install }} - - name: Build lib - working-directory: ${{env.PKG_PATH}} - run: | - npm install --ignore-scripts - npx napi build --platform --release --strip --target ${{ matrix.target }} - - name: Upload artifacts to release - uses: softprops/action-gh-release@v1 - with: - draft: true - files: ${{env.PKG_PATH}}/*.node - - publish-nodejs-package: - name: "Package nodejs package" - runs-on: ubuntu-latest - needs: - - upload-assets - steps: - # 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: dtolnay/rust-toolchain@master - with: - toolchain: nightly-2023-07-03 - - name: Install Node.js - uses: actions/setup-node@v3 - - name: Build lib - working-directory: ${{env.PKG_PATH}} - run: | - npm install --ignore-scripts - npm run build - npm pack - - name: Upload npm package to release - uses: softprops/action-gh-release@v1 - with: - draft: true - files: ${{env.PKG_PATH}}/*tgz - - name: Publish to npmjs.com - uses: JS-DevTools/npm-publish@v1 - with: - package: ${{env.PKG_PATH}}/package.json - access: public - token: ${{ secrets.NPM_TOKEN }} diff --git a/Cargo.lock b/Cargo.lock index e59db9f27..245afe959 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -956,15 +956,6 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "core-foundation" version = "0.9.3" @@ -2402,16 +2393,6 @@ version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if", - "winapi", -] - [[package]] name = "libm" version = "0.2.7" @@ -2756,24 +2737,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "matrix-sdk-crypto-nodejs" -version = "0.6.0" -dependencies = [ - "http", - "matrix-sdk-common", - "matrix-sdk-crypto", - "matrix-sdk-sqlite", - "napi", - "napi-build", - "napi-derive", - "ruma", - "serde_json", - "tracing-subscriber", - "vodozemac", - "zeroize", -] - [[package]] name = "matrix-sdk-ffi" version = "0.2.0" @@ -3082,64 +3045,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "napi" -version = "2.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ede2d12cd6fce44da537a4be1f5510c73be2506c2e32dfaaafd1f36968f3a0e" -dependencies = [ - "bitflags 2.3.3", - "ctor", - "napi-derive", - "napi-sys", - "once_cell", - "tokio", -] - -[[package]] -name = "napi-build" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882a73d9ef23e8dc2ebbffb6a6ae2ef467c0f18ac10711e4cc59c5485d41df0e" - -[[package]] -name = "napi-derive" -version = "2.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da1c6a8fa84d549aa8708fcd062372bf8ec6e849de39016ab921067d21bde367" -dependencies = [ - "cfg-if", - "convert_case", - "napi-derive-backend", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "napi-derive-backend" -version = "1.0.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20bbc7c69168d06a848f925ec5f0e0997f98e8c8d4f2cc30157f0da51c009e17" -dependencies = [ - "convert_case", - "once_cell", - "proc-macro2", - "quote", - "regex", - "semver", - "syn 1.0.109", -] - -[[package]] -name = "napi-sys" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "166b5ef52a3ab5575047a9fe8d4a030cdd0f63c96f071cd6907674453b07bae3" -dependencies = [ - "libloading", -] - [[package]] name = "native-tls" version = "0.2.11" @@ -5268,7 +5173,6 @@ dependencies = [ "sharded-slab", "smallvec", "thread_local", - "time 0.3.22", "tracing", "tracing-core", "tracing-log", @@ -5337,12 +5241,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - [[package]] name = "unicode-xid" version = "0.2.4" diff --git a/Cargo.toml b/Cargo.toml index 42f971848..b9b3b6835 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,6 @@ members = [ "benchmarks", "bindings/matrix-sdk-crypto-ffi", "bindings/matrix-sdk-crypto-js", - "bindings/matrix-sdk-crypto-nodejs", "bindings/matrix-sdk-ffi", "crates/*", "testing/*", diff --git a/bindings/README.md b/bindings/README.md index a6bfd8975..372509ce3 100644 --- a/bindings/README.md +++ b/bindings/README.md @@ -9,17 +9,22 @@ maintained by the owners of the Matrix Rust SDK project. crate, * [`matrix-sdk-crypto-js`], JavaScript bindings of the [`matrix-sdk-crypto`] crate, -* [`matrix-sdk-crypto-nodejs`], Node.js bindings of the - [`matrix-sdk-crypto`] crate, * [`matrix-sdk-ffi`], UniFFI bindings of the [`matrix-sdk`] crate. +There are also external bindings in other repositories: + +* [`matrix-sdk-crypto-nodejs`], Node.js bindings of the + [`matrix-sdk-crypto`] crate + [`apple`]: ./apple [`matrix-sdk-crypto-ffi`]: ./matrix-sdk-crypto-ffi [`matrix-sdk-crypto-js`]: ./matrix-sdk-crypto-js -[`matrix-sdk-crypto-nodejs`]: ./matrix-sdk-crypto-nodejs [`matrix-sdk-crypto`]: ../crates/matrix-sdk-crypto [`matrix-sdk-ffi`]: ./matrix-sdk-ffi [`matrix-sdk`]: ../crates/matrix-sdk -# Contributing -To contribute read this [guide](./CONTRIBUTING.md). \ No newline at end of file +[`matrix-sdk-crypto-nodejs`]: https://github.com/matrix-org/matrix-rust-sdk-crypto-nodejs + +## Contributing + +To contribute read this [guide](./CONTRIBUTING.md). diff --git a/bindings/matrix-sdk-crypto-nodejs/.gitignore b/bindings/matrix-sdk-crypto-nodejs/.gitignore deleted file mode 100644 index 4dc1f7592..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -/node_modules -/package-lock.json -/index.js -/index.d.ts -/matrix-sdk-crypto.*.node -/docs/* -*.tgz diff --git a/bindings/matrix-sdk-crypto-nodejs/.npmignore b/bindings/matrix-sdk-crypto-nodejs/.npmignore deleted file mode 100644 index cebcc362e..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/.npmignore +++ /dev/null @@ -1,7 +0,0 @@ -src/ -tests/ -Cargo.toml -build.rs -*.node -*.tgz -tsconfig.json diff --git a/bindings/matrix-sdk-crypto-nodejs/.prettierignore b/bindings/matrix-sdk-crypto-nodejs/.prettierignore deleted file mode 100644 index fc5bd9083..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/.prettierignore +++ /dev/null @@ -1 +0,0 @@ -/pkg diff --git a/bindings/matrix-sdk-crypto-nodejs/.prettierrc.js b/bindings/matrix-sdk-crypto-nodejs/.prettierrc.js deleted file mode 100644 index f739c10be..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/.prettierrc.js +++ /dev/null @@ -1,9 +0,0 @@ -// prettier configuration: the same as the conventions used throughout Matrix.org -// see: https://github.com/matrix-org/eslint-plugin-matrix-org/blob/main/.prettierrc.js - -module.exports = { - printWidth: 120, - tabWidth: 4, - quoteProps: "consistent", - trailingComma: "all", -}; diff --git a/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md b/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md deleted file mode 100644 index ad372b52f..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/CHANGELOG.md +++ /dev/null @@ -1,32 +0,0 @@ -# Matrix-Rust-SDK Node.js Bindings - -## 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 -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). diff --git a/bindings/matrix-sdk-crypto-nodejs/Cargo.toml b/bindings/matrix-sdk-crypto-nodejs/Cargo.toml deleted file mode 100644 index cfd5c7684..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -authors = ["Ivan Enderlin "] -description = "Matrix encryption library, for NodeJS" -edition = "2021" -homepage = "https://github.com/matrix-org/matrix-rust-sdk" -keywords = ["matrix", "chat", "messaging", "ruma", "nio"] -license = "Apache-2.0" -name = "matrix-sdk-crypto-nodejs" -readme = "README.md" -repository = "https://github.com/matrix-org/matrix-rust-sdk" -rust-version = { workspace = true } -version = "0.6.0" - -[package.metadata.docs.rs] -rustdoc-args = ["--cfg", "docsrs"] - -[lib] -crate-type = ["cdylib"] - -[features] -default = ["bundled-sqlite"] -bundled-sqlite = ["matrix-sdk-sqlite/bundled"] -qrcode = ["matrix-sdk-crypto/qrcode"] -tracing = ["dep:tracing-subscriber"] - -[dependencies] -matrix-sdk-common = { version = "0.6.0", path = "../../crates/matrix-sdk-common", features = ["js"] } -matrix-sdk-sqlite = { version = "0.1.0", path = "../../crates/matrix-sdk-sqlite", features = ["crypto-store"] } -ruma = { workspace = true, features = ["rand"] } -napi = { version = "2.9.1", default-features = false, features = ["napi6", "tokio_rt"] } -napi-derive = "2.9.1" -serde_json = { workspace = true } -http = { workspace = true } -tracing-subscriber = { version = "0.3", default-features = false, features = ["tracing-log", "time", "smallvec", "fmt", "env-filter"], optional = true } -vodozemac = { workspace = true, features = ["js"] } -zeroize = { workspace = true } - -[dependencies.matrix-sdk-crypto] -path = "../../crates/matrix-sdk-crypto" -version = "0.6.0" -default_features = false -features = ["js", "automatic-room-key-forwarding"] - -[build-dependencies] -napi-build = "2.0.0" diff --git a/bindings/matrix-sdk-crypto-nodejs/README.md b/bindings/matrix-sdk-crypto-nodejs/README.md deleted file mode 100644 index e9b98ddbf..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/README.md +++ /dev/null @@ -1,220 +0,0 @@ -# `matrix-sdk-crypto-nodejs` - -Welcome to the [Node.js] binding for the Rust [`matrix-sdk-crypto`] -library! This binding is part of the [`matrix-rust-sdk`] project, -which is a library implementation of a [Matrix] client-server. - -`matrix-sdk-crypto-nodejs` is a no-network-IO implementation of a -state machine, named `OlmMachine`, that handles E2EE ([End-to-End -Encryption](https://en.wikipedia.org/wiki/End-to-end_encryption)) for -[Matrix] clients. - -## Usage - -Just add the latest release to your `package.json`: - -```sh -$ npm install --save @matrix-org/matrix-sdk-crypto-nodejs -``` - -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 -pretty classical by using [npm], see [the Downloading and installing -Node.js and npm -Page](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). - -The binding is compatible with, and tested against, the Node.js -versions that are in “current”, “active” or “maintenance” states, -according to [the Node.js Releases -Page](https://nodejs.org/en/about/releases/), _and_ which are -compatible with [NAPI v6 (Node.js -API)](https://nodejs.org/api/n-api.html#node-api-version-matrix). It -means that this binding will work with the following versions: 16.0.0, -18.0.0, 19.0.0 and 20.0.0. - -Once the Rust compiler, Node.js and npm are installed, you can run the -following commands: - -```sh -$ npm install --ignore-scripts -$ npm run build -$ npm run test -``` - -An `index.js`, `index.d.ts` and a `*.node` files should be -generated. At the same level of those files, you can edit a file and -try this: - -```javascript -const { OlmMachine } = require("./index.js"); - -// Let's see what we can do. -``` - -The `OlmMachine` state machine works in a push/pull manner: - -- You push state changes and events retrieved from a Matrix homeserver - `/sync` response, into the state machine, -- You pull requests that you will need to send back to the homeserver - out of the state machine. - -```javascript -const { OlmMachine, UserId, DeviceId, RoomId, DeviceLists } = require("./index.js"); - -async function main() { - // Define a user ID. - const alice = new UserId("@alice:example.org"); - - // Define a device ID. - const device = new DeviceId("DEVICEID"); - - // Let's create the `OlmMachine` state machine. - const machine = await OlmMachine.initialize(alice, device); - - // Let's pretend we have received changes and events from a - // `/sync` endpoint of a Matrix homeserver, … - const toDeviceEvents = "[]"; // JSON-encoded list of events - const changedDevices = new DeviceLists(); - const oneTimeKeyCounts = {}; - const unusedFallbackKeys = []; - - // … and push them into the state machine. - const decryptedToDevice = await machine.receiveSyncChanges( - toDeviceEvents, - changedDevices, - oneTimeKeyCounts, - unusedFallbackKeys, - ); - - // Now, let's pull requests that we need to send out to the Matrix - // homeserver. - const outgoingRequests = await machine.outgoingRequests(); - - // To complete the workflow, send the requests here out and call - // `machine.markRequestAsSent`. -} - -main(); -``` - -### With tracing (experimental) - -If you want to enable [tracing](https://tracing.rs), i.e. to get the -logs, you should re-compile the extension with the `tracing` feature -turned on: - -```sh -$ npm run build -- --features tracing -``` - -Now, you can use the `MATRIX_LOG` environment variable to tweak the log filtering, such as: - -```sh -$ MATRIX_LOG=debug npm run test -``` - -See -[`tracing-subscriber`](https://tracing.rs/tracing_subscriber/index.html) -to learn more about the `RUST_LOG`/`MATRIX_LOG` environment variable. - -#### Using tracing in dependent projects - -To enable tracing in client applications that import these bindings, here's how to do it in -a local development environment: - -- In this directory, run `npm link` to make your local build of the bindings available to - other Node projects on your system -- In your client app's source directory, run `npm link @matrix-org/matrix-sdk-crypto-nodejs` - to make it use your trace-enabled local build of the bindings -- In your client app's source code, add a call to `initTracing` near startup time -- Run your app with the `MATRIX_LOG` environment variable set to the desired log level - -Either `npm link` command may be substituted with `yarn link`. - -## Documentation - -[The documentation can be found -online](https://matrix-org.github.io/matrix-rust-sdk/bindings/matrix-sdk-crypto-nodejs/). - -To generate the documentation locally, please run the following -command: - -```sh -$ npm run doc -``` - -The documentation is generated in the `./docs` directory. - -[Node.js]: https://nodejs.org/ -[`matrix-sdk-crypto`]: https://github.com/matrix-org/matrix-rust-sdk/tree/main/crates/matrix-sdk-crypto -[`matrix-rust-sdk`]: https://github.com/matrix-org/matrix-rust-sdk -[Matrix]: https://matrix.org/ -[Rust]: https://www.rust-lang.org/ -[npm]: https://www.npmjs.com/ diff --git a/bindings/matrix-sdk-crypto-nodejs/build.rs b/bindings/matrix-sdk-crypto-nodejs/build.rs deleted file mode 100644 index 0f1b01002..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - napi_build::setup(); -} diff --git a/bindings/matrix-sdk-crypto-nodejs/download-lib.js b/bindings/matrix-sdk-crypto-nodejs/download-lib.js deleted file mode 100644 index c23719e30..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/download-lib.js +++ /dev/null @@ -1,121 +0,0 @@ -const { HttpsProxyAgent } = require("https-proxy-agent"); -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-v${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, - }); - - const proxy = process.env.https_proxy ?? process.env.HTTPS_PROXY; - if (proxy) { - const proxyAgent = new HttpsProxyAgent(proxy); - dl.updateOptions({ - httpsRequestOptions: { agent: proxyAgent }, - }); - } - - 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 deleted file mode 100644 index 36de43e42..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "@matrix-org/matrix-sdk-crypto-nodejs", - "version": "0.1.0-beta.1", - "main": "index.js", - "types": "index.d.ts", - "napi": { - "name": "matrix-sdk-crypto", - "triples": { - "additional": [ - "aarch64-apple-darwin" - ] - } - }, - "license": "Apache-2.0", - "devDependencies": { - "@napi-rs/cli": "^2.9.0", - "jest": "^28.1.0", - "prettier": "^2.8.3", - "typedoc": "^0.22.17", - "yargs-parser": "~21.0.1" - }, - "engines": { - "node": ">= 16" - }, - "scripts": { - "lint": "prettier --check .", - "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": { - "https-proxy-agent": "^5.0.1", - "node-downloader-helper": "^2.1.5" - } -} diff --git a/bindings/matrix-sdk-crypto-nodejs/src/attachment.rs b/bindings/matrix-sdk-crypto-nodejs/src/attachment.rs deleted file mode 100644 index f0f2c9b2e..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/src/attachment.rs +++ /dev/null @@ -1,123 +0,0 @@ -use std::{ - io::{Cursor, Read}, - ops::Deref, -}; - -use napi::bindgen_prelude::Uint8Array; -use napi_derive::*; - -use crate::into_err; - -/// A type to encrypt and to decrypt anything that can fit in an -/// `Uint8Array`, usually big buffer. -#[napi] -pub struct Attachment; - -#[napi] -impl Attachment { - /// Encrypt the content of the `Uint8Array`. - /// - /// It produces an `EncryptedAttachment`, which can be used to - /// retrieve the media encryption information, or the encrypted - /// data. - #[napi] - pub fn encrypt(array: Uint8Array) -> napi::Result { - let buffer: &[u8] = array.deref(); - - let mut cursor = Cursor::new(buffer); - let mut encryptor = matrix_sdk_crypto::AttachmentEncryptor::new(&mut cursor); - - let mut encrypted_data = Vec::new(); - encryptor.read_to_end(&mut encrypted_data).map_err(into_err)?; - - let media_encryption_info = Some(encryptor.finish()); - - Ok(EncryptedAttachment { - encrypted_data: Uint8Array::new(encrypted_data), - media_encryption_info, - }) - } - - /// Decrypt an `EncryptedAttachment`. - /// - /// The encrypted attachment can be created manually, or from the - /// `encrypt` method. - /// - /// **Warning**: The encrypted attachment can be used only - /// **once**! The encrypted data will still be present, but the - /// media encryption info (which contain secrets) will be - /// destroyed. It is still possible to get a JSON-encoded backup - /// by calling `EncryptedAttachment.mediaEncryptionInfo`. - #[napi] - pub fn decrypt(attachment: &mut EncryptedAttachment) -> napi::Result { - let Some(media_encryption_info) = attachment.media_encryption_info.take() else { - return Err(napi::Error::from_reason( - "The media encryption info are absent from the given encrypted attachment" - .to_owned(), - )); - }; - - let encrypted_data: &[u8] = attachment.encrypted_data.deref(); - - let mut cursor = Cursor::new(encrypted_data); - let mut decryptor = - matrix_sdk_crypto::AttachmentDecryptor::new(&mut cursor, media_encryption_info) - .map_err(into_err)?; - - let mut decrypted_data = Vec::new(); - decryptor.read_to_end(&mut decrypted_data).map_err(into_err)?; - - Ok(Uint8Array::new(decrypted_data)) - } -} - -/// An encrypted attachment, usually created from `Attachment.encrypt`. -#[napi] -pub struct EncryptedAttachment { - media_encryption_info: Option, - - /// The actual encrypted data. - pub encrypted_data: Uint8Array, -} - -#[napi] -impl EncryptedAttachment { - /// Create a new encrypted attachment manually. - /// - /// It needs encrypted data, stored in an `Uint8Array`, and a - /// [media encryption - /// information](https://docs.rs/matrix-sdk-crypto/latest/matrix_sdk_crypto/struct.MediaEncryptionInfo.html), - /// as a JSON-encoded string. - /// - /// The media encryption information aren't stored as a string: - /// they are parsed, validated and fully deserialized. - /// - /// See [the specification to learn - /// more](https://spec.matrix.org/unstable/client-server-api/#extensions-to-mroommessage-msgtypes). - #[napi(constructor)] - pub fn new(encrypted_data: Uint8Array, media_encryption_info: String) -> napi::Result { - Ok(Self { - encrypted_data, - media_encryption_info: Some( - serde_json::from_str(media_encryption_info.as_str()).map_err(into_err)?, - ), - }) - } - - /// Return the media encryption info as a JSON-encoded string. The - /// structure is fully valid. - /// - /// If the media encryption info have been consumed already, it - /// will return `null`. - #[napi(getter)] - pub fn media_encryption_info(&self) -> Option { - serde_json::to_string(self.media_encryption_info.as_ref()?).ok() - } - - /// Check whether the media encryption info has been consumed by - /// `Attachment.decrypt` already. - #[napi(getter)] - pub fn has_media_encryption_info_been_consumed(&self) -> bool { - self.media_encryption_info.is_none() - } -} diff --git a/bindings/matrix-sdk-crypto-nodejs/src/encryption.rs b/bindings/matrix-sdk-crypto-nodejs/src/encryption.rs deleted file mode 100644 index 69ce50052..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/src/encryption.rs +++ /dev/null @@ -1,140 +0,0 @@ -use std::time::Duration; - -use matrix_sdk_common::deserialized_responses::ShieldState as RustShieldState; -use napi::bindgen_prelude::{BigInt, FromNapiValue, ToNapiValue}; -use napi_derive::*; - -use crate::events; - -/// An encryption algorithm to be used to encrypt messages sent to a -/// room. -#[napi] -pub enum EncryptionAlgorithm { - /// Olm version 1 using Curve25519, AES-256, and SHA-256. - OlmV1Curve25519AesSha2, - - /// Megolm version 1 using AES-256 and SHA-256. - MegolmV1AesSha2, -} - -impl From for matrix_sdk_crypto::types::EventEncryptionAlgorithm { - fn from(value: EncryptionAlgorithm) -> Self { - use EncryptionAlgorithm::*; - - match value { - OlmV1Curve25519AesSha2 => Self::OlmV1Curve25519AesSha2, - MegolmV1AesSha2 => Self::MegolmV1AesSha2, - } - } -} - -impl From for EncryptionAlgorithm { - fn from(value: matrix_sdk_crypto::types::EventEncryptionAlgorithm) -> Self { - use matrix_sdk_crypto::types::EventEncryptionAlgorithm::*; - - match value { - OlmV1Curve25519AesSha2 => Self::OlmV1Curve25519AesSha2, - MegolmV1AesSha2 => Self::MegolmV1AesSha2, - _ => unreachable!("Unknown variant"), - } - } -} - -/// Settings for an encrypted room. -/// -/// This determines the algorithm and rotation periods of a group -/// session. -#[napi] -pub struct EncryptionSettings { - /// The encryption algorithm that should be used in the room. - pub algorithm: EncryptionAlgorithm, - - /// How long the session should be used before changing it, - /// expressed in microseconds. - pub rotation_period: BigInt, - - /// How many messages should be sent before changing the session. - pub rotation_period_messages: BigInt, - - /// The history visibility of the room when the session was - /// created. - pub history_visibility: events::HistoryVisibility, - - /// Should untrusted devices receive the room key, or should they be - /// excluded from the conversation. - pub only_allow_trusted_devices: bool, -} - -impl Default for EncryptionSettings { - fn default() -> Self { - let default = matrix_sdk_crypto::olm::EncryptionSettings::default(); - - Self { - algorithm: default.algorithm.into(), - rotation_period: { - let n: u64 = default.rotation_period.as_micros().try_into().unwrap(); - - n.into() - }, - rotation_period_messages: { - let n = default.rotation_period_msgs; - - n.into() - }, - history_visibility: default.history_visibility.into(), - only_allow_trusted_devices: default.only_allow_trusted_devices, - } - } -} - -#[napi] -impl EncryptionSettings { - /// Create a new `EncryptionSettings` with default values. - #[napi(constructor)] - pub fn new() -> EncryptionSettings { - Self::default() - } -} - -impl From<&EncryptionSettings> for matrix_sdk_crypto::olm::EncryptionSettings { - fn from(value: &EncryptionSettings) -> Self { - Self { - algorithm: value.algorithm.into(), - rotation_period: Duration::from_micros(value.rotation_period.get_u64().1), - rotation_period_msgs: value.rotation_period_messages.get_u64().1, - history_visibility: value.history_visibility.into(), - only_allow_trusted_devices: value.only_allow_trusted_devices, - } - } -} - -/// Take a look at [`matrix_sdk_common::deserialized_responses::ShieldState`] -/// for more info. -#[napi] -pub enum ShieldColor { - Red, - Grey, - None, -} - -/// Take a look at [`matrix_sdk_common::deserialized_responses::ShieldState`] -/// for more info. -#[napi] -pub struct ShieldState { - pub color: ShieldColor, - pub message: Option<&'static str>, -} - -impl From for ShieldState { - fn from(value: RustShieldState) -> Self { - match value { - RustShieldState::Red { message } => { - ShieldState { color: ShieldColor::Red, message: Some(message) } - } - RustShieldState::Grey { message } => { - ShieldState { color: ShieldColor::Grey, message: Some(message) } - } - RustShieldState::None => ShieldState { color: ShieldColor::None, message: None }, - } - } -} diff --git a/bindings/matrix-sdk-crypto-nodejs/src/errors.rs b/bindings/matrix-sdk-crypto-nodejs/src/errors.rs deleted file mode 100644 index 758bef063..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/src/errors.rs +++ /dev/null @@ -1,28 +0,0 @@ -/// Generic error wrapping `napi::Error`. -#[derive(Debug)] -pub struct Error(napi::Error); - -impl From for Error -where - E: std::error::Error, -{ - fn from(error: E) -> Self { - Self(napi::Error::from_reason(error.to_string())) - } -} - -impl From for napi::Error { - #[inline] - fn from(value: Error) -> Self { - value.0 - } -} - -/// Helper to replace the `E` to `Error` to `napi::Error` conversion. -#[inline] -pub fn into_err(error: E) -> napi::Error -where - E: std::error::Error, -{ - Error::from(error).into() -} diff --git a/bindings/matrix-sdk-crypto-nodejs/src/events.rs b/bindings/matrix-sdk-crypto-nodejs/src/events.rs deleted file mode 100644 index aca9d4da4..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/src/events.rs +++ /dev/null @@ -1,62 +0,0 @@ -//! Types related to events. - -use napi::bindgen_prelude::{FromNapiValue, ToNapiValue}; -use napi_derive::*; -use ruma::events::room::history_visibility::HistoryVisibility as RumaHistoryVisibility; - -/// Who can see a room's history. -#[napi] -#[derive(Debug)] -pub enum HistoryVisibility { - /// Previous events are accessible to newly joined members from - /// the point they were invited onwards. - /// - /// Events stop being accessible when the member's state changes - /// to something other than *invite* or *join*. - Invited, - - /// Previous events are accessible to newly joined members from - /// the point they joined the room onwards. - /// - /// Events stop being accessible when the member's state changes - /// to something other than *join*. - Joined, - - /// Previous events are always accessible to newly joined members. - /// - /// All events in the room are accessible, even those sent when - /// the member was not a part of the room. - Shared, - - /// All events while this is the `HistoryVisibility` value may be - /// shared by any participating homeserver with anyone, regardless - /// of whether they have ever joined the room. - WorldReadable, -} - -impl From for RumaHistoryVisibility { - fn from(value: HistoryVisibility) -> Self { - use HistoryVisibility::*; - - match value { - Invited => Self::Invited, - Joined => Self::Joined, - Shared => Self::Shared, - WorldReadable => Self::WorldReadable, - } - } -} - -impl From for HistoryVisibility { - fn from(value: RumaHistoryVisibility) -> Self { - use RumaHistoryVisibility::*; - - match value { - Invited => Self::Invited, - Joined => Self::Joined, - Shared => Self::Shared, - WorldReadable => Self::WorldReadable, - _ => unreachable!("Unknown variant"), - } - } -} diff --git a/bindings/matrix-sdk-crypto-nodejs/src/identifiers.rs b/bindings/matrix-sdk-crypto-nodejs/src/identifiers.rs deleted file mode 100644 index c7b8f1025..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/src/identifiers.rs +++ /dev/null @@ -1,281 +0,0 @@ -//! Types for [Matrix](https://matrix.org/) identifiers for devices, -//! events, keys, rooms, servers, users and URIs. - -use napi::bindgen_prelude::{FromNapiValue, ToNapiValue}; -use napi_derive::*; - -use crate::into_err; - -/// A Matrix [user ID]. -/// -/// [user ID]: https://spec.matrix.org/v1.2/appendices/#user-identifiers -#[napi] -#[derive(Debug, Clone)] -pub struct UserId { - pub(crate) inner: ruma::OwnedUserId, -} - -impl From for UserId { - fn from(inner: ruma::OwnedUserId) -> Self { - Self { inner } - } -} - -#[napi] -impl UserId { - /// Parse/validate and create a new `UserId`. - #[napi(constructor, strict)] - pub fn new(id: String) -> napi::Result { - Ok(Self::from(ruma::UserId::parse(id.as_str()).map_err(into_err)?)) - } - - /// Returns the user's localpart. - #[napi(getter)] - pub fn localpart(&self) -> String { - self.inner.localpart().to_owned() - } - - /// Returns the server name of the user ID. - #[napi(getter)] - pub fn server_name(&self) -> ServerName { - ServerName { inner: self.inner.server_name().to_owned() } - } - - /// Whether this user ID is a historical one. - /// - /// A historical user ID is one that doesn't conform to the latest - /// specification of the user ID grammar but is still accepted - /// because it was previously allowed. - #[napi] - pub fn is_historical(&self) -> bool { - self.inner.is_historical() - } - - /// Return the user ID as a string. - #[napi] - #[allow(clippy::inherent_to_string)] - pub fn to_string(&self) -> String { - self.inner.as_str().to_owned() - } -} - -/// A Matrix device ID. -/// -/// Device identifiers in Matrix are completely opaque character -/// sequences. This type is provided simply for its semantic value. -#[napi] -#[derive(Debug, Clone)] -pub struct DeviceId { - pub(crate) inner: ruma::OwnedDeviceId, -} - -impl From for DeviceId { - fn from(inner: ruma::OwnedDeviceId) -> Self { - Self { inner } - } -} - -#[napi] -impl DeviceId { - /// Create a new `DeviceId`. - #[napi(constructor, strict)] - pub fn new(id: String) -> Self { - Self::from(Into::::into(id)) - } - - /// Return the device ID as a string. - #[napi] - #[allow(clippy::inherent_to_string)] - pub fn to_string(&self) -> String { - self.inner.as_str().to_owned() - } -} - -/// A Matrix device key ID. -/// -/// A key algorithm and a device ID, combined with a ‘:’. -#[napi] -#[derive(Debug, Clone)] -pub struct DeviceKeyId { - pub(crate) inner: ruma::OwnedDeviceKeyId, -} - -impl From for DeviceKeyId { - fn from(inner: ruma::OwnedDeviceKeyId) -> Self { - Self { inner } - } -} - -#[napi] -impl DeviceKeyId { - /// Parse/validate and create a new `DeviceKeyId`. - #[napi(constructor, strict)] - pub fn new(id: String) -> napi::Result { - Ok(Self::from(ruma::DeviceKeyId::parse(id.as_str()).map_err(into_err)?)) - } - - /// Returns key algorithm of the device key ID. - #[napi(getter)] - pub fn algorithm(&self) -> DeviceKeyAlgorithm { - self.inner.algorithm().into() - } - - /// Returns device ID of the device key ID. - #[napi(getter)] - pub fn device_id(&self) -> DeviceId { - self.inner.device_id().to_owned().into() - } - - /// Return the device key ID as a string. - #[napi] - #[allow(clippy::inherent_to_string)] - pub fn to_string(&self) -> String { - self.inner.to_string() - } -} - -/// The basic key algorithms in the specification. -#[napi] -pub struct DeviceKeyAlgorithm { - inner: ruma::DeviceKeyAlgorithm, -} - -impl From for DeviceKeyAlgorithm { - fn from(inner: ruma::DeviceKeyAlgorithm) -> Self { - Self { inner } - } -} - -#[napi] -impl DeviceKeyAlgorithm { - /// Read the device key algorithm's name. If the name is - /// `Unknown`, one may be interested by the `to_string` method to - /// read the original name. - #[napi(getter)] - pub fn name(&self) -> DeviceKeyAlgorithmName { - self.inner.clone().into() - } - - /// Return the device key algorithm as a string. - #[napi] - #[allow(clippy::inherent_to_string)] - pub fn to_string(&self) -> String { - self.inner.to_string() - } -} - -/// The basic key algorithm names in the specification. -#[napi] -pub enum DeviceKeyAlgorithmName { - /// The Ed25519 signature algorithm. - Ed25519, - - /// The Curve25519 ECDH algorithm. - Curve25519, - - /// The Curve25519 ECDH algorithm, but the key also contains - /// signatures. - SignedCurve25519, - - /// An unknown device key algorithm. - Unknown, -} - -impl From for DeviceKeyAlgorithmName { - fn from(value: ruma::DeviceKeyAlgorithm) -> Self { - use ruma::DeviceKeyAlgorithm::*; - - match value { - Ed25519 => Self::Ed25519, - Curve25519 => Self::Curve25519, - SignedCurve25519 => Self::SignedCurve25519, - _ => Self::Unknown, - } - } -} - -/// A Matrix [room ID]. -/// -/// [room ID]: https://spec.matrix.org/v1.2/appendices/#room-ids-and-event-ids -#[napi] -#[derive(Debug, Clone)] -pub struct RoomId { - pub(crate) inner: ruma::OwnedRoomId, -} - -impl From for RoomId { - fn from(inner: ruma::OwnedRoomId) -> Self { - Self { inner } - } -} - -#[napi] -impl RoomId { - /// Parse/validate and create a new `RoomId`. - #[napi(constructor, strict)] - pub fn new(id: String) -> napi::Result { - Ok(Self::from(ruma::RoomId::parse(id).map_err(into_err)?)) - } - - /// Returns the user's localpart. - #[napi(getter)] - pub fn localpart(&self) -> String { - self.inner.localpart().to_owned() - } - - /// Returns the server name of the room ID. - #[napi(getter)] - pub fn server_name(&self) -> ServerName { - ServerName { inner: self.inner.server_name().to_owned() } - } - - /// Return the room ID as a string. - #[napi] - #[allow(clippy::inherent_to_string)] - pub fn to_string(&self) -> String { - self.inner.as_str().to_owned() - } -} - -/// A Matrix-spec compliant [server name]. -/// -/// It consists of a host and an optional port (separated by a colon if -/// present). -/// -/// [server name]: https://spec.matrix.org/v1.2/appendices/#server-name -#[napi] -#[derive(Debug)] -pub struct ServerName { - inner: ruma::OwnedServerName, -} - -#[napi] -impl ServerName { - /// Parse/validate and create a new `ServerName`. - #[napi(constructor, strict)] - pub fn new(name: String) -> napi::Result { - Ok(Self { inner: ruma::ServerName::parse(name).map_err(into_err)? }) - } - - /// Returns the host of the server name. - /// - /// That is: Return the part of the server before `:` or the - /// full server name if there is no port. - #[napi(getter)] - pub fn host(&self) -> String { - self.inner.host().to_owned() - } - - /// Returns the port of the server name if any. - #[napi(getter)] - pub fn port(&self) -> Option { - self.inner.port() - } - - /// Returns true if and only if the server name is an IPv4 or IPv6 - /// address. - #[napi] - pub fn is_ip_literal(&self) -> bool { - self.inner.is_ip_literal() - } -} diff --git a/bindings/matrix-sdk-crypto-nodejs/src/lib.rs b/bindings/matrix-sdk-crypto-nodejs/src/lib.rs deleted file mode 100644 index 540204be7..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/src/lib.rs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2022 The Matrix.org Foundation C.I.C. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#![doc = include_str!("../README.md")] -#![cfg_attr(docsrs, feature(doc_auto_cfg))] -//#![warn(missing_docs, missing_debug_implementations)] - -use napi_derive::napi; - -pub mod attachment; -pub mod encryption; -mod errors; -pub mod events; -pub mod identifiers; -pub mod machine; -pub mod olm; -pub mod requests; -pub mod responses; -pub mod sync_events; -#[cfg(feature = "tracing")] -pub mod tracing; -pub mod types; -pub mod vodozemac; - -/// Object containing the versions of the Rust libraries we are using. -#[napi] -pub struct Versions { - /// The version of the vodozemac crate. - #[napi(getter)] - pub vodozemac: String, - - /// The version of the matrix-sdk-crypto crate. - #[napi(getter)] - pub matrix_sdk_crypto: String, -} - -/// Get the versions of the Rust libraries we are using. -#[napi(js_name = "getVersions")] -pub fn get_versions() -> Versions { - Versions { - vodozemac: matrix_sdk_crypto::vodozemac::VERSION.to_owned(), - matrix_sdk_crypto: matrix_sdk_crypto::VERSION.to_owned(), - } -} - -use crate::errors::into_err; diff --git a/bindings/matrix-sdk-crypto-nodejs/src/machine.rs b/bindings/matrix-sdk-crypto-nodejs/src/machine.rs deleted file mode 100644 index 1d3d92807..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/src/machine.rs +++ /dev/null @@ -1,479 +0,0 @@ -//! The crypto specific Olm objects. - -use std::{ - collections::{BTreeMap, HashMap}, - mem::ManuallyDrop, - ops::Deref, - sync::Arc, -}; - -use napi::bindgen_prelude::{within_runtime_if_available, Either7, FromNapiValue, ToNapiValue}; -use napi_derive::*; -use ruma::{serde::Raw, DeviceKeyAlgorithm, OwnedTransactionId, UInt}; -use serde_json::{value::RawValue, Value as JsonValue}; -use zeroize::Zeroize; - -use crate::{ - encryption, identifiers, into_err, olm, requests, responses, responses::response_from_string, - sync_events, types, vodozemac, -}; - -/// The value used by the `OlmMachine` JS class. -/// -/// It has 2 states: `Opened` and `Closed`. Why maintaining the state here? -/// Because NodeJS has no way to drop an object explicitly, and we want to be -/// able to “close” the `OlmMachine` to free all associated data. More over, -/// `napi-rs` doesn't allow a function to take the ownership of the type itself -/// (`fn close(self) { … }`). So we manage the state ourselves. -/// -/// Using the `OlmMachine` when its state is `Closed` will panic. -enum OlmMachineInner { - Opened(ManuallyDrop), - Closed, -} - -impl Drop for OlmMachineInner { - fn drop(&mut self) { - if let Self::Opened(machine) = self { - // SAFETY: `self` won't be used anymore after this `take`, so it's safe to do it - // here. - let machine = unsafe { ManuallyDrop::take(machine) }; - within_runtime_if_available(move || drop(machine)); - } - } -} - -impl Deref for OlmMachineInner { - type Target = matrix_sdk_crypto::OlmMachine; - - #[inline] - fn deref(&self) -> &Self::Target { - match self { - Self::Opened(machine) => machine, - Self::Closed => panic!("The `OlmMachine` has been closed, cannot use it anymore"), - } - } -} - -/// Represents the type of store an `OlmMachine` can use. -#[derive(Default)] -#[napi] -pub enum StoreType { - /// Use `matrix-sdk-sqlite`. - #[default] - Sqlite, -} - -/// State machine implementation of the Olm/Megolm encryption protocol -/// used for Matrix end to end encryption. -// #[napi(custom_finalize)] -#[napi] -pub struct OlmMachine { - inner: OlmMachineInner, -} - -#[napi] -impl OlmMachine { - // JavaScript doesn't support asynchronous constructor. So let's - // use a factory pattern, where the constructor cannot be used (it - // returns an error), and a new method is provided to construct - // the object. napi provides `#[napi(factory)]` to address those - // needs automatically. Unfortunately, it doesn't support - // asynchronous factory methods. - // - // So let's do this manually. The `initialize` async method _is_ - // the factory function. We also manually implement the - // constructor to raise an error when called. - - /// Create a new `OlmMachine` asynchronously. - /// - /// The persistence of the encryption keys and all the inner - /// objects are controlled by the `store_path` argument. - /// - /// # Arguments - /// - /// * `user_id`, the unique ID of the user that owns this machine. - /// * `device_id`, the unique id of the device that owns this machine. - /// * `store_path`, the path to a directory where the state of the machine - /// should be persisted; if not set, the created machine will keep the - /// encryption keys only in memory, and once the object is dropped, the - /// keys will be lost. - /// * `store_passphrase`, the passphrase that should be used to encrypt the - /// data at rest in the store. **Warning**, if no passphrase is given, the - /// store and all its data will remain unencrypted. This argument is - /// ignored if `store_path` is not set. - #[napi(strict)] - pub async fn initialize( - user_id: &identifiers::UserId, - device_id: &identifiers::DeviceId, - store_path: Option, - mut store_passphrase: Option, - store_type: Option, - ) -> napi::Result { - let user_id = user_id.clone().inner; - let device_id = device_id.clone().inner; - - let user_id = user_id.as_ref(); - let device_id = device_id.as_ref(); - - Ok(OlmMachine { - inner: OlmMachineInner::Opened(ManuallyDrop::new(match store_path { - Some(store_path) => { - let machine = match store_type.unwrap_or_default() { - StoreType::Sqlite => { - matrix_sdk_crypto::OlmMachine::with_store( - user_id, - device_id, - matrix_sdk_sqlite::SqliteCryptoStore::open( - store_path, - store_passphrase.as_deref(), - ) - .await - .map(Arc::new) - .map_err(into_err)?, - ) - .await - } - }; - - store_passphrase.zeroize(); - - machine.map_err(into_err)? - } - - None => matrix_sdk_crypto::OlmMachine::new(user_id, device_id).await, - })), - }) - } - - /// It's not possible to construct an `OlmMachine` with its - /// constructor because building an `OlmMachine` is - /// asynchronous. Please use the `finalize` method. - #[napi(constructor)] - pub fn new() -> napi::Result { - Err(napi::Error::from_reason( - "To build an `OlmMachine`, please use the `initialize` method", - )) - } - - /// The unique user ID that owns this `OlmMachine` instance. - #[napi(getter)] - pub fn user_id(&self) -> identifiers::UserId { - identifiers::UserId::from(self.inner.user_id().to_owned()) - } - - /// The unique device ID that identifies this `OlmMachine`. - #[napi(getter)] - pub fn device_id(&self) -> identifiers::DeviceId { - identifiers::DeviceId::from(self.inner.device_id().to_owned()) - } - - /// Get the public parts of our Olm identity keys. - #[napi(getter)] - pub fn identity_keys(&self) -> vodozemac::IdentityKeys { - self.inner.identity_keys().into() - } - - /// Handle a to-device and one-time key counts from a sync response. - /// - /// This will decrypt and handle to-device events returning the - /// decrypted versions of them, as a JSON-encoded string. - /// - /// To decrypt an event from the room timeline, please use - /// `decrypt_room_event`. - /// - /// # Arguments - /// - /// * `to_device_events`, the to-device events of the current sync response. - /// * `changed_devices`, the list of devices that changed in this sync - /// response. - /// * `one_time_keys_count`, the current one-time keys counts that the sync - /// response returned. - #[napi(strict)] - pub async fn receive_sync_changes( - &self, - to_device_events: String, - changed_devices: &sync_events::DeviceLists, - one_time_key_counts: HashMap, - unused_fallback_keys: Vec, - ) -> napi::Result { - let to_device_events = serde_json::from_str(to_device_events.as_ref()).map_err(into_err)?; - let changed_devices = changed_devices.inner.clone(); - let one_time_key_counts = one_time_key_counts - .iter() - .map(|(key, value)| (DeviceKeyAlgorithm::from(key.as_str()), UInt::from(*value))) - .collect::>(); - let unused_fallback_keys = Some( - unused_fallback_keys - .into_iter() - .map(|key| DeviceKeyAlgorithm::from(key.as_str())) - .collect::>(), - ); - - serde_json::to_string( - &self - .inner - .receive_sync_changes( - to_device_events, - &changed_devices, - &one_time_key_counts, - unused_fallback_keys.as_deref(), - ) - .await - .map_err(into_err)?, - ) - .map_err(into_err) - } - - /// Get the outgoing requests that need to be sent out. - /// - /// This returns a list of `KeysUploadRequest`, or - /// `KeysQueryRequest`, or `KeysClaimRequest`, or - /// `ToDeviceRequest`, or `SignatureUploadRequest`, or - /// `RoomMessageRequest`, or `KeysBackupRequest`. Those requests - /// need to be sent out to the server and the responses need to be - /// passed back to the state machine using `mark_request_as_sent`. - #[napi] - pub async fn outgoing_requests( - &self, - ) -> napi::Result< - Vec< - // We could be tempted to use `requests::OutgoingRequests` as its - // a type alias for this giant `Either7`. But `napi` won't unfold - // it properly into a valid TypeScript definition, so… let's - // copy-paste :-(. - Either7< - requests::KeysUploadRequest, - requests::KeysQueryRequest, - requests::KeysClaimRequest, - requests::ToDeviceRequest, - requests::SignatureUploadRequest, - requests::RoomMessageRequest, - requests::KeysBackupRequest, - >, - >, - > { - self.inner - .outgoing_requests() - .await - .map_err(into_err)? - .into_iter() - .map(requests::OutgoingRequest) - .map(TryFrom::try_from) - .collect() - } - - /// Mark the request with the given request ID as sent. - /// - /// # Arguments - /// - /// * `request_id`, the unique ID of the request that was sent out. This is - /// needed to couple the response with the now sent out request. - /// * `request_type`, the request type associated to the request ID. - /// * `response`, the response that was received from the server after the - /// outgoing request was sent out. - #[napi(strict)] - pub async fn mark_request_as_sent( - &self, - request_id: String, - request_type: requests::RequestType, - response: String, - ) -> napi::Result { - let transaction_id = OwnedTransactionId::from(request_id); - let response = response_from_string(response.as_str()).map_err(into_err)?; - let incoming_response = responses::OwnedResponse::try_from((request_type, response))?; - - self.inner - .mark_request_as_sent(&transaction_id, &incoming_response) - .await - .map(|_| true) - .map_err(into_err) - } - - /// Get the a key claiming request for the user/device pairs that - /// we are missing Olm sessions for. - /// - /// Returns `null` if no key claiming request needs to be sent - /// out. - /// - /// Sessions need to be established between devices so group - /// sessions for a room can be shared with them. - /// - /// This should be called every time a group session needs to be - /// shared as well as between sync calls. After a sync some - /// devices may request room keys without us having a valid Olm - /// session with them, making it impossible to server the room key - /// request, thus it’s necessary to check for missing sessions - /// between sync as well. - /// - /// Note: Care should be taken that only one such request at a - /// time is in flight, e.g. using a lock. - /// - /// The response of a successful key claiming requests needs to be - /// passed to the `OlmMachine` with the `mark_request_as_sent`. - /// - /// # Arguments - /// - /// * `users`, the list of users that we should check if we lack a session - /// with one of their devices. This can be an empty array or `null` when - /// calling this method between sync requests. - #[napi(strict)] - pub async fn get_missing_sessions( - &self, - users: Option>, - ) -> napi::Result> { - let users = users - .unwrap_or_default() - .into_iter() - .map(|user| user.inner.clone()) - .collect::>(); - - match self - .inner - .get_missing_sessions(users.iter().map(AsRef::as_ref)) - .await - .map_err(into_err)? - { - Some((transaction_id, keys_claim_request)) => Ok(Some( - requests::KeysClaimRequest::try_from(( - transaction_id.to_string(), - &keys_claim_request, - )) - .map_err(into_err)?, - )), - - None => Ok(None), - } - } - - /// Update the tracked users. - /// - /// This will mark users that weren’t seen before for a key query - /// and tracking. - /// - /// If the user is already known to the Olm machine it will not be - /// considered for a key query. - /// - /// # Arguments - /// - /// * `users`, an array over user IDs that should be marked for tracking. - #[napi(strict)] - pub async fn update_tracked_users(&self, users: Vec<&identifiers::UserId>) -> napi::Result<()> { - let users = users.into_iter().map(|user| user.inner.clone()).collect::>(); - - self.inner.update_tracked_users(users.iter().map(AsRef::as_ref)).await.map_err(into_err)?; - - Ok(()) - } - - /// Get to-device requests to share a room key with users in a room. - /// - /// # Arguments - /// - /// * `room_id`, the room ID of the room where the room key will be used. - /// * `users`, the list of users that should receive the room key. - /// * `encryption_settings`, the encryption settings. - #[napi(strict)] - pub async fn share_room_key( - &self, - room_id: &identifiers::RoomId, - users: Vec<&identifiers::UserId>, - encryption_settings: &encryption::EncryptionSettings, - ) -> napi::Result { - let room_id = room_id.inner.clone(); - let users = users.into_iter().map(|user| user.inner.clone()).collect::>(); - let encryption_settings = - matrix_sdk_crypto::olm::EncryptionSettings::from(encryption_settings); - - serde_json::to_string( - &self - .inner - .share_room_key(&room_id, users.iter().map(AsRef::as_ref), encryption_settings) - .await - .map_err(into_err)?, - ) - .map_err(into_err) - } - - /// Encrypt a JSON-encoded content for the given room. - /// - /// # Arguments - /// - /// * `room_id`, the ID of the room for which the message should be - /// encrypted. - /// * `event_type`, the plaintext type of the event. - /// * `content`, the JSON-encoded content of the message that should be - /// encrypted. - #[napi(strict)] - pub async fn encrypt_room_event( - &self, - room_id: &identifiers::RoomId, - event_type: String, - content: String, - ) -> napi::Result { - let room_id = room_id.inner.clone(); - let content: JsonValue = serde_json::from_str(content.as_str()).map_err(into_err)?; - - serde_json::to_string( - &self - .inner - .encrypt_room_event_raw(&room_id, content, event_type.as_ref()) - .await - .map_err(into_err)?, - ) - .map_err(into_err) - } - - /// Decrypt an event from a room timeline. - /// - /// # Arguments - /// - /// * `event`, the event that should be decrypted. - /// * `room_id`, the ID of the room where the event was sent to. - #[napi(strict)] - pub async fn decrypt_room_event( - &self, - event: String, - room_id: &identifiers::RoomId, - ) -> napi::Result { - let event = Raw::from_json(RawValue::from_string(event).map_err(into_err)?); - let room_id = room_id.inner.clone(); - - let room_event = self.inner.decrypt_room_event(&event, &room_id).await.map_err(into_err)?; - - Ok(room_event.into()) - } - - /// Get the status of the private cross signing keys. - /// - /// This can be used to check which private cross signing keys we - /// have stored locally. - #[napi] - pub async fn cross_signing_status(&self) -> olm::CrossSigningStatus { - self.inner.cross_signing_status().await.into() - } - - /// Sign the given message using our device key and if available - /// cross-signing master key. - #[napi(strict)] - pub async fn sign(&self, message: String) -> types::Signatures { - self.inner.sign(message.as_str()).await.into() - } - - /// Shut down the `OlmMachine`. - /// - /// The `OlmMachine` cannot be used after this method has been called, - /// otherwise it will panic. - /// - /// All associated resources will be closed too, like the crypto storage - /// connections. - /// - /// # Safety - /// - /// The caller is responsible to **not** use any objects that came from this - /// `OlmMachine` after this `close` method has been called. - #[napi(strict)] - pub fn close(&mut self) { - self.inner = OlmMachineInner::Closed; - } -} diff --git a/bindings/matrix-sdk-crypto-nodejs/src/olm.rs b/bindings/matrix-sdk-crypto-nodejs/src/olm.rs deleted file mode 100644 index c45c79c29..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/src/olm.rs +++ /dev/null @@ -1,40 +0,0 @@ -//! Olm types. - -use napi_derive::*; - -/// Struct representing the state of our private cross signing keys, -/// it shows which private cross signing keys we have locally stored. -#[napi] -#[derive(Debug)] -pub struct CrossSigningStatus { - inner: matrix_sdk_crypto::olm::CrossSigningStatus, -} - -impl From for CrossSigningStatus { - fn from(inner: matrix_sdk_crypto::olm::CrossSigningStatus) -> Self { - Self { inner } - } -} - -#[napi] -impl CrossSigningStatus { - /// Do we have the master key. - #[napi(getter)] - pub fn has_master(&self) -> bool { - self.inner.has_master - } - - /// Do we have the self signing key, this one is necessary to sign - /// our own devices. - #[napi(getter)] - pub fn has_self_signing(&self) -> bool { - self.inner.has_self_signing - } - - /// Do we have the user signing key, this one is necessary to sign - /// other users. - #[napi(getter)] - pub fn has_user_signing(&self) -> bool { - self.inner.has_user_signing - } -} diff --git a/bindings/matrix-sdk-crypto-nodejs/src/requests.rs b/bindings/matrix-sdk-crypto-nodejs/src/requests.rs deleted file mode 100644 index 35d16d4f6..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/src/requests.rs +++ /dev/null @@ -1,401 +0,0 @@ -//! Types to handle requests. - -use std::time::Duration; - -use matrix_sdk_crypto::requests::{ - KeysBackupRequest as RumaKeysBackupRequest, KeysQueryRequest as RumaKeysQueryRequest, - RoomMessageRequest as RumaRoomMessageRequest, ToDeviceRequest as RumaToDeviceRequest, -}; -use napi::bindgen_prelude::{Either7, FromNapiValue, ToNapiValue}; -use napi_derive::*; -use ruma::{ - api::client::keys::{ - claim_keys::v3::Request as RumaKeysClaimRequest, - upload_keys::v3::Request as RumaKeysUploadRequest, - upload_signatures::v3::Request as RumaSignatureUploadRequest, - }, - events::EventContent, -}; - -use crate::into_err; - -/// Data for a request to the `/keys/upload` API endpoint -/// ([specification]). -/// -/// Publishes end-to-end encryption keys for the device. -/// -/// [specification]: https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3keysupload -#[napi] -pub struct KeysUploadRequest { - /// The request ID. - #[napi(readonly)] - pub id: String, - - /// A JSON-encoded string containing the rest of the payload: `device_keys`, - /// `one_time_keys`, `fallback_keys`. - /// - /// It represents the body of the HTTP request. - #[napi(readonly)] - pub body: String, -} - -#[napi] -impl KeysUploadRequest { - /// Get its request type. - #[napi(getter, js_name = "type")] - pub fn request_type(&self) -> RequestType { - RequestType::KeysUpload - } -} - -/// Data for a request to the `/keys/query` API endpoint -/// ([specification]). -/// -/// Returns the current devices and identity keys for the given users. -/// -/// [specification]: https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3keysquery -#[napi] -pub struct KeysQueryRequest { - /// The request ID. - #[napi(readonly)] - pub id: String, - - /// A JSON-encoded object of form: - /// - /// ```json - /// {"timeout": …, "one_time_keys": …} - /// ``` - #[napi(readonly)] - pub body: String, -} - -#[napi] -impl KeysQueryRequest { - /// Get its request type. - #[napi(getter, js_name = "type")] - pub fn request_type(&self) -> RequestType { - RequestType::KeysQuery - } -} - -/// Data for a request to the `/keys/claim` API endpoint -/// ([specification]). -/// -/// Claims one-time keys that can be used to establish 1-to-1 E2EE -/// sessions. -/// -/// [specification]: https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3keysclaim -#[napi] -pub struct KeysClaimRequest { - /// The request ID. - #[napi(readonly)] - pub id: String, - - /// A JSON-encoded object of form: - /// - /// ```json - /// {"event_type": …, "txn_id": …, "messages": …} - /// ``` - #[napi(readonly)] - pub body: String, -} - -#[napi] -impl KeysClaimRequest { - /// Get its request type. - #[napi(getter, js_name = "type")] - pub fn request_type(&self) -> RequestType { - RequestType::KeysClaim - } -} - -/// Data for a request to the `/sendToDevice` API endpoint -/// ([specification]). -/// -/// Send an event to a single device or to a group of devices. -/// -/// [specification]: https://spec.matrix.org/unstable/client-server-api/#put_matrixclientv3sendtodeviceeventtypetxnid -#[napi] -pub struct ToDeviceRequest { - /// The request ID. - #[napi(readonly)] - pub id: String, - - /// A string representing the type of event being sent to each devices. - #[napi(readonly)] - pub event_type: String, - - /// A string representing a request identifier unique to the access token - /// used to send the request. - #[napi(readonly)] - pub txn_id: String, - - /// A JSON-encoded string containing the rest of the payload: `messages`. - /// - /// It represents the body of the HTTP request. - #[napi(readonly)] - pub body: String, -} - -#[napi] -impl ToDeviceRequest { - /// Get its request type. - #[napi(getter, js_name = "type")] - pub fn request_type(&self) -> RequestType { - RequestType::ToDevice - } -} - -/// Data for a request to the `/keys/signatures/upload` API endpoint -/// ([specification]). -/// -/// Publishes cross-signing signatures for the user. -/// -/// [specification]: https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3keyssignaturesupload -#[napi] -pub struct SignatureUploadRequest { - /// The request ID. - #[napi(readonly)] - pub id: String, - - /// A JSON-encoded string containing the rest of the payload: `signed_keys`. - /// - /// It represents the body of the HTTP request. - #[napi(readonly)] - pub body: String, -} - -#[napi] -impl SignatureUploadRequest { - /// Get its request type. - #[napi(getter, js_name = "type")] - pub fn request_type(&self) -> RequestType { - RequestType::SignatureUpload - } -} - -/// A customized owned request type for sending out room messages -/// ([specification]). -/// -/// [specification]: https://spec.matrix.org/unstable/client-server-api/#put_matrixclientv3roomsroomidsendeventtypetxnid -#[napi] -pub struct RoomMessageRequest { - /// The request ID. - #[napi(readonly)] - pub id: String, - - /// A string representing the room to send the event to. - #[napi(readonly)] - pub room_id: String, - - /// A string representing the transaction ID for this event. - /// - /// Clients should generate an ID unique across requests with the same - /// access token; it will be used by the server to ensure idempotency of - /// requests. - #[napi(readonly)] - pub txn_id: String, - - /// A string representing the type of event to be sent. - #[napi(readonly)] - pub event_type: String, - - /// A JSON-encoded string containing the message's content. - #[napi(readonly, js_name = "body")] - pub content: String, -} - -#[napi] -impl RoomMessageRequest { - /// Get its request type. - #[napi(getter, js_name = "type")] - pub fn request_type(&self) -> RequestType { - RequestType::RoomMessage - } -} - -/// A request that will back up a batch of room keys to the server -/// ([specification]). -/// -/// [specification]: https://spec.matrix.org/unstable/client-server-api/#put_matrixclientv3room_keyskeys -#[napi] -pub struct KeysBackupRequest { - /// The request ID. - #[napi(readonly)] - pub id: String, - - /// A JSON-encoded string containing the rest of the payload: `rooms`. - /// - /// It represents the body of the HTTP request. - #[napi(readonly)] - pub body: String, -} - -#[napi] -impl KeysBackupRequest { - /// Get its request type. - #[napi(getter, js_name = "type")] - pub fn request_type(&self) -> RequestType { - RequestType::KeysBackup - } -} - -macro_rules! request { - ( - $destination_request:ident from $source_request:ident - $( extracts $( $field_name:ident : $field_type:tt ),+ $(,)? )? - $( $( and )? groups $( $grouped_field_name:ident $( { $grouped_field_transformation:expr } )? ),+ $(,)? )? - ) => { - impl TryFrom<(String, &$source_request)> for $destination_request { - type Error = napi::Error; - - fn try_from( - (request_id, request): (String, &$source_request), - ) -> Result { - request!( - @__try_from $destination_request from $source_request - (request_id = request_id.into(), request = request) - $( extracts [ $( $field_name : $field_type, )+ ] )? - $( groups [ $( $grouped_field_name $( { $grouped_field_transformation } )? , )+ ] )? - ) - } - } - }; - - ( - @__try_from $destination_request:ident from $source_request:ident - (request_id = $request_id:expr, request = $request:expr) - $( extracts [ $( $field_name:ident : $field_type:tt ),* $(,)? ] )? - $( groups [ $( $grouped_field_name:ident $( { $grouped_field_transformation:expr } )? ),* $(,)? ] )? - ) => { - { - Ok($destination_request { - id: $request_id, - $( - $( - $field_name: request!(@__field $field_name : $field_type ; request = $request), - )* - )? - $( - body: { - let mut map = serde_json::Map::new(); - $( - - let field = &$request.$grouped_field_name; - $( - let field = { - let $grouped_field_name = field; - - $grouped_field_transformation - }; - )? - map.insert(stringify!($grouped_field_name).to_owned(), serde_json::to_value(field).map_err(into_err)?); - )* - let object = serde_json::Value::Object(map); - - serde_json::to_string(&object).map_err(into_err)?.into() - } - )? - }) - } - }; - - ( @__field $field_name:ident : $field_type:ident ; request = $request:expr ) => { - request!(@__field_type as $field_type ; request = $request, field_name = $field_name) - }; - - ( @__field_type as string ; request = $request:expr, field_name = $field_name:ident ) => { - $request.$field_name.to_string().into() - }; - - ( @__field_type as json ; request = $request:expr, field_name = $field_name:ident ) => { - serde_json::to_string(&$request.$field_name).map_err(into_err)?.into() - }; - - ( @__field_type as event_type ; request = $request:expr, field_name = $field_name:ident ) => { - $request.content.event_type().to_string().into() - }; -} - -request!(KeysUploadRequest from RumaKeysUploadRequest groups device_keys, one_time_keys, fallback_keys); -request!(KeysQueryRequest from RumaKeysQueryRequest groups timeout { timeout.as_ref().map(Duration::as_millis).map(u64::try_from).transpose().map_err(into_err)? }, device_keys, token); -request!(KeysClaimRequest from RumaKeysClaimRequest groups timeout { timeout.as_ref().map(Duration::as_millis).map(u64::try_from).transpose().map_err(into_err)? }, one_time_keys); -request!(ToDeviceRequest from RumaToDeviceRequest extracts event_type: string, txn_id: string and groups messages); -request!(SignatureUploadRequest from RumaSignatureUploadRequest groups signed_keys); -request!(RoomMessageRequest from RumaRoomMessageRequest extracts room_id: string, txn_id: string, event_type: event_type, content: json); -request!(KeysBackupRequest from RumaKeysBackupRequest groups rooms); - -pub type OutgoingRequests = Either7< - KeysUploadRequest, - KeysQueryRequest, - KeysClaimRequest, - ToDeviceRequest, - SignatureUploadRequest, - RoomMessageRequest, - KeysBackupRequest, ->; - -pub(crate) struct OutgoingRequest(pub(crate) matrix_sdk_crypto::OutgoingRequest); - -impl TryFrom for OutgoingRequests { - type Error = napi::Error; - - fn try_from(outgoing_request: OutgoingRequest) -> Result { - let request_id = outgoing_request.0.request_id().to_string(); - - Ok(match outgoing_request.0.request() { - matrix_sdk_crypto::OutgoingRequests::KeysUpload(request) => { - Either7::A(KeysUploadRequest::try_from((request_id, request))?) - } - - matrix_sdk_crypto::OutgoingRequests::KeysQuery(request) => { - Either7::B(KeysQueryRequest::try_from((request_id, request))?) - } - - matrix_sdk_crypto::OutgoingRequests::KeysClaim(request) => { - Either7::C(KeysClaimRequest::try_from((request_id, request))?) - } - - matrix_sdk_crypto::OutgoingRequests::ToDeviceRequest(request) => { - Either7::D(ToDeviceRequest::try_from((request_id, request))?) - } - - matrix_sdk_crypto::OutgoingRequests::SignatureUpload(request) => { - Either7::E(SignatureUploadRequest::try_from((request_id, request))?) - } - - matrix_sdk_crypto::OutgoingRequests::RoomMessage(request) => { - Either7::F(RoomMessageRequest::try_from((request_id, request))?) - } - - matrix_sdk_crypto::OutgoingRequests::KeysBackup(request) => { - Either7::G(KeysBackupRequest::try_from((request_id, request))?) - } - }) - } -} - -/// Represent the type of a request. -#[napi] -pub enum RequestType { - /// Represents a `KeysUploadRequest`. - KeysUpload, - - /// Represents a `KeysQueryRequest`. - KeysQuery, - - /// Represents a `KeysClaimRequest`. - KeysClaim, - - /// Represents a `ToDeviceRequest`. - ToDevice, - - /// Represents a `SignatureUploadRequest`. - SignatureUpload, - - /// Represents a `RoomMessageRequest`. - RoomMessage, - - /// Represents a `KeysBackupRequest`. - KeysBackup, -} diff --git a/bindings/matrix-sdk-crypto-nodejs/src/responses.rs b/bindings/matrix-sdk-crypto-nodejs/src/responses.rs deleted file mode 100644 index 14eb94c89..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/src/responses.rs +++ /dev/null @@ -1,202 +0,0 @@ -use matrix_sdk_common::deserialized_responses::{AlgorithmInfo, EncryptionInfo}; -use matrix_sdk_crypto::IncomingResponse; -use napi_derive::*; -pub(crate) use ruma::api::client::{ - backup::add_backup_keys::v3::Response as KeysBackupResponse, - keys::{ - claim_keys::v3::Response as KeysClaimResponse, get_keys::v3::Response as KeysQueryResponse, - upload_keys::v3::Response as KeysUploadResponse, - upload_signatures::v3::Response as SignatureUploadResponse, - }, - message::send_message_event::v3::Response as RoomMessageResponse, - to_device::send_event_to_device::v3::Response as ToDeviceResponse, -}; -use ruma::api::IncomingResponse as RumaIncomingResponse; - -use crate::{encryption, identifiers, into_err, requests::RequestType}; - -pub(crate) fn response_from_string(body: &str) -> http::Result>> { - http::Response::builder().status(200).body(body.as_bytes().to_vec()) -} - -/// Intermediate private type to store an incoming owned response, -/// without the need to manage lifetime. -pub(crate) enum OwnedResponse { - KeysUpload(KeysUploadResponse), - KeysQuery(KeysQueryResponse), - KeysClaim(KeysClaimResponse), - ToDevice(ToDeviceResponse), - SignatureUpload(SignatureUploadResponse), - RoomMessage(RoomMessageResponse), - KeysBackup(KeysBackupResponse), -} - -impl From for OwnedResponse { - fn from(response: KeysUploadResponse) -> Self { - OwnedResponse::KeysUpload(response) - } -} - -impl From for OwnedResponse { - fn from(response: KeysQueryResponse) -> Self { - OwnedResponse::KeysQuery(response) - } -} - -impl From for OwnedResponse { - fn from(response: KeysClaimResponse) -> Self { - OwnedResponse::KeysClaim(response) - } -} - -impl From for OwnedResponse { - fn from(response: ToDeviceResponse) -> Self { - OwnedResponse::ToDevice(response) - } -} - -impl From for OwnedResponse { - fn from(response: SignatureUploadResponse) -> Self { - Self::SignatureUpload(response) - } -} - -impl From for OwnedResponse { - fn from(response: RoomMessageResponse) -> Self { - OwnedResponse::RoomMessage(response) - } -} - -impl From for OwnedResponse { - fn from(r: KeysBackupResponse) -> Self { - Self::KeysBackup(r) - } -} - -impl TryFrom<(RequestType, http::Response>)> for OwnedResponse { - type Error = napi::Error; - - fn try_from( - (request_type, response): (RequestType, http::Response>), - ) -> Result { - match request_type { - RequestType::KeysUpload => { - KeysUploadResponse::try_from_http_response(response).map(Into::into) - } - - RequestType::KeysQuery => { - KeysQueryResponse::try_from_http_response(response).map(Into::into) - } - - RequestType::KeysClaim => { - KeysClaimResponse::try_from_http_response(response).map(Into::into) - } - - RequestType::ToDevice => { - ToDeviceResponse::try_from_http_response(response).map(Into::into) - } - - RequestType::SignatureUpload => { - SignatureUploadResponse::try_from_http_response(response).map(Into::into) - } - - RequestType::RoomMessage => { - RoomMessageResponse::try_from_http_response(response).map(Into::into) - } - - RequestType::KeysBackup => { - KeysBackupResponse::try_from_http_response(response).map(Into::into) - } - } - .map_err(into_err) - } -} - -impl<'a> From<&'a OwnedResponse> for IncomingResponse<'a> { - fn from(response: &'a OwnedResponse) -> Self { - match response { - OwnedResponse::KeysUpload(response) => IncomingResponse::KeysUpload(response), - OwnedResponse::KeysQuery(response) => IncomingResponse::KeysQuery(response), - OwnedResponse::KeysClaim(response) => IncomingResponse::KeysClaim(response), - OwnedResponse::ToDevice(response) => IncomingResponse::ToDevice(response), - OwnedResponse::SignatureUpload(response) => IncomingResponse::SignatureUpload(response), - OwnedResponse::RoomMessage(response) => IncomingResponse::RoomMessage(response), - OwnedResponse::KeysBackup(response) => IncomingResponse::KeysBackup(response), - } - } -} - -/// A decrypted room event. -#[napi] -pub struct DecryptedRoomEvent { - /// The JSON-encoded decrypted event. - #[napi(readonly)] - pub event: String, - - encryption_info: Option, -} - -#[napi] -impl DecryptedRoomEvent { - /// The user ID of the event sender, note this is untrusted data - /// unless the `verification_state` is as well trusted. - #[napi(getter)] - pub fn sender(&self) -> Option { - Some(identifiers::UserId::from(self.encryption_info.as_ref()?.sender.clone())) - } - - /// The device ID of the device that sent us the event, note this - /// is untrusted data unless `verification_state` is as well - /// trusted. - #[napi(getter)] - pub fn sender_device(&self) -> Option { - Some(self.encryption_info.as_ref()?.sender_device.as_ref()?.clone().into()) - } - - /// The Curve25519 key of the device that created the megolm - /// decryption key originally. - #[napi(getter)] - pub fn sender_curve25519_key(&self) -> Option { - Some(match &self.encryption_info.as_ref()?.algorithm_info { - AlgorithmInfo::MegolmV1AesSha2 { curve25519_key, .. } => curve25519_key.clone(), - }) - } - - /// The signing Ed25519 key that have created the megolm key that - /// was used to decrypt this session. - #[napi(getter)] - pub fn sender_claimed_ed25519_key(&self) -> Option { - match &self.encryption_info.as_ref()?.algorithm_info { - AlgorithmInfo::MegolmV1AesSha2 { sender_claimed_keys, .. } => { - sender_claimed_keys.get(&ruma::DeviceKeyAlgorithm::Ed25519).cloned() - } - } - } - - /// Chain of Curve25519 keys through which this session was - /// forwarded, via `m.forwarded_room_key` events. - #[napi(getter)] - pub fn forwarding_curve25519_key_chain(&self) -> Vec { - vec![] - } - - /// The verification state of the device that sent us the event, - /// note this is the state of the device at the time of - /// decryption. It may change in the future if a device gets - /// verified or deleted. - #[napi] - pub fn shield_state(&self, strict: bool) -> Option { - let state = &self.encryption_info.as_ref()?.verification_state; - if strict { - Some(state.to_shield_state_strict().into()) - } else { - Some(state.to_shield_state_lax().into()) - } - } -} - -impl From for DecryptedRoomEvent { - fn from(value: matrix_sdk_common::deserialized_responses::TimelineEvent) -> Self { - Self { event: value.event.json().get().to_owned(), encryption_info: value.encryption_info } - } -} diff --git a/bindings/matrix-sdk-crypto-nodejs/src/sync_events.rs b/bindings/matrix-sdk-crypto-nodejs/src/sync_events.rs deleted file mode 100644 index 4122bba2d..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/src/sync_events.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! `GET /_matrix/client/*/sync`. - -use napi_derive::*; - -use crate::identifiers; - -/// Information on E2E device updates. -#[napi] -pub struct DeviceLists { - pub(crate) inner: ruma::api::client::sync::sync_events::DeviceLists, -} - -#[napi] -impl DeviceLists { - /// Create an empty `DeviceLists`. - #[napi(constructor, strict)] - pub fn new( - changed: Option>, - left: Option>, - ) -> Self { - let mut inner = ruma::api::client::sync::sync_events::DeviceLists::default(); - - inner.changed = changed.into_iter().flatten().map(|user| user.inner.clone()).collect(); - inner.left = left.into_iter().flatten().map(|user| user.inner.clone()).collect(); - - Self { inner } - } - - /// Returns true if there are no device list updates. - #[napi] - pub fn is_empty(&self) -> bool { - self.inner.is_empty() - } - - /// List of users who have updated their device identity keys or - /// who now share an encrypted room with the client since the - /// previous sync. - #[napi(getter)] - pub fn changed(&self) -> Vec { - self.inner.changed.iter().map(|user| identifiers::UserId::from(user.to_owned())).collect() - } - - /// List of users who no longer share encrypted rooms since the - /// previous sync response. - #[napi(getter)] - pub fn left(&self) -> Vec { - self.inner.left.iter().map(|user| identifiers::UserId::from(user.to_owned())).collect() - } -} diff --git a/bindings/matrix-sdk-crypto-nodejs/src/tracing.rs b/bindings/matrix-sdk-crypto-nodejs/src/tracing.rs deleted file mode 100644 index 917838d71..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/src/tracing.rs +++ /dev/null @@ -1,11 +0,0 @@ -use napi_derive::*; -use tracing_subscriber::{fmt, prelude::*, EnvFilter}; - -/// Subscribe to tracing events, i.e. turn on logs. -#[napi] -pub fn init_tracing() { - tracing_subscriber::registry() - .with(fmt::layer()) - .with(EnvFilter::from_env("MATRIX_LOG")) - .init(); -} diff --git a/bindings/matrix-sdk-crypto-nodejs/src/types.rs b/bindings/matrix-sdk-crypto-nodejs/src/types.rs deleted file mode 100644 index 89d1027d5..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/src/types.rs +++ /dev/null @@ -1,156 +0,0 @@ -use std::collections::HashMap; - -use napi_derive::*; - -use crate::{ - identifiers::{DeviceKeyId, UserId}, - vodozemac::Ed25519Signature, -}; - -#[napi] -#[derive(Default)] -pub struct Signatures { - inner: matrix_sdk_crypto::types::Signatures, -} - -impl From for Signatures { - fn from(inner: matrix_sdk_crypto::types::Signatures) -> Self { - Self { inner } - } -} - -#[napi] -impl Signatures { - /// Creates a new, empty, signatures collection. - #[napi(constructor)] - pub fn new() -> Self { - matrix_sdk_crypto::types::Signatures::new().into() - } - - /// Add the given signature from the given signer and the given key ID to - /// the collection. - #[napi(strict)] - pub fn add_signature( - &mut self, - signer: &UserId, - key_id: &DeviceKeyId, - signature: &Ed25519Signature, - ) -> Option { - self.inner - .add_signature(signer.inner.clone(), key_id.inner.clone(), signature.inner) - .map(Into::into) - } - - /// Try to find an Ed25519 signature from the given signer with - /// the given key ID. - #[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(strict)] - pub fn get(&self, signer: &UserId) -> Option> { - self.inner.get(signer.inner.as_ref()).map(|map| { - map.iter() - .map(|(device_key_id, maybe_signature)| { - (device_key_id.as_str().to_owned(), maybe_signature.clone().into()) - }) - .collect() - }) - } - - /// Remove all the signatures we currently hold. - #[napi] - pub fn clear(&mut self) { - self.inner.clear(); - } - - /// Do we hold any signatures or is our collection completely - /// empty. - #[napi(getter)] - pub fn is_empty(&self) -> bool { - self.inner.is_empty() - } - - /// How many signatures do we currently hold. - #[napi(getter)] - pub fn count(&self) -> usize { - self.inner.signature_count() - } -} - -/// Represents a potentially decoded signature (but not a validated -/// one). -#[napi] -pub struct Signature { - inner: matrix_sdk_crypto::types::Signature, -} - -impl From for Signature { - fn from(inner: matrix_sdk_crypto::types::Signature) -> Self { - Self { inner } - } -} - -#[napi] -impl Signature { - /// Get the Ed25519 signature, if this is one. - #[napi(getter)] - pub fn ed25519(&self) -> Option { - self.inner.ed25519().map(Into::into) - } - - /// Convert the signature to a base64 encoded string. - #[napi] - pub fn to_base64(&self) -> String { - self.inner.to_base64() - } -} - -type MaybeSignatureInner = - Result; - -/// Represents a signature that is either valid _or_ that could not be -/// decoded. -#[napi] -pub struct MaybeSignature { - inner: MaybeSignatureInner, -} - -impl From for MaybeSignature { - fn from(inner: MaybeSignatureInner) -> Self { - Self { inner } - } -} - -#[napi] -impl MaybeSignature { - /// Check whether the signature has been successfully decoded. - #[napi(getter)] - pub fn is_valid(&self) -> bool { - self.inner.is_ok() - } - - /// Check whether the signature could not be successfully decoded. - #[napi(getter)] - pub fn is_invalid(&self) -> bool { - self.inner.is_err() - } - - /// The signature, if successfully decoded. - #[napi(getter)] - pub fn signature(&self) -> Option { - self.inner.as_ref().cloned().map(Into::into).ok() - } - - /// The base64 encoded string that is claimed to contain a - /// signature but could not be decoded, if any. - #[napi(getter)] - pub fn invalid_signature_source(&self) -> Option { - match &self.inner { - Ok(_) => None, - Err(signature) => Some(signature.source.clone()), - } - } -} diff --git a/bindings/matrix-sdk-crypto-nodejs/src/vodozemac.rs b/bindings/matrix-sdk-crypto-nodejs/src/vodozemac.rs deleted file mode 100644 index f2ecfc06b..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/src/vodozemac.rs +++ /dev/null @@ -1,113 +0,0 @@ -use napi_derive::*; - -use crate::into_err; - -/// An Ed25519 public key, used to verify digital signatures. -#[napi] -#[derive(Clone)] -pub struct Ed25519PublicKey { - inner: vodozemac::Ed25519PublicKey, -} - -#[napi] -impl Ed25519PublicKey { - /// The number of bytes an Ed25519 public key has. - #[napi(getter)] - pub fn length(&self) -> u32 { - vodozemac::Ed25519PublicKey::LENGTH as u32 - } - - /// Serialize an Ed25519 public key to an unpadded base64 - /// representation. - #[napi] - pub fn to_base64(&self) -> String { - self.inner.to_base64() - } -} - -/// An Ed25519 digital signature, can be used to verify the -/// authenticity of a message. -#[napi] -pub struct Ed25519Signature { - pub(crate) inner: vodozemac::Ed25519Signature, -} - -impl From for Ed25519Signature { - fn from(inner: vodozemac::Ed25519Signature) -> Self { - Self { inner } - } -} - -#[napi] -impl Ed25519Signature { - /// Try to create an Ed25519 signature from an unpadded base64 - /// representation. - #[napi(constructor, strict)] - pub fn new(signature: String) -> napi::Result { - Ok(Self { - inner: vodozemac::Ed25519Signature::from_base64(signature.as_str()) - .map_err(into_err)?, - }) - } - - /// Serialize a Ed25519 signature to an unpadded base64 - /// representation. - #[napi] - pub fn to_base64(&self) -> String { - self.inner.to_base64() - } -} - -/// A Curve25519 public key. -#[napi] -#[derive(Clone)] -pub struct Curve25519PublicKey { - inner: vodozemac::Curve25519PublicKey, -} - -#[napi] -impl Curve25519PublicKey { - /// The number of bytes a Curve25519 public key has. - #[napi(getter)] - pub fn length(&self) -> u32 { - vodozemac::Curve25519PublicKey::LENGTH as u32 - } - - /// Serialize an Curve25519 public key to an unpadded base64 - /// representation. - #[napi] - pub fn to_base64(&self) -> String { - self.inner.to_base64() - } -} - -/// Struct holding the two public identity keys of an account. -#[napi] -pub struct IdentityKeys { - ed25519: Ed25519PublicKey, - curve25519: Curve25519PublicKey, -} - -#[napi] -impl IdentityKeys { - /// The Ed25519 public key, used for signing. - #[napi(getter)] - pub fn ed25519(&self) -> Ed25519PublicKey { - self.ed25519.clone() - } - - /// The Curve25519 public key, used for establish shared secrets. - #[napi(getter)] - pub fn curve25519(&self) -> Curve25519PublicKey { - self.curve25519.clone() - } -} - -impl From for IdentityKeys { - fn from(value: matrix_sdk_crypto::olm::IdentityKeys) -> Self { - Self { - ed25519: Ed25519PublicKey { inner: value.ed25519 }, - curve25519: Curve25519PublicKey { inner: value.curve25519 }, - } - } -} diff --git a/bindings/matrix-sdk-crypto-nodejs/tests/attachment.test.js b/bindings/matrix-sdk-crypto-nodejs/tests/attachment.test.js deleted file mode 100644 index 99dc632c1..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/tests/attachment.test.js +++ /dev/null @@ -1,83 +0,0 @@ -const { Attachment, EncryptedAttachment } = require("../"); - -describe(Attachment.name, () => { - const originalData = "hello"; - const textEncoder = new TextEncoder(); - const textDecoder = new TextDecoder(); - - let encryptedAttachment; - - test("can encrypt data", () => { - encryptedAttachment = Attachment.encrypt(textEncoder.encode(originalData)); - - const mediaEncryptionInfo = JSON.parse(encryptedAttachment.mediaEncryptionInfo); - - expect(mediaEncryptionInfo).toMatchObject({ - v: "v2", - key: { - kty: expect.any(String), - key_ops: expect.arrayContaining(["encrypt", "decrypt"]), - alg: expect.any(String), - k: expect.any(String), - ext: expect.any(Boolean), - }, - iv: expect.stringMatching(/^[A-Za-z0-9\+/]+$/), - hashes: { - sha256: expect.stringMatching(/^[A-Za-z0-9\+/]+$/), - }, - }); - - const encryptedData = encryptedAttachment.encryptedData; - expect( - encryptedData.every((i) => { - i != 0; - }), - ).toStrictEqual(false); - }); - - test("can decrypt data", () => { - expect(encryptedAttachment.hasMediaEncryptionInfoBeenConsumed).toStrictEqual(false); - - const decryptedAttachment = Attachment.decrypt(encryptedAttachment); - - expect(textDecoder.decode(decryptedAttachment)).toStrictEqual(originalData); - expect(encryptedAttachment.hasMediaEncryptionInfoBeenConsumed).toStrictEqual(true); - }); - - test("can only decrypt once", () => { - expect(encryptedAttachment.hasMediaEncryptionInfoBeenConsumed).toStrictEqual(true); - - expect(() => { - textDecoder.decode(decryptedAttachment); - }).toThrow(); - }); -}); - -describe(EncryptedAttachment.name, () => { - const originalData = "hello"; - const textDecoder = new TextDecoder(); - - test("can be created manually", () => { - const encryptedAttachment = new EncryptedAttachment( - new Uint8Array([24, 150, 67, 37, 144]), - JSON.stringify({ - v: "v2", - key: { - kty: "oct", - key_ops: ["encrypt", "decrypt"], - alg: "A256CTR", - k: "QbNXUjuukFyEJ8cQZjJuzN6mMokg0HJIjx0wVMLf5BM", - ext: true, - }, - iv: "xk2AcWkomiYAAAAAAAAAAA", - hashes: { - sha256: "JsRbDXgOja4xvDiF3DwBuLHdxUzIrVYIuj7W/t3aEok", - }, - }), - ); - - expect(encryptedAttachment.hasMediaEncryptionInfoBeenConsumed).toStrictEqual(false); - expect(textDecoder.decode(Attachment.decrypt(encryptedAttachment))).toStrictEqual(originalData); - expect(encryptedAttachment.hasMediaEncryptionInfoBeenConsumed).toStrictEqual(true); - }); -}); diff --git a/bindings/matrix-sdk-crypto-nodejs/tests/encryption.test.js b/bindings/matrix-sdk-crypto-nodejs/tests/encryption.test.js deleted file mode 100644 index aac973150..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/tests/encryption.test.js +++ /dev/null @@ -1,30 +0,0 @@ -const { EncryptionAlgorithm, EncryptionSettings, HistoryVisibility, VerificationState } = require("../"); - -describe("EncryptionAlgorithm", () => { - test("has the correct variant values", () => { - expect(EncryptionAlgorithm.OlmV1Curve25519AesSha2).toStrictEqual(0); - expect(EncryptionAlgorithm.MegolmV1AesSha2).toStrictEqual(1); - }); -}); - -describe(EncryptionSettings.name, () => { - test("can be instantiated with default values", () => { - const es = new EncryptionSettings(); - - expect(es.algorithm).toStrictEqual(EncryptionAlgorithm.MegolmV1AesSha2); - expect(es.rotationPeriod).toStrictEqual(604800000000n); - expect(es.rotationPeriodMessages).toStrictEqual(100n); - expect(es.historyVisibility).toStrictEqual(HistoryVisibility.Shared); - }); - - test("checks the history visibility values", () => { - const es = new EncryptionSettings(); - - es.historyVisibility = HistoryVisibility.Invited; - - expect(es.historyVisibility).toStrictEqual(HistoryVisibility.Invited); - expect(() => { - es.historyVisibility = 42; - }).toThrow(); - }); -}); diff --git a/bindings/matrix-sdk-crypto-nodejs/tests/events.test.js b/bindings/matrix-sdk-crypto-nodejs/tests/events.test.js deleted file mode 100644 index cec4d57e0..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/tests/events.test.js +++ /dev/null @@ -1,10 +0,0 @@ -const { HistoryVisibility } = require("../"); - -describe("HistoryVisibility", () => { - test("has the correct variant values", () => { - expect(HistoryVisibility.Invited).toStrictEqual(0); - expect(HistoryVisibility.Joined).toStrictEqual(1); - expect(HistoryVisibility.Shared).toStrictEqual(2); - expect(HistoryVisibility.WorldReadable).toStrictEqual(3); - }); -}); diff --git a/bindings/matrix-sdk-crypto-nodejs/tests/identifiers.test.js b/bindings/matrix-sdk-crypto-nodejs/tests/identifiers.test.js deleted file mode 100644 index f08e67d00..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/tests/identifiers.test.js +++ /dev/null @@ -1,140 +0,0 @@ -const { - UserId, - DeviceId, - DeviceKeyId, - DeviceKeyAlgorithm, - DeviceKeyAlgorithmName, - RoomId, - ServerName, -} = require("../"); - -describe(UserId.name, () => { - test("cannot be invalid", () => { - expect(() => { - new UserId("@foobar"); - }).toThrow(); - }); - - const user = new UserId("@foo:bar.org"); - - test("localpart is present", () => { - expect(user.localpart).toStrictEqual("foo"); - }); - - test("server name is present", () => { - expect(user.serverName).toBeInstanceOf(ServerName); - }); - - test("user ID is not historical", () => { - expect(user.isHistorical()).toStrictEqual(false); - }); - - test("can read the user ID as a string", () => { - expect(user.toString()).toStrictEqual("@foo:bar.org"); - }); -}); - -describe(DeviceId.name, () => { - const device = new DeviceId("foo"); - - test("can read the device ID as a string", () => { - expect(device.toString()).toStrictEqual("foo"); - }); -}); - -describe(DeviceKeyId.name, () => { - for (const deviceKey of [ - { - name: "ed25519", - id: "ed25519:foobar", - algorithmName: DeviceKeyAlgorithmName.Ed25519, - algorithm: "ed25519", - deviceId: "foobar", - }, - - { - name: "curve25519", - id: "curve25519:foobar", - algorithmName: DeviceKeyAlgorithmName.Curve25519, - algorithm: "curve25519", - deviceId: "foobar", - }, - - { - name: "signed curve25519", - id: "signed_curve25519:foobar", - algorithmName: DeviceKeyAlgorithmName.SignedCurve25519, - algorithm: "signed_curve25519", - deviceId: "foobar", - }, - - { - name: "unknown", - id: "hello:foobar", - algorithmName: DeviceKeyAlgorithmName.Unknown, - algorithm: "hello", - deviceId: "foobar", - }, - ]) { - test(`${deviceKey.name} algorithm`, () => { - const dk = new DeviceKeyId(deviceKey.id); - - expect(dk.algorithm.name).toStrictEqual(deviceKey.algorithmName); - expect(dk.algorithm.toString()).toStrictEqual(deviceKey.algorithm); - expect(dk.deviceId.toString()).toStrictEqual(deviceKey.deviceId); - expect(dk.toString()).toStrictEqual(deviceKey.id); - }); - } -}); - -describe("DeviceKeyAlgorithmName", () => { - test("has the correct variants", () => { - expect(DeviceKeyAlgorithmName.Ed25519).toStrictEqual(0); - expect(DeviceKeyAlgorithmName.Curve25519).toStrictEqual(1); - expect(DeviceKeyAlgorithmName.SignedCurve25519).toStrictEqual(2); - expect(DeviceKeyAlgorithmName.Unknown).toStrictEqual(3); - }); -}); - -describe(RoomId.name, () => { - test("cannot be invalid", () => { - expect(() => { - new RoomId("!foo"); - }).toThrow(); - }); - - const room = new RoomId("!foo:bar.org"); - - test("localpart is present", () => { - expect(room.localpart).toStrictEqual("foo"); - }); - - test("server name is present", () => { - expect(room.serverName).toBeInstanceOf(ServerName); - }); - - test("can read the room ID as string", () => { - expect(room.toString()).toStrictEqual("!foo:bar.org"); - }); -}); - -describe(ServerName.name, () => { - test("cannot be invalid", () => { - expect(() => { - new ServerName("@foobar"); - }).toThrow(); - }); - - test("host is present", () => { - expect(new ServerName("foo.org").host).toStrictEqual("foo.org"); - }); - - test("port can be optional", () => { - expect(new ServerName("foo.org").port).toStrictEqual(null); - expect(new ServerName("foo.org:1234").port).toStrictEqual(1234); - }); - - test("server is not an IP literal", () => { - expect(new ServerName("foo.org").isIpLiteral()).toStrictEqual(false); - }); -}); diff --git a/bindings/matrix-sdk-crypto-nodejs/tests/machine.test.js b/bindings/matrix-sdk-crypto-nodejs/tests/machine.test.js deleted file mode 100644 index 6c2024895..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/tests/machine.test.js +++ /dev/null @@ -1,483 +0,0 @@ -const { - OlmMachine, - UserId, - DeviceId, - DeviceKeyId, - RoomId, - DeviceLists, - RequestType, - KeysUploadRequest, - KeysQueryRequest, - KeysClaimRequest, - EncryptionSettings, - DecryptedRoomEvent, - VerificationState, - CrossSigningStatus, - MaybeSignature, - ShieldColor, - StoreType, - Versions, - getVersions, -} = require("../"); -const path = require("path"); -const os = require("os"); -const fs = require("fs/promises"); - -describe("StoreType", () => { - test("has the correct variant values", () => { - expect(StoreType.Sqlite).toStrictEqual(0); - }); -}); - -describe("Versions", () => { - test("can find out the crate versions", async () => { - const versions = getVersions(); - - expect(versions).toBeInstanceOf(Versions); - expect(versions.vodozemac).toBeDefined(); - expect(versions.matrixSdkCrypto).toBeDefined(); - }); -}); - -describe(OlmMachine.name, () => { - test("cannot be instantiated with the constructor", () => { - expect(() => { - new OlmMachine(); - }).toThrow(); - }); - - test("can be instantiated with the async initializer", async () => { - expect(await OlmMachine.initialize(new UserId("@foo:bar.org"), new DeviceId("baz"))).toBeInstanceOf(OlmMachine); - }); - - describe("can be instantiated with a store", () => { - for (const [store_type, store_name] of [ - [StoreType.Sqlite, "sqlite"], - [null, "default"], - ]) { - test(`with no passphrase (store: ${store_name})`, async () => { - const temp_directory = await fs.mkdtemp(path.join(os.tmpdir(), "matrix-sdk-crypto--")); - - expect( - await OlmMachine.initialize( - new UserId("@foo:bar.org"), - new DeviceId("baz"), - temp_directory, - null, - store_type, - ), - ).toBeInstanceOf(OlmMachine); - }); - - test(`with a passphrase (store: ${store_name})`, async () => { - const temp_directory = await fs.mkdtemp(path.join(os.tmpdir(), "matrix-sdk-crypto--")); - - expect( - await OlmMachine.initialize( - new UserId("@foo:bar.org"), - new DeviceId("baz"), - temp_directory, - "hello", - store_type, - ), - ).toBeInstanceOf(OlmMachine); - }); - } - }); - - const user = new UserId("@alice:example.org"); - const device = new DeviceId("foobar"); - const room = new RoomId("!baz:matrix.org"); - - function machine(new_user, new_device) { - return OlmMachine.initialize(new_user || user, new_device || device); - } - - test("can drop/close, and then re-open", async () => { - const temp_directory = await fs.mkdtemp(path.join(os.tmpdir(), "matrix-sdk-crypto--")); - - let m1 = await OlmMachine.initialize( - new UserId("@test:bar.org"), - new DeviceId("device"), - temp_directory, - "hello", - ); - m1.close(); - - let m2 = await OlmMachine.initialize( - new UserId("@test:bar.org"), - new DeviceId("device"), - temp_directory, - "hello", - ); - m2.close(); - }); - - test("can read user ID", async () => { - expect((await machine()).userId.toString()).toStrictEqual(user.toString()); - }); - - test("can read device ID", async () => { - expect((await machine()).deviceId.toString()).toStrictEqual(device.toString()); - }); - - test("can read identity keys", async () => { - const identityKeys = (await machine()).identityKeys; - - expect(identityKeys.ed25519.toBase64()).toMatch(/^[A-Za-z0-9+/]+$/); - expect(identityKeys.curve25519.toBase64()).toMatch(/^[A-Za-z0-9+/]+$/); - }); - - test("can receive sync changes", async () => { - const m = await machine(); - const toDeviceEvents = JSON.stringify([]); - const changedDevices = new DeviceLists(); - const oneTimeKeyCounts = {}; - const unusedFallbackKeys = []; - - const receiveSyncChanges = JSON.parse( - await m.receiveSyncChanges(toDeviceEvents, changedDevices, oneTimeKeyCounts, unusedFallbackKeys), - ); - - expect(receiveSyncChanges).toEqual([[], []]); - }); - - test("can get the outgoing requests that need to be send out", async () => { - const m = await machine(); - const toDeviceEvents = JSON.stringify([]); - const changedDevices = new DeviceLists(); - const oneTimeKeyCounts = {}; - const unusedFallbackKeys = []; - - const receiveSyncChanges = JSON.parse( - await m.receiveSyncChanges(toDeviceEvents, changedDevices, oneTimeKeyCounts, unusedFallbackKeys), - ); - - expect(receiveSyncChanges).toEqual([[], []]); - - const outgoingRequests = await m.outgoingRequests(); - - expect(outgoingRequests).toHaveLength(2); - - { - expect(outgoingRequests[0]).toBeInstanceOf(KeysUploadRequest); - expect(outgoingRequests[0].id).toBeDefined(); - expect(outgoingRequests[0].type).toStrictEqual(RequestType.KeysUpload); - - const body = JSON.parse(outgoingRequests[0].body); - expect(body.device_keys).toBeDefined(); - expect(body.one_time_keys).toBeDefined(); - } - - { - expect(outgoingRequests[1]).toBeInstanceOf(KeysQueryRequest); - expect(outgoingRequests[1].id).toBeDefined(); - expect(outgoingRequests[1].type).toStrictEqual(RequestType.KeysQuery); - - const body = JSON.parse(outgoingRequests[1].body); - expect(body.timeout).toBeDefined(); - expect(body.device_keys).toBeDefined(); - expect(body.token).toBeDefined(); - } - }); - - describe("setup workflow to mark requests as sent", () => { - let m; - let ougoingRequests; - - beforeAll(async () => { - m = await machine(new UserId("@alice:example.org"), new DeviceId("DEVICEID")); - - const toDeviceEvents = JSON.stringify([]); - const changedDevices = new DeviceLists(); - const oneTimeKeyCounts = {}; - const unusedFallbackKeys = []; - - await m.receiveSyncChanges(toDeviceEvents, changedDevices, oneTimeKeyCounts, unusedFallbackKeys); - outgoingRequests = await m.outgoingRequests(); - - expect(outgoingRequests).toHaveLength(2); - }); - - test("can mark requests as sent", async () => { - { - const request = outgoingRequests[0]; - expect(request).toBeInstanceOf(KeysUploadRequest); - - // https://spec.matrix.org/v1.2/client-server-api/#post_matrixclientv3keysupload - const hypothetical_response = JSON.stringify({ - one_time_key_counts: { - curve25519: 10, - signed_curve25519: 20, - }, - }); - const marked = await m.markRequestAsSent(request.id, request.type, hypothetical_response); - expect(marked).toStrictEqual(true); - } - - { - const request = outgoingRequests[1]; - expect(request).toBeInstanceOf(KeysQueryRequest); - - // https://spec.matrix.org/v1.2/client-server-api/#post_matrixclientv3keysquery - const hypothetical_response = JSON.stringify({ - device_keys: { - "@alice:example.org": { - JLAFKJWSCS: { - algorithms: ["m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"], - device_id: "JLAFKJWSCS", - keys: { - "curve25519:JLAFKJWSCS": "wjLpTLRqbqBzLs63aYaEv2Boi6cFEbbM/sSRQ2oAKk4", - "ed25519:JLAFKJWSCS": "nE6W2fCblxDcOFmeEtCHNl8/l8bXcu7GKyAswA4r3mM", - }, - signatures: { - "@alice:example.org": { - "ed25519:JLAFKJWSCS": - "m53Wkbh2HXkc3vFApZvCrfXcX3AI51GsDHustMhKwlv3TuOJMj4wistcOTM8q2+e/Ro7rWFUb9ZfnNbwptSUBA", - }, - }, - unsigned: { - device_display_name: "Alice's mobile phone", - }, - user_id: "@alice:example.org", - }, - }, - }, - failures: {}, - }); - const marked = await m.markRequestAsSent(request.id, request.type, hypothetical_response); - expect(marked).toStrictEqual(true); - } - }); - }); - - describe("setup workflow to encrypt/decrypt events", () => { - let m; - const user = new UserId("@alice:example.org"); - const device = new DeviceId("JLAFKJWSCS"); - const room = new RoomId("!test:localhost"); - - beforeAll(async () => { - m = await machine(user, device); - }); - - test("can pass keysquery and keysclaim requests directly", async () => { - { - // derived from https://github.com/matrix-org/matrix-rust-sdk/blob/7f49618d350fab66b7e1dc4eaf64ec25ceafd658/benchmarks/benches/crypto_bench/keys_query.json - const hypothetical_response = JSON.stringify({ - device_keys: { - "@example:localhost": { - AFGUOBTZWM: { - algorithms: ["m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"], - device_id: "AFGUOBTZWM", - keys: { - "curve25519:AFGUOBTZWM": "boYjDpaC+7NkECQEeMh5dC+I1+AfriX0VXG2UV7EUQo", - "ed25519:AFGUOBTZWM": "NayrMQ33ObqMRqz6R9GosmHdT6HQ6b/RX/3QlZ2yiec", - }, - signatures: { - "@example:localhost": { - "ed25519:AFGUOBTZWM": - "RoSWvru1jj6fs2arnTedWsyIyBmKHMdOu7r9gDi0BZ61h9SbCK2zLXzuJ9ZFLao2VvA0yEd7CASCmDHDLYpXCA", - }, - }, - user_id: "@example:localhost", - unsigned: { - device_display_name: "rust-sdk", - }, - }, - }, - }, - failures: {}, - master_keys: { - "@example:localhost": { - user_id: "@example:localhost", - usage: ["master"], - keys: { - "ed25519:n2lpJGx0LiKnuNE1IucZP3QExrD4SeRP0veBHPe3XUU": - "n2lpJGx0LiKnuNE1IucZP3QExrD4SeRP0veBHPe3XUU", - }, - signatures: { - "@example:localhost": { - "ed25519:TCSJXPWGVS": - "+j9G3L41I1fe0++wwusTTQvbboYW0yDtRWUEujhwZz4MAltjLSfJvY0hxhnz+wHHmuEXvQDen39XOpr1p29sAg", - }, - }, - }, - }, - self_signing_keys: { - "@example:localhost": { - user_id: "@example:localhost", - usage: ["self_signing"], - keys: { - "ed25519:kQXOuy639Yt47mvNTdrIluoC6DMvfbZLYbxAmwiDyhI": - "kQXOuy639Yt47mvNTdrIluoC6DMvfbZLYbxAmwiDyhI", - }, - signatures: { - "@example:localhost": { - "ed25519:n2lpJGx0LiKnuNE1IucZP3QExrD4SeRP0veBHPe3XUU": - "q32ifix/qyRpvmegw2BEJklwoBCAJldDNkcX+fp+lBA4Rpyqtycxge6BA4hcJdxYsy3oV0IHRuugS8rJMMFyAA", - }, - }, - }, - }, - user_signing_keys: { - "@example:localhost": { - user_id: "@example:localhost", - usage: ["user_signing"], - keys: { - "ed25519:g4ED07Fnqf3GzVWNN1pZ0IFrPQVdqQf+PYoJNH4eE0s": - "g4ED07Fnqf3GzVWNN1pZ0IFrPQVdqQf+PYoJNH4eE0s", - }, - signatures: { - "@example:localhost": { - "ed25519:n2lpJGx0LiKnuNE1IucZP3QExrD4SeRP0veBHPe3XUU": - "nKQu8alQKDefNbZz9luYPcNj+Z+ouQSot4fU/A23ELl1xrI06QVBku/SmDx0sIW1ytso0Cqwy1a+3PzCa1XABg", - }, - }, - }, - }, - }); - const marked = await m.markRequestAsSent("foo", RequestType.KeysQuery, hypothetical_response); - } - - { - // derived from https://github.com/matrix-org/matrix-rust-sdk/blob/7f49618d350fab66b7e1dc4eaf64ec25ceafd658/benchmarks/benches/crypto_bench/keys_claim.json - const hypothetical_response = JSON.stringify({ - one_time_keys: { - "@example:localhost": { - AFGUOBTZWM: { - "signed_curve25519:AAAABQ": { - key: "9IGouMnkB6c6HOd4xUsNv4i3Dulb4IS96TzDordzOws", - signatures: { - "@example:localhost": { - "ed25519:AFGUOBTZWM": - "2bvUbbmJegrV0eVP/vcJKuIWC3kud+V8+C0dZtg4dVovOSJdTP/iF36tQn2bh5+rb9xLlSeztXBdhy4c+LiOAg", - }, - }, - }, - }, - }, - }, - failures: {}, - }); - const marked = await m.markRequestAsSent("bar", RequestType.KeysClaim, hypothetical_response); - } - }); - - test("can share a room key", async () => { - const other_users = [new UserId("@example:localhost")]; - - const requests = JSON.parse(await m.shareRoomKey(room, other_users, new EncryptionSettings())); - - expect(requests).toHaveLength(1); - expect(requests[0].event_type).toBeDefined(); - expect(requests[0].txn_id).toBeDefined(); - expect(requests[0].messages).toBeDefined(); - expect(requests[0].messages["@example:localhost"]).toBeDefined(); - }); - - let encrypted; - - test("can encrypt an event", async () => { - encrypted = JSON.parse( - await m.encryptRoomEvent( - room, - "m.room.message", - JSON.stringify({ - hello: "world", - }), - ), - ); - - expect(encrypted.algorithm).toBeDefined(); - expect(encrypted.ciphertext).toBeDefined(); - expect(encrypted.sender_key).toBeDefined(); - expect(encrypted.device_id).toStrictEqual(device.toString()); - expect(encrypted.session_id).toBeDefined(); - }); - - test("can decrypt an event", async () => { - const decrypted = await m.decryptRoomEvent( - JSON.stringify({ - type: "m.room.encrypted", - event_id: "$xxxxx:example.org", - origin_server_ts: Date.now(), - sender: user.toString(), - content: encrypted, - unsigned: { - age: 1234, - }, - }), - room, - ); - - expect(decrypted).toBeInstanceOf(DecryptedRoomEvent); - - const event = JSON.parse(decrypted.event); - expect(event.content.hello).toStrictEqual("world"); - - expect(decrypted.sender.toString()).toStrictEqual(user.toString()); - expect(decrypted.senderDevice.toString()).toStrictEqual(device.toString()); - expect(decrypted.senderCurve25519Key).toBeDefined(); - expect(decrypted.senderClaimedEd25519Key).toBeDefined(); - expect(decrypted.forwardingCurve25519KeyChain).toHaveLength(0); - expect(decrypted.shieldState(true).color).toStrictEqual(ShieldColor.Red); - expect(decrypted.shieldState(false).color).toStrictEqual(ShieldColor.Red); - }); - }); - - test("can update tracked users", async () => { - const m = await machine(); - - expect(await m.updateTrackedUsers([user])).toStrictEqual(undefined); - }); - - test("can read cross-signing status", async () => { - const m = await machine(); - const crossSigningStatus = await m.crossSigningStatus(); - - expect(crossSigningStatus).toBeInstanceOf(CrossSigningStatus); - expect(crossSigningStatus.hasMaster).toStrictEqual(false); - expect(crossSigningStatus.hasSelfSigning).toStrictEqual(false); - expect(crossSigningStatus.hasUserSigning).toStrictEqual(false); - }); - - test("can sign a message", async () => { - const m = await machine(); - const signatures = await m.sign("foo"); - - expect(signatures.isEmpty).toStrictEqual(false); - expect(signatures.count).toStrictEqual(1n); - - let base64; - - // `get` - { - const signature = signatures.get(user); - - expect(signature).toMatchObject({ - "ed25519:foobar": expect.any(MaybeSignature), - }); - expect(signature["ed25519:foobar"].isValid).toStrictEqual(true); - expect(signature["ed25519:foobar"].isInvalid).toStrictEqual(false); - expect(signature["ed25519:foobar"].invalidSignatureSource).toBeNull(); - - base64 = signature["ed25519:foobar"].signature.toBase64(); - - expect(base64).toMatch(/^[A-Za-z0-9\+/]+$/); - expect(signature["ed25519:foobar"].signature.ed25519.toBase64()).toStrictEqual(base64); - } - - // `getSignature` - { - const signature = signatures.getSignature(user, new DeviceKeyId("ed25519:foobar")); - expect(signature.toBase64()).toStrictEqual(base64); - } - - // Unknown signatures. - { - expect(signatures.get(new UserId("@hello:example.org"))).toBeNull(); - expect(signatures.getSignature(user, new DeviceKeyId("world:foobar"))).toBeNull(); - } - }); -}); diff --git a/bindings/matrix-sdk-crypto-nodejs/tests/requests.test.js b/bindings/matrix-sdk-crypto-nodejs/tests/requests.test.js deleted file mode 100644 index 51aeb3944..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/tests/requests.test.js +++ /dev/null @@ -1,40 +0,0 @@ -const { - RequestType, - KeysUploadRequest, - KeysQueryRequest, - KeysClaimRequest, - ToDeviceRequest, - SignatureUploadRequest, - RoomMessageRequest, - KeysBackupRequest, -} = require("../"); - -describe("RequestType", () => { - test("has the correct variant values", () => { - expect(RequestType.KeysUpload).toStrictEqual(0); - expect(RequestType.KeysQuery).toStrictEqual(1); - expect(RequestType.KeysClaim).toStrictEqual(2); - expect(RequestType.ToDevice).toStrictEqual(3); - expect(RequestType.SignatureUpload).toStrictEqual(4); - expect(RequestType.RoomMessage).toStrictEqual(5); - expect(RequestType.KeysBackup).toStrictEqual(6); - }); -}); - -for (const request of [ - KeysUploadRequest, - KeysQueryRequest, - KeysClaimRequest, - ToDeviceRequest, - SignatureUploadRequest, - RoomMessageRequest, - KeysBackupRequest, -]) { - describe(request.name, () => { - test("cannot be instantiated", () => { - expect(() => { - new request(); - }).toThrow(); - }); - }); -} diff --git a/bindings/matrix-sdk-crypto-nodejs/tests/responses.test.js b/bindings/matrix-sdk-crypto-nodejs/tests/responses.test.js deleted file mode 100644 index 924f00d7b..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/tests/responses.test.js +++ /dev/null @@ -1,9 +0,0 @@ -const { DecryptedRoomEvent } = require("../"); - -describe(DecryptedRoomEvent.name, () => { - test("cannot be instantiated", () => { - expect(() => { - new DecryptedRoomEvent(); - }).toThrow(); - }); -}); diff --git a/bindings/matrix-sdk-crypto-nodejs/tests/sync_events.test.js b/bindings/matrix-sdk-crypto-nodejs/tests/sync_events.test.js deleted file mode 100644 index c52e180ac..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/tests/sync_events.test.js +++ /dev/null @@ -1,31 +0,0 @@ -const { DeviceLists, UserId } = require("../"); - -describe(DeviceLists.name, () => { - test("can be empty", () => { - const empty = new DeviceLists(); - - expect(empty.isEmpty()).toStrictEqual(true); - expect(empty.changed).toHaveLength(0); - expect(empty.left).toHaveLength(0); - }); - - test("can be coerced empty", () => { - const empty = new DeviceLists([], []); - - expect(empty.isEmpty()).toStrictEqual(true); - expect(empty.changed).toHaveLength(0); - expect(empty.left).toHaveLength(0); - }); - - test("returns the correct `changed` and `left`", () => { - const list = new DeviceLists([new UserId("@foo:bar.org")], [new UserId("@baz:qux.org")]); - - expect(list.isEmpty()).toStrictEqual(false); - - expect(list.changed).toHaveLength(1); - expect(list.changed[0].toString()).toStrictEqual("@foo:bar.org"); - - expect(list.left).toHaveLength(1); - expect(list.left[0].toString()).toStrictEqual("@baz:qux.org"); - }); -}); diff --git a/bindings/matrix-sdk-crypto-nodejs/tsconfig.json b/bindings/matrix-sdk-crypto-nodejs/tsconfig.json deleted file mode 100644 index fbbcf4105..000000000 --- a/bindings/matrix-sdk-crypto-nodejs/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "strict": true - }, - "typedocOptions": { - "entryPoints": ["index.d.ts"], - "out": "docs", - "readme": "README.md" - } -} diff --git a/codecov.yaml b/codecov.yaml index 3185752e4..4aff405eb 100644 --- a/codecov.yaml +++ b/codecov.yaml @@ -28,7 +28,6 @@ coverage: ignore: - "bindings/matrix-sdk-crypto-ffi" - "bindings/matrix-sdk-crypto-js" - - "bindings/matrix-sdk-crypto-nodejs" - "bindings/matrix-sdk-ffi" - "crates/matrix-sdk-indexeddb" - "testing" diff --git a/tarpaulin.toml b/tarpaulin.toml index 9af3af97c..a6e86434c 100644 --- a/tarpaulin.toml +++ b/tarpaulin.toml @@ -14,7 +14,6 @@ exclude = [ # bindings "matrix-sdk-crypto-ffi", "matrix-sdk-crypto-js", - "matrix-sdk-crypto-nodejs", "matrix-sdk-ffi", # wasm only, can't get coverage "matrix-sdk-indexeddb",