matrix-synapse 1.145.0rc2__cp310-abi3-manylinux_2_28_x86_64.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 (1636) hide show
  1. AUTHORS.rst +51 -0
  2. CHANGES.md +1732 -0
  3. CONTRIBUTING.md +3 -0
  4. Cargo.lock +1923 -0
  5. Cargo.toml +6 -0
  6. INSTALL.md +7 -0
  7. LICENSE-AGPL-3.0 +661 -0
  8. LICENSE-COMMERCIAL +6 -0
  9. UPGRADE.rst +7 -0
  10. book.toml +47 -0
  11. changelog.d/.gitignore +1 -0
  12. demo/.gitignore +4 -0
  13. demo/clean.sh +22 -0
  14. demo/start.sh +173 -0
  15. demo/stop.sh +14 -0
  16. docs/.sample_config_header.yaml +12 -0
  17. docs/CAPTCHA_SETUP.md +37 -0
  18. docs/README.md +86 -0
  19. docs/SUMMARY.md +126 -0
  20. docs/admin_api/README.rst +13 -0
  21. docs/admin_api/account_validity.md +47 -0
  22. docs/admin_api/client_server_api_extensions.md +67 -0
  23. docs/admin_api/event_reports.md +185 -0
  24. docs/admin_api/experimental_features.md +52 -0
  25. docs/admin_api/fetch_event.md +53 -0
  26. docs/admin_api/media_admin_api.md +372 -0
  27. docs/admin_api/purge_history_api.md +77 -0
  28. docs/admin_api/register_api.md +92 -0
  29. docs/admin_api/room_membership.md +35 -0
  30. docs/admin_api/rooms.md +1190 -0
  31. docs/admin_api/scheduled_tasks.md +54 -0
  32. docs/admin_api/server_notices.md +48 -0
  33. docs/admin_api/statistics.md +132 -0
  34. docs/admin_api/user_admin_api.md +1602 -0
  35. docs/admin_api/version_api.md +23 -0
  36. docs/ancient_architecture_notes.md +81 -0
  37. docs/application_services.md +36 -0
  38. docs/architecture.md +65 -0
  39. docs/auth_chain_diff.dot +32 -0
  40. docs/auth_chain_diff.dot.png +0 -0
  41. docs/auth_chain_difference_algorithm.md +141 -0
  42. docs/changelogs/CHANGES-2019.md +1039 -0
  43. docs/changelogs/CHANGES-2020.md +2145 -0
  44. docs/changelogs/CHANGES-2021.md +2573 -0
  45. docs/changelogs/CHANGES-2022.md +2766 -0
  46. docs/changelogs/CHANGES-2023.md +2202 -0
  47. docs/changelogs/CHANGES-2024.md +1586 -0
  48. docs/changelogs/CHANGES-pre-1.0.md +3641 -0
  49. docs/changelogs/README.md +1 -0
  50. docs/code_style.md +119 -0
  51. docs/consent_tracking.md +197 -0
  52. docs/delegate.md +111 -0
  53. docs/deprecation_policy.md +89 -0
  54. docs/development/cas.md +64 -0
  55. docs/development/contributing_guide.md +554 -0
  56. docs/development/database_schema.md +404 -0
  57. docs/development/demo.md +42 -0
  58. docs/development/dependencies.md +326 -0
  59. docs/development/experimental_features.md +37 -0
  60. docs/development/git.md +148 -0
  61. docs/development/img/git/branches.jpg +0 -0
  62. docs/development/img/git/clean.png +0 -0
  63. docs/development/img/git/squash.png +0 -0
  64. docs/development/internal_documentation/README.md +12 -0
  65. docs/development/internal_documentation/release_notes_review_checklist.md +12 -0
  66. docs/development/releases.md +37 -0
  67. docs/development/reviews.md +41 -0
  68. docs/development/room-dag-concepts.md +115 -0
  69. docs/development/saml.md +40 -0
  70. docs/development/synapse_architecture/cancellation.md +392 -0
  71. docs/development/synapse_architecture/faster_joins.md +375 -0
  72. docs/development/synapse_architecture/streams.md +198 -0
  73. docs/element_logo_white_bg.svg +94 -0
  74. docs/favicon.png +0 -0
  75. docs/favicon.svg +58 -0
  76. docs/federate.md +67 -0
  77. docs/jwt.md +105 -0
  78. docs/log_contexts.md +566 -0
  79. docs/manhole.md +101 -0
  80. docs/media_repository.md +78 -0
  81. docs/message_retention_policies.md +207 -0
  82. docs/metrics-howto.md +315 -0
  83. docs/modules/account_data_callbacks.md +106 -0
  84. docs/modules/account_validity_callbacks.md +57 -0
  85. docs/modules/add_extra_fields_to_client_events_unsigned.md +32 -0
  86. docs/modules/background_update_controller_callbacks.md +71 -0
  87. docs/modules/index.md +53 -0
  88. docs/modules/media_repository_callbacks.md +131 -0
  89. docs/modules/password_auth_provider_callbacks.md +270 -0
  90. docs/modules/porting_legacy_module.md +20 -0
  91. docs/modules/presence_router_callbacks.md +112 -0
  92. docs/modules/ratelimit_callbacks.md +43 -0
  93. docs/modules/spam_checker_callbacks.md +517 -0
  94. docs/modules/third_party_rules_callbacks.md +350 -0
  95. docs/modules/writing_a_module.md +141 -0
  96. docs/openid.md +783 -0
  97. docs/opentracing.md +99 -0
  98. docs/other/running_synapse_on_single_board_computers.md +75 -0
  99. docs/password_auth_providers.md +129 -0
  100. docs/postgres.md +269 -0
  101. docs/presence_router_module.md +247 -0
  102. docs/privacy_policy_templates/en/1.0.html +26 -0
  103. docs/privacy_policy_templates/en/success.html +11 -0
  104. docs/replication.md +36 -0
  105. docs/reverse_proxy.md +327 -0
  106. docs/room_and_user_statistics.md +22 -0
  107. docs/sample_config.yaml +47 -0
  108. docs/sample_log_config.yaml +75 -0
  109. docs/server_notices.md +66 -0
  110. docs/setup/forward_proxy.md +89 -0
  111. docs/setup/installation.md +656 -0
  112. docs/setup/security.md +41 -0
  113. docs/setup/turn/coturn.md +197 -0
  114. docs/setup/turn/eturnal.md +170 -0
  115. docs/spam_checker.md +122 -0
  116. docs/sso_mapping_providers.md +208 -0
  117. docs/structured_logging.md +80 -0
  118. docs/synctl_workers.md +36 -0
  119. docs/systemd-with-workers/README.md +101 -0
  120. docs/systemd-with-workers/system/matrix-synapse-worker@.service +26 -0
  121. docs/systemd-with-workers/system/matrix-synapse.service +23 -0
  122. docs/systemd-with-workers/system/matrix-synapse.target +6 -0
  123. docs/systemd-with-workers/workers/background_worker.yaml +4 -0
  124. docs/systemd-with-workers/workers/event_persister.yaml +20 -0
  125. docs/systemd-with-workers/workers/federation_sender.yaml +4 -0
  126. docs/systemd-with-workers/workers/generic_worker.yaml +11 -0
  127. docs/systemd-with-workers/workers/media_worker.yaml +11 -0
  128. docs/systemd-with-workers/workers/pusher_worker.yaml +4 -0
  129. docs/tcp_replication.md +258 -0
  130. docs/templates.md +254 -0
  131. docs/turn-howto.md +168 -0
  132. docs/upgrade.md +2876 -0
  133. docs/usage/administration/README.md +7 -0
  134. docs/usage/administration/admin_api/README.md +47 -0
  135. docs/usage/administration/admin_api/background_updates.md +109 -0
  136. docs/usage/administration/admin_api/federation.md +212 -0
  137. docs/usage/administration/admin_api/registration_tokens.md +298 -0
  138. docs/usage/administration/admin_faq.md +294 -0
  139. docs/usage/administration/backups.md +125 -0
  140. docs/usage/administration/database_maintenance_tools.md +18 -0
  141. docs/usage/administration/monitoring/reporting_homeserver_usage_statistics.md +77 -0
  142. docs/usage/administration/monthly_active_users.md +84 -0
  143. docs/usage/administration/request_log.md +44 -0
  144. docs/usage/administration/state_groups.md +25 -0
  145. docs/usage/administration/understanding_synapse_through_grafana_graphs.md +83 -0
  146. docs/usage/administration/useful_sql_for_admins.md +216 -0
  147. docs/usage/configuration/README.md +4 -0
  148. docs/usage/configuration/config_documentation.md +4768 -0
  149. docs/usage/configuration/homeserver_sample_config.md +17 -0
  150. docs/usage/configuration/logging_sample_config.md +19 -0
  151. docs/usage/configuration/user_authentication/README.md +15 -0
  152. docs/usage/configuration/user_authentication/refresh_tokens.md +139 -0
  153. docs/usage/configuration/user_authentication/single_sign_on/README.md +5 -0
  154. docs/usage/configuration/user_authentication/single_sign_on/cas.md +8 -0
  155. docs/usage/configuration/user_authentication/single_sign_on/saml.md +8 -0
  156. docs/user_directory.md +130 -0
  157. docs/website_files/README.md +35 -0
  158. docs/website_files/indent-section-headers.css +7 -0
  159. docs/website_files/remove-nav-buttons.css +8 -0
  160. docs/website_files/table-of-contents.css +47 -0
  161. docs/website_files/table-of-contents.js +148 -0
  162. docs/website_files/theme/index.hbs +324 -0
  163. docs/website_files/version-picker.css +78 -0
  164. docs/website_files/version-picker.js +147 -0
  165. docs/website_files/version.js +1 -0
  166. docs/welcome_and_overview.md +67 -0
  167. docs/workers.md +897 -0
  168. matrix_synapse-1.145.0rc2.dist-info/METADATA +260 -0
  169. matrix_synapse-1.145.0rc2.dist-info/RECORD +1636 -0
  170. matrix_synapse-1.145.0rc2.dist-info/WHEEL +5 -0
  171. matrix_synapse-1.145.0rc2.dist-info/entry_points.txt +13 -0
  172. matrix_synapse-1.145.0rc2.dist-info/licenses/AUTHORS.rst +51 -0
  173. matrix_synapse-1.145.0rc2.dist-info/licenses/LICENSE-AGPL-3.0 +661 -0
  174. matrix_synapse-1.145.0rc2.dist-info/licenses/LICENSE-COMMERCIAL +6 -0
  175. mypy.ini +115 -0
  176. rust/Cargo.toml +63 -0
  177. rust/build.rs +45 -0
  178. scripts-dev/build_debian_packages.py +228 -0
  179. scripts-dev/check-newsfragment.sh +62 -0
  180. scripts-dev/check_line_terminators.sh +29 -0
  181. scripts-dev/check_locked_deps_have_sdists.py +64 -0
  182. scripts-dev/check_schema_delta.py +240 -0
  183. scripts-dev/complement.sh +332 -0
  184. scripts-dev/config-lint.sh +15 -0
  185. scripts-dev/database-save.sh +15 -0
  186. scripts-dev/docker_update_debian_changelog.sh +70 -0
  187. scripts-dev/dump_macaroon.py +25 -0
  188. scripts-dev/federation_client.py +428 -0
  189. scripts-dev/gen_config_documentation.py +510 -0
  190. scripts-dev/generate_sample_config.sh +28 -0
  191. scripts-dev/lint.sh +141 -0
  192. scripts-dev/make_full_schema.sh +310 -0
  193. scripts-dev/mypy_synapse_plugin.py +918 -0
  194. scripts-dev/next_github_number.sh +9 -0
  195. scripts-dev/release.py +986 -0
  196. scripts-dev/schema_versions.py +182 -0
  197. scripts-dev/sign_json.py +172 -0
  198. synapse/__init__.py +97 -0
  199. synapse/_scripts/__init__.py +0 -0
  200. synapse/_scripts/export_signing_key.py +109 -0
  201. synapse/_scripts/generate_config.py +83 -0
  202. synapse/_scripts/generate_log_config.py +56 -0
  203. synapse/_scripts/generate_signing_key.py +55 -0
  204. synapse/_scripts/generate_workers_map.py +318 -0
  205. synapse/_scripts/hash_password.py +95 -0
  206. synapse/_scripts/move_remote_media_to_new_store.py +128 -0
  207. synapse/_scripts/register_new_matrix_user.py +402 -0
  208. synapse/_scripts/review_recent_signups.py +212 -0
  209. synapse/_scripts/synapse_port_db.py +1604 -0
  210. synapse/_scripts/synctl.py +365 -0
  211. synapse/_scripts/update_synapse_database.py +130 -0
  212. synapse/api/__init__.py +20 -0
  213. synapse/api/auth/__init__.py +207 -0
  214. synapse/api/auth/base.py +406 -0
  215. synapse/api/auth/internal.py +299 -0
  216. synapse/api/auth/mas.py +436 -0
  217. synapse/api/auth/msc3861_delegated.py +617 -0
  218. synapse/api/auth_blocking.py +144 -0
  219. synapse/api/constants.py +379 -0
  220. synapse/api/errors.py +913 -0
  221. synapse/api/filtering.py +537 -0
  222. synapse/api/presence.py +102 -0
  223. synapse/api/ratelimiting.py +481 -0
  224. synapse/api/room_versions.py +535 -0
  225. synapse/api/urls.py +118 -0
  226. synapse/app/__init__.py +62 -0
  227. synapse/app/_base.py +906 -0
  228. synapse/app/admin_cmd.py +388 -0
  229. synapse/app/appservice.py +30 -0
  230. synapse/app/client_reader.py +30 -0
  231. synapse/app/complement_fork_starter.py +206 -0
  232. synapse/app/event_creator.py +29 -0
  233. synapse/app/federation_reader.py +30 -0
  234. synapse/app/federation_sender.py +30 -0
  235. synapse/app/frontend_proxy.py +30 -0
  236. synapse/app/generic_worker.py +475 -0
  237. synapse/app/homeserver.py +505 -0
  238. synapse/app/media_repository.py +30 -0
  239. synapse/app/phone_stats_home.py +292 -0
  240. synapse/app/pusher.py +30 -0
  241. synapse/app/synchrotron.py +30 -0
  242. synapse/app/user_dir.py +31 -0
  243. synapse/appservice/__init__.py +458 -0
  244. synapse/appservice/api.py +567 -0
  245. synapse/appservice/scheduler.py +565 -0
  246. synapse/config/__init__.py +27 -0
  247. synapse/config/__main__.py +62 -0
  248. synapse/config/_base.py +1154 -0
  249. synapse/config/_base.pyi +216 -0
  250. synapse/config/_util.py +99 -0
  251. synapse/config/account_validity.py +116 -0
  252. synapse/config/api.py +141 -0
  253. synapse/config/appservice.py +210 -0
  254. synapse/config/auth.py +80 -0
  255. synapse/config/auto_accept_invites.py +43 -0
  256. synapse/config/background_updates.py +44 -0
  257. synapse/config/cache.py +231 -0
  258. synapse/config/captcha.py +90 -0
  259. synapse/config/cas.py +116 -0
  260. synapse/config/consent.py +73 -0
  261. synapse/config/database.py +184 -0
  262. synapse/config/emailconfig.py +367 -0
  263. synapse/config/experimental.py +601 -0
  264. synapse/config/federation.py +114 -0
  265. synapse/config/homeserver.py +141 -0
  266. synapse/config/jwt.py +55 -0
  267. synapse/config/key.py +447 -0
  268. synapse/config/logger.py +390 -0
  269. synapse/config/mas.py +192 -0
  270. synapse/config/matrixrtc.py +66 -0
  271. synapse/config/metrics.py +93 -0
  272. synapse/config/modules.py +40 -0
  273. synapse/config/oembed.py +185 -0
  274. synapse/config/oidc.py +509 -0
  275. synapse/config/password_auth_providers.py +82 -0
  276. synapse/config/push.py +64 -0
  277. synapse/config/ratelimiting.py +260 -0
  278. synapse/config/redis.py +74 -0
  279. synapse/config/registration.py +296 -0
  280. synapse/config/repository.py +311 -0
  281. synapse/config/retention.py +162 -0
  282. synapse/config/room.py +88 -0
  283. synapse/config/room_directory.py +165 -0
  284. synapse/config/saml2.py +251 -0
  285. synapse/config/server.py +1139 -0
  286. synapse/config/server_notices.py +84 -0
  287. synapse/config/spam_checker.py +66 -0
  288. synapse/config/sso.py +121 -0
  289. synapse/config/stats.py +54 -0
  290. synapse/config/third_party_event_rules.py +40 -0
  291. synapse/config/tls.py +192 -0
  292. synapse/config/tracer.py +71 -0
  293. synapse/config/user_directory.py +47 -0
  294. synapse/config/user_types.py +42 -0
  295. synapse/config/voip.py +59 -0
  296. synapse/config/workers.py +642 -0
  297. synapse/crypto/__init__.py +20 -0
  298. synapse/crypto/context_factory.py +278 -0
  299. synapse/crypto/event_signing.py +194 -0
  300. synapse/crypto/keyring.py +980 -0
  301. synapse/event_auth.py +1266 -0
  302. synapse/events/__init__.py +667 -0
  303. synapse/events/auto_accept_invites.py +216 -0
  304. synapse/events/builder.py +387 -0
  305. synapse/events/presence_router.py +243 -0
  306. synapse/events/snapshot.py +559 -0
  307. synapse/events/utils.py +924 -0
  308. synapse/events/validator.py +305 -0
  309. synapse/federation/__init__.py +22 -0
  310. synapse/federation/federation_base.py +382 -0
  311. synapse/federation/federation_client.py +2133 -0
  312. synapse/federation/federation_server.py +1543 -0
  313. synapse/federation/persistence.py +70 -0
  314. synapse/federation/send_queue.py +532 -0
  315. synapse/federation/sender/__init__.py +1165 -0
  316. synapse/federation/sender/per_destination_queue.py +886 -0
  317. synapse/federation/sender/transaction_manager.py +210 -0
  318. synapse/federation/transport/__init__.py +28 -0
  319. synapse/federation/transport/client.py +1199 -0
  320. synapse/federation/transport/server/__init__.py +334 -0
  321. synapse/federation/transport/server/_base.py +429 -0
  322. synapse/federation/transport/server/federation.py +910 -0
  323. synapse/federation/units.py +133 -0
  324. synapse/handlers/__init__.py +20 -0
  325. synapse/handlers/account.py +162 -0
  326. synapse/handlers/account_data.py +360 -0
  327. synapse/handlers/account_validity.py +362 -0
  328. synapse/handlers/admin.py +615 -0
  329. synapse/handlers/appservice.py +989 -0
  330. synapse/handlers/auth.py +2482 -0
  331. synapse/handlers/cas.py +413 -0
  332. synapse/handlers/deactivate_account.py +363 -0
  333. synapse/handlers/delayed_events.py +607 -0
  334. synapse/handlers/device.py +1869 -0
  335. synapse/handlers/devicemessage.py +399 -0
  336. synapse/handlers/directory.py +545 -0
  337. synapse/handlers/e2e_keys.py +1835 -0
  338. synapse/handlers/e2e_room_keys.py +455 -0
  339. synapse/handlers/event_auth.py +390 -0
  340. synapse/handlers/events.py +203 -0
  341. synapse/handlers/federation.py +2042 -0
  342. synapse/handlers/federation_event.py +2420 -0
  343. synapse/handlers/identity.py +812 -0
  344. synapse/handlers/initial_sync.py +528 -0
  345. synapse/handlers/jwt.py +120 -0
  346. synapse/handlers/message.py +2357 -0
  347. synapse/handlers/oidc.py +1801 -0
  348. synapse/handlers/pagination.py +811 -0
  349. synapse/handlers/password_policy.py +102 -0
  350. synapse/handlers/presence.py +2634 -0
  351. synapse/handlers/profile.py +656 -0
  352. synapse/handlers/push_rules.py +164 -0
  353. synapse/handlers/read_marker.py +79 -0
  354. synapse/handlers/receipts.py +351 -0
  355. synapse/handlers/register.py +1059 -0
  356. synapse/handlers/relations.py +623 -0
  357. synapse/handlers/reports.py +98 -0
  358. synapse/handlers/room.py +2449 -0
  359. synapse/handlers/room_list.py +632 -0
  360. synapse/handlers/room_member.py +2366 -0
  361. synapse/handlers/room_member_worker.py +146 -0
  362. synapse/handlers/room_policy.py +186 -0
  363. synapse/handlers/room_summary.py +1057 -0
  364. synapse/handlers/saml.py +524 -0
  365. synapse/handlers/search.py +723 -0
  366. synapse/handlers/send_email.py +209 -0
  367. synapse/handlers/set_password.py +71 -0
  368. synapse/handlers/sliding_sync/__init__.py +1961 -0
  369. synapse/handlers/sliding_sync/extensions.py +969 -0
  370. synapse/handlers/sliding_sync/room_lists.py +2317 -0
  371. synapse/handlers/sliding_sync/store.py +126 -0
  372. synapse/handlers/sso.py +1291 -0
  373. synapse/handlers/state_deltas.py +82 -0
  374. synapse/handlers/stats.py +322 -0
  375. synapse/handlers/sync.py +3096 -0
  376. synapse/handlers/thread_subscriptions.py +190 -0
  377. synapse/handlers/typing.py +612 -0
  378. synapse/handlers/ui_auth/__init__.py +48 -0
  379. synapse/handlers/ui_auth/checkers.py +332 -0
  380. synapse/handlers/user_directory.py +786 -0
  381. synapse/handlers/worker_lock.py +371 -0
  382. synapse/http/__init__.py +105 -0
  383. synapse/http/additional_resource.py +62 -0
  384. synapse/http/client.py +1377 -0
  385. synapse/http/connectproxyclient.py +316 -0
  386. synapse/http/federation/__init__.py +19 -0
  387. synapse/http/federation/matrix_federation_agent.py +490 -0
  388. synapse/http/federation/srv_resolver.py +196 -0
  389. synapse/http/federation/well_known_resolver.py +368 -0
  390. synapse/http/matrixfederationclient.py +1874 -0
  391. synapse/http/proxy.py +290 -0
  392. synapse/http/proxyagent.py +497 -0
  393. synapse/http/replicationagent.py +203 -0
  394. synapse/http/request_metrics.py +309 -0
  395. synapse/http/server.py +1111 -0
  396. synapse/http/servlet.py +1018 -0
  397. synapse/http/site.py +952 -0
  398. synapse/http/types.py +27 -0
  399. synapse/logging/__init__.py +31 -0
  400. synapse/logging/_remote.py +261 -0
  401. synapse/logging/_terse_json.py +95 -0
  402. synapse/logging/context.py +1209 -0
  403. synapse/logging/formatter.py +62 -0
  404. synapse/logging/handlers.py +99 -0
  405. synapse/logging/loggers.py +25 -0
  406. synapse/logging/opentracing.py +1132 -0
  407. synapse/logging/scopecontextmanager.py +160 -0
  408. synapse/media/_base.py +831 -0
  409. synapse/media/filepath.py +417 -0
  410. synapse/media/media_repository.py +1595 -0
  411. synapse/media/media_storage.py +703 -0
  412. synapse/media/oembed.py +277 -0
  413. synapse/media/preview_html.py +556 -0
  414. synapse/media/storage_provider.py +195 -0
  415. synapse/media/thumbnailer.py +833 -0
  416. synapse/media/url_previewer.py +884 -0
  417. synapse/metrics/__init__.py +748 -0
  418. synapse/metrics/_gc.py +219 -0
  419. synapse/metrics/_reactor_metrics.py +171 -0
  420. synapse/metrics/_types.py +38 -0
  421. synapse/metrics/background_process_metrics.py +555 -0
  422. synapse/metrics/common_usage_metrics.py +95 -0
  423. synapse/metrics/jemalloc.py +248 -0
  424. synapse/module_api/__init__.py +2131 -0
  425. synapse/module_api/callbacks/__init__.py +50 -0
  426. synapse/module_api/callbacks/account_validity_callbacks.py +106 -0
  427. synapse/module_api/callbacks/media_repository_callbacks.py +157 -0
  428. synapse/module_api/callbacks/ratelimit_callbacks.py +78 -0
  429. synapse/module_api/callbacks/spamchecker_callbacks.py +991 -0
  430. synapse/module_api/callbacks/third_party_event_rules_callbacks.py +592 -0
  431. synapse/module_api/errors.py +42 -0
  432. synapse/notifier.py +969 -0
  433. synapse/push/__init__.py +212 -0
  434. synapse/push/bulk_push_rule_evaluator.py +635 -0
  435. synapse/push/clientformat.py +126 -0
  436. synapse/push/emailpusher.py +334 -0
  437. synapse/push/httppusher.py +565 -0
  438. synapse/push/mailer.py +1009 -0
  439. synapse/push/presentable_names.py +216 -0
  440. synapse/push/push_tools.py +114 -0
  441. synapse/push/push_types.py +141 -0
  442. synapse/push/pusher.py +87 -0
  443. synapse/push/pusherpool.py +501 -0
  444. synapse/push/rulekinds.py +33 -0
  445. synapse/py.typed +0 -0
  446. synapse/replication/__init__.py +20 -0
  447. synapse/replication/http/__init__.py +68 -0
  448. synapse/replication/http/_base.py +469 -0
  449. synapse/replication/http/account_data.py +297 -0
  450. synapse/replication/http/deactivate_account.py +81 -0
  451. synapse/replication/http/delayed_events.py +62 -0
  452. synapse/replication/http/devices.py +254 -0
  453. synapse/replication/http/federation.py +334 -0
  454. synapse/replication/http/login.py +106 -0
  455. synapse/replication/http/membership.py +364 -0
  456. synapse/replication/http/presence.py +133 -0
  457. synapse/replication/http/push.py +156 -0
  458. synapse/replication/http/register.py +172 -0
  459. synapse/replication/http/send_events.py +182 -0
  460. synapse/replication/http/state.py +82 -0
  461. synapse/replication/http/streams.py +101 -0
  462. synapse/replication/tcp/__init__.py +56 -0
  463. synapse/replication/tcp/client.py +553 -0
  464. synapse/replication/tcp/commands.py +569 -0
  465. synapse/replication/tcp/context.py +41 -0
  466. synapse/replication/tcp/external_cache.py +156 -0
  467. synapse/replication/tcp/handler.py +922 -0
  468. synapse/replication/tcp/protocol.py +611 -0
  469. synapse/replication/tcp/redis.py +510 -0
  470. synapse/replication/tcp/resource.py +349 -0
  471. synapse/replication/tcp/streams/__init__.py +96 -0
  472. synapse/replication/tcp/streams/_base.py +765 -0
  473. synapse/replication/tcp/streams/events.py +287 -0
  474. synapse/replication/tcp/streams/federation.py +92 -0
  475. synapse/replication/tcp/streams/partial_state.py +80 -0
  476. synapse/res/providers.json +29 -0
  477. synapse/res/templates/_base.html +29 -0
  478. synapse/res/templates/account_previously_renewed.html +6 -0
  479. synapse/res/templates/account_renewed.html +6 -0
  480. synapse/res/templates/add_threepid.html +8 -0
  481. synapse/res/templates/add_threepid.txt +6 -0
  482. synapse/res/templates/add_threepid_failure.html +7 -0
  483. synapse/res/templates/add_threepid_success.html +6 -0
  484. synapse/res/templates/already_in_use.html +12 -0
  485. synapse/res/templates/already_in_use.txt +10 -0
  486. synapse/res/templates/auth_success.html +21 -0
  487. synapse/res/templates/invalid_token.html +6 -0
  488. synapse/res/templates/mail-Element.css +7 -0
  489. synapse/res/templates/mail-Vector.css +7 -0
  490. synapse/res/templates/mail-expiry.css +4 -0
  491. synapse/res/templates/mail.css +156 -0
  492. synapse/res/templates/notice_expiry.html +46 -0
  493. synapse/res/templates/notice_expiry.txt +7 -0
  494. synapse/res/templates/notif.html +51 -0
  495. synapse/res/templates/notif.txt +22 -0
  496. synapse/res/templates/notif_mail.html +59 -0
  497. synapse/res/templates/notif_mail.txt +10 -0
  498. synapse/res/templates/password_reset.html +10 -0
  499. synapse/res/templates/password_reset.txt +7 -0
  500. synapse/res/templates/password_reset_confirmation.html +15 -0
  501. synapse/res/templates/password_reset_failure.html +7 -0
  502. synapse/res/templates/password_reset_success.html +6 -0
  503. synapse/res/templates/recaptcha.html +42 -0
  504. synapse/res/templates/registration.html +12 -0
  505. synapse/res/templates/registration.txt +10 -0
  506. synapse/res/templates/registration_failure.html +6 -0
  507. synapse/res/templates/registration_success.html +6 -0
  508. synapse/res/templates/registration_token.html +18 -0
  509. synapse/res/templates/room.html +33 -0
  510. synapse/res/templates/room.txt +9 -0
  511. synapse/res/templates/sso.css +129 -0
  512. synapse/res/templates/sso_account_deactivated.html +25 -0
  513. synapse/res/templates/sso_auth_account_details.html +186 -0
  514. synapse/res/templates/sso_auth_account_details.js +116 -0
  515. synapse/res/templates/sso_auth_bad_user.html +26 -0
  516. synapse/res/templates/sso_auth_confirm.html +27 -0
  517. synapse/res/templates/sso_auth_success.html +26 -0
  518. synapse/res/templates/sso_error.html +71 -0
  519. synapse/res/templates/sso_footer.html +19 -0
  520. synapse/res/templates/sso_login_idp_picker.html +60 -0
  521. synapse/res/templates/sso_new_user_consent.html +30 -0
  522. synapse/res/templates/sso_partial_profile.html +19 -0
  523. synapse/res/templates/sso_redirect_confirm.html +39 -0
  524. synapse/res/templates/style.css +33 -0
  525. synapse/res/templates/terms.html +27 -0
  526. synapse/rest/__init__.py +197 -0
  527. synapse/rest/admin/__init__.py +395 -0
  528. synapse/rest/admin/_base.py +72 -0
  529. synapse/rest/admin/background_updates.py +171 -0
  530. synapse/rest/admin/devices.py +221 -0
  531. synapse/rest/admin/event_reports.py +173 -0
  532. synapse/rest/admin/events.py +69 -0
  533. synapse/rest/admin/experimental_features.py +137 -0
  534. synapse/rest/admin/federation.py +243 -0
  535. synapse/rest/admin/media.py +540 -0
  536. synapse/rest/admin/registration_tokens.py +358 -0
  537. synapse/rest/admin/rooms.py +1092 -0
  538. synapse/rest/admin/scheduled_tasks.py +70 -0
  539. synapse/rest/admin/server_notice_servlet.py +132 -0
  540. synapse/rest/admin/statistics.py +132 -0
  541. synapse/rest/admin/username_available.py +58 -0
  542. synapse/rest/admin/users.py +1634 -0
  543. synapse/rest/client/__init__.py +20 -0
  544. synapse/rest/client/_base.py +113 -0
  545. synapse/rest/client/account.py +937 -0
  546. synapse/rest/client/account_data.py +319 -0
  547. synapse/rest/client/account_validity.py +103 -0
  548. synapse/rest/client/appservice_ping.py +125 -0
  549. synapse/rest/client/auth.py +218 -0
  550. synapse/rest/client/auth_metadata.py +122 -0
  551. synapse/rest/client/capabilities.py +121 -0
  552. synapse/rest/client/delayed_events.py +165 -0
  553. synapse/rest/client/devices.py +587 -0
  554. synapse/rest/client/directory.py +211 -0
  555. synapse/rest/client/events.py +116 -0
  556. synapse/rest/client/filter.py +112 -0
  557. synapse/rest/client/initial_sync.py +65 -0
  558. synapse/rest/client/keys.py +678 -0
  559. synapse/rest/client/knock.py +104 -0
  560. synapse/rest/client/login.py +750 -0
  561. synapse/rest/client/login_token_request.py +127 -0
  562. synapse/rest/client/logout.py +93 -0
  563. synapse/rest/client/matrixrtc.py +52 -0
  564. synapse/rest/client/media.py +307 -0
  565. synapse/rest/client/mutual_rooms.py +145 -0
  566. synapse/rest/client/notifications.py +137 -0
  567. synapse/rest/client/openid.py +109 -0
  568. synapse/rest/client/password_policy.py +69 -0
  569. synapse/rest/client/presence.py +131 -0
  570. synapse/rest/client/profile.py +291 -0
  571. synapse/rest/client/push_rule.py +331 -0
  572. synapse/rest/client/pusher.py +181 -0
  573. synapse/rest/client/read_marker.py +104 -0
  574. synapse/rest/client/receipts.py +165 -0
  575. synapse/rest/client/register.py +1072 -0
  576. synapse/rest/client/relations.py +138 -0
  577. synapse/rest/client/rendezvous.py +76 -0
  578. synapse/rest/client/reporting.py +207 -0
  579. synapse/rest/client/room.py +1763 -0
  580. synapse/rest/client/room_keys.py +426 -0
  581. synapse/rest/client/room_upgrade_rest_servlet.py +112 -0
  582. synapse/rest/client/sendtodevice.py +85 -0
  583. synapse/rest/client/sync.py +1131 -0
  584. synapse/rest/client/tags.py +129 -0
  585. synapse/rest/client/thirdparty.py +130 -0
  586. synapse/rest/client/thread_subscriptions.py +247 -0
  587. synapse/rest/client/tokenrefresh.py +52 -0
  588. synapse/rest/client/transactions.py +150 -0
  589. synapse/rest/client/user_directory.py +99 -0
  590. synapse/rest/client/versions.py +193 -0
  591. synapse/rest/client/voip.py +88 -0
  592. synapse/rest/consent/__init__.py +0 -0
  593. synapse/rest/consent/consent_resource.py +210 -0
  594. synapse/rest/health.py +38 -0
  595. synapse/rest/key/__init__.py +20 -0
  596. synapse/rest/key/v2/__init__.py +40 -0
  597. synapse/rest/key/v2/local_key_resource.py +125 -0
  598. synapse/rest/key/v2/remote_key_resource.py +302 -0
  599. synapse/rest/media/__init__.py +0 -0
  600. synapse/rest/media/config_resource.py +53 -0
  601. synapse/rest/media/create_resource.py +90 -0
  602. synapse/rest/media/download_resource.py +110 -0
  603. synapse/rest/media/media_repository_resource.py +113 -0
  604. synapse/rest/media/preview_url_resource.py +77 -0
  605. synapse/rest/media/thumbnail_resource.py +142 -0
  606. synapse/rest/media/upload_resource.py +187 -0
  607. synapse/rest/media/v1/__init__.py +39 -0
  608. synapse/rest/media/v1/_base.py +23 -0
  609. synapse/rest/media/v1/media_storage.py +23 -0
  610. synapse/rest/media/v1/storage_provider.py +23 -0
  611. synapse/rest/synapse/__init__.py +20 -0
  612. synapse/rest/synapse/client/__init__.py +93 -0
  613. synapse/rest/synapse/client/federation_whitelist.py +66 -0
  614. synapse/rest/synapse/client/jwks.py +77 -0
  615. synapse/rest/synapse/client/new_user_consent.py +115 -0
  616. synapse/rest/synapse/client/oidc/__init__.py +45 -0
  617. synapse/rest/synapse/client/oidc/backchannel_logout_resource.py +42 -0
  618. synapse/rest/synapse/client/oidc/callback_resource.py +48 -0
  619. synapse/rest/synapse/client/password_reset.py +129 -0
  620. synapse/rest/synapse/client/pick_idp.py +107 -0
  621. synapse/rest/synapse/client/pick_username.py +153 -0
  622. synapse/rest/synapse/client/rendezvous.py +58 -0
  623. synapse/rest/synapse/client/saml2/__init__.py +42 -0
  624. synapse/rest/synapse/client/saml2/metadata_resource.py +46 -0
  625. synapse/rest/synapse/client/saml2/response_resource.py +52 -0
  626. synapse/rest/synapse/client/sso_register.py +56 -0
  627. synapse/rest/synapse/client/unsubscribe.py +88 -0
  628. synapse/rest/synapse/mas/__init__.py +71 -0
  629. synapse/rest/synapse/mas/_base.py +55 -0
  630. synapse/rest/synapse/mas/devices.py +239 -0
  631. synapse/rest/synapse/mas/users.py +469 -0
  632. synapse/rest/well_known.py +148 -0
  633. synapse/server.py +1279 -0
  634. synapse/server_notices/__init__.py +0 -0
  635. synapse/server_notices/consent_server_notices.py +136 -0
  636. synapse/server_notices/resource_limits_server_notices.py +215 -0
  637. synapse/server_notices/server_notices_manager.py +388 -0
  638. synapse/server_notices/server_notices_sender.py +67 -0
  639. synapse/server_notices/worker_server_notices_sender.py +46 -0
  640. synapse/spam_checker_api/__init__.py +31 -0
  641. synapse/state/__init__.py +1023 -0
  642. synapse/state/v1.py +369 -0
  643. synapse/state/v2.py +985 -0
  644. synapse/static/client/login/index.html +47 -0
  645. synapse/static/client/login/js/jquery-3.4.1.min.js +2 -0
  646. synapse/static/client/login/js/login.js +291 -0
  647. synapse/static/client/login/spinner.gif +0 -0
  648. synapse/static/client/login/style.css +79 -0
  649. synapse/static/index.html +63 -0
  650. synapse/storage/__init__.py +43 -0
  651. synapse/storage/_base.py +245 -0
  652. synapse/storage/admin_client_config.py +25 -0
  653. synapse/storage/background_updates.py +1189 -0
  654. synapse/storage/controllers/__init__.py +57 -0
  655. synapse/storage/controllers/persist_events.py +1237 -0
  656. synapse/storage/controllers/purge_events.py +456 -0
  657. synapse/storage/controllers/state.py +950 -0
  658. synapse/storage/controllers/stats.py +119 -0
  659. synapse/storage/database.py +2720 -0
  660. synapse/storage/databases/__init__.py +175 -0
  661. synapse/storage/databases/main/__init__.py +420 -0
  662. synapse/storage/databases/main/account_data.py +1073 -0
  663. synapse/storage/databases/main/appservice.py +473 -0
  664. synapse/storage/databases/main/cache.py +912 -0
  665. synapse/storage/databases/main/censor_events.py +226 -0
  666. synapse/storage/databases/main/client_ips.py +816 -0
  667. synapse/storage/databases/main/delayed_events.py +577 -0
  668. synapse/storage/databases/main/deviceinbox.py +1272 -0
  669. synapse/storage/databases/main/devices.py +2579 -0
  670. synapse/storage/databases/main/directory.py +212 -0
  671. synapse/storage/databases/main/e2e_room_keys.py +689 -0
  672. synapse/storage/databases/main/end_to_end_keys.py +1894 -0
  673. synapse/storage/databases/main/event_federation.py +2511 -0
  674. synapse/storage/databases/main/event_push_actions.py +1936 -0
  675. synapse/storage/databases/main/events.py +3765 -0
  676. synapse/storage/databases/main/events_bg_updates.py +2910 -0
  677. synapse/storage/databases/main/events_forward_extremities.py +126 -0
  678. synapse/storage/databases/main/events_worker.py +2787 -0
  679. synapse/storage/databases/main/experimental_features.py +130 -0
  680. synapse/storage/databases/main/filtering.py +231 -0
  681. synapse/storage/databases/main/keys.py +291 -0
  682. synapse/storage/databases/main/lock.py +554 -0
  683. synapse/storage/databases/main/media_repository.py +1068 -0
  684. synapse/storage/databases/main/metrics.py +461 -0
  685. synapse/storage/databases/main/monthly_active_users.py +443 -0
  686. synapse/storage/databases/main/openid.py +60 -0
  687. synapse/storage/databases/main/presence.py +509 -0
  688. synapse/storage/databases/main/profile.py +539 -0
  689. synapse/storage/databases/main/purge_events.py +521 -0
  690. synapse/storage/databases/main/push_rule.py +970 -0
  691. synapse/storage/databases/main/pusher.py +793 -0
  692. synapse/storage/databases/main/receipts.py +1341 -0
  693. synapse/storage/databases/main/registration.py +3071 -0
  694. synapse/storage/databases/main/rejections.py +37 -0
  695. synapse/storage/databases/main/relations.py +1116 -0
  696. synapse/storage/databases/main/room.py +2779 -0
  697. synapse/storage/databases/main/roommember.py +2132 -0
  698. synapse/storage/databases/main/search.py +939 -0
  699. synapse/storage/databases/main/session.py +152 -0
  700. synapse/storage/databases/main/signatures.py +94 -0
  701. synapse/storage/databases/main/sliding_sync.py +842 -0
  702. synapse/storage/databases/main/state.py +1002 -0
  703. synapse/storage/databases/main/state_deltas.py +360 -0
  704. synapse/storage/databases/main/stats.py +789 -0
  705. synapse/storage/databases/main/stream.py +2589 -0
  706. synapse/storage/databases/main/tags.py +360 -0
  707. synapse/storage/databases/main/task_scheduler.py +225 -0
  708. synapse/storage/databases/main/thread_subscriptions.py +589 -0
  709. synapse/storage/databases/main/transactions.py +676 -0
  710. synapse/storage/databases/main/ui_auth.py +420 -0
  711. synapse/storage/databases/main/user_directory.py +1330 -0
  712. synapse/storage/databases/main/user_erasure_store.py +117 -0
  713. synapse/storage/databases/state/__init__.py +22 -0
  714. synapse/storage/databases/state/bg_updates.py +497 -0
  715. synapse/storage/databases/state/deletion.py +557 -0
  716. synapse/storage/databases/state/store.py +948 -0
  717. synapse/storage/engines/__init__.py +70 -0
  718. synapse/storage/engines/_base.py +154 -0
  719. synapse/storage/engines/postgres.py +261 -0
  720. synapse/storage/engines/sqlite.py +199 -0
  721. synapse/storage/invite_rule.py +152 -0
  722. synapse/storage/keys.py +40 -0
  723. synapse/storage/prepare_database.py +730 -0
  724. synapse/storage/push_rule.py +28 -0
  725. synapse/storage/roommember.py +88 -0
  726. synapse/storage/schema/README.md +4 -0
  727. synapse/storage/schema/__init__.py +186 -0
  728. synapse/storage/schema/common/delta/25/00background_updates.sql +40 -0
  729. synapse/storage/schema/common/delta/35/00background_updates_add_col.sql +36 -0
  730. synapse/storage/schema/common/delta/58/00background_update_ordering.sql +38 -0
  731. synapse/storage/schema/common/full_schemas/72/full.sql.postgres +8 -0
  732. synapse/storage/schema/common/full_schemas/72/full.sql.sqlite +6 -0
  733. synapse/storage/schema/common/schema_version.sql +60 -0
  734. synapse/storage/schema/main/delta/12/v12.sql +82 -0
  735. synapse/storage/schema/main/delta/13/v13.sql +38 -0
  736. synapse/storage/schema/main/delta/14/v14.sql +42 -0
  737. synapse/storage/schema/main/delta/15/appservice_txns.sql +50 -0
  738. synapse/storage/schema/main/delta/15/presence_indices.sql +2 -0
  739. synapse/storage/schema/main/delta/15/v15.sql +24 -0
  740. synapse/storage/schema/main/delta/16/events_order_index.sql +4 -0
  741. synapse/storage/schema/main/delta/16/remote_media_cache_index.sql +2 -0
  742. synapse/storage/schema/main/delta/16/remove_duplicates.sql +9 -0
  743. synapse/storage/schema/main/delta/16/room_alias_index.sql +3 -0
  744. synapse/storage/schema/main/delta/16/unique_constraints.sql +72 -0
  745. synapse/storage/schema/main/delta/16/users.sql +56 -0
  746. synapse/storage/schema/main/delta/17/drop_indexes.sql +37 -0
  747. synapse/storage/schema/main/delta/17/server_keys.sql +43 -0
  748. synapse/storage/schema/main/delta/17/user_threepids.sql +9 -0
  749. synapse/storage/schema/main/delta/18/server_keys_bigger_ints.sql +51 -0
  750. synapse/storage/schema/main/delta/19/event_index.sql +38 -0
  751. synapse/storage/schema/main/delta/20/dummy.sql +1 -0
  752. synapse/storage/schema/main/delta/20/pushers.py +93 -0
  753. synapse/storage/schema/main/delta/21/end_to_end_keys.sql +53 -0
  754. synapse/storage/schema/main/delta/21/receipts.sql +57 -0
  755. synapse/storage/schema/main/delta/22/receipts_index.sql +41 -0
  756. synapse/storage/schema/main/delta/22/user_threepids_unique.sql +19 -0
  757. synapse/storage/schema/main/delta/24/stats_reporting.sql +37 -0
  758. synapse/storage/schema/main/delta/25/fts.py +81 -0
  759. synapse/storage/schema/main/delta/25/guest_access.sql +44 -0
  760. synapse/storage/schema/main/delta/25/history_visibility.sql +44 -0
  761. synapse/storage/schema/main/delta/25/tags.sql +57 -0
  762. synapse/storage/schema/main/delta/26/account_data.sql +36 -0
  763. synapse/storage/schema/main/delta/27/account_data.sql +55 -0
  764. synapse/storage/schema/main/delta/27/forgotten_memberships.sql +45 -0
  765. synapse/storage/schema/main/delta/27/ts.py +61 -0
  766. synapse/storage/schema/main/delta/28/event_push_actions.sql +46 -0
  767. synapse/storage/schema/main/delta/28/events_room_stream.sql +39 -0
  768. synapse/storage/schema/main/delta/28/public_roms_index.sql +39 -0
  769. synapse/storage/schema/main/delta/28/receipts_user_id_index.sql +41 -0
  770. synapse/storage/schema/main/delta/28/upgrade_times.sql +40 -0
  771. synapse/storage/schema/main/delta/28/users_is_guest.sql +41 -0
  772. synapse/storage/schema/main/delta/29/push_actions.sql +54 -0
  773. synapse/storage/schema/main/delta/30/alias_creator.sql +35 -0
  774. synapse/storage/schema/main/delta/30/as_users.py +82 -0
  775. synapse/storage/schema/main/delta/30/deleted_pushers.sql +44 -0
  776. synapse/storage/schema/main/delta/30/presence_stream.sql +49 -0
  777. synapse/storage/schema/main/delta/30/public_rooms.sql +42 -0
  778. synapse/storage/schema/main/delta/30/push_rule_stream.sql +57 -0
  779. synapse/storage/schema/main/delta/30/threepid_guest_access_tokens.sql +43 -0
  780. synapse/storage/schema/main/delta/31/invites.sql +61 -0
  781. synapse/storage/schema/main/delta/31/local_media_repository_url_cache.sql +46 -0
  782. synapse/storage/schema/main/delta/31/pushers_0.py +92 -0
  783. synapse/storage/schema/main/delta/31/pushers_index.sql +41 -0
  784. synapse/storage/schema/main/delta/31/search_update.py +65 -0
  785. synapse/storage/schema/main/delta/32/events.sql +35 -0
  786. synapse/storage/schema/main/delta/32/openid.sql +9 -0
  787. synapse/storage/schema/main/delta/32/pusher_throttle.sql +42 -0
  788. synapse/storage/schema/main/delta/32/remove_indices.sql +52 -0
  789. synapse/storage/schema/main/delta/32/reports.sql +44 -0
  790. synapse/storage/schema/main/delta/33/access_tokens_device_index.sql +36 -0
  791. synapse/storage/schema/main/delta/33/devices.sql +40 -0
  792. synapse/storage/schema/main/delta/33/devices_for_e2e_keys.sql +38 -0
  793. synapse/storage/schema/main/delta/33/devices_for_e2e_keys_clear_unknown_device.sql +39 -0
  794. synapse/storage/schema/main/delta/33/event_fields.py +61 -0
  795. synapse/storage/schema/main/delta/33/remote_media_ts.py +43 -0
  796. synapse/storage/schema/main/delta/33/user_ips_index.sql +36 -0
  797. synapse/storage/schema/main/delta/34/appservice_stream.sql +42 -0
  798. synapse/storage/schema/main/delta/34/cache_stream.py +50 -0
  799. synapse/storage/schema/main/delta/34/device_inbox.sql +43 -0
  800. synapse/storage/schema/main/delta/34/push_display_name_rename.sql +39 -0
  801. synapse/storage/schema/main/delta/34/received_txn_purge.py +36 -0
  802. synapse/storage/schema/main/delta/35/contains_url.sql +36 -0
  803. synapse/storage/schema/main/delta/35/device_outbox.sql +58 -0
  804. synapse/storage/schema/main/delta/35/device_stream_id.sql +40 -0
  805. synapse/storage/schema/main/delta/35/event_push_actions_index.sql +36 -0
  806. synapse/storage/schema/main/delta/35/public_room_list_change_stream.sql +52 -0
  807. synapse/storage/schema/main/delta/35/stream_order_to_extrem.sql +56 -0
  808. synapse/storage/schema/main/delta/36/readd_public_rooms.sql +45 -0
  809. synapse/storage/schema/main/delta/37/remove_auth_idx.py +89 -0
  810. synapse/storage/schema/main/delta/37/user_threepids.sql +71 -0
  811. synapse/storage/schema/main/delta/38/postgres_fts_gist.sql +38 -0
  812. synapse/storage/schema/main/delta/39/appservice_room_list.sql +48 -0
  813. synapse/storage/schema/main/delta/39/device_federation_stream_idx.sql +35 -0
  814. synapse/storage/schema/main/delta/39/event_push_index.sql +36 -0
  815. synapse/storage/schema/main/delta/39/federation_out_position.sql +41 -0
  816. synapse/storage/schema/main/delta/39/membership_profile.sql +39 -0
  817. synapse/storage/schema/main/delta/40/current_state_idx.sql +36 -0
  818. synapse/storage/schema/main/delta/40/device_inbox.sql +40 -0
  819. synapse/storage/schema/main/delta/40/device_list_streams.sql +79 -0
  820. synapse/storage/schema/main/delta/40/event_push_summary.sql +57 -0
  821. synapse/storage/schema/main/delta/40/pushers.sql +58 -0
  822. synapse/storage/schema/main/delta/41/device_list_stream_idx.sql +36 -0
  823. synapse/storage/schema/main/delta/41/device_outbound_index.sql +35 -0
  824. synapse/storage/schema/main/delta/41/event_search_event_id_idx.sql +36 -0
  825. synapse/storage/schema/main/delta/41/ratelimit.sql +41 -0
  826. synapse/storage/schema/main/delta/42/current_state_delta.sql +48 -0
  827. synapse/storage/schema/main/delta/42/device_list_last_id.sql +52 -0
  828. synapse/storage/schema/main/delta/42/event_auth_state_only.sql +36 -0
  829. synapse/storage/schema/main/delta/42/user_dir.py +88 -0
  830. synapse/storage/schema/main/delta/43/blocked_rooms.sql +40 -0
  831. synapse/storage/schema/main/delta/43/quarantine_media.sql +36 -0
  832. synapse/storage/schema/main/delta/43/url_cache.sql +35 -0
  833. synapse/storage/schema/main/delta/43/user_share.sql +52 -0
  834. synapse/storage/schema/main/delta/44/expire_url_cache.sql +60 -0
  835. synapse/storage/schema/main/delta/45/group_server.sql +186 -0
  836. synapse/storage/schema/main/delta/45/profile_cache.sql +47 -0
  837. synapse/storage/schema/main/delta/46/drop_refresh_tokens.sql +36 -0
  838. synapse/storage/schema/main/delta/46/drop_unique_deleted_pushers.sql +54 -0
  839. synapse/storage/schema/main/delta/46/group_server.sql +51 -0
  840. synapse/storage/schema/main/delta/46/local_media_repository_url_idx.sql +43 -0
  841. synapse/storage/schema/main/delta/46/user_dir_null_room_ids.sql +54 -0
  842. synapse/storage/schema/main/delta/46/user_dir_typos.sql +43 -0
  843. synapse/storage/schema/main/delta/47/last_access_media.sql +35 -0
  844. synapse/storage/schema/main/delta/47/postgres_fts_gin.sql +36 -0
  845. synapse/storage/schema/main/delta/47/push_actions_staging.sql +47 -0
  846. synapse/storage/schema/main/delta/48/add_user_consent.sql +37 -0
  847. synapse/storage/schema/main/delta/48/add_user_ips_last_seen_index.sql +36 -0
  848. synapse/storage/schema/main/delta/48/deactivated_users.sql +44 -0
  849. synapse/storage/schema/main/delta/48/group_unique_indexes.py +67 -0
  850. synapse/storage/schema/main/delta/48/groups_joinable.sql +41 -0
  851. synapse/storage/schema/main/delta/49/add_user_consent_server_notice_sent.sql +39 -0
  852. synapse/storage/schema/main/delta/49/add_user_daily_visits.sql +40 -0
  853. synapse/storage/schema/main/delta/49/add_user_ips_last_seen_only_index.sql +36 -0
  854. synapse/storage/schema/main/delta/50/add_creation_ts_users_index.sql +38 -0
  855. synapse/storage/schema/main/delta/50/erasure_store.sql +40 -0
  856. synapse/storage/schema/main/delta/50/make_event_content_nullable.py +102 -0
  857. synapse/storage/schema/main/delta/51/e2e_room_keys.sql +58 -0
  858. synapse/storage/schema/main/delta/51/monthly_active_users.sql +46 -0
  859. synapse/storage/schema/main/delta/52/add_event_to_state_group_index.sql +38 -0
  860. synapse/storage/schema/main/delta/52/device_list_streams_unique_idx.sql +55 -0
  861. synapse/storage/schema/main/delta/52/e2e_room_keys.sql +72 -0
  862. synapse/storage/schema/main/delta/53/add_user_type_to_users.sql +38 -0
  863. synapse/storage/schema/main/delta/53/drop_sent_transactions.sql +35 -0
  864. synapse/storage/schema/main/delta/53/event_format_version.sql +35 -0
  865. synapse/storage/schema/main/delta/53/user_dir_populate.sql +49 -0
  866. synapse/storage/schema/main/delta/53/user_ips_index.sql +49 -0
  867. synapse/storage/schema/main/delta/53/user_share.sql +63 -0
  868. synapse/storage/schema/main/delta/53/user_threepid_id.sql +48 -0
  869. synapse/storage/schema/main/delta/53/users_in_public_rooms.sql +47 -0
  870. synapse/storage/schema/main/delta/54/account_validity_with_renewal.sql +49 -0
  871. synapse/storage/schema/main/delta/54/add_validity_to_server_keys.sql +42 -0
  872. synapse/storage/schema/main/delta/54/delete_forward_extremities.sql +42 -0
  873. synapse/storage/schema/main/delta/54/drop_legacy_tables.sql +49 -0
  874. synapse/storage/schema/main/delta/54/drop_presence_list.sql +35 -0
  875. synapse/storage/schema/main/delta/54/relations.sql +46 -0
  876. synapse/storage/schema/main/delta/54/stats.sql +99 -0
  877. synapse/storage/schema/main/delta/54/stats2.sql +47 -0
  878. synapse/storage/schema/main/delta/55/access_token_expiry.sql +37 -0
  879. synapse/storage/schema/main/delta/55/track_threepid_validations.sql +50 -0
  880. synapse/storage/schema/main/delta/55/users_alter_deactivated.sql +38 -0
  881. synapse/storage/schema/main/delta/56/add_spans_to_device_lists.sql +39 -0
  882. synapse/storage/schema/main/delta/56/current_state_events_membership.sql +41 -0
  883. synapse/storage/schema/main/delta/56/current_state_events_membership_mk2.sql +43 -0
  884. synapse/storage/schema/main/delta/56/delete_keys_from_deleted_backups.sql +44 -0
  885. synapse/storage/schema/main/delta/56/destinations_failure_ts.sql +44 -0
  886. synapse/storage/schema/main/delta/56/destinations_retry_interval_type.sql.postgres +18 -0
  887. synapse/storage/schema/main/delta/56/device_stream_id_insert.sql +39 -0
  888. synapse/storage/schema/main/delta/56/devices_last_seen.sql +43 -0
  889. synapse/storage/schema/main/delta/56/drop_unused_event_tables.sql +39 -0
  890. synapse/storage/schema/main/delta/56/event_expiry.sql +40 -0
  891. synapse/storage/schema/main/delta/56/event_labels.sql +49 -0
  892. synapse/storage/schema/main/delta/56/event_labels_background_update.sql +36 -0
  893. synapse/storage/schema/main/delta/56/fix_room_keys_index.sql +37 -0
  894. synapse/storage/schema/main/delta/56/hidden_devices.sql +37 -0
  895. synapse/storage/schema/main/delta/56/hidden_devices_fix.sql.sqlite +42 -0
  896. synapse/storage/schema/main/delta/56/nuke_empty_communities_from_db.sql +48 -0
  897. synapse/storage/schema/main/delta/56/public_room_list_idx.sql +35 -0
  898. synapse/storage/schema/main/delta/56/redaction_censor.sql +35 -0
  899. synapse/storage/schema/main/delta/56/redaction_censor2.sql +41 -0
  900. synapse/storage/schema/main/delta/56/redaction_censor3_fix_update.sql.postgres +25 -0
  901. synapse/storage/schema/main/delta/56/redaction_censor4.sql +35 -0
  902. synapse/storage/schema/main/delta/56/remove_tombstoned_rooms_from_directory.sql +38 -0
  903. synapse/storage/schema/main/delta/56/room_key_etag.sql +36 -0
  904. synapse/storage/schema/main/delta/56/room_membership_idx.sql +37 -0
  905. synapse/storage/schema/main/delta/56/room_retention.sql +52 -0
  906. synapse/storage/schema/main/delta/56/signing_keys.sql +75 -0
  907. synapse/storage/schema/main/delta/56/signing_keys_nonunique_signatures.sql +41 -0
  908. synapse/storage/schema/main/delta/56/stats_separated.sql +175 -0
  909. synapse/storage/schema/main/delta/56/unique_user_filter_index.py +46 -0
  910. synapse/storage/schema/main/delta/56/user_external_ids.sql +43 -0
  911. synapse/storage/schema/main/delta/56/users_in_public_rooms_idx.sql +36 -0
  912. synapse/storage/schema/main/delta/57/delete_old_current_state_events.sql +41 -0
  913. synapse/storage/schema/main/delta/57/device_list_remote_cache_stale.sql +44 -0
  914. synapse/storage/schema/main/delta/57/local_current_membership.py +111 -0
  915. synapse/storage/schema/main/delta/57/remove_sent_outbound_pokes.sql +40 -0
  916. synapse/storage/schema/main/delta/57/rooms_version_column.sql +43 -0
  917. synapse/storage/schema/main/delta/57/rooms_version_column_2.sql.postgres +35 -0
  918. synapse/storage/schema/main/delta/57/rooms_version_column_2.sql.sqlite +22 -0
  919. synapse/storage/schema/main/delta/57/rooms_version_column_3.sql.postgres +39 -0
  920. synapse/storage/schema/main/delta/57/rooms_version_column_3.sql.sqlite +23 -0
  921. synapse/storage/schema/main/delta/58/02remove_dup_outbound_pokes.sql +41 -0
  922. synapse/storage/schema/main/delta/58/03persist_ui_auth.sql +55 -0
  923. synapse/storage/schema/main/delta/58/05cache_instance.sql.postgres +30 -0
  924. synapse/storage/schema/main/delta/58/06dlols_unique_idx.py +83 -0
  925. synapse/storage/schema/main/delta/58/07add_method_to_thumbnail_constraint.sql.postgres +33 -0
  926. synapse/storage/schema/main/delta/58/07add_method_to_thumbnail_constraint.sql.sqlite +44 -0
  927. synapse/storage/schema/main/delta/58/07persist_ui_auth_ips.sql +44 -0
  928. synapse/storage/schema/main/delta/58/08_media_safe_from_quarantine.sql.postgres +18 -0
  929. synapse/storage/schema/main/delta/58/08_media_safe_from_quarantine.sql.sqlite +18 -0
  930. synapse/storage/schema/main/delta/58/09shadow_ban.sql +37 -0
  931. synapse/storage/schema/main/delta/58/10_pushrules_enabled_delete_obsolete.sql +47 -0
  932. synapse/storage/schema/main/delta/58/10drop_local_rejections_stream.sql +41 -0
  933. synapse/storage/schema/main/delta/58/10federation_pos_instance_name.sql +41 -0
  934. synapse/storage/schema/main/delta/58/11dehydration.sql +39 -0
  935. synapse/storage/schema/main/delta/58/11fallback.sql +43 -0
  936. synapse/storage/schema/main/delta/58/11user_id_seq.py +38 -0
  937. synapse/storage/schema/main/delta/58/12room_stats.sql +51 -0
  938. synapse/storage/schema/main/delta/58/13remove_presence_allow_inbound.sql +36 -0
  939. synapse/storage/schema/main/delta/58/14events_instance_name.sql +35 -0
  940. synapse/storage/schema/main/delta/58/14events_instance_name.sql.postgres +28 -0
  941. synapse/storage/schema/main/delta/58/15_catchup_destination_rooms.sql +61 -0
  942. synapse/storage/schema/main/delta/58/15unread_count.sql +45 -0
  943. synapse/storage/schema/main/delta/58/16populate_stats_process_rooms_fix.sql +41 -0
  944. synapse/storage/schema/main/delta/58/17_catchup_last_successful.sql +40 -0
  945. synapse/storage/schema/main/delta/58/18stream_positions.sql +41 -0
  946. synapse/storage/schema/main/delta/58/19instance_map.sql.postgres +25 -0
  947. synapse/storage/schema/main/delta/58/19txn_id.sql +59 -0
  948. synapse/storage/schema/main/delta/58/20instance_name_event_tables.sql +36 -0
  949. synapse/storage/schema/main/delta/58/20user_daily_visits.sql +37 -0
  950. synapse/storage/schema/main/delta/58/21as_device_stream.sql +36 -0
  951. synapse/storage/schema/main/delta/58/21drop_device_max_stream_id.sql +1 -0
  952. synapse/storage/schema/main/delta/58/22puppet_token.sql +36 -0
  953. synapse/storage/schema/main/delta/58/22users_have_local_media.sql +2 -0
  954. synapse/storage/schema/main/delta/58/23e2e_cross_signing_keys_idx.sql +36 -0
  955. synapse/storage/schema/main/delta/58/24drop_event_json_index.sql +38 -0
  956. synapse/storage/schema/main/delta/58/25user_external_ids_user_id_idx.sql +36 -0
  957. synapse/storage/schema/main/delta/58/26access_token_last_validated.sql +37 -0
  958. synapse/storage/schema/main/delta/58/27local_invites.sql +37 -0
  959. synapse/storage/schema/main/delta/58/28drop_last_used_column.sql.postgres +16 -0
  960. synapse/storage/schema/main/delta/58/28drop_last_used_column.sql.sqlite +62 -0
  961. synapse/storage/schema/main/delta/59/01ignored_user.py +85 -0
  962. synapse/storage/schema/main/delta/59/02shard_send_to_device.sql +37 -0
  963. synapse/storage/schema/main/delta/59/03shard_send_to_device_sequence.sql.postgres +25 -0
  964. synapse/storage/schema/main/delta/59/04_event_auth_chains.sql +71 -0
  965. synapse/storage/schema/main/delta/59/04_event_auth_chains.sql.postgres +16 -0
  966. synapse/storage/schema/main/delta/59/04drop_account_data.sql +36 -0
  967. synapse/storage/schema/main/delta/59/05cache_invalidation.sql +36 -0
  968. synapse/storage/schema/main/delta/59/06chain_cover_index.sql +36 -0
  969. synapse/storage/schema/main/delta/59/06shard_account_data.sql +39 -0
  970. synapse/storage/schema/main/delta/59/06shard_account_data.sql.postgres +32 -0
  971. synapse/storage/schema/main/delta/59/07shard_account_data_fix.sql +37 -0
  972. synapse/storage/schema/main/delta/59/08delete_pushers_for_deactivated_accounts.sql +39 -0
  973. synapse/storage/schema/main/delta/59/08delete_stale_pushers.sql +39 -0
  974. synapse/storage/schema/main/delta/59/09rejected_events_metadata.sql +45 -0
  975. synapse/storage/schema/main/delta/59/10delete_purged_chain_cover.sql +36 -0
  976. synapse/storage/schema/main/delta/59/11add_knock_members_to_stats.sql +39 -0
  977. synapse/storage/schema/main/delta/59/11drop_thumbnail_constraint.sql.postgres +22 -0
  978. synapse/storage/schema/main/delta/59/12account_validity_token_used_ts_ms.sql +37 -0
  979. synapse/storage/schema/main/delta/59/12presence_stream_instance.sql +37 -0
  980. synapse/storage/schema/main/delta/59/12presence_stream_instance_seq.sql.postgres +20 -0
  981. synapse/storage/schema/main/delta/59/13users_to_send_full_presence_to.sql +53 -0
  982. synapse/storage/schema/main/delta/59/14refresh_tokens.sql +53 -0
  983. synapse/storage/schema/main/delta/59/15locks.sql +56 -0
  984. synapse/storage/schema/main/delta/59/16federation_inbound_staging.sql +51 -0
  985. synapse/storage/schema/main/delta/60/01recreate_stream_ordering.sql.postgres +45 -0
  986. synapse/storage/schema/main/delta/60/02change_stream_ordering_columns.sql.postgres +30 -0
  987. synapse/storage/schema/main/delta/61/01change_appservices_txns.sql.postgres +23 -0
  988. synapse/storage/schema/main/delta/61/01insertion_event_lookups.sql +68 -0
  989. synapse/storage/schema/main/delta/61/02drop_redundant_room_depth_index.sql +37 -0
  990. synapse/storage/schema/main/delta/61/03recreate_min_depth.py +74 -0
  991. synapse/storage/schema/main/delta/62/01insertion_event_extremities.sql +43 -0
  992. synapse/storage/schema/main/delta/63/01create_registration_tokens.sql +42 -0
  993. synapse/storage/schema/main/delta/63/02delete_unlinked_email_pushers.sql +39 -0
  994. synapse/storage/schema/main/delta/63/02populate-rooms-creator.sql +36 -0
  995. synapse/storage/schema/main/delta/63/03session_store.sql +42 -0
  996. synapse/storage/schema/main/delta/63/04add_presence_stream_not_offline_index.sql +37 -0
  997. synapse/storage/schema/main/delta/64/01msc2716_chunk_to_batch_rename.sql.postgres +23 -0
  998. synapse/storage/schema/main/delta/64/01msc2716_chunk_to_batch_rename.sql.sqlite +37 -0
  999. synapse/storage/schema/main/delta/65/01msc2716_insertion_event_edges.sql +38 -0
  1000. synapse/storage/schema/main/delta/65/03remove_hidden_devices_from_device_inbox.sql +41 -0
  1001. synapse/storage/schema/main/delta/65/04_local_group_updates.sql +37 -0
  1002. synapse/storage/schema/main/delta/65/05_remove_room_stats_historical_and_user_stats_historical.sql +38 -0
  1003. synapse/storage/schema/main/delta/65/06remove_deleted_devices_from_device_inbox.sql +53 -0
  1004. synapse/storage/schema/main/delta/65/07_arbitrary_relations.sql +37 -0
  1005. synapse/storage/schema/main/delta/65/08_device_inbox_background_updates.sql +37 -0
  1006. synapse/storage/schema/main/delta/65/10_expirable_refresh_tokens.sql +47 -0
  1007. synapse/storage/schema/main/delta/65/11_devices_auth_provider_session.sql +46 -0
  1008. synapse/storage/schema/main/delta/67/01drop_public_room_list_stream.sql +37 -0
  1009. synapse/storage/schema/main/delta/68/01event_columns.sql +45 -0
  1010. synapse/storage/schema/main/delta/68/02_msc2409_add_device_id_appservice_stream_type.sql +40 -0
  1011. synapse/storage/schema/main/delta/68/03_delete_account_data_for_deactivated_accounts.sql +39 -0
  1012. synapse/storage/schema/main/delta/68/04_refresh_tokens_index_next_token_id.sql +47 -0
  1013. synapse/storage/schema/main/delta/68/04partial_state_rooms.sql +60 -0
  1014. synapse/storage/schema/main/delta/68/05_delete_non_strings_from_event_search.sql.sqlite +22 -0
  1015. synapse/storage/schema/main/delta/68/05partial_state_rooms_triggers.py +80 -0
  1016. synapse/storage/schema/main/delta/68/06_msc3202_add_device_list_appservice_stream_type.sql +42 -0
  1017. synapse/storage/schema/main/delta/69/01as_txn_seq.py +54 -0
  1018. synapse/storage/schema/main/delta/69/01device_list_oubound_by_room.sql +57 -0
  1019. synapse/storage/schema/main/delta/69/02cache_invalidation_index.sql +37 -0
  1020. synapse/storage/schema/main/delta/70/01clean_table_purged_rooms.sql +39 -0
  1021. synapse/storage/schema/main/delta/71/01rebuild_event_edges.sql.postgres +43 -0
  1022. synapse/storage/schema/main/delta/71/01rebuild_event_edges.sql.sqlite +47 -0
  1023. synapse/storage/schema/main/delta/71/01remove_noop_background_updates.sql +80 -0
  1024. synapse/storage/schema/main/delta/71/02event_push_summary_unique.sql +37 -0
  1025. synapse/storage/schema/main/delta/72/01add_room_type_to_state_stats.sql +38 -0
  1026. synapse/storage/schema/main/delta/72/01event_push_summary_receipt.sql +54 -0
  1027. synapse/storage/schema/main/delta/72/02event_push_actions_index.sql +38 -0
  1028. synapse/storage/schema/main/delta/72/03bg_populate_events_columns.py +57 -0
  1029. synapse/storage/schema/main/delta/72/03drop_event_reference_hashes.sql +36 -0
  1030. synapse/storage/schema/main/delta/72/03remove_groups.sql +50 -0
  1031. synapse/storage/schema/main/delta/72/04drop_column_application_services_state_last_txn.sql.postgres +17 -0
  1032. synapse/storage/schema/main/delta/72/04drop_column_application_services_state_last_txn.sql.sqlite +40 -0
  1033. synapse/storage/schema/main/delta/72/05receipts_event_stream_ordering.sql +38 -0
  1034. synapse/storage/schema/main/delta/72/05remove_unstable_private_read_receipts.sql +38 -0
  1035. synapse/storage/schema/main/delta/72/06add_consent_ts_to_users.sql +35 -0
  1036. synapse/storage/schema/main/delta/72/06thread_notifications.sql +49 -0
  1037. synapse/storage/schema/main/delta/72/07force_update_current_state_events_membership.py +67 -0
  1038. synapse/storage/schema/main/delta/72/07thread_receipts.sql.postgres +30 -0
  1039. synapse/storage/schema/main/delta/72/07thread_receipts.sql.sqlite +70 -0
  1040. synapse/storage/schema/main/delta/72/08begin_cache_invalidation_seq_at_2.sql.postgres +23 -0
  1041. synapse/storage/schema/main/delta/72/08thread_receipts.sql +39 -0
  1042. synapse/storage/schema/main/delta/72/09partial_indices.sql.sqlite +56 -0
  1043. synapse/storage/schema/main/delta/73/01event_failed_pull_attempts.sql +48 -0
  1044. synapse/storage/schema/main/delta/73/02add_pusher_enabled.sql +35 -0
  1045. synapse/storage/schema/main/delta/73/02room_id_indexes_for_purging.sql +41 -0
  1046. synapse/storage/schema/main/delta/73/03pusher_device_id.sql +39 -0
  1047. synapse/storage/schema/main/delta/73/03users_approved_column.sql +39 -0
  1048. synapse/storage/schema/main/delta/73/04partial_join_details.sql +42 -0
  1049. synapse/storage/schema/main/delta/73/04pending_device_list_updates.sql +47 -0
  1050. synapse/storage/schema/main/delta/73/05old_push_actions.sql.postgres +22 -0
  1051. synapse/storage/schema/main/delta/73/05old_push_actions.sql.sqlite +24 -0
  1052. synapse/storage/schema/main/delta/73/06thread_notifications_thread_id_idx.sql +42 -0
  1053. synapse/storage/schema/main/delta/73/08thread_receipts_non_null.sql.postgres +23 -0
  1054. synapse/storage/schema/main/delta/73/08thread_receipts_non_null.sql.sqlite +76 -0
  1055. synapse/storage/schema/main/delta/73/09partial_joined_via_destination.sql +37 -0
  1056. synapse/storage/schema/main/delta/73/09threads_table.sql +49 -0
  1057. synapse/storage/schema/main/delta/73/10_update_sqlite_fts4_tokenizer.py +71 -0
  1058. synapse/storage/schema/main/delta/73/10login_tokens.sql +54 -0
  1059. synapse/storage/schema/main/delta/73/11event_search_room_id_n_distinct.sql.postgres +33 -0
  1060. synapse/storage/schema/main/delta/73/12refactor_device_list_outbound_pokes.sql +72 -0
  1061. synapse/storage/schema/main/delta/73/13add_device_lists_index.sql +39 -0
  1062. synapse/storage/schema/main/delta/73/20_un_partial_stated_room_stream.sql +51 -0
  1063. synapse/storage/schema/main/delta/73/21_un_partial_stated_room_stream_seq.sql.postgres +20 -0
  1064. synapse/storage/schema/main/delta/73/22_rebuild_user_dir_stats.sql +48 -0
  1065. synapse/storage/schema/main/delta/73/22_un_partial_stated_event_stream.sql +53 -0
  1066. synapse/storage/schema/main/delta/73/23_fix_thread_index.sql +52 -0
  1067. synapse/storage/schema/main/delta/73/23_un_partial_stated_room_stream_seq.sql.postgres +20 -0
  1068. synapse/storage/schema/main/delta/73/24_events_jump_to_date_index.sql +36 -0
  1069. synapse/storage/schema/main/delta/73/25drop_presence.sql +36 -0
  1070. synapse/storage/schema/main/delta/74/01_user_directory_stale_remote_users.sql +58 -0
  1071. synapse/storage/schema/main/delta/74/02_set_device_id_for_pushers_bg_update.sql +38 -0
  1072. synapse/storage/schema/main/delta/74/03_membership_tables_event_stream_ordering.sql.postgres +29 -0
  1073. synapse/storage/schema/main/delta/74/03_membership_tables_event_stream_ordering.sql.sqlite +23 -0
  1074. synapse/storage/schema/main/delta/74/03_room_membership_index.sql +38 -0
  1075. synapse/storage/schema/main/delta/74/04_delete_e2e_backup_keys_for_deactivated_users.sql +36 -0
  1076. synapse/storage/schema/main/delta/74/04_membership_tables_event_stream_ordering_triggers.py +87 -0
  1077. synapse/storage/schema/main/delta/74/05_events_txn_id_device_id.sql +72 -0
  1078. synapse/storage/schema/main/delta/74/90COMMENTS_destinations.sql.postgres +52 -0
  1079. synapse/storage/schema/main/delta/76/01_add_profiles_full_user_id_column.sql +39 -0
  1080. synapse/storage/schema/main/delta/76/02_add_user_filters_full_user_id_column.sql +39 -0
  1081. synapse/storage/schema/main/delta/76/03_per_user_experimental_features.sql +46 -0
  1082. synapse/storage/schema/main/delta/76/04_add_room_forgetter.sql +43 -0
  1083. synapse/storage/schema/main/delta/77/01_add_profiles_not_valid_check.sql.postgres +16 -0
  1084. synapse/storage/schema/main/delta/77/02_add_user_filters_not_valid_check.sql.postgres +16 -0
  1085. synapse/storage/schema/main/delta/77/03bg_populate_full_user_id_profiles.sql +35 -0
  1086. synapse/storage/schema/main/delta/77/04bg_populate_full_user_id_user_filters.sql +35 -0
  1087. synapse/storage/schema/main/delta/77/05thread_notifications_backfill.sql +67 -0
  1088. synapse/storage/schema/main/delta/77/06thread_notifications_not_null.sql.sqlite +102 -0
  1089. synapse/storage/schema/main/delta/77/06thread_notifications_not_null_event_push_actions.sql.postgres +27 -0
  1090. synapse/storage/schema/main/delta/77/06thread_notifications_not_null_event_push_actions_staging.sql.postgres +27 -0
  1091. synapse/storage/schema/main/delta/77/06thread_notifications_not_null_event_push_summary.sql.postgres +29 -0
  1092. synapse/storage/schema/main/delta/77/14bg_indices_event_stream_ordering.sql +39 -0
  1093. synapse/storage/schema/main/delta/78/01_validate_and_update_profiles.py +99 -0
  1094. synapse/storage/schema/main/delta/78/02_validate_and_update_user_filters.py +100 -0
  1095. synapse/storage/schema/main/delta/78/03_remove_unused_indexes_user_filters.py +72 -0
  1096. synapse/storage/schema/main/delta/78/03event_extremities_constraints.py +65 -0
  1097. synapse/storage/schema/main/delta/78/04_add_full_user_id_index_user_filters.py +32 -0
  1098. synapse/storage/schema/main/delta/79/03_read_write_locks_triggers.sql.postgres +102 -0
  1099. synapse/storage/schema/main/delta/79/03_read_write_locks_triggers.sql.sqlite +72 -0
  1100. synapse/storage/schema/main/delta/79/04_mitigate_stream_ordering_update_race.py +70 -0
  1101. synapse/storage/schema/main/delta/79/05_read_write_locks_triggers.sql.postgres +69 -0
  1102. synapse/storage/schema/main/delta/79/05_read_write_locks_triggers.sql.sqlite +65 -0
  1103. synapse/storage/schema/main/delta/80/01_users_alter_locked.sql +35 -0
  1104. synapse/storage/schema/main/delta/80/02_read_write_locks_unlogged.sql.postgres +30 -0
  1105. synapse/storage/schema/main/delta/80/02_scheduled_tasks.sql +47 -0
  1106. synapse/storage/schema/main/delta/80/03_read_write_locks_triggers.sql.postgres +37 -0
  1107. synapse/storage/schema/main/delta/80/04_read_write_locks_deadlock.sql.postgres +71 -0
  1108. synapse/storage/schema/main/delta/82/02_scheduled_tasks_index.sql +35 -0
  1109. synapse/storage/schema/main/delta/82/04_add_indices_for_purging_rooms.sql +39 -0
  1110. synapse/storage/schema/main/delta/82/05gaps.sql +44 -0
  1111. synapse/storage/schema/main/delta/83/01_drop_old_tables.sql +43 -0
  1112. synapse/storage/schema/main/delta/83/03_instance_name_receipts.sql.sqlite +17 -0
  1113. synapse/storage/schema/main/delta/83/05_cross_signing_key_update_grant.sql +34 -0
  1114. synapse/storage/schema/main/delta/83/06_event_push_summary_room.sql +36 -0
  1115. synapse/storage/schema/main/delta/84/01_auth_links_stats.sql.postgres +20 -0
  1116. synapse/storage/schema/main/delta/84/02_auth_links_index.sql +16 -0
  1117. synapse/storage/schema/main/delta/84/03_auth_links_analyze.sql.postgres +16 -0
  1118. synapse/storage/schema/main/delta/84/04_access_token_index.sql +15 -0
  1119. synapse/storage/schema/main/delta/85/01_add_suspended.sql +14 -0
  1120. synapse/storage/schema/main/delta/85/02_add_instance_names.sql +27 -0
  1121. synapse/storage/schema/main/delta/85/03_new_sequences.sql.postgres +54 -0
  1122. synapse/storage/schema/main/delta/85/04_cleanup_device_federation_outbox.sql +15 -0
  1123. synapse/storage/schema/main/delta/85/05_add_instance_names_converted_pos.sql +16 -0
  1124. synapse/storage/schema/main/delta/85/06_add_room_reports.sql +20 -0
  1125. synapse/storage/schema/main/delta/86/01_authenticate_media.sql +15 -0
  1126. synapse/storage/schema/main/delta/86/02_receipts_event_id_index.sql +15 -0
  1127. synapse/storage/schema/main/delta/87/01_sliding_sync_memberships.sql +169 -0
  1128. synapse/storage/schema/main/delta/87/02_per_connection_state.sql +81 -0
  1129. synapse/storage/schema/main/delta/87/03_current_state_index.sql +19 -0
  1130. synapse/storage/schema/main/delta/88/01_add_delayed_events.sql +43 -0
  1131. synapse/storage/schema/main/delta/88/01_custom_profile_fields.sql +15 -0
  1132. synapse/storage/schema/main/delta/88/02_fix_sliding_sync_membership_snapshots_forgotten_column.sql +21 -0
  1133. synapse/storage/schema/main/delta/88/03_add_otk_ts_added_index.sql +18 -0
  1134. synapse/storage/schema/main/delta/88/04_current_state_delta_index.sql +18 -0
  1135. synapse/storage/schema/main/delta/88/05_drop_old_otks.sql.postgres +19 -0
  1136. synapse/storage/schema/main/delta/88/05_drop_old_otks.sql.sqlite +19 -0
  1137. synapse/storage/schema/main/delta/88/05_sliding_sync_room_config_index.sql +20 -0
  1138. synapse/storage/schema/main/delta/88/06_events_received_ts_index.sql +17 -0
  1139. synapse/storage/schema/main/delta/89/01_sliding_sync_membership_snapshot_index.sql +15 -0
  1140. synapse/storage/schema/main/delta/90/01_add_column_participant_room_memberships_table.sql +16 -0
  1141. synapse/storage/schema/main/delta/91/01_media_hash.sql +28 -0
  1142. synapse/storage/schema/main/delta/92/01_remove_trigger.sql.postgres +16 -0
  1143. synapse/storage/schema/main/delta/92/01_remove_trigger.sql.sqlite +16 -0
  1144. synapse/storage/schema/main/delta/92/02_remove_populate_participant_bg_update.sql +17 -0
  1145. synapse/storage/schema/main/delta/92/04_ss_membership_snapshot_idx.sql +16 -0
  1146. synapse/storage/schema/main/delta/92/04_thread_subscriptions.sql +59 -0
  1147. synapse/storage/schema/main/delta/92/04_thread_subscriptions_seq.sql.postgres +19 -0
  1148. synapse/storage/schema/main/delta/92/05_fixup_max_depth_cap.sql +17 -0
  1149. synapse/storage/schema/main/delta/92/05_thread_subscriptions_comments.sql.postgres +18 -0
  1150. synapse/storage/schema/main/delta/92/06_device_federation_inbox_index.sql +16 -0
  1151. synapse/storage/schema/main/delta/92/06_threads_last_sent_stream_ordering_comments.sql.postgres +24 -0
  1152. synapse/storage/schema/main/delta/92/07_add_user_reports.sql +22 -0
  1153. synapse/storage/schema/main/delta/92/07_event_txn_id_device_id_txn_id2.sql +15 -0
  1154. synapse/storage/schema/main/delta/92/08_room_ban_redactions.sql +21 -0
  1155. synapse/storage/schema/main/delta/92/08_thread_subscriptions_seq_fixup.sql.postgres +19 -0
  1156. synapse/storage/schema/main/delta/92/09_thread_subscriptions_update.sql +20 -0
  1157. synapse/storage/schema/main/delta/92/09_thread_subscriptions_update.sql.postgres +18 -0
  1158. synapse/storage/schema/main/delta/93/01_add_delayed_events.sql +15 -0
  1159. synapse/storage/schema/main/delta/93/02_sliding_sync_members.sql +60 -0
  1160. synapse/storage/schema/main/delta/93/03_sss_pos_last_used.sql +27 -0
  1161. synapse/storage/schema/main/full_schemas/72/full.sql.postgres +1344 -0
  1162. synapse/storage/schema/main/full_schemas/72/full.sql.sqlite +646 -0
  1163. synapse/storage/schema/state/delta/23/drop_state_index.sql +35 -0
  1164. synapse/storage/schema/state/delta/32/remove_state_indices.sql +38 -0
  1165. synapse/storage/schema/state/delta/35/add_state_index.sql +36 -0
  1166. synapse/storage/schema/state/delta/35/state.sql +41 -0
  1167. synapse/storage/schema/state/delta/35/state_dedupe.sql +36 -0
  1168. synapse/storage/schema/state/delta/47/state_group_seq.py +38 -0
  1169. synapse/storage/schema/state/delta/56/state_group_room_idx.sql +36 -0
  1170. synapse/storage/schema/state/delta/61/02state_groups_state_n_distinct.sql.postgres +34 -0
  1171. synapse/storage/schema/state/delta/70/08_state_group_edges_unique.sql +36 -0
  1172. synapse/storage/schema/state/delta/89/01_state_groups_deletion.sql +39 -0
  1173. synapse/storage/schema/state/delta/90/02_delete_unreferenced_state_groups.sql +16 -0
  1174. synapse/storage/schema/state/delta/90/03_remove_old_deletion_bg_update.sql +15 -0
  1175. synapse/storage/schema/state/full_schemas/72/full.sql.postgres +30 -0
  1176. synapse/storage/schema/state/full_schemas/72/full.sql.sqlite +20 -0
  1177. synapse/storage/types.py +183 -0
  1178. synapse/storage/util/__init__.py +20 -0
  1179. synapse/storage/util/id_generators.py +928 -0
  1180. synapse/storage/util/partial_state_events_tracker.py +194 -0
  1181. synapse/storage/util/sequence.py +315 -0
  1182. synapse/streams/__init__.py +43 -0
  1183. synapse/streams/config.py +91 -0
  1184. synapse/streams/events.py +203 -0
  1185. synapse/synapse_rust/__init__.pyi +3 -0
  1186. synapse/synapse_rust/acl.pyi +20 -0
  1187. synapse/synapse_rust/events.pyi +136 -0
  1188. synapse/synapse_rust/http_client.pyi +32 -0
  1189. synapse/synapse_rust/push.pyi +86 -0
  1190. synapse/synapse_rust/rendezvous.pyi +30 -0
  1191. synapse/synapse_rust/segmenter.pyi +1 -0
  1192. synapse/synapse_rust.abi3.so +0 -0
  1193. synapse/types/__init__.py +1600 -0
  1194. synapse/types/handlers/__init__.py +93 -0
  1195. synapse/types/handlers/policy_server.py +16 -0
  1196. synapse/types/handlers/sliding_sync.py +1004 -0
  1197. synapse/types/rest/__init__.py +25 -0
  1198. synapse/types/rest/client/__init__.py +413 -0
  1199. synapse/types/state.py +634 -0
  1200. synapse/types/storage/__init__.py +66 -0
  1201. synapse/util/__init__.py +160 -0
  1202. synapse/util/async_helpers.py +1048 -0
  1203. synapse/util/background_queue.py +142 -0
  1204. synapse/util/batching_queue.py +203 -0
  1205. synapse/util/caches/__init__.py +300 -0
  1206. synapse/util/caches/cached_call.py +143 -0
  1207. synapse/util/caches/deferred_cache.py +530 -0
  1208. synapse/util/caches/descriptors.py +692 -0
  1209. synapse/util/caches/dictionary_cache.py +346 -0
  1210. synapse/util/caches/expiringcache.py +250 -0
  1211. synapse/util/caches/lrucache.py +976 -0
  1212. synapse/util/caches/response_cache.py +323 -0
  1213. synapse/util/caches/stream_change_cache.py +370 -0
  1214. synapse/util/caches/treecache.py +189 -0
  1215. synapse/util/caches/ttlcache.py +197 -0
  1216. synapse/util/cancellation.py +63 -0
  1217. synapse/util/check_dependencies.py +335 -0
  1218. synapse/util/clock.py +592 -0
  1219. synapse/util/daemonize.py +165 -0
  1220. synapse/util/distributor.py +157 -0
  1221. synapse/util/duration.py +117 -0
  1222. synapse/util/events.py +134 -0
  1223. synapse/util/file_consumer.py +164 -0
  1224. synapse/util/frozenutils.py +57 -0
  1225. synapse/util/gai_resolver.py +178 -0
  1226. synapse/util/hash.py +38 -0
  1227. synapse/util/httpresourcetree.py +108 -0
  1228. synapse/util/iterutils.py +190 -0
  1229. synapse/util/json.py +56 -0
  1230. synapse/util/linked_list.py +156 -0
  1231. synapse/util/logcontext.py +46 -0
  1232. synapse/util/logformatter.py +28 -0
  1233. synapse/util/macaroons.py +325 -0
  1234. synapse/util/manhole.py +191 -0
  1235. synapse/util/metrics.py +339 -0
  1236. synapse/util/module_loader.py +116 -0
  1237. synapse/util/msisdn.py +51 -0
  1238. synapse/util/patch_inline_callbacks.py +250 -0
  1239. synapse/util/pydantic_models.py +63 -0
  1240. synapse/util/ratelimitutils.py +422 -0
  1241. synapse/util/retryutils.py +339 -0
  1242. synapse/util/rlimit.py +42 -0
  1243. synapse/util/rust.py +164 -0
  1244. synapse/util/sentinel.py +21 -0
  1245. synapse/util/stringutils.py +293 -0
  1246. synapse/util/task_scheduler.py +494 -0
  1247. synapse/util/templates.py +126 -0
  1248. synapse/util/threepids.py +123 -0
  1249. synapse/util/wheel_timer.py +112 -0
  1250. synapse/visibility.py +869 -0
  1251. synmark/__init__.py +47 -0
  1252. synmark/__main__.py +128 -0
  1253. synmark/suites/__init__.py +9 -0
  1254. synmark/suites/logging.py +154 -0
  1255. synmark/suites/lrucache.py +48 -0
  1256. synmark/suites/lrucache_evict.py +49 -0
  1257. sytest-blacklist +33 -0
  1258. tests/__init__.py +29 -0
  1259. tests/api/__init__.py +0 -0
  1260. tests/api/test_auth.py +548 -0
  1261. tests/api/test_errors.py +46 -0
  1262. tests/api/test_filtering.py +622 -0
  1263. tests/api/test_ratelimiting.py +505 -0
  1264. tests/api/test_urls.py +81 -0
  1265. tests/app/__init__.py +0 -0
  1266. tests/app/test_homeserver_shutdown.py +271 -0
  1267. tests/app/test_homeserver_start.py +49 -0
  1268. tests/app/test_openid_listener.py +139 -0
  1269. tests/app/test_phone_stats_home.py +248 -0
  1270. tests/appservice/__init__.py +20 -0
  1271. tests/appservice/test_api.py +253 -0
  1272. tests/appservice/test_appservice.py +259 -0
  1273. tests/appservice/test_scheduler.py +477 -0
  1274. tests/config/__init__.py +20 -0
  1275. tests/config/test___main__.py +38 -0
  1276. tests/config/test_api.py +146 -0
  1277. tests/config/test_appservice.py +48 -0
  1278. tests/config/test_background_update.py +65 -0
  1279. tests/config/test_base.py +151 -0
  1280. tests/config/test_cache.py +193 -0
  1281. tests/config/test_database.py +42 -0
  1282. tests/config/test_generate.py +72 -0
  1283. tests/config/test_load.py +322 -0
  1284. tests/config/test_oauth_delegation.py +454 -0
  1285. tests/config/test_ratelimiting.py +77 -0
  1286. tests/config/test_registration_config.py +203 -0
  1287. tests/config/test_room_directory.py +203 -0
  1288. tests/config/test_server.py +248 -0
  1289. tests/config/test_tls.py +209 -0
  1290. tests/config/test_util.py +59 -0
  1291. tests/config/test_workers.py +332 -0
  1292. tests/config/utils.py +66 -0
  1293. tests/crypto/__init__.py +20 -0
  1294. tests/crypto/test_event_signing.py +109 -0
  1295. tests/crypto/test_keyring.py +737 -0
  1296. tests/events/__init__.py +0 -0
  1297. tests/events/test_auto_accept_invites.py +827 -0
  1298. tests/events/test_presence_router.py +540 -0
  1299. tests/events/test_snapshot.py +121 -0
  1300. tests/events/test_utils.py +986 -0
  1301. tests/federation/__init__.py +0 -0
  1302. tests/federation/test_complexity.py +257 -0
  1303. tests/federation/test_federation_catch_up.py +585 -0
  1304. tests/federation/test_federation_client.py +316 -0
  1305. tests/federation/test_federation_devices.py +161 -0
  1306. tests/federation/test_federation_media.py +295 -0
  1307. tests/federation/test_federation_out_of_band_membership.py +671 -0
  1308. tests/federation/test_federation_sender.py +956 -0
  1309. tests/federation/test_federation_server.py +631 -0
  1310. tests/federation/transport/__init__.py +0 -0
  1311. tests/federation/transport/server/__init__.py +20 -0
  1312. tests/federation/transport/server/test__base.py +156 -0
  1313. tests/federation/transport/test_client.py +157 -0
  1314. tests/federation/transport/test_knocking.py +323 -0
  1315. tests/federation/transport/test_server.py +74 -0
  1316. tests/handlers/__init__.py +0 -0
  1317. tests/handlers/oidc_test_key.p8 +5 -0
  1318. tests/handlers/oidc_test_key.pub.pem +4 -0
  1319. tests/handlers/test_admin.py +361 -0
  1320. tests/handlers/test_appservice.py +1336 -0
  1321. tests/handlers/test_auth.py +248 -0
  1322. tests/handlers/test_cas.py +239 -0
  1323. tests/handlers/test_deactivate_account.py +485 -0
  1324. tests/handlers/test_device.py +665 -0
  1325. tests/handlers/test_directory.py +613 -0
  1326. tests/handlers/test_e2e_keys.py +2025 -0
  1327. tests/handlers/test_e2e_room_keys.py +569 -0
  1328. tests/handlers/test_federation.py +794 -0
  1329. tests/handlers/test_federation_event.py +1181 -0
  1330. tests/handlers/test_message.py +322 -0
  1331. tests/handlers/test_oauth_delegation.py +1314 -0
  1332. tests/handlers/test_oidc.py +1688 -0
  1333. tests/handlers/test_password_providers.py +987 -0
  1334. tests/handlers/test_presence.py +2144 -0
  1335. tests/handlers/test_profile.py +401 -0
  1336. tests/handlers/test_receipts.py +342 -0
  1337. tests/handlers/test_register.py +880 -0
  1338. tests/handlers/test_room.py +108 -0
  1339. tests/handlers/test_room_list.py +93 -0
  1340. tests/handlers/test_room_member.py +764 -0
  1341. tests/handlers/test_room_policy.py +468 -0
  1342. tests/handlers/test_room_summary.py +1248 -0
  1343. tests/handlers/test_saml.py +427 -0
  1344. tests/handlers/test_send_email.py +230 -0
  1345. tests/handlers/test_sliding_sync.py +5065 -0
  1346. tests/handlers/test_sso.py +152 -0
  1347. tests/handlers/test_stats.py +594 -0
  1348. tests/handlers/test_sync.py +1275 -0
  1349. tests/handlers/test_typing.py +557 -0
  1350. tests/handlers/test_user_directory.py +1435 -0
  1351. tests/handlers/test_worker_lock.py +126 -0
  1352. tests/http/__init__.py +196 -0
  1353. tests/http/ca.crt +19 -0
  1354. tests/http/ca.key +27 -0
  1355. tests/http/federation/__init__.py +19 -0
  1356. tests/http/federation/test_matrix_federation_agent.py +1855 -0
  1357. tests/http/federation/test_srv_resolver.py +220 -0
  1358. tests/http/server/__init__.py +20 -0
  1359. tests/http/server/_base.py +621 -0
  1360. tests/http/server.key +27 -0
  1361. tests/http/test_additional_resource.py +76 -0
  1362. tests/http/test_client.py +422 -0
  1363. tests/http/test_endpoint.py +62 -0
  1364. tests/http/test_matrixfederationclient.py +1092 -0
  1365. tests/http/test_proxy.py +75 -0
  1366. tests/http/test_proxyagent.py +1008 -0
  1367. tests/http/test_servlet.py +145 -0
  1368. tests/http/test_simple_client.py +188 -0
  1369. tests/http/test_site.py +247 -0
  1370. tests/logging/__init__.py +42 -0
  1371. tests/logging/test_loggers.py +127 -0
  1372. tests/logging/test_opentracing.py +524 -0
  1373. tests/logging/test_remote_handler.py +184 -0
  1374. tests/logging/test_terse_json.py +253 -0
  1375. tests/media/__init__.py +20 -0
  1376. tests/media/test_base.py +88 -0
  1377. tests/media/test_filepath.py +602 -0
  1378. tests/media/test_html_preview.py +565 -0
  1379. tests/media/test_media_retention.py +299 -0
  1380. tests/media/test_media_storage.py +1401 -0
  1381. tests/media/test_oembed.py +172 -0
  1382. tests/media/test_url_previewer.py +120 -0
  1383. tests/metrics/__init__.py +0 -0
  1384. tests/metrics/test_background_process_metrics.py +21 -0
  1385. tests/metrics/test_metrics.py +407 -0
  1386. tests/metrics/test_phone_home_stats.py +263 -0
  1387. tests/module_api/__init__.py +0 -0
  1388. tests/module_api/test_account_data_manager.py +171 -0
  1389. tests/module_api/test_api.py +1035 -0
  1390. tests/module_api/test_event_unsigned_addition.py +66 -0
  1391. tests/module_api/test_spamchecker.py +286 -0
  1392. tests/push/__init__.py +0 -0
  1393. tests/push/test_bulk_push_rule_evaluator.py +652 -0
  1394. tests/push/test_email.py +570 -0
  1395. tests/push/test_http.py +1247 -0
  1396. tests/push/test_presentable_names.py +238 -0
  1397. tests/push/test_push_rule_evaluator.py +1069 -0
  1398. tests/replication/__init__.py +20 -0
  1399. tests/replication/_base.py +619 -0
  1400. tests/replication/http/__init__.py +20 -0
  1401. tests/replication/http/test__base.py +113 -0
  1402. tests/replication/storage/__init__.py +20 -0
  1403. tests/replication/storage/_base.py +85 -0
  1404. tests/replication/storage/test_events.py +299 -0
  1405. tests/replication/tcp/__init__.py +19 -0
  1406. tests/replication/tcp/streams/__init__.py +19 -0
  1407. tests/replication/tcp/streams/test_account_data.py +133 -0
  1408. tests/replication/tcp/streams/test_events.py +565 -0
  1409. tests/replication/tcp/streams/test_federation.py +117 -0
  1410. tests/replication/tcp/streams/test_partial_state.py +72 -0
  1411. tests/replication/tcp/streams/test_receipts.py +110 -0
  1412. tests/replication/tcp/streams/test_thread_subscriptions.py +157 -0
  1413. tests/replication/tcp/streams/test_to_device.py +112 -0
  1414. tests/replication/tcp/streams/test_typing.py +223 -0
  1415. tests/replication/tcp/test_commands.py +50 -0
  1416. tests/replication/tcp/test_handler.py +211 -0
  1417. tests/replication/test_auth.py +120 -0
  1418. tests/replication/test_client_reader_shard.py +101 -0
  1419. tests/replication/test_federation_ack.py +88 -0
  1420. tests/replication/test_federation_sender_shard.py +352 -0
  1421. tests/replication/test_module_cache_invalidation.py +89 -0
  1422. tests/replication/test_multi_media_repo.py +496 -0
  1423. tests/replication/test_pusher_shard.py +192 -0
  1424. tests/replication/test_sharded_event_persister.py +332 -0
  1425. tests/replication/test_sharded_receipts.py +250 -0
  1426. tests/rest/__init__.py +20 -0
  1427. tests/rest/admin/__init__.py +19 -0
  1428. tests/rest/admin/test_admin.py +614 -0
  1429. tests/rest/admin/test_background_updates.py +375 -0
  1430. tests/rest/admin/test_device.py +600 -0
  1431. tests/rest/admin/test_event.py +74 -0
  1432. tests/rest/admin/test_event_reports.py +781 -0
  1433. tests/rest/admin/test_federation.py +863 -0
  1434. tests/rest/admin/test_jwks.py +106 -0
  1435. tests/rest/admin/test_media.py +1091 -0
  1436. tests/rest/admin/test_registration_tokens.py +729 -0
  1437. tests/rest/admin/test_room.py +3626 -0
  1438. tests/rest/admin/test_scheduled_tasks.py +192 -0
  1439. tests/rest/admin/test_server_notice.py +753 -0
  1440. tests/rest/admin/test_statistics.py +523 -0
  1441. tests/rest/admin/test_user.py +6061 -0
  1442. tests/rest/admin/test_username_available.py +82 -0
  1443. tests/rest/client/__init__.py +20 -0
  1444. tests/rest/client/sliding_sync/__init__.py +13 -0
  1445. tests/rest/client/sliding_sync/test_connection_tracking.py +505 -0
  1446. tests/rest/client/sliding_sync/test_extension_account_data.py +1056 -0
  1447. tests/rest/client/sliding_sync/test_extension_e2ee.py +459 -0
  1448. tests/rest/client/sliding_sync/test_extension_receipts.py +934 -0
  1449. tests/rest/client/sliding_sync/test_extension_thread_subscriptions.py +497 -0
  1450. tests/rest/client/sliding_sync/test_extension_to_device.py +294 -0
  1451. tests/rest/client/sliding_sync/test_extension_typing.py +500 -0
  1452. tests/rest/client/sliding_sync/test_extensions.py +306 -0
  1453. tests/rest/client/sliding_sync/test_lists_filters.py +1975 -0
  1454. tests/rest/client/sliding_sync/test_room_subscriptions.py +303 -0
  1455. tests/rest/client/sliding_sync/test_rooms_invites.py +528 -0
  1456. tests/rest/client/sliding_sync/test_rooms_meta.py +1338 -0
  1457. tests/rest/client/sliding_sync/test_rooms_required_state.py +2247 -0
  1458. tests/rest/client/sliding_sync/test_rooms_timeline.py +718 -0
  1459. tests/rest/client/sliding_sync/test_sliding_sync.py +1688 -0
  1460. tests/rest/client/test_account.py +1543 -0
  1461. tests/rest/client/test_account_data.py +81 -0
  1462. tests/rest/client/test_auth.py +1508 -0
  1463. tests/rest/client/test_auth_metadata.py +145 -0
  1464. tests/rest/client/test_capabilities.py +318 -0
  1465. tests/rest/client/test_consent.py +138 -0
  1466. tests/rest/client/test_delayed_events.py +553 -0
  1467. tests/rest/client/test_devices.py +634 -0
  1468. tests/rest/client/test_directory.py +249 -0
  1469. tests/rest/client/test_ephemeral_message.py +113 -0
  1470. tests/rest/client/test_events.py +165 -0
  1471. tests/rest/client/test_filter.py +124 -0
  1472. tests/rest/client/test_identity.py +67 -0
  1473. tests/rest/client/test_keys.py +516 -0
  1474. tests/rest/client/test_login.py +1881 -0
  1475. tests/rest/client/test_login_token_request.py +175 -0
  1476. tests/rest/client/test_matrixrtc.py +105 -0
  1477. tests/rest/client/test_media.py +3156 -0
  1478. tests/rest/client/test_models.py +83 -0
  1479. tests/rest/client/test_mutual_rooms.py +235 -0
  1480. tests/rest/client/test_notifications.py +231 -0
  1481. tests/rest/client/test_owned_state.py +308 -0
  1482. tests/rest/client/test_password_policy.py +186 -0
  1483. tests/rest/client/test_power_levels.py +295 -0
  1484. tests/rest/client/test_presence.py +149 -0
  1485. tests/rest/client/test_profile.py +925 -0
  1486. tests/rest/client/test_push_rule_attrs.py +510 -0
  1487. tests/rest/client/test_read_marker.py +151 -0
  1488. tests/rest/client/test_receipts.py +287 -0
  1489. tests/rest/client/test_redactions.py +657 -0
  1490. tests/rest/client/test_register.py +1314 -0
  1491. tests/rest/client/test_relations.py +1954 -0
  1492. tests/rest/client/test_rendezvous.py +468 -0
  1493. tests/rest/client/test_reporting.py +324 -0
  1494. tests/rest/client/test_retention.py +389 -0
  1495. tests/rest/client/test_rooms.py +5486 -0
  1496. tests/rest/client/test_sendtodevice.py +271 -0
  1497. tests/rest/client/test_shadow_banned.py +335 -0
  1498. tests/rest/client/test_sync.py +1147 -0
  1499. tests/rest/client/test_tags.py +161 -0
  1500. tests/rest/client/test_third_party_rules.py +1076 -0
  1501. tests/rest/client/test_thread_subscriptions.py +351 -0
  1502. tests/rest/client/test_transactions.py +204 -0
  1503. tests/rest/client/test_typing.py +114 -0
  1504. tests/rest/client/test_upgrade_room.py +433 -0
  1505. tests/rest/client/utils.py +985 -0
  1506. tests/rest/key/__init__.py +0 -0
  1507. tests/rest/key/v2/__init__.py +0 -0
  1508. tests/rest/key/v2/test_remote_key_resource.py +282 -0
  1509. tests/rest/media/__init__.py +19 -0
  1510. tests/rest/media/test_domain_blocking.py +148 -0
  1511. tests/rest/media/test_url_preview.py +1445 -0
  1512. tests/rest/synapse/__init__.py +12 -0
  1513. tests/rest/synapse/client/__init__.py +12 -0
  1514. tests/rest/synapse/client/test_federation_whitelist.py +118 -0
  1515. tests/rest/synapse/mas/__init__.py +12 -0
  1516. tests/rest/synapse/mas/_base.py +43 -0
  1517. tests/rest/synapse/mas/test_devices.py +693 -0
  1518. tests/rest/synapse/mas/test_users.py +1399 -0
  1519. tests/rest/test_health.py +35 -0
  1520. tests/rest/test_well_known.py +155 -0
  1521. tests/scripts/__init__.py +0 -0
  1522. tests/scripts/test_new_matrix_user.py +172 -0
  1523. tests/server.py +1374 -0
  1524. tests/server_notices/__init__.py +241 -0
  1525. tests/server_notices/test_consent.py +111 -0
  1526. tests/server_notices/test_resource_limits_server_notices.py +409 -0
  1527. tests/state/__init__.py +0 -0
  1528. tests/state/test_v2.py +1096 -0
  1529. tests/state/test_v21.py +506 -0
  1530. tests/storage/__init__.py +0 -0
  1531. tests/storage/databases/__init__.py +20 -0
  1532. tests/storage/databases/main/__init__.py +20 -0
  1533. tests/storage/databases/main/test_cache.py +124 -0
  1534. tests/storage/databases/main/test_deviceinbox.py +323 -0
  1535. tests/storage/databases/main/test_end_to_end_keys.py +127 -0
  1536. tests/storage/databases/main/test_events_worker.py +594 -0
  1537. tests/storage/databases/main/test_lock.py +499 -0
  1538. tests/storage/databases/main/test_metrics.py +88 -0
  1539. tests/storage/databases/main/test_receipts.py +218 -0
  1540. tests/storage/databases/main/test_room.py +192 -0
  1541. tests/storage/test__base.py +178 -0
  1542. tests/storage/test_account_data.py +186 -0
  1543. tests/storage/test_appservice.py +568 -0
  1544. tests/storage/test_background_update.py +671 -0
  1545. tests/storage/test_base.py +813 -0
  1546. tests/storage/test_cleanup_extrems.py +396 -0
  1547. tests/storage/test_client_ips.py +788 -0
  1548. tests/storage/test_database.py +288 -0
  1549. tests/storage/test_devices.py +353 -0
  1550. tests/storage/test_directory.py +74 -0
  1551. tests/storage/test_e2e_room_keys.py +87 -0
  1552. tests/storage/test_end_to_end_keys.py +120 -0
  1553. tests/storage/test_event_chain.py +826 -0
  1554. tests/storage/test_event_federation.py +1433 -0
  1555. tests/storage/test_event_push_actions.py +809 -0
  1556. tests/storage/test_events.py +591 -0
  1557. tests/storage/test_events_bg_updates.py +156 -0
  1558. tests/storage/test_id_generators.py +791 -0
  1559. tests/storage/test_invite_rule.py +171 -0
  1560. tests/storage/test_main.py +56 -0
  1561. tests/storage/test_monthly_active_users.py +500 -0
  1562. tests/storage/test_profile.py +134 -0
  1563. tests/storage/test_purge.py +459 -0
  1564. tests/storage/test_receipts.py +309 -0
  1565. tests/storage/test_redaction.py +462 -0
  1566. tests/storage/test_registration.py +277 -0
  1567. tests/storage/test_relations.py +118 -0
  1568. tests/storage/test_rollback_worker.py +132 -0
  1569. tests/storage/test_room.py +69 -0
  1570. tests/storage/test_room_search.py +383 -0
  1571. tests/storage/test_roommember.py +812 -0
  1572. tests/storage/test_sliding_sync_tables.py +5187 -0
  1573. tests/storage/test_state.py +959 -0
  1574. tests/storage/test_state_deletion.py +475 -0
  1575. tests/storage/test_stream.py +1533 -0
  1576. tests/storage/test_thread_subscriptions.py +369 -0
  1577. tests/storage/test_transactions.py +77 -0
  1578. tests/storage/test_txn_limit.py +49 -0
  1579. tests/storage/test_unsafe_locale.py +67 -0
  1580. tests/storage/test_user_directory.py +691 -0
  1581. tests/storage/test_user_filters.py +101 -0
  1582. tests/storage/util/__init__.py +20 -0
  1583. tests/storage/util/test_partial_state_events_tracker.py +181 -0
  1584. tests/synapse_rust/__init__.py +11 -0
  1585. tests/synapse_rust/test_http_client.py +225 -0
  1586. tests/test_distributor.py +74 -0
  1587. tests/test_event_auth.py +921 -0
  1588. tests/test_mau.py +347 -0
  1589. tests/test_phone_home.py +102 -0
  1590. tests/test_rust.py +11 -0
  1591. tests/test_server.py +557 -0
  1592. tests/test_state.py +902 -0
  1593. tests/test_terms_auth.py +128 -0
  1594. tests/test_types.py +201 -0
  1595. tests/test_utils/__init__.py +161 -0
  1596. tests/test_utils/event_injection.py +150 -0
  1597. tests/test_utils/html_parsers.py +59 -0
  1598. tests/test_utils/logging_setup.py +74 -0
  1599. tests/test_utils/oidc.py +370 -0
  1600. tests/test_visibility.py +712 -0
  1601. tests/types/__init__.py +0 -0
  1602. tests/types/test_init.py +51 -0
  1603. tests/types/test_state.py +627 -0
  1604. tests/unittest.py +1108 -0
  1605. tests/util/__init__.py +20 -0
  1606. tests/util/caches/__init__.py +20 -0
  1607. tests/util/caches/test_cached_call.py +168 -0
  1608. tests/util/caches/test_deferred_cache.py +317 -0
  1609. tests/util/caches/test_descriptors.py +1110 -0
  1610. tests/util/caches/test_response_cache.py +225 -0
  1611. tests/util/caches/test_ttlcache.py +90 -0
  1612. tests/util/test_async_helpers.py +808 -0
  1613. tests/util/test_background_queue.py +117 -0
  1614. tests/util/test_batching_queue.py +252 -0
  1615. tests/util/test_check_dependencies.py +243 -0
  1616. tests/util/test_dict_cache.py +130 -0
  1617. tests/util/test_events.py +118 -0
  1618. tests/util/test_expiring_cache.py +113 -0
  1619. tests/util/test_file_consumer.py +199 -0
  1620. tests/util/test_itertools.py +190 -0
  1621. tests/util/test_linearizer.py +264 -0
  1622. tests/util/test_logcontext.py +715 -0
  1623. tests/util/test_logformatter.py +44 -0
  1624. tests/util/test_lrucache.py +479 -0
  1625. tests/util/test_macaroons.py +126 -0
  1626. tests/util/test_mutable_overlay_mapping.py +189 -0
  1627. tests/util/test_ratelimitutils.py +146 -0
  1628. tests/util/test_retryutils.py +314 -0
  1629. tests/util/test_rwlock.py +401 -0
  1630. tests/util/test_stream_change_cache.py +304 -0
  1631. tests/util/test_stringutils.py +86 -0
  1632. tests/util/test_task_scheduler.py +227 -0
  1633. tests/util/test_threepids.py +55 -0
  1634. tests/util/test_treecache.py +93 -0
  1635. tests/util/test_wheel_timer.py +82 -0
  1636. tests/utils.py +342 -0
@@ -0,0 +1,2317 @@
1
+ #
2
+ # This file is licensed under the Affero General Public License (AGPL) version 3.
3
+ #
4
+ # Copyright (C) 2023 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
+
15
+
16
+ import logging
17
+ from itertools import chain
18
+ from typing import (
19
+ TYPE_CHECKING,
20
+ AbstractSet,
21
+ Literal,
22
+ Mapping,
23
+ MutableMapping,
24
+ cast,
25
+ )
26
+
27
+ import attr
28
+ from immutabledict import immutabledict
29
+ from typing_extensions import assert_never
30
+
31
+ from synapse.api.constants import (
32
+ AccountDataTypes,
33
+ EventContentFields,
34
+ EventTypes,
35
+ Membership,
36
+ )
37
+ from synapse.api.errors import SlidingSyncUnknownPosition
38
+ from synapse.api.room_versions import KNOWN_ROOM_VERSIONS
39
+ from synapse.events import StrippedStateEvent
40
+ from synapse.events.utils import parse_stripped_state_event
41
+ from synapse.logging.opentracing import start_active_span, trace
42
+ from synapse.storage.databases.main.sliding_sync import UPDATE_INTERVAL_LAST_USED_TS
43
+ from synapse.storage.databases.main.state import (
44
+ ROOM_UNKNOWN_SENTINEL,
45
+ Sentinel as StateSentinel,
46
+ )
47
+ from synapse.storage.databases.main.stream import CurrentStateDeltaMembership
48
+ from synapse.storage.invite_rule import InviteRule
49
+ from synapse.storage.roommember import (
50
+ RoomsForUser,
51
+ RoomsForUserSlidingSync,
52
+ RoomsForUserStateReset,
53
+ )
54
+ from synapse.types import (
55
+ MutableStateMap,
56
+ RoomStreamToken,
57
+ StateMap,
58
+ StrCollection,
59
+ StreamKeyType,
60
+ StreamToken,
61
+ UserID,
62
+ )
63
+ from synapse.types.handlers.sliding_sync import (
64
+ HaveSentRoomFlag,
65
+ OperationType,
66
+ PerConnectionState,
67
+ RoomSyncConfig,
68
+ SlidingSyncConfig,
69
+ SlidingSyncResult,
70
+ )
71
+ from synapse.types.state import StateFilter
72
+ from synapse.util import MutableOverlayMapping
73
+ from synapse.util.duration import Duration
74
+ from synapse.util.sentinel import Sentinel
75
+
76
+ if TYPE_CHECKING:
77
+ from synapse.server import HomeServer
78
+
79
+
80
+ logger = logging.getLogger(__name__)
81
+
82
+
83
+ # Minimum time in milliseconds since the last sync before we consider expiring
84
+ # the connection due to too many rooms to send. This stops from getting into
85
+ # tight loops with clients that request lots of data at once.
86
+ #
87
+ # c.f. `NUM_ROOMS_THRESHOLD`. These values are somewhat arbitrary picked.
88
+ MINIMUM_NOT_USED_AGE_EXPIRY = Duration(hours=1)
89
+
90
+ # How many rooms with updates we allow before we consider the connection expired
91
+ # due to too many rooms to send.
92
+ #
93
+ # c.f. `MINIMUM_NOT_USED_AGE_EXPIRY_MS`. These values are somewhat arbitrary
94
+ # picked.
95
+ NUM_ROOMS_THRESHOLD = 100
96
+
97
+ # Sanity check that our minimum age is sensible compared to the update interval,
98
+ # i.e. if `MINIMUM_NOT_USED_AGE_EXPIRY_MS` is too small then we might expire the
99
+ # connection even if it is actively being used (and we're just not updating the
100
+ # DB frequently enough). We arbitrarily double the update interval to give some
101
+ # wiggle room.
102
+ assert 2 * UPDATE_INTERVAL_LAST_USED_TS < MINIMUM_NOT_USED_AGE_EXPIRY
103
+
104
+ # Helper definition for the types that we might return. We do this to avoid
105
+ # copying data between types (which can be expensive for many rooms).
106
+ RoomsForUserType = RoomsForUserStateReset | RoomsForUser | RoomsForUserSlidingSync
107
+
108
+
109
+ @attr.s(auto_attribs=True, slots=True, frozen=True)
110
+ class SlidingSyncInterestedRooms:
111
+ """The set of rooms and metadata a client is interested in based on their
112
+ sliding sync request.
113
+
114
+ Returned by `compute_interested_rooms`.
115
+
116
+ Attributes:
117
+ lists: A mapping from list name to the list result for the response
118
+ relevant_room_map: A map from rooms that match the sync request to
119
+ their room sync config.
120
+ relevant_rooms_to_send_map: Subset of `relevant_room_map` that
121
+ includes the rooms that *may* have relevant updates. Rooms not
122
+ in this map will definitely not have room updates (though
123
+ extensions may have updates in these rooms).
124
+ newly_joined_rooms: The set of rooms that were joined in the token range
125
+ and the user is still joined to at the end of this range.
126
+ newly_left_rooms: The set of rooms that we left in the token range
127
+ and are still "leave" at the end of this range.
128
+ dm_room_ids: The set of rooms the user consider as direct-message (DM) rooms
129
+ """
130
+
131
+ lists: Mapping[str, SlidingSyncResult.SlidingWindowList]
132
+ relevant_room_map: Mapping[str, RoomSyncConfig]
133
+ relevant_rooms_to_send_map: Mapping[str, RoomSyncConfig]
134
+ all_rooms: set[str]
135
+ room_membership_for_user_map: Mapping[str, RoomsForUserType]
136
+
137
+ newly_joined_rooms: AbstractSet[str]
138
+ newly_left_rooms: AbstractSet[str]
139
+ dm_room_ids: AbstractSet[str]
140
+
141
+ @staticmethod
142
+ def empty() -> "SlidingSyncInterestedRooms":
143
+ return SlidingSyncInterestedRooms(
144
+ lists={},
145
+ relevant_room_map={},
146
+ relevant_rooms_to_send_map={},
147
+ all_rooms=set(),
148
+ room_membership_for_user_map={},
149
+ newly_joined_rooms=set(),
150
+ newly_left_rooms=set(),
151
+ dm_room_ids=set(),
152
+ )
153
+
154
+
155
+ def filter_membership_for_sync(
156
+ *,
157
+ user_id: str,
158
+ room_membership_for_user: RoomsForUserType,
159
+ newly_left: bool,
160
+ ) -> bool:
161
+ """
162
+ Returns True if the membership event should be included in the sync response,
163
+ otherwise False.
164
+
165
+ Attributes:
166
+ user_id: The user ID that the membership applies to
167
+ room_membership_for_user: Membership information for the user in the room
168
+ """
169
+
170
+ membership = room_membership_for_user.membership
171
+ sender = room_membership_for_user.sender
172
+
173
+ # We want to allow everything except rooms the user has left unless `newly_left`
174
+ # because we want everything that's *still* relevant to the user. We include
175
+ # `newly_left` rooms because the last event that the user should see is their own
176
+ # leave event.
177
+ #
178
+ # A leave != kick. This logic includes kicks (leave events where the sender is not
179
+ # the same user).
180
+ #
181
+ # When `sender=None`, it means that a state reset happened that removed the user
182
+ # from the room without a corresponding leave event. We can just remove the rooms
183
+ # since they are no longer relevant to the user but will still appear if they are
184
+ # `newly_left`.
185
+ return (
186
+ # Anything except leave events
187
+ membership != Membership.LEAVE
188
+ # Unless...
189
+ or newly_left
190
+ # Allow kicks
191
+ or (membership == Membership.LEAVE and sender not in (user_id, None))
192
+ )
193
+
194
+
195
+ class SlidingSyncRoomLists:
196
+ """Handles calculating the room lists from sliding sync requests"""
197
+
198
+ def __init__(self, hs: "HomeServer"):
199
+ self.store = hs.get_datastores().main
200
+ self.storage_controllers = hs.get_storage_controllers()
201
+ self.rooms_to_exclude_globally = hs.config.server.rooms_to_exclude_from_sync
202
+ self.is_mine_id = hs.is_mine_id
203
+ self._clock = hs.get_clock()
204
+
205
+ async def compute_interested_rooms(
206
+ self,
207
+ sync_config: SlidingSyncConfig,
208
+ previous_connection_state: "PerConnectionState",
209
+ to_token: StreamToken,
210
+ from_token: StreamToken | None,
211
+ ) -> SlidingSyncInterestedRooms:
212
+ """Fetch the set of rooms that match the request"""
213
+ has_lists = sync_config.lists is not None and len(sync_config.lists) > 0
214
+ has_room_subscriptions = (
215
+ sync_config.room_subscriptions is not None
216
+ and len(sync_config.room_subscriptions) > 0
217
+ )
218
+
219
+ if not has_lists and not has_room_subscriptions:
220
+ return SlidingSyncInterestedRooms.empty()
221
+
222
+ if await self.store.have_finished_sliding_sync_background_jobs():
223
+ return await self._compute_interested_rooms_new_tables(
224
+ sync_config=sync_config,
225
+ previous_connection_state=previous_connection_state,
226
+ to_token=to_token,
227
+ from_token=from_token,
228
+ )
229
+ else:
230
+ # FIXME: This can be removed once we bump `SCHEMA_COMPAT_VERSION` and run the
231
+ # foreground update for
232
+ # `sliding_sync_joined_rooms`/`sliding_sync_membership_snapshots` (tracked by
233
+ # https://github.com/element-hq/synapse/issues/17623)
234
+ return await self._compute_interested_rooms_fallback(
235
+ sync_config=sync_config,
236
+ previous_connection_state=previous_connection_state,
237
+ to_token=to_token,
238
+ from_token=from_token,
239
+ )
240
+
241
+ @trace
242
+ async def _compute_interested_rooms_new_tables(
243
+ self,
244
+ sync_config: SlidingSyncConfig,
245
+ previous_connection_state: "PerConnectionState",
246
+ to_token: StreamToken,
247
+ from_token: StreamToken | None,
248
+ ) -> SlidingSyncInterestedRooms:
249
+ """Implementation of `compute_interested_rooms` using new sliding sync db tables."""
250
+ user_id = sync_config.user.to_string()
251
+
252
+ # Assemble sliding window lists
253
+ lists: dict[str, SlidingSyncResult.SlidingWindowList] = {}
254
+ # Keep track of the rooms that we can display and need to fetch more info about
255
+ relevant_room_map: dict[str, RoomSyncConfig] = {}
256
+ # The set of room IDs of all rooms that could appear in any list. These
257
+ # include rooms that are outside the list ranges.
258
+ all_rooms: set[str] = set()
259
+
260
+ # Note: this won't include rooms the user has left themselves. We add back
261
+ # `newly_left` rooms below. This is more efficient than fetching all rooms and
262
+ # then filtering out the old left rooms.
263
+ room_membership_for_user_map: MutableMapping[str, RoomsForUserSlidingSync] = (
264
+ MutableOverlayMapping(
265
+ await self.store.get_sliding_sync_rooms_for_user_from_membership_snapshots(
266
+ user_id
267
+ )
268
+ )
269
+ )
270
+ # To play nice with the rewind logic below, we need to go fetch the rooms the
271
+ # user has left themselves but only if it changed after the `to_token`.
272
+ #
273
+ # If a leave happens *after* the token range, we may have still been joined (or
274
+ # any non-self-leave which is relevant to sync) to the room before so we need to
275
+ # include it in the list of potentially relevant rooms and apply our rewind
276
+ # logic (outside of this function) to see if it's actually relevant.
277
+ #
278
+ # We do this separately from
279
+ # `get_sliding_sync_rooms_for_user_from_membership_snapshots` as those results
280
+ # are cached and the `to_token` isn't very cache friendly (people are constantly
281
+ # requesting with new tokens) so we separate it out here.
282
+ self_leave_room_membership_for_user_map = (
283
+ await self.store.get_sliding_sync_self_leave_rooms_after_to_token(
284
+ user_id, to_token
285
+ )
286
+ )
287
+ if self_leave_room_membership_for_user_map:
288
+ room_membership_for_user_map.update(self_leave_room_membership_for_user_map)
289
+
290
+ # Remove invites from ignored users
291
+ ignored_users = await self.store.ignored_users(user_id)
292
+ invite_config = await self.store.get_invite_config_for_user(user_id)
293
+ if ignored_users:
294
+ # Make a copy so we don't run into an error: `dictionary changed size during
295
+ # iteration`, when we remove items
296
+ for room_id in list(room_membership_for_user_map.keys()):
297
+ room_for_user_sliding_sync = room_membership_for_user_map[room_id]
298
+ if (
299
+ room_for_user_sliding_sync.membership == Membership.INVITE
300
+ and room_for_user_sliding_sync.sender
301
+ and (
302
+ room_for_user_sliding_sync.sender in ignored_users
303
+ or invite_config.get_invite_rule(
304
+ room_for_user_sliding_sync.sender
305
+ )
306
+ == InviteRule.IGNORE
307
+ )
308
+ ):
309
+ room_membership_for_user_map.pop(room_id, None)
310
+
311
+ (
312
+ newly_joined_room_ids,
313
+ newly_left_room_map,
314
+ ) = await self._get_newly_joined_and_left_rooms(
315
+ user_id, from_token=from_token, to_token=to_token
316
+ )
317
+
318
+ changes = await self._get_rewind_changes_to_current_membership_to_token(
319
+ sync_config.user, room_membership_for_user_map, to_token=to_token
320
+ )
321
+ if changes:
322
+ for room_id, change in changes.items():
323
+ if change is None:
324
+ # Remove rooms that the user joined after the `to_token`
325
+ room_membership_for_user_map.pop(room_id, None)
326
+ continue
327
+
328
+ existing_room = room_membership_for_user_map.get(room_id)
329
+ if existing_room is not None:
330
+ # Update room membership events to the point in time of the `to_token`
331
+ room_for_user = RoomsForUserSlidingSync(
332
+ room_id=room_id,
333
+ sender=change.sender,
334
+ membership=change.membership,
335
+ event_id=change.event_id,
336
+ event_pos=change.event_pos,
337
+ room_version_id=change.room_version_id,
338
+ # We keep the state of the room though
339
+ has_known_state=existing_room.has_known_state,
340
+ room_type=existing_room.room_type,
341
+ is_encrypted=existing_room.is_encrypted,
342
+ )
343
+ if filter_membership_for_sync(
344
+ user_id=user_id,
345
+ room_membership_for_user=room_for_user,
346
+ newly_left=room_id in newly_left_room_map,
347
+ ):
348
+ room_membership_for_user_map[room_id] = room_for_user
349
+ else:
350
+ room_membership_for_user_map.pop(room_id, None)
351
+
352
+ # Add back `newly_left` rooms (rooms left in the from -> to token range).
353
+ #
354
+ # We do this because `get_sliding_sync_rooms_for_user_from_membership_snapshots(...)` doesn't include
355
+ # rooms that the user left themselves as it's more efficient to add them back
356
+ # here than to fetch all rooms and then filter out the old left rooms. The user
357
+ # only leaves a room once in a blue moon so this barely needs to run.
358
+ #
359
+ missing_newly_left_rooms = (
360
+ newly_left_room_map.keys() - room_membership_for_user_map.keys()
361
+ )
362
+ if missing_newly_left_rooms:
363
+ for room_id in missing_newly_left_rooms:
364
+ newly_left_room_for_user = newly_left_room_map[room_id]
365
+ # This should be a given
366
+ assert newly_left_room_for_user.membership == Membership.LEAVE
367
+
368
+ # Add back `newly_left` rooms
369
+ #
370
+ # Check for membership and state in the Sliding Sync tables as it's just
371
+ # another membership
372
+ newly_left_room_for_user_sliding_sync = (
373
+ await self.store.get_sliding_sync_room_for_user(user_id, room_id)
374
+ )
375
+ # If the membership exists, it's just a normal user left the room on
376
+ # their own
377
+ if newly_left_room_for_user_sliding_sync is not None:
378
+ if filter_membership_for_sync(
379
+ user_id=user_id,
380
+ room_membership_for_user=newly_left_room_for_user_sliding_sync,
381
+ newly_left=room_id in newly_left_room_map,
382
+ ):
383
+ room_membership_for_user_map[room_id] = (
384
+ newly_left_room_for_user_sliding_sync
385
+ )
386
+ else:
387
+ room_membership_for_user_map.pop(room_id, None)
388
+
389
+ change = changes.get(room_id)
390
+ if change is not None:
391
+ # Update room membership events to the point in time of the `to_token`
392
+ room_for_user = RoomsForUserSlidingSync(
393
+ room_id=room_id,
394
+ sender=change.sender,
395
+ membership=change.membership,
396
+ event_id=change.event_id,
397
+ event_pos=change.event_pos,
398
+ room_version_id=change.room_version_id,
399
+ # We keep the state of the room though
400
+ has_known_state=newly_left_room_for_user_sliding_sync.has_known_state,
401
+ room_type=newly_left_room_for_user_sliding_sync.room_type,
402
+ is_encrypted=newly_left_room_for_user_sliding_sync.is_encrypted,
403
+ )
404
+ if filter_membership_for_sync(
405
+ user_id=user_id,
406
+ room_membership_for_user=room_for_user,
407
+ newly_left=room_id in newly_left_room_map,
408
+ ):
409
+ room_membership_for_user_map[room_id] = room_for_user
410
+ else:
411
+ room_membership_for_user_map.pop(room_id, None)
412
+
413
+ # If we are `newly_left` from the room but can't find any membership,
414
+ # then we have been "state reset" out of the room
415
+ else:
416
+ # Get the state at the time. We can't read from the Sliding Sync
417
+ # tables because the user has no membership in the room according to
418
+ # the state (thanks to the state reset).
419
+ #
420
+ # Note: `room_type` never changes, so we can just get current room
421
+ # type
422
+ room_type = await self.store.get_room_type(room_id)
423
+ has_known_state = room_type is not ROOM_UNKNOWN_SENTINEL
424
+ if isinstance(room_type, StateSentinel):
425
+ room_type = None
426
+
427
+ # Get the encryption status at the time of the token
428
+ is_encrypted = await self.get_is_encrypted_for_room_at_token(
429
+ room_id,
430
+ newly_left_room_for_user.event_pos.to_room_stream_token(),
431
+ )
432
+
433
+ room_for_user = RoomsForUserSlidingSync(
434
+ room_id=room_id,
435
+ sender=newly_left_room_for_user.sender,
436
+ membership=newly_left_room_for_user.membership,
437
+ event_id=newly_left_room_for_user.event_id,
438
+ event_pos=newly_left_room_for_user.event_pos,
439
+ room_version_id=newly_left_room_for_user.room_version_id,
440
+ has_known_state=has_known_state,
441
+ room_type=room_type,
442
+ is_encrypted=is_encrypted,
443
+ )
444
+ if filter_membership_for_sync(
445
+ user_id=user_id,
446
+ room_membership_for_user=room_for_user,
447
+ newly_left=room_id in newly_left_room_map,
448
+ ):
449
+ room_membership_for_user_map[room_id] = room_for_user
450
+ else:
451
+ room_membership_for_user_map.pop(room_id, None)
452
+
453
+ # Remove any rooms that we globally exclude from sync.
454
+ for room_id in self.rooms_to_exclude_globally:
455
+ room_membership_for_user_map.pop(room_id, None)
456
+
457
+ dm_room_ids = await self._get_dm_rooms_for_user(user_id)
458
+
459
+ if sync_config.lists:
460
+ sync_room_map = room_membership_for_user_map
461
+ with start_active_span("assemble_sliding_window_lists"):
462
+ for list_key, list_config in sync_config.lists.items():
463
+ # Apply filters
464
+ filtered_sync_room_map = sync_room_map
465
+ if list_config.filters is not None:
466
+ filtered_sync_room_map = await self.filter_rooms_using_tables(
467
+ user_id,
468
+ sync_room_map,
469
+ previous_connection_state,
470
+ list_config.filters,
471
+ to_token,
472
+ dm_room_ids,
473
+ )
474
+
475
+ # Find which rooms are partially stated and may need to be filtered out
476
+ # depending on the `required_state` requested (see below).
477
+ partial_state_rooms = await self.store.get_partial_rooms()
478
+
479
+ # Since creating the `RoomSyncConfig` takes some work, let's just do it
480
+ # once.
481
+ room_sync_config = RoomSyncConfig.from_room_config(list_config)
482
+
483
+ # Exclude partially-stated rooms if we must wait for the room to be
484
+ # fully-stated
485
+ if room_sync_config.must_await_full_state(self.is_mine_id):
486
+ filtered_sync_room_map = {
487
+ room_id: room
488
+ for room_id, room in filtered_sync_room_map.items()
489
+ if room_id not in partial_state_rooms
490
+ }
491
+
492
+ all_rooms.update(filtered_sync_room_map)
493
+
494
+ ops: list[SlidingSyncResult.SlidingWindowList.Operation] = []
495
+
496
+ if list_config.ranges:
497
+ # Optimization: If we are asking for the full range, we don't
498
+ # need to sort the list.
499
+ if (
500
+ # We're looking for a single range that covers the entire list
501
+ len(list_config.ranges) == 1
502
+ # Range starts at 0
503
+ and list_config.ranges[0][0] == 0
504
+ # And the range extends to the end of the list or more. Each
505
+ # side is inclusive.
506
+ and list_config.ranges[0][1]
507
+ >= len(filtered_sync_room_map) - 1
508
+ ):
509
+ sorted_room_info: list[RoomsForUserType] = list(
510
+ filtered_sync_room_map.values()
511
+ )
512
+ else:
513
+ # Sort the list
514
+ sorted_room_info = await self.sort_rooms(
515
+ # Cast is safe because RoomsForUserSlidingSync is part
516
+ # of the `RoomsForUserType` union. Why can't it detect this?
517
+ cast(
518
+ dict[str, RoomsForUserType], filtered_sync_room_map
519
+ ),
520
+ to_token,
521
+ # We only need to sort the rooms up to the end
522
+ # of the largest range. Both sides of range are
523
+ # inclusive so we `+ 1`.
524
+ limit=max(range[1] + 1 for range in list_config.ranges),
525
+ )
526
+
527
+ for range in list_config.ranges:
528
+ room_ids_in_list: list[str] = []
529
+
530
+ # We're going to loop through the sorted list of rooms starting
531
+ # at the range start index and keep adding rooms until we fill
532
+ # up the range or run out of rooms.
533
+ #
534
+ # Both sides of range are inclusive so we `+ 1`
535
+ max_num_rooms = range[1] - range[0] + 1
536
+ for room_membership in sorted_room_info[range[0] :]:
537
+ room_id = room_membership.room_id
538
+
539
+ if len(room_ids_in_list) >= max_num_rooms:
540
+ break
541
+
542
+ # Take the superset of the `RoomSyncConfig` for each room.
543
+ #
544
+ # Update our `relevant_room_map` with the room we're going
545
+ # to display and need to fetch more info about.
546
+ existing_room_sync_config = relevant_room_map.get(
547
+ room_id
548
+ )
549
+ if existing_room_sync_config is not None:
550
+ room_sync_config = existing_room_sync_config.combine_room_sync_config(
551
+ room_sync_config
552
+ )
553
+
554
+ relevant_room_map[room_id] = room_sync_config
555
+
556
+ room_ids_in_list.append(room_id)
557
+
558
+ ops.append(
559
+ SlidingSyncResult.SlidingWindowList.Operation(
560
+ op=OperationType.SYNC,
561
+ range=range,
562
+ room_ids=room_ids_in_list,
563
+ )
564
+ )
565
+
566
+ lists[list_key] = SlidingSyncResult.SlidingWindowList(
567
+ count=len(filtered_sync_room_map),
568
+ ops=ops,
569
+ )
570
+
571
+ if sync_config.room_subscriptions:
572
+ with start_active_span("assemble_room_subscriptions"):
573
+ # Find which rooms are partially stated and may need to be filtered out
574
+ # depending on the `required_state` requested (see below).
575
+ partial_state_rooms = await self.store.get_partial_rooms()
576
+
577
+ # Fetch any rooms that we have not already fetched from the database.
578
+ subscription_sliding_sync_rooms = (
579
+ await self.store.get_sliding_sync_room_for_user_batch(
580
+ user_id,
581
+ sync_config.room_subscriptions.keys()
582
+ - room_membership_for_user_map.keys(),
583
+ )
584
+ )
585
+ room_membership_for_user_map.update(subscription_sliding_sync_rooms)
586
+
587
+ for (
588
+ room_id,
589
+ room_subscription,
590
+ ) in sync_config.room_subscriptions.items():
591
+ # Check if we have a membership for the room, but didn't pull it out
592
+ # above. This could be e.g. a leave that we don't pull out by
593
+ # default.
594
+ current_room_entry = room_membership_for_user_map.get(room_id)
595
+ if not current_room_entry:
596
+ # TODO: Handle rooms the user isn't in.
597
+ continue
598
+
599
+ all_rooms.add(room_id)
600
+
601
+ # Take the superset of the `RoomSyncConfig` for each room.
602
+ room_sync_config = RoomSyncConfig.from_room_config(
603
+ room_subscription
604
+ )
605
+
606
+ # Exclude partially-stated rooms if we must wait for the room to be
607
+ # fully-stated
608
+ if room_sync_config.must_await_full_state(self.is_mine_id):
609
+ if room_id in partial_state_rooms:
610
+ continue
611
+
612
+ # Update our `relevant_room_map` with the room we're going to display
613
+ # and need to fetch more info about.
614
+ existing_room_sync_config = relevant_room_map.get(room_id)
615
+ if existing_room_sync_config is not None:
616
+ room_sync_config = (
617
+ existing_room_sync_config.combine_room_sync_config(
618
+ room_sync_config
619
+ )
620
+ )
621
+
622
+ relevant_room_map[room_id] = room_sync_config
623
+
624
+ # Filtered subset of `relevant_room_map` for rooms that may have updates
625
+ # (in the event stream)
626
+ relevant_rooms_to_send_map = await self._filter_relevant_rooms_to_send(
627
+ previous_connection_state, from_token, relevant_room_map
628
+ )
629
+
630
+ return SlidingSyncInterestedRooms(
631
+ lists=lists,
632
+ relevant_room_map=relevant_room_map,
633
+ relevant_rooms_to_send_map=relevant_rooms_to_send_map,
634
+ all_rooms=all_rooms,
635
+ room_membership_for_user_map=room_membership_for_user_map,
636
+ newly_joined_rooms=newly_joined_room_ids,
637
+ newly_left_rooms=set(newly_left_room_map),
638
+ dm_room_ids=dm_room_ids,
639
+ )
640
+
641
+ async def _compute_interested_rooms_fallback(
642
+ self,
643
+ sync_config: SlidingSyncConfig,
644
+ previous_connection_state: "PerConnectionState",
645
+ to_token: StreamToken,
646
+ from_token: StreamToken | None,
647
+ ) -> SlidingSyncInterestedRooms:
648
+ """Fallback code when the database background updates haven't completed yet."""
649
+
650
+ (
651
+ room_membership_for_user_map,
652
+ newly_joined_room_ids,
653
+ newly_left_room_ids,
654
+ ) = await self.get_room_membership_for_user_at_to_token(
655
+ sync_config.user, to_token, from_token
656
+ )
657
+
658
+ dm_room_ids = await self._get_dm_rooms_for_user(sync_config.user.to_string())
659
+
660
+ # Assemble sliding window lists
661
+ lists: dict[str, SlidingSyncResult.SlidingWindowList] = {}
662
+ # Keep track of the rooms that we can display and need to fetch more info about
663
+ relevant_room_map: dict[str, RoomSyncConfig] = {}
664
+ # The set of room IDs of all rooms that could appear in any list. These
665
+ # include rooms that are outside the list ranges.
666
+ all_rooms: set[str] = set()
667
+
668
+ if sync_config.lists:
669
+ with start_active_span("assemble_sliding_window_lists"):
670
+ sync_room_map = await self.filter_rooms_relevant_for_sync(
671
+ user=sync_config.user,
672
+ room_membership_for_user_map=room_membership_for_user_map,
673
+ newly_left_room_ids=newly_left_room_ids,
674
+ )
675
+
676
+ for list_key, list_config in sync_config.lists.items():
677
+ # Apply filters
678
+ filtered_sync_room_map = sync_room_map
679
+ if list_config.filters is not None:
680
+ filtered_sync_room_map = await self.filter_rooms(
681
+ sync_config.user,
682
+ sync_room_map,
683
+ previous_connection_state,
684
+ list_config.filters,
685
+ to_token,
686
+ dm_room_ids,
687
+ )
688
+
689
+ # Find which rooms are partially stated and may need to be filtered out
690
+ # depending on the `required_state` requested (see below).
691
+ partial_state_rooms = await self.store.get_partial_rooms()
692
+
693
+ # Since creating the `RoomSyncConfig` takes some work, let's just do it
694
+ # once.
695
+ room_sync_config = RoomSyncConfig.from_room_config(list_config)
696
+
697
+ # Exclude partially-stated rooms if we must wait for the room to be
698
+ # fully-stated
699
+ if room_sync_config.must_await_full_state(self.is_mine_id):
700
+ filtered_sync_room_map = {
701
+ room_id: room
702
+ for room_id, room in filtered_sync_room_map.items()
703
+ if room_id not in partial_state_rooms
704
+ }
705
+
706
+ all_rooms.update(filtered_sync_room_map)
707
+
708
+ # Sort the list
709
+ sorted_room_info = await self.sort_rooms(
710
+ filtered_sync_room_map, to_token
711
+ )
712
+
713
+ ops: list[SlidingSyncResult.SlidingWindowList.Operation] = []
714
+ if list_config.ranges:
715
+ for range in list_config.ranges:
716
+ room_ids_in_list: list[str] = []
717
+
718
+ # We're going to loop through the sorted list of rooms starting
719
+ # at the range start index and keep adding rooms until we fill
720
+ # up the range or run out of rooms.
721
+ #
722
+ # Both sides of range are inclusive so we `+ 1`
723
+ max_num_rooms = range[1] - range[0] + 1
724
+ for room_membership in sorted_room_info[range[0] :]:
725
+ room_id = room_membership.room_id
726
+
727
+ if len(room_ids_in_list) >= max_num_rooms:
728
+ break
729
+
730
+ # Take the superset of the `RoomSyncConfig` for each room.
731
+ #
732
+ # Update our `relevant_room_map` with the room we're going
733
+ # to display and need to fetch more info about.
734
+ existing_room_sync_config = relevant_room_map.get(
735
+ room_id
736
+ )
737
+ if existing_room_sync_config is not None:
738
+ room_sync_config = existing_room_sync_config.combine_room_sync_config(
739
+ room_sync_config
740
+ )
741
+
742
+ relevant_room_map[room_id] = room_sync_config
743
+
744
+ room_ids_in_list.append(room_id)
745
+
746
+ ops.append(
747
+ SlidingSyncResult.SlidingWindowList.Operation(
748
+ op=OperationType.SYNC,
749
+ range=range,
750
+ room_ids=room_ids_in_list,
751
+ )
752
+ )
753
+
754
+ lists[list_key] = SlidingSyncResult.SlidingWindowList(
755
+ count=len(sorted_room_info),
756
+ ops=ops,
757
+ )
758
+
759
+ if sync_config.room_subscriptions:
760
+ with start_active_span("assemble_room_subscriptions"):
761
+ # Find which rooms are partially stated and may need to be filtered out
762
+ # depending on the `required_state` requested (see below).
763
+ partial_state_rooms = await self.store.get_partial_rooms()
764
+
765
+ for (
766
+ room_id,
767
+ room_subscription,
768
+ ) in sync_config.room_subscriptions.items():
769
+ room_membership_for_user_at_to_token = (
770
+ await self.check_room_subscription_allowed_for_user(
771
+ room_id=room_id,
772
+ room_membership_for_user_map=room_membership_for_user_map,
773
+ to_token=to_token,
774
+ )
775
+ )
776
+
777
+ # Skip this room if the user isn't allowed to see it
778
+ if not room_membership_for_user_at_to_token:
779
+ continue
780
+
781
+ all_rooms.add(room_id)
782
+
783
+ room_membership_for_user_map[room_id] = (
784
+ room_membership_for_user_at_to_token
785
+ )
786
+
787
+ # Take the superset of the `RoomSyncConfig` for each room.
788
+ room_sync_config = RoomSyncConfig.from_room_config(
789
+ room_subscription
790
+ )
791
+
792
+ # Exclude partially-stated rooms if we must wait for the room to be
793
+ # fully-stated
794
+ if room_sync_config.must_await_full_state(self.is_mine_id):
795
+ if room_id in partial_state_rooms:
796
+ continue
797
+
798
+ all_rooms.add(room_id)
799
+
800
+ # Update our `relevant_room_map` with the room we're going to display
801
+ # and need to fetch more info about.
802
+ existing_room_sync_config = relevant_room_map.get(room_id)
803
+ if existing_room_sync_config is not None:
804
+ room_sync_config = (
805
+ existing_room_sync_config.combine_room_sync_config(
806
+ room_sync_config
807
+ )
808
+ )
809
+
810
+ relevant_room_map[room_id] = room_sync_config
811
+
812
+ # Filtered subset of `relevant_room_map` for rooms that may have updates
813
+ # (in the event stream)
814
+ relevant_rooms_to_send_map = await self._filter_relevant_rooms_to_send(
815
+ previous_connection_state, from_token, relevant_room_map
816
+ )
817
+
818
+ return SlidingSyncInterestedRooms(
819
+ lists=lists,
820
+ relevant_room_map=relevant_room_map,
821
+ relevant_rooms_to_send_map=relevant_rooms_to_send_map,
822
+ all_rooms=all_rooms,
823
+ room_membership_for_user_map=room_membership_for_user_map,
824
+ newly_joined_rooms=newly_joined_room_ids,
825
+ newly_left_rooms=newly_left_room_ids,
826
+ dm_room_ids=dm_room_ids,
827
+ )
828
+
829
+ async def _filter_relevant_rooms_to_send(
830
+ self,
831
+ previous_connection_state: PerConnectionState,
832
+ from_token: StreamToken | None,
833
+ relevant_room_map: dict[str, RoomSyncConfig],
834
+ ) -> dict[str, RoomSyncConfig]:
835
+ """Filters the `relevant_room_map` down to those rooms that may have
836
+ updates we need to fetch and return."""
837
+
838
+ # Filtered subset of `relevant_room_map` for rooms that may have updates
839
+ # (in the event stream)
840
+ relevant_rooms_to_send_map: dict[str, RoomSyncConfig] = relevant_room_map
841
+ if relevant_room_map:
842
+ with start_active_span("filter_relevant_rooms_to_send"):
843
+ if from_token:
844
+ rooms_should_send = set()
845
+
846
+ # First we check if there are rooms that match a list/room
847
+ # subscription and have updates we need to send (i.e. either because
848
+ # we haven't sent the room down, or we have but there are missing
849
+ # updates).
850
+ for room_id, room_config in relevant_room_map.items():
851
+ prev_room_sync_config = (
852
+ previous_connection_state.room_configs.get(room_id)
853
+ )
854
+ if prev_room_sync_config is not None:
855
+ # Always include rooms whose timeline limit has increased.
856
+ # (see the "XXX: Odd behavior" described below)
857
+ if (
858
+ prev_room_sync_config.timeline_limit
859
+ < room_config.timeline_limit
860
+ ):
861
+ rooms_should_send.add(room_id)
862
+ continue
863
+
864
+ status = previous_connection_state.rooms.have_sent_room(room_id)
865
+ if (
866
+ # The room was never sent down before so the client needs to know
867
+ # about it regardless of any updates.
868
+ status.status == HaveSentRoomFlag.NEVER
869
+ # `PREVIOUSLY` literally means the "room was sent down before *AND*
870
+ # there are updates we haven't sent down" so we already know this
871
+ # room has updates.
872
+ or status.status == HaveSentRoomFlag.PREVIOUSLY
873
+ ):
874
+ rooms_should_send.add(room_id)
875
+ elif status.status == HaveSentRoomFlag.LIVE:
876
+ # We know that we've sent all updates up until `from_token`,
877
+ # so we just need to check if there have been updates since
878
+ # then.
879
+ pass
880
+ else:
881
+ assert_never(status.status)
882
+
883
+ # We only need to check for new events since any state changes
884
+ # will also come down as new events.
885
+
886
+ rooms_that_have_updates = await (
887
+ self.store.get_rooms_that_have_updates_since_sliding_sync_table(
888
+ relevant_room_map.keys(), from_token.room_key
889
+ )
890
+ )
891
+
892
+ # Check if we have lots of updates to send, if so then its
893
+ # better for us to tell the client to do a full resync
894
+ # instead (to try and avoid long SSS response times when
895
+ # there is new data).
896
+ #
897
+ # Due to the construction of the SSS API, the client is in
898
+ # charge of setting the range of rooms to request updates
899
+ # for. Generally, it will start with a small range and then
900
+ # expand (and occasionally it may contract the range again
901
+ # if its been offline for a while). If we know there are a
902
+ # lot of updates, it's better to reset the connection and
903
+ # wait for the client to start again (with a much smaller
904
+ # range) than to try and send down a large number of updates
905
+ # (which can take a long time).
906
+ #
907
+ # We only do this if the last sync was over
908
+ # `MINIMUM_NOT_USED_AGE_EXPIRY_MS` to ensure we don't get
909
+ # into tight loops with clients that keep requesting large
910
+ # sliding sync windows.
911
+ if len(rooms_that_have_updates) > NUM_ROOMS_THRESHOLD:
912
+ last_sync_ts = previous_connection_state.last_used_ts
913
+ if (
914
+ last_sync_ts is not None
915
+ and (self._clock.time_msec() - last_sync_ts)
916
+ > MINIMUM_NOT_USED_AGE_EXPIRY.as_millis()
917
+ ):
918
+ raise SlidingSyncUnknownPosition()
919
+
920
+ rooms_should_send.update(rooms_that_have_updates)
921
+ relevant_rooms_to_send_map = {
922
+ room_id: room_sync_config
923
+ for room_id, room_sync_config in relevant_room_map.items()
924
+ if room_id in rooms_should_send
925
+ }
926
+
927
+ return relevant_rooms_to_send_map
928
+
929
+ @trace
930
+ async def _get_rewind_changes_to_current_membership_to_token(
931
+ self,
932
+ user: UserID,
933
+ rooms_for_user: Mapping[str, RoomsForUserType],
934
+ to_token: StreamToken,
935
+ ) -> Mapping[str, RoomsForUser | None]:
936
+ """
937
+ Takes the current set of rooms for a user (retrieved after the given
938
+ token), and returns the changes needed to "rewind" it to match the set of
939
+ memberships *at that token* (<= `to_token`).
940
+
941
+ Args:
942
+ user: User to fetch rooms for
943
+ rooms_for_user: The set of rooms for the user after the `to_token`.
944
+ to_token: The token to rewind to
945
+
946
+ Returns:
947
+ The changes to apply to rewind the the current memberships.
948
+ """
949
+ # If the user has never joined any rooms before, we can just return an empty list
950
+ if not rooms_for_user:
951
+ return {}
952
+
953
+ user_id = user.to_string()
954
+
955
+ # Get the `RoomStreamToken` that represents the spot we queried up to when we got
956
+ # our membership snapshot from `get_rooms_for_local_user_where_membership_is()`.
957
+ #
958
+ # First, we need to get the max stream_ordering of each event persister instance
959
+ # that we queried events from.
960
+ instance_to_max_stream_ordering_map: dict[str, int] = {}
961
+ for room_for_user in rooms_for_user.values():
962
+ instance_name = room_for_user.event_pos.instance_name
963
+ stream_ordering = room_for_user.event_pos.stream
964
+
965
+ current_instance_max_stream_ordering = (
966
+ instance_to_max_stream_ordering_map.get(instance_name)
967
+ )
968
+ if (
969
+ current_instance_max_stream_ordering is None
970
+ or stream_ordering > current_instance_max_stream_ordering
971
+ ):
972
+ instance_to_max_stream_ordering_map[instance_name] = stream_ordering
973
+
974
+ # Then assemble the `RoomStreamToken`
975
+ min_stream_pos = min(instance_to_max_stream_ordering_map.values())
976
+ membership_snapshot_token = RoomStreamToken(
977
+ # Minimum position in the `instance_map`
978
+ stream=min_stream_pos,
979
+ instance_map=immutabledict(
980
+ {
981
+ instance_name: stream_pos
982
+ for instance_name, stream_pos in instance_to_max_stream_ordering_map.items()
983
+ if stream_pos > min_stream_pos
984
+ }
985
+ ),
986
+ )
987
+
988
+ # Since we fetched the users room list at some point in time after the
989
+ # tokens, we need to revert/rewind some membership changes to match the point in
990
+ # time of the `to_token`. In particular, we need to make these fixups:
991
+ #
992
+ # - a) Remove rooms that the user joined after the `to_token`
993
+ # - b) Update room membership events to the point in time of the `to_token`
994
+
995
+ # Fetch membership changes that fall in the range from `to_token` up to
996
+ # `membership_snapshot_token`
997
+ #
998
+ # If our `to_token` is already the same or ahead of the latest room membership
999
+ # for the user, we don't need to do any "2)" fix-ups and can just straight-up
1000
+ # use the room list from the snapshot as a base (nothing has changed)
1001
+ current_state_delta_membership_changes_after_to_token = []
1002
+ if not membership_snapshot_token.is_before_or_eq(to_token.room_key):
1003
+ current_state_delta_membership_changes_after_to_token = (
1004
+ await self.store.get_current_state_delta_membership_changes_for_user(
1005
+ user_id,
1006
+ from_key=to_token.room_key,
1007
+ to_key=membership_snapshot_token,
1008
+ excluded_room_ids=self.rooms_to_exclude_globally,
1009
+ )
1010
+ )
1011
+
1012
+ if not current_state_delta_membership_changes_after_to_token:
1013
+ # There have been no membership changes, so we can early return.
1014
+ return {}
1015
+
1016
+ # Otherwise we're about to make changes to `rooms_for_user`, so we turn
1017
+ # it into a mutable dict.
1018
+ changes: dict[str, RoomsForUser | None] = {}
1019
+
1020
+ # Assemble a list of the first membership event after the `to_token` so we can
1021
+ # step backward to the previous membership that would apply to the from/to
1022
+ # range.
1023
+ first_membership_change_by_room_id_after_to_token: dict[
1024
+ str, CurrentStateDeltaMembership
1025
+ ] = {}
1026
+ for membership_change in current_state_delta_membership_changes_after_to_token:
1027
+ # Only set if we haven't already set it
1028
+ first_membership_change_by_room_id_after_to_token.setdefault(
1029
+ membership_change.room_id, membership_change
1030
+ )
1031
+
1032
+ # Since we fetched a snapshot of the users room list at some point in time after
1033
+ # the from/to tokens, we need to revert/rewind some membership changes to match
1034
+ # the point in time of the `to_token`.
1035
+ for (
1036
+ room_id,
1037
+ first_membership_change_after_to_token,
1038
+ ) in first_membership_change_by_room_id_after_to_token.items():
1039
+ # 1a) Remove rooms that the user joined after the `to_token`
1040
+ if first_membership_change_after_to_token.prev_event_id is None:
1041
+ changes[room_id] = None
1042
+ # 1b) 1c) From the first membership event after the `to_token`, step backward to the
1043
+ # previous membership that would apply to the from/to range.
1044
+ else:
1045
+ # We don't expect these fields to be `None` if we have a `prev_event_id`
1046
+ # but we're being defensive since it's possible that the prev event was
1047
+ # culled from the database.
1048
+ if (
1049
+ first_membership_change_after_to_token.prev_event_pos is not None
1050
+ and first_membership_change_after_to_token.prev_membership
1051
+ is not None
1052
+ and first_membership_change_after_to_token.prev_sender is not None
1053
+ ):
1054
+ # We need to know the room version ID, which we normally we
1055
+ # can get from the current membership, but if we don't have
1056
+ # that then we need to query the DB.
1057
+ current_membership = rooms_for_user.get(room_id)
1058
+ if current_membership is not None:
1059
+ room_version_id = current_membership.room_version_id
1060
+ else:
1061
+ room_version_id = await self.store.get_room_version_id(room_id)
1062
+
1063
+ changes[room_id] = RoomsForUser(
1064
+ room_id=room_id,
1065
+ event_id=first_membership_change_after_to_token.prev_event_id,
1066
+ event_pos=first_membership_change_after_to_token.prev_event_pos,
1067
+ membership=first_membership_change_after_to_token.prev_membership,
1068
+ sender=first_membership_change_after_to_token.prev_sender,
1069
+ room_version_id=room_version_id,
1070
+ )
1071
+ else:
1072
+ # If we can't find the previous membership event, we shouldn't
1073
+ # include the room in the sync response since we can't determine the
1074
+ # exact membership state and shouldn't rely on the current snapshot.
1075
+ changes[room_id] = None
1076
+
1077
+ return changes
1078
+
1079
+ @trace
1080
+ async def get_room_membership_for_user_at_to_token(
1081
+ self,
1082
+ user: UserID,
1083
+ to_token: StreamToken,
1084
+ from_token: StreamToken | None,
1085
+ ) -> tuple[dict[str, RoomsForUserType], AbstractSet[str], AbstractSet[str]]:
1086
+ """
1087
+ Fetch room IDs that the user has had membership in (the full room list including
1088
+ long-lost left rooms that will be filtered, sorted, and sliced).
1089
+
1090
+ We're looking for rooms where the user has had any sort of membership in the
1091
+ token range (> `from_token` and <= `to_token`)
1092
+
1093
+ In order for bans/kicks to not show up, you need to `/forget` those rooms. This
1094
+ doesn't modify the event itself though and only adds the `forgotten` flag to the
1095
+ `room_memberships` table in Synapse. There isn't a way to tell when a room was
1096
+ forgotten at the moment so we can't factor it into the token range.
1097
+
1098
+ Args:
1099
+ user: User to fetch rooms for
1100
+ to_token: The token to fetch rooms up to.
1101
+ from_token: The point in the stream to sync from.
1102
+
1103
+ Returns:
1104
+ A 3-tuple of:
1105
+ - A dictionary of room IDs that the user has had membership in along with
1106
+ membership information in that room at the time of `to_token`.
1107
+ - Set of newly joined rooms
1108
+ - Set of newly left rooms
1109
+ """
1110
+ user_id = user.to_string()
1111
+
1112
+ # First grab a current snapshot rooms for the user
1113
+ # (also handles forgotten rooms)
1114
+ room_for_user_list = await self.store.get_rooms_for_local_user_where_membership_is(
1115
+ user_id=user_id,
1116
+ # We want to fetch any kind of membership (joined and left rooms) in order
1117
+ # to get the `event_pos` of the latest room membership event for the
1118
+ # user.
1119
+ membership_list=Membership.LIST,
1120
+ excluded_rooms=self.rooms_to_exclude_globally,
1121
+ )
1122
+
1123
+ # We filter out unknown room versions before we try and load any
1124
+ # metadata about the room. They shouldn't go down sync anyway, and their
1125
+ # metadata may be in a broken state.
1126
+ room_for_user_list = [
1127
+ room_for_user
1128
+ for room_for_user in room_for_user_list
1129
+ if room_for_user.room_version_id in KNOWN_ROOM_VERSIONS
1130
+ ]
1131
+
1132
+ # Remove invites from ignored users
1133
+ ignored_users = await self.store.ignored_users(user_id)
1134
+ if ignored_users:
1135
+ room_for_user_list = [
1136
+ room_for_user
1137
+ for room_for_user in room_for_user_list
1138
+ if not (
1139
+ room_for_user.membership == Membership.INVITE
1140
+ and room_for_user.sender in ignored_users
1141
+ )
1142
+ ]
1143
+
1144
+ (
1145
+ newly_joined_room_ids,
1146
+ newly_left_room_map,
1147
+ ) = await self._get_newly_joined_and_left_rooms_fallback(
1148
+ user_id, to_token=to_token, from_token=from_token
1149
+ )
1150
+
1151
+ # If the user has never joined any rooms before, we can just return an empty
1152
+ # list. We also have to check the `newly_left_room_map` in case someone was
1153
+ # state reset out of all of the rooms they were in.
1154
+ if not room_for_user_list and not newly_left_room_map:
1155
+ return {}, set(), set()
1156
+
1157
+ # Since we fetched the users room list at some point in time after the
1158
+ # tokens, we need to revert/rewind some membership changes to match the point in
1159
+ # time of the `to_token`.
1160
+ rooms_for_user: dict[str, RoomsForUserType] = {
1161
+ room.room_id: room for room in room_for_user_list
1162
+ }
1163
+ changes = await self._get_rewind_changes_to_current_membership_to_token(
1164
+ user, rooms_for_user, to_token
1165
+ )
1166
+ for room_id, change_room_for_user in changes.items():
1167
+ if change_room_for_user is None:
1168
+ rooms_for_user.pop(room_id, None)
1169
+ else:
1170
+ rooms_for_user[room_id] = change_room_for_user
1171
+
1172
+ # Ensure we have entries for rooms that the user has been "state reset"
1173
+ # out of. These are rooms appear in the `newly_left_rooms` map but
1174
+ # aren't in the `rooms_for_user` map.
1175
+ for room_id, newly_left_room_for_user in newly_left_room_map.items():
1176
+ # If we already know about the room, it's not a state reset
1177
+ if room_id in rooms_for_user:
1178
+ continue
1179
+
1180
+ # This should be true if it's a state reset
1181
+ assert newly_left_room_for_user.membership is Membership.LEAVE
1182
+ assert newly_left_room_for_user.event_id is None
1183
+ assert newly_left_room_for_user.sender is None
1184
+
1185
+ rooms_for_user[room_id] = newly_left_room_for_user
1186
+
1187
+ return rooms_for_user, newly_joined_room_ids, set(newly_left_room_map)
1188
+
1189
+ @trace
1190
+ async def _get_newly_joined_and_left_rooms(
1191
+ self,
1192
+ user_id: str,
1193
+ to_token: StreamToken,
1194
+ from_token: StreamToken | None,
1195
+ ) -> tuple[AbstractSet[str], Mapping[str, RoomsForUserStateReset]]:
1196
+ """Fetch the sets of rooms that the user newly joined or left in the
1197
+ given token range.
1198
+
1199
+ Note: there may be rooms in the newly left rooms where the user was
1200
+ "state reset" out of the room, and so that room would not be part of the
1201
+ "current memberships" of the user.
1202
+
1203
+ Returns:
1204
+ A 2-tuple of newly joined room IDs and a map of newly_left room
1205
+ IDs to the `RoomsForUserStateReset` entry.
1206
+
1207
+ We're using `RoomsForUserStateReset` but that doesn't necessarily mean the
1208
+ user was state reset of the rooms. It's just that the `event_id`/`sender`
1209
+ are optional and we can't tell the difference between the server leaving the
1210
+ room when the user was the last person participating in the room and left or
1211
+ was state reset out of the room. To actually check for a state reset, you
1212
+ need to check if a membership still exists in the room.
1213
+ """
1214
+
1215
+ newly_joined_room_ids: set[str] = set()
1216
+ newly_left_room_map: dict[str, RoomsForUserStateReset] = {}
1217
+
1218
+ if not from_token:
1219
+ return newly_joined_room_ids, newly_left_room_map
1220
+
1221
+ changes = await self.store.get_sliding_sync_membership_changes(
1222
+ user_id,
1223
+ from_key=from_token.room_key,
1224
+ to_key=to_token.room_key,
1225
+ excluded_room_ids=set(self.rooms_to_exclude_globally),
1226
+ )
1227
+
1228
+ for room_id, entry in changes.items():
1229
+ if entry.membership == Membership.JOIN:
1230
+ newly_joined_room_ids.add(room_id)
1231
+ elif entry.membership == Membership.LEAVE:
1232
+ newly_left_room_map[room_id] = entry
1233
+
1234
+ return newly_joined_room_ids, newly_left_room_map
1235
+
1236
+ @trace
1237
+ async def _get_newly_joined_and_left_rooms_fallback(
1238
+ self,
1239
+ user_id: str,
1240
+ to_token: StreamToken,
1241
+ from_token: StreamToken | None,
1242
+ ) -> tuple[AbstractSet[str], Mapping[str, RoomsForUserStateReset]]:
1243
+ """Fetch the sets of rooms that the user newly joined or left in the
1244
+ given token range.
1245
+
1246
+ Note: there may be rooms in the newly left rooms where the user was
1247
+ "state reset" out of the room, and so that room would not be part of the
1248
+ "current memberships" of the user.
1249
+
1250
+ Returns:
1251
+ A 2-tuple of newly joined room IDs and a map of newly_left room
1252
+ IDs to the `RoomsForUserStateReset` entry.
1253
+
1254
+ We're using `RoomsForUserStateReset` but that doesn't necessarily mean the
1255
+ user was state reset of the rooms. It's just that the `event_id`/`sender`
1256
+ are optional and we can't tell the difference between the server leaving the
1257
+ room when the user was the last person participating in the room and left or
1258
+ was state reset out of the room. To actually check for a state reset, you
1259
+ need to check if a membership still exists in the room.
1260
+ """
1261
+ newly_joined_room_ids: set[str] = set()
1262
+ newly_left_room_map: dict[str, RoomsForUserStateReset] = {}
1263
+
1264
+ # We need to figure out the
1265
+ #
1266
+ # - 1) Figure out which rooms are `newly_left` rooms (> `from_token` and <= `to_token`)
1267
+ # - 2) Figure out which rooms are `newly_joined` (> `from_token` and <= `to_token`)
1268
+
1269
+ # 1) Fetch membership changes that fall in the range from `from_token` up to `to_token`
1270
+ current_state_delta_membership_changes_in_from_to_range = []
1271
+ if from_token:
1272
+ current_state_delta_membership_changes_in_from_to_range = (
1273
+ await self.store.get_current_state_delta_membership_changes_for_user(
1274
+ user_id,
1275
+ from_key=from_token.room_key,
1276
+ to_key=to_token.room_key,
1277
+ excluded_room_ids=self.rooms_to_exclude_globally,
1278
+ )
1279
+ )
1280
+
1281
+ # 1) Assemble a list of the last membership events in some given ranges. Someone
1282
+ # could have left and joined multiple times during the given range but we only
1283
+ # care about end-result so we grab the last one.
1284
+ last_membership_change_by_room_id_in_from_to_range: dict[
1285
+ str, CurrentStateDeltaMembership
1286
+ ] = {}
1287
+ # We also want to assemble a list of the first membership events during the token
1288
+ # range so we can step backward to the previous membership that would apply to
1289
+ # before the token range to see if we have `newly_joined` the room.
1290
+ first_membership_change_by_room_id_in_from_to_range: dict[
1291
+ str, CurrentStateDeltaMembership
1292
+ ] = {}
1293
+ # Keep track if the room has a non-join event in the token range so we can later
1294
+ # tell if it was a `newly_joined` room. If the last membership event in the
1295
+ # token range is a join and there is also some non-join in the range, we know
1296
+ # they `newly_joined`.
1297
+ has_non_join_event_by_room_id_in_from_to_range: dict[str, bool] = {}
1298
+ for (
1299
+ membership_change
1300
+ ) in current_state_delta_membership_changes_in_from_to_range:
1301
+ room_id = membership_change.room_id
1302
+
1303
+ last_membership_change_by_room_id_in_from_to_range[room_id] = (
1304
+ membership_change
1305
+ )
1306
+ # Only set if we haven't already set it
1307
+ first_membership_change_by_room_id_in_from_to_range.setdefault(
1308
+ room_id, membership_change
1309
+ )
1310
+
1311
+ if membership_change.membership != Membership.JOIN:
1312
+ has_non_join_event_by_room_id_in_from_to_range[room_id] = True
1313
+
1314
+ # 1) Fixup
1315
+ #
1316
+ # 2) We also want to assemble a list of possibly newly joined rooms. Someone
1317
+ # could have left and joined multiple times during the given range but we only
1318
+ # care about whether they are joined at the end of the token range so we are
1319
+ # working with the last membership even in the token range.
1320
+ possibly_newly_joined_room_ids = set()
1321
+ for (
1322
+ last_membership_change_in_from_to_range
1323
+ ) in last_membership_change_by_room_id_in_from_to_range.values():
1324
+ room_id = last_membership_change_in_from_to_range.room_id
1325
+
1326
+ # 2)
1327
+ if last_membership_change_in_from_to_range.membership == Membership.JOIN:
1328
+ possibly_newly_joined_room_ids.add(room_id)
1329
+
1330
+ # 1) Figure out newly_left rooms (> `from_token` and <= `to_token`).
1331
+ if last_membership_change_in_from_to_range.membership == Membership.LEAVE:
1332
+ # 1) Mark this room as `newly_left`
1333
+ newly_left_room_map[room_id] = RoomsForUserStateReset(
1334
+ room_id=room_id,
1335
+ sender=last_membership_change_in_from_to_range.sender,
1336
+ membership=Membership.LEAVE,
1337
+ event_id=last_membership_change_in_from_to_range.event_id,
1338
+ event_pos=last_membership_change_in_from_to_range.event_pos,
1339
+ room_version_id=await self.store.get_room_version_id(room_id),
1340
+ )
1341
+
1342
+ # 2) Figure out `newly_joined`
1343
+ for room_id in possibly_newly_joined_room_ids:
1344
+ has_non_join_in_from_to_range = (
1345
+ has_non_join_event_by_room_id_in_from_to_range.get(room_id, False)
1346
+ )
1347
+ # If the last membership event in the token range is a join and there is
1348
+ # also some non-join in the range, we know they `newly_joined`.
1349
+ if has_non_join_in_from_to_range:
1350
+ # We found a `newly_joined` room (we left and joined within the token range)
1351
+ newly_joined_room_ids.add(room_id)
1352
+ else:
1353
+ prev_event_id = first_membership_change_by_room_id_in_from_to_range[
1354
+ room_id
1355
+ ].prev_event_id
1356
+ prev_membership = first_membership_change_by_room_id_in_from_to_range[
1357
+ room_id
1358
+ ].prev_membership
1359
+
1360
+ if prev_event_id is None:
1361
+ # We found a `newly_joined` room (we are joining the room for the
1362
+ # first time within the token range)
1363
+ newly_joined_room_ids.add(room_id)
1364
+ # Last resort, we need to step back to the previous membership event
1365
+ # just before the token range to see if we're joined then or not.
1366
+ elif prev_membership != Membership.JOIN:
1367
+ # We found a `newly_joined` room (we left before the token range
1368
+ # and joined within the token range)
1369
+ newly_joined_room_ids.add(room_id)
1370
+
1371
+ return newly_joined_room_ids, newly_left_room_map
1372
+
1373
+ @trace
1374
+ async def _get_dm_rooms_for_user(
1375
+ self,
1376
+ user_id: str,
1377
+ ) -> AbstractSet[str]:
1378
+ """Get the set of DM rooms for the user."""
1379
+
1380
+ # We're using global account data (`m.direct`) instead of checking for
1381
+ # `is_direct` on membership events because that property only appears for
1382
+ # the invitee membership event (doesn't show up for the inviter).
1383
+ #
1384
+ # We're unable to take `to_token` into account for global account data since
1385
+ # we only keep track of the latest account data for the user.
1386
+ dm_map = await self.store.get_global_account_data_by_type_for_user(
1387
+ user_id, AccountDataTypes.DIRECT
1388
+ )
1389
+
1390
+ # Flatten out the map. Account data is set by the client so it needs to be
1391
+ # scrutinized.
1392
+ dm_room_id_set = set()
1393
+ if isinstance(dm_map, dict):
1394
+ for room_ids in dm_map.values():
1395
+ # Account data should be a list of room IDs. Ignore anything else
1396
+ if isinstance(room_ids, list):
1397
+ for room_id in room_ids:
1398
+ if isinstance(room_id, str):
1399
+ dm_room_id_set.add(room_id)
1400
+
1401
+ return dm_room_id_set
1402
+
1403
+ @trace
1404
+ async def filter_rooms_relevant_for_sync(
1405
+ self,
1406
+ user: UserID,
1407
+ room_membership_for_user_map: dict[str, RoomsForUserType],
1408
+ newly_left_room_ids: AbstractSet[str],
1409
+ ) -> dict[str, RoomsForUserType]:
1410
+ """
1411
+ Filter room IDs that should/can be listed for this user in the sync response (the
1412
+ full room list that will be further filtered, sorted, and sliced).
1413
+
1414
+ We're looking for rooms where the user has the following state in the token
1415
+ range (> `from_token` and <= `to_token`):
1416
+
1417
+ - `invite`, `join`, `knock`, `ban` membership events
1418
+ - Kicks (`leave` membership events where `sender` is different from the
1419
+ `user_id`/`state_key`)
1420
+ - `newly_left` (rooms that were left during the given token range)
1421
+ - In order for bans/kicks to not show up in sync, you need to `/forget` those
1422
+ rooms. This doesn't modify the event itself though and only adds the
1423
+ `forgotten` flag to the `room_memberships` table in Synapse. There isn't a way
1424
+ to tell when a room was forgotten at the moment so we can't factor it into the
1425
+ from/to range.
1426
+
1427
+ Args:
1428
+ user: User that is syncing
1429
+ room_membership_for_user_map: Room membership for the user
1430
+ newly_left_room_ids: The set of room IDs we have newly left
1431
+
1432
+ Returns:
1433
+ A dictionary of room IDs that should be listed in the sync response along
1434
+ with membership information in that room at the time of `to_token`.
1435
+ """
1436
+ user_id = user.to_string()
1437
+
1438
+ # Filter rooms to only what we're interested to sync with
1439
+ filtered_sync_room_map = {
1440
+ room_id: room_membership_for_user
1441
+ for room_id, room_membership_for_user in room_membership_for_user_map.items()
1442
+ if filter_membership_for_sync(
1443
+ user_id=user_id,
1444
+ room_membership_for_user=room_membership_for_user,
1445
+ newly_left=room_id in newly_left_room_ids,
1446
+ )
1447
+ }
1448
+
1449
+ return filtered_sync_room_map
1450
+
1451
+ async def check_room_subscription_allowed_for_user(
1452
+ self,
1453
+ room_id: str,
1454
+ room_membership_for_user_map: dict[str, RoomsForUserType],
1455
+ to_token: StreamToken,
1456
+ ) -> RoomsForUserType | None:
1457
+ """
1458
+ Check whether the user is allowed to see the room based on whether they have
1459
+ ever had membership in the room or if the room is `world_readable`.
1460
+
1461
+ Similar to `check_user_in_room_or_world_readable(...)`
1462
+
1463
+ Args:
1464
+ room_id: Room to check
1465
+ room_membership_for_user_map: Room membership for the user at the time of
1466
+ the `to_token` (<= `to_token`).
1467
+ to_token: The token to fetch rooms up to.
1468
+
1469
+ Returns:
1470
+ The room membership for the user if they are allowed to subscribe to the
1471
+ room else `None`.
1472
+ """
1473
+
1474
+ # We can first check if they are already allowed to see the room based
1475
+ # on our previous work to assemble the `room_membership_for_user_map`.
1476
+ #
1477
+ # If they have had any membership in the room over time (up to the `to_token`),
1478
+ # let them subscribe and see what they can.
1479
+ existing_membership_for_user = room_membership_for_user_map.get(room_id)
1480
+ if existing_membership_for_user is not None:
1481
+ return existing_membership_for_user
1482
+
1483
+ # TODO: Handle `world_readable` rooms
1484
+ return None
1485
+
1486
+ # If the room is `world_readable`, it doesn't matter whether they can join,
1487
+ # everyone can see the room.
1488
+ # not_in_room_membership_for_user = _RoomMembershipForUser(
1489
+ # room_id=room_id,
1490
+ # event_id=None,
1491
+ # event_pos=None,
1492
+ # membership=None,
1493
+ # sender=None,
1494
+ # newly_joined=False,
1495
+ # newly_left=False,
1496
+ # is_dm=False,
1497
+ # )
1498
+ # room_state = await self.get_current_state_at(
1499
+ # room_id=room_id,
1500
+ # room_membership_for_user_at_to_token=not_in_room_membership_for_user,
1501
+ # state_filter=StateFilter.from_types(
1502
+ # [(EventTypes.RoomHistoryVisibility, "")]
1503
+ # ),
1504
+ # to_token=to_token,
1505
+ # )
1506
+
1507
+ # visibility_event = room_state.get((EventTypes.RoomHistoryVisibility, ""))
1508
+ # if (
1509
+ # visibility_event is not None
1510
+ # and visibility_event.content.get("history_visibility")
1511
+ # == HistoryVisibility.WORLD_READABLE
1512
+ # ):
1513
+ # return not_in_room_membership_for_user
1514
+
1515
+ # return None
1516
+
1517
+ @trace
1518
+ async def _bulk_get_stripped_state_for_rooms_from_sync_room_map(
1519
+ self,
1520
+ room_ids: StrCollection,
1521
+ sync_room_map: dict[str, RoomsForUserType],
1522
+ ) -> dict[str, StateMap[StrippedStateEvent] | None]:
1523
+ """
1524
+ Fetch stripped state for a list of room IDs. Stripped state is only
1525
+ applicable to invite/knock rooms. Other rooms will have `None` as their
1526
+ stripped state.
1527
+
1528
+ For invite rooms, we pull from `unsigned.invite_room_state`.
1529
+ For knock rooms, we pull from `unsigned.knock_room_state`.
1530
+
1531
+ Args:
1532
+ room_ids: Room IDs to fetch stripped state for
1533
+ sync_room_map: Dictionary of room IDs to sort along with membership
1534
+ information in the room at the time of `to_token`.
1535
+
1536
+ Returns:
1537
+ Mapping from room_id to mapping of (type, state_key) to stripped state
1538
+ event.
1539
+ """
1540
+ room_id_to_stripped_state_map: dict[
1541
+ str, StateMap[StrippedStateEvent] | None
1542
+ ] = {}
1543
+
1544
+ # Fetch what we haven't before
1545
+ room_ids_to_fetch = [
1546
+ room_id
1547
+ for room_id in room_ids
1548
+ if room_id not in room_id_to_stripped_state_map
1549
+ ]
1550
+
1551
+ # Gather a list of event IDs we can grab stripped state from
1552
+ invite_or_knock_event_ids: list[str] = []
1553
+ for room_id in room_ids_to_fetch:
1554
+ if sync_room_map[room_id].membership in (
1555
+ Membership.INVITE,
1556
+ Membership.KNOCK,
1557
+ ):
1558
+ event_id = sync_room_map[room_id].event_id
1559
+ # If this is an invite/knock then there should be an event_id
1560
+ assert event_id is not None
1561
+ invite_or_knock_event_ids.append(event_id)
1562
+ else:
1563
+ room_id_to_stripped_state_map[room_id] = None
1564
+
1565
+ invite_or_knock_events = await self.store.get_events(invite_or_knock_event_ids)
1566
+ for invite_or_knock_event in invite_or_knock_events.values():
1567
+ room_id = invite_or_knock_event.room_id
1568
+ membership = invite_or_knock_event.membership
1569
+
1570
+ raw_stripped_state_events = None
1571
+ if membership == Membership.INVITE:
1572
+ invite_room_state = invite_or_knock_event.unsigned.get(
1573
+ "invite_room_state"
1574
+ )
1575
+ raw_stripped_state_events = invite_room_state
1576
+ elif membership == Membership.KNOCK:
1577
+ knock_room_state = invite_or_knock_event.unsigned.get(
1578
+ "knock_room_state"
1579
+ )
1580
+ raw_stripped_state_events = knock_room_state
1581
+ else:
1582
+ raise AssertionError(
1583
+ f"Unexpected membership {membership} (this is a problem with Synapse itself)"
1584
+ )
1585
+
1586
+ stripped_state_map: MutableStateMap[StrippedStateEvent] | None = None
1587
+ # Scrutinize unsigned things. `raw_stripped_state_events` should be a list
1588
+ # of stripped events
1589
+ if raw_stripped_state_events is not None:
1590
+ stripped_state_map = {}
1591
+ if isinstance(raw_stripped_state_events, list):
1592
+ for raw_stripped_event in raw_stripped_state_events:
1593
+ stripped_state_event = parse_stripped_state_event(
1594
+ raw_stripped_event
1595
+ )
1596
+ if stripped_state_event is not None:
1597
+ stripped_state_map[
1598
+ (
1599
+ stripped_state_event.type,
1600
+ stripped_state_event.state_key,
1601
+ )
1602
+ ] = stripped_state_event
1603
+
1604
+ room_id_to_stripped_state_map[room_id] = stripped_state_map
1605
+
1606
+ return room_id_to_stripped_state_map
1607
+
1608
+ @trace
1609
+ async def _bulk_get_partial_current_state_content_for_rooms(
1610
+ self,
1611
+ content_type: Literal[
1612
+ # `content.type` from `EventTypes.Create``
1613
+ "room_type",
1614
+ # `content.algorithm` from `EventTypes.RoomEncryption`
1615
+ "room_encryption",
1616
+ ],
1617
+ room_ids: set[str],
1618
+ sync_room_map: dict[str, RoomsForUserType],
1619
+ to_token: StreamToken,
1620
+ room_id_to_stripped_state_map: dict[str, StateMap[StrippedStateEvent] | None],
1621
+ ) -> Mapping[str, str | None | StateSentinel]:
1622
+ """
1623
+ Get the given state event content for a list of rooms. First we check the
1624
+ current state of the room, then fallback to stripped state if available, then
1625
+ historical state.
1626
+
1627
+ Args:
1628
+ content_type: Which content to grab
1629
+ room_ids: Room IDs to fetch the given content field for.
1630
+ sync_room_map: Dictionary of room IDs to sort along with membership
1631
+ information in the room at the time of `to_token`.
1632
+ to_token: We filter based on the state of the room at this token
1633
+ room_id_to_stripped_state_map: This does not need to be filled in before
1634
+ calling this function. Mapping from room_id to mapping of (type, state_key)
1635
+ to stripped state event. Modified in place when we fetch new rooms so we can
1636
+ save work next time this function is called.
1637
+
1638
+ Returns:
1639
+ A mapping from room ID to the state event content if the room has
1640
+ the given state event (event_type, ""), otherwise `None`. Rooms unknown to
1641
+ this server will return `ROOM_UNKNOWN_SENTINEL`.
1642
+ """
1643
+ room_id_to_content: dict[str, str | None | StateSentinel] = {}
1644
+
1645
+ # As a bulk shortcut, use the current state if the server is particpating in the
1646
+ # room (meaning we have current state). Ideally, for leave/ban rooms, we would
1647
+ # want the state at the time of the membership instead of current state to not
1648
+ # leak anything but we consider the create/encryption stripped state events to
1649
+ # not be a secret given they are often set at the start of the room and they are
1650
+ # normally handed out on invite/knock.
1651
+ #
1652
+ # Be mindful to only use this for non-sensitive details. For example, even
1653
+ # though the room name/avatar/topic are also stripped state, they seem a lot
1654
+ # more senstive to leak the current state value of.
1655
+ #
1656
+ # Since this function is cached, we need to make a mutable copy via
1657
+ # `dict(...)`.
1658
+ event_type = ""
1659
+ event_content_field = ""
1660
+ if content_type == "room_type":
1661
+ event_type = EventTypes.Create
1662
+ event_content_field = EventContentFields.ROOM_TYPE
1663
+ room_id_to_content = dict(await self.store.bulk_get_room_type(room_ids))
1664
+ elif content_type == "room_encryption":
1665
+ event_type = EventTypes.RoomEncryption
1666
+ event_content_field = EventContentFields.ENCRYPTION_ALGORITHM
1667
+ room_id_to_content = dict(
1668
+ await self.store.bulk_get_room_encryption(room_ids)
1669
+ )
1670
+ else:
1671
+ assert_never(content_type)
1672
+
1673
+ room_ids_with_results = [
1674
+ room_id
1675
+ for room_id, content_field in room_id_to_content.items()
1676
+ if content_field is not ROOM_UNKNOWN_SENTINEL
1677
+ ]
1678
+
1679
+ # We might not have current room state for remote invite/knocks if we are
1680
+ # the first person on our server to see the room. The best we can do is look
1681
+ # in the optional stripped state from the invite/knock event.
1682
+ room_ids_without_results = room_ids.difference(
1683
+ chain(
1684
+ room_ids_with_results,
1685
+ [
1686
+ room_id
1687
+ for room_id, stripped_state_map in room_id_to_stripped_state_map.items()
1688
+ if stripped_state_map is not None
1689
+ ],
1690
+ )
1691
+ )
1692
+ room_id_to_stripped_state_map.update(
1693
+ await self._bulk_get_stripped_state_for_rooms_from_sync_room_map(
1694
+ room_ids_without_results, sync_room_map
1695
+ )
1696
+ )
1697
+
1698
+ # Update our `room_id_to_content` map based on the stripped state
1699
+ # (applies to invite/knock rooms)
1700
+ rooms_ids_without_stripped_state: set[str] = set()
1701
+ for room_id in room_ids_without_results:
1702
+ stripped_state_map = room_id_to_stripped_state_map.get(
1703
+ room_id, Sentinel.UNSET_SENTINEL
1704
+ )
1705
+ assert stripped_state_map is not Sentinel.UNSET_SENTINEL, (
1706
+ f"Stripped state left unset for room {room_id}. "
1707
+ + "Make sure you're calling `_bulk_get_stripped_state_for_rooms_from_sync_room_map(...)` "
1708
+ + "with that room_id. (this is a problem with Synapse itself)"
1709
+ )
1710
+
1711
+ # If there is some stripped state, we assume the remote server passed *all*
1712
+ # of the potential stripped state events for the room.
1713
+ if stripped_state_map is not None:
1714
+ create_stripped_event = stripped_state_map.get((EventTypes.Create, ""))
1715
+ stripped_event = stripped_state_map.get((event_type, ""))
1716
+ # Sanity check that we at-least have the create event
1717
+ if create_stripped_event is not None:
1718
+ if stripped_event is not None:
1719
+ room_id_to_content[room_id] = stripped_event.content.get(
1720
+ event_content_field
1721
+ )
1722
+ else:
1723
+ # Didn't see the state event we're looking for in the stripped
1724
+ # state so we can assume relevant content field is `None`.
1725
+ room_id_to_content[room_id] = None
1726
+ else:
1727
+ rooms_ids_without_stripped_state.add(room_id)
1728
+
1729
+ # Last resort, we might not have current room state for rooms that the
1730
+ # server has left (no one local is in the room) but we can look at the
1731
+ # historical state.
1732
+ #
1733
+ # Update our `room_id_to_content` map based on the state at the time of
1734
+ # the membership event.
1735
+ for room_id in rooms_ids_without_stripped_state:
1736
+ # TODO: It would be nice to look this up in a bulk way (N+1 queries)
1737
+ #
1738
+ # TODO: `get_state_at(...)` doesn't take into account the "current state".
1739
+ room_state = await self.storage_controllers.state.get_state_at(
1740
+ room_id=room_id,
1741
+ stream_position=to_token.copy_and_replace(
1742
+ StreamKeyType.ROOM,
1743
+ sync_room_map[room_id].event_pos.to_room_stream_token(),
1744
+ ),
1745
+ state_filter=StateFilter.from_types(
1746
+ [
1747
+ (EventTypes.Create, ""),
1748
+ (event_type, ""),
1749
+ ]
1750
+ ),
1751
+ # Partially-stated rooms should have all state events except for
1752
+ # remote membership events so we don't need to wait at all because
1753
+ # we only want the create event and some non-member event.
1754
+ await_full_state=False,
1755
+ )
1756
+ # We can use the create event as a canary to tell whether the server has
1757
+ # seen the room before
1758
+ create_event = room_state.get((EventTypes.Create, ""))
1759
+ state_event = room_state.get((event_type, ""))
1760
+
1761
+ if create_event is None:
1762
+ # Skip for unknown rooms
1763
+ continue
1764
+
1765
+ if state_event is not None:
1766
+ room_id_to_content[room_id] = state_event.content.get(
1767
+ event_content_field
1768
+ )
1769
+ else:
1770
+ # Didn't see the state event we're looking for in the stripped
1771
+ # state so we can assume relevant content field is `None`.
1772
+ room_id_to_content[room_id] = None
1773
+
1774
+ return room_id_to_content
1775
+
1776
+ @trace
1777
+ async def filter_rooms(
1778
+ self,
1779
+ user: UserID,
1780
+ sync_room_map: dict[str, RoomsForUserType],
1781
+ previous_connection_state: PerConnectionState,
1782
+ filters: SlidingSyncConfig.SlidingSyncList.Filters,
1783
+ to_token: StreamToken,
1784
+ dm_room_ids: AbstractSet[str],
1785
+ ) -> dict[str, RoomsForUserType]:
1786
+ """
1787
+ Filter rooms based on the sync request.
1788
+
1789
+ Args:
1790
+ user: User to filter rooms for
1791
+ sync_room_map: Dictionary of room IDs to sort along with membership
1792
+ information in the room at the time of `to_token`.
1793
+ filters: Filters to apply
1794
+ to_token: We filter based on the state of the room at this token
1795
+ dm_room_ids: Set of room IDs that are DMs for the user
1796
+
1797
+ Returns:
1798
+ A filtered dictionary of room IDs along with membership information in the
1799
+ room at the time of `to_token`.
1800
+ """
1801
+ user_id = user.to_string()
1802
+
1803
+ room_id_to_stripped_state_map: dict[
1804
+ str, StateMap[StrippedStateEvent] | None
1805
+ ] = {}
1806
+
1807
+ filtered_room_id_set = set(sync_room_map.keys())
1808
+
1809
+ # Filter for Direct-Message (DM) rooms
1810
+ if filters.is_dm is not None:
1811
+ with start_active_span("filters.is_dm"):
1812
+ if filters.is_dm:
1813
+ # Only DM rooms please
1814
+ filtered_room_id_set = {
1815
+ room_id
1816
+ for room_id in filtered_room_id_set
1817
+ if room_id in dm_room_ids
1818
+ }
1819
+ else:
1820
+ # Only non-DM rooms please
1821
+ filtered_room_id_set = {
1822
+ room_id
1823
+ for room_id in filtered_room_id_set
1824
+ if room_id not in dm_room_ids
1825
+ }
1826
+
1827
+ if filters.spaces is not None:
1828
+ with start_active_span("filters.spaces"):
1829
+ raise NotImplementedError()
1830
+
1831
+ # Filter for encrypted rooms
1832
+ if filters.is_encrypted is not None:
1833
+ with start_active_span("filters.is_encrypted"):
1834
+ room_id_to_encryption = (
1835
+ await self._bulk_get_partial_current_state_content_for_rooms(
1836
+ content_type="room_encryption",
1837
+ room_ids=filtered_room_id_set,
1838
+ to_token=to_token,
1839
+ sync_room_map=sync_room_map,
1840
+ room_id_to_stripped_state_map=room_id_to_stripped_state_map,
1841
+ )
1842
+ )
1843
+
1844
+ # Make a copy so we don't run into an error: `Set changed size during
1845
+ # iteration`, when we filter out and remove items
1846
+ for room_id in filtered_room_id_set.copy():
1847
+ encryption = room_id_to_encryption.get(
1848
+ room_id, ROOM_UNKNOWN_SENTINEL
1849
+ )
1850
+
1851
+ # Just remove rooms if we can't determine their encryption status
1852
+ if encryption is ROOM_UNKNOWN_SENTINEL:
1853
+ filtered_room_id_set.remove(room_id)
1854
+ continue
1855
+
1856
+ # If we're looking for encrypted rooms, filter out rooms that are not
1857
+ # encrypted and vice versa
1858
+ is_encrypted = encryption is not None
1859
+ if (filters.is_encrypted and not is_encrypted) or (
1860
+ not filters.is_encrypted and is_encrypted
1861
+ ):
1862
+ filtered_room_id_set.remove(room_id)
1863
+
1864
+ # Filter for rooms that the user has been invited to
1865
+ if filters.is_invite is not None:
1866
+ with start_active_span("filters.is_invite"):
1867
+ # Make a copy so we don't run into an error: `Set changed size during
1868
+ # iteration`, when we filter out and remove items
1869
+ for room_id in filtered_room_id_set.copy():
1870
+ room_for_user = sync_room_map[room_id]
1871
+ # If we're looking for invite rooms, filter out rooms that the user is
1872
+ # not invited to and vice versa
1873
+ if (
1874
+ filters.is_invite
1875
+ and room_for_user.membership != Membership.INVITE
1876
+ ) or (
1877
+ not filters.is_invite
1878
+ and room_for_user.membership == Membership.INVITE
1879
+ ):
1880
+ filtered_room_id_set.remove(room_id)
1881
+
1882
+ # Filter by room type (space vs room, etc). A room must match one of the types
1883
+ # provided in the list. `None` is a valid type for rooms which do not have a
1884
+ # room type.
1885
+ if filters.room_types is not None or filters.not_room_types is not None:
1886
+ with start_active_span("filters.room_types"):
1887
+ room_id_to_type = (
1888
+ await self._bulk_get_partial_current_state_content_for_rooms(
1889
+ content_type="room_type",
1890
+ room_ids=filtered_room_id_set,
1891
+ to_token=to_token,
1892
+ sync_room_map=sync_room_map,
1893
+ room_id_to_stripped_state_map=room_id_to_stripped_state_map,
1894
+ )
1895
+ )
1896
+
1897
+ # Make a copy so we don't run into an error: `Set changed size during
1898
+ # iteration`, when we filter out and remove items
1899
+ for room_id in filtered_room_id_set.copy():
1900
+ room_type = room_id_to_type.get(room_id, ROOM_UNKNOWN_SENTINEL)
1901
+
1902
+ # Just remove rooms if we can't determine their type
1903
+ if room_type is ROOM_UNKNOWN_SENTINEL:
1904
+ filtered_room_id_set.remove(room_id)
1905
+ continue
1906
+
1907
+ if (
1908
+ filters.room_types is not None
1909
+ and room_type not in filters.room_types
1910
+ ):
1911
+ filtered_room_id_set.remove(room_id)
1912
+ continue
1913
+
1914
+ if (
1915
+ filters.not_room_types is not None
1916
+ and room_type in filters.not_room_types
1917
+ ):
1918
+ filtered_room_id_set.remove(room_id)
1919
+ continue
1920
+
1921
+ if filters.room_name_like is not None:
1922
+ with start_active_span("filters.room_name_like"):
1923
+ # TODO: The room name is a bit more sensitive to leak than the
1924
+ # create/encryption event. Maybe we should consider a better way to fetch
1925
+ # historical state before implementing this.
1926
+ #
1927
+ # room_id_to_create_content = await self._bulk_get_partial_current_state_content_for_rooms(
1928
+ # content_type="room_name",
1929
+ # room_ids=filtered_room_id_set,
1930
+ # to_token=to_token,
1931
+ # sync_room_map=sync_room_map,
1932
+ # room_id_to_stripped_state_map=room_id_to_stripped_state_map,
1933
+ # )
1934
+ raise NotImplementedError()
1935
+
1936
+ # Filter by room tags according to the users account data
1937
+ if filters.tags is not None or filters.not_tags is not None:
1938
+ with start_active_span("filters.tags"):
1939
+ # Fetch the user tags for their rooms
1940
+ room_tags = await self.store.get_tags_for_user(user_id)
1941
+ room_id_to_tag_name_set: dict[str, set[str]] = {
1942
+ room_id: set(tags.keys()) for room_id, tags in room_tags.items()
1943
+ }
1944
+
1945
+ if filters.tags is not None:
1946
+ tags_set = set(filters.tags)
1947
+ filtered_room_id_set = {
1948
+ room_id
1949
+ for room_id in filtered_room_id_set
1950
+ # Remove rooms that don't have one of the tags in the filter
1951
+ if room_id_to_tag_name_set.get(room_id, set()).intersection(
1952
+ tags_set
1953
+ )
1954
+ }
1955
+
1956
+ if filters.not_tags is not None:
1957
+ not_tags_set = set(filters.not_tags)
1958
+ filtered_room_id_set = {
1959
+ room_id
1960
+ for room_id in filtered_room_id_set
1961
+ # Remove rooms if they have any of the tags in the filter
1962
+ if not room_id_to_tag_name_set.get(room_id, set()).intersection(
1963
+ not_tags_set
1964
+ )
1965
+ }
1966
+
1967
+ # Keep rooms if the user has been state reset out of it but we previously sent
1968
+ # down the connection before. We want to make sure that we send these down to
1969
+ # the client regardless of filters so they find out about the state reset.
1970
+ #
1971
+ # We don't always have access to the state in a room after being state reset if
1972
+ # no one else locally on the server is participating in the room so we patch
1973
+ # these back in manually.
1974
+ state_reset_out_of_room_id_set = {
1975
+ room_id
1976
+ for room_id in sync_room_map.keys()
1977
+ if sync_room_map[room_id].event_id is None
1978
+ and previous_connection_state.rooms.have_sent_room(room_id).status
1979
+ != HaveSentRoomFlag.NEVER
1980
+ }
1981
+
1982
+ # Assemble a new sync room map but only with the `filtered_room_id_set`
1983
+ return {
1984
+ room_id: sync_room_map[room_id]
1985
+ for room_id in filtered_room_id_set | state_reset_out_of_room_id_set
1986
+ }
1987
+
1988
+ @trace
1989
+ async def filter_rooms_using_tables(
1990
+ self,
1991
+ user_id: str,
1992
+ sync_room_map: Mapping[str, RoomsForUserSlidingSync],
1993
+ previous_connection_state: PerConnectionState,
1994
+ filters: SlidingSyncConfig.SlidingSyncList.Filters,
1995
+ to_token: StreamToken,
1996
+ dm_room_ids: AbstractSet[str],
1997
+ ) -> dict[str, RoomsForUserSlidingSync]:
1998
+ """
1999
+ Filter rooms based on the sync request.
2000
+
2001
+ Args:
2002
+ user: User to filter rooms for
2003
+ sync_room_map: Dictionary of room IDs to sort along with membership
2004
+ information in the room at the time of `to_token`.
2005
+ filters: Filters to apply
2006
+ to_token: We filter based on the state of the room at this token
2007
+ dm_room_ids: Set of room IDs which are DMs
2008
+ room_tags: Mapping of room ID to tags
2009
+
2010
+ Returns:
2011
+ A filtered dictionary of room IDs along with membership information in the
2012
+ room at the time of `to_token`.
2013
+ """
2014
+
2015
+ filtered_room_id_set = set(sync_room_map.keys())
2016
+
2017
+ # Filter for Direct-Message (DM) rooms
2018
+ if filters.is_dm is not None:
2019
+ with start_active_span("filters.is_dm"):
2020
+ if filters.is_dm:
2021
+ # Intersect with the DM room set
2022
+ filtered_room_id_set &= dm_room_ids
2023
+ else:
2024
+ # Remove DMs
2025
+ filtered_room_id_set -= dm_room_ids
2026
+
2027
+ if filters.spaces is not None:
2028
+ with start_active_span("filters.spaces"):
2029
+ raise NotImplementedError()
2030
+
2031
+ # Filter for encrypted rooms
2032
+ if filters.is_encrypted is not None:
2033
+ filtered_room_id_set = {
2034
+ room_id
2035
+ for room_id in filtered_room_id_set
2036
+ # Remove rooms if we can't figure out what the encryption status is
2037
+ if sync_room_map[room_id].has_known_state
2038
+ # Or remove if it doesn't match the filter
2039
+ and sync_room_map[room_id].is_encrypted == filters.is_encrypted
2040
+ }
2041
+
2042
+ # Filter for rooms that the user has been invited to
2043
+ if filters.is_invite is not None:
2044
+ with start_active_span("filters.is_invite"):
2045
+ # Make a copy so we don't run into an error: `Set changed size during
2046
+ # iteration`, when we filter out and remove items
2047
+ for room_id in filtered_room_id_set.copy():
2048
+ room_for_user = sync_room_map[room_id]
2049
+ # If we're looking for invite rooms, filter out rooms that the user is
2050
+ # not invited to and vice versa
2051
+ if (
2052
+ filters.is_invite
2053
+ and room_for_user.membership != Membership.INVITE
2054
+ ) or (
2055
+ not filters.is_invite
2056
+ and room_for_user.membership == Membership.INVITE
2057
+ ):
2058
+ filtered_room_id_set.remove(room_id)
2059
+
2060
+ # Filter by room type (space vs room, etc). A room must match one of the types
2061
+ # provided in the list. `None` is a valid type for rooms which do not have a
2062
+ # room type.
2063
+ if filters.room_types is not None or filters.not_room_types is not None:
2064
+ with start_active_span("filters.room_types"):
2065
+ # Make a copy so we don't run into an error: `Set changed size during
2066
+ # iteration`, when we filter out and remove items
2067
+ for room_id in filtered_room_id_set.copy():
2068
+ # Remove rooms if we can't figure out what room type it is
2069
+ if not sync_room_map[room_id].has_known_state:
2070
+ filtered_room_id_set.remove(room_id)
2071
+ continue
2072
+
2073
+ room_type = sync_room_map[room_id].room_type
2074
+
2075
+ if (
2076
+ filters.room_types is not None
2077
+ and room_type not in filters.room_types
2078
+ ):
2079
+ filtered_room_id_set.remove(room_id)
2080
+ continue
2081
+
2082
+ if (
2083
+ filters.not_room_types is not None
2084
+ and room_type in filters.not_room_types
2085
+ ):
2086
+ filtered_room_id_set.remove(room_id)
2087
+ continue
2088
+
2089
+ if filters.room_name_like is not None:
2090
+ with start_active_span("filters.room_name_like"):
2091
+ # TODO: The room name is a bit more sensitive to leak than the
2092
+ # create/encryption event. Maybe we should consider a better way to fetch
2093
+ # historical state before implementing this.
2094
+ #
2095
+ # room_id_to_create_content = await self._bulk_get_partial_current_state_content_for_rooms(
2096
+ # content_type="room_name",
2097
+ # room_ids=filtered_room_id_set,
2098
+ # to_token=to_token,
2099
+ # sync_room_map=sync_room_map,
2100
+ # room_id_to_stripped_state_map=room_id_to_stripped_state_map,
2101
+ # )
2102
+ raise NotImplementedError()
2103
+
2104
+ # Filter by room tags according to the users account data
2105
+ if filters.tags is not None or filters.not_tags is not None:
2106
+ with start_active_span("filters.tags"):
2107
+ # Fetch the user tags for their rooms
2108
+ room_tags = await self.store.get_tags_for_user(user_id)
2109
+ room_id_to_tag_name_set: dict[str, set[str]] = {
2110
+ room_id: set(tags.keys()) for room_id, tags in room_tags.items()
2111
+ }
2112
+
2113
+ if filters.tags is not None:
2114
+ tags_set = set(filters.tags)
2115
+ filtered_room_id_set = {
2116
+ room_id
2117
+ for room_id in filtered_room_id_set
2118
+ # Remove rooms that don't have one of the tags in the filter
2119
+ if room_id_to_tag_name_set.get(room_id, set()).intersection(
2120
+ tags_set
2121
+ )
2122
+ }
2123
+
2124
+ if filters.not_tags is not None:
2125
+ not_tags_set = set(filters.not_tags)
2126
+ filtered_room_id_set = {
2127
+ room_id
2128
+ for room_id in filtered_room_id_set
2129
+ # Remove rooms if they have any of the tags in the filter
2130
+ if not room_id_to_tag_name_set.get(room_id, set()).intersection(
2131
+ not_tags_set
2132
+ )
2133
+ }
2134
+
2135
+ # Keep rooms if the user has been state reset out of it but we previously sent
2136
+ # down the connection before. We want to make sure that we send these down to
2137
+ # the client regardless of filters so they find out about the state reset.
2138
+ #
2139
+ # We don't always have access to the state in a room after being state reset if
2140
+ # no one else locally on the server is participating in the room so we patch
2141
+ # these back in manually.
2142
+ state_reset_out_of_room_id_set = {
2143
+ room_id
2144
+ for room_id in sync_room_map.keys()
2145
+ if sync_room_map[room_id].event_id is None
2146
+ and previous_connection_state.rooms.have_sent_room(room_id).status
2147
+ != HaveSentRoomFlag.NEVER
2148
+ }
2149
+
2150
+ # Assemble a new sync room map but only with the `filtered_room_id_set`
2151
+ return {
2152
+ room_id: sync_room_map[room_id]
2153
+ for room_id in filtered_room_id_set | state_reset_out_of_room_id_set
2154
+ }
2155
+
2156
+ @trace
2157
+ async def sort_rooms(
2158
+ self,
2159
+ sync_room_map: dict[str, RoomsForUserType],
2160
+ to_token: StreamToken,
2161
+ limit: int | None = None,
2162
+ ) -> list[RoomsForUserType]:
2163
+ """
2164
+ Sort by `stream_ordering` of the last event that the user should see in the
2165
+ room. `stream_ordering` is unique so we get a stable sort.
2166
+
2167
+ If `limit` is specified then sort may return fewer entries, but will
2168
+ always return at least the top N rooms. This is useful as we don't always
2169
+ need to sort the full list, but are just interested in the top N.
2170
+
2171
+ Args:
2172
+ sync_room_map: Dictionary of room IDs to sort along with membership
2173
+ information in the room at the time of `to_token`.
2174
+ to_token: We sort based on the events in the room at this token (<= `to_token`)
2175
+ limit: The number of rooms that we need to return from the top of the list.
2176
+
2177
+ Returns:
2178
+ A sorted list of room IDs by `stream_ordering` along with membership information.
2179
+ """
2180
+
2181
+ # Assemble a map of room ID to the `stream_ordering` of the last activity that the
2182
+ # user should see in the room (<= `to_token`)
2183
+ last_activity_in_room_map: dict[str, int] = {}
2184
+
2185
+ # Same as above, except for positions that we know are in the event
2186
+ # stream cache.
2187
+ cached_positions: dict[str, int] = {}
2188
+
2189
+ earliest_cache_position = (
2190
+ self.store._events_stream_cache.get_earliest_known_position()
2191
+ )
2192
+
2193
+ for room_id, room_for_user in sync_room_map.items():
2194
+ if room_for_user.membership == Membership.JOIN:
2195
+ # For joined rooms check the stream change cache.
2196
+ cached_position = (
2197
+ self.store._events_stream_cache.get_max_pos_of_last_change(room_id)
2198
+ )
2199
+ if cached_position is not None:
2200
+ cached_positions[room_id] = cached_position
2201
+ else:
2202
+ # If the user has left/been invited/knocked/been banned from a
2203
+ # room, they shouldn't see anything past that point.
2204
+ #
2205
+ # FIXME: It's possible that people should see beyond this point
2206
+ # in invited/knocked cases if for example the room has
2207
+ # `invite`/`world_readable` history visibility, see
2208
+ # https://github.com/matrix-org/matrix-spec-proposals/pull/3575#discussion_r1653045932
2209
+ last_activity_in_room_map[room_id] = room_for_user.event_pos.stream
2210
+
2211
+ # If the stream position is in range of the stream change cache
2212
+ # we can include it.
2213
+ if room_for_user.event_pos.stream > earliest_cache_position:
2214
+ cached_positions[room_id] = room_for_user.event_pos.stream
2215
+
2216
+ # If we are only asked for the top N rooms, and we have enough from
2217
+ # looking in the stream change cache, then we can return early. This
2218
+ # is because the cache must include all entries above
2219
+ # `.get_earliest_known_position()`.
2220
+ if limit is not None and len(cached_positions) >= limit:
2221
+ # ... but first we need to handle the case where the cached max
2222
+ # position is greater than the to_token, in which case we do
2223
+ # actually query the DB. This should happen rarely, so can do it in
2224
+ # a loop.
2225
+ for room_id, position in list(cached_positions.items()):
2226
+ if position > to_token.room_key.stream:
2227
+ result = await self.store.get_last_event_pos_in_room_before_stream_ordering(
2228
+ room_id, to_token.room_key
2229
+ )
2230
+ if (
2231
+ result is not None
2232
+ and result[1].stream > earliest_cache_position
2233
+ ):
2234
+ # We have a stream position in the cached range.
2235
+ cached_positions[room_id] = result[1].stream
2236
+ else:
2237
+ # No position in the range, so we remove the entry.
2238
+ cached_positions.pop(room_id)
2239
+
2240
+ if limit is not None and len(cached_positions) >= limit:
2241
+ return sorted(
2242
+ (
2243
+ room
2244
+ for room in sync_room_map.values()
2245
+ if room.room_id in cached_positions
2246
+ ),
2247
+ # Sort by the last activity (stream_ordering) in the room
2248
+ key=lambda room_info: cached_positions[room_info.room_id],
2249
+ # We want descending order
2250
+ reverse=True,
2251
+ )
2252
+
2253
+ # For fully-joined rooms, we find the latest activity at/before the
2254
+ # `to_token`.
2255
+ joined_room_positions = (
2256
+ await self.store.bulk_get_last_event_pos_in_room_before_stream_ordering(
2257
+ [
2258
+ room_id
2259
+ for room_id, room_for_user in sync_room_map.items()
2260
+ if room_for_user.membership == Membership.JOIN
2261
+ ],
2262
+ to_token.room_key,
2263
+ )
2264
+ )
2265
+
2266
+ last_activity_in_room_map.update(joined_room_positions)
2267
+
2268
+ return sorted(
2269
+ sync_room_map.values(),
2270
+ # Sort by the last activity (stream_ordering) in the room
2271
+ key=lambda room_info: last_activity_in_room_map[room_info.room_id],
2272
+ # We want descending order
2273
+ reverse=True,
2274
+ )
2275
+
2276
+ async def get_is_encrypted_for_room_at_token(
2277
+ self, room_id: str, to_token: RoomStreamToken
2278
+ ) -> bool:
2279
+ """Get if the room is encrypted at the time."""
2280
+
2281
+ # Fetch the current encryption state
2282
+ state_ids = await self.store.get_partial_filtered_current_state_ids(
2283
+ room_id, StateFilter.from_types([(EventTypes.RoomEncryption, "")])
2284
+ )
2285
+ encryption_event_id = state_ids.get((EventTypes.RoomEncryption, ""))
2286
+
2287
+ # Now roll back the state by looking at the state deltas between
2288
+ # to_token and now.
2289
+ deltas = await self.store.get_current_state_deltas_for_room(
2290
+ room_id,
2291
+ from_token=to_token,
2292
+ to_token=self.store.get_room_max_token(),
2293
+ )
2294
+
2295
+ for delta in deltas:
2296
+ if delta.event_type != EventTypes.RoomEncryption:
2297
+ continue
2298
+
2299
+ # Found the first change, we look at the previous event ID to get
2300
+ # the state at the to token.
2301
+
2302
+ if delta.prev_event_id is None:
2303
+ # There is no prev event, so no encryption state event, so room is not encrypted
2304
+ return False
2305
+
2306
+ encryption_event_id = delta.prev_event_id
2307
+ break
2308
+
2309
+ # We didn't find an encryption state, room isn't encrypted
2310
+ if encryption_event_id is None:
2311
+ return False
2312
+
2313
+ # We found encryption state, check if content has a non-null algorithm
2314
+ encrypted_event = await self.store.get_event(encryption_event_id)
2315
+ algorithm = encrypted_event.content.get(EventContentFields.ENCRYPTION_ALGORITHM)
2316
+
2317
+ return algorithm is not None