mirror of
https://github.com/element-hq/synapse.git
synced 2025-07-04 00:00:27 -04:00
Compare commits
29 Commits
007c0ea42e
...
179815a90f
Author | SHA1 | Date | |
---|---|---|---|
|
179815a90f | ||
|
e6b8eedd02 | ||
|
87fc518e0c | ||
|
3bd476eb0d | ||
|
717f67f3d3 | ||
|
c2108948a3 | ||
|
cb4b5585a4 | ||
|
a3ec2d3b3f | ||
|
81ca2923d1 | ||
|
2372f3e6b7 | ||
|
82757144e9 | ||
|
2f9c9d5eba | ||
|
6ddbb03612 | ||
|
cc8da2c5ed | ||
|
af6ca26af0 | ||
|
17ce194081 | ||
|
8d7eddd6f9 | ||
|
65d7b41b1c | ||
|
4323879d23 | ||
|
80e0979653 | ||
|
5a53b9337f | ||
|
656b648420 | ||
|
5ad9e66fdd | ||
|
e4a1014209 | ||
|
b6aa6c0ccf | ||
|
e8d328f3bb | ||
|
8c606cd397 | ||
|
ce555e7cf7 | ||
|
0766119fc9 |
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
@ -30,7 +30,7 @@ jobs:
|
|||||||
run: docker buildx inspect
|
run: docker buildx inspect
|
||||||
|
|
||||||
- name: Install Cosign
|
- name: Install Cosign
|
||||||
uses: sigstore/cosign-installer@fb28c2b6339dcd94da6e4cbcbc5e888961f6f8c3 # v3.9.0
|
uses: sigstore/cosign-installer@398d4b0eeef1380460a10c8013a76f728fb906ac # v3.9.1
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
15
.github/workflows/fix_lint.yaml
vendored
15
.github/workflows/fix_lint.yaml
vendored
@ -6,6 +6,11 @@ name: Attempt to automatically fix linting errors
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
# We use nightly so that `fmt` correctly groups together imports, and
|
||||||
|
# clippy correctly fixes up the benchmarks.
|
||||||
|
RUST_VERSION: nightly-2025-06-24
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
fixup:
|
fixup:
|
||||||
name: Fix up
|
name: Fix up
|
||||||
@ -16,13 +21,11 @@ jobs:
|
|||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@56f84321dbccf38fb67ce29ab63e4754056677e0 # master (rust 1.85.1)
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
with:
|
with:
|
||||||
# We use nightly so that `fmt` correctly groups together imports, and
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
# clippy correctly fixes up the benchmarks.
|
|
||||||
toolchain: nightly-2022-12-01
|
|
||||||
components: clippy, rustfmt
|
components: clippy, rustfmt
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
- name: Setup Poetry
|
- name: Setup Poetry
|
||||||
uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||||
@ -44,6 +47,6 @@ jobs:
|
|||||||
- run: cargo fmt
|
- run: cargo fmt
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
- uses: stefanzweifel/git-auto-commit-action@b863ae1933cb653a53c021fe36dbb774e1fb9403 # v5.2.0
|
- uses: stefanzweifel/git-auto-commit-action@778341af668090896ca464160c2def5d1d1a3eb0 # v6.0.1
|
||||||
with:
|
with:
|
||||||
commit_message: "Attempt to fix linting"
|
commit_message: "Attempt to fix linting"
|
||||||
|
21
.github/workflows/latest_deps.yml
vendored
21
.github/workflows/latest_deps.yml
vendored
@ -21,6 +21,9 @@ concurrency:
|
|||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
RUST_VERSION: 1.87.0
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check_repo:
|
check_repo:
|
||||||
# Prevent this workflow from running on any fork of Synapse other than element-hq/synapse, as it is
|
# Prevent this workflow from running on any fork of Synapse other than element-hq/synapse, as it is
|
||||||
@ -41,8 +44,10 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable (rust 1.85.1)
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
# The dev dependencies aren't exposed in the wheel metadata (at least with current
|
# The dev dependencies aren't exposed in the wheel metadata (at least with current
|
||||||
# poetry-core versions), so we install with poetry.
|
# poetry-core versions), so we install with poetry.
|
||||||
@ -75,8 +80,10 @@ jobs:
|
|||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable (rust 1.85.1)
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
- run: sudo apt-get -qq install xmlsec1
|
- run: sudo apt-get -qq install xmlsec1
|
||||||
- name: Set up PostgreSQL ${{ matrix.postgres-version }}
|
- name: Set up PostgreSQL ${{ matrix.postgres-version }}
|
||||||
@ -148,8 +155,10 @@ jobs:
|
|||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable (rust 1.85.1)
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
- name: Ensure sytest runs `pip install`
|
- name: Ensure sytest runs `pip install`
|
||||||
# Delete the lockfile so sytest will `pip install` rather than `poetry install`
|
# Delete the lockfile so sytest will `pip install` rather than `poetry install`
|
||||||
|
68
.github/workflows/tests.yml
vendored
68
.github/workflows/tests.yml
vendored
@ -11,6 +11,9 @@ concurrency:
|
|||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
RUST_VERSION: 1.87.0
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Job to detect what has changed so we don't run e.g. Rust checks on PRs that
|
# Job to detect what has changed so we don't run e.g. Rust checks on PRs that
|
||||||
# don't modify Rust code.
|
# don't modify Rust code.
|
||||||
@ -85,8 +88,10 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@c1678930c21fb233e4987c4ae12158f9125e5762 # 1.81.0
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||||
with:
|
with:
|
||||||
python-version: "3.x"
|
python-version: "3.x"
|
||||||
@ -149,8 +154,10 @@ jobs:
|
|||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@c1678930c21fb233e4987c4ae12158f9125e5762 # 1.81.0
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
- name: Setup Poetry
|
- name: Setup Poetry
|
||||||
uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||||
@ -210,8 +217,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@c1678930c21fb233e4987c4ae12158f9125e5762 # 1.81.0
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||||
with:
|
with:
|
||||||
poetry-version: "2.1.1"
|
poetry-version: "2.1.1"
|
||||||
@ -227,10 +236,11 @@ jobs:
|
|||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@0d72692bcfbf448b1e2afa01a67f71b455a9dcec # 1.86.0
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
with:
|
with:
|
||||||
components: clippy
|
components: clippy
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
- run: cargo clippy -- -D warnings
|
- run: cargo clippy -- -D warnings
|
||||||
|
|
||||||
@ -245,11 +255,11 @@ jobs:
|
|||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@56f84321dbccf38fb67ce29ab63e4754056677e0 # master (rust 1.85.1)
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
with:
|
with:
|
||||||
toolchain: nightly-2025-04-23
|
toolchain: nightly-2025-04-23
|
||||||
components: clippy
|
components: clippy
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
- run: cargo clippy --all-features -- -D warnings
|
- run: cargo clippy --all-features -- -D warnings
|
||||||
|
|
||||||
@ -262,12 +272,12 @@ jobs:
|
|||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@56f84321dbccf38fb67ce29ab63e4754056677e0 # master (rust 1.85.1)
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
with:
|
with:
|
||||||
# We use nightly so that it correctly groups together imports
|
# We use nightly so that it correctly groups together imports
|
||||||
toolchain: nightly-2025-04-23
|
toolchain: nightly-2025-04-23
|
||||||
components: rustfmt
|
components: rustfmt
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
- run: cargo fmt --check
|
- run: cargo fmt --check
|
||||||
|
|
||||||
@ -362,8 +372,10 @@ jobs:
|
|||||||
postgres:${{ matrix.job.postgres-version }}
|
postgres:${{ matrix.job.postgres-version }}
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@c1678930c21fb233e4987c4ae12158f9125e5762 # 1.81.0
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||||
with:
|
with:
|
||||||
@ -404,8 +416,10 @@ jobs:
|
|||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@c1678930c21fb233e4987c4ae12158f9125e5762 # 1.81.0
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
# There aren't wheels for some of the older deps, so we need to install
|
# There aren't wheels for some of the older deps, so we need to install
|
||||||
# their build dependencies
|
# their build dependencies
|
||||||
@ -519,8 +533,10 @@ jobs:
|
|||||||
run: cat sytest-blacklist .ci/worker-blacklist > synapse-blacklist-with-workers
|
run: cat sytest-blacklist .ci/worker-blacklist > synapse-blacklist-with-workers
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@c1678930c21fb233e4987c4ae12158f9125e5762 # 1.81.0
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
- name: Run SyTest
|
- name: Run SyTest
|
||||||
run: /bootstrap.sh synapse
|
run: /bootstrap.sh synapse
|
||||||
@ -663,8 +679,10 @@ jobs:
|
|||||||
path: synapse
|
path: synapse
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@c1678930c21fb233e4987c4ae12158f9125e5762 # 1.81.0
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
- name: Prepare Complement's Prerequisites
|
- name: Prepare Complement's Prerequisites
|
||||||
run: synapse/.ci/scripts/setup_complement_prerequisites.sh
|
run: synapse/.ci/scripts/setup_complement_prerequisites.sh
|
||||||
@ -695,8 +713,10 @@ jobs:
|
|||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@c1678930c21fb233e4987c4ae12158f9125e5762 # 1.81.0
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
- run: cargo test
|
- run: cargo test
|
||||||
|
|
||||||
@ -713,10 +733,10 @@ jobs:
|
|||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@56f84321dbccf38fb67ce29ab63e4754056677e0 # master (rust 1.85.1)
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
with:
|
with:
|
||||||
toolchain: nightly-2022-12-01
|
toolchain: nightly-2022-12-01
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
- run: cargo bench --no-run
|
- run: cargo bench --no-run
|
||||||
|
|
||||||
|
21
.github/workflows/twisted_trunk.yml
vendored
21
.github/workflows/twisted_trunk.yml
vendored
@ -20,6 +20,9 @@ concurrency:
|
|||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
RUST_VERSION: 1.87.0
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check_repo:
|
check_repo:
|
||||||
# Prevent this workflow from running on any fork of Synapse other than element-hq/synapse, as it is
|
# Prevent this workflow from running on any fork of Synapse other than element-hq/synapse, as it is
|
||||||
@ -43,8 +46,10 @@ jobs:
|
|||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable (rust 1.85.1)
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||||
with:
|
with:
|
||||||
@ -69,8 +74,10 @@ jobs:
|
|||||||
- run: sudo apt-get -qq install xmlsec1
|
- run: sudo apt-get -qq install xmlsec1
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable (rust 1.85.1)
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
- uses: matrix-org/setup-python-poetry@5bbf6603c5c930615ec8a29f1b5d7d258d905aa4 # v2.0.0
|
||||||
with:
|
with:
|
||||||
@ -113,8 +120,10 @@ jobs:
|
|||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable (rust 1.85.1)
|
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # master
|
||||||
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
|
with:
|
||||||
|
toolchain: ${{ env.RUST_VERSION }}
|
||||||
|
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||||
|
|
||||||
- name: Patch dependencies
|
- name: Patch dependencies
|
||||||
# Note: The poetry commands want to create a virtualenv in /src/.venv/,
|
# Note: The poetry commands want to create a virtualenv in /src/.venv/,
|
||||||
|
31
Cargo.lock
generated
31
Cargo.lock
generated
@ -65,12 +65,6 @@ dependencies = [
|
|||||||
"windows-targets",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "base64"
|
|
||||||
version = "0.21.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.22.1"
|
version = "0.22.1"
|
||||||
@ -371,7 +365,7 @@ version = "0.4.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb"
|
checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64",
|
||||||
"bytes",
|
"bytes",
|
||||||
"headers-core",
|
"headers-core",
|
||||||
"http",
|
"http",
|
||||||
@ -491,7 +485,7 @@ version = "0.1.14"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb"
|
checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@ -664,6 +658,17 @@ version = "2.0.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
|
checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "io-uring"
|
||||||
|
version = "0.7.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.11.0"
|
version = "2.11.0"
|
||||||
@ -1059,7 +1064,7 @@ version = "0.12.20"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eabf4c97d9130e2bf606614eb937e86edac8292eaa6f422f995d7e8de1eb1813"
|
checksum = "eabf4c97d9130e2bf606614eb937e86edac8292eaa6f422f995d7e8de1eb1813"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@ -1333,7 +1338,7 @@ name = "synapse"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.21.7",
|
"base64",
|
||||||
"blake2",
|
"blake2",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures",
|
"futures",
|
||||||
@ -1429,15 +1434,17 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.45.1"
|
version = "1.46.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779"
|
checksum = "1140bb80481756a8cbe10541f37433b459c5aa1e727b4c020fbfebdc25bf3ec4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
"io-uring",
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"slab",
|
||||||
"socket2",
|
"socket2",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
1
changelog.d/18540.feature
Normal file
1
changelog.d/18540.feature
Normal file
@ -0,0 +1 @@
|
|||||||
|
Add support for [MSC4293](https://github.com/matrix-org/matrix-spec-proposals/pull/4293) - Redact on Kick/Ban.
|
1
changelog.d/18575.misc
Normal file
1
changelog.d/18575.misc
Normal file
@ -0,0 +1 @@
|
|||||||
|
Raise poetry-core version cap to 2.1.3.
|
1
changelog.d/18594.bugfix
Normal file
1
changelog.d/18594.bugfix
Normal file
@ -0,0 +1 @@
|
|||||||
|
Respond with 401 & `M_USER_LOCKED` when a locked user calls `POST /login`, as per the spec.
|
1
changelog.d/18596.misc
Normal file
1
changelog.d/18596.misc
Normal file
@ -0,0 +1 @@
|
|||||||
|
Update to Rust 1.87.0 in CI, and bump the pinned commit of the `dtolnay/rust-toolchain` GitHub Action to `b3b07ba8b418998c39fb20f53e8b695cdcc8de1b`.
|
1
changelog.d/18625.misc
Normal file
1
changelog.d/18625.misc
Normal file
@ -0,0 +1 @@
|
|||||||
|
Log the room ID we're purging state for.
|
267
poetry.lock
generated
267
poetry.lock
generated
@ -1,4 +1,4 @@
|
|||||||
# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand.
|
# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand.
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "annotated-types"
|
name = "annotated-types"
|
||||||
@ -39,7 +39,7 @@ description = "The ultimate Python library in building OAuth and OpenID Connect
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.9"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"oidc\" or extra == \"jwt\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"jwt\" or extra == \"oidc\""
|
||||||
files = [
|
files = [
|
||||||
{file = "authlib-1.5.2-py2.py3-none-any.whl", hash = "sha256:8804dd4402ac5e4a0435ac49e0b6e19e395357cfa632a3f624dcb4f6df13b4b1"},
|
{file = "authlib-1.5.2-py2.py3-none-any.whl", hash = "sha256:8804dd4402ac5e4a0435ac49e0b6e19e395357cfa632a3f624dcb4f6df13b4b1"},
|
||||||
{file = "authlib-1.5.2.tar.gz", hash = "sha256:fe85ec7e50c5f86f1e2603518bb3b4f632985eb4a355e52256530790e326c512"},
|
{file = "authlib-1.5.2.tar.gz", hash = "sha256:fe85ec7e50c5f86f1e2603518bb3b4f632985eb4a355e52256530790e326c512"},
|
||||||
@ -450,7 +450,7 @@ description = "XML bomb protection for Python stdlib modules"
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"saml2\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"saml2\""
|
||||||
files = [
|
files = [
|
||||||
{file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"},
|
{file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"},
|
||||||
{file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"},
|
{file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"},
|
||||||
@ -493,7 +493,7 @@ description = "XPath 1.0/2.0/3.0/3.1 parsers and selectors for ElementTree and l
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"saml2\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"saml2\""
|
||||||
files = [
|
files = [
|
||||||
{file = "elementpath-4.1.5-py3-none-any.whl", hash = "sha256:2ac1a2fb31eb22bbbf817f8cf6752f844513216263f0e3892c8e79782fe4bb55"},
|
{file = "elementpath-4.1.5-py3-none-any.whl", hash = "sha256:2ac1a2fb31eb22bbbf817f8cf6752f844513216263f0e3892c8e79782fe4bb55"},
|
||||||
{file = "elementpath-4.1.5.tar.gz", hash = "sha256:c2d6dc524b29ef751ecfc416b0627668119d8812441c555d7471da41d4bacb8d"},
|
{file = "elementpath-4.1.5.tar.gz", hash = "sha256:c2d6dc524b29ef751ecfc416b0627668119d8812441c555d7471da41d4bacb8d"},
|
||||||
@ -543,7 +543,7 @@ description = "Python wrapper for hiredis"
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"redis\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"redis\""
|
||||||
files = [
|
files = [
|
||||||
{file = "hiredis-3.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:2892db9db21f0cf7cc298d09f85d3e1f6dc4c4c24463ab67f79bc7a006d51867"},
|
{file = "hiredis-3.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:2892db9db21f0cf7cc298d09f85d3e1f6dc4c4c24463ab67f79bc7a006d51867"},
|
||||||
{file = "hiredis-3.1.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:93cfa6cc25ee2ceb0be81dc61eca9995160b9e16bdb7cca4a00607d57e998918"},
|
{file = "hiredis-3.1.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:93cfa6cc25ee2ceb0be81dc61eca9995160b9e16bdb7cca4a00607d57e998918"},
|
||||||
@ -889,7 +889,7 @@ description = "Jaeger Python OpenTracing Tracer implementation"
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"opentracing\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"opentracing\""
|
||||||
files = [
|
files = [
|
||||||
{file = "jaeger-client-4.8.0.tar.gz", hash = "sha256:3157836edab8e2c209bd2d6ae61113db36f7ee399e66b1dcbb715d87ab49bfe0"},
|
{file = "jaeger-client-4.8.0.tar.gz", hash = "sha256:3157836edab8e2c209bd2d6ae61113db36f7ee399e66b1dcbb715d87ab49bfe0"},
|
||||||
]
|
]
|
||||||
@ -1027,7 +1027,7 @@ description = "A strictly RFC 4510 conforming LDAP V3 pure Python client library
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"matrix-synapse-ldap3\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"matrix-synapse-ldap3\""
|
||||||
files = [
|
files = [
|
||||||
{file = "ldap3-2.9.1-py2.py3-none-any.whl", hash = "sha256:5869596fc4948797020d3f03b7939da938778a0f9e2009f7a072ccf92b8e8d70"},
|
{file = "ldap3-2.9.1-py2.py3-none-any.whl", hash = "sha256:5869596fc4948797020d3f03b7939da938778a0f9e2009f7a072ccf92b8e8d70"},
|
||||||
{file = "ldap3-2.9.1.tar.gz", hash = "sha256:f3e7fc4718e3f09dda568b57100095e0ce58633bcabbed8667ce3f8fbaa4229f"},
|
{file = "ldap3-2.9.1.tar.gz", hash = "sha256:f3e7fc4718e3f09dda568b57100095e0ce58633bcabbed8667ce3f8fbaa4229f"},
|
||||||
@ -1043,7 +1043,7 @@ description = "Powerful and Pythonic XML processing library combining libxml2/li
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"url-preview\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"url-preview\""
|
||||||
files = [
|
files = [
|
||||||
{file = "lxml-5.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e7bc6df34d42322c5289e37e9971d6ed114e3776b45fa879f734bded9d1fea9c"},
|
{file = "lxml-5.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e7bc6df34d42322c5289e37e9971d6ed114e3776b45fa879f734bded9d1fea9c"},
|
||||||
{file = "lxml-5.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6854f8bd8a1536f8a1d9a3655e6354faa6406621cf857dc27b681b69860645c7"},
|
{file = "lxml-5.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6854f8bd8a1536f8a1d9a3655e6354faa6406621cf857dc27b681b69860645c7"},
|
||||||
@ -1323,7 +1323,7 @@ description = "An LDAP3 auth provider for Synapse"
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"matrix-synapse-ldap3\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"matrix-synapse-ldap3\""
|
||||||
files = [
|
files = [
|
||||||
{file = "matrix-synapse-ldap3-0.3.0.tar.gz", hash = "sha256:8bb6517173164d4b9cc44f49de411d8cebdb2e705d5dd1ea1f38733c4a009e1d"},
|
{file = "matrix-synapse-ldap3-0.3.0.tar.gz", hash = "sha256:8bb6517173164d4b9cc44f49de411d8cebdb2e705d5dd1ea1f38733c4a009e1d"},
|
||||||
{file = "matrix_synapse_ldap3-0.3.0-py3-none-any.whl", hash = "sha256:8b4d701f8702551e98cc1d8c20dbed532de5613584c08d0df22de376ba99159d"},
|
{file = "matrix_synapse_ldap3-0.3.0-py3-none-any.whl", hash = "sha256:8b4d701f8702551e98cc1d8c20dbed532de5613584c08d0df22de376ba99159d"},
|
||||||
@ -1436,6 +1436,22 @@ files = [
|
|||||||
{file = "msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e"},
|
{file = "msgpack-1.1.0.tar.gz", hash = "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "multipart"
|
||||||
|
version = "1.2.1"
|
||||||
|
description = "Parser for multipart/form-data"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "multipart-1.2.1-py3-none-any.whl", hash = "sha256:c03dc203bc2e67f6b46a599467ae0d87cf71d7530504b2c1ff4a9ea21d8b8c8c"},
|
||||||
|
{file = "multipart-1.2.1.tar.gz", hash = "sha256:829b909b67bc1ad1c6d4488fcdc6391c2847842b08323addf5200db88dbe9480"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dev = ["build", "pytest", "pytest-cov", "twine"]
|
||||||
|
docs = ["sphinx (>=8,<9)", "sphinx-autobuild"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mypy"
|
name = "mypy"
|
||||||
version = "1.13.0"
|
version = "1.13.0"
|
||||||
@ -1544,7 +1560,7 @@ description = "OpenTracing API for Python. See documentation at http://opentraci
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"opentracing\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"opentracing\""
|
||||||
files = [
|
files = [
|
||||||
{file = "opentracing-2.4.0.tar.gz", hash = "sha256:a173117e6ef580d55874734d1fa7ecb6f3655160b8b8974a2a1e98e5ec9c840d"},
|
{file = "opentracing-2.4.0.tar.gz", hash = "sha256:a173117e6ef580d55874734d1fa7ecb6f3655160b8b8974a2a1e98e5ec9c840d"},
|
||||||
]
|
]
|
||||||
@ -1593,114 +1609,119 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pillow"
|
name = "pillow"
|
||||||
version = "11.2.1"
|
version = "11.3.0"
|
||||||
description = "Python Imaging Library (Fork)"
|
description = "Python Imaging Library (Fork)"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.9"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "pillow-11.2.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:d57a75d53922fc20c165016a20d9c44f73305e67c351bbc60d1adaf662e74047"},
|
{file = "pillow-11.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1b9c17fd4ace828b3003dfd1e30bff24863e0eb59b535e8f80194d9cc7ecf860"},
|
||||||
{file = "pillow-11.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:127bf6ac4a5b58b3d32fc8289656f77f80567d65660bc46f72c0d77e6600cc95"},
|
{file = "pillow-11.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:65dc69160114cdd0ca0f35cb434633c75e8e7fad4cf855177a05bf38678f73ad"},
|
||||||
{file = "pillow-11.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4ba4be812c7a40280629e55ae0b14a0aafa150dd6451297562e1764808bbe61"},
|
{file = "pillow-11.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1f182ebd2303acf8c380a54f615ec883322593320a9b00438eb842c1f37ae50"},
|
||||||
{file = "pillow-11.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8bd62331e5032bc396a93609982a9ab6b411c05078a52f5fe3cc59234a3abd1"},
|
{file = "pillow-11.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4445fa62e15936a028672fd48c4c11a66d641d2c05726c7ec1f8ba6a572036ae"},
|
||||||
{file = "pillow-11.2.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:562d11134c97a62fe3af29581f083033179f7ff435f78392565a1ad2d1c2c45c"},
|
{file = "pillow-11.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:71f511f6b3b91dd543282477be45a033e4845a40278fa8dcdbfdb07109bf18f9"},
|
||||||
{file = "pillow-11.2.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:c97209e85b5be259994eb5b69ff50c5d20cca0f458ef9abd835e262d9d88b39d"},
|
{file = "pillow-11.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:040a5b691b0713e1f6cbe222e0f4f74cd233421e105850ae3b3c0ceda520f42e"},
|
||||||
{file = "pillow-11.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0c3e6d0f59171dfa2e25d7116217543310908dfa2770aa64b8f87605f8cacc97"},
|
{file = "pillow-11.3.0-cp310-cp310-win32.whl", hash = "sha256:89bd777bc6624fe4115e9fac3352c79ed60f3bb18651420635f26e643e3dd1f6"},
|
||||||
{file = "pillow-11.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc1c3bc53befb6096b84165956e886b1729634a799e9d6329a0c512ab651e579"},
|
{file = "pillow-11.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:19d2ff547c75b8e3ff46f4d9ef969a06c30ab2d4263a9e287733aa8b2429ce8f"},
|
||||||
{file = "pillow-11.2.1-cp310-cp310-win32.whl", hash = "sha256:312c77b7f07ab2139924d2639860e084ec2a13e72af54d4f08ac843a5fc9c79d"},
|
{file = "pillow-11.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:819931d25e57b513242859ce1876c58c59dc31587847bf74cfe06b2e0cb22d2f"},
|
||||||
{file = "pillow-11.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:9bc7ae48b8057a611e5fe9f853baa88093b9a76303937449397899385da06fad"},
|
{file = "pillow-11.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1cd110edf822773368b396281a2293aeb91c90a2db00d78ea43e7e861631b722"},
|
||||||
{file = "pillow-11.2.1-cp310-cp310-win_arm64.whl", hash = "sha256:2728567e249cdd939f6cc3d1f049595c66e4187f3c34078cbc0a7d21c47482d2"},
|
{file = "pillow-11.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c412fddd1b77a75aa904615ebaa6001f169b26fd467b4be93aded278266b288"},
|
||||||
{file = "pillow-11.2.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35ca289f712ccfc699508c4658a1d14652e8033e9b69839edf83cbdd0ba39e70"},
|
{file = "pillow-11.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:643f189248837533073c405ec2f0bb250ba54598cf80e8c1e043381a60632f58"},
|
||||||
{file = "pillow-11.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0409af9f829f87a2dfb7e259f78f317a5351f2045158be321fd135973fff7bf"},
|
{file = "pillow-11.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:106064daa23a745510dabce1d84f29137a37224831d88eb4ce94bb187b1d7e5f"},
|
||||||
{file = "pillow-11.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4e5c5edee874dce4f653dbe59db7c73a600119fbea8d31f53423586ee2aafd7"},
|
{file = "pillow-11.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cd8ff254faf15591e724dc7c4ddb6bf4793efcbe13802a4ae3e863cd300b493e"},
|
||||||
{file = "pillow-11.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b93a07e76d13bff9444f1a029e0af2964e654bfc2e2c2d46bfd080df5ad5f3d8"},
|
{file = "pillow-11.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:932c754c2d51ad2b2271fd01c3d121daaa35e27efae2a616f77bf164bc0b3e94"},
|
||||||
{file = "pillow-11.2.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:e6def7eed9e7fa90fde255afaf08060dc4b343bbe524a8f69bdd2a2f0018f600"},
|
{file = "pillow-11.3.0-cp311-cp311-win32.whl", hash = "sha256:b4b8f3efc8d530a1544e5962bd6b403d5f7fe8b9e08227c6b255f98ad82b4ba0"},
|
||||||
{file = "pillow-11.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8f4f3724c068be008c08257207210c138d5f3731af6c155a81c2b09a9eb3a788"},
|
{file = "pillow-11.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:1a992e86b0dd7aeb1f053cd506508c0999d710a8f07b4c791c63843fc6a807ac"},
|
||||||
{file = "pillow-11.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0a6709b47019dff32e678bc12c63008311b82b9327613f534e496dacaefb71e"},
|
{file = "pillow-11.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:30807c931ff7c095620fe04448e2c2fc673fcbb1ffe2a7da3fb39613489b1ddd"},
|
||||||
{file = "pillow-11.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f6b0c664ccb879109ee3ca702a9272d877f4fcd21e5eb63c26422fd6e415365e"},
|
{file = "pillow-11.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdae223722da47b024b867c1ea0be64e0df702c5e0a60e27daad39bf960dd1e4"},
|
||||||
{file = "pillow-11.2.1-cp311-cp311-win32.whl", hash = "sha256:cc5d875d56e49f112b6def6813c4e3d3036d269c008bf8aef72cd08d20ca6df6"},
|
{file = "pillow-11.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:921bd305b10e82b4d1f5e802b6850677f965d8394203d182f078873851dada69"},
|
||||||
{file = "pillow-11.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:0f5c7eda47bf8e3c8a283762cab94e496ba977a420868cb819159980b6709193"},
|
{file = "pillow-11.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f07ed9f56a3b9b5f49d3661dc9607484e85c67e27f3e8be2c7d28ca032fec7"},
|
||||||
{file = "pillow-11.2.1-cp311-cp311-win_arm64.whl", hash = "sha256:4d375eb838755f2528ac8cbc926c3e31cc49ca4ad0cf79cff48b20e30634a4a7"},
|
{file = "pillow-11.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:676b2815362456b5b3216b4fd5bd89d362100dc6f4945154ff172e206a22c024"},
|
||||||
{file = "pillow-11.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:78afba22027b4accef10dbd5eed84425930ba41b3ea0a86fa8d20baaf19d807f"},
|
{file = "pillow-11.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3e184b2f26ff146363dd07bde8b711833d7b0202e27d13540bfe2e35a323a809"},
|
||||||
{file = "pillow-11.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78092232a4ab376a35d68c4e6d5e00dfd73454bd12b230420025fbe178ee3b0b"},
|
{file = "pillow-11.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6be31e3fc9a621e071bc17bb7de63b85cbe0bfae91bb0363c893cbe67247780d"},
|
||||||
{file = "pillow-11.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a5f306095c6780c52e6bbb6109624b95c5b18e40aab1c3041da3e9e0cd3e2d"},
|
{file = "pillow-11.3.0-cp312-cp312-win32.whl", hash = "sha256:7b161756381f0918e05e7cb8a371fff367e807770f8fe92ecb20d905d0e1c149"},
|
||||||
{file = "pillow-11.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c7b29dbd4281923a2bfe562acb734cee96bbb129e96e6972d315ed9f232bef4"},
|
{file = "pillow-11.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a6444696fce635783440b7f7a9fc24b3ad10a9ea3f0ab66c5905be1c19ccf17d"},
|
||||||
{file = "pillow-11.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3e645b020f3209a0181a418bffe7b4a93171eef6c4ef6cc20980b30bebf17b7d"},
|
{file = "pillow-11.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:2aceea54f957dd4448264f9bf40875da0415c83eb85f55069d89c0ed436e3542"},
|
||||||
{file = "pillow-11.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b2dbea1012ccb784a65349f57bbc93730b96e85b42e9bf7b01ef40443db720b4"},
|
{file = "pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:1c627742b539bba4309df89171356fcb3cc5a9178355b2727d1b74a6cf155fbd"},
|
||||||
{file = "pillow-11.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:da3104c57bbd72948d75f6a9389e6727d2ab6333c3617f0a89d72d4940aa0443"},
|
{file = "pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:30b7c02f3899d10f13d7a48163c8969e4e653f8b43416d23d13d1bbfdc93b9f8"},
|
||||||
{file = "pillow-11.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:598174aef4589af795f66f9caab87ba4ff860ce08cd5bb447c6fc553ffee603c"},
|
{file = "pillow-11.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7859a4cc7c9295f5838015d8cc0a9c215b77e43d07a25e460f35cf516df8626f"},
|
||||||
{file = "pillow-11.2.1-cp312-cp312-win32.whl", hash = "sha256:1d535df14716e7f8776b9e7fee118576d65572b4aad3ed639be9e4fa88a1cad3"},
|
{file = "pillow-11.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec1ee50470b0d050984394423d96325b744d55c701a439d2bd66089bff963d3c"},
|
||||||
{file = "pillow-11.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:14e33b28bf17c7a38eede290f77db7c664e4eb01f7869e37fa98a5aa95978941"},
|
{file = "pillow-11.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7db51d222548ccfd274e4572fdbf3e810a5e66b00608862f947b163e613b67dd"},
|
||||||
{file = "pillow-11.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:21e1470ac9e5739ff880c211fc3af01e3ae505859392bf65458c224d0bf283eb"},
|
{file = "pillow-11.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c37d8ba9411d6003bba9e518db0db0c58a680ab9fe5179f040b0463644bc9805"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fdec757fea0b793056419bca3e9932eb2b0ceec90ef4813ea4c1e072c389eb28"},
|
{file = "pillow-11.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13f87d581e71d9189ab21fe0efb5a23e9f28552d5be6979e84001d3b8505abe8"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0e130705d568e2f43a17bcbe74d90958e8a16263868a12c3e0d9c8162690830"},
|
{file = "pillow-11.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:023f6d2d11784a465f09fd09a34b150ea4672e85fb3d05931d89f373ab14abb2"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bdb5e09068332578214cadd9c05e3d64d99e0e87591be22a324bdbc18925be0"},
|
{file = "pillow-11.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:45dfc51ac5975b938e9809451c51734124e73b04d0f0ac621649821a63852e7b"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d189ba1bebfbc0c0e529159631ec72bb9e9bc041f01ec6d3233d6d82eb823bc1"},
|
{file = "pillow-11.3.0-cp313-cp313-win32.whl", hash = "sha256:a4d336baed65d50d37b88ca5b60c0fa9d81e3a87d4a7930d3880d1624d5b31f3"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:191955c55d8a712fab8934a42bfefbf99dd0b5875078240943f913bb66d46d9f"},
|
{file = "pillow-11.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bce5c4fd0921f99d2e858dc4d4d64193407e1b99478bc5cacecba2311abde51"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:ad275964d52e2243430472fc5d2c2334b4fc3ff9c16cb0a19254e25efa03a155"},
|
{file = "pillow-11.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:1904e1264881f682f02b7f8167935cce37bc97db457f8e7849dc3a6a52b99580"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:750f96efe0597382660d8b53e90dd1dd44568a8edb51cb7f9d5d918b80d4de14"},
|
{file = "pillow-11.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4c834a3921375c48ee6b9624061076bc0a32a60b5532b322cc0ea64e639dd50e"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fe15238d3798788d00716637b3d4e7bb6bde18b26e5d08335a96e88564a36b6b"},
|
{file = "pillow-11.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5e05688ccef30ea69b9317a9ead994b93975104a677a36a8ed8106be9260aa6d"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313-win32.whl", hash = "sha256:3fe735ced9a607fee4f481423a9c36701a39719252a9bb251679635f99d0f7d2"},
|
{file = "pillow-11.3.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f85acb69adf2aaee8b7da124efebbdb959a104db34d3a2cb0f3793dbae422a8"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:74ee3d7ecb3f3c05459ba95eed5efa28d6092d751ce9bf20e3e253a4e497e691"},
|
{file = "pillow-11.3.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05f6ecbeff5005399bb48d198f098a9b4b6bdf27b8487c7f38ca16eeb070cd59"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:5119225c622403afb4b44bad4c1ca6c1f98eed79db8d3bc6e4e160fc6339d66c"},
|
{file = "pillow-11.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a7bc6e6fd0395bc052f16b1a8670859964dbd7003bd0af2ff08342eb6e442cfe"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8ce2e8411c7aaef53e6bb29fe98f28cd4fbd9a1d9be2eeea434331aac0536b22"},
|
{file = "pillow-11.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:83e1b0161c9d148125083a35c1c5a89db5b7054834fd4387499e06552035236c"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9ee66787e095127116d91dea2143db65c7bb1e232f617aa5957c0d9d2a3f23a7"},
|
{file = "pillow-11.3.0-cp313-cp313t-win32.whl", hash = "sha256:2a3117c06b8fb646639dce83694f2f9eac405472713fcb1ae887469c0d4f6788"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9622e3b6c1d8b551b6e6f21873bdcc55762b4b2126633014cea1803368a9aa16"},
|
{file = "pillow-11.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:857844335c95bea93fb39e0fa2726b4d9d758850b34075a7e3ff4f4fa3aa3b31"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63b5dff3a68f371ea06025a1a6966c9a1e1ee452fc8020c2cd0ea41b83e9037b"},
|
{file = "pillow-11.3.0-cp313-cp313t-win_arm64.whl", hash = "sha256:8797edc41f3e8536ae4b10897ee2f637235c94f27404cac7297f7b607dd0716e"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:31df6e2d3d8fc99f993fd253e97fae451a8db2e7207acf97859732273e108406"},
|
{file = "pillow-11.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d9da3df5f9ea2a89b81bb6087177fb1f4d1c7146d583a3fe5c672c0d94e55e12"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:062b7a42d672c45a70fa1f8b43d1d38ff76b63421cbbe7f88146b39e8a558d91"},
|
{file = "pillow-11.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0b275ff9b04df7b640c59ec5a3cb113eefd3795a8df80bac69646ef699c6981a"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4eb92eca2711ef8be42fd3f67533765d9fd043b8c80db204f16c8ea62ee1a751"},
|
{file = "pillow-11.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41742638139424703b4d01665b807c6468e23e699e8e90cffefe291c5832b027"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f91ebf30830a48c825590aede79376cb40f110b387c17ee9bd59932c961044f9"},
|
{file = "pillow-11.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93efb0b4de7e340d99057415c749175e24c8864302369e05914682ba642e5d77"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313t-win32.whl", hash = "sha256:e0b55f27f584ed623221cfe995c912c61606be8513bfa0e07d2c674b4516d9dd"},
|
{file = "pillow-11.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7966e38dcd0fa11ca390aed7c6f20454443581d758242023cf36fcb319b1a874"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:36d6b82164c39ce5482f649b437382c0fb2395eabc1e2b1702a6deb8ad647d6e"},
|
{file = "pillow-11.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:98a9afa7b9007c67ed84c57c9e0ad86a6000da96eaa638e4f8abe5b65ff83f0a"},
|
||||||
{file = "pillow-11.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:225c832a13326e34f212d2072982bb1adb210e0cc0b153e688743018c94a2681"},
|
{file = "pillow-11.3.0-cp314-cp314-win32.whl", hash = "sha256:02a723e6bf909e7cea0dac1b0e0310be9d7650cd66222a5f1c571455c0a45214"},
|
||||||
{file = "pillow-11.2.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:7491cf8a79b8eb867d419648fff2f83cb0b3891c8b36da92cc7f1931d46108c8"},
|
{file = "pillow-11.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:a418486160228f64dd9e9efcd132679b7a02a5f22c982c78b6fc7dab3fefb635"},
|
||||||
{file = "pillow-11.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b02d8f9cb83c52578a0b4beadba92e37d83a4ef11570a8688bbf43f4ca50909"},
|
{file = "pillow-11.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:155658efb5e044669c08896c0c44231c5e9abcaadbc5cd3648df2f7c0b96b9a6"},
|
||||||
{file = "pillow-11.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:014ca0050c85003620526b0ac1ac53f56fc93af128f7546623cc8e31875ab928"},
|
{file = "pillow-11.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:59a03cdf019efbfeeed910bf79c7c93255c3d54bc45898ac2a4140071b02b4ae"},
|
||||||
{file = "pillow-11.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3692b68c87096ac6308296d96354eddd25f98740c9d2ab54e1549d6c8aea9d79"},
|
{file = "pillow-11.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f8a5827f84d973d8636e9dc5764af4f0cf2318d26744b3d902931701b0d46653"},
|
||||||
{file = "pillow-11.2.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:f781dcb0bc9929adc77bad571b8621ecb1e4cdef86e940fe2e5b5ee24fd33b35"},
|
{file = "pillow-11.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c96f993ab8c98460cd0c001447bff6194403e8b1d7e149ade5f00594918128b"},
|
||||||
{file = "pillow-11.2.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:2b490402c96f907a166615e9a5afacf2519e28295f157ec3a2bb9bd57de638cb"},
|
{file = "pillow-11.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41342b64afeba938edb034d122b2dda5db2139b9a4af999729ba8818e0056477"},
|
||||||
{file = "pillow-11.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dd6b20b93b3ccc9c1b597999209e4bc5cf2853f9ee66e3fc9a400a78733ffc9a"},
|
{file = "pillow-11.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:068d9c39a2d1b358eb9f245ce7ab1b5c3246c7c8c7d9ba58cfa5b43146c06e50"},
|
||||||
{file = "pillow-11.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:4b835d89c08a6c2ee7781b8dd0a30209a8012b5f09c0a665b65b0eb3560b6f36"},
|
{file = "pillow-11.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a1bc6ba083b145187f648b667e05a2534ecc4b9f2784c2cbe3089e44868f2b9b"},
|
||||||
{file = "pillow-11.2.1-cp39-cp39-win32.whl", hash = "sha256:b10428b3416d4f9c61f94b494681280be7686bda15898a3a9e08eb66a6d92d67"},
|
{file = "pillow-11.3.0-cp314-cp314t-win32.whl", hash = "sha256:118ca10c0d60b06d006be10a501fd6bbdfef559251ed31b794668ed569c87e12"},
|
||||||
{file = "pillow-11.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:6ebce70c3f486acf7591a3d73431fa504a4e18a9b97ff27f5f47b7368e4b9dd1"},
|
{file = "pillow-11.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8924748b688aa210d79883357d102cd64690e56b923a186f35a82cbc10f997db"},
|
||||||
{file = "pillow-11.2.1-cp39-cp39-win_arm64.whl", hash = "sha256:c27476257b2fdcd7872d54cfd119b3a9ce4610fb85c8e32b70b42e3680a29a1e"},
|
{file = "pillow-11.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:79ea0d14d3ebad43ec77ad5272e6ff9bba5b679ef73375ea760261207fa8e0aa"},
|
||||||
{file = "pillow-11.2.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:9b7b0d4fd2635f54ad82785d56bc0d94f147096493a79985d0ab57aedd563156"},
|
{file = "pillow-11.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:48d254f8a4c776de343051023eb61ffe818299eeac478da55227d96e241de53f"},
|
||||||
{file = "pillow-11.2.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:aa442755e31c64037aa7c1cb186e0b369f8416c567381852c63444dd666fb772"},
|
{file = "pillow-11.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7aee118e30a4cf54fdd873bd3a29de51e29105ab11f9aad8c32123f58c8f8081"},
|
||||||
{file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0d3348c95b766f54b76116d53d4cb171b52992a1027e7ca50c81b43b9d9e363"},
|
{file = "pillow-11.3.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:092c80c76635f5ecb10f3f83d76716165c96f5229addbd1ec2bdbbda7d496e06"},
|
||||||
{file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85d27ea4c889342f7e35f6d56e7e1cb345632ad592e8c51b693d7b7556043ce0"},
|
{file = "pillow-11.3.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cadc9e0ea0a2431124cde7e1697106471fc4c1da01530e679b2391c37d3fbb3a"},
|
||||||
{file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bf2c33d6791c598142f00c9c4c7d47f6476731c31081331664eb26d6ab583e01"},
|
{file = "pillow-11.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6a418691000f2a418c9135a7cf0d797c1bb7d9a485e61fe8e7722845b95ef978"},
|
||||||
{file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e616e7154c37669fc1dfc14584f11e284e05d1c650e1c0f972f281c4ccc53193"},
|
{file = "pillow-11.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:97afb3a00b65cc0804d1c7abddbf090a81eaac02768af58cbdcaaa0a931e0b6d"},
|
||||||
{file = "pillow-11.2.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:39ad2e0f424394e3aebc40168845fee52df1394a4673a6ee512d840d14ab3013"},
|
{file = "pillow-11.3.0-cp39-cp39-win32.whl", hash = "sha256:ea944117a7974ae78059fcc1800e5d3295172bb97035c0c1d9345fca1419da71"},
|
||||||
{file = "pillow-11.2.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:80f1df8dbe9572b4b7abdfa17eb5d78dd620b1d55d9e25f834efdbee872d3aed"},
|
{file = "pillow-11.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:e5c5858ad8ec655450a7c7df532e9842cf8df7cc349df7225c60d5d348c8aada"},
|
||||||
{file = "pillow-11.2.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ea926cfbc3957090becbcbbb65ad177161a2ff2ad578b5a6ec9bb1e1cd78753c"},
|
{file = "pillow-11.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:6abdbfd3aea42be05702a8dd98832329c167ee84400a1d1f61ab11437f1717eb"},
|
||||||
{file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:738db0e0941ca0376804d4de6a782c005245264edaa253ffce24e5a15cbdc7bd"},
|
{file = "pillow-11.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3cee80663f29e3843b68199b9d6f4f54bd1d4a6b59bdd91bceefc51238bcb967"},
|
||||||
{file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db98ab6565c69082ec9b0d4e40dd9f6181dab0dd236d26f7a50b8b9bfbd5076"},
|
{file = "pillow-11.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b5f56c3f344f2ccaf0dd875d3e180f631dc60a51b314295a3e681fe8cf851fbe"},
|
||||||
{file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:036e53f4170e270ddb8797d4c590e6dd14d28e15c7da375c18978045f7e6c37b"},
|
{file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:527b37216b6ac3a12d7838dc3bd75208ec57c1c6d11ef01902266a5a0c14fc27"},
|
||||||
{file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:14f73f7c291279bd65fda51ee87affd7c1e097709f7fdd0188957a16c264601f"},
|
{file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:be5463ac478b623b9dd3937afd7fb7ab3d79dd290a28e2b6df292dc75063eb8a"},
|
||||||
{file = "pillow-11.2.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:208653868d5c9ecc2b327f9b9ef34e0e42a4cdd172c2988fd81d62d2bc9bc044"},
|
{file = "pillow-11.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:8dc70ca24c110503e16918a658b869019126ecfe03109b754c402daff12b3d9f"},
|
||||||
{file = "pillow-11.2.1.tar.gz", hash = "sha256:a64dd61998416367b7ef979b73d3a85853ba9bec4c2925f74e588879a58716b6"},
|
{file = "pillow-11.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7c8ec7a017ad1bd562f93dbd8505763e688d388cde6e4a010ae1486916e713e6"},
|
||||||
|
{file = "pillow-11.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9ab6ae226de48019caa8074894544af5b53a117ccb9d3b3dcb2871464c829438"},
|
||||||
|
{file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5418b53c0d59b3824d05e029669efa023bbef0f3e92e75ec8428f3799487f361"},
|
||||||
|
{file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:504b6f59505f08ae014f724b6207ff6222662aab5cc9542577fb084ed0676ac7"},
|
||||||
|
{file = "pillow-11.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c84d689db21a1c397d001aa08241044aa2069e7587b398c8cc63020390b1c1b8"},
|
||||||
|
{file = "pillow-11.3.0.tar.gz", hash = "sha256:3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"]
|
docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-autobuild", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"]
|
||||||
fpx = ["olefile"]
|
fpx = ["olefile"]
|
||||||
mic = ["olefile"]
|
mic = ["olefile"]
|
||||||
test-arrow = ["pyarrow"]
|
test-arrow = ["pyarrow"]
|
||||||
tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout", "trove-classifiers (>=2024.10.12)"]
|
tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "trove-classifiers (>=2024.10.12)"]
|
||||||
typing = ["typing-extensions ; python_version < \"3.10\""]
|
typing = ["typing-extensions ; python_version < \"3.10\""]
|
||||||
xmp = ["defusedxml"]
|
xmp = ["defusedxml"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prometheus-client"
|
name = "prometheus-client"
|
||||||
version = "0.21.0"
|
version = "0.22.1"
|
||||||
description = "Python client for the Prometheus monitoring system."
|
description = "Python client for the Prometheus monitoring system."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.9"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "prometheus_client-0.21.0-py3-none-any.whl", hash = "sha256:4fa6b4dd0ac16d58bb587c04b1caae65b8c5043e85f778f42f5f632f6af2e166"},
|
{file = "prometheus_client-0.22.1-py3-none-any.whl", hash = "sha256:cca895342e308174341b2cbf99a56bef291fbc0ef7b9e5412a0f26d653ba7094"},
|
||||||
{file = "prometheus_client-0.21.0.tar.gz", hash = "sha256:96c83c606b71ff2b0a433c98889d275f51ffec6c5e267de37c7a2b5c9aa9233e"},
|
{file = "prometheus_client-0.22.1.tar.gz", hash = "sha256:190f1331e783cf21eb60bca559354e0a4d4378facecf78f5428c39b675d20d28"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
@ -1713,7 +1734,7 @@ description = "psycopg2 - Python-PostgreSQL Database Adapter"
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"postgres\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"postgres\""
|
||||||
files = [
|
files = [
|
||||||
{file = "psycopg2-2.9.10-cp310-cp310-win32.whl", hash = "sha256:5df2b672140f95adb453af93a7d669d7a7bf0a56bcd26f1502329166f4a61716"},
|
{file = "psycopg2-2.9.10-cp310-cp310-win32.whl", hash = "sha256:5df2b672140f95adb453af93a7d669d7a7bf0a56bcd26f1502329166f4a61716"},
|
||||||
{file = "psycopg2-2.9.10-cp310-cp310-win_amd64.whl", hash = "sha256:c6f7b8561225f9e711a9c47087388a97fdc948211c10a4bccbf0ba68ab7b3b5a"},
|
{file = "psycopg2-2.9.10-cp310-cp310-win_amd64.whl", hash = "sha256:c6f7b8561225f9e711a9c47087388a97fdc948211c10a4bccbf0ba68ab7b3b5a"},
|
||||||
@ -1721,6 +1742,7 @@ files = [
|
|||||||
{file = "psycopg2-2.9.10-cp311-cp311-win_amd64.whl", hash = "sha256:0435034157049f6846e95103bd8f5a668788dd913a7c30162ca9503fdf542cb4"},
|
{file = "psycopg2-2.9.10-cp311-cp311-win_amd64.whl", hash = "sha256:0435034157049f6846e95103bd8f5a668788dd913a7c30162ca9503fdf542cb4"},
|
||||||
{file = "psycopg2-2.9.10-cp312-cp312-win32.whl", hash = "sha256:65a63d7ab0e067e2cdb3cf266de39663203d38d6a8ed97f5ca0cb315c73fe067"},
|
{file = "psycopg2-2.9.10-cp312-cp312-win32.whl", hash = "sha256:65a63d7ab0e067e2cdb3cf266de39663203d38d6a8ed97f5ca0cb315c73fe067"},
|
||||||
{file = "psycopg2-2.9.10-cp312-cp312-win_amd64.whl", hash = "sha256:4a579d6243da40a7b3182e0430493dbd55950c493d8c68f4eec0b302f6bbf20e"},
|
{file = "psycopg2-2.9.10-cp312-cp312-win_amd64.whl", hash = "sha256:4a579d6243da40a7b3182e0430493dbd55950c493d8c68f4eec0b302f6bbf20e"},
|
||||||
|
{file = "psycopg2-2.9.10-cp313-cp313-win_amd64.whl", hash = "sha256:91fd603a2155da8d0cfcdbf8ab24a2d54bca72795b90d2a3ed2b6da8d979dee2"},
|
||||||
{file = "psycopg2-2.9.10-cp39-cp39-win32.whl", hash = "sha256:9d5b3b94b79a844a986d029eee38998232451119ad653aea42bb9220a8c5066b"},
|
{file = "psycopg2-2.9.10-cp39-cp39-win32.whl", hash = "sha256:9d5b3b94b79a844a986d029eee38998232451119ad653aea42bb9220a8c5066b"},
|
||||||
{file = "psycopg2-2.9.10-cp39-cp39-win_amd64.whl", hash = "sha256:88138c8dedcbfa96408023ea2b0c369eda40fe5d75002c0964c78f46f11fa442"},
|
{file = "psycopg2-2.9.10-cp39-cp39-win_amd64.whl", hash = "sha256:88138c8dedcbfa96408023ea2b0c369eda40fe5d75002c0964c78f46f11fa442"},
|
||||||
{file = "psycopg2-2.9.10.tar.gz", hash = "sha256:12ec0b40b0273f95296233e8750441339298e6a572f7039da5b260e3c8b60e11"},
|
{file = "psycopg2-2.9.10.tar.gz", hash = "sha256:12ec0b40b0273f95296233e8750441339298e6a572f7039da5b260e3c8b60e11"},
|
||||||
@ -1733,7 +1755,7 @@ description = ".. image:: https://travis-ci.org/chtd/psycopg2cffi.svg?branch=mas
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "platform_python_implementation == \"PyPy\" and (extra == \"postgres\" or extra == \"all\")"
|
markers = "platform_python_implementation == \"PyPy\" and (extra == \"all\" or extra == \"postgres\")"
|
||||||
files = [
|
files = [
|
||||||
{file = "psycopg2cffi-2.9.0.tar.gz", hash = "sha256:7e272edcd837de3a1d12b62185eb85c45a19feda9e62fa1b120c54f9e8d35c52"},
|
{file = "psycopg2cffi-2.9.0.tar.gz", hash = "sha256:7e272edcd837de3a1d12b62185eb85c45a19feda9e62fa1b120c54f9e8d35c52"},
|
||||||
]
|
]
|
||||||
@ -1749,7 +1771,7 @@ description = "A Simple library to enable psycopg2 compatability"
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "platform_python_implementation == \"PyPy\" and (extra == \"postgres\" or extra == \"all\")"
|
markers = "platform_python_implementation == \"PyPy\" and (extra == \"all\" or extra == \"postgres\")"
|
||||||
files = [
|
files = [
|
||||||
{file = "psycopg2cffi-compat-1.1.tar.gz", hash = "sha256:d25e921748475522b33d13420aad5c2831c743227dc1f1f2585e0fdb5c914e05"},
|
{file = "psycopg2cffi-compat-1.1.tar.gz", hash = "sha256:d25e921748475522b33d13420aad5c2831c743227dc1f1f2585e0fdb5c914e05"},
|
||||||
]
|
]
|
||||||
@ -1972,7 +1994,7 @@ description = "Python extension wrapping the ICU C++ API"
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"user-search\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"user-search\""
|
||||||
files = [
|
files = [
|
||||||
{file = "PyICU-2.14.tar.gz", hash = "sha256:acc7eb92bd5c554ed577249c6978450a4feda0aa6f01470152b3a7b382a02132"},
|
{file = "PyICU-2.14.tar.gz", hash = "sha256:acc7eb92bd5c554ed577249c6978450a4feda0aa6f01470152b3a7b382a02132"},
|
||||||
]
|
]
|
||||||
@ -2021,7 +2043,7 @@ description = "A development tool to measure, monitor and analyze the memory beh
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"cache-memory\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"cache-memory\""
|
||||||
files = [
|
files = [
|
||||||
{file = "Pympler-1.0.1-py3-none-any.whl", hash = "sha256:d260dda9ae781e1eab6ea15bacb84015849833ba5555f141d2d9b7b7473b307d"},
|
{file = "Pympler-1.0.1-py3-none-any.whl", hash = "sha256:d260dda9ae781e1eab6ea15bacb84015849833ba5555f141d2d9b7b7473b307d"},
|
||||||
{file = "Pympler-1.0.1.tar.gz", hash = "sha256:993f1a3599ca3f4fcd7160c7545ad06310c9e12f70174ae7ae8d4e25f6c5d3fa"},
|
{file = "Pympler-1.0.1.tar.gz", hash = "sha256:993f1a3599ca3f4fcd7160c7545ad06310c9e12f70174ae7ae8d4e25f6c5d3fa"},
|
||||||
@ -2081,7 +2103,7 @@ description = "Python implementation of SAML Version 2 Standard"
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.9,<4.0"
|
python-versions = ">=3.9,<4.0"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"saml2\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"saml2\""
|
||||||
files = [
|
files = [
|
||||||
{file = "pysaml2-7.5.0-py3-none-any.whl", hash = "sha256:bc6627cc344476a83c757f440a73fda1369f13b6fda1b4e16bca63ffbabb5318"},
|
{file = "pysaml2-7.5.0-py3-none-any.whl", hash = "sha256:bc6627cc344476a83c757f440a73fda1369f13b6fda1b4e16bca63ffbabb5318"},
|
||||||
{file = "pysaml2-7.5.0.tar.gz", hash = "sha256:f36871d4e5ee857c6b85532e942550d2cf90ea4ee943d75eb681044bbc4f54f7"},
|
{file = "pysaml2-7.5.0.tar.gz", hash = "sha256:f36871d4e5ee857c6b85532e942550d2cf90ea4ee943d75eb681044bbc4f54f7"},
|
||||||
@ -2106,7 +2128,7 @@ description = "Extensions to the standard Python datetime module"
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"saml2\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"saml2\""
|
||||||
files = [
|
files = [
|
||||||
{file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
|
{file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
|
||||||
{file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
|
{file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
|
||||||
@ -2134,7 +2156,7 @@ description = "World timezone definitions, modern and historical"
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"saml2\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"saml2\""
|
||||||
files = [
|
files = [
|
||||||
{file = "pytz-2022.7.1-py2.py3-none-any.whl", hash = "sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a"},
|
{file = "pytz-2022.7.1-py2.py3-none-any.whl", hash = "sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a"},
|
||||||
{file = "pytz-2022.7.1.tar.gz", hash = "sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0"},
|
{file = "pytz-2022.7.1.tar.gz", hash = "sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0"},
|
||||||
@ -2498,7 +2520,7 @@ description = "Python client for Sentry (https://sentry.io)"
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"sentry\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"sentry\""
|
||||||
files = [
|
files = [
|
||||||
{file = "sentry_sdk-2.22.0-py2.py3-none-any.whl", hash = "sha256:3d791d631a6c97aad4da7074081a57073126c69487560c6f8bffcf586461de66"},
|
{file = "sentry_sdk-2.22.0-py2.py3-none-any.whl", hash = "sha256:3d791d631a6c97aad4da7074081a57073126c69487560c6f8bffcf586461de66"},
|
||||||
{file = "sentry_sdk-2.22.0.tar.gz", hash = "sha256:b4bf43bb38f547c84b2eadcefbe389b36ef75f3f38253d7a74d6b928c07ae944"},
|
{file = "sentry_sdk-2.22.0.tar.gz", hash = "sha256:b4bf43bb38f547c84b2eadcefbe389b36ef75f3f38253d7a74d6b928c07ae944"},
|
||||||
@ -2686,7 +2708,7 @@ description = "Tornado IOLoop Backed Concurrent Futures"
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"opentracing\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"opentracing\""
|
||||||
files = [
|
files = [
|
||||||
{file = "threadloop-1.0.2-py2-none-any.whl", hash = "sha256:5c90dbefab6ffbdba26afb4829d2a9df8275d13ac7dc58dccb0e279992679599"},
|
{file = "threadloop-1.0.2-py2-none-any.whl", hash = "sha256:5c90dbefab6ffbdba26afb4829d2a9df8275d13ac7dc58dccb0e279992679599"},
|
||||||
{file = "threadloop-1.0.2.tar.gz", hash = "sha256:8b180aac31013de13c2ad5c834819771992d350267bddb854613ae77ef571944"},
|
{file = "threadloop-1.0.2.tar.gz", hash = "sha256:8b180aac31013de13c2ad5c834819771992d350267bddb854613ae77ef571944"},
|
||||||
@ -2702,7 +2724,7 @@ description = "Python bindings for the Apache Thrift RPC system"
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"opentracing\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"opentracing\""
|
||||||
files = [
|
files = [
|
||||||
{file = "thrift-0.16.0.tar.gz", hash = "sha256:2b5b6488fcded21f9d312aa23c9ff6a0195d0f6ae26ddbd5ad9e3e25dfc14408"},
|
{file = "thrift-0.16.0.tar.gz", hash = "sha256:2b5b6488fcded21f9d312aa23c9ff6a0195d0f6ae26ddbd5ad9e3e25dfc14408"},
|
||||||
]
|
]
|
||||||
@ -2764,7 +2786,7 @@ description = "Tornado is a Python web framework and asynchronous networking lib
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.9"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"opentracing\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"opentracing\""
|
||||||
files = [
|
files = [
|
||||||
{file = "tornado-6.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:f81067dad2e4443b015368b24e802d0083fecada4f0a4572fdb72fc06e54a9a6"},
|
{file = "tornado-6.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:f81067dad2e4443b015368b24e802d0083fecada4f0a4572fdb72fc06e54a9a6"},
|
||||||
{file = "tornado-6.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9ac1cbe1db860b3cbb251e795c701c41d343f06a96049d6274e7c77559117e41"},
|
{file = "tornado-6.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9ac1cbe1db860b3cbb251e795c701c41d343f06a96049d6274e7c77559117e41"},
|
||||||
@ -2804,27 +2826,28 @@ dev = ["furo (>=2024.05.06)", "nox", "packaging", "sphinx (>=5)", "twisted"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "treq"
|
name = "treq"
|
||||||
version = "24.9.1"
|
version = "25.5.0"
|
||||||
description = "High-level Twisted HTTP Client API"
|
description = "High-level Twisted HTTP Client API"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.8.0"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "treq-24.9.1-py3-none-any.whl", hash = "sha256:eee4756fd9a857c77f180fd5202b52c518f2d3e2826dce28b89066c03bfc45d0"},
|
{file = "treq-25.5.0-py3-none-any.whl", hash = "sha256:e99d4e66cacaa1f0da82bb60b317d104c29dbd8ac0a75d7f657b348178d830f4"},
|
||||||
{file = "treq-24.9.1.tar.gz", hash = "sha256:15da7fc404f3e4ed59d0abe5f8eef4966fabbe618039a2a23bc7c15305cefea8"},
|
{file = "treq-25.5.0.tar.gz", hash = "sha256:25dde3a55ae85ec2f2c56332c99aef255ab14f997d0d00552ebff13538a9804a"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
attrs = "*"
|
attrs = "*"
|
||||||
hyperlink = ">=21.0.0"
|
hyperlink = ">=21.0.0"
|
||||||
incremental = "*"
|
incremental = ">=24.7.2"
|
||||||
|
multipart = "*"
|
||||||
requests = ">=2.1.0"
|
requests = ">=2.1.0"
|
||||||
Twisted = {version = ">=22.10.0", extras = ["tls"]}
|
twisted = {version = ">=22.10.0", extras = ["tls"]}
|
||||||
typing-extensions = ">=3.10.0"
|
typing-extensions = ">=3.10.0"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
dev = ["httpbin (==0.7.0)", "pep8", "pyflakes", "werkzeug (==2.0.3)"]
|
dev = ["httpbin (==0.7.0)", "pep8", "pyflakes", "werkzeug (==2.0.3)"]
|
||||||
docs = ["sphinx (<7.0.0)"]
|
docs = ["sphinx", "sphinx-rtd-theme"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "twine"
|
name = "twine"
|
||||||
@ -2900,7 +2923,7 @@ description = "non-blocking redis client for python"
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"redis\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"redis\""
|
||||||
files = [
|
files = [
|
||||||
{file = "txredisapi-1.4.11-py3-none-any.whl", hash = "sha256:ac64d7a9342b58edca13ef267d4fa7637c1aa63f8595e066801c1e8b56b22d0b"},
|
{file = "txredisapi-1.4.11-py3-none-any.whl", hash = "sha256:ac64d7a9342b58edca13ef267d4fa7637c1aa63f8595e066801c1e8b56b22d0b"},
|
||||||
{file = "txredisapi-1.4.11.tar.gz", hash = "sha256:3eb1af99aefdefb59eb877b1dd08861efad60915e30ad5bf3d5bf6c5cedcdbc6"},
|
{file = "txredisapi-1.4.11.tar.gz", hash = "sha256:3eb1af99aefdefb59eb877b1dd08861efad60915e30ad5bf3d5bf6c5cedcdbc6"},
|
||||||
@ -2966,14 +2989,14 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "types-jsonschema"
|
name = "types-jsonschema"
|
||||||
version = "4.23.0.20250516"
|
version = "4.24.0.20250528"
|
||||||
description = "Typing stubs for jsonschema"
|
description = "Typing stubs for jsonschema"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.9"
|
||||||
groups = ["dev"]
|
groups = ["dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "types_jsonschema-4.23.0.20250516-py3-none-any.whl", hash = "sha256:e7d0dd7db7e59e63c26e3230e26ffc64c4704cc5170dc21270b366a35ead1618"},
|
{file = "types_jsonschema-4.24.0.20250528-py3-none-any.whl", hash = "sha256:6a906b5ff73ac11c8d1e0b6c30a9693e1e4e1ab56c56c932b3a7e081b86d187b"},
|
||||||
{file = "types_jsonschema-4.23.0.20250516.tar.gz", hash = "sha256:9ace09d9d35c4390a7251ccd7d833b92ccc189d24d1b347f26212afce361117e"},
|
{file = "types_jsonschema-4.24.0.20250528.tar.gz", hash = "sha256:7e28c64e0ae7980eeb158105b20663fc6a6b8f81d5f86ea6614aa0014417bd1e"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -3243,7 +3266,7 @@ description = "An XML Schema validator and decoder"
|
|||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "extra == \"saml2\" or extra == \"all\""
|
markers = "extra == \"all\" or extra == \"saml2\""
|
||||||
files = [
|
files = [
|
||||||
{file = "xmlschema-2.4.0-py3-none-any.whl", hash = "sha256:dc87be0caaa61f42649899189aab2fd8e0d567f2cf548433ba7b79278d231a4a"},
|
{file = "xmlschema-2.4.0-py3-none-any.whl", hash = "sha256:dc87be0caaa61f42649899189aab2fd8e0d567f2cf548433ba7b79278d231a4a"},
|
||||||
{file = "xmlschema-2.4.0.tar.gz", hash = "sha256:d74cd0c10866ac609e1ef94a5a69b018ad16e39077bc6393408b40c6babee793"},
|
{file = "xmlschema-2.4.0.tar.gz", hash = "sha256:d74cd0c10866ac609e1ef94a5a69b018ad16e39077bc6393408b40c6babee793"},
|
||||||
|
@ -374,7 +374,7 @@ tomli = ">=1.2.3"
|
|||||||
# runtime errors caused by build system changes.
|
# runtime errors caused by build system changes.
|
||||||
# We are happy to raise these upper bounds upon request,
|
# We are happy to raise these upper bounds upon request,
|
||||||
# provided we check that it's safe to do so (i.e. that CI passes).
|
# provided we check that it's safe to do so (i.e. that CI passes).
|
||||||
requires = ["poetry-core>=1.1.0,<=1.9.1", "setuptools_rust>=1.3,<=1.10.2"]
|
requires = ["poetry-core>=1.1.0,<=2.1.3", "setuptools_rust>=1.3,<=1.10.2"]
|
||||||
build-backend = "poetry.core.masonry.api"
|
build-backend = "poetry.core.masonry.api"
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ from synapse.api.errors import (
|
|||||||
InvalidClientTokenError,
|
InvalidClientTokenError,
|
||||||
MissingClientTokenError,
|
MissingClientTokenError,
|
||||||
UnrecognizedRequestError,
|
UnrecognizedRequestError,
|
||||||
|
UserLockedError,
|
||||||
)
|
)
|
||||||
from synapse.http.site import SynapseRequest
|
from synapse.http.site import SynapseRequest
|
||||||
from synapse.logging.opentracing import active_span, force_tracing, start_active_span
|
from synapse.logging.opentracing import active_span, force_tracing, start_active_span
|
||||||
@ -162,12 +163,7 @@ class InternalAuth(BaseAuth):
|
|||||||
if not allow_locked and await self.store.get_user_locked_status(
|
if not allow_locked and await self.store.get_user_locked_status(
|
||||||
requester.user.to_string()
|
requester.user.to_string()
|
||||||
):
|
):
|
||||||
raise AuthError(
|
raise UserLockedError()
|
||||||
401,
|
|
||||||
"User account has been locked",
|
|
||||||
errcode=Codes.USER_LOCKED,
|
|
||||||
additional_fields={"soft_logout": True},
|
|
||||||
)
|
|
||||||
|
|
||||||
# Deny the request if the user account has expired.
|
# Deny the request if the user account has expired.
|
||||||
# This check is only done for regular users, not appservice ones.
|
# This check is only done for regular users, not appservice ones.
|
||||||
|
@ -306,6 +306,20 @@ class UserDeactivatedError(SynapseError):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class UserLockedError(SynapseError):
|
||||||
|
"""The error returned to the client when the user attempted to access an
|
||||||
|
authenticated endpoint, but the account has been locked.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__(
|
||||||
|
code=HTTPStatus.UNAUTHORIZED,
|
||||||
|
msg="User account has been locked",
|
||||||
|
errcode=Codes.USER_LOCKED,
|
||||||
|
additional_fields={"soft_logout": True},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class FederationDeniedError(SynapseError):
|
class FederationDeniedError(SynapseError):
|
||||||
"""An error raised when the server tries to federate with a server which
|
"""An error raised when the server tries to federate with a server which
|
||||||
is not on its federation whitelist.
|
is not on its federation whitelist.
|
||||||
|
@ -575,3 +575,6 @@ class ExperimentalConfig(Config):
|
|||||||
|
|
||||||
# MSC4155: Invite filtering
|
# MSC4155: Invite filtering
|
||||||
self.msc4155_enabled: bool = experimental.get("msc4155_enabled", False)
|
self.msc4155_enabled: bool = experimental.get("msc4155_enabled", False)
|
||||||
|
|
||||||
|
# MSC4293: Redact on Kick/Ban
|
||||||
|
self.msc4293_enabled: bool = experimental.get("msc4293_enabled", False)
|
||||||
|
@ -42,6 +42,7 @@ from synapse.api.errors import (
|
|||||||
NotApprovedError,
|
NotApprovedError,
|
||||||
SynapseError,
|
SynapseError,
|
||||||
UserDeactivatedError,
|
UserDeactivatedError,
|
||||||
|
UserLockedError,
|
||||||
)
|
)
|
||||||
from synapse.api.ratelimiting import Ratelimiter
|
from synapse.api.ratelimiting import Ratelimiter
|
||||||
from synapse.api.urls import CLIENT_API_PREFIX
|
from synapse.api.urls import CLIENT_API_PREFIX
|
||||||
@ -313,7 +314,7 @@ class LoginRestServlet(RestServlet):
|
|||||||
should_issue_refresh_token=should_issue_refresh_token,
|
should_issue_refresh_token=should_issue_refresh_token,
|
||||||
# The user represented by an appservice's configured sender_localpart
|
# The user represented by an appservice's configured sender_localpart
|
||||||
# is not actually created in Synapse.
|
# is not actually created in Synapse.
|
||||||
should_check_deactivated=qualified_user_id != appservice.sender,
|
should_check_deactivated_or_locked=qualified_user_id != appservice.sender,
|
||||||
request_info=request_info,
|
request_info=request_info,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -367,7 +368,7 @@ class LoginRestServlet(RestServlet):
|
|||||||
auth_provider_id: Optional[str] = None,
|
auth_provider_id: Optional[str] = None,
|
||||||
should_issue_refresh_token: bool = False,
|
should_issue_refresh_token: bool = False,
|
||||||
auth_provider_session_id: Optional[str] = None,
|
auth_provider_session_id: Optional[str] = None,
|
||||||
should_check_deactivated: bool = True,
|
should_check_deactivated_or_locked: bool = True,
|
||||||
*,
|
*,
|
||||||
request_info: RequestInfo,
|
request_info: RequestInfo,
|
||||||
) -> LoginResponse:
|
) -> LoginResponse:
|
||||||
@ -389,8 +390,8 @@ class LoginRestServlet(RestServlet):
|
|||||||
should_issue_refresh_token: True if this login should issue
|
should_issue_refresh_token: True if this login should issue
|
||||||
a refresh token alongside the access token.
|
a refresh token alongside the access token.
|
||||||
auth_provider_session_id: The session ID got during login from the SSO IdP.
|
auth_provider_session_id: The session ID got during login from the SSO IdP.
|
||||||
should_check_deactivated: True if the user should be checked for
|
should_check_deactivated_or_locked: True if the user should be checked for
|
||||||
deactivation status before logging in.
|
deactivation or locked status before logging in.
|
||||||
|
|
||||||
This exists purely for appservice's configured sender_localpart
|
This exists purely for appservice's configured sender_localpart
|
||||||
which doesn't have an associated user in the database.
|
which doesn't have an associated user in the database.
|
||||||
@ -415,11 +416,14 @@ class LoginRestServlet(RestServlet):
|
|||||||
)
|
)
|
||||||
user_id = canonical_uid
|
user_id = canonical_uid
|
||||||
|
|
||||||
# If the account has been deactivated, do not proceed with the login.
|
# If the account has been deactivated or locked, do not proceed with the login.
|
||||||
if should_check_deactivated:
|
if should_check_deactivated_or_locked:
|
||||||
deactivated = await self._main_store.get_user_deactivated_status(user_id)
|
deactivated = await self._main_store.get_user_deactivated_status(user_id)
|
||||||
if deactivated:
|
if deactivated:
|
||||||
raise UserDeactivatedError("This account has been deactivated")
|
raise UserDeactivatedError("This account has been deactivated")
|
||||||
|
locked = await self._main_store.get_user_locked_status(user_id)
|
||||||
|
if locked:
|
||||||
|
raise UserLockedError()
|
||||||
|
|
||||||
device_id = login_submission.get("device_id")
|
device_id = login_submission.get("device_id")
|
||||||
|
|
||||||
|
@ -1088,6 +1088,7 @@ class RoomMembershipRestServlet(TransactionRestServlet):
|
|||||||
super().__init__(hs)
|
super().__init__(hs)
|
||||||
self.room_member_handler = hs.get_room_member_handler()
|
self.room_member_handler = hs.get_room_member_handler()
|
||||||
self.auth = hs.get_auth()
|
self.auth = hs.get_auth()
|
||||||
|
self.config = hs.config
|
||||||
|
|
||||||
def register(self, http_server: HttpServer) -> None:
|
def register(self, http_server: HttpServer) -> None:
|
||||||
# /rooms/$roomid/[join|invite|leave|ban|unban|kick]
|
# /rooms/$roomid/[join|invite|leave|ban|unban|kick]
|
||||||
@ -1111,12 +1112,12 @@ class RoomMembershipRestServlet(TransactionRestServlet):
|
|||||||
}:
|
}:
|
||||||
raise AuthError(403, "Guest access not allowed")
|
raise AuthError(403, "Guest access not allowed")
|
||||||
|
|
||||||
content = parse_json_object_from_request(request, allow_empty_body=True)
|
request_body = parse_json_object_from_request(request, allow_empty_body=True)
|
||||||
|
|
||||||
if membership_action == "invite" and all(
|
if membership_action == "invite" and all(
|
||||||
key in content for key in ("medium", "address")
|
key in request_body for key in ("medium", "address")
|
||||||
):
|
):
|
||||||
if not all(key in content for key in ("id_server", "id_access_token")):
|
if not all(key in request_body for key in ("id_server", "id_access_token")):
|
||||||
raise SynapseError(
|
raise SynapseError(
|
||||||
HTTPStatus.BAD_REQUEST,
|
HTTPStatus.BAD_REQUEST,
|
||||||
"`id_server` and `id_access_token` are required when doing 3pid invite",
|
"`id_server` and `id_access_token` are required when doing 3pid invite",
|
||||||
@ -1127,12 +1128,12 @@ class RoomMembershipRestServlet(TransactionRestServlet):
|
|||||||
await self.room_member_handler.do_3pid_invite(
|
await self.room_member_handler.do_3pid_invite(
|
||||||
room_id,
|
room_id,
|
||||||
requester.user,
|
requester.user,
|
||||||
content["medium"],
|
request_body["medium"],
|
||||||
content["address"],
|
request_body["address"],
|
||||||
content["id_server"],
|
request_body["id_server"],
|
||||||
requester,
|
requester,
|
||||||
txn_id,
|
txn_id,
|
||||||
content["id_access_token"],
|
request_body["id_access_token"],
|
||||||
)
|
)
|
||||||
except ShadowBanError:
|
except ShadowBanError:
|
||||||
# Pretend the request succeeded.
|
# Pretend the request succeeded.
|
||||||
@ -1141,12 +1142,19 @@ class RoomMembershipRestServlet(TransactionRestServlet):
|
|||||||
|
|
||||||
target = requester.user
|
target = requester.user
|
||||||
if membership_action in ["invite", "ban", "unban", "kick"]:
|
if membership_action in ["invite", "ban", "unban", "kick"]:
|
||||||
assert_params_in_dict(content, ["user_id"])
|
assert_params_in_dict(request_body, ["user_id"])
|
||||||
target = UserID.from_string(content["user_id"])
|
target = UserID.from_string(request_body["user_id"])
|
||||||
|
|
||||||
event_content = None
|
event_content = None
|
||||||
if "reason" in content:
|
if "reason" in request_body:
|
||||||
event_content = {"reason": content["reason"]}
|
event_content = {"reason": request_body["reason"]}
|
||||||
|
if self.config.experimental.msc4293_enabled:
|
||||||
|
if "org.matrix.msc4293.redact_events" in request_body:
|
||||||
|
if event_content is None:
|
||||||
|
event_content = {}
|
||||||
|
event_content["org.matrix.msc4293.redact_events"] = request_body[
|
||||||
|
"org.matrix.msc4293.redact_events"
|
||||||
|
]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await self.room_member_handler.update_membership(
|
await self.room_member_handler.update_membership(
|
||||||
@ -1155,7 +1163,7 @@ class RoomMembershipRestServlet(TransactionRestServlet):
|
|||||||
room_id=room_id,
|
room_id=room_id,
|
||||||
action=membership_action,
|
action=membership_action,
|
||||||
txn_id=txn_id,
|
txn_id=txn_id,
|
||||||
third_party_signed=content.get("third_party_signed", None),
|
third_party_signed=request_body.get("third_party_signed", None),
|
||||||
content=event_content,
|
content=event_content,
|
||||||
)
|
)
|
||||||
except ShadowBanError:
|
except ShadowBanError:
|
||||||
|
@ -34,6 +34,7 @@ from synapse.metrics.background_process_metrics import wrap_as_background_proces
|
|||||||
from synapse.storage.database import LoggingTransaction
|
from synapse.storage.database import LoggingTransaction
|
||||||
from synapse.storage.databases import Databases
|
from synapse.storage.databases import Databases
|
||||||
from synapse.types.storage import _BackgroundUpdates
|
from synapse.types.storage import _BackgroundUpdates
|
||||||
|
from synapse.util.stringutils import shortstr
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from synapse.server import HomeServer
|
from synapse.server import HomeServer
|
||||||
@ -167,6 +168,12 @@ class PurgeEventsStorageController:
|
|||||||
break
|
break
|
||||||
|
|
||||||
(room_id, groups_to_sequences) = next_to_delete
|
(room_id, groups_to_sequences) = next_to_delete
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"[purge] deleting state groups for room %s: %s",
|
||||||
|
room_id,
|
||||||
|
shortstr(groups_to_sequences.keys(), maxitems=10),
|
||||||
|
)
|
||||||
made_progress = await self._delete_state_groups(
|
made_progress = await self._delete_state_groups(
|
||||||
room_id, groups_to_sequences
|
room_id, groups_to_sequences
|
||||||
)
|
)
|
||||||
|
@ -108,6 +108,9 @@ SLIDING_SYNC_RELEVANT_STATE_SET = (
|
|||||||
(EventTypes.Tombstone, ""),
|
(EventTypes.Tombstone, ""),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# An arbitrarily large number
|
||||||
|
MAX_EVENTS = 1000000
|
||||||
|
|
||||||
|
|
||||||
@attr.s(slots=True, auto_attribs=True)
|
@attr.s(slots=True, auto_attribs=True)
|
||||||
class DeltaState:
|
class DeltaState:
|
||||||
@ -376,6 +379,109 @@ class PersistEventsStore:
|
|||||||
|
|
||||||
event_counter.labels(event.type, origin_type, origin_entity).inc()
|
event_counter.labels(event.type, origin_type, origin_entity).inc()
|
||||||
|
|
||||||
|
if (
|
||||||
|
not self.hs.config.experimental.msc4293_enabled
|
||||||
|
or event.type != EventTypes.Member
|
||||||
|
or event.state_key is None
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# check if this is an unban/join that will undo a ban/kick redaction for
|
||||||
|
# user in room
|
||||||
|
if event.membership in [Membership.LEAVE, Membership.JOIN]:
|
||||||
|
if event.membership == Membership.LEAVE:
|
||||||
|
# self-leave, ignore
|
||||||
|
if event.sender == event.state_key:
|
||||||
|
continue
|
||||||
|
# check to see if there is an existing ban/leave causing redactions for
|
||||||
|
# this user/room combination
|
||||||
|
res = await self.db_pool.simple_select_list(
|
||||||
|
"room_ban_redactions",
|
||||||
|
{"room_id": event.room_id, "user_id": event.state_key},
|
||||||
|
["room_id", "user_id"],
|
||||||
|
)
|
||||||
|
if res:
|
||||||
|
# if so, update the entry with the stream ordering when the redactions should
|
||||||
|
# stop
|
||||||
|
await self.db_pool.simple_update(
|
||||||
|
"room_ban_redactions",
|
||||||
|
{"room_id": event.room_id, "user_id": event.state_key},
|
||||||
|
{
|
||||||
|
"redact_end_ordering": event.internal_metadata.stream_ordering
|
||||||
|
},
|
||||||
|
desc="room_ban_redactions update redact_end_ordering",
|
||||||
|
)
|
||||||
|
|
||||||
|
# check for msc4293 redact_events flag and apply if found
|
||||||
|
if event.membership not in [Membership.LEAVE, Membership.BAN]:
|
||||||
|
continue
|
||||||
|
redact = event.content.get("org.matrix.msc4293.redact_events", False)
|
||||||
|
if not redact or not isinstance(redact, bool):
|
||||||
|
continue
|
||||||
|
# self-bans currently are not authorized so we don't check for that
|
||||||
|
# case
|
||||||
|
if (
|
||||||
|
event.membership == Membership.LEAVE
|
||||||
|
and event.sender == event.state_key
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
# check that sender can redact
|
||||||
|
state_filter = StateFilter.from_types([(EventTypes.PowerLevels, "")])
|
||||||
|
state = await self.store.get_partial_filtered_current_state_ids(
|
||||||
|
event.room_id, state_filter
|
||||||
|
)
|
||||||
|
pl_id = state[(EventTypes.PowerLevels, "")]
|
||||||
|
pl_event = await self.store.get_event(pl_id)
|
||||||
|
if pl_event:
|
||||||
|
sender_level = pl_event.content.get("users", {}).get(event.sender)
|
||||||
|
if sender_level is None:
|
||||||
|
sender_level = pl_event.content.get("users_default", 0)
|
||||||
|
|
||||||
|
redact_level = pl_event.content.get("redact")
|
||||||
|
if not redact_level:
|
||||||
|
redact_level = pl_event.content.get("events_default", 0)
|
||||||
|
|
||||||
|
room_redaction_level = pl_event.content.get("events", {}).get(
|
||||||
|
"m.room.redaction"
|
||||||
|
)
|
||||||
|
if room_redaction_level:
|
||||||
|
if sender_level < room_redaction_level:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if sender_level >= redact_level:
|
||||||
|
await self.db_pool.simple_upsert(
|
||||||
|
"room_ban_redactions",
|
||||||
|
{"room_id": event.room_id, "user_id": event.state_key},
|
||||||
|
{
|
||||||
|
"redacting_event_id": event.event_id,
|
||||||
|
"redact_end_ordering": None,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"room_id": event.room_id,
|
||||||
|
"user_id": event.state_key,
|
||||||
|
"redacting_event_id": event.event_id,
|
||||||
|
"redact_end_ordering": None,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
# normally the cache entry for a redacted event would be invalidated
|
||||||
|
# by an arriving redaction event, but since we are not creating redaction
|
||||||
|
# events we invalidate manually
|
||||||
|
ids_to_redact = (
|
||||||
|
await self.store.get_events_sent_by_user_in_room(
|
||||||
|
event.state_key, event.room_id, limit=MAX_EVENTS
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if not ids_to_redact:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for id in ids_to_redact:
|
||||||
|
await self.db_pool.runInteraction(
|
||||||
|
"invalidate cache",
|
||||||
|
self.store.invalidate_get_event_cache_after_txn,
|
||||||
|
id,
|
||||||
|
)
|
||||||
|
|
||||||
if new_forward_extremities:
|
if new_forward_extremities:
|
||||||
self.store.get_latest_event_ids_in_room.prefill(
|
self.store.get_latest_event_ids_in_room.prefill(
|
||||||
(room_id,), frozenset(new_forward_extremities)
|
(room_id,), frozenset(new_forward_extremities)
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
# [This file includes modifications made by New Vector Limited]
|
# [This file includes modifications made by New Vector Limited]
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import threading
|
import threading
|
||||||
import weakref
|
import weakref
|
||||||
@ -1571,6 +1571,42 @@ class EventsWorkerStore(SQLBaseStore):
|
|||||||
if d:
|
if d:
|
||||||
d.redactions.append(redacter)
|
d.redactions.append(redacter)
|
||||||
|
|
||||||
|
# check for MSC4932 redactions
|
||||||
|
to_check = []
|
||||||
|
events: List[_EventRow] = []
|
||||||
|
for e in evs:
|
||||||
|
event = event_dict.get(e)
|
||||||
|
if not event:
|
||||||
|
continue
|
||||||
|
events.append(event)
|
||||||
|
event_json = json.loads(event.json)
|
||||||
|
room_id = event_json.get("room_id")
|
||||||
|
user_id = event_json.get("sender")
|
||||||
|
to_check.append((room_id, user_id))
|
||||||
|
|
||||||
|
# likely that some of these events may be for the same room/user combo, in
|
||||||
|
# which case we don't need to do redundant queries
|
||||||
|
to_check_set = set(to_check)
|
||||||
|
for room_and_user in to_check_set:
|
||||||
|
room_redactions_sql = "SELECT redacting_event_id, redact_end_ordering FROM room_ban_redactions WHERE room_id = ? and user_id = ?"
|
||||||
|
txn.execute(room_redactions_sql, room_and_user)
|
||||||
|
|
||||||
|
res = txn.fetchone()
|
||||||
|
# we have a redaction for a room, user_id combo - apply it to matching events
|
||||||
|
if not res:
|
||||||
|
continue
|
||||||
|
for e_row in events:
|
||||||
|
e_json = json.loads(e_row.json)
|
||||||
|
room_id = e_json.get("room_id")
|
||||||
|
user_id = e_json.get("sender")
|
||||||
|
if room_and_user != (room_id, user_id):
|
||||||
|
continue
|
||||||
|
redacting_event_id, redact_end_ordering = res
|
||||||
|
if redact_end_ordering:
|
||||||
|
if e_row.stream_ordering < redact_end_ordering:
|
||||||
|
e_row.redactions.append(redacting_event_id)
|
||||||
|
else:
|
||||||
|
e_row.redactions.append(redacting_event_id)
|
||||||
return event_dict
|
return event_dict
|
||||||
|
|
||||||
def _maybe_redact_event_row(
|
def _maybe_redact_event_row(
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
--
|
||||||
|
-- This file is licensed under the Affero General Public License (AGPL) version 3.
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2025 New Vector, Ltd
|
||||||
|
--
|
||||||
|
-- This program is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU Affero General Public License as
|
||||||
|
-- published by the Free Software Foundation, either version 3 of the
|
||||||
|
-- License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- See the GNU Affero General Public License for more details:
|
||||||
|
-- <https://www.gnu.org/licenses/agpl-3.0.html>.
|
||||||
|
|
||||||
|
CREATE TABLE room_ban_redactions(
|
||||||
|
room_id text NOT NULL,
|
||||||
|
user_id text NOT NULL,
|
||||||
|
redacting_event_id text NOT NULL,
|
||||||
|
redact_end_ordering bigint DEFAULT NULL, -- stream ordering after which redactions are not applied
|
||||||
|
CONSTRAINT room_ban_redaction_uniqueness UNIQUE (room_id, user_id)
|
||||||
|
);
|
||||||
|
|
@ -2846,6 +2846,16 @@ class UserRestTestCase(unittest.HomeserverTestCase):
|
|||||||
self.assertEqual(Codes.USER_LOCKED, channel.json_body["errcode"])
|
self.assertEqual(Codes.USER_LOCKED, channel.json_body["errcode"])
|
||||||
self.assertTrue(channel.json_body["soft_logout"])
|
self.assertTrue(channel.json_body["soft_logout"])
|
||||||
|
|
||||||
|
# User is not authorized to log in anymore
|
||||||
|
channel = self.make_request(
|
||||||
|
"POST",
|
||||||
|
"/_matrix/client/r0/login",
|
||||||
|
{"type": "m.login.password", "user": "user", "password": "pass"},
|
||||||
|
)
|
||||||
|
self.assertEqual(401, channel.code, msg=channel.json_body)
|
||||||
|
self.assertEqual(Codes.USER_LOCKED, channel.json_body["errcode"])
|
||||||
|
self.assertTrue(channel.json_body["soft_logout"])
|
||||||
|
|
||||||
@override_config({"user_directory": {"enabled": True, "search_all_users": True}})
|
@override_config({"user_directory": {"enabled": True, "search_all_users": True}})
|
||||||
def test_locked_user_not_in_user_dir(self) -> None:
|
def test_locked_user_not_in_user_dir(self) -> None:
|
||||||
# User is available in the user dir
|
# User is available in the user dir
|
||||||
|
@ -43,8 +43,9 @@ from synapse.api.constants import (
|
|||||||
RoomTypes,
|
RoomTypes,
|
||||||
)
|
)
|
||||||
from synapse.api.errors import Codes, HttpResponseException
|
from synapse.api.errors import Codes, HttpResponseException
|
||||||
|
from synapse.api.room_versions import RoomVersions
|
||||||
from synapse.appservice import ApplicationService
|
from synapse.appservice import ApplicationService
|
||||||
from synapse.events import EventBase
|
from synapse.events import EventBase, make_event_from_dict
|
||||||
from synapse.events.snapshot import EventContext
|
from synapse.events.snapshot import EventContext
|
||||||
from synapse.rest import admin
|
from synapse.rest import admin
|
||||||
from synapse.rest.client import (
|
from synapse.rest.client import (
|
||||||
@ -4401,3 +4402,985 @@ class RoomParticipantTestCase(unittest.HomeserverTestCase):
|
|||||||
self.store.get_room_participation(self.user2, self.room1)
|
self.store.get_room_participation(self.user2, self.room1)
|
||||||
)
|
)
|
||||||
self.assertFalse(participant)
|
self.assertFalse(participant)
|
||||||
|
|
||||||
|
|
||||||
|
class MSC4293RedactOnBanKickTestCase(unittest.FederatingHomeserverTestCase):
|
||||||
|
servlets = [
|
||||||
|
synapse.rest.admin.register_servlets_for_client_rest_resource,
|
||||||
|
room.register_servlets,
|
||||||
|
login.register_servlets,
|
||||||
|
admin.register_servlets,
|
||||||
|
]
|
||||||
|
|
||||||
|
def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
|
||||||
|
super().prepare(reactor, clock, hs)
|
||||||
|
self.creator = self.register_user("creator", "test")
|
||||||
|
self.creator_tok = self.login("creator", "test")
|
||||||
|
|
||||||
|
self.bad_user_id = self.register_user("bad", "test")
|
||||||
|
self.bad_tok = self.login("bad", "test")
|
||||||
|
|
||||||
|
self.room_id = self.helper.create_room_as(self.creator, tok=self.creator_tok)
|
||||||
|
|
||||||
|
self.store = hs.get_datastores().main
|
||||||
|
self._storage_controllers = hs.get_storage_controllers()
|
||||||
|
|
||||||
|
self.federation_event_handler = self.hs.get_federation_event_handler()
|
||||||
|
|
||||||
|
self.hs.config.experimental.msc4293_enabled = True
|
||||||
|
|
||||||
|
def _check_redactions(
|
||||||
|
self,
|
||||||
|
original_events: List[EventBase],
|
||||||
|
pulled_events: List[JsonDict],
|
||||||
|
expect_redaction: bool,
|
||||||
|
reason: Optional[str] = None,
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Checks a set of original events against a second set of the same events, pulled
|
||||||
|
from the /messages api. If expect_redaction is true, we expect that the second
|
||||||
|
set of events will be redacted, and the test will fail if that is not the case.
|
||||||
|
Otherwise, verifies that the events have not been redacted and fails if not.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
original_events: A list of the original events sent
|
||||||
|
pulled_events: A list of the same events as the orignal events, fetched
|
||||||
|
over the /messages api
|
||||||
|
expect_redaction: Whether or not the pulled_events should be redacted
|
||||||
|
reason: If the events are expected to be redacted, the expected reason
|
||||||
|
for the redaction
|
||||||
|
|
||||||
|
"""
|
||||||
|
if expect_redaction:
|
||||||
|
redacted_count = 0
|
||||||
|
for pulled_event in pulled_events:
|
||||||
|
for old_event in original_events:
|
||||||
|
if pulled_event["event_id"] != old_event.event_id:
|
||||||
|
continue
|
||||||
|
# we have a matching event, check that it is redacted
|
||||||
|
event_content = pulled_event["content"]
|
||||||
|
if event_content:
|
||||||
|
self.fail(f"Expected event {pulled_event} to be redacted")
|
||||||
|
redacting_event = pulled_event.get("redacted_because")
|
||||||
|
if not redacting_event:
|
||||||
|
self.fail(
|
||||||
|
f"Expected event {pulled_event} to have a redacting event."
|
||||||
|
)
|
||||||
|
# check that the redacting event records the expected reason, and the
|
||||||
|
# redact_events flag
|
||||||
|
content = redacting_event["content"]
|
||||||
|
self.assertEqual(content["reason"], reason)
|
||||||
|
self.assertEqual(content["org.matrix.msc4293.redact_events"], True)
|
||||||
|
redacted_count += 1
|
||||||
|
# all provided events should be redacted
|
||||||
|
self.assertEqual(len(original_events), redacted_count)
|
||||||
|
else:
|
||||||
|
unredacted_events = 0
|
||||||
|
for pulled_event in pulled_events:
|
||||||
|
for old_event in original_events:
|
||||||
|
if pulled_event["event_id"] != old_event.event_id:
|
||||||
|
continue
|
||||||
|
# we have a matching event, make sure it is not redacted
|
||||||
|
redacted_because = pulled_event.get("redacted_because")
|
||||||
|
if redacted_because:
|
||||||
|
self.fail("Event should not have been redacted")
|
||||||
|
self.assertEqual(old_event.content, pulled_event["content"])
|
||||||
|
unredacted_events += 1
|
||||||
|
# all provided events should not have been redacted
|
||||||
|
self.assertEqual(unredacted_events, len(original_events))
|
||||||
|
|
||||||
|
def test_banning_local_member_with_flag_redacts_their_events(self) -> None:
|
||||||
|
self.helper.join(self.room_id, self.bad_user_id, tok=self.bad_tok)
|
||||||
|
|
||||||
|
# bad user send some messages
|
||||||
|
originals = []
|
||||||
|
for i in range(5):
|
||||||
|
event = {"body": f"bothersome noise {i}", "msgtype": "m.text"}
|
||||||
|
res = self.helper.send_event(
|
||||||
|
self.room_id, "m.room.message", event, tok=self.bad_tok, expect_code=200
|
||||||
|
)
|
||||||
|
originals.append(res["event_id"])
|
||||||
|
|
||||||
|
# grab original events for comparison
|
||||||
|
original_events = [self.get_success(self.store.get_event(x)) for x in originals]
|
||||||
|
|
||||||
|
# creator bans user with redaction flag set
|
||||||
|
content = {
|
||||||
|
"reason": "flooding",
|
||||||
|
"org.matrix.msc4293.redact_events": True,
|
||||||
|
}
|
||||||
|
self.helper.change_membership(
|
||||||
|
self.room_id,
|
||||||
|
self.creator,
|
||||||
|
self.bad_user_id,
|
||||||
|
"ban",
|
||||||
|
content,
|
||||||
|
self.creator_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
filter = json.dumps({"types": [EventTypes.Message]})
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
f"rooms/{self.room_id}/messages?filter={filter}&limit=50",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
self._check_redactions(
|
||||||
|
original_events,
|
||||||
|
channel.json_body["chunk"],
|
||||||
|
expect_redaction=True,
|
||||||
|
reason="flooding",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_banning_remote_member_with_flag_redacts_their_events(self) -> None:
|
||||||
|
bad_user = "@remote_bad_user:" + self.OTHER_SERVER_NAME
|
||||||
|
channel = self.make_signed_federation_request(
|
||||||
|
"GET",
|
||||||
|
f"/_matrix/federation/v1/make_join/{self.room_id}/{bad_user}?ver=10",
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, HTTPStatus.OK, channel.json_body)
|
||||||
|
join_result = channel.json_body
|
||||||
|
|
||||||
|
join_event_dict = join_result["event"]
|
||||||
|
self.add_hashes_and_signatures_from_other_server(
|
||||||
|
join_event_dict,
|
||||||
|
RoomVersions.V10,
|
||||||
|
)
|
||||||
|
channel = self.make_signed_federation_request(
|
||||||
|
"PUT",
|
||||||
|
f"/_matrix/federation/v2/send_join/{self.room_id}/x",
|
||||||
|
content=join_event_dict,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, HTTPStatus.OK, channel.json_body)
|
||||||
|
|
||||||
|
# the room should show that the bad user is a member
|
||||||
|
r = self.get_success(
|
||||||
|
self._storage_controllers.state.get_current_state(self.room_id)
|
||||||
|
)
|
||||||
|
self.assertEqual(r[("m.room.member", bad_user)].membership, "join")
|
||||||
|
|
||||||
|
auth_ids = [
|
||||||
|
r[("m.room.create", "")].event_id,
|
||||||
|
r[("m.room.power_levels", "")].event_id,
|
||||||
|
r[("m.room.member", "@remote_bad_user:other.example.com")].event_id,
|
||||||
|
]
|
||||||
|
original_messages = []
|
||||||
|
for i in range(5):
|
||||||
|
remote_message = make_event_from_dict(
|
||||||
|
self.add_hashes_and_signatures_from_other_server(
|
||||||
|
{
|
||||||
|
"room_id": self.room_id,
|
||||||
|
"sender": bad_user,
|
||||||
|
"depth": 1000,
|
||||||
|
"origin_server_ts": 1,
|
||||||
|
"type": "m.room.message",
|
||||||
|
"content": {"body": f"remote bummer{i}"},
|
||||||
|
"auth_events": auth_ids,
|
||||||
|
"prev_events": auth_ids,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
room_version=RoomVersions.V10,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.get_success(
|
||||||
|
self.federation_event_handler.on_receive_pdu(
|
||||||
|
self.OTHER_SERVER_NAME, remote_message
|
||||||
|
)
|
||||||
|
)
|
||||||
|
original_messages.append(remote_message)
|
||||||
|
|
||||||
|
# creator bans bad user with redaction flag set
|
||||||
|
content = {
|
||||||
|
"reason": "bummer messages",
|
||||||
|
"org.matrix.msc4293.redact_events": True,
|
||||||
|
}
|
||||||
|
res = self.helper.change_membership(
|
||||||
|
self.room_id, self.creator, bad_user, "ban", content, self.creator_tok
|
||||||
|
)
|
||||||
|
ban_event_id = res["event_id"]
|
||||||
|
|
||||||
|
filter = json.dumps({"types": [EventTypes.Message]})
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
f"rooms/{self.room_id}/messages?filter={filter}&limit=50",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
self._check_redactions(
|
||||||
|
original_messages,
|
||||||
|
channel.json_body["chunk"],
|
||||||
|
expect_redaction=True,
|
||||||
|
reason="bummer messages",
|
||||||
|
)
|
||||||
|
|
||||||
|
# any future messages that are soft-failed are also redacted - send messages referencing
|
||||||
|
# dag before ban, they should be soft-failed but also redacted
|
||||||
|
new_original_messages = []
|
||||||
|
for i in range(5):
|
||||||
|
remote_message = make_event_from_dict(
|
||||||
|
self.add_hashes_and_signatures_from_other_server(
|
||||||
|
{
|
||||||
|
"room_id": self.room_id,
|
||||||
|
"sender": bad_user,
|
||||||
|
"depth": 1000,
|
||||||
|
"origin_server_ts": 1,
|
||||||
|
"type": "m.room.message",
|
||||||
|
"content": {"body": f"soft-fail remote bummer{i}"},
|
||||||
|
"auth_events": auth_ids,
|
||||||
|
"prev_events": auth_ids,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
room_version=RoomVersions.V10,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.get_success(
|
||||||
|
self.federation_event_handler.on_receive_pdu(
|
||||||
|
self.OTHER_SERVER_NAME, remote_message
|
||||||
|
)
|
||||||
|
)
|
||||||
|
new_original_messages.append(remote_message)
|
||||||
|
|
||||||
|
# pull them from the db to check because they should be soft-failed and thus not available over
|
||||||
|
# cs-api
|
||||||
|
for message in new_original_messages:
|
||||||
|
original = self.get_success(self.store.get_event(message.event_id))
|
||||||
|
if not original:
|
||||||
|
self.fail("Expected to find remote message in DB")
|
||||||
|
redacted_because = original.unsigned.get("redacted_because")
|
||||||
|
if not redacted_because:
|
||||||
|
self.fail("Did not find redacted_because field")
|
||||||
|
self.assertEqual(redacted_because.event_id, ban_event_id)
|
||||||
|
|
||||||
|
def test_unbanning_remote_user_stops_redaction_action(self) -> None:
|
||||||
|
bad_user = "@remote_bad_user:" + self.OTHER_SERVER_NAME
|
||||||
|
channel = self.make_signed_federation_request(
|
||||||
|
"GET",
|
||||||
|
f"/_matrix/federation/v1/make_join/{self.room_id}/{bad_user}?ver=10",
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, HTTPStatus.OK, channel.json_body)
|
||||||
|
join_result = channel.json_body
|
||||||
|
|
||||||
|
join_event_dict = join_result["event"]
|
||||||
|
self.add_hashes_and_signatures_from_other_server(
|
||||||
|
join_event_dict,
|
||||||
|
RoomVersions.V10,
|
||||||
|
)
|
||||||
|
channel = self.make_signed_federation_request(
|
||||||
|
"PUT",
|
||||||
|
f"/_matrix/federation/v2/send_join/{self.room_id}/x",
|
||||||
|
content=join_event_dict,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, HTTPStatus.OK, channel.json_body)
|
||||||
|
|
||||||
|
# the room should show that the bad user is a member
|
||||||
|
r = self.get_success(
|
||||||
|
self._storage_controllers.state.get_current_state(self.room_id)
|
||||||
|
)
|
||||||
|
self.assertEqual(r[("m.room.member", bad_user)].membership, "join")
|
||||||
|
|
||||||
|
auth_ids = [
|
||||||
|
r[("m.room.create", "")].event_id,
|
||||||
|
r[("m.room.power_levels", "")].event_id,
|
||||||
|
r[("m.room.member", "@remote_bad_user:other.example.com")].event_id,
|
||||||
|
]
|
||||||
|
original_messages = []
|
||||||
|
for i in range(5):
|
||||||
|
remote_message = make_event_from_dict(
|
||||||
|
self.add_hashes_and_signatures_from_other_server(
|
||||||
|
{
|
||||||
|
"room_id": self.room_id,
|
||||||
|
"sender": bad_user,
|
||||||
|
"depth": 1000,
|
||||||
|
"origin_server_ts": 1,
|
||||||
|
"type": "m.room.message",
|
||||||
|
"content": {"body": f"annoying messages {i}"},
|
||||||
|
"auth_events": auth_ids,
|
||||||
|
"prev_events": auth_ids,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
room_version=RoomVersions.V10,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.get_success(
|
||||||
|
self.federation_event_handler.on_receive_pdu(
|
||||||
|
self.OTHER_SERVER_NAME, remote_message
|
||||||
|
)
|
||||||
|
)
|
||||||
|
original_messages.append(remote_message)
|
||||||
|
|
||||||
|
# creator bans bad user with redaction flag set
|
||||||
|
content = {
|
||||||
|
"reason": "this dude sucks",
|
||||||
|
"org.matrix.msc4293.redact_events": True,
|
||||||
|
}
|
||||||
|
self.helper.change_membership(
|
||||||
|
self.room_id, self.creator, bad_user, "ban", content, self.creator_tok
|
||||||
|
)
|
||||||
|
|
||||||
|
filter = json.dumps({"types": [EventTypes.Message]})
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
f"rooms/{self.room_id}/messages?filter={filter}&limit=50",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
self._check_redactions(
|
||||||
|
original_messages,
|
||||||
|
channel.json_body["chunk"],
|
||||||
|
True,
|
||||||
|
reason="this dude sucks",
|
||||||
|
)
|
||||||
|
|
||||||
|
# unban user
|
||||||
|
self.helper.change_membership(
|
||||||
|
self.room_id, self.creator, bad_user, "unban", {}, self.creator_tok
|
||||||
|
)
|
||||||
|
|
||||||
|
# user should be able to join again
|
||||||
|
channel = self.make_signed_federation_request(
|
||||||
|
"GET",
|
||||||
|
f"/_matrix/federation/v1/make_join/{self.room_id}/{bad_user}?ver=10",
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, HTTPStatus.OK, channel.json_body)
|
||||||
|
join_result = channel.json_body
|
||||||
|
|
||||||
|
join_event_dict = join_result["event"]
|
||||||
|
self.add_hashes_and_signatures_from_other_server(
|
||||||
|
join_event_dict,
|
||||||
|
RoomVersions.V10,
|
||||||
|
)
|
||||||
|
channel = self.make_signed_federation_request(
|
||||||
|
"PUT",
|
||||||
|
f"/_matrix/federation/v2/send_join/{self.room_id}/x",
|
||||||
|
content=join_event_dict,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, HTTPStatus.OK, channel.json_body)
|
||||||
|
|
||||||
|
# the room should show that the bad user is a member again
|
||||||
|
new_state = self.get_success(
|
||||||
|
self._storage_controllers.state.get_current_state(self.room_id)
|
||||||
|
)
|
||||||
|
self.assertEqual(new_state[("m.room.member", bad_user)].membership, "join")
|
||||||
|
|
||||||
|
new_state = self.get_success(
|
||||||
|
self._storage_controllers.state.get_current_state(self.room_id)
|
||||||
|
)
|
||||||
|
auth_ids = [
|
||||||
|
new_state[("m.room.create", "")].event_id,
|
||||||
|
new_state[("m.room.power_levels", "")].event_id,
|
||||||
|
new_state[("m.room.member", "@remote_bad_user:other.example.com")].event_id,
|
||||||
|
]
|
||||||
|
|
||||||
|
# messages after unban and join proceed unredacted
|
||||||
|
new_original_messages = []
|
||||||
|
for i in range(5):
|
||||||
|
remote_message = make_event_from_dict(
|
||||||
|
self.add_hashes_and_signatures_from_other_server(
|
||||||
|
{
|
||||||
|
"room_id": self.room_id,
|
||||||
|
"sender": bad_user,
|
||||||
|
"depth": 1000,
|
||||||
|
"origin_server_ts": 1,
|
||||||
|
"type": "m.room.message",
|
||||||
|
"content": {"body": f"no longer a bummer {i}"},
|
||||||
|
"auth_events": auth_ids,
|
||||||
|
"prev_events": auth_ids,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
room_version=RoomVersions.V10,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.get_success(
|
||||||
|
self.federation_event_handler.on_receive_pdu(
|
||||||
|
self.OTHER_SERVER_NAME, remote_message
|
||||||
|
)
|
||||||
|
)
|
||||||
|
new_original_messages.append(remote_message)
|
||||||
|
|
||||||
|
filter = json.dumps({"types": [EventTypes.Message]})
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
f"rooms/{self.room_id}/messages?filter={filter}&limit=50",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
self._check_redactions(new_original_messages, channel.json_body["chunk"], False)
|
||||||
|
|
||||||
|
def test_redaction_flag_ignored_for_user_if_banner_lacks_redaction_power(
|
||||||
|
self,
|
||||||
|
) -> None:
|
||||||
|
# change power levels so creator can ban but not redact
|
||||||
|
self.helper.send_state(
|
||||||
|
self.room_id,
|
||||||
|
"m.room.power_levels",
|
||||||
|
{"events_default": 0, "redact": 100, "users": {self.creator: 75}},
|
||||||
|
tok=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.helper.join(self.room_id, self.bad_user_id, tok=self.bad_tok)
|
||||||
|
|
||||||
|
# bad user send some messages
|
||||||
|
original_ids = []
|
||||||
|
for i in range(15):
|
||||||
|
event = {"body": f"being a menace {i}", "msgtype": "m.text"}
|
||||||
|
res = self.helper.send_event(
|
||||||
|
self.room_id, "m.room.message", event, tok=self.bad_tok, expect_code=200
|
||||||
|
)
|
||||||
|
original_ids.append(res["event_id"])
|
||||||
|
|
||||||
|
# grab original events before ban
|
||||||
|
originals = [self.get_success(self.store.get_event(x)) for x in original_ids]
|
||||||
|
|
||||||
|
# creator bans bad user with redaction flag
|
||||||
|
content = {
|
||||||
|
"reason": "flooding",
|
||||||
|
"org.matrix.msc4293.redact_events": True,
|
||||||
|
}
|
||||||
|
self.helper.change_membership(
|
||||||
|
self.room_id,
|
||||||
|
self.creator,
|
||||||
|
self.bad_user_id,
|
||||||
|
"ban",
|
||||||
|
content,
|
||||||
|
self.creator_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
filter = json.dumps({"types": [EventTypes.Message]})
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
f"rooms/{self.room_id}/messages?filter={filter}&limit=50",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
# messages are not redacted
|
||||||
|
self._check_redactions(originals, channel.json_body["chunk"], False)
|
||||||
|
|
||||||
|
def test_kicking_local_member_with_flag_redacts_their_events(self) -> None:
|
||||||
|
self.helper.join(self.room_id, self.bad_user_id, tok=self.bad_tok)
|
||||||
|
|
||||||
|
# bad user send some messages
|
||||||
|
originals = []
|
||||||
|
for i in range(5):
|
||||||
|
event = {"body": f"bothersome noise {i}", "msgtype": "m.text"}
|
||||||
|
res = self.helper.send_event(
|
||||||
|
self.room_id, "m.room.message", event, tok=self.bad_tok, expect_code=200
|
||||||
|
)
|
||||||
|
originals.append(res["event_id"])
|
||||||
|
|
||||||
|
# grab original events for comparison
|
||||||
|
original_events = [self.get_success(self.store.get_event(x)) for x in originals]
|
||||||
|
|
||||||
|
# creator kicks user with redaction flag set
|
||||||
|
content = {
|
||||||
|
"reason": "flooding",
|
||||||
|
"org.matrix.msc4293.redact_events": True,
|
||||||
|
}
|
||||||
|
self.helper.change_membership(
|
||||||
|
self.room_id,
|
||||||
|
self.creator,
|
||||||
|
self.bad_user_id,
|
||||||
|
"kick",
|
||||||
|
content,
|
||||||
|
self.creator_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
filter = json.dumps({"types": [EventTypes.Message]})
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
f"rooms/{self.room_id}/messages?filter={filter}&limit=50",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
self._check_redactions(
|
||||||
|
original_events,
|
||||||
|
channel.json_body["chunk"],
|
||||||
|
expect_redaction=True,
|
||||||
|
reason="flooding",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_kicking_remote_member_with_flag_redacts_their_events(self) -> None:
|
||||||
|
bad_user = "@remote_bad_user:" + self.OTHER_SERVER_NAME
|
||||||
|
channel = self.make_signed_federation_request(
|
||||||
|
"GET",
|
||||||
|
f"/_matrix/federation/v1/make_join/{self.room_id}/{bad_user}?ver=10",
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, HTTPStatus.OK, channel.json_body)
|
||||||
|
join_result = channel.json_body
|
||||||
|
|
||||||
|
join_event_dict = join_result["event"]
|
||||||
|
self.add_hashes_and_signatures_from_other_server(
|
||||||
|
join_event_dict,
|
||||||
|
RoomVersions.V10,
|
||||||
|
)
|
||||||
|
channel = self.make_signed_federation_request(
|
||||||
|
"PUT",
|
||||||
|
f"/_matrix/federation/v2/send_join/{self.room_id}/x",
|
||||||
|
content=join_event_dict,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, HTTPStatus.OK, channel.json_body)
|
||||||
|
|
||||||
|
# the room should show that the bad user is a member
|
||||||
|
r = self.get_success(
|
||||||
|
self._storage_controllers.state.get_current_state(self.room_id)
|
||||||
|
)
|
||||||
|
self.assertEqual(r[("m.room.member", bad_user)].membership, "join")
|
||||||
|
|
||||||
|
auth_ids = [
|
||||||
|
r[("m.room.create", "")].event_id,
|
||||||
|
r[("m.room.power_levels", "")].event_id,
|
||||||
|
r[("m.room.member", "@remote_bad_user:other.example.com")].event_id,
|
||||||
|
]
|
||||||
|
original_messages = []
|
||||||
|
for i in range(5):
|
||||||
|
remote_message = make_event_from_dict(
|
||||||
|
self.add_hashes_and_signatures_from_other_server(
|
||||||
|
{
|
||||||
|
"room_id": self.room_id,
|
||||||
|
"sender": bad_user,
|
||||||
|
"depth": 1000,
|
||||||
|
"origin_server_ts": 1,
|
||||||
|
"type": "m.room.message",
|
||||||
|
"content": {"body": f"remote bummer{i}"},
|
||||||
|
"auth_events": auth_ids,
|
||||||
|
"prev_events": auth_ids,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
room_version=RoomVersions.V10,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.get_success(
|
||||||
|
self.federation_event_handler.on_receive_pdu(
|
||||||
|
self.OTHER_SERVER_NAME, remote_message
|
||||||
|
)
|
||||||
|
)
|
||||||
|
original_messages.append(remote_message)
|
||||||
|
|
||||||
|
# creator kicks bad user with redaction flag set
|
||||||
|
content = {
|
||||||
|
"reason": "bummer messages",
|
||||||
|
"org.matrix.msc4293.redact_events": True,
|
||||||
|
}
|
||||||
|
res = self.helper.change_membership(
|
||||||
|
self.room_id, self.creator, bad_user, "kick", content, self.creator_tok
|
||||||
|
)
|
||||||
|
ban_event_id = res["event_id"]
|
||||||
|
|
||||||
|
filter = json.dumps({"types": [EventTypes.Message]})
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
f"rooms/{self.room_id}/messages?filter={filter}&limit=50",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
self._check_redactions(
|
||||||
|
original_messages,
|
||||||
|
channel.json_body["chunk"],
|
||||||
|
expect_redaction=True,
|
||||||
|
reason="bummer messages",
|
||||||
|
)
|
||||||
|
|
||||||
|
# any future messages that are soft-failed are also redacted - send messages referencing
|
||||||
|
# dag before ban, they should be soft-failed but also redacted
|
||||||
|
new_original_messages = []
|
||||||
|
for i in range(5):
|
||||||
|
remote_message = make_event_from_dict(
|
||||||
|
self.add_hashes_and_signatures_from_other_server(
|
||||||
|
{
|
||||||
|
"room_id": self.room_id,
|
||||||
|
"sender": bad_user,
|
||||||
|
"depth": 1000,
|
||||||
|
"origin_server_ts": 1,
|
||||||
|
"type": "m.room.message",
|
||||||
|
"content": {"body": f"soft-fail remote bummer{i}"},
|
||||||
|
"auth_events": auth_ids,
|
||||||
|
"prev_events": auth_ids,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
room_version=RoomVersions.V10,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.get_success(
|
||||||
|
self.federation_event_handler.on_receive_pdu(
|
||||||
|
self.OTHER_SERVER_NAME, remote_message
|
||||||
|
)
|
||||||
|
)
|
||||||
|
new_original_messages.append(remote_message)
|
||||||
|
|
||||||
|
# pull them from the db to check because they should be soft-failed and thus not available over
|
||||||
|
# cs-api
|
||||||
|
for message in new_original_messages:
|
||||||
|
original = self.get_success(self.store.get_event(message.event_id))
|
||||||
|
if not original:
|
||||||
|
self.fail("Expected to find remote message in DB")
|
||||||
|
self.assertEqual(original.unsigned["redacted_by"], ban_event_id)
|
||||||
|
|
||||||
|
def test_rejoining_kicked_remote_user_stops_redaction_action(self) -> None:
|
||||||
|
bad_user = "@remote_bad_user:" + self.OTHER_SERVER_NAME
|
||||||
|
channel = self.make_signed_federation_request(
|
||||||
|
"GET",
|
||||||
|
f"/_matrix/federation/v1/make_join/{self.room_id}/{bad_user}?ver=10",
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, HTTPStatus.OK, channel.json_body)
|
||||||
|
join_result = channel.json_body
|
||||||
|
|
||||||
|
join_event_dict = join_result["event"]
|
||||||
|
self.add_hashes_and_signatures_from_other_server(
|
||||||
|
join_event_dict,
|
||||||
|
RoomVersions.V10,
|
||||||
|
)
|
||||||
|
channel = self.make_signed_federation_request(
|
||||||
|
"PUT",
|
||||||
|
f"/_matrix/federation/v2/send_join/{self.room_id}/x",
|
||||||
|
content=join_event_dict,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, HTTPStatus.OK, channel.json_body)
|
||||||
|
|
||||||
|
# the room should show that the bad user is a member
|
||||||
|
r = self.get_success(
|
||||||
|
self._storage_controllers.state.get_current_state(self.room_id)
|
||||||
|
)
|
||||||
|
self.assertEqual(r[("m.room.member", bad_user)].membership, "join")
|
||||||
|
|
||||||
|
auth_ids = [
|
||||||
|
r[("m.room.create", "")].event_id,
|
||||||
|
r[("m.room.power_levels", "")].event_id,
|
||||||
|
r[("m.room.member", "@remote_bad_user:other.example.com")].event_id,
|
||||||
|
]
|
||||||
|
original_messages = []
|
||||||
|
for i in range(5):
|
||||||
|
remote_message = make_event_from_dict(
|
||||||
|
self.add_hashes_and_signatures_from_other_server(
|
||||||
|
{
|
||||||
|
"room_id": self.room_id,
|
||||||
|
"sender": bad_user,
|
||||||
|
"depth": 1000,
|
||||||
|
"origin_server_ts": 1,
|
||||||
|
"type": "m.room.message",
|
||||||
|
"content": {"body": f"annoying messages {i}"},
|
||||||
|
"auth_events": auth_ids,
|
||||||
|
"prev_events": auth_ids,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
room_version=RoomVersions.V10,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.get_success(
|
||||||
|
self.federation_event_handler.on_receive_pdu(
|
||||||
|
self.OTHER_SERVER_NAME, remote_message
|
||||||
|
)
|
||||||
|
)
|
||||||
|
original_messages.append(remote_message)
|
||||||
|
|
||||||
|
# creator kicks bad user with redaction flag set
|
||||||
|
content = {
|
||||||
|
"reason": "this dude sucks",
|
||||||
|
"org.matrix.msc4293.redact_events": True,
|
||||||
|
}
|
||||||
|
self.helper.change_membership(
|
||||||
|
self.room_id, self.creator, bad_user, "kick", content, self.creator_tok
|
||||||
|
)
|
||||||
|
|
||||||
|
filter = json.dumps({"types": [EventTypes.Message]})
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
f"rooms/{self.room_id}/messages?filter={filter}&limit=50",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
self._check_redactions(
|
||||||
|
original_messages,
|
||||||
|
channel.json_body["chunk"],
|
||||||
|
True,
|
||||||
|
reason="this dude sucks",
|
||||||
|
)
|
||||||
|
|
||||||
|
# user re-joins after kick
|
||||||
|
channel = self.make_signed_federation_request(
|
||||||
|
"GET",
|
||||||
|
f"/_matrix/federation/v1/make_join/{self.room_id}/{bad_user}?ver=10",
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, HTTPStatus.OK, channel.json_body)
|
||||||
|
join_result = channel.json_body
|
||||||
|
|
||||||
|
join_event_dict = join_result["event"]
|
||||||
|
self.add_hashes_and_signatures_from_other_server(
|
||||||
|
join_event_dict,
|
||||||
|
RoomVersions.V10,
|
||||||
|
)
|
||||||
|
channel = self.make_signed_federation_request(
|
||||||
|
"PUT",
|
||||||
|
f"/_matrix/federation/v2/send_join/{self.room_id}/x",
|
||||||
|
content=join_event_dict,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, HTTPStatus.OK, channel.json_body)
|
||||||
|
|
||||||
|
# the room should show that the bad user is a member again
|
||||||
|
new_state = self.get_success(
|
||||||
|
self._storage_controllers.state.get_current_state(self.room_id)
|
||||||
|
)
|
||||||
|
self.assertEqual(new_state[("m.room.member", bad_user)].membership, "join")
|
||||||
|
|
||||||
|
new_state = self.get_success(
|
||||||
|
self._storage_controllers.state.get_current_state(self.room_id)
|
||||||
|
)
|
||||||
|
auth_ids = [
|
||||||
|
new_state[("m.room.create", "")].event_id,
|
||||||
|
new_state[("m.room.power_levels", "")].event_id,
|
||||||
|
new_state[("m.room.member", "@remote_bad_user:other.example.com")].event_id,
|
||||||
|
]
|
||||||
|
|
||||||
|
# messages after kick and re-join proceed unredacted
|
||||||
|
new_original_messages = []
|
||||||
|
for i in range(5):
|
||||||
|
remote_message = make_event_from_dict(
|
||||||
|
self.add_hashes_and_signatures_from_other_server(
|
||||||
|
{
|
||||||
|
"room_id": self.room_id,
|
||||||
|
"sender": bad_user,
|
||||||
|
"depth": 1000,
|
||||||
|
"origin_server_ts": 1,
|
||||||
|
"type": "m.room.message",
|
||||||
|
"content": {"body": f"no longer a bummer {i}"},
|
||||||
|
"auth_events": auth_ids,
|
||||||
|
"prev_events": auth_ids,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
room_version=RoomVersions.V10,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.get_success(
|
||||||
|
self.federation_event_handler.on_receive_pdu(
|
||||||
|
self.OTHER_SERVER_NAME, remote_message
|
||||||
|
)
|
||||||
|
)
|
||||||
|
new_original_messages.append(remote_message)
|
||||||
|
|
||||||
|
filter = json.dumps({"types": [EventTypes.Message]})
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
f"rooms/{self.room_id}/messages?filter={filter}&limit=50",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
self._check_redactions(new_original_messages, channel.json_body["chunk"], False)
|
||||||
|
|
||||||
|
def test_redaction_flag_ignored_for_user_if_kicker_lacks_redaction_power(
|
||||||
|
self,
|
||||||
|
) -> None:
|
||||||
|
# change power levels so creator can kick but not redact
|
||||||
|
self.helper.send_state(
|
||||||
|
self.room_id,
|
||||||
|
"m.room.power_levels",
|
||||||
|
{"events_default": 0, "redact": 100, "users": {self.creator: 75}},
|
||||||
|
tok=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.helper.join(self.room_id, self.bad_user_id, tok=self.bad_tok)
|
||||||
|
|
||||||
|
# bad user send some messages
|
||||||
|
original_ids = []
|
||||||
|
for i in range(15):
|
||||||
|
event = {"body": f"being a menace {i}", "msgtype": "m.text"}
|
||||||
|
res = self.helper.send_event(
|
||||||
|
self.room_id, "m.room.message", event, tok=self.bad_tok, expect_code=200
|
||||||
|
)
|
||||||
|
original_ids.append(res["event_id"])
|
||||||
|
|
||||||
|
# grab original events before ban
|
||||||
|
originals = [self.get_success(self.store.get_event(x)) for x in original_ids]
|
||||||
|
|
||||||
|
# creator kicks bad user with redaction flag
|
||||||
|
content = {
|
||||||
|
"reason": "flooding",
|
||||||
|
"org.matrix.msc4293.redact_events": True,
|
||||||
|
}
|
||||||
|
self.helper.change_membership(
|
||||||
|
self.room_id,
|
||||||
|
self.creator,
|
||||||
|
self.bad_user_id,
|
||||||
|
"kick",
|
||||||
|
content,
|
||||||
|
self.creator_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
filter = json.dumps({"types": [EventTypes.Message]})
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
f"rooms/{self.room_id}/messages?filter={filter}&limit=50",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
# messages are not redacted
|
||||||
|
self._check_redactions(originals, channel.json_body["chunk"], False)
|
||||||
|
|
||||||
|
def test_MSC4293_flag_ignored_in_other_membership_events(self) -> None:
|
||||||
|
self.helper.join(self.room_id, self.bad_user_id, tok=self.bad_tok)
|
||||||
|
|
||||||
|
# bad user send some messages
|
||||||
|
original_ids = []
|
||||||
|
for i in range(15):
|
||||||
|
event = {"body": f"being a menace {i}", "msgtype": "m.text"}
|
||||||
|
res = self.helper.send_event(
|
||||||
|
self.room_id, "m.room.message", event, tok=self.bad_tok, expect_code=200
|
||||||
|
)
|
||||||
|
original_ids.append(res["event_id"])
|
||||||
|
|
||||||
|
# grab original events before ban
|
||||||
|
originals = [self.get_success(self.store.get_event(x)) for x in original_ids]
|
||||||
|
|
||||||
|
# bad user leaves on their own with flag
|
||||||
|
content = {
|
||||||
|
"org.matrix.msc4293.redact_events": True,
|
||||||
|
}
|
||||||
|
self.helper.change_membership(
|
||||||
|
self.room_id,
|
||||||
|
self.bad_user_id,
|
||||||
|
self.bad_user_id,
|
||||||
|
"leave",
|
||||||
|
content,
|
||||||
|
self.bad_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
# their messages are not redacted
|
||||||
|
filter = json.dumps({"types": [EventTypes.Message]})
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
f"rooms/{self.room_id}/messages?filter={filter}&limit=50",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
self._check_redactions(originals, channel.json_body["chunk"], False)
|
||||||
|
|
||||||
|
# bad user is invited with flag in invite event
|
||||||
|
content = {
|
||||||
|
"org.matrix.msc4293.redact_events": True,
|
||||||
|
}
|
||||||
|
self.helper.change_membership(
|
||||||
|
self.room_id,
|
||||||
|
self.creator,
|
||||||
|
self.bad_user_id,
|
||||||
|
"invite",
|
||||||
|
content,
|
||||||
|
self.creator_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
# their messages are still not redacted
|
||||||
|
filter = json.dumps({"types": [EventTypes.Message]})
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
f"rooms/{self.room_id}/messages?filter={filter}&limit=50",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
self._check_redactions(originals, channel.json_body["chunk"], False)
|
||||||
|
|
||||||
|
# bad user joins with flag in invite event
|
||||||
|
content = {
|
||||||
|
"org.matrix.msc4293.redact_events": True,
|
||||||
|
}
|
||||||
|
self.helper.change_membership(
|
||||||
|
self.room_id,
|
||||||
|
self.bad_user_id,
|
||||||
|
self.bad_user_id,
|
||||||
|
"join",
|
||||||
|
content,
|
||||||
|
self.bad_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
# and still their messages are not redacted
|
||||||
|
filter = json.dumps({"types": [EventTypes.Message]})
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
f"rooms/{self.room_id}/messages?filter={filter}&limit=50",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
self._check_redactions(originals, channel.json_body["chunk"], False)
|
||||||
|
|
||||||
|
def test_MSC4293_redaction_applied_via_kick_api(self) -> None:
|
||||||
|
"""
|
||||||
|
Test that MSC4239 field passed through and applied when using /kick
|
||||||
|
"""
|
||||||
|
self.helper.join(self.room_id, self.bad_user_id, tok=self.bad_tok)
|
||||||
|
|
||||||
|
# bad user send some messages
|
||||||
|
original_ids = []
|
||||||
|
for i in range(15):
|
||||||
|
event = {"body": f"being a menace {i}", "msgtype": "m.text"}
|
||||||
|
res = self.helper.send_event(
|
||||||
|
self.room_id, "m.room.message", event, tok=self.bad_tok, expect_code=200
|
||||||
|
)
|
||||||
|
original_ids.append(res["event_id"])
|
||||||
|
|
||||||
|
# grab original events before kick
|
||||||
|
originals = [self.get_success(self.store.get_event(x)) for x in original_ids]
|
||||||
|
|
||||||
|
channel = self.make_request(
|
||||||
|
"POST",
|
||||||
|
f"/_matrix/client/v3/rooms/{self.room_id}/kick",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
content={
|
||||||
|
"reason": "being annoying",
|
||||||
|
"org.matrix.msc4293.redact_events": True,
|
||||||
|
"user_id": self.bad_user_id,
|
||||||
|
},
|
||||||
|
shorthand=False,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
|
||||||
|
filter = json.dumps({"types": [EventTypes.Message]})
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
f"rooms/{self.room_id}/messages?filter={filter}&limit=50",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
self._check_redactions(
|
||||||
|
originals,
|
||||||
|
channel.json_body["chunk"],
|
||||||
|
expect_redaction=True,
|
||||||
|
reason="being annoying",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_MSC4293_redaction_applied_via_ban_api(self) -> None:
|
||||||
|
"""
|
||||||
|
Test that MSC4239 field passed through and applied when using /ban
|
||||||
|
"""
|
||||||
|
self.helper.join(self.room_id, self.bad_user_id, tok=self.bad_tok)
|
||||||
|
|
||||||
|
# bad user send some messages
|
||||||
|
original_ids = []
|
||||||
|
for i in range(15):
|
||||||
|
event = {"body": f"being a menace {i}", "msgtype": "m.text"}
|
||||||
|
res = self.helper.send_event(
|
||||||
|
self.room_id, "m.room.message", event, tok=self.bad_tok, expect_code=200
|
||||||
|
)
|
||||||
|
original_ids.append(res["event_id"])
|
||||||
|
|
||||||
|
# grab original events before ban
|
||||||
|
originals = [self.get_success(self.store.get_event(x)) for x in original_ids]
|
||||||
|
|
||||||
|
channel = self.make_request(
|
||||||
|
"POST",
|
||||||
|
f"/_matrix/client/v3/rooms/{self.room_id}/ban",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
content={
|
||||||
|
"reason": "being disruptive",
|
||||||
|
"org.matrix.msc4293.redact_events": True,
|
||||||
|
"user_id": self.bad_user_id,
|
||||||
|
},
|
||||||
|
shorthand=False,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
|
||||||
|
filter = json.dumps({"types": [EventTypes.Message]})
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
f"rooms/{self.room_id}/messages?filter={filter}&limit=50",
|
||||||
|
access_token=self.creator_tok,
|
||||||
|
)
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
self._check_redactions(
|
||||||
|
originals,
|
||||||
|
channel.json_body["chunk"],
|
||||||
|
expect_redaction=True,
|
||||||
|
reason="being disruptive",
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user