mirror of
https://github.com/element-hq/synapse
synced 2024-09-17 20:05:10 +00:00
Merge branch 'madlittlemods/11850-migrate-to-opentelemetry' into madlittlemods/13356-messages-investigation-scratch-v1
This commit is contained in:
commit
c3f3e59cca
28 changed files with 213 additions and 176 deletions
1
changelog.d/13230.doc
Normal file
1
changelog.d/13230.doc
Normal file
|
@ -0,0 +1 @@
|
|||
Add steps describing how to elevate an existing user to administrator by manipulating the database.
|
1
changelog.d/13368.misc
Normal file
1
changelog.d/13368.misc
Normal file
|
@ -0,0 +1 @@
|
|||
Instrument `/messages` for understandable traces in Jaeger.
|
1
changelog.d/13372.docker
Normal file
1
changelog.d/13372.docker
Normal file
|
@ -0,0 +1 @@
|
|||
Make docker images build on armv7 by installing cryptography dependencies in the "requirements" stage. Contributed by Jasper Spaans.
|
1
changelog.d/13374.bugfix
Normal file
1
changelog.d/13374.bugfix
Normal file
|
@ -0,0 +1 @@
|
|||
Fix a bug introduced in Synapse 0.24.0 that would respond with the wrong error status code to `/joined_members` requests when the requester is not a current member of the room. Contributed by @andrewdoh.
|
1
changelog.d/13428.feature
Normal file
1
changelog.d/13428.feature
Normal file
|
@ -0,0 +1 @@
|
|||
Add a module API method to translate a room alias into a room ID.
|
1
changelog.d/13437.doc
Normal file
1
changelog.d/13437.doc
Normal file
|
@ -0,0 +1 @@
|
|||
Fix wrong headline for `url_preview_accept_language` in documentation.
|
1
changelog.d/13438.doc
Normal file
1
changelog.d/13438.doc
Normal file
|
@ -0,0 +1 @@
|
|||
Remove redundant 'Contents' section from the Configuration Manual. Contributed by @dklimpel.
|
1
changelog.d/13439.misc
Normal file
1
changelog.d/13439.misc
Normal file
|
@ -0,0 +1 @@
|
|||
Add some tracing to give more insight into local room joins.
|
1
changelog.d/13442.misc
Normal file
1
changelog.d/13442.misc
Normal file
|
@ -0,0 +1 @@
|
|||
Rename class `RateLimitConfig` to `RatelimitSettings` and `FederationRateLimitConfig` to `FederationRatelimitSettings`.
|
1
changelog.d/13443.doc
Normal file
1
changelog.d/13443.doc
Normal file
|
@ -0,0 +1 @@
|
|||
Update documentation for config setting `macaroon_secret_key`.
|
|
@ -40,7 +40,8 @@ FROM docker.io/python:${PYTHON_VERSION}-slim as requirements
|
|||
RUN \
|
||||
--mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||||
apt-get update -qq && apt-get install -yqq git \
|
||||
apt-get update -qq && apt-get install -yqq \
|
||||
build-essential cargo git libffi-dev libssl-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# We install poetry in its own build stage to avoid its dependencies conflicting with
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
# OpenTracing
|
||||
# Tracing
|
||||
|
||||
## Background
|
||||
|
||||
OpenTracing is a semi-standard being adopted by a number of distributed
|
||||
tracing platforms. It is a common api for facilitating vendor-agnostic
|
||||
tracing instrumentation. That is, we can use the OpenTracing api and
|
||||
select one of a number of tracer implementations to do the heavy lifting
|
||||
in the background. Our current selected implementation is Jaeger.
|
||||
OpenTelemetry is a semi-standard being adopted by a number of distributed
|
||||
tracing platforms. It is a common API for facilitating vendor-agnostic
|
||||
tracing instrumentation.
|
||||
|
||||
OpenTracing is a tool which gives an insight into the causal
|
||||
Tracing is a tool which gives an insight into the causal
|
||||
relationship of work done in and between servers. The servers each track
|
||||
events and report them to a centralised server - in Synapse's case:
|
||||
Jaeger. The basic unit used to represent events is the span. The span
|
||||
|
@ -22,7 +20,7 @@ finish.
|
|||
Since this is undertaken in a distributed environment a request to
|
||||
another server, such as an RPC or a simple GET, can be considered a span
|
||||
(a unit or work) for the local server. This causal link is what
|
||||
OpenTracing aims to capture and visualise. In order to do this metadata
|
||||
tracing aims to capture and visualise. In order to do this metadata
|
||||
about the local server's span, i.e the 'span context', needs to be
|
||||
included with the request to the remote.
|
||||
|
||||
|
@ -30,15 +28,18 @@ It is up to the remote server to decide what it does with the spans it
|
|||
creates. This is called the sampling policy and it can be configured
|
||||
through Jaeger's settings.
|
||||
|
||||
For OpenTracing concepts see
|
||||
<https://opentracing.io/docs/overview/what-is-tracing/>.
|
||||
For OpenTelemetry concepts, see
|
||||
<https://opentelemetry.io/docs/concepts/>.
|
||||
|
||||
For more information about Jaeger's implementation see
|
||||
For more information about the Python implementation of OpenTelemetry we're using, see
|
||||
<https://opentelemetry.io/docs/instrumentation/python/>
|
||||
|
||||
For more information about Jaeger, see
|
||||
<https://www.jaegertracing.io/docs/>
|
||||
|
||||
## Setting up OpenTracing
|
||||
## Setting up tracing
|
||||
|
||||
To receive OpenTracing spans, start up a Jaeger server. This can be done
|
||||
To receive tracing spans, start up a Jaeger server. This can be done
|
||||
using docker like so:
|
||||
|
||||
```sh
|
||||
|
@ -54,15 +55,15 @@ docker run -d --name jaeger \
|
|||
Latest documentation is probably at
|
||||
https://www.jaegertracing.io/docs/latest/getting-started.
|
||||
|
||||
## Enable OpenTracing in Synapse
|
||||
## Enable tracing in Synapse
|
||||
|
||||
OpenTracing is not enabled by default. It must be enabled in the
|
||||
homeserver config by adding the `opentracing` option to your config file. You can find
|
||||
documentation about how to do this in the [config manual under the header 'Opentracing'](usage/configuration/config_documentation.md#opentracing).
|
||||
See below for an example Opentracing configuration:
|
||||
Tracing is not enabled by default. It must be enabled in the
|
||||
homeserver config by adding the `tracing` option to your config file. You can find
|
||||
documentation about how to do this in the [config manual under the header 'Tracing'](usage/configuration/config_documentation.md#tracing).
|
||||
See below for an example tracing configuration:
|
||||
|
||||
```yaml
|
||||
opentracing:
|
||||
tracing:
|
||||
enabled: true
|
||||
homeserver_whitelist:
|
||||
- "mytrustedhomeserver.org"
|
||||
|
@ -86,9 +87,4 @@ to two problems, namely:
|
|||
- Sending servers can attach arbitrary data to spans, known as
|
||||
'baggage'. For safety this has been disabled in Synapse but that
|
||||
doesn't prevent another server sending you baggage which will be
|
||||
logged to OpenTracing's logs.
|
||||
|
||||
## Configuring Jaeger
|
||||
|
||||
Sampling strategies can be set as in this document:
|
||||
<https://www.jaegertracing.io/docs/latest/sampling/>.
|
||||
logged in the trace.
|
||||
|
|
|
@ -5,8 +5,9 @@
|
|||
Many of the API calls in the admin api will require an `access_token` for a
|
||||
server admin. (Note that a server admin is distinct from a room admin.)
|
||||
|
||||
A user can be marked as a server admin by updating the database directly, e.g.:
|
||||
An existing user can be marked as a server admin by updating the database directly.
|
||||
|
||||
Check your [database settings](config_documentation.md#database) in the configuration file, connect to the correct database using either `psql [database name]` (if using PostgreSQL) or `sqlite3 path/to/your/database.db` (if using SQLite) and elevate the user `@foo:bar.com` to administrator.
|
||||
```sql
|
||||
UPDATE users SET admin = 1 WHERE name = '@foo:bar.com';
|
||||
```
|
||||
|
|
|
@ -72,48 +72,6 @@ apply if you want your config file to be read properly. A few helpful things to
|
|||
In addition, each setting has an example of its usage, with the proper indentation
|
||||
shown.
|
||||
|
||||
## Contents
|
||||
[Modules](#modules)
|
||||
|
||||
[Server](#server)
|
||||
|
||||
[Homeserver Blocking](#homeserver-blocking)
|
||||
|
||||
[TLS](#tls)
|
||||
|
||||
[Federation](#federation)
|
||||
|
||||
[Caching](#caching)
|
||||
|
||||
[Database](#database)
|
||||
|
||||
[Logging](#logging)
|
||||
|
||||
[Ratelimiting](#ratelimiting)
|
||||
|
||||
[Media Store](#media-store)
|
||||
|
||||
[Captcha](#captcha)
|
||||
|
||||
[TURN](#turn)
|
||||
|
||||
[Registration](#registration)
|
||||
|
||||
[API Configuration](#api-configuration)
|
||||
|
||||
[Signing Keys](#signing-keys)
|
||||
|
||||
[Single Sign On Integration](#single-sign-on-integration)
|
||||
|
||||
[Push](#push)
|
||||
|
||||
[Rooms](#rooms)
|
||||
|
||||
[Tracing](#tracing)
|
||||
|
||||
[Workers](#workers)
|
||||
|
||||
[Background Updates](#background-updates)
|
||||
|
||||
## Modules
|
||||
|
||||
|
@ -1859,7 +1817,7 @@ Example configuration:
|
|||
max_spider_size: 8M
|
||||
```
|
||||
---
|
||||
### `url_preview_language`
|
||||
### `url_preview_accept_language`
|
||||
|
||||
A list of values for the Accept-Language HTTP header used when
|
||||
downloading webpages during URL preview generation. This allows
|
||||
|
@ -2538,9 +2496,13 @@ track_appservice_user_ips: true
|
|||
---
|
||||
### `macaroon_secret_key`
|
||||
|
||||
A secret which is used to sign access tokens. If none is specified,
|
||||
the `registration_shared_secret` is used, if one is given; otherwise,
|
||||
a secret key is derived from the signing key.
|
||||
A secret which is used to sign
|
||||
- access token for guest users,
|
||||
- short-term login token used during SSO logins (OIDC or SAML2) and
|
||||
- token used for unsubscribing from email notifications.
|
||||
|
||||
If none is specified, the `registration_shared_secret` is used, if one is given;
|
||||
otherwise, a secret key is derived from the signing key.
|
||||
|
||||
Example configuration:
|
||||
```yaml
|
||||
|
@ -3578,7 +3540,7 @@ OpenTelemetry.
|
|||
Sub-options include:
|
||||
* `enabled`: whether tracing is enabled. Set to true to enable. Disabled by default.
|
||||
* `homeserver_whitelist`: The list of homeservers we wish to send and receive span contexts and span baggage.
|
||||
See [here](../../tracing.md) for more.
|
||||
See [here](../../tracing.md#homeserver-whitelisting) for more.
|
||||
This is a list of regexes which are matched against the `server_name` of the homeserver.
|
||||
By default, it is empty, so no servers are matched.
|
||||
* `sample_rate`: The probability that a given span and subsequent child spans in the trace will be
|
||||
|
|
61
poetry.lock
generated
61
poetry.lock
generated
|
@ -1267,22 +1267,17 @@ telegram = ["requests"]
|
|||
|
||||
[[package]]
|
||||
name = "treq"
|
||||
version = "22.2.0"
|
||||
description = "High-level Twisted HTTP Client API"
|
||||
version = "15.1.0"
|
||||
description = "A requests-like API built on top of twisted.web's Agent"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
python-versions = "*"
|
||||
|
||||
[package.dependencies]
|
||||
attrs = "*"
|
||||
hyperlink = ">=21.0.0"
|
||||
incremental = "*"
|
||||
pyOpenSSL = {version = ">=0.15.1", markers = "python_version > \"3.0\""}
|
||||
requests = ">=2.1.0"
|
||||
Twisted = {version = ">=18.7.0", extras = ["tls"]}
|
||||
|
||||
[package.extras]
|
||||
dev = ["pep8", "pyflakes", "httpbin (==0.5.0)"]
|
||||
docs = ["sphinx (>=1.4.8)"]
|
||||
service_identity = ">=14.0.0"
|
||||
Twisted = {version = ">=15.5.0", markers = "python_version > \"3.0\""}
|
||||
|
||||
[[package]]
|
||||
name = "twine"
|
||||
|
@ -1305,41 +1300,46 @@ tqdm = ">=4.14"
|
|||
urllib3 = ">=1.26.0"
|
||||
|
||||
[[package]]
|
||||
name = "twisted"
|
||||
version = "22.4.0"
|
||||
name = "Twisted"
|
||||
version = "22.4.0.post0"
|
||||
description = "An asynchronous networking framework written in Python"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6.7"
|
||||
python-versions = ">=3.7.1"
|
||||
develop = false
|
||||
|
||||
[package.dependencies]
|
||||
attrs = ">=19.2.0"
|
||||
Automat = ">=0.8.0"
|
||||
constantly = ">=15.1"
|
||||
hyperlink = ">=17.1.1"
|
||||
idna = {version = ">=2.4", optional = true, markers = "extra == \"tls\""}
|
||||
incremental = ">=21.3.0"
|
||||
pyopenssl = {version = ">=16.0.0", optional = true, markers = "extra == \"tls\""}
|
||||
service-identity = {version = ">=18.1.0", optional = true, markers = "extra == \"tls\""}
|
||||
twisted-iocpsupport = {version = ">=1.0.2,<2", markers = "platform_system == \"Windows\""}
|
||||
typing-extensions = ">=3.6.5"
|
||||
"zope.interface" = ">=4.4.2"
|
||||
|
||||
[package.extras]
|
||||
all_non_platform = ["cython-test-exception-raiser (>=1.0.2,<2)", "PyHamcrest (>=1.9.0)", "pyopenssl (>=16.0.0)", "service-identity (>=18.1.0)", "idna (>=2.4)", "pyasn1", "cryptography (>=2.6)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "pyserial (>=3.0)", "h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)", "pywin32 (!=226)", "contextvars (>=2.4,<3)"]
|
||||
all_non_platform = ["cython-test-exception-raiser (>=1.0.2,<2)", "PyHamcrest (>=1.9.0)", "pyopenssl (>=21.0.0)", "service-identity (>=18.1.0)", "idna (>=2.4)", "pyasn1", "cryptography (>=2.6)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "pyserial (>=3.0)", "h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)", "pywin32 (!=226)", "contextvars (>=2.4,<3)"]
|
||||
conch = ["pyasn1", "cryptography (>=2.6)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)"]
|
||||
conch_nacl = ["pyasn1", "cryptography (>=2.6)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "pynacl"]
|
||||
contextvars = ["contextvars (>=2.4,<3)"]
|
||||
dev = ["towncrier (>=19.2,<20.0)", "sphinx-rtd-theme (>=0.5,<1.0)", "readthedocs-sphinx-ext (>=2.1,<3.0)", "sphinx (>=4.1.2,<6)", "pyflakes (>=2.2,<3.0)", "twistedchecker (>=0.7,<1.0)", "coverage (>=6b1,<7)", "python-subunit (>=1.4,<2.0)", "pydoctor (>=21.9.0,<21.10.0)"]
|
||||
dev_release = ["towncrier (>=19.2,<20.0)", "sphinx-rtd-theme (>=0.5,<1.0)", "readthedocs-sphinx-ext (>=2.1,<3.0)", "sphinx (>=4.1.2,<6)", "pydoctor (>=21.9.0,<21.10.0)"]
|
||||
dev = ["towncrier (>=19.2,<20.0)", "pydoctor (>=22.7.0,<22.8.0)", "sphinx-rtd-theme (>=0.5,<1.0)", "readthedocs-sphinx-ext (>=2.1,<3.0)", "sphinx (>=4.1.2,<6)", "pyflakes (>=2.2,<3.0)", "twistedchecker (>=0.7,<1.0)", "coverage (>=6b1,<7)", "python-subunit (>=1.4,<2.0)"]
|
||||
dev_release = ["towncrier (>=19.2,<20.0)", "pydoctor (>=22.7.0,<22.8.0)", "sphinx-rtd-theme (>=0.5,<1.0)", "readthedocs-sphinx-ext (>=2.1,<3.0)", "sphinx (>=4.1.2,<6)"]
|
||||
gtk_platform = ["pygobject", "cython-test-exception-raiser (>=1.0.2,<2)", "PyHamcrest (>=1.9.0)", "pyopenssl (>=21.0.0)", "service-identity (>=18.1.0)", "idna (>=2.4)", "pyasn1", "cryptography (>=2.6)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "pyserial (>=3.0)", "h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)", "pywin32 (!=226)", "contextvars (>=2.4,<3)"]
|
||||
http2 = ["h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)"]
|
||||
macos_platform = ["pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "cython-test-exception-raiser (>=1.0.2,<2)", "PyHamcrest (>=1.9.0)", "pyopenssl (>=16.0.0)", "service-identity (>=18.1.0)", "idna (>=2.4)", "pyasn1", "cryptography (>=2.6)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "pyserial (>=3.0)", "h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)", "pywin32 (!=226)", "contextvars (>=2.4,<3)"]
|
||||
mypy = ["mypy (==0.930)", "mypy-zope (==0.3.4)", "types-setuptools", "types-pyopenssl", "towncrier (>=19.2,<20.0)", "sphinx-rtd-theme (>=0.5,<1.0)", "readthedocs-sphinx-ext (>=2.1,<3.0)", "sphinx (>=4.1.2,<6)", "pyflakes (>=2.2,<3.0)", "twistedchecker (>=0.7,<1.0)", "coverage (>=6b1,<7)", "cython-test-exception-raiser (>=1.0.2,<2)", "PyHamcrest (>=1.9.0)", "pyopenssl (>=16.0.0)", "service-identity (>=18.1.0)", "idna (>=2.4)", "pyasn1", "cryptography (>=2.6)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "pyserial (>=3.0)", "h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)", "pynacl", "pywin32 (!=226)", "python-subunit (>=1.4,<2.0)", "contextvars (>=2.4,<3)", "pydoctor (>=21.9.0,<21.10.0)"]
|
||||
osx_platform = ["pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "cython-test-exception-raiser (>=1.0.2,<2)", "PyHamcrest (>=1.9.0)", "pyopenssl (>=16.0.0)", "service-identity (>=18.1.0)", "idna (>=2.4)", "pyasn1", "cryptography (>=2.6)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "pyserial (>=3.0)", "h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)", "pywin32 (!=226)", "contextvars (>=2.4,<3)"]
|
||||
macos_platform = ["pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "cython-test-exception-raiser (>=1.0.2,<2)", "PyHamcrest (>=1.9.0)", "pyopenssl (>=21.0.0)", "service-identity (>=18.1.0)", "idna (>=2.4)", "pyasn1", "cryptography (>=2.6)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "pyserial (>=3.0)", "h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)", "pywin32 (!=226)", "contextvars (>=2.4,<3)"]
|
||||
mypy = ["mypy (==0.930)", "mypy-zope (==0.3.4)", "types-setuptools", "types-pyopenssl", "towncrier (>=19.2,<20.0)", "pydoctor (>=22.7.0,<22.8.0)", "sphinx-rtd-theme (>=0.5,<1.0)", "readthedocs-sphinx-ext (>=2.1,<3.0)", "sphinx (>=4.1.2,<6)", "pyflakes (>=2.2,<3.0)", "twistedchecker (>=0.7,<1.0)", "coverage (>=6b1,<7)", "cython-test-exception-raiser (>=1.0.2,<2)", "PyHamcrest (>=1.9.0)", "pyopenssl (>=21.0.0)", "service-identity (>=18.1.0)", "idna (>=2.4)", "pyasn1", "cryptography (>=2.6)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "pyserial (>=3.0)", "h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)", "pynacl", "pywin32 (!=226)", "python-subunit (>=1.4,<2.0)", "contextvars (>=2.4,<3)"]
|
||||
osx_platform = ["pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "cython-test-exception-raiser (>=1.0.2,<2)", "PyHamcrest (>=1.9.0)", "pyopenssl (>=21.0.0)", "service-identity (>=18.1.0)", "idna (>=2.4)", "pyasn1", "cryptography (>=2.6)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "pyserial (>=3.0)", "h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)", "pywin32 (!=226)", "contextvars (>=2.4,<3)"]
|
||||
serial = ["pyserial (>=3.0)", "pywin32 (!=226)"]
|
||||
test = ["cython-test-exception-raiser (>=1.0.2,<2)", "PyHamcrest (>=1.9.0)"]
|
||||
tls = ["pyopenssl (>=16.0.0)", "service-identity (>=18.1.0)", "idna (>=2.4)"]
|
||||
windows_platform = ["pywin32 (!=226)", "cython-test-exception-raiser (>=1.0.2,<2)", "PyHamcrest (>=1.9.0)", "pyopenssl (>=16.0.0)", "service-identity (>=18.1.0)", "idna (>=2.4)", "pyasn1", "cryptography (>=2.6)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "pyserial (>=3.0)", "h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)", "pywin32 (!=226)", "contextvars (>=2.4,<3)"]
|
||||
tls = ["pyopenssl (>=21.0.0)", "service-identity (>=18.1.0)", "idna (>=2.4)"]
|
||||
windows_platform = ["pywin32 (!=226)", "cython-test-exception-raiser (>=1.0.2,<2)", "PyHamcrest (>=1.9.0)", "pyopenssl (>=21.0.0)", "service-identity (>=18.1.0)", "idna (>=2.4)", "pyasn1", "cryptography (>=2.6)", "appdirs (>=1.4.0)", "bcrypt (>=3.0.0)", "pyserial (>=3.0)", "h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)", "pywin32 (!=226)", "contextvars (>=2.4,<3)"]
|
||||
|
||||
[package.source]
|
||||
type = "git"
|
||||
url = "https://github.com/twisted/twisted.git"
|
||||
reference = "trunk"
|
||||
resolved_reference = "ff2ea6181f7ca4887adbaf4158b2fe0891e17ef9"
|
||||
|
||||
[[package]]
|
||||
name = "twisted-iocpsupport"
|
||||
|
@ -1615,7 +1615,7 @@ url_preview = ["lxml"]
|
|||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.7.1"
|
||||
content-hash = "06a9f9259d4aa587a48242adf571bbd1132eda149226c1d2819a8b7a05c7ce5c"
|
||||
content-hash = "c2cfbb348a49e088c404148c1b682fc5af5abb6278cf4479c6a51fff1656328c"
|
||||
|
||||
[metadata.files]
|
||||
attrs = [
|
||||
|
@ -2642,17 +2642,14 @@ tqdm = [
|
|||
{file = "tqdm-4.63.0.tar.gz", hash = "sha256:1d9835ede8e394bb8c9dcbffbca02d717217113adc679236873eeaac5bc0b3cd"},
|
||||
]
|
||||
treq = [
|
||||
{file = "treq-22.2.0-py3-none-any.whl", hash = "sha256:27d95b07c5c14be3e7b280416139b036087617ad5595be913b1f9b3ce981b9b2"},
|
||||
{file = "treq-22.2.0.tar.gz", hash = "sha256:df757e3f141fc782ede076a604521194ffcb40fa2645cf48e5a37060307f52ec"},
|
||||
{file = "treq-15.1.0-py2.py3-none-any.whl", hash = "sha256:1ad1ba89ddc62ae877084b290bd327755b13f6e7bc7076dc4d8e2efb701bfd63"},
|
||||
{file = "treq-15.1.0.tar.gz", hash = "sha256:425a47d5d52a993d51211028fb6ade252e5fbea094e878bb4b644096a7322de8"},
|
||||
]
|
||||
twine = [
|
||||
{file = "twine-3.8.0-py3-none-any.whl", hash = "sha256:d0550fca9dc19f3d5e8eadfce0c227294df0a2a951251a4385797c8a6198b7c8"},
|
||||
{file = "twine-3.8.0.tar.gz", hash = "sha256:8efa52658e0ae770686a13b675569328f1fba9837e5de1867bfe5f46a9aefe19"},
|
||||
]
|
||||
twisted = [
|
||||
{file = "Twisted-22.4.0-py3-none-any.whl", hash = "sha256:f9f7a91f94932477a9fc3b169d57f54f96c6e74a23d78d9ce54039a7f48928a2"},
|
||||
{file = "Twisted-22.4.0.tar.gz", hash = "sha256:a047990f57dfae1e0bd2b7df2526d4f16dcdc843774dc108b78c52f2a5f13680"},
|
||||
]
|
||||
Twisted = []
|
||||
twisted-iocpsupport = [
|
||||
{file = "twisted-iocpsupport-1.0.2.tar.gz", hash = "sha256:72068b206ee809c9c596b57b5287259ea41ddb4774d86725b19f35bf56aa32a9"},
|
||||
{file = "twisted_iocpsupport-1.0.2-cp310-cp310-win32.whl", hash = "sha256:985c06a33f5c0dae92c71a036d1ea63872ee86a21dd9b01e1f287486f15524b4"},
|
||||
|
|
|
@ -119,7 +119,6 @@ signedjson = "^1.1.0"
|
|||
service-identity = ">=18.1.0"
|
||||
# Twisted 18.9 introduces some logger improvements that the structured
|
||||
# logger utilises
|
||||
Twisted = {extras = ["tls"], version = ">=18.9.0"}
|
||||
treq = ">=15.1"
|
||||
# Twisted has required pyopenssl 16.0 since about Twisted 16.6.
|
||||
pyOpenSSL = ">=16.0.0"
|
||||
|
@ -183,6 +182,7 @@ idna = { version = ">=2.5", optional = true }
|
|||
opentelemetry-api = {version = "^1.11.1", optional = true}
|
||||
opentelemetry-sdk = {version = "^1.11.1", optional = true}
|
||||
opentelemetry-exporter-jaeger = {version = "^1.11.1", optional = true}
|
||||
twisted = {git = "https://github.com/twisted/twisted.git", rev = "trunk"}
|
||||
|
||||
[tool.poetry.extras]
|
||||
# NB: Packages that should be part of `pip install matrix-synapse[all]` need to be specified
|
||||
|
|
|
@ -17,7 +17,7 @@ from collections import OrderedDict
|
|||
from typing import Hashable, Optional, Tuple
|
||||
|
||||
from synapse.api.errors import LimitExceededError
|
||||
from synapse.config.ratelimiting import RateLimitConfig
|
||||
from synapse.config.ratelimiting import RatelimitSettings
|
||||
from synapse.storage.databases.main import DataStore
|
||||
from synapse.types import Requester
|
||||
from synapse.util import Clock
|
||||
|
@ -314,8 +314,8 @@ class RequestRatelimiter:
|
|||
self,
|
||||
store: DataStore,
|
||||
clock: Clock,
|
||||
rc_message: RateLimitConfig,
|
||||
rc_admin_redaction: Optional[RateLimitConfig],
|
||||
rc_message: RatelimitSettings,
|
||||
rc_admin_redaction: Optional[RatelimitSettings],
|
||||
):
|
||||
self.store = store
|
||||
self.clock = clock
|
||||
|
|
|
@ -21,7 +21,7 @@ from synapse.types import JsonDict
|
|||
from ._base import Config
|
||||
|
||||
|
||||
class RateLimitConfig:
|
||||
class RatelimitSettings:
|
||||
def __init__(
|
||||
self,
|
||||
config: Dict[str, float],
|
||||
|
@ -34,7 +34,7 @@ class RateLimitConfig:
|
|||
|
||||
|
||||
@attr.s(auto_attribs=True)
|
||||
class FederationRateLimitConfig:
|
||||
class FederationRatelimitSettings:
|
||||
window_size: int = 1000
|
||||
sleep_limit: int = 10
|
||||
sleep_delay: int = 500
|
||||
|
@ -50,11 +50,11 @@ class RatelimitConfig(Config):
|
|||
# Load the new-style messages config if it exists. Otherwise fall back
|
||||
# to the old method.
|
||||
if "rc_message" in config:
|
||||
self.rc_message = RateLimitConfig(
|
||||
self.rc_message = RatelimitSettings(
|
||||
config["rc_message"], defaults={"per_second": 0.2, "burst_count": 10.0}
|
||||
)
|
||||
else:
|
||||
self.rc_message = RateLimitConfig(
|
||||
self.rc_message = RatelimitSettings(
|
||||
{
|
||||
"per_second": config.get("rc_messages_per_second", 0.2),
|
||||
"burst_count": config.get("rc_message_burst_count", 10.0),
|
||||
|
@ -64,9 +64,9 @@ class RatelimitConfig(Config):
|
|||
# Load the new-style federation config, if it exists. Otherwise, fall
|
||||
# back to the old method.
|
||||
if "rc_federation" in config:
|
||||
self.rc_federation = FederationRateLimitConfig(**config["rc_federation"])
|
||||
self.rc_federation = FederationRatelimitSettings(**config["rc_federation"])
|
||||
else:
|
||||
self.rc_federation = FederationRateLimitConfig(
|
||||
self.rc_federation = FederationRatelimitSettings(
|
||||
**{
|
||||
k: v
|
||||
for k, v in {
|
||||
|
@ -80,17 +80,17 @@ class RatelimitConfig(Config):
|
|||
}
|
||||
)
|
||||
|
||||
self.rc_registration = RateLimitConfig(config.get("rc_registration", {}))
|
||||
self.rc_registration = RatelimitSettings(config.get("rc_registration", {}))
|
||||
|
||||
self.rc_registration_token_validity = RateLimitConfig(
|
||||
self.rc_registration_token_validity = RatelimitSettings(
|
||||
config.get("rc_registration_token_validity", {}),
|
||||
defaults={"per_second": 0.1, "burst_count": 5},
|
||||
)
|
||||
|
||||
rc_login_config = config.get("rc_login", {})
|
||||
self.rc_login_address = RateLimitConfig(rc_login_config.get("address", {}))
|
||||
self.rc_login_account = RateLimitConfig(rc_login_config.get("account", {}))
|
||||
self.rc_login_failed_attempts = RateLimitConfig(
|
||||
self.rc_login_address = RatelimitSettings(rc_login_config.get("address", {}))
|
||||
self.rc_login_account = RatelimitSettings(rc_login_config.get("account", {}))
|
||||
self.rc_login_failed_attempts = RatelimitSettings(
|
||||
rc_login_config.get("failed_attempts", {})
|
||||
)
|
||||
|
||||
|
@ -101,20 +101,20 @@ class RatelimitConfig(Config):
|
|||
rc_admin_redaction = config.get("rc_admin_redaction")
|
||||
self.rc_admin_redaction = None
|
||||
if rc_admin_redaction:
|
||||
self.rc_admin_redaction = RateLimitConfig(rc_admin_redaction)
|
||||
self.rc_admin_redaction = RatelimitSettings(rc_admin_redaction)
|
||||
|
||||
self.rc_joins_local = RateLimitConfig(
|
||||
self.rc_joins_local = RatelimitSettings(
|
||||
config.get("rc_joins", {}).get("local", {}),
|
||||
defaults={"per_second": 0.1, "burst_count": 10},
|
||||
)
|
||||
self.rc_joins_remote = RateLimitConfig(
|
||||
self.rc_joins_remote = RatelimitSettings(
|
||||
config.get("rc_joins", {}).get("remote", {}),
|
||||
defaults={"per_second": 0.01, "burst_count": 10},
|
||||
)
|
||||
|
||||
# Track the rate of joins to a given room. If there are too many, temporarily
|
||||
# prevent local joins and remote joins via this server.
|
||||
self.rc_joins_per_room = RateLimitConfig(
|
||||
self.rc_joins_per_room = RatelimitSettings(
|
||||
config.get("rc_joins_per_room", {}),
|
||||
defaults={"per_second": 1, "burst_count": 10},
|
||||
)
|
||||
|
@ -124,31 +124,31 @@ class RatelimitConfig(Config):
|
|||
# * For requests received over federation this is keyed by the origin.
|
||||
#
|
||||
# Note that this isn't exposed in the configuration as it is obscure.
|
||||
self.rc_key_requests = RateLimitConfig(
|
||||
self.rc_key_requests = RatelimitSettings(
|
||||
config.get("rc_key_requests", {}),
|
||||
defaults={"per_second": 20, "burst_count": 100},
|
||||
)
|
||||
|
||||
self.rc_3pid_validation = RateLimitConfig(
|
||||
self.rc_3pid_validation = RatelimitSettings(
|
||||
config.get("rc_3pid_validation") or {},
|
||||
defaults={"per_second": 0.003, "burst_count": 5},
|
||||
)
|
||||
|
||||
self.rc_invites_per_room = RateLimitConfig(
|
||||
self.rc_invites_per_room = RatelimitSettings(
|
||||
config.get("rc_invites", {}).get("per_room", {}),
|
||||
defaults={"per_second": 0.3, "burst_count": 10},
|
||||
)
|
||||
self.rc_invites_per_user = RateLimitConfig(
|
||||
self.rc_invites_per_user = RatelimitSettings(
|
||||
config.get("rc_invites", {}).get("per_user", {}),
|
||||
defaults={"per_second": 0.003, "burst_count": 5},
|
||||
)
|
||||
|
||||
self.rc_invites_per_issuer = RateLimitConfig(
|
||||
self.rc_invites_per_issuer = RatelimitSettings(
|
||||
config.get("rc_invites", {}).get("per_issuer", {}),
|
||||
defaults={"per_second": 0.3, "burst_count": 10},
|
||||
)
|
||||
|
||||
self.rc_third_party_invite = RateLimitConfig(
|
||||
self.rc_third_party_invite = RatelimitSettings(
|
||||
config.get("rc_third_party_invite", {}),
|
||||
defaults={
|
||||
"per_second": self.rc_message.per_second,
|
||||
|
|
|
@ -52,6 +52,7 @@ from synapse.events.builder import EventBuilder
|
|||
from synapse.events.snapshot import EventContext
|
||||
from synapse.events.validator import EventValidator
|
||||
from synapse.handlers.directory import DirectoryHandler
|
||||
from synapse.logging import tracing
|
||||
from synapse.logging.context import make_deferred_yieldable, run_in_background
|
||||
from synapse.metrics.background_process_metrics import run_as_background_process
|
||||
from synapse.replication.http.send_event import ReplicationSendEventRestServlet
|
||||
|
@ -324,8 +325,10 @@ class MessageHandler:
|
|||
room_id, user_id, allow_departed_users=True
|
||||
)
|
||||
if membership != Membership.JOIN:
|
||||
raise NotImplementedError(
|
||||
"Getting joined members after leaving is not implemented"
|
||||
raise SynapseError(
|
||||
code=403,
|
||||
errcode=Codes.FORBIDDEN,
|
||||
msg="Getting joined members while not being a current member of the room is forbidden.",
|
||||
)
|
||||
|
||||
users_with_profile = await self.store.get_users_in_room_with_profiles(room_id)
|
||||
|
@ -1372,9 +1375,10 @@ class EventCreationHandler:
|
|||
# and `state_groups` because they have `prev_events` that aren't persisted yet
|
||||
# (historical messages persisted in reverse-chronological order).
|
||||
if not event.internal_metadata.is_historical():
|
||||
await self._bulk_push_rule_evaluator.action_for_event_by_user(
|
||||
event, context
|
||||
)
|
||||
with tracing.start_active_span("calculate_push_actions"):
|
||||
await self._bulk_push_rule_evaluator.action_for_event_by_user(
|
||||
event, context
|
||||
)
|
||||
|
||||
try:
|
||||
# If we're a worker we need to hit out to the master.
|
||||
|
@ -1461,9 +1465,10 @@ class EventCreationHandler:
|
|||
state = await state_entry.get_state(
|
||||
self._storage_controllers.state, StateFilter.all()
|
||||
)
|
||||
joined_hosts = await self.store.get_joined_hosts(
|
||||
event.room_id, state, state_entry
|
||||
)
|
||||
with tracing.start_active_span("get_joined_hosts"):
|
||||
joined_hosts = await self.store.get_joined_hosts(
|
||||
event.room_id, state, state_entry
|
||||
)
|
||||
|
||||
# Note that the expiry times must be larger than the expiry time in
|
||||
# _external_cache_joined_hosts_updates.
|
||||
|
|
|
@ -32,6 +32,7 @@ from synapse.event_auth import get_named_level, get_power_level_event
|
|||
from synapse.events import EventBase
|
||||
from synapse.events.snapshot import EventContext
|
||||
from synapse.handlers.profile import MAX_AVATAR_URL_LEN, MAX_DISPLAYNAME_LEN
|
||||
from synapse.logging import tracing
|
||||
from synapse.module_api import NOT_SPAM
|
||||
from synapse.storage.state import StateFilter
|
||||
from synapse.types import (
|
||||
|
@ -428,14 +429,14 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
|
|||
await self._join_rate_per_room_limiter.ratelimit(
|
||||
requester, key=room_id, update=False
|
||||
)
|
||||
|
||||
result_event = await self.event_creation_handler.handle_new_client_event(
|
||||
requester,
|
||||
event,
|
||||
context,
|
||||
extra_users=[target],
|
||||
ratelimit=ratelimit,
|
||||
)
|
||||
with tracing.start_active_span("handle_new_client_event"):
|
||||
result_event = await self.event_creation_handler.handle_new_client_event(
|
||||
requester,
|
||||
event,
|
||||
context,
|
||||
extra_users=[target],
|
||||
ratelimit=ratelimit,
|
||||
)
|
||||
|
||||
if event.membership == Membership.LEAVE:
|
||||
if prev_member_event_id:
|
||||
|
@ -564,25 +565,26 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
|
|||
# by application services), and then by room ID.
|
||||
async with self.member_as_limiter.queue(as_id):
|
||||
async with self.member_linearizer.queue(key):
|
||||
result = await self.update_membership_locked(
|
||||
requester,
|
||||
target,
|
||||
room_id,
|
||||
action,
|
||||
txn_id=txn_id,
|
||||
remote_room_hosts=remote_room_hosts,
|
||||
third_party_signed=third_party_signed,
|
||||
ratelimit=ratelimit,
|
||||
content=content,
|
||||
new_room=new_room,
|
||||
require_consent=require_consent,
|
||||
outlier=outlier,
|
||||
historical=historical,
|
||||
allow_no_prev_events=allow_no_prev_events,
|
||||
prev_event_ids=prev_event_ids,
|
||||
state_event_ids=state_event_ids,
|
||||
depth=depth,
|
||||
)
|
||||
with tracing.start_active_span("update_membership_locked"):
|
||||
result = await self.update_membership_locked(
|
||||
requester,
|
||||
target,
|
||||
room_id,
|
||||
action,
|
||||
txn_id=txn_id,
|
||||
remote_room_hosts=remote_room_hosts,
|
||||
third_party_signed=third_party_signed,
|
||||
ratelimit=ratelimit,
|
||||
content=content,
|
||||
new_room=new_room,
|
||||
require_consent=require_consent,
|
||||
outlier=outlier,
|
||||
historical=historical,
|
||||
allow_no_prev_events=allow_no_prev_events,
|
||||
prev_event_ids=prev_event_ids,
|
||||
state_event_ids=state_event_ids,
|
||||
depth=depth,
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
|
@ -649,6 +651,7 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
|
|||
Returns:
|
||||
A tuple of the new event ID and stream ID.
|
||||
"""
|
||||
|
||||
content_specified = bool(content)
|
||||
if content is None:
|
||||
content = {}
|
||||
|
|
|
@ -330,8 +330,10 @@ class LoggingContext:
|
|||
@classmethod
|
||||
def current_context(cls) -> LoggingContextOrSentinel:
|
||||
"""Get the current logging context from thread local storage
|
||||
|
||||
This exists for backwards compatibility. ``current_context()`` should be
|
||||
called directly.
|
||||
|
||||
Returns:
|
||||
LoggingContext: the current logging context
|
||||
"""
|
||||
|
|
|
@ -1452,6 +1452,30 @@ class ModuleApi:
|
|||
start_timestamp, end_timestamp
|
||||
)
|
||||
|
||||
async def lookup_room_alias(self, room_alias: str) -> Tuple[str, List[str]]:
|
||||
"""
|
||||
Get the room ID associated with a room alias.
|
||||
|
||||
Added in Synapse v1.65.0.
|
||||
|
||||
Args:
|
||||
room_alias: The alias to look up.
|
||||
|
||||
Returns:
|
||||
A tuple of:
|
||||
The room ID (str).
|
||||
Hosts likely to be participating in the room ([str]).
|
||||
|
||||
Raises:
|
||||
SynapseError if room alias is invalid or could not be found.
|
||||
"""
|
||||
alias = RoomAlias.from_string(room_alias)
|
||||
(room_id, hosts) = await self._hs.get_room_member_handler().lookup_room_alias(
|
||||
alias
|
||||
)
|
||||
|
||||
return room_id.to_string(), hosts
|
||||
|
||||
|
||||
class PublicRoomListManager:
|
||||
"""Contains methods for adding to, removing from and querying whether a room
|
||||
|
|
|
@ -33,7 +33,7 @@ from synapse.api.ratelimiting import Ratelimiter
|
|||
from synapse.config import ConfigError
|
||||
from synapse.config.emailconfig import ThreepidBehaviour
|
||||
from synapse.config.homeserver import HomeServerConfig
|
||||
from synapse.config.ratelimiting import FederationRateLimitConfig
|
||||
from synapse.config.ratelimiting import FederationRatelimitSettings
|
||||
from synapse.config.server import is_threepid_reserved
|
||||
from synapse.handlers.auth import AuthHandler
|
||||
from synapse.handlers.ui_auth import UIAuthSessionDataConstants
|
||||
|
@ -325,7 +325,7 @@ class UsernameAvailabilityRestServlet(RestServlet):
|
|||
self.registration_handler = hs.get_registration_handler()
|
||||
self.ratelimiter = FederationRateLimiter(
|
||||
hs.get_clock(),
|
||||
FederationRateLimitConfig(
|
||||
FederationRatelimitSettings(
|
||||
# Time window of 2s
|
||||
window_size=2000,
|
||||
# Artificially delay requests if rate > sleep_limit/window_size
|
||||
|
|
|
@ -21,6 +21,7 @@ from synapse.handlers.presence import PresenceEventSource
|
|||
from synapse.handlers.receipts import ReceiptEventSource
|
||||
from synapse.handlers.room import RoomEventSource
|
||||
from synapse.handlers.typing import TypingNotificationEventSource
|
||||
from synapse.logging.tracing import trace
|
||||
from synapse.streams import EventSource
|
||||
from synapse.types import StreamToken
|
||||
|
||||
|
@ -69,6 +70,7 @@ class EventSources:
|
|||
)
|
||||
return token
|
||||
|
||||
@trace
|
||||
async def get_current_token_for_pagination(self, room_id: str) -> StreamToken:
|
||||
"""Get the current token for a given room to be used to paginate
|
||||
events.
|
||||
|
|
|
@ -21,7 +21,7 @@ from typing import Any, DefaultDict, Iterator, List, Set
|
|||
from twisted.internet import defer
|
||||
|
||||
from synapse.api.errors import LimitExceededError
|
||||
from synapse.config.ratelimiting import FederationRateLimitConfig
|
||||
from synapse.config.ratelimiting import FederationRatelimitSettings
|
||||
from synapse.logging.context import (
|
||||
PreserveLoggingContext,
|
||||
make_deferred_yieldable,
|
||||
|
@ -36,7 +36,7 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class FederationRateLimiter:
|
||||
def __init__(self, clock: Clock, config: FederationRateLimitConfig):
|
||||
def __init__(self, clock: Clock, config: FederationRatelimitSettings):
|
||||
def new_limiter() -> "_PerHostRatelimiter":
|
||||
return _PerHostRatelimiter(clock=clock, config=config)
|
||||
|
||||
|
@ -63,7 +63,7 @@ class FederationRateLimiter:
|
|||
|
||||
|
||||
class _PerHostRatelimiter:
|
||||
def __init__(self, clock: Clock, config: FederationRateLimitConfig):
|
||||
def __init__(self, clock: Clock, config: FederationRatelimitSettings):
|
||||
"""
|
||||
Args:
|
||||
clock
|
||||
|
|
|
@ -139,10 +139,10 @@ class TracingTestCase(TestCase):
|
|||
with start_active_span(
|
||||
f"task{i}",
|
||||
tracer=self._tracer,
|
||||
) as span1:
|
||||
self.assertEqual(opentelemetry.trace.get_current_span(), span1)
|
||||
) as span:
|
||||
self.assertEqual(opentelemetry.trace.get_current_span(), span)
|
||||
await clock.sleep(4)
|
||||
self.assertEqual(opentelemetry.trace.get_current_span(), span1)
|
||||
self.assertEqual(opentelemetry.trace.get_current_span(), span)
|
||||
|
||||
async def root():
|
||||
with start_active_span("root_span", tracer=self._tracer) as root_span:
|
||||
|
@ -163,12 +163,12 @@ class TracingTestCase(TestCase):
|
|||
self.assertEqual(opentelemetry.trace.get_current_span(), root_span)
|
||||
|
||||
# start the test off
|
||||
d1 = defer.ensureDeferred(root())
|
||||
root_defferred = defer.ensureDeferred(root())
|
||||
|
||||
# let the tasks complete
|
||||
reactor.pump((2,) * 8)
|
||||
|
||||
self.successResultOf(d1)
|
||||
self.successResultOf(root_defferred)
|
||||
# Active span is unset now that we're outside of the `with` scopes
|
||||
self.assertEqual(
|
||||
opentelemetry.trace.get_current_span(), opentelemetry.trace.INVALID_SPAN
|
||||
|
|
|
@ -635,6 +635,25 @@ class ModuleApiTestCase(HomeserverTestCase):
|
|||
[{"set_tweak": "sound", "value": "default"}]
|
||||
)
|
||||
|
||||
def test_lookup_room_alias(self) -> None:
|
||||
"""Test that modules can resolve a room alias to a room ID."""
|
||||
password = "password"
|
||||
user_id = self.register_user("user", password)
|
||||
access_token = self.login(user_id, password)
|
||||
room_alias = "my-alias"
|
||||
reference_room_id = self.helper.create_room_as(
|
||||
tok=access_token, extra_content={"room_alias_name": room_alias}
|
||||
)
|
||||
self.assertIsNotNone(reference_room_id)
|
||||
|
||||
(room_id, _) = self.get_success(
|
||||
self.module_api.lookup_room_alias(
|
||||
f"#{room_alias}:{self.module_api.server_name}"
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(room_id, reference_room_id)
|
||||
|
||||
|
||||
class ModuleApiWorkerTestCase(BaseMultiWorkerStreamTestCase):
|
||||
"""For testing ModuleApi functionality in a multi-worker setup"""
|
||||
|
|
|
@ -1772,6 +1772,21 @@ class RoomTestCase(unittest.HomeserverTestCase):
|
|||
tok=admin_user_tok,
|
||||
)
|
||||
|
||||
def test_get_joined_members_after_leave_room(self) -> None:
|
||||
"""Test that requesting room members after leaving the room raises a 403 error."""
|
||||
|
||||
# create the room
|
||||
user = self.register_user("foo", "pass")
|
||||
user_tok = self.login("foo", "pass")
|
||||
room_id = self.helper.create_room_as(user, tok=user_tok)
|
||||
self.helper.leave(room_id, user, tok=user_tok)
|
||||
|
||||
# delete the rooms and get joined roomed membership
|
||||
url = f"/_matrix/client/r0/rooms/{room_id}/joined_members"
|
||||
channel = self.make_request("GET", url.encode("ascii"), access_token=user_tok)
|
||||
self.assertEqual(HTTPStatus.FORBIDDEN, channel.code, msg=channel.json_body)
|
||||
self.assertEqual(Codes.FORBIDDEN, channel.json_body["errcode"])
|
||||
|
||||
|
||||
class JoinAliasRoomTestCase(unittest.HomeserverTestCase):
|
||||
|
||||
|
|
Loading…
Reference in a new issue