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,1881 @@
1
+ #
2
+ # This file is licensed under the Affero General Public License (AGPL) version 3.
3
+ #
4
+ # Copyright 2019-2021 The Matrix.org Foundation C.I.C.
5
+ # Copyright (C) 2023 New Vector, Ltd
6
+ #
7
+ # This program is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Affero General Public License as
9
+ # published by the Free Software Foundation, either version 3 of the
10
+ # License, or (at your option) any later version.
11
+ #
12
+ # See the GNU Affero General Public License for more details:
13
+ # <https://www.gnu.org/licenses/agpl-3.0.html>.
14
+ #
15
+ # Originally licensed under the Apache License, Version 2.0:
16
+ # <http://www.apache.org/licenses/LICENSE-2.0>.
17
+ #
18
+ # [This file includes modifications made by New Vector Limited]
19
+ #
20
+ #
21
+ import time
22
+ import urllib.parse
23
+ from typing import (
24
+ Any,
25
+ BinaryIO,
26
+ Callable,
27
+ Collection,
28
+ Literal,
29
+ )
30
+ from unittest.mock import Mock
31
+ from urllib.parse import urlencode
32
+
33
+ import pymacaroons
34
+
35
+ from twisted.internet.testing import MemoryReactor
36
+ from twisted.web.resource import Resource
37
+
38
+ import synapse.rest.admin
39
+ from synapse.api.constants import ApprovalNoticeMedium, LoginType
40
+ from synapse.api.errors import Codes
41
+ from synapse.api.urls import LoginSSORedirectURIBuilder
42
+ from synapse.appservice import ApplicationService
43
+ from synapse.http.client import RawHeaders
44
+ from synapse.module_api import ModuleApi
45
+ from synapse.rest.client import account, devices, login, logout, profile, register
46
+ from synapse.rest.client.account import WhoamiRestServlet
47
+ from synapse.rest.synapse.client import build_synapse_client_resource_tree
48
+ from synapse.server import HomeServer
49
+ from synapse.types import JsonDict, UserID, create_requester
50
+ from synapse.util.clock import Clock
51
+
52
+ from tests import unittest
53
+ from tests.handlers.test_oidc import HAS_OIDC
54
+ from tests.handlers.test_saml import has_saml2
55
+ from tests.rest.client.utils import TEST_OIDC_CONFIG
56
+ from tests.server import FakeChannel
57
+ from tests.test_utils.html_parsers import TestHtmlParser
58
+ from tests.test_utils.oidc import FakeOidcServer
59
+ from tests.unittest import HomeserverTestCase, override_config, skip_unless
60
+
61
+ try:
62
+ from authlib.jose import JsonWebKey, jwt
63
+
64
+ HAS_JWT = True
65
+ except ImportError:
66
+ HAS_JWT = False
67
+
68
+ import logging
69
+
70
+ logger = logging.getLogger(__name__)
71
+
72
+
73
+ # synapse server name: used to populate public_baseurl in some tests
74
+ SYNAPSE_SERVER_PUBLIC_HOSTNAME = "synapse"
75
+
76
+ # public_baseurl for some tests. It uses an http:// scheme because
77
+ # FakeChannel.isSecure() returns False, so synapse will see the requested uri as
78
+ # http://..., so using http in the public_baseurl stops Synapse trying to redirect to
79
+ # https://....
80
+ PUBLIC_BASEURL = "http://%s/" % (SYNAPSE_SERVER_PUBLIC_HOSTNAME,)
81
+
82
+ # CAS server used in some tests
83
+ CAS_SERVER = "https://fake.test"
84
+
85
+ # just enough to tell pysaml2 where to redirect to
86
+ SAML_SERVER = "https://test.saml.server/idp/sso"
87
+ TEST_SAML_METADATA = """
88
+ <md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
89
+ <md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
90
+ <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="%(SAML_SERVER)s"/>
91
+ </md:IDPSSODescriptor>
92
+ </md:EntityDescriptor>
93
+ """ % {
94
+ "SAML_SERVER": SAML_SERVER,
95
+ }
96
+
97
+ LOGIN_URL = b"/_matrix/client/r0/login"
98
+ TEST_URL = b"/_matrix/client/r0/account/whoami"
99
+
100
+ # a (valid) url with some annoying characters in. %3D is =, %26 is &, %2B is +
101
+ TEST_CLIENT_REDIRECT_URL = 'https://x?<ab c>&q"+%3D%2B"="fö%26=o"'
102
+
103
+ # the query params in TEST_CLIENT_REDIRECT_URL
104
+ EXPECTED_CLIENT_REDIRECT_URL_PARAMS = [("<ab c>", ""), ('q" =+"', '"fö&=o"')]
105
+
106
+ # Login flows we expect to appear in the list after the normal ones.
107
+ ADDITIONAL_LOGIN_FLOWS = [
108
+ {"type": "m.login.application_service"},
109
+ ]
110
+
111
+
112
+ def get_relative_uri_from_absolute_uri(absolute_uri: str) -> str:
113
+ """
114
+ Peels off the path and query string from an absolute URI. Useful when interacting
115
+ with `make_request(...)` util function which expects a relative path instead of a
116
+ full URI.
117
+ """
118
+ parsed_uri = urllib.parse.urlparse(absolute_uri)
119
+ # Sanity check that we're working with an absolute URI
120
+ assert parsed_uri.scheme == "http" or parsed_uri.scheme == "https"
121
+
122
+ relative_uri = parsed_uri.path
123
+ if parsed_uri.query:
124
+ relative_uri += "?" + parsed_uri.query
125
+
126
+ return relative_uri
127
+
128
+
129
+ class TestSpamChecker:
130
+ def __init__(self, config: None, api: ModuleApi):
131
+ api.register_spam_checker_callbacks(
132
+ check_login_for_spam=self.check_login_for_spam,
133
+ )
134
+
135
+ @staticmethod
136
+ def parse_config(config: JsonDict) -> None:
137
+ return None
138
+
139
+ async def check_login_for_spam(
140
+ self,
141
+ user_id: str,
142
+ device_id: str | None,
143
+ initial_display_name: str | None,
144
+ request_info: Collection[tuple[str | None, str]],
145
+ auth_provider_id: str | None = None,
146
+ ) -> Literal["NOT_SPAM"] | tuple["synapse.module_api.errors.Codes", JsonDict]:
147
+ return "NOT_SPAM"
148
+
149
+
150
+ class DenyAllSpamChecker:
151
+ def __init__(self, config: None, api: ModuleApi):
152
+ api.register_spam_checker_callbacks(
153
+ check_login_for_spam=self.check_login_for_spam,
154
+ )
155
+
156
+ @staticmethod
157
+ def parse_config(config: JsonDict) -> None:
158
+ return None
159
+
160
+ async def check_login_for_spam(
161
+ self,
162
+ user_id: str,
163
+ device_id: str | None,
164
+ initial_display_name: str | None,
165
+ request_info: Collection[tuple[str | None, str]],
166
+ auth_provider_id: str | None = None,
167
+ ) -> Literal["NOT_SPAM"] | tuple["synapse.module_api.errors.Codes", JsonDict]:
168
+ # Return an odd set of values to ensure that they get correctly passed
169
+ # to the client.
170
+ return Codes.LIMIT_EXCEEDED, {"extra": "value"}
171
+
172
+
173
+ class LoginRestServletTestCase(unittest.HomeserverTestCase):
174
+ servlets = [
175
+ synapse.rest.admin.register_servlets_for_client_rest_resource,
176
+ login.register_servlets,
177
+ logout.register_servlets,
178
+ devices.register_servlets,
179
+ lambda hs, http_server: WhoamiRestServlet(hs).register(http_server),
180
+ register.register_servlets,
181
+ ]
182
+
183
+ def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer:
184
+ self.hs = self.setup_test_homeserver()
185
+ self.hs.config.registration.enable_registration = True
186
+ self.hs.config.registration.registrations_require_3pid = []
187
+ self.hs.config.registration.auto_join_rooms = []
188
+ self.hs.config.captcha.enable_registration_captcha = False
189
+
190
+ return self.hs
191
+
192
+ @override_config(
193
+ {
194
+ "rc_login": {
195
+ "address": {"per_second": 0.17, "burst_count": 5},
196
+ # Prevent the account login ratelimiter from raising first
197
+ #
198
+ # This is normally covered by the default test homeserver config
199
+ # which sets these values to 10000, but as we're overriding the entire
200
+ # rc_login dict here, we need to set this manually as well
201
+ "account": {"per_second": 10000, "burst_count": 10000},
202
+ },
203
+ }
204
+ )
205
+ def test_POST_ratelimiting_per_address(self) -> None:
206
+ # Create different users so we're sure not to be bothered by the per-user
207
+ # ratelimiter.
208
+ for i in range(6):
209
+ self.register_user("kermit" + str(i), "monkey")
210
+
211
+ for i in range(6):
212
+ params = {
213
+ "type": "m.login.password",
214
+ "identifier": {"type": "m.id.user", "user": "kermit" + str(i)},
215
+ "password": "monkey",
216
+ }
217
+ channel = self.make_request(b"POST", LOGIN_URL, params)
218
+
219
+ if i == 5:
220
+ self.assertEqual(channel.code, 429, msg=channel.result)
221
+ retry_after_ms = int(channel.json_body["retry_after_ms"])
222
+ retry_header = channel.headers.getRawHeaders("Retry-After")
223
+ else:
224
+ self.assertEqual(channel.code, 200, msg=channel.result)
225
+
226
+ # Since we're ratelimiting at 1 request/min, retry_after_ms should be lower
227
+ # than 1min.
228
+ self.assertLess(retry_after_ms, 6000)
229
+ assert retry_header
230
+ self.assertLessEqual(int(retry_header[0]), 6)
231
+
232
+ self.reactor.advance(retry_after_ms / 1000.0 + 1.0)
233
+
234
+ params = {
235
+ "type": "m.login.password",
236
+ "identifier": {"type": "m.id.user", "user": "kermit" + str(i)},
237
+ "password": "monkey",
238
+ }
239
+ channel = self.make_request(b"POST", LOGIN_URL, params)
240
+
241
+ self.assertEqual(channel.code, 200, msg=channel.result)
242
+
243
+ @override_config(
244
+ {
245
+ "rc_login": {
246
+ "account": {"per_second": 0.17, "burst_count": 5},
247
+ # Prevent the address login ratelimiter from raising first
248
+ #
249
+ # This is normally covered by the default test homeserver config
250
+ # which sets these values to 10000, but as we're overriding the entire
251
+ # rc_login dict here, we need to set this manually as well
252
+ "address": {"per_second": 10000, "burst_count": 10000},
253
+ },
254
+ }
255
+ )
256
+ def test_POST_ratelimiting_per_account(self) -> None:
257
+ self.register_user("kermit", "monkey")
258
+
259
+ for i in range(6):
260
+ params = {
261
+ "type": "m.login.password",
262
+ "identifier": {"type": "m.id.user", "user": "kermit"},
263
+ "password": "monkey",
264
+ }
265
+ channel = self.make_request(b"POST", LOGIN_URL, params)
266
+
267
+ if i == 5:
268
+ self.assertEqual(channel.code, 429, msg=channel.result)
269
+ retry_after_ms = int(channel.json_body["retry_after_ms"])
270
+ retry_header = channel.headers.getRawHeaders("Retry-After")
271
+ else:
272
+ self.assertEqual(channel.code, 200, msg=channel.result)
273
+
274
+ # Since we're ratelimiting at 1 request/min, retry_after_ms should be lower
275
+ # than 1min.
276
+ self.assertLess(retry_after_ms, 6000)
277
+ assert retry_header
278
+ self.assertLessEqual(int(retry_header[0]), 6)
279
+
280
+ self.reactor.advance(retry_after_ms / 1000.0)
281
+
282
+ params = {
283
+ "type": "m.login.password",
284
+ "identifier": {"type": "m.id.user", "user": "kermit"},
285
+ "password": "monkey",
286
+ }
287
+ channel = self.make_request(b"POST", LOGIN_URL, params)
288
+
289
+ self.assertEqual(channel.code, 200, msg=channel.result)
290
+
291
+ @override_config(
292
+ {
293
+ "rc_login": {
294
+ # Prevent the address login ratelimiter from raising first
295
+ #
296
+ # This is normally covered by the default test homeserver config
297
+ # which sets these values to 10000, but as we're overriding the entire
298
+ # rc_login dict here, we need to set this manually as well
299
+ "address": {"per_second": 10000, "burst_count": 10000},
300
+ "failed_attempts": {"per_second": 0.17, "burst_count": 5},
301
+ },
302
+ }
303
+ )
304
+ def test_POST_ratelimiting_per_account_failed_attempts(self) -> None:
305
+ self.register_user("kermit", "monkey")
306
+
307
+ for i in range(6):
308
+ params = {
309
+ "type": "m.login.password",
310
+ "identifier": {"type": "m.id.user", "user": "kermit"},
311
+ "password": "notamonkey",
312
+ }
313
+ channel = self.make_request(b"POST", LOGIN_URL, params)
314
+
315
+ if i == 5:
316
+ self.assertEqual(channel.code, 429, msg=channel.result)
317
+ retry_after_ms = int(channel.json_body["retry_after_ms"])
318
+ retry_header = channel.headers.getRawHeaders("Retry-After")
319
+ else:
320
+ self.assertEqual(channel.code, 403, msg=channel.result)
321
+
322
+ # Since we're ratelimiting at 1 request/min, retry_after_ms should be lower
323
+ # than 1min.
324
+ self.assertLess(retry_after_ms, 6000)
325
+ assert retry_header
326
+ self.assertLessEqual(int(retry_header[0]), 6)
327
+
328
+ self.reactor.advance(retry_after_ms / 1000.0 + 1.0)
329
+
330
+ params = {
331
+ "type": "m.login.password",
332
+ "identifier": {"type": "m.id.user", "user": "kermit"},
333
+ "password": "notamonkey",
334
+ }
335
+ channel = self.make_request(b"POST", LOGIN_URL, params)
336
+
337
+ self.assertEqual(channel.code, 403, msg=channel.result)
338
+
339
+ @override_config({"session_lifetime": "24h"})
340
+ def test_soft_logout(self) -> None:
341
+ self.register_user("kermit", "monkey")
342
+
343
+ # we shouldn't be able to make requests without an access token
344
+ channel = self.make_request(b"GET", TEST_URL)
345
+ self.assertEqual(channel.code, 401, msg=channel.result)
346
+ self.assertEqual(channel.json_body["errcode"], "M_MISSING_TOKEN")
347
+
348
+ # log in as normal
349
+ params = {
350
+ "type": "m.login.password",
351
+ "identifier": {"type": "m.id.user", "user": "kermit"},
352
+ "password": "monkey",
353
+ }
354
+ channel = self.make_request(b"POST", LOGIN_URL, params)
355
+
356
+ self.assertEqual(channel.code, 200, channel.result)
357
+ access_token = channel.json_body["access_token"]
358
+ device_id = channel.json_body["device_id"]
359
+
360
+ # we should now be able to make requests with the access token
361
+ channel = self.make_request(b"GET", TEST_URL, access_token=access_token)
362
+ self.assertEqual(channel.code, 200, channel.result)
363
+
364
+ # time passes
365
+ self.reactor.advance(24 * 3600)
366
+
367
+ # ... and we should be soft-logouted
368
+ channel = self.make_request(b"GET", TEST_URL, access_token=access_token)
369
+ self.assertEqual(channel.code, 401, channel.result)
370
+ self.assertEqual(channel.json_body["errcode"], "M_UNKNOWN_TOKEN")
371
+ self.assertEqual(channel.json_body["soft_logout"], True)
372
+
373
+ #
374
+ # test behaviour after deleting the expired device
375
+ #
376
+
377
+ # we now log in as a different device
378
+ access_token_2 = self.login("kermit", "monkey")
379
+
380
+ # more requests with the expired token should still return a soft-logout
381
+ self.reactor.advance(3600)
382
+ channel = self.make_request(b"GET", TEST_URL, access_token=access_token)
383
+ self.assertEqual(channel.code, 401, channel.result)
384
+ self.assertEqual(channel.json_body["errcode"], "M_UNKNOWN_TOKEN")
385
+ self.assertEqual(channel.json_body["soft_logout"], True)
386
+
387
+ # ... but if we delete that device, it will be a proper logout
388
+ self._delete_device(access_token_2, "kermit", "monkey", device_id)
389
+
390
+ channel = self.make_request(b"GET", TEST_URL, access_token=access_token)
391
+ self.assertEqual(channel.code, 401, channel.result)
392
+ self.assertEqual(channel.json_body["errcode"], "M_UNKNOWN_TOKEN")
393
+ self.assertEqual(channel.json_body["soft_logout"], False)
394
+
395
+ def _delete_device(
396
+ self, access_token: str, user_id: str, password: str, device_id: str
397
+ ) -> None:
398
+ """Perform the UI-Auth to delete a device"""
399
+ channel = self.make_request(
400
+ b"DELETE", "devices/" + device_id, access_token=access_token
401
+ )
402
+ self.assertEqual(channel.code, 401, channel.result)
403
+ # check it's a UI-Auth fail
404
+ self.assertEqual(
405
+ set(channel.json_body.keys()),
406
+ {"flows", "params", "session"},
407
+ channel.result,
408
+ )
409
+
410
+ auth = {
411
+ "type": "m.login.password",
412
+ # https://github.com/matrix-org/synapse/issues/5665
413
+ # "identifier": {"type": "m.id.user", "user": user_id},
414
+ "user": user_id,
415
+ "password": password,
416
+ "session": channel.json_body["session"],
417
+ }
418
+
419
+ channel = self.make_request(
420
+ b"DELETE",
421
+ "devices/" + device_id,
422
+ access_token=access_token,
423
+ content={"auth": auth},
424
+ )
425
+ self.assertEqual(channel.code, 200, channel.result)
426
+
427
+ @override_config({"session_lifetime": "24h"})
428
+ def test_session_can_hard_logout_after_being_soft_logged_out(self) -> None:
429
+ self.register_user("kermit", "monkey")
430
+
431
+ # log in as normal
432
+ access_token = self.login("kermit", "monkey")
433
+
434
+ # we should now be able to make requests with the access token
435
+ channel = self.make_request(b"GET", TEST_URL, access_token=access_token)
436
+ self.assertEqual(channel.code, 200, channel.result)
437
+
438
+ # time passes
439
+ self.reactor.advance(24 * 3600)
440
+
441
+ # ... and we should be soft-logouted
442
+ channel = self.make_request(b"GET", TEST_URL, access_token=access_token)
443
+ self.assertEqual(channel.code, 401, channel.result)
444
+ self.assertEqual(channel.json_body["errcode"], "M_UNKNOWN_TOKEN")
445
+ self.assertEqual(channel.json_body["soft_logout"], True)
446
+
447
+ # Now try to hard logout this session
448
+ channel = self.make_request(b"POST", "/logout", access_token=access_token)
449
+ self.assertEqual(channel.code, 200, msg=channel.result)
450
+
451
+ @override_config({"session_lifetime": "24h"})
452
+ def test_session_can_hard_logout_all_sessions_after_being_soft_logged_out(
453
+ self,
454
+ ) -> None:
455
+ self.register_user("kermit", "monkey")
456
+
457
+ # log in as normal
458
+ access_token = self.login("kermit", "monkey")
459
+
460
+ # we should now be able to make requests with the access token
461
+ channel = self.make_request(b"GET", TEST_URL, access_token=access_token)
462
+ self.assertEqual(channel.code, 200, channel.result)
463
+
464
+ # time passes
465
+ self.reactor.advance(24 * 3600)
466
+
467
+ # ... and we should be soft-logouted
468
+ channel = self.make_request(b"GET", TEST_URL, access_token=access_token)
469
+ self.assertEqual(channel.code, 401, channel.result)
470
+ self.assertEqual(channel.json_body["errcode"], "M_UNKNOWN_TOKEN")
471
+ self.assertEqual(channel.json_body["soft_logout"], True)
472
+
473
+ # Now try to hard log out all of the user's sessions
474
+ channel = self.make_request(b"POST", "/logout/all", access_token=access_token)
475
+ self.assertEqual(channel.code, 200, msg=channel.result)
476
+
477
+ def test_login_with_overly_long_device_id_fails(self) -> None:
478
+ self.register_user("mickey", "cheese")
479
+
480
+ # create a device_id longer than 512 characters
481
+ device_id = "yolo" * 512
482
+
483
+ body = {
484
+ "type": "m.login.password",
485
+ "user": "mickey",
486
+ "password": "cheese",
487
+ "device_id": device_id,
488
+ }
489
+
490
+ # make a login request with the bad device_id
491
+ channel = self.make_request(
492
+ "POST",
493
+ "/_matrix/client/v3/login",
494
+ body,
495
+ custom_headers=None,
496
+ )
497
+
498
+ # test that the login fails with the correct error code
499
+ self.assertEqual(channel.code, 400)
500
+ self.assertEqual(channel.json_body["errcode"], "M_INVALID_PARAM")
501
+
502
+ @override_config(
503
+ {
504
+ "experimental_features": {
505
+ "msc3866": {
506
+ "enabled": True,
507
+ "require_approval_for_new_accounts": True,
508
+ }
509
+ }
510
+ }
511
+ )
512
+ def test_require_approval(self) -> None:
513
+ channel = self.make_request(
514
+ "POST",
515
+ "register",
516
+ {
517
+ "username": "kermit",
518
+ "password": "monkey",
519
+ "auth": {"type": LoginType.DUMMY},
520
+ },
521
+ )
522
+ self.assertEqual(403, channel.code, channel.result)
523
+ self.assertEqual(Codes.USER_AWAITING_APPROVAL, channel.json_body["errcode"])
524
+ self.assertEqual(
525
+ ApprovalNoticeMedium.NONE, channel.json_body["approval_notice_medium"]
526
+ )
527
+
528
+ params = {
529
+ "type": LoginType.PASSWORD,
530
+ "identifier": {"type": "m.id.user", "user": "kermit"},
531
+ "password": "monkey",
532
+ }
533
+ channel = self.make_request("POST", LOGIN_URL, params)
534
+ self.assertEqual(403, channel.code, channel.result)
535
+ self.assertEqual(Codes.USER_AWAITING_APPROVAL, channel.json_body["errcode"])
536
+ self.assertEqual(
537
+ ApprovalNoticeMedium.NONE, channel.json_body["approval_notice_medium"]
538
+ )
539
+
540
+ def test_get_login_flows_with_login_via_existing_disabled(self) -> None:
541
+ """GET /login should return m.login.token without get_login_token"""
542
+ channel = self.make_request("GET", "/_matrix/client/r0/login")
543
+ self.assertEqual(channel.code, 200, channel.result)
544
+
545
+ flows = {flow["type"]: flow for flow in channel.json_body["flows"]}
546
+ self.assertNotIn("m.login.token", flows)
547
+
548
+ @override_config({"login_via_existing_session": {"enabled": True}})
549
+ def test_get_login_flows_with_login_via_existing_enabled(self) -> None:
550
+ """GET /login should return m.login.token with get_login_token true"""
551
+ channel = self.make_request("GET", "/_matrix/client/r0/login")
552
+ self.assertEqual(channel.code, 200, channel.result)
553
+
554
+ self.assertCountEqual(
555
+ channel.json_body["flows"],
556
+ [
557
+ {"type": "m.login.token", "get_login_token": True},
558
+ {"type": "m.login.password"},
559
+ {"type": "m.login.application_service"},
560
+ ],
561
+ )
562
+
563
+ @override_config(
564
+ {
565
+ "modules": [
566
+ {
567
+ "module": TestSpamChecker.__module__
568
+ + "."
569
+ + TestSpamChecker.__qualname__
570
+ }
571
+ ]
572
+ }
573
+ )
574
+ def test_spam_checker_allow(self) -> None:
575
+ """Check that that adding a spam checker doesn't break login."""
576
+ self.register_user("kermit", "monkey")
577
+
578
+ body = {"type": "m.login.password", "user": "kermit", "password": "monkey"}
579
+
580
+ channel = self.make_request(
581
+ "POST",
582
+ "/_matrix/client/r0/login",
583
+ body,
584
+ )
585
+ self.assertEqual(channel.code, 200, channel.result)
586
+
587
+ @override_config(
588
+ {
589
+ "modules": [
590
+ {
591
+ "module": DenyAllSpamChecker.__module__
592
+ + "."
593
+ + DenyAllSpamChecker.__qualname__
594
+ }
595
+ ]
596
+ }
597
+ )
598
+ def test_spam_checker_deny(self) -> None:
599
+ """Check that login"""
600
+
601
+ self.register_user("kermit", "monkey")
602
+
603
+ body = {"type": "m.login.password", "user": "kermit", "password": "monkey"}
604
+
605
+ channel = self.make_request(
606
+ "POST",
607
+ "/_matrix/client/r0/login",
608
+ body,
609
+ )
610
+ self.assertEqual(channel.code, 403, channel.result)
611
+ self.assertLessEqual(
612
+ {"errcode": Codes.LIMIT_EXCEEDED, "extra": "value"}.items(),
613
+ channel.json_body.items(),
614
+ )
615
+
616
+
617
+ @skip_unless(has_saml2 and HAS_OIDC, "Requires SAML2 and OIDC")
618
+ class MultiSSOTestCase(unittest.HomeserverTestCase):
619
+ """Tests for homeservers with multiple SSO providers enabled"""
620
+
621
+ servlets = [
622
+ login.register_servlets,
623
+ ]
624
+
625
+ def default_config(self) -> dict[str, Any]:
626
+ config = super().default_config()
627
+
628
+ config["public_baseurl"] = PUBLIC_BASEURL
629
+
630
+ config["cas_config"] = {
631
+ "enabled": True,
632
+ "server_url": CAS_SERVER,
633
+ "service_url": "https://matrix.goodserver.com:8448",
634
+ }
635
+
636
+ config["saml2_config"] = {
637
+ "sp_config": {
638
+ "metadata": {"inline": [TEST_SAML_METADATA]},
639
+ # use the XMLSecurity backend to avoid relying on xmlsec1
640
+ "crypto_backend": "XMLSecurity",
641
+ },
642
+ }
643
+
644
+ # default OIDC provider
645
+ config["oidc_config"] = TEST_OIDC_CONFIG
646
+
647
+ # additional OIDC providers
648
+ config["oidc_providers"] = [
649
+ {
650
+ "idp_id": "idp1",
651
+ "idp_name": "IDP1",
652
+ "discover": False,
653
+ "issuer": "https://issuer1",
654
+ "client_id": "test-client-id",
655
+ "client_secret": "test-client-secret",
656
+ "scopes": ["profile"],
657
+ "authorization_endpoint": "https://issuer1/auth",
658
+ "token_endpoint": "https://issuer1/token",
659
+ "userinfo_endpoint": "https://issuer1/userinfo",
660
+ "user_mapping_provider": {
661
+ "config": {"localpart_template": "{{ user.sub }}"}
662
+ },
663
+ }
664
+ ]
665
+ return config
666
+
667
+ def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
668
+ self.login_sso_redirect_url_builder = LoginSSORedirectURIBuilder(hs.config)
669
+
670
+ def create_resource_dict(self) -> dict[str, Resource]:
671
+ d = super().create_resource_dict()
672
+ d.update(build_synapse_client_resource_tree(self.hs))
673
+ return d
674
+
675
+ def test_get_login_flows(self) -> None:
676
+ """GET /login should return password and SSO flows"""
677
+ channel = self.make_request("GET", "/_matrix/client/r0/login")
678
+ self.assertEqual(channel.code, 200, channel.result)
679
+
680
+ expected_flow_types = [
681
+ "m.login.cas",
682
+ "m.login.sso",
683
+ "m.login.token",
684
+ "m.login.password",
685
+ ] + [f["type"] for f in ADDITIONAL_LOGIN_FLOWS]
686
+
687
+ self.assertCountEqual(
688
+ [f["type"] for f in channel.json_body["flows"]], expected_flow_types
689
+ )
690
+
691
+ flows = {flow["type"]: flow for flow in channel.json_body["flows"]}
692
+ self.assertCountEqual(
693
+ flows["m.login.sso"]["identity_providers"],
694
+ [
695
+ {"id": "cas", "name": "CAS"},
696
+ {"id": "saml", "name": "SAML"},
697
+ {"id": "oidc-idp1", "name": "IDP1"},
698
+ {"id": "oidc", "name": "OIDC"},
699
+ ],
700
+ )
701
+
702
+ def test_multi_sso_redirect(self) -> None:
703
+ """/login/sso/redirect should redirect to an identity picker"""
704
+ # first hit the redirect url, which should redirect to our idp picker
705
+ channel = self._make_sso_redirect_request(None)
706
+ self.assertEqual(channel.code, 302, channel.result)
707
+ location_headers = channel.headers.getRawHeaders("Location")
708
+ assert location_headers
709
+ uri = location_headers[0]
710
+
711
+ # hitting that picker should give us some HTML
712
+ channel = self.make_request("GET", uri)
713
+ self.assertEqual(channel.code, 200, channel.result)
714
+
715
+ # parse the form to check it has fields assumed elsewhere in this class
716
+ html = channel.result["body"].decode("utf-8")
717
+ p = TestHtmlParser()
718
+ p.feed(html)
719
+ p.close()
720
+
721
+ # there should be a link for each href
722
+ returned_idps: list[str] = []
723
+ for link in p.links:
724
+ path, query = link.split("?", 1)
725
+ self.assertEqual(path, "pick_idp")
726
+ params = urllib.parse.parse_qs(query)
727
+ self.assertEqual(params["redirectUrl"], [TEST_CLIENT_REDIRECT_URL])
728
+ returned_idps.append(params["idp"][0])
729
+
730
+ self.assertCountEqual(returned_idps, ["cas", "oidc", "oidc-idp1", "saml"])
731
+
732
+ def test_multi_sso_redirect_to_cas(self) -> None:
733
+ """If CAS is chosen, should redirect to the CAS server"""
734
+
735
+ channel = self.make_request(
736
+ "GET",
737
+ "/_synapse/client/pick_idp?redirectUrl="
738
+ + urllib.parse.quote_plus(TEST_CLIENT_REDIRECT_URL)
739
+ + "&idp=cas",
740
+ shorthand=False,
741
+ )
742
+ self.assertEqual(channel.code, 302, channel.result)
743
+ location_headers = channel.headers.getRawHeaders("Location")
744
+ assert location_headers
745
+ sso_login_redirect_uri = location_headers[0]
746
+
747
+ # it should redirect us to the standard login SSO redirect flow
748
+ self.assertEqual(
749
+ sso_login_redirect_uri,
750
+ self.login_sso_redirect_url_builder.build_login_sso_redirect_uri(
751
+ idp_id="cas", client_redirect_url=TEST_CLIENT_REDIRECT_URL
752
+ ),
753
+ )
754
+
755
+ # follow the redirect
756
+ channel = self.make_request(
757
+ "GET",
758
+ # We have to make this relative to be compatible with `make_request(...)`
759
+ get_relative_uri_from_absolute_uri(sso_login_redirect_uri),
760
+ # We have to set the Host header to match the `public_baseurl` to avoid
761
+ # the extra redirect in the `SsoRedirectServlet` in order for the
762
+ # cookies to be visible.
763
+ custom_headers=[
764
+ ("Host", SYNAPSE_SERVER_PUBLIC_HOSTNAME),
765
+ ],
766
+ )
767
+
768
+ self.assertEqual(channel.code, 302, channel.result)
769
+ location_headers = channel.headers.getRawHeaders("Location")
770
+ assert location_headers
771
+ cas_uri = location_headers[0]
772
+ cas_uri_path, cas_uri_query = cas_uri.split("?", 1)
773
+
774
+ # it should redirect us to the login page of the cas server
775
+ self.assertEqual(cas_uri_path, CAS_SERVER + "/login")
776
+
777
+ # check that the redirectUrl is correctly encoded in the service param - ie, the
778
+ # place that CAS will redirect to
779
+ cas_uri_params = urllib.parse.parse_qs(cas_uri_query)
780
+ service_uri = cas_uri_params["service"][0]
781
+ _, service_uri_query = service_uri.split("?", 1)
782
+ service_uri_params = urllib.parse.parse_qs(service_uri_query)
783
+ self.assertEqual(service_uri_params["redirectUrl"][0], TEST_CLIENT_REDIRECT_URL)
784
+
785
+ def test_multi_sso_redirect_to_saml(self) -> None:
786
+ """If SAML is chosen, should redirect to the SAML server"""
787
+ channel = self.make_request(
788
+ "GET",
789
+ "/_synapse/client/pick_idp?redirectUrl="
790
+ + urllib.parse.quote_plus(TEST_CLIENT_REDIRECT_URL)
791
+ + "&idp=saml",
792
+ )
793
+ self.assertEqual(channel.code, 302, channel.result)
794
+ location_headers = channel.headers.getRawHeaders("Location")
795
+ assert location_headers
796
+ sso_login_redirect_uri = location_headers[0]
797
+
798
+ # it should redirect us to the standard login SSO redirect flow
799
+ self.assertEqual(
800
+ sso_login_redirect_uri,
801
+ self.login_sso_redirect_url_builder.build_login_sso_redirect_uri(
802
+ idp_id="saml", client_redirect_url=TEST_CLIENT_REDIRECT_URL
803
+ ),
804
+ )
805
+
806
+ # follow the redirect
807
+ channel = self.make_request(
808
+ "GET",
809
+ # We have to make this relative to be compatible with `make_request(...)`
810
+ get_relative_uri_from_absolute_uri(sso_login_redirect_uri),
811
+ # We have to set the Host header to match the `public_baseurl` to avoid
812
+ # the extra redirect in the `SsoRedirectServlet` in order for the
813
+ # cookies to be visible.
814
+ custom_headers=[
815
+ ("Host", SYNAPSE_SERVER_PUBLIC_HOSTNAME),
816
+ ],
817
+ )
818
+
819
+ self.assertEqual(channel.code, 302, channel.result)
820
+ location_headers = channel.headers.getRawHeaders("Location")
821
+ assert location_headers
822
+ saml_uri = location_headers[0]
823
+ saml_uri_path, saml_uri_query = saml_uri.split("?", 1)
824
+
825
+ # it should redirect us to the login page of the SAML server
826
+ self.assertEqual(saml_uri_path, SAML_SERVER)
827
+
828
+ # the RelayState is used to carry the client redirect url
829
+ saml_uri_params = urllib.parse.parse_qs(saml_uri_query)
830
+ relay_state_param = saml_uri_params["RelayState"][0]
831
+ self.assertEqual(relay_state_param, TEST_CLIENT_REDIRECT_URL)
832
+
833
+ def test_login_via_oidc(self) -> None:
834
+ """If OIDC is chosen, should redirect to the OIDC auth endpoint"""
835
+
836
+ fake_oidc_server = self.helper.fake_oidc_server()
837
+
838
+ with fake_oidc_server.patch_homeserver(hs=self.hs):
839
+ # pick the default OIDC provider
840
+ channel = self.make_request(
841
+ "GET",
842
+ f"/_synapse/client/pick_idp?redirectUrl={urllib.parse.quote_plus(TEST_CLIENT_REDIRECT_URL)}&idp=oidc",
843
+ )
844
+ self.assertEqual(channel.code, 302, channel.result)
845
+ location_headers = channel.headers.getRawHeaders("Location")
846
+ assert location_headers
847
+ sso_login_redirect_uri = location_headers[0]
848
+
849
+ # it should redirect us to the standard login SSO redirect flow
850
+ self.assertEqual(
851
+ sso_login_redirect_uri,
852
+ self.login_sso_redirect_url_builder.build_login_sso_redirect_uri(
853
+ idp_id="oidc", client_redirect_url=TEST_CLIENT_REDIRECT_URL
854
+ ),
855
+ )
856
+
857
+ with fake_oidc_server.patch_homeserver(hs=self.hs):
858
+ # follow the redirect
859
+ channel = self.make_request(
860
+ "GET",
861
+ # We have to make this relative to be compatible with `make_request(...)`
862
+ get_relative_uri_from_absolute_uri(sso_login_redirect_uri),
863
+ # We have to set the Host header to match the `public_baseurl` to avoid
864
+ # the extra redirect in the `SsoRedirectServlet` in order for the
865
+ # cookies to be visible.
866
+ custom_headers=[
867
+ ("Host", SYNAPSE_SERVER_PUBLIC_HOSTNAME),
868
+ ],
869
+ )
870
+
871
+ self.assertEqual(channel.code, 302, channel.result)
872
+ location_headers = channel.headers.getRawHeaders("Location")
873
+ assert location_headers
874
+ oidc_uri = location_headers[0]
875
+ oidc_uri_path, oidc_uri_query = oidc_uri.split("?", 1)
876
+
877
+ # it should redirect us to the auth page of the OIDC server
878
+ self.assertEqual(oidc_uri_path, fake_oidc_server.authorization_endpoint)
879
+
880
+ # ... and should have set a cookie including the redirect url
881
+ cookie_headers = channel.headers.getRawHeaders("Set-Cookie")
882
+ assert cookie_headers
883
+ cookies: dict[str, str] = {}
884
+ for h in cookie_headers:
885
+ key, value = h.split(";")[0].split("=", maxsplit=1)
886
+ cookies[key] = value
887
+
888
+ oidc_session_cookie = cookies["oidc_session"]
889
+ macaroon = pymacaroons.Macaroon.deserialize(oidc_session_cookie)
890
+ self.assertEqual(
891
+ self._get_value_from_macaroon(macaroon, "client_redirect_url"),
892
+ TEST_CLIENT_REDIRECT_URL,
893
+ )
894
+
895
+ channel, _ = self.helper.complete_oidc_auth(
896
+ fake_oidc_server, oidc_uri, cookies, {"sub": "user1"}
897
+ )
898
+
899
+ # that should serve a confirmation page
900
+ self.assertEqual(channel.code, 200, channel.result)
901
+ content_type_headers = channel.headers.getRawHeaders("Content-Type")
902
+ assert content_type_headers
903
+ self.assertTrue(content_type_headers[-1].startswith("text/html"))
904
+ p = TestHtmlParser()
905
+ p.feed(channel.text_body)
906
+ p.close()
907
+
908
+ # ... which should contain our redirect link
909
+ self.assertEqual(len(p.links), 1)
910
+ path, query = p.links[0].split("?", 1)
911
+ self.assertEqual(path, "https://x")
912
+
913
+ # it will have url-encoded the params properly, so we'll have to parse them
914
+ params = urllib.parse.parse_qsl(
915
+ query, keep_blank_values=True, strict_parsing=True, errors="strict"
916
+ )
917
+ self.assertEqual(params[0:2], EXPECTED_CLIENT_REDIRECT_URL_PARAMS)
918
+ self.assertEqual(params[2][0], "loginToken")
919
+
920
+ # finally, submit the matrix login token to the login API, which gives us our
921
+ # matrix access token, mxid, and device id.
922
+ login_token = params[2][1]
923
+ chan = self.make_request(
924
+ "POST",
925
+ "/login",
926
+ content={"type": "m.login.token", "token": login_token},
927
+ )
928
+ self.assertEqual(chan.code, 200, chan.result)
929
+ self.assertEqual(chan.json_body["user_id"], "@user1:test")
930
+
931
+ def test_multi_sso_redirect_unknown_idp(self) -> None:
932
+ """An unknown IdP should cause a 400 bad request error"""
933
+ channel = self.make_request(
934
+ "GET",
935
+ "/_synapse/client/pick_idp?redirectUrl=http://x&idp=xyz",
936
+ )
937
+ self.assertEqual(channel.code, 400, channel.result)
938
+
939
+ def test_multi_sso_redirect_unknown_idp_as_url(self) -> None:
940
+ """
941
+ An unknown IdP that looks like a URL should cause a 400 bad request error (to
942
+ avoid open redirects).
943
+
944
+ Ideally, we'd have another test for a known IdP with a URL as the `idp_id`, but
945
+ we can't configure that in our tests because the config validation on
946
+ `oidc_providers` only allows a subset of characters. If we could configure
947
+ `oidc_providers` with a URL as the `idp_id`, it should still be URL-encoded
948
+ properly to avoid open redirections. We do have `test_url_as_idp_id_is_escaped`
949
+ in the URL building tests to cover this case but is only a unit test vs
950
+ something at the REST layer here that covers things end-to-end.
951
+ """
952
+ channel = self.make_request(
953
+ "GET",
954
+ "/_synapse/client/pick_idp?redirectUrl=something&idp=https://element.io/",
955
+ )
956
+ self.assertEqual(channel.code, 400, channel.result)
957
+
958
+ def test_client_idp_redirect_to_unknown(self) -> None:
959
+ """If the client tries to pick an unknown IdP, return a 404"""
960
+ channel = self._make_sso_redirect_request("xxx")
961
+ self.assertEqual(channel.code, 404, channel.result)
962
+ self.assertEqual(channel.json_body["errcode"], "M_NOT_FOUND")
963
+
964
+ def test_client_idp_redirect_to_oidc(self) -> None:
965
+ """If the client pick a known IdP, redirect to it"""
966
+ fake_oidc_server = self.helper.fake_oidc_server()
967
+
968
+ with fake_oidc_server.patch_homeserver(hs=self.hs):
969
+ channel = self._make_sso_redirect_request("oidc")
970
+ self.assertEqual(channel.code, 302, channel.result)
971
+ location_headers = channel.headers.getRawHeaders("Location")
972
+ assert location_headers
973
+ oidc_uri = location_headers[0]
974
+ oidc_uri_path, oidc_uri_query = oidc_uri.split("?", 1)
975
+
976
+ # it should redirect us to the auth page of the OIDC server
977
+ self.assertEqual(oidc_uri_path, fake_oidc_server.authorization_endpoint)
978
+
979
+ def _make_sso_redirect_request(self, idp_prov: str | None = None) -> FakeChannel:
980
+ """Send a request to /_matrix/client/r0/login/sso/redirect
981
+
982
+ ... possibly specifying an IDP provider
983
+ """
984
+ endpoint = "/_matrix/client/r0/login/sso/redirect"
985
+ if idp_prov is not None:
986
+ endpoint += "/" + idp_prov
987
+ endpoint += "?redirectUrl=" + urllib.parse.quote_plus(TEST_CLIENT_REDIRECT_URL)
988
+
989
+ return self.make_request(
990
+ "GET",
991
+ endpoint,
992
+ custom_headers=[("Host", SYNAPSE_SERVER_PUBLIC_HOSTNAME)],
993
+ )
994
+
995
+ @staticmethod
996
+ def _get_value_from_macaroon(macaroon: pymacaroons.Macaroon, key: str) -> str:
997
+ prefix = key + " = "
998
+ for caveat in macaroon.caveats:
999
+ if caveat.caveat_id.startswith(prefix):
1000
+ return caveat.caveat_id[len(prefix) :]
1001
+ raise ValueError("No %s caveat in macaroon" % (key,))
1002
+
1003
+
1004
+ class CASTestCase(unittest.HomeserverTestCase):
1005
+ servlets = [
1006
+ login.register_servlets,
1007
+ ]
1008
+
1009
+ def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer:
1010
+ self.base_url = "https://matrix.goodserver.com/"
1011
+ self.redirect_path = "_synapse/client/login/sso/redirect/confirm"
1012
+
1013
+ config = self.default_config()
1014
+ config["public_baseurl"] = (
1015
+ config.get("public_baseurl") or "https://matrix.goodserver.com:8448"
1016
+ )
1017
+ config["cas_config"] = {
1018
+ "enabled": True,
1019
+ "server_url": CAS_SERVER,
1020
+ }
1021
+
1022
+ cas_user_id = "username"
1023
+ self.user_id = "@%s:test" % cas_user_id
1024
+
1025
+ async def get_raw(uri: str, args: Any) -> bytes:
1026
+ """Return an example response payload from a call to the `/proxyValidate`
1027
+ endpoint of a CAS server, copied from
1028
+ https://apereo.github.io/cas/5.0.x/protocol/CAS-Protocol-V2-Specification.html#26-proxyvalidate-cas-20
1029
+
1030
+ This needs to be returned by an async function (as opposed to set as the
1031
+ mock's return value) because the corresponding Synapse code awaits on it.
1032
+ """
1033
+ return (
1034
+ """
1035
+ <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
1036
+ <cas:authenticationSuccess>
1037
+ <cas:user>%s</cas:user>
1038
+ <cas:proxyGrantingTicket>PGTIOU-84678-8a9d...</cas:proxyGrantingTicket>
1039
+ <cas:proxies>
1040
+ <cas:proxy>https://proxy2/pgtUrl</cas:proxy>
1041
+ <cas:proxy>https://proxy1/pgtUrl</cas:proxy>
1042
+ </cas:proxies>
1043
+ </cas:authenticationSuccess>
1044
+ </cas:serviceResponse>
1045
+ """
1046
+ % cas_user_id
1047
+ ).encode("utf-8")
1048
+
1049
+ mocked_http_client = Mock(spec=["get_raw"])
1050
+ mocked_http_client.get_raw.side_effect = get_raw
1051
+
1052
+ self.hs = self.setup_test_homeserver(
1053
+ config=config,
1054
+ proxied_http_client=mocked_http_client,
1055
+ )
1056
+
1057
+ return self.hs
1058
+
1059
+ def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
1060
+ self.deactivate_account_handler = hs.get_deactivate_account_handler()
1061
+
1062
+ def test_cas_redirect_confirm(self) -> None:
1063
+ """Tests that the SSO login flow serves a confirmation page before redirecting a
1064
+ user to the redirect URL.
1065
+ """
1066
+ base_url = "/_matrix/client/r0/login/cas/ticket?redirectUrl"
1067
+ redirect_url = "https://dodgy-site.com/"
1068
+
1069
+ url_parts = list(urllib.parse.urlparse(base_url))
1070
+ query = dict(urllib.parse.parse_qsl(url_parts[4]))
1071
+ query.update({"redirectUrl": redirect_url})
1072
+ query.update({"ticket": "ticket"})
1073
+ url_parts[4] = urllib.parse.urlencode(query)
1074
+ cas_ticket_url = urllib.parse.urlunparse(url_parts)
1075
+
1076
+ # Get Synapse to call the fake CAS and serve the template.
1077
+ channel = self.make_request("GET", cas_ticket_url)
1078
+
1079
+ # Test that the response is HTML.
1080
+ self.assertEqual(channel.code, 200, channel.result)
1081
+ content_type_header_value = ""
1082
+ for header in channel.headers.getRawHeaders("Content-Type", []):
1083
+ content_type_header_value = header
1084
+
1085
+ self.assertTrue(content_type_header_value.startswith("text/html"))
1086
+
1087
+ # Test that the body isn't empty.
1088
+ self.assertTrue(len(channel.result["body"]) > 0)
1089
+
1090
+ # And that it contains our redirect link
1091
+ self.assertIn(redirect_url, channel.result["body"].decode("UTF-8"))
1092
+
1093
+ @override_config(
1094
+ {
1095
+ "sso": {
1096
+ "client_whitelist": [
1097
+ "https://legit-site.com/",
1098
+ "https://other-site.com/",
1099
+ ]
1100
+ }
1101
+ }
1102
+ )
1103
+ def test_cas_redirect_whitelisted(self) -> None:
1104
+ """Tests that the SSO login flow serves a redirect to a whitelisted url"""
1105
+ self._test_redirect("https://legit-site.com/")
1106
+
1107
+ @override_config({"public_baseurl": "https://example.com"})
1108
+ def test_cas_redirect_login_fallback(self) -> None:
1109
+ self._test_redirect("https://example.com/_matrix/static/client/login")
1110
+
1111
+ def _test_redirect(self, redirect_url: str) -> None:
1112
+ """Tests that the SSO login flow serves a redirect for the given redirect URL."""
1113
+ cas_ticket_url = (
1114
+ "/_matrix/client/r0/login/cas/ticket?redirectUrl=%s&ticket=ticket"
1115
+ % (urllib.parse.quote(redirect_url))
1116
+ )
1117
+
1118
+ # Get Synapse to call the fake CAS and serve the template.
1119
+ channel = self.make_request("GET", cas_ticket_url)
1120
+
1121
+ self.assertEqual(channel.code, 302)
1122
+ location_headers = channel.headers.getRawHeaders("Location")
1123
+ assert location_headers
1124
+ self.assertEqual(location_headers[0][: len(redirect_url)], redirect_url)
1125
+
1126
+ @override_config({"sso": {"client_whitelist": ["https://legit-site.com/"]}})
1127
+ def test_deactivated_user(self) -> None:
1128
+ """Logging in as a deactivated account should error."""
1129
+ redirect_url = "https://legit-site.com/"
1130
+
1131
+ # First login (to create the user).
1132
+ self._test_redirect(redirect_url)
1133
+
1134
+ # Deactivate the account.
1135
+ self.get_success(
1136
+ self.deactivate_account_handler.deactivate_account(
1137
+ self.user_id, False, create_requester(self.user_id)
1138
+ )
1139
+ )
1140
+
1141
+ # Request the CAS ticket.
1142
+ cas_ticket_url = (
1143
+ "/_matrix/client/r0/login/cas/ticket?redirectUrl=%s&ticket=ticket"
1144
+ % (urllib.parse.quote(redirect_url))
1145
+ )
1146
+
1147
+ # Get Synapse to call the fake CAS and serve the template.
1148
+ channel = self.make_request("GET", cas_ticket_url)
1149
+
1150
+ # Because the user is deactivated they are served an error template.
1151
+ self.assertEqual(channel.code, 403)
1152
+ self.assertIn(b"SSO account deactivated", channel.result["body"])
1153
+
1154
+
1155
+ @skip_unless(HAS_JWT, "requires authlib")
1156
+ class JWTTestCase(unittest.HomeserverTestCase):
1157
+ servlets = [
1158
+ synapse.rest.admin.register_servlets_for_client_rest_resource,
1159
+ login.register_servlets,
1160
+ profile.register_servlets,
1161
+ ]
1162
+
1163
+ jwt_secret = "secret"
1164
+ jwt_algorithm = "HS256"
1165
+ base_config = {
1166
+ "enabled": True,
1167
+ "secret": jwt_secret,
1168
+ "algorithm": jwt_algorithm,
1169
+ }
1170
+
1171
+ def default_config(self) -> dict[str, Any]:
1172
+ config = super().default_config()
1173
+
1174
+ # If jwt_config has been defined (eg via @override_config), don't replace it.
1175
+ if config.get("jwt_config") is None:
1176
+ config["jwt_config"] = self.base_config
1177
+
1178
+ return config
1179
+
1180
+ def jwt_encode(self, payload: dict[str, Any], secret: str = jwt_secret) -> str:
1181
+ header = {"alg": self.jwt_algorithm}
1182
+ result: bytes = jwt.encode(header, payload, secret)
1183
+ return result.decode("ascii")
1184
+
1185
+ def jwt_login(self, *args: Any) -> FakeChannel:
1186
+ params = {"type": "org.matrix.login.jwt", "token": self.jwt_encode(*args)}
1187
+ channel = self.make_request(b"POST", LOGIN_URL, params)
1188
+ return channel
1189
+
1190
+ def test_login_jwt_valid_registered(self) -> None:
1191
+ self.register_user("kermit", "monkey")
1192
+ channel = self.jwt_login({"sub": "kermit"})
1193
+ self.assertEqual(channel.code, 200, msg=channel.result)
1194
+ self.assertEqual(channel.json_body["user_id"], "@kermit:test")
1195
+
1196
+ def test_login_jwt_valid_unregistered(self) -> None:
1197
+ channel = self.jwt_login({"sub": "frog"})
1198
+ self.assertEqual(channel.code, 200, msg=channel.result)
1199
+ self.assertEqual(channel.json_body["user_id"], "@frog:test")
1200
+
1201
+ def test_login_jwt_invalid_signature(self) -> None:
1202
+ channel = self.jwt_login({"sub": "frog"}, "notsecret")
1203
+ self.assertEqual(channel.code, 403, msg=channel.result)
1204
+ self.assertEqual(channel.json_body["errcode"], "M_FORBIDDEN")
1205
+ self.assertEqual(
1206
+ channel.json_body["error"],
1207
+ "JWT validation failed: Signature verification failed",
1208
+ )
1209
+
1210
+ def test_login_jwt_expired(self) -> None:
1211
+ channel = self.jwt_login({"sub": "frog", "exp": 864000})
1212
+ self.assertEqual(channel.code, 403, msg=channel.result)
1213
+ self.assertEqual(channel.json_body["errcode"], "M_FORBIDDEN")
1214
+ self.assertEqual(
1215
+ channel.json_body["error"],
1216
+ "JWT validation failed: expired_token: The token is expired",
1217
+ )
1218
+
1219
+ def test_login_jwt_not_before(self) -> None:
1220
+ now = int(time.time())
1221
+ channel = self.jwt_login({"sub": "frog", "nbf": now + 3600})
1222
+ self.assertEqual(channel.code, 403, msg=channel.result)
1223
+ self.assertEqual(channel.json_body["errcode"], "M_FORBIDDEN")
1224
+ self.assertEqual(
1225
+ channel.json_body["error"],
1226
+ "JWT validation failed: invalid_token: The token is not valid yet",
1227
+ )
1228
+
1229
+ def test_login_no_sub(self) -> None:
1230
+ channel = self.jwt_login({"username": "root"})
1231
+ self.assertEqual(channel.code, 403, msg=channel.result)
1232
+ self.assertEqual(channel.json_body["errcode"], "M_FORBIDDEN")
1233
+ self.assertEqual(channel.json_body["error"], "Invalid JWT")
1234
+
1235
+ @override_config({"jwt_config": {**base_config, "issuer": "test-issuer"}})
1236
+ def test_login_iss(self) -> None:
1237
+ """Test validating the issuer claim."""
1238
+ # A valid issuer.
1239
+ channel = self.jwt_login({"sub": "kermit", "iss": "test-issuer"})
1240
+ self.assertEqual(channel.code, 200, msg=channel.result)
1241
+ self.assertEqual(channel.json_body["user_id"], "@kermit:test")
1242
+
1243
+ # An invalid issuer.
1244
+ channel = self.jwt_login({"sub": "kermit", "iss": "invalid"})
1245
+ self.assertEqual(channel.code, 403, msg=channel.result)
1246
+ self.assertEqual(channel.json_body["errcode"], "M_FORBIDDEN")
1247
+ self.assertRegex(
1248
+ channel.json_body["error"],
1249
+ r"^JWT validation failed: invalid_claim: Invalid claim [\"']iss[\"']$",
1250
+ )
1251
+
1252
+ # Not providing an issuer.
1253
+ channel = self.jwt_login({"sub": "kermit"})
1254
+ self.assertEqual(channel.code, 403, msg=channel.result)
1255
+ self.assertEqual(channel.json_body["errcode"], "M_FORBIDDEN")
1256
+ self.assertRegex(
1257
+ channel.json_body["error"],
1258
+ r"^JWT validation failed: missing_claim: Missing [\"']iss[\"'] claim$",
1259
+ )
1260
+
1261
+ def test_login_iss_no_config(self) -> None:
1262
+ """Test providing an issuer claim without requiring it in the configuration."""
1263
+ channel = self.jwt_login({"sub": "kermit", "iss": "invalid"})
1264
+ self.assertEqual(channel.code, 200, msg=channel.result)
1265
+ self.assertEqual(channel.json_body["user_id"], "@kermit:test")
1266
+
1267
+ @override_config({"jwt_config": {**base_config, "audiences": ["test-audience"]}})
1268
+ def test_login_aud(self) -> None:
1269
+ """Test validating the audience claim."""
1270
+ # A valid audience.
1271
+ channel = self.jwt_login({"sub": "kermit", "aud": "test-audience"})
1272
+ self.assertEqual(channel.code, 200, msg=channel.result)
1273
+ self.assertEqual(channel.json_body["user_id"], "@kermit:test")
1274
+
1275
+ # An invalid audience.
1276
+ channel = self.jwt_login({"sub": "kermit", "aud": "invalid"})
1277
+ self.assertEqual(channel.code, 403, msg=channel.result)
1278
+ self.assertEqual(channel.json_body["errcode"], "M_FORBIDDEN")
1279
+ self.assertRegex(
1280
+ channel.json_body["error"],
1281
+ r"^JWT validation failed: invalid_claim: Invalid claim [\"']aud[\"']$",
1282
+ )
1283
+
1284
+ # Not providing an audience.
1285
+ channel = self.jwt_login({"sub": "kermit"})
1286
+ self.assertEqual(channel.code, 403, msg=channel.result)
1287
+ self.assertEqual(channel.json_body["errcode"], "M_FORBIDDEN")
1288
+ self.assertRegex(
1289
+ channel.json_body["error"],
1290
+ r"^JWT validation failed: missing_claim: Missing [\"']aud[\"'] claim$",
1291
+ )
1292
+
1293
+ def test_login_aud_no_config(self) -> None:
1294
+ """Test providing an audience without requiring it in the configuration."""
1295
+ channel = self.jwt_login({"sub": "kermit", "aud": "invalid"})
1296
+ self.assertEqual(channel.code, 403, msg=channel.result)
1297
+ self.assertEqual(channel.json_body["errcode"], "M_FORBIDDEN")
1298
+ self.assertRegex(
1299
+ channel.json_body["error"],
1300
+ r"^JWT validation failed: invalid_claim: Invalid claim [\"']aud[\"']$",
1301
+ )
1302
+
1303
+ def test_login_default_sub(self) -> None:
1304
+ """Test reading user ID from the default subject claim."""
1305
+ channel = self.jwt_login({"sub": "kermit"})
1306
+ self.assertEqual(channel.code, 200, msg=channel.result)
1307
+ self.assertEqual(channel.json_body["user_id"], "@kermit:test")
1308
+
1309
+ @override_config({"jwt_config": {**base_config, "subject_claim": "username"}})
1310
+ def test_login_custom_sub(self) -> None:
1311
+ """Test reading user ID from a custom subject claim."""
1312
+ channel = self.jwt_login({"username": "frog"})
1313
+ self.assertEqual(channel.code, 200, msg=channel.result)
1314
+ self.assertEqual(channel.json_body["user_id"], "@frog:test")
1315
+
1316
+ @override_config(
1317
+ {"jwt_config": {**base_config, "display_name_claim": "display_name"}}
1318
+ )
1319
+ def test_login_custom_display_name(self) -> None:
1320
+ """Test setting a custom display name."""
1321
+ localpart = "pinkie"
1322
+ user_id = f"@{localpart}:test"
1323
+ display_name = "Pinkie Pie"
1324
+
1325
+ # Perform the login, specifying a custom display name.
1326
+ channel = self.jwt_login({"sub": localpart, "display_name": display_name})
1327
+ self.assertEqual(channel.code, 200, msg=channel.result)
1328
+ self.assertEqual(channel.json_body["user_id"], user_id)
1329
+
1330
+ # Fetch the user's display name and check that it was set correctly.
1331
+ access_token = channel.json_body["access_token"]
1332
+ channel = self.make_request(
1333
+ "GET",
1334
+ f"/_matrix/client/v3/profile/{user_id}/displayname",
1335
+ access_token=access_token,
1336
+ )
1337
+ self.assertEqual(channel.code, 200, msg=channel.result)
1338
+ self.assertEqual(channel.json_body["displayname"], display_name)
1339
+
1340
+ def test_login_no_token(self) -> None:
1341
+ params = {"type": "org.matrix.login.jwt"}
1342
+ channel = self.make_request(b"POST", LOGIN_URL, params)
1343
+ self.assertEqual(channel.code, 403, msg=channel.result)
1344
+ self.assertEqual(channel.json_body["errcode"], "M_FORBIDDEN")
1345
+ self.assertEqual(channel.json_body["error"], "Token field for JWT is missing")
1346
+
1347
+ def test_deactivated_user(self) -> None:
1348
+ """Logging in as a deactivated account should error."""
1349
+ user_id = self.register_user("kermit", "monkey")
1350
+ self.get_success(
1351
+ self.hs.get_deactivate_account_handler().deactivate_account(
1352
+ user_id, erase_data=False, requester=create_requester(user_id)
1353
+ )
1354
+ )
1355
+
1356
+ channel = self.jwt_login({"sub": "kermit"})
1357
+ self.assertEqual(channel.code, 403, msg=channel.result)
1358
+ self.assertEqual(channel.json_body["errcode"], "M_USER_DEACTIVATED")
1359
+ self.assertEqual(
1360
+ channel.json_body["error"], "This account has been deactivated"
1361
+ )
1362
+
1363
+
1364
+ # The JWTPubKeyTestCase is a complement to JWTTestCase where we instead use
1365
+ # RSS256, with a public key configured in synapse as "jwt_secret", and tokens
1366
+ # signed by the private key.
1367
+ @skip_unless(HAS_JWT, "requires authlib")
1368
+ class JWTPubKeyTestCase(unittest.HomeserverTestCase):
1369
+ servlets = [
1370
+ login.register_servlets,
1371
+ ]
1372
+
1373
+ # This key's pubkey is used as the jwt_secret setting of synapse. Valid
1374
+ # tokens are signed by this and validated using the pubkey. It is generated
1375
+ # with `openssl genrsa 512` (not a secure way to generate real keys, but
1376
+ # good enough for tests!)
1377
+ jwt_privatekey = "\n".join(
1378
+ [
1379
+ "-----BEGIN RSA PRIVATE KEY-----",
1380
+ "MIIBPAIBAAJBAM50f1Q5gsdmzifLstzLHb5NhfajiOt7TKO1vSEWdq7u9x8SMFiB",
1381
+ "492RM9W/XFoh8WUfL9uL6Now6tPRDsWv3xsCAwEAAQJAUv7OOSOtiU+wzJq82rnk",
1382
+ "yR4NHqt7XX8BvkZPM7/+EjBRanmZNSp5kYZzKVaZ/gTOM9+9MwlmhidrUOweKfB/",
1383
+ "kQIhAPZwHazbjo7dYlJs7wPQz1vd+aHSEH+3uQKIysebkmm3AiEA1nc6mDdmgiUq",
1384
+ "TpIN8A4MBKmfZMWTLq6z05y/qjKyxb0CIQDYJxCwTEenIaEa4PdoJl+qmXFasVDN",
1385
+ "ZU0+XtNV7yul0wIhAMI9IhiStIjS2EppBa6RSlk+t1oxh2gUWlIh+YVQfZGRAiEA",
1386
+ "tqBR7qLZGJ5CVKxWmNhJZGt1QHoUtOch8t9C4IdOZ2g=",
1387
+ "-----END RSA PRIVATE KEY-----",
1388
+ ]
1389
+ )
1390
+
1391
+ # Generated with `openssl rsa -in foo.key -pubout`, with the the above
1392
+ # private key placed in foo.key (jwt_privatekey).
1393
+ jwt_pubkey = "\n".join(
1394
+ [
1395
+ "-----BEGIN PUBLIC KEY-----",
1396
+ "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAM50f1Q5gsdmzifLstzLHb5NhfajiOt7",
1397
+ "TKO1vSEWdq7u9x8SMFiB492RM9W/XFoh8WUfL9uL6Now6tPRDsWv3xsCAwEAAQ==",
1398
+ "-----END PUBLIC KEY-----",
1399
+ ]
1400
+ )
1401
+
1402
+ # This key is used to sign tokens that shouldn't be accepted by synapse.
1403
+ # Generated just like jwt_privatekey.
1404
+ bad_privatekey = "\n".join(
1405
+ [
1406
+ "-----BEGIN RSA PRIVATE KEY-----",
1407
+ "MIIBOgIBAAJBAL//SQrKpKbjCCnv/FlasJCv+t3k/MPsZfniJe4DVFhsktF2lwQv",
1408
+ "gLjmQD3jBUTz+/FndLSBvr3F4OHtGL9O/osCAwEAAQJAJqH0jZJW7Smzo9ShP02L",
1409
+ "R6HRZcLExZuUrWI+5ZSP7TaZ1uwJzGFspDrunqaVoPobndw/8VsP8HFyKtceC7vY",
1410
+ "uQIhAPdYInDDSJ8rFKGiy3Ajv5KWISBicjevWHF9dbotmNO9AiEAxrdRJVU+EI9I",
1411
+ "eB4qRZpY6n4pnwyP0p8f/A3NBaQPG+cCIFlj08aW/PbxNdqYoBdeBA0xDrXKfmbb",
1412
+ "iwYxBkwL0JCtAiBYmsi94sJn09u2Y4zpuCbJeDPKzWkbuwQh+W1fhIWQJQIhAKR0",
1413
+ "KydN6cRLvphNQ9c/vBTdlzWxzcSxREpguC7F1J1m",
1414
+ "-----END RSA PRIVATE KEY-----",
1415
+ ]
1416
+ )
1417
+
1418
+ def default_config(self) -> dict[str, Any]:
1419
+ config = super().default_config()
1420
+ config["jwt_config"] = {
1421
+ "enabled": True,
1422
+ "secret": self.jwt_pubkey,
1423
+ "algorithm": "RS256",
1424
+ }
1425
+ return config
1426
+
1427
+ def jwt_encode(self, payload: dict[str, Any], secret: str = jwt_privatekey) -> str:
1428
+ header = {"alg": "RS256"}
1429
+ if secret.startswith("-----BEGIN RSA PRIVATE KEY-----"):
1430
+ secret = JsonWebKey.import_key(secret, {"kty": "RSA"})
1431
+ result: bytes = jwt.encode(header, payload, secret)
1432
+ return result.decode("ascii")
1433
+
1434
+ def jwt_login(self, *args: Any) -> FakeChannel:
1435
+ params = {"type": "org.matrix.login.jwt", "token": self.jwt_encode(*args)}
1436
+ channel = self.make_request(b"POST", LOGIN_URL, params)
1437
+ return channel
1438
+
1439
+ def test_login_jwt_valid(self) -> None:
1440
+ channel = self.jwt_login({"sub": "kermit"})
1441
+ self.assertEqual(channel.code, 200, msg=channel.result)
1442
+ self.assertEqual(channel.json_body["user_id"], "@kermit:test")
1443
+
1444
+ def test_login_jwt_invalid_signature(self) -> None:
1445
+ channel = self.jwt_login({"sub": "frog"}, self.bad_privatekey)
1446
+ self.assertEqual(channel.code, 403, msg=channel.result)
1447
+ self.assertEqual(channel.json_body["errcode"], "M_FORBIDDEN")
1448
+ self.assertEqual(
1449
+ channel.json_body["error"],
1450
+ "JWT validation failed: Signature verification failed",
1451
+ )
1452
+
1453
+
1454
+ AS_USER = "as_user_alice"
1455
+
1456
+
1457
+ class AppserviceLoginRestServletTestCase(unittest.HomeserverTestCase):
1458
+ servlets = [
1459
+ login.register_servlets,
1460
+ register.register_servlets,
1461
+ ]
1462
+
1463
+ def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer:
1464
+ self.hs = self.setup_test_homeserver()
1465
+
1466
+ self.service = ApplicationService(
1467
+ id="unique_identifier",
1468
+ token="some_token",
1469
+ sender=UserID.from_string("@asbot:example.com"),
1470
+ namespaces={
1471
+ ApplicationService.NS_USERS: [
1472
+ {"regex": r"@as_user.*", "exclusive": False}
1473
+ ],
1474
+ ApplicationService.NS_ROOMS: [],
1475
+ ApplicationService.NS_ALIASES: [],
1476
+ },
1477
+ )
1478
+ self.another_service = ApplicationService(
1479
+ id="another__identifier",
1480
+ token="another_token",
1481
+ sender=UserID.from_string("@as2bot:example.com"),
1482
+ namespaces={
1483
+ ApplicationService.NS_USERS: [
1484
+ {"regex": r"@as2_user.*", "exclusive": False}
1485
+ ],
1486
+ ApplicationService.NS_ROOMS: [],
1487
+ ApplicationService.NS_ALIASES: [],
1488
+ },
1489
+ )
1490
+ self.msc4190_service = ApplicationService(
1491
+ id="third__identifier",
1492
+ token="third_token",
1493
+ sender=UserID.from_string("@as3bot:example.com"),
1494
+ namespaces={
1495
+ ApplicationService.NS_USERS: [
1496
+ {"regex": r"@as3_user.*", "exclusive": False}
1497
+ ],
1498
+ ApplicationService.NS_ROOMS: [],
1499
+ ApplicationService.NS_ALIASES: [],
1500
+ },
1501
+ msc4190_device_management=True,
1502
+ )
1503
+
1504
+ self.hs.get_datastores().main.services_cache.append(self.service)
1505
+ self.hs.get_datastores().main.services_cache.append(self.another_service)
1506
+ self.hs.get_datastores().main.services_cache.append(self.msc4190_service)
1507
+ return self.hs
1508
+
1509
+ def test_login_appservice_user(self) -> None:
1510
+ """Test that an appservice user can use /login"""
1511
+ self.register_appservice_user(AS_USER, self.service.token)
1512
+
1513
+ params = {
1514
+ "type": login.LoginRestServlet.APPSERVICE_TYPE,
1515
+ "identifier": {"type": "m.id.user", "user": AS_USER},
1516
+ }
1517
+ channel = self.make_request(
1518
+ b"POST", LOGIN_URL, params, access_token=self.service.token
1519
+ )
1520
+
1521
+ self.assertEqual(channel.code, 200, msg=channel.result)
1522
+
1523
+ def test_login_appservice_msc4190_fail(self) -> None:
1524
+ """Test that an appservice user can use /login"""
1525
+ self.register_appservice_user(
1526
+ "as3_user_alice", self.msc4190_service.token, inhibit_login=True
1527
+ )
1528
+
1529
+ params = {
1530
+ "type": login.LoginRestServlet.APPSERVICE_TYPE,
1531
+ "identifier": {"type": "m.id.user", "user": "as3_user_alice"},
1532
+ }
1533
+ channel = self.make_request(
1534
+ b"POST", LOGIN_URL, params, access_token=self.msc4190_service.token
1535
+ )
1536
+
1537
+ self.assertEqual(channel.code, 400, msg=channel.result)
1538
+ self.assertEqual(
1539
+ channel.json_body.get("errcode"),
1540
+ Codes.APPSERVICE_LOGIN_UNSUPPORTED,
1541
+ channel.json_body,
1542
+ )
1543
+
1544
+ def test_login_appservice_user_bot(self) -> None:
1545
+ """Test that the appservice bot can use /login"""
1546
+ self.register_appservice_user(AS_USER, self.service.token)
1547
+
1548
+ params = {
1549
+ "type": login.LoginRestServlet.APPSERVICE_TYPE,
1550
+ "identifier": {
1551
+ "type": "m.id.user",
1552
+ "user": self.service.sender.to_string(),
1553
+ },
1554
+ }
1555
+ channel = self.make_request(
1556
+ b"POST", LOGIN_URL, params, access_token=self.service.token
1557
+ )
1558
+
1559
+ self.assertEqual(channel.code, 200, msg=channel.result)
1560
+
1561
+ def test_login_appservice_wrong_user(self) -> None:
1562
+ """Test that non-as users cannot login with the as token"""
1563
+ self.register_appservice_user(AS_USER, self.service.token)
1564
+
1565
+ params = {
1566
+ "type": login.LoginRestServlet.APPSERVICE_TYPE,
1567
+ "identifier": {"type": "m.id.user", "user": "fibble_wibble"},
1568
+ }
1569
+ channel = self.make_request(
1570
+ b"POST", LOGIN_URL, params, access_token=self.service.token
1571
+ )
1572
+
1573
+ self.assertEqual(channel.code, 403, msg=channel.result)
1574
+
1575
+ def test_login_appservice_wrong_as(self) -> None:
1576
+ """Test that as users cannot login with wrong as token"""
1577
+ self.register_appservice_user(AS_USER, self.service.token)
1578
+
1579
+ params = {
1580
+ "type": login.LoginRestServlet.APPSERVICE_TYPE,
1581
+ "identifier": {"type": "m.id.user", "user": AS_USER},
1582
+ }
1583
+ channel = self.make_request(
1584
+ b"POST", LOGIN_URL, params, access_token=self.another_service.token
1585
+ )
1586
+
1587
+ self.assertEqual(channel.code, 403, msg=channel.result)
1588
+
1589
+ def test_login_appservice_no_token(self) -> None:
1590
+ """Test that users must provide a token when using the appservice
1591
+ login method
1592
+ """
1593
+ self.register_appservice_user(AS_USER, self.service.token)
1594
+
1595
+ params = {
1596
+ "type": login.LoginRestServlet.APPSERVICE_TYPE,
1597
+ "identifier": {"type": "m.id.user", "user": AS_USER},
1598
+ }
1599
+ channel = self.make_request(b"POST", LOGIN_URL, params)
1600
+
1601
+ self.assertEqual(channel.code, 401, msg=channel.result)
1602
+
1603
+
1604
+ @skip_unless(HAS_OIDC, "requires OIDC")
1605
+ class UsernamePickerTestCase(HomeserverTestCase):
1606
+ """Tests for the username picker flow of SSO login"""
1607
+
1608
+ servlets = [
1609
+ login.register_servlets,
1610
+ profile.register_servlets,
1611
+ account.register_servlets,
1612
+ ]
1613
+
1614
+ def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer:
1615
+ self.http_client = Mock(spec=["get_file"])
1616
+ self.http_client.get_file.side_effect = mock_get_file
1617
+ hs = self.setup_test_homeserver(
1618
+ proxied_blocklisted_http_client=self.http_client
1619
+ )
1620
+ return hs
1621
+
1622
+ def default_config(self) -> dict[str, Any]:
1623
+ config = super().default_config()
1624
+ config["public_baseurl"] = PUBLIC_BASEURL
1625
+
1626
+ config["oidc_config"] = {}
1627
+ config["oidc_config"].update(TEST_OIDC_CONFIG)
1628
+ config["oidc_config"]["user_mapping_provider"] = {
1629
+ "config": {
1630
+ "display_name_template": "{{ user.displayname }}",
1631
+ "email_template": "{{ user.email }}",
1632
+ "picture_template": "{{ user.picture }}",
1633
+ }
1634
+ }
1635
+
1636
+ # whitelist this client URI so we redirect straight to it rather than
1637
+ # serving a confirmation page
1638
+ config["sso"] = {"client_whitelist": ["https://x"]}
1639
+ return config
1640
+
1641
+ def create_resource_dict(self) -> dict[str, Resource]:
1642
+ d = super().create_resource_dict()
1643
+ d.update(build_synapse_client_resource_tree(self.hs))
1644
+ return d
1645
+
1646
+ def proceed_to_username_picker_page(
1647
+ self,
1648
+ fake_oidc_server: FakeOidcServer,
1649
+ displayname: str,
1650
+ email: str,
1651
+ picture: str,
1652
+ ) -> tuple[str, str]:
1653
+ # do the start of the login flow
1654
+ channel, _ = self.helper.auth_via_oidc(
1655
+ fake_oidc_server,
1656
+ {
1657
+ "sub": "tester",
1658
+ "displayname": displayname,
1659
+ "picture": picture,
1660
+ "email": email,
1661
+ },
1662
+ TEST_CLIENT_REDIRECT_URL,
1663
+ )
1664
+
1665
+ # that should redirect to the username picker
1666
+ self.assertEqual(channel.code, 302, channel.result)
1667
+ location_headers = channel.headers.getRawHeaders("Location")
1668
+ assert location_headers
1669
+ picker_url = location_headers[0]
1670
+ self.assertEqual(picker_url, "/_synapse/client/pick_username/account_details")
1671
+
1672
+ # ... with a username_mapping_session cookie
1673
+ cookies: dict[str, str] = {}
1674
+ channel.extract_cookies(cookies)
1675
+ self.assertIn("username_mapping_session", cookies)
1676
+ session_id = cookies["username_mapping_session"]
1677
+
1678
+ # introspect the sso handler a bit to check that the username mapping session
1679
+ # looks ok.
1680
+ username_mapping_sessions = self.hs.get_sso_handler()._username_mapping_sessions
1681
+ self.assertIn(
1682
+ session_id,
1683
+ username_mapping_sessions,
1684
+ "session id not found in map",
1685
+ )
1686
+ session = username_mapping_sessions[session_id]
1687
+ self.assertEqual(session.remote_user_id, "tester")
1688
+ self.assertEqual(session.display_name, displayname)
1689
+ self.assertEqual(session.emails, [email])
1690
+ self.assertEqual(session.avatar_url, picture)
1691
+ self.assertEqual(session.client_redirect_url, TEST_CLIENT_REDIRECT_URL)
1692
+
1693
+ # the expiry time should be about 15 minutes away
1694
+ expected_expiry = self.clock.time_msec() + (15 * 60 * 1000)
1695
+ self.assertApproximates(session.expiry_time_ms, expected_expiry, tolerance=1000)
1696
+
1697
+ return picker_url, session_id
1698
+
1699
+ def test_username_picker_use_displayname_avatar_and_email(self) -> None:
1700
+ """Test the happy path of a username picker flow with using displayname, avatar and email."""
1701
+
1702
+ fake_oidc_server = self.helper.fake_oidc_server()
1703
+
1704
+ mxid = "@bobby:test"
1705
+ displayname = "Jonny"
1706
+ email = "bobby@test.com"
1707
+ picture = "mxc://test/avatar_url"
1708
+
1709
+ picker_url, session_id = self.proceed_to_username_picker_page(
1710
+ fake_oidc_server, displayname, email, picture
1711
+ )
1712
+
1713
+ # Now, submit a username to the username picker, which should serve a redirect
1714
+ # to the completion page.
1715
+ # Also specify that we should use the provided displayname, avatar and email.
1716
+ content = urlencode(
1717
+ {
1718
+ b"username": b"bobby",
1719
+ b"use_display_name": b"true",
1720
+ b"use_avatar": b"true",
1721
+ b"use_email": email,
1722
+ }
1723
+ ).encode("utf8")
1724
+ chan = self.make_request(
1725
+ "POST",
1726
+ path=picker_url,
1727
+ content=content,
1728
+ content_is_form=True,
1729
+ custom_headers=[
1730
+ ("Cookie", "username_mapping_session=" + session_id),
1731
+ ],
1732
+ )
1733
+ self.assertEqual(chan.code, 302, chan.result)
1734
+ location_headers = chan.headers.getRawHeaders("Location")
1735
+ assert location_headers
1736
+
1737
+ # send a request to the completion page, which should 302 to the client redirectUrl
1738
+ chan = self.make_request(
1739
+ "GET",
1740
+ path=location_headers[0],
1741
+ custom_headers=[("Cookie", "username_mapping_session=" + session_id)],
1742
+ )
1743
+ self.assertEqual(chan.code, 302, chan.result)
1744
+ location_headers = chan.headers.getRawHeaders("Location")
1745
+ assert location_headers
1746
+
1747
+ # ensure that the returned location matches the requested redirect URL
1748
+ path, query = location_headers[0].split("?", 1)
1749
+ self.assertEqual(path, "https://x")
1750
+
1751
+ # it will have url-encoded the params properly, so we'll have to parse them
1752
+ params = urllib.parse.parse_qsl(
1753
+ query, keep_blank_values=True, strict_parsing=True, errors="strict"
1754
+ )
1755
+ self.assertEqual(params[0:2], EXPECTED_CLIENT_REDIRECT_URL_PARAMS)
1756
+ self.assertEqual(params[2][0], "loginToken")
1757
+
1758
+ # fish the login token out of the returned redirect uri
1759
+ login_token = params[2][1]
1760
+
1761
+ # finally, submit the matrix login token to the login API, which gives us our
1762
+ # matrix access token, mxid, and device id.
1763
+ chan = self.make_request(
1764
+ "POST",
1765
+ "/login",
1766
+ content={"type": "m.login.token", "token": login_token},
1767
+ )
1768
+ self.assertEqual(chan.code, 200, chan.result)
1769
+ self.assertEqual(chan.json_body["user_id"], mxid)
1770
+
1771
+ # ensure the displayname and avatar from the OIDC response have been configured for the user.
1772
+ channel = self.make_request(
1773
+ "GET", "/profile/" + mxid, access_token=chan.json_body["access_token"]
1774
+ )
1775
+ self.assertEqual(channel.code, 200, channel.result)
1776
+ self.assertIn("mxc://test", channel.json_body["avatar_url"])
1777
+ self.assertEqual(displayname, channel.json_body["displayname"])
1778
+
1779
+ # ensure the email from the OIDC response has been configured for the user.
1780
+ channel = self.make_request(
1781
+ "GET", "/account/3pid", access_token=chan.json_body["access_token"]
1782
+ )
1783
+ self.assertEqual(channel.code, 200, channel.result)
1784
+ self.assertEqual(email, channel.json_body["threepids"][0]["address"])
1785
+
1786
+ def test_username_picker_dont_use_displayname_avatar_or_email(self) -> None:
1787
+ """Test the happy path of a username picker flow without using displayname, avatar or email."""
1788
+
1789
+ fake_oidc_server = self.helper.fake_oidc_server()
1790
+
1791
+ mxid = "@bobby:test"
1792
+ displayname = "Jonny"
1793
+ email = "bobby@test.com"
1794
+ picture = "mxc://test/avatar_url"
1795
+ username = "bobby"
1796
+
1797
+ picker_url, session_id = self.proceed_to_username_picker_page(
1798
+ fake_oidc_server, displayname, email, picture
1799
+ )
1800
+
1801
+ # Now, submit a username to the username picker, which should serve a redirect
1802
+ # to the completion page.
1803
+ # Also specify that we should not use the provided displayname, avatar or email.
1804
+ content = urlencode(
1805
+ {
1806
+ b"username": username,
1807
+ b"use_display_name": b"false",
1808
+ b"use_avatar": b"false",
1809
+ }
1810
+ ).encode("utf8")
1811
+ chan = self.make_request(
1812
+ "POST",
1813
+ path=picker_url,
1814
+ content=content,
1815
+ content_is_form=True,
1816
+ custom_headers=[
1817
+ ("Cookie", "username_mapping_session=" + session_id),
1818
+ ],
1819
+ )
1820
+ self.assertEqual(chan.code, 302, chan.result)
1821
+ location_headers = chan.headers.getRawHeaders("Location")
1822
+ assert location_headers
1823
+
1824
+ # send a request to the completion page, which should 302 to the client redirectUrl
1825
+ chan = self.make_request(
1826
+ "GET",
1827
+ path=location_headers[0],
1828
+ custom_headers=[("Cookie", "username_mapping_session=" + session_id)],
1829
+ )
1830
+ self.assertEqual(chan.code, 302, chan.result)
1831
+ location_headers = chan.headers.getRawHeaders("Location")
1832
+ assert location_headers
1833
+
1834
+ # ensure that the returned location matches the requested redirect URL
1835
+ path, query = location_headers[0].split("?", 1)
1836
+ self.assertEqual(path, "https://x")
1837
+
1838
+ # it will have url-encoded the params properly, so we'll have to parse them
1839
+ params = urllib.parse.parse_qsl(
1840
+ query, keep_blank_values=True, strict_parsing=True, errors="strict"
1841
+ )
1842
+ self.assertEqual(params[0:2], EXPECTED_CLIENT_REDIRECT_URL_PARAMS)
1843
+ self.assertEqual(params[2][0], "loginToken")
1844
+
1845
+ # fish the login token out of the returned redirect uri
1846
+ login_token = params[2][1]
1847
+
1848
+ # finally, submit the matrix login token to the login API, which gives us our
1849
+ # matrix access token, mxid, and device id.
1850
+ chan = self.make_request(
1851
+ "POST",
1852
+ "/login",
1853
+ content={"type": "m.login.token", "token": login_token},
1854
+ )
1855
+ self.assertEqual(chan.code, 200, chan.result)
1856
+ self.assertEqual(chan.json_body["user_id"], mxid)
1857
+
1858
+ # ensure the displayname and avatar from the OIDC response have not been configured for the user.
1859
+ channel = self.make_request(
1860
+ "GET", "/profile/" + mxid, access_token=chan.json_body["access_token"]
1861
+ )
1862
+ self.assertEqual(channel.code, 200, channel.result)
1863
+ self.assertNotIn("avatar_url", channel.json_body)
1864
+ self.assertEqual(username, channel.json_body["displayname"])
1865
+
1866
+ # ensure the email from the OIDC response has not been configured for the user.
1867
+ channel = self.make_request(
1868
+ "GET", "/account/3pid", access_token=chan.json_body["access_token"]
1869
+ )
1870
+ self.assertEqual(channel.code, 200, channel.result)
1871
+ self.assertListEqual([], channel.json_body["threepids"])
1872
+
1873
+
1874
+ async def mock_get_file(
1875
+ url: str,
1876
+ output_stream: BinaryIO,
1877
+ max_size: int | None = None,
1878
+ headers: RawHeaders | None = None,
1879
+ is_allowed_content_type: Callable[[str], bool] | None = None,
1880
+ ) -> tuple[int, dict[bytes, list[bytes]], str, int]:
1881
+ return 0, {b"Content-Type": [b"image/png"]}, "", 200