matrix-synapse 1.139.0rc2__cp39-abi3-musllinux_1_2_aarch64.whl → 1.140.0rc1__cp39-abi3-musllinux_1_2_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of matrix-synapse might be problematic. Click here for more details.

Files changed (159) hide show
  1. {matrix_synapse-1.139.0rc2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/METADATA +5 -3
  2. {matrix_synapse-1.139.0rc2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/RECORD +158 -155
  3. synapse/_scripts/generate_workers_map.py +6 -1
  4. synapse/_scripts/synapse_port_db.py +0 -2
  5. synapse/_scripts/update_synapse_database.py +1 -6
  6. synapse/api/auth/base.py +1 -3
  7. synapse/api/auth/mas.py +6 -8
  8. synapse/api/auth/msc3861_delegated.py +6 -8
  9. synapse/api/errors.py +3 -0
  10. synapse/app/_base.py +101 -39
  11. synapse/app/admin_cmd.py +2 -4
  12. synapse/app/appservice.py +1 -1
  13. synapse/app/client_reader.py +1 -1
  14. synapse/app/event_creator.py +1 -1
  15. synapse/app/federation_reader.py +1 -1
  16. synapse/app/federation_sender.py +1 -1
  17. synapse/app/frontend_proxy.py +1 -1
  18. synapse/app/generic_worker.py +17 -11
  19. synapse/app/homeserver.py +85 -47
  20. synapse/app/media_repository.py +1 -1
  21. synapse/app/phone_stats_home.py +16 -14
  22. synapse/app/pusher.py +1 -1
  23. synapse/app/synchrotron.py +1 -1
  24. synapse/app/user_dir.py +1 -1
  25. synapse/appservice/__init__.py +29 -2
  26. synapse/appservice/scheduler.py +8 -8
  27. synapse/config/_base.py +32 -14
  28. synapse/config/_base.pyi +5 -3
  29. synapse/config/experimental.py +3 -0
  30. synapse/config/homeserver.py +27 -1
  31. synapse/config/logger.py +3 -4
  32. synapse/config/matrixrtc.py +67 -0
  33. synapse/crypto/keyring.py +18 -4
  34. synapse/events/auto_accept_invites.py +0 -1
  35. synapse/federation/federation_client.py +39 -0
  36. synapse/federation/federation_server.py +1 -1
  37. synapse/federation/send_queue.py +3 -0
  38. synapse/federation/sender/__init__.py +24 -8
  39. synapse/federation/sender/per_destination_queue.py +31 -8
  40. synapse/federation/sender/transaction_manager.py +12 -0
  41. synapse/federation/transport/client.py +29 -0
  42. synapse/handlers/account_validity.py +2 -4
  43. synapse/handlers/appservice.py +5 -7
  44. synapse/handlers/deactivate_account.py +2 -3
  45. synapse/handlers/delayed_events.py +10 -13
  46. synapse/handlers/device.py +14 -14
  47. synapse/handlers/e2e_keys.py +16 -11
  48. synapse/handlers/federation.py +7 -11
  49. synapse/handlers/federation_event.py +5 -6
  50. synapse/handlers/message.py +16 -10
  51. synapse/handlers/pagination.py +3 -7
  52. synapse/handlers/presence.py +21 -25
  53. synapse/handlers/profile.py +1 -1
  54. synapse/handlers/read_marker.py +3 -1
  55. synapse/handlers/register.py +8 -1
  56. synapse/handlers/room.py +13 -4
  57. synapse/handlers/room_member.py +11 -7
  58. synapse/handlers/room_policy.py +96 -2
  59. synapse/handlers/sso.py +1 -1
  60. synapse/handlers/stats.py +5 -3
  61. synapse/handlers/sync.py +20 -13
  62. synapse/handlers/typing.py +5 -10
  63. synapse/handlers/user_directory.py +12 -11
  64. synapse/handlers/worker_lock.py +19 -15
  65. synapse/http/client.py +18 -13
  66. synapse/http/federation/matrix_federation_agent.py +6 -1
  67. synapse/http/federation/well_known_resolver.py +3 -1
  68. synapse/http/matrixfederationclient.py +50 -11
  69. synapse/http/proxy.py +2 -2
  70. synapse/http/server.py +36 -2
  71. synapse/http/site.py +109 -17
  72. synapse/logging/context.py +201 -110
  73. synapse/logging/opentracing.py +30 -6
  74. synapse/logging/scopecontextmanager.py +161 -0
  75. synapse/media/_base.py +2 -1
  76. synapse/media/media_repository.py +20 -6
  77. synapse/media/url_previewer.py +5 -6
  78. synapse/metrics/_gc.py +3 -1
  79. synapse/metrics/background_process_metrics.py +128 -24
  80. synapse/metrics/common_usage_metrics.py +3 -5
  81. synapse/module_api/__init__.py +42 -5
  82. synapse/notifier.py +10 -3
  83. synapse/push/emailpusher.py +5 -4
  84. synapse/push/httppusher.py +6 -6
  85. synapse/push/pusherpool.py +3 -8
  86. synapse/replication/http/devices.py +0 -41
  87. synapse/replication/tcp/client.py +8 -5
  88. synapse/replication/tcp/handler.py +2 -3
  89. synapse/replication/tcp/protocol.py +14 -7
  90. synapse/replication/tcp/redis.py +16 -11
  91. synapse/replication/tcp/resource.py +5 -4
  92. synapse/replication/tcp/streams/__init__.py +2 -0
  93. synapse/res/providers.json +6 -5
  94. synapse/rest/__init__.py +2 -0
  95. synapse/rest/admin/__init__.py +4 -0
  96. synapse/rest/admin/events.py +69 -0
  97. synapse/rest/admin/media.py +70 -2
  98. synapse/rest/client/keys.py +147 -3
  99. synapse/rest/client/matrixrtc.py +52 -0
  100. synapse/rest/client/push_rule.py +1 -1
  101. synapse/rest/client/room.py +2 -3
  102. synapse/rest/client/sync.py +1 -3
  103. synapse/rest/client/transactions.py +1 -1
  104. synapse/server.py +271 -38
  105. synapse/server_notices/server_notices_manager.py +1 -0
  106. synapse/state/__init__.py +4 -1
  107. synapse/storage/_base.py +1 -1
  108. synapse/storage/background_updates.py +8 -3
  109. synapse/storage/controllers/persist_events.py +4 -3
  110. synapse/storage/controllers/purge_events.py +2 -3
  111. synapse/storage/controllers/state.py +5 -5
  112. synapse/storage/database.py +12 -7
  113. synapse/storage/databases/main/__init__.py +7 -2
  114. synapse/storage/databases/main/cache.py +4 -3
  115. synapse/storage/databases/main/censor_events.py +1 -1
  116. synapse/storage/databases/main/client_ips.py +9 -8
  117. synapse/storage/databases/main/deviceinbox.py +7 -6
  118. synapse/storage/databases/main/devices.py +4 -4
  119. synapse/storage/databases/main/end_to_end_keys.py +6 -3
  120. synapse/storage/databases/main/event_federation.py +7 -6
  121. synapse/storage/databases/main/event_push_actions.py +13 -13
  122. synapse/storage/databases/main/events_bg_updates.py +1 -1
  123. synapse/storage/databases/main/events_worker.py +6 -8
  124. synapse/storage/databases/main/lock.py +17 -13
  125. synapse/storage/databases/main/media_repository.py +2 -2
  126. synapse/storage/databases/main/metrics.py +6 -6
  127. synapse/storage/databases/main/monthly_active_users.py +3 -4
  128. synapse/storage/databases/main/receipts.py +1 -1
  129. synapse/storage/databases/main/registration.py +18 -19
  130. synapse/storage/databases/main/roommember.py +1 -1
  131. synapse/storage/databases/main/session.py +3 -3
  132. synapse/storage/databases/main/sliding_sync.py +2 -2
  133. synapse/storage/databases/main/transactions.py +3 -3
  134. synapse/storage/databases/state/store.py +2 -0
  135. synapse/synapse_rust/http_client.pyi +4 -0
  136. synapse/synapse_rust.abi3.so +0 -0
  137. synapse/util/async_helpers.py +36 -24
  138. synapse/util/batching_queue.py +16 -6
  139. synapse/util/caches/__init__.py +1 -1
  140. synapse/util/caches/deferred_cache.py +4 -0
  141. synapse/util/caches/descriptors.py +14 -2
  142. synapse/util/caches/dictionary_cache.py +6 -1
  143. synapse/util/caches/expiringcache.py +16 -5
  144. synapse/util/caches/lrucache.py +14 -26
  145. synapse/util/caches/response_cache.py +11 -1
  146. synapse/util/clock.py +215 -39
  147. synapse/util/constants.py +2 -0
  148. synapse/util/daemonize.py +5 -1
  149. synapse/util/distributor.py +9 -5
  150. synapse/util/metrics.py +35 -6
  151. synapse/util/ratelimitutils.py +4 -1
  152. synapse/util/retryutils.py +7 -4
  153. synapse/util/task_scheduler.py +11 -14
  154. synapse/logging/filter.py +0 -38
  155. {matrix_synapse-1.139.0rc2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/AUTHORS.rst +0 -0
  156. {matrix_synapse-1.139.0rc2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/LICENSE-AGPL-3.0 +0 -0
  157. {matrix_synapse-1.139.0rc2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/LICENSE-COMMERCIAL +0 -0
  158. {matrix_synapse-1.139.0rc2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/WHEEL +0 -0
  159. {matrix_synapse-1.139.0rc2.dist-info → matrix_synapse-1.140.0rc1.dist-info}/entry_points.txt +0 -0
@@ -23,10 +23,19 @@
23
23
  import logging
24
24
  import re
25
25
  from collections import Counter
26
- from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple
26
+ from http import HTTPStatus
27
+ from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Tuple, Union
27
28
 
29
+ from typing_extensions import Self
30
+
31
+ from synapse._pydantic_compat import (
32
+ StrictBool,
33
+ StrictStr,
34
+ validator,
35
+ )
28
36
  from synapse.api.auth.mas import MasDelegatedAuth
29
37
  from synapse.api.errors import (
38
+ Codes,
30
39
  InteractiveAuthIncompleteError,
31
40
  InvalidAPICallError,
32
41
  SynapseError,
@@ -37,11 +46,13 @@ from synapse.http.servlet import (
37
46
  parse_integer,
38
47
  parse_json_object_from_request,
39
48
  parse_string,
49
+ validate_json_object,
40
50
  )
41
51
  from synapse.http.site import SynapseRequest
42
52
  from synapse.logging.opentracing import log_kv, set_tag
43
53
  from synapse.rest.client._base import client_patterns, interactive_auth_handler
44
54
  from synapse.types import JsonDict, StreamToken
55
+ from synapse.types.rest import RequestBodyModel
45
56
  from synapse.util.cancellation import cancellable
46
57
 
47
58
  if TYPE_CHECKING:
@@ -59,7 +70,6 @@ class KeyUploadServlet(RestServlet):
59
70
  "device_keys": {
60
71
  "user_id": "<user_id>",
61
72
  "device_id": "<device_id>",
62
- "valid_until_ts": <millisecond_timestamp>,
63
73
  "algorithms": [
64
74
  "m.olm.curve25519-aes-sha2",
65
75
  ]
@@ -111,12 +121,123 @@ class KeyUploadServlet(RestServlet):
111
121
  self._clock = hs.get_clock()
112
122
  self._store = hs.get_datastores().main
113
123
 
124
+ class KeyUploadRequestBody(RequestBodyModel):
125
+ """
126
+ The body of a `POST /_matrix/client/v3/keys/upload` request.
127
+
128
+ Based on https://spec.matrix.org/v1.16/client-server-api/#post_matrixclientv3keysupload.
129
+ """
130
+
131
+ class DeviceKeys(RequestBodyModel):
132
+ algorithms: List[StrictStr]
133
+ """The encryption algorithms supported by this device."""
134
+
135
+ device_id: StrictStr
136
+ """The ID of the device these keys belong to. Must match the device ID used when logging in."""
137
+
138
+ keys: Mapping[StrictStr, StrictStr]
139
+ """
140
+ Public identity keys. The names of the properties should be in the
141
+ format `<algorithm>:<device_id>`. The keys themselves should be encoded as
142
+ specified by the key algorithm.
143
+ """
144
+
145
+ signatures: Mapping[StrictStr, Mapping[StrictStr, StrictStr]]
146
+ """Signatures for the device key object. A map from user ID, to a map from "<algorithm>:<device_id>" to the signature."""
147
+
148
+ user_id: StrictStr
149
+ """The ID of the user the device belongs to. Must match the user ID used when logging in."""
150
+
151
+ class KeyObject(RequestBodyModel):
152
+ key: StrictStr
153
+ """The key, encoded using unpadded base64."""
154
+
155
+ fallback: Optional[StrictBool] = False
156
+ """Whether this is a fallback key. Only used when handling fallback keys."""
157
+
158
+ signatures: Mapping[StrictStr, Mapping[StrictStr, StrictStr]]
159
+ """Signature for the device. Mapped from user ID to another map of key signing identifier to the signature itself.
160
+
161
+ See the following for more detail: https://spec.matrix.org/v1.16/appendices/#signing-details
162
+ """
163
+
164
+ device_keys: Optional[DeviceKeys] = None
165
+ """Identity keys for the device. May be absent if no new identity keys are required."""
166
+
167
+ fallback_keys: Optional[Mapping[StrictStr, Union[StrictStr, KeyObject]]]
168
+ """
169
+ The public key which should be used if the device's one-time keys are
170
+ exhausted. The fallback key is not deleted once used, but should be
171
+ replaced when additional one-time keys are being uploaded. The server
172
+ will notify the client of the fallback key being used through `/sync`.
173
+
174
+ There can only be at most one key per algorithm uploaded, and the server
175
+ will only persist one key per algorithm.
176
+
177
+ When uploading a signed key, an additional fallback: true key should be
178
+ included to denote that the key is a fallback key.
179
+
180
+ May be absent if a new fallback key is not required.
181
+ """
182
+
183
+ @validator("fallback_keys", pre=True)
184
+ def validate_fallback_keys(cls: Self, v: Any) -> Any:
185
+ if v is None:
186
+ return v
187
+ if not isinstance(v, dict):
188
+ raise TypeError("fallback_keys must be a mapping")
189
+
190
+ for k in v.keys():
191
+ if not len(k.split(":")) == 2:
192
+ raise SynapseError(
193
+ code=HTTPStatus.BAD_REQUEST,
194
+ errcode=Codes.BAD_JSON,
195
+ msg=f"Invalid fallback_keys key {k!r}. "
196
+ 'Expected "<algorithm>:<device_id>".',
197
+ )
198
+ return v
199
+
200
+ one_time_keys: Optional[Mapping[StrictStr, Union[StrictStr, KeyObject]]] = None
201
+ """
202
+ One-time public keys for "pre-key" messages. The names of the properties
203
+ should be in the format `<algorithm>:<key_id>`.
204
+
205
+ The format of the key is determined by the key algorithm, see:
206
+ https://spec.matrix.org/v1.16/client-server-api/#key-algorithms.
207
+ """
208
+
209
+ @validator("one_time_keys", pre=True)
210
+ def validate_one_time_keys(cls: Self, v: Any) -> Any:
211
+ if v is None:
212
+ return v
213
+ if not isinstance(v, dict):
214
+ raise TypeError("one_time_keys must be a mapping")
215
+
216
+ for k, _ in v.items():
217
+ if not len(k.split(":")) == 2:
218
+ raise SynapseError(
219
+ code=HTTPStatus.BAD_REQUEST,
220
+ errcode=Codes.BAD_JSON,
221
+ msg=f"Invalid one_time_keys key {k!r}. "
222
+ 'Expected "<algorithm>:<device_id>".',
223
+ )
224
+ return v
225
+
114
226
  async def on_POST(
115
227
  self, request: SynapseRequest, device_id: Optional[str]
116
228
  ) -> Tuple[int, JsonDict]:
117
229
  requester = await self.auth.get_user_by_req(request, allow_guest=True)
118
230
  user_id = requester.user.to_string()
231
+
232
+ # Parse the request body. Validate separately, as the handler expects a
233
+ # plain dict, rather than any parsed object.
234
+ #
235
+ # Note: It would be nice to work with a parsed object, but the handler
236
+ # needs to encode portions of the request body as canonical JSON before
237
+ # storing the result in the DB. There's little point in converted to a
238
+ # parsed object and then back to a dict.
119
239
  body = parse_json_object_from_request(request)
240
+ validate_json_object(body, self.KeyUploadRequestBody)
120
241
 
121
242
  if device_id is not None:
122
243
  # Providing the device_id should only be done for setting keys
@@ -149,8 +270,31 @@ class KeyUploadServlet(RestServlet):
149
270
  400, "To upload keys, you must pass device_id when authenticating"
150
271
  )
151
272
 
273
+ if "device_keys" in body and isinstance(body["device_keys"], dict):
274
+ # Validate the provided `user_id` and `device_id` fields in
275
+ # `device_keys` match that of the requesting user. We can't do
276
+ # this directly in the pydantic model as we don't have access
277
+ # to the requester yet.
278
+ #
279
+ # TODO: We could use ValidationInfo when we switch to Pydantic v2.
280
+ # https://docs.pydantic.dev/latest/concepts/validators/#validation-info
281
+ if body["device_keys"].get("user_id") != user_id:
282
+ raise SynapseError(
283
+ code=HTTPStatus.BAD_REQUEST,
284
+ errcode=Codes.BAD_JSON,
285
+ msg="Provided `user_id` in `device_keys` does not match that of the authenticated user",
286
+ )
287
+ if body["device_keys"].get("device_id") != device_id:
288
+ raise SynapseError(
289
+ code=HTTPStatus.BAD_REQUEST,
290
+ errcode=Codes.BAD_JSON,
291
+ msg="Provided `device_id` in `device_keys` does not match that of the authenticated user device",
292
+ )
293
+
152
294
  result = await self.e2e_keys_handler.upload_keys_for_user(
153
- user_id=user_id, device_id=device_id, keys=body
295
+ user_id=user_id,
296
+ device_id=device_id,
297
+ keys=body,
154
298
  )
155
299
 
156
300
  return 200, result
@@ -0,0 +1,52 @@
1
+ #
2
+ # This file is licensed under the Affero General Public License (AGPL) version 3.
3
+ #
4
+ # Copyright (C) 2025 New Vector, Ltd
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as
8
+ # published by the Free Software Foundation, either version 3 of the
9
+ # License, or (at your option) any later version.
10
+ #
11
+ # See the GNU Affero General Public License for more details:
12
+ # <https://www.gnu.org/licenses/agpl-3.0.html>.
13
+ #
14
+ # [This file includes modifications made by New Vector Limited]
15
+ #
16
+ #
17
+
18
+ from typing import TYPE_CHECKING, Tuple
19
+
20
+ from synapse.http.server import HttpServer
21
+ from synapse.http.servlet import RestServlet
22
+ from synapse.http.site import SynapseRequest
23
+ from synapse.rest.client._base import client_patterns
24
+ from synapse.types import JsonDict
25
+
26
+ if TYPE_CHECKING:
27
+ from synapse.server import HomeServer
28
+
29
+
30
+ class MatrixRTCRestServlet(RestServlet):
31
+ PATTERNS = client_patterns(r"/org\.matrix\.msc4143/rtc/transports$", releases=())
32
+ CATEGORY = "Client API requests"
33
+
34
+ def __init__(self, hs: "HomeServer"):
35
+ super().__init__()
36
+ self._hs = hs
37
+ self._auth = hs.get_auth()
38
+ self._transports = hs.config.matrix_rtc.transports
39
+
40
+ async def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
41
+ # Require authentication for this endpoint.
42
+ await self._auth.get_user_by_req(request)
43
+
44
+ if self._transports:
45
+ return 200, {"rtc_transports": self._transports}
46
+
47
+ return 200, {}
48
+
49
+
50
+ def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
51
+ if hs.config.experimental.msc4143_enabled:
52
+ MatrixRTCRestServlet(hs).register(http_server)
@@ -65,7 +65,7 @@ class PushRuleRestServlet(RestServlet):
65
65
  hs.get_instance_name() in hs.config.worker.writers.push_rules
66
66
  )
67
67
  self._push_rules_handler = hs.get_push_rules_handler()
68
- self._push_rule_linearizer = Linearizer(name="push_rules")
68
+ self._push_rule_linearizer = Linearizer(name="push_rules", clock=hs.get_clock())
69
69
 
70
70
  async def on_PUT(self, request: SynapseRequest, path: str) -> Tuple[int, JsonDict]:
71
71
  if not self._is_push_worker:
@@ -66,7 +66,6 @@ from synapse.http.site import SynapseRequest
66
66
  from synapse.logging.context import make_deferred_yieldable, run_in_background
67
67
  from synapse.logging.opentracing import set_tag
68
68
  from synapse.metrics import SERVER_NAME_LABEL
69
- from synapse.metrics.background_process_metrics import run_as_background_process
70
69
  from synapse.rest.client._base import client_patterns
71
70
  from synapse.rest.client.transactions import HttpTransactionCache
72
71
  from synapse.state import CREATE_KEY, POWER_KEY
@@ -1225,6 +1224,7 @@ class RoomRedactEventRestServlet(TransactionRestServlet):
1225
1224
  def __init__(self, hs: "HomeServer"):
1226
1225
  super().__init__(hs)
1227
1226
  self.server_name = hs.hostname
1227
+ self.hs = hs
1228
1228
  self.event_creation_handler = hs.get_event_creation_handler()
1229
1229
  self.auth = hs.get_auth()
1230
1230
  self._store = hs.get_datastores().main
@@ -1307,9 +1307,8 @@ class RoomRedactEventRestServlet(TransactionRestServlet):
1307
1307
  )
1308
1308
 
1309
1309
  if with_relations:
1310
- run_as_background_process(
1310
+ self.hs.run_as_background_process(
1311
1311
  "redact_related_events",
1312
- self.server_name,
1313
1312
  self._relation_handler.redact_events_related_to,
1314
1313
  requester=requester,
1315
1314
  event_id=event_id,
@@ -126,6 +126,7 @@ class SyncRestServlet(RestServlet):
126
126
 
127
127
  self._json_filter_cache: LruCache[str, bool] = LruCache(
128
128
  max_size=1000,
129
+ clock=self.clock,
129
130
  cache_name="sync_valid_filter",
130
131
  server_name=self.server_name,
131
132
  )
@@ -363,9 +364,6 @@ class SyncRestServlet(RestServlet):
363
364
 
364
365
  # https://github.com/matrix-org/matrix-doc/blob/54255851f642f84a4f1aaf7bc063eebe3d76752b/proposals/2732-olm-fallback-keys.md
365
366
  # states that this field should always be included, as long as the server supports the feature.
366
- response["org.matrix.msc2732.device_unused_fallback_key_types"] = (
367
- sync_result.device_unused_fallback_key_types
368
- )
369
367
  response["device_unused_fallback_key_types"] = (
370
368
  sync_result.device_unused_fallback_key_types
371
369
  )
@@ -56,7 +56,7 @@ class HttpTransactionCache:
56
56
  ] = {}
57
57
  # Try to clean entries every 30 mins. This means entries will exist
58
58
  # for at *LEAST* 30 mins, and at *MOST* 60 mins.
59
- self.cleaner = self.clock.looping_call(self._cleanup, CLEANUP_PERIOD_MS)
59
+ self.clock.looping_call(self._cleanup, CLEANUP_PERIOD_MS)
60
60
 
61
61
  def _get_transaction_key(self, request: IRequest, requester: Requester) -> Hashable:
62
62
  """A helper function which returns a transaction key that can be used