matrix-synapse 1.142.0rc3__cp314-abi3-musllinux_1_2_aarch64.whl

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

Potentially problematic release.


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

Files changed (1057) hide show
  1. matrix_synapse-1.142.0rc3.dist-info/AUTHORS.rst +51 -0
  2. matrix_synapse-1.142.0rc3.dist-info/LICENSE-AGPL-3.0 +661 -0
  3. matrix_synapse-1.142.0rc3.dist-info/LICENSE-COMMERCIAL +6 -0
  4. matrix_synapse-1.142.0rc3.dist-info/METADATA +375 -0
  5. matrix_synapse-1.142.0rc3.dist-info/RECORD +1057 -0
  6. matrix_synapse-1.142.0rc3.dist-info/WHEEL +4 -0
  7. matrix_synapse-1.142.0rc3.dist-info/entry_points.txt +14 -0
  8. matrix_synapse.libs/libgcc_s-2d945d6c.so.1 +0 -0
  9. synapse/__init__.py +97 -0
  10. synapse/_scripts/__init__.py +0 -0
  11. synapse/_scripts/export_signing_key.py +109 -0
  12. synapse/_scripts/generate_config.py +83 -0
  13. synapse/_scripts/generate_log_config.py +56 -0
  14. synapse/_scripts/generate_signing_key.py +55 -0
  15. synapse/_scripts/generate_workers_map.py +318 -0
  16. synapse/_scripts/hash_password.py +95 -0
  17. synapse/_scripts/move_remote_media_to_new_store.py +128 -0
  18. synapse/_scripts/register_new_matrix_user.py +374 -0
  19. synapse/_scripts/review_recent_signups.py +212 -0
  20. synapse/_scripts/synapse_port_db.py +1603 -0
  21. synapse/_scripts/synctl.py +365 -0
  22. synapse/_scripts/update_synapse_database.py +130 -0
  23. synapse/api/__init__.py +20 -0
  24. synapse/api/auth/__init__.py +207 -0
  25. synapse/api/auth/base.py +406 -0
  26. synapse/api/auth/internal.py +299 -0
  27. synapse/api/auth/mas.py +457 -0
  28. synapse/api/auth/msc3861_delegated.py +617 -0
  29. synapse/api/auth_blocking.py +144 -0
  30. synapse/api/constants.py +362 -0
  31. synapse/api/errors.py +907 -0
  32. synapse/api/filtering.py +539 -0
  33. synapse/api/presence.py +104 -0
  34. synapse/api/ratelimiting.py +482 -0
  35. synapse/api/room_versions.py +535 -0
  36. synapse/api/urls.py +119 -0
  37. synapse/app/__init__.py +60 -0
  38. synapse/app/_base.py +866 -0
  39. synapse/app/admin_cmd.py +388 -0
  40. synapse/app/appservice.py +30 -0
  41. synapse/app/client_reader.py +30 -0
  42. synapse/app/complement_fork_starter.py +206 -0
  43. synapse/app/event_creator.py +29 -0
  44. synapse/app/federation_reader.py +30 -0
  45. synapse/app/federation_sender.py +30 -0
  46. synapse/app/frontend_proxy.py +30 -0
  47. synapse/app/generic_worker.py +475 -0
  48. synapse/app/homeserver.py +504 -0
  49. synapse/app/media_repository.py +30 -0
  50. synapse/app/phone_stats_home.py +296 -0
  51. synapse/app/pusher.py +30 -0
  52. synapse/app/synchrotron.py +30 -0
  53. synapse/app/user_dir.py +31 -0
  54. synapse/appservice/__init__.py +461 -0
  55. synapse/appservice/api.py +569 -0
  56. synapse/appservice/scheduler.py +567 -0
  57. synapse/config/__init__.py +27 -0
  58. synapse/config/__main__.py +62 -0
  59. synapse/config/_base.py +1108 -0
  60. synapse/config/_base.pyi +217 -0
  61. synapse/config/_util.py +99 -0
  62. synapse/config/account_validity.py +116 -0
  63. synapse/config/api.py +141 -0
  64. synapse/config/appservice.py +210 -0
  65. synapse/config/auth.py +80 -0
  66. synapse/config/auto_accept_invites.py +43 -0
  67. synapse/config/background_updates.py +44 -0
  68. synapse/config/cache.py +231 -0
  69. synapse/config/captcha.py +90 -0
  70. synapse/config/cas.py +116 -0
  71. synapse/config/consent.py +73 -0
  72. synapse/config/database.py +184 -0
  73. synapse/config/emailconfig.py +367 -0
  74. synapse/config/experimental.py +595 -0
  75. synapse/config/federation.py +114 -0
  76. synapse/config/homeserver.py +141 -0
  77. synapse/config/jwt.py +55 -0
  78. synapse/config/key.py +447 -0
  79. synapse/config/logger.py +390 -0
  80. synapse/config/mas.py +191 -0
  81. synapse/config/matrixrtc.py +66 -0
  82. synapse/config/metrics.py +84 -0
  83. synapse/config/modules.py +40 -0
  84. synapse/config/oembed.py +185 -0
  85. synapse/config/oidc.py +509 -0
  86. synapse/config/password_auth_providers.py +82 -0
  87. synapse/config/push.py +64 -0
  88. synapse/config/ratelimiting.py +254 -0
  89. synapse/config/redis.py +74 -0
  90. synapse/config/registration.py +296 -0
  91. synapse/config/repository.py +311 -0
  92. synapse/config/retention.py +162 -0
  93. synapse/config/room.py +88 -0
  94. synapse/config/room_directory.py +165 -0
  95. synapse/config/saml2.py +251 -0
  96. synapse/config/server.py +1170 -0
  97. synapse/config/server_notices.py +84 -0
  98. synapse/config/spam_checker.py +66 -0
  99. synapse/config/sso.py +121 -0
  100. synapse/config/stats.py +54 -0
  101. synapse/config/third_party_event_rules.py +40 -0
  102. synapse/config/tls.py +192 -0
  103. synapse/config/tracer.py +71 -0
  104. synapse/config/user_directory.py +47 -0
  105. synapse/config/user_types.py +44 -0
  106. synapse/config/voip.py +59 -0
  107. synapse/config/workers.py +642 -0
  108. synapse/crypto/__init__.py +20 -0
  109. synapse/crypto/context_factory.py +278 -0
  110. synapse/crypto/event_signing.py +194 -0
  111. synapse/crypto/keyring.py +931 -0
  112. synapse/event_auth.py +1266 -0
  113. synapse/events/__init__.py +668 -0
  114. synapse/events/auto_accept_invites.py +216 -0
  115. synapse/events/builder.py +387 -0
  116. synapse/events/presence_router.py +245 -0
  117. synapse/events/snapshot.py +559 -0
  118. synapse/events/utils.py +928 -0
  119. synapse/events/validator.py +305 -0
  120. synapse/federation/__init__.py +22 -0
  121. synapse/federation/federation_base.py +383 -0
  122. synapse/federation/federation_client.py +2134 -0
  123. synapse/federation/federation_server.py +1544 -0
  124. synapse/federation/persistence.py +71 -0
  125. synapse/federation/send_queue.py +532 -0
  126. synapse/federation/sender/__init__.py +1165 -0
  127. synapse/federation/sender/per_destination_queue.py +884 -0
  128. synapse/federation/sender/transaction_manager.py +210 -0
  129. synapse/federation/transport/__init__.py +28 -0
  130. synapse/federation/transport/client.py +1201 -0
  131. synapse/federation/transport/server/__init__.py +334 -0
  132. synapse/federation/transport/server/_base.py +429 -0
  133. synapse/federation/transport/server/federation.py +912 -0
  134. synapse/federation/units.py +133 -0
  135. synapse/handlers/__init__.py +20 -0
  136. synapse/handlers/account.py +162 -0
  137. synapse/handlers/account_data.py +362 -0
  138. synapse/handlers/account_validity.py +361 -0
  139. synapse/handlers/admin.py +618 -0
  140. synapse/handlers/appservice.py +991 -0
  141. synapse/handlers/auth.py +2494 -0
  142. synapse/handlers/cas.py +413 -0
  143. synapse/handlers/deactivate_account.py +363 -0
  144. synapse/handlers/delayed_events.py +635 -0
  145. synapse/handlers/device.py +1873 -0
  146. synapse/handlers/devicemessage.py +399 -0
  147. synapse/handlers/directory.py +554 -0
  148. synapse/handlers/e2e_keys.py +1834 -0
  149. synapse/handlers/e2e_room_keys.py +455 -0
  150. synapse/handlers/event_auth.py +390 -0
  151. synapse/handlers/events.py +201 -0
  152. synapse/handlers/federation.py +2043 -0
  153. synapse/handlers/federation_event.py +2420 -0
  154. synapse/handlers/identity.py +812 -0
  155. synapse/handlers/initial_sync.py +528 -0
  156. synapse/handlers/jwt.py +120 -0
  157. synapse/handlers/message.py +2347 -0
  158. synapse/handlers/oidc.py +1803 -0
  159. synapse/handlers/pagination.py +768 -0
  160. synapse/handlers/password_policy.py +102 -0
  161. synapse/handlers/presence.py +2638 -0
  162. synapse/handlers/profile.py +655 -0
  163. synapse/handlers/push_rules.py +164 -0
  164. synapse/handlers/read_marker.py +79 -0
  165. synapse/handlers/receipts.py +351 -0
  166. synapse/handlers/register.py +1060 -0
  167. synapse/handlers/relations.py +624 -0
  168. synapse/handlers/reports.py +98 -0
  169. synapse/handlers/room.py +2447 -0
  170. synapse/handlers/room_list.py +632 -0
  171. synapse/handlers/room_member.py +2365 -0
  172. synapse/handlers/room_member_worker.py +146 -0
  173. synapse/handlers/room_policy.py +186 -0
  174. synapse/handlers/room_summary.py +1057 -0
  175. synapse/handlers/saml.py +524 -0
  176. synapse/handlers/search.py +723 -0
  177. synapse/handlers/send_email.py +209 -0
  178. synapse/handlers/set_password.py +71 -0
  179. synapse/handlers/sliding_sync/__init__.py +1701 -0
  180. synapse/handlers/sliding_sync/extensions.py +970 -0
  181. synapse/handlers/sliding_sync/room_lists.py +2266 -0
  182. synapse/handlers/sliding_sync/store.py +128 -0
  183. synapse/handlers/sso.py +1292 -0
  184. synapse/handlers/state_deltas.py +82 -0
  185. synapse/handlers/stats.py +322 -0
  186. synapse/handlers/sync.py +3109 -0
  187. synapse/handlers/thread_subscriptions.py +190 -0
  188. synapse/handlers/typing.py +606 -0
  189. synapse/handlers/ui_auth/__init__.py +48 -0
  190. synapse/handlers/ui_auth/checkers.py +332 -0
  191. synapse/handlers/user_directory.py +783 -0
  192. synapse/handlers/worker_lock.py +365 -0
  193. synapse/http/__init__.py +106 -0
  194. synapse/http/additional_resource.py +62 -0
  195. synapse/http/client.py +1360 -0
  196. synapse/http/connectproxyclient.py +309 -0
  197. synapse/http/federation/__init__.py +19 -0
  198. synapse/http/federation/matrix_federation_agent.py +490 -0
  199. synapse/http/federation/srv_resolver.py +196 -0
  200. synapse/http/federation/well_known_resolver.py +367 -0
  201. synapse/http/matrixfederationclient.py +1875 -0
  202. synapse/http/proxy.py +290 -0
  203. synapse/http/proxyagent.py +497 -0
  204. synapse/http/replicationagent.py +203 -0
  205. synapse/http/request_metrics.py +309 -0
  206. synapse/http/server.py +1114 -0
  207. synapse/http/servlet.py +1019 -0
  208. synapse/http/site.py +825 -0
  209. synapse/http/types.py +27 -0
  210. synapse/logging/__init__.py +31 -0
  211. synapse/logging/_remote.py +261 -0
  212. synapse/logging/_terse_json.py +95 -0
  213. synapse/logging/context.py +1211 -0
  214. synapse/logging/formatter.py +63 -0
  215. synapse/logging/handlers.py +99 -0
  216. synapse/logging/loggers.py +25 -0
  217. synapse/logging/opentracing.py +1132 -0
  218. synapse/logging/scopecontextmanager.py +161 -0
  219. synapse/media/_base.py +827 -0
  220. synapse/media/filepath.py +417 -0
  221. synapse/media/media_repository.py +1580 -0
  222. synapse/media/media_storage.py +704 -0
  223. synapse/media/oembed.py +277 -0
  224. synapse/media/preview_html.py +559 -0
  225. synapse/media/storage_provider.py +195 -0
  226. synapse/media/thumbnailer.py +833 -0
  227. synapse/media/url_previewer.py +875 -0
  228. synapse/metrics/__init__.py +754 -0
  229. synapse/metrics/_gc.py +219 -0
  230. synapse/metrics/_reactor_metrics.py +171 -0
  231. synapse/metrics/_types.py +38 -0
  232. synapse/metrics/background_process_metrics.py +556 -0
  233. synapse/metrics/common_usage_metrics.py +94 -0
  234. synapse/metrics/jemalloc.py +248 -0
  235. synapse/module_api/__init__.py +2154 -0
  236. synapse/module_api/callbacks/__init__.py +50 -0
  237. synapse/module_api/callbacks/account_validity_callbacks.py +106 -0
  238. synapse/module_api/callbacks/media_repository_callbacks.py +160 -0
  239. synapse/module_api/callbacks/ratelimit_callbacks.py +79 -0
  240. synapse/module_api/callbacks/spamchecker_callbacks.py +1113 -0
  241. synapse/module_api/callbacks/third_party_event_rules_callbacks.py +599 -0
  242. synapse/module_api/errors.py +42 -0
  243. synapse/notifier.py +972 -0
  244. synapse/push/__init__.py +212 -0
  245. synapse/push/bulk_push_rule_evaluator.py +637 -0
  246. synapse/push/clientformat.py +126 -0
  247. synapse/push/emailpusher.py +333 -0
  248. synapse/push/httppusher.py +564 -0
  249. synapse/push/mailer.py +1012 -0
  250. synapse/push/presentable_names.py +216 -0
  251. synapse/push/push_tools.py +114 -0
  252. synapse/push/push_types.py +141 -0
  253. synapse/push/pusher.py +87 -0
  254. synapse/push/pusherpool.py +501 -0
  255. synapse/push/rulekinds.py +33 -0
  256. synapse/py.typed +0 -0
  257. synapse/replication/__init__.py +20 -0
  258. synapse/replication/http/__init__.py +68 -0
  259. synapse/replication/http/_base.py +468 -0
  260. synapse/replication/http/account_data.py +297 -0
  261. synapse/replication/http/deactivate_account.py +81 -0
  262. synapse/replication/http/delayed_events.py +62 -0
  263. synapse/replication/http/devices.py +254 -0
  264. synapse/replication/http/federation.py +334 -0
  265. synapse/replication/http/login.py +106 -0
  266. synapse/replication/http/membership.py +364 -0
  267. synapse/replication/http/presence.py +133 -0
  268. synapse/replication/http/push.py +156 -0
  269. synapse/replication/http/register.py +172 -0
  270. synapse/replication/http/send_events.py +182 -0
  271. synapse/replication/http/state.py +82 -0
  272. synapse/replication/http/streams.py +101 -0
  273. synapse/replication/tcp/__init__.py +56 -0
  274. synapse/replication/tcp/client.py +552 -0
  275. synapse/replication/tcp/commands.py +569 -0
  276. synapse/replication/tcp/context.py +41 -0
  277. synapse/replication/tcp/external_cache.py +156 -0
  278. synapse/replication/tcp/handler.py +942 -0
  279. synapse/replication/tcp/protocol.py +608 -0
  280. synapse/replication/tcp/redis.py +509 -0
  281. synapse/replication/tcp/resource.py +348 -0
  282. synapse/replication/tcp/streams/__init__.py +96 -0
  283. synapse/replication/tcp/streams/_base.py +766 -0
  284. synapse/replication/tcp/streams/events.py +287 -0
  285. synapse/replication/tcp/streams/federation.py +92 -0
  286. synapse/replication/tcp/streams/partial_state.py +80 -0
  287. synapse/res/providers.json +29 -0
  288. synapse/res/templates/_base.html +29 -0
  289. synapse/res/templates/account_previously_renewed.html +6 -0
  290. synapse/res/templates/account_renewed.html +6 -0
  291. synapse/res/templates/add_threepid.html +8 -0
  292. synapse/res/templates/add_threepid.txt +6 -0
  293. synapse/res/templates/add_threepid_failure.html +7 -0
  294. synapse/res/templates/add_threepid_success.html +6 -0
  295. synapse/res/templates/already_in_use.html +12 -0
  296. synapse/res/templates/already_in_use.txt +10 -0
  297. synapse/res/templates/auth_success.html +21 -0
  298. synapse/res/templates/invalid_token.html +6 -0
  299. synapse/res/templates/mail-Element.css +7 -0
  300. synapse/res/templates/mail-Vector.css +7 -0
  301. synapse/res/templates/mail-expiry.css +4 -0
  302. synapse/res/templates/mail.css +156 -0
  303. synapse/res/templates/notice_expiry.html +46 -0
  304. synapse/res/templates/notice_expiry.txt +7 -0
  305. synapse/res/templates/notif.html +51 -0
  306. synapse/res/templates/notif.txt +22 -0
  307. synapse/res/templates/notif_mail.html +59 -0
  308. synapse/res/templates/notif_mail.txt +10 -0
  309. synapse/res/templates/password_reset.html +10 -0
  310. synapse/res/templates/password_reset.txt +7 -0
  311. synapse/res/templates/password_reset_confirmation.html +15 -0
  312. synapse/res/templates/password_reset_failure.html +7 -0
  313. synapse/res/templates/password_reset_success.html +6 -0
  314. synapse/res/templates/recaptcha.html +42 -0
  315. synapse/res/templates/registration.html +12 -0
  316. synapse/res/templates/registration.txt +10 -0
  317. synapse/res/templates/registration_failure.html +6 -0
  318. synapse/res/templates/registration_success.html +6 -0
  319. synapse/res/templates/registration_token.html +18 -0
  320. synapse/res/templates/room.html +33 -0
  321. synapse/res/templates/room.txt +9 -0
  322. synapse/res/templates/sso.css +129 -0
  323. synapse/res/templates/sso_account_deactivated.html +25 -0
  324. synapse/res/templates/sso_auth_account_details.html +186 -0
  325. synapse/res/templates/sso_auth_account_details.js +116 -0
  326. synapse/res/templates/sso_auth_bad_user.html +26 -0
  327. synapse/res/templates/sso_auth_confirm.html +27 -0
  328. synapse/res/templates/sso_auth_success.html +26 -0
  329. synapse/res/templates/sso_error.html +71 -0
  330. synapse/res/templates/sso_footer.html +19 -0
  331. synapse/res/templates/sso_login_idp_picker.html +60 -0
  332. synapse/res/templates/sso_new_user_consent.html +30 -0
  333. synapse/res/templates/sso_partial_profile.html +19 -0
  334. synapse/res/templates/sso_redirect_confirm.html +39 -0
  335. synapse/res/templates/style.css +33 -0
  336. synapse/res/templates/terms.html +27 -0
  337. synapse/rest/__init__.py +197 -0
  338. synapse/rest/admin/__init__.py +390 -0
  339. synapse/rest/admin/_base.py +72 -0
  340. synapse/rest/admin/background_updates.py +171 -0
  341. synapse/rest/admin/devices.py +221 -0
  342. synapse/rest/admin/event_reports.py +173 -0
  343. synapse/rest/admin/events.py +69 -0
  344. synapse/rest/admin/experimental_features.py +137 -0
  345. synapse/rest/admin/federation.py +243 -0
  346. synapse/rest/admin/media.py +540 -0
  347. synapse/rest/admin/registration_tokens.py +358 -0
  348. synapse/rest/admin/rooms.py +1061 -0
  349. synapse/rest/admin/scheduled_tasks.py +70 -0
  350. synapse/rest/admin/server_notice_servlet.py +132 -0
  351. synapse/rest/admin/statistics.py +132 -0
  352. synapse/rest/admin/username_available.py +58 -0
  353. synapse/rest/admin/users.py +1608 -0
  354. synapse/rest/client/__init__.py +20 -0
  355. synapse/rest/client/_base.py +113 -0
  356. synapse/rest/client/account.py +930 -0
  357. synapse/rest/client/account_data.py +319 -0
  358. synapse/rest/client/account_validity.py +103 -0
  359. synapse/rest/client/appservice_ping.py +125 -0
  360. synapse/rest/client/auth.py +218 -0
  361. synapse/rest/client/auth_metadata.py +122 -0
  362. synapse/rest/client/capabilities.py +121 -0
  363. synapse/rest/client/delayed_events.py +111 -0
  364. synapse/rest/client/devices.py +587 -0
  365. synapse/rest/client/directory.py +211 -0
  366. synapse/rest/client/events.py +116 -0
  367. synapse/rest/client/filter.py +112 -0
  368. synapse/rest/client/initial_sync.py +65 -0
  369. synapse/rest/client/keys.py +678 -0
  370. synapse/rest/client/knock.py +104 -0
  371. synapse/rest/client/login.py +754 -0
  372. synapse/rest/client/login_token_request.py +127 -0
  373. synapse/rest/client/logout.py +93 -0
  374. synapse/rest/client/matrixrtc.py +52 -0
  375. synapse/rest/client/media.py +286 -0
  376. synapse/rest/client/mutual_rooms.py +93 -0
  377. synapse/rest/client/notifications.py +137 -0
  378. synapse/rest/client/openid.py +109 -0
  379. synapse/rest/client/password_policy.py +69 -0
  380. synapse/rest/client/presence.py +131 -0
  381. synapse/rest/client/profile.py +291 -0
  382. synapse/rest/client/push_rule.py +331 -0
  383. synapse/rest/client/pusher.py +181 -0
  384. synapse/rest/client/read_marker.py +104 -0
  385. synapse/rest/client/receipts.py +165 -0
  386. synapse/rest/client/register.py +1067 -0
  387. synapse/rest/client/relations.py +138 -0
  388. synapse/rest/client/rendezvous.py +76 -0
  389. synapse/rest/client/reporting.py +207 -0
  390. synapse/rest/client/room.py +1669 -0
  391. synapse/rest/client/room_keys.py +426 -0
  392. synapse/rest/client/room_upgrade_rest_servlet.py +112 -0
  393. synapse/rest/client/sendtodevice.py +85 -0
  394. synapse/rest/client/sync.py +1131 -0
  395. synapse/rest/client/tags.py +129 -0
  396. synapse/rest/client/thirdparty.py +130 -0
  397. synapse/rest/client/thread_subscriptions.py +247 -0
  398. synapse/rest/client/tokenrefresh.py +52 -0
  399. synapse/rest/client/transactions.py +149 -0
  400. synapse/rest/client/user_directory.py +90 -0
  401. synapse/rest/client/versions.py +191 -0
  402. synapse/rest/client/voip.py +88 -0
  403. synapse/rest/consent/__init__.py +0 -0
  404. synapse/rest/consent/consent_resource.py +210 -0
  405. synapse/rest/health.py +38 -0
  406. synapse/rest/key/__init__.py +20 -0
  407. synapse/rest/key/v2/__init__.py +40 -0
  408. synapse/rest/key/v2/local_key_resource.py +125 -0
  409. synapse/rest/key/v2/remote_key_resource.py +302 -0
  410. synapse/rest/media/__init__.py +0 -0
  411. synapse/rest/media/config_resource.py +53 -0
  412. synapse/rest/media/create_resource.py +90 -0
  413. synapse/rest/media/download_resource.py +110 -0
  414. synapse/rest/media/media_repository_resource.py +113 -0
  415. synapse/rest/media/preview_url_resource.py +77 -0
  416. synapse/rest/media/thumbnail_resource.py +142 -0
  417. synapse/rest/media/upload_resource.py +187 -0
  418. synapse/rest/media/v1/__init__.py +39 -0
  419. synapse/rest/media/v1/_base.py +23 -0
  420. synapse/rest/media/v1/media_storage.py +23 -0
  421. synapse/rest/media/v1/storage_provider.py +23 -0
  422. synapse/rest/synapse/__init__.py +20 -0
  423. synapse/rest/synapse/client/__init__.py +93 -0
  424. synapse/rest/synapse/client/federation_whitelist.py +66 -0
  425. synapse/rest/synapse/client/jwks.py +77 -0
  426. synapse/rest/synapse/client/new_user_consent.py +115 -0
  427. synapse/rest/synapse/client/oidc/__init__.py +45 -0
  428. synapse/rest/synapse/client/oidc/backchannel_logout_resource.py +42 -0
  429. synapse/rest/synapse/client/oidc/callback_resource.py +48 -0
  430. synapse/rest/synapse/client/password_reset.py +129 -0
  431. synapse/rest/synapse/client/pick_idp.py +107 -0
  432. synapse/rest/synapse/client/pick_username.py +153 -0
  433. synapse/rest/synapse/client/rendezvous.py +58 -0
  434. synapse/rest/synapse/client/saml2/__init__.py +42 -0
  435. synapse/rest/synapse/client/saml2/metadata_resource.py +46 -0
  436. synapse/rest/synapse/client/saml2/response_resource.py +52 -0
  437. synapse/rest/synapse/client/sso_register.py +56 -0
  438. synapse/rest/synapse/client/unsubscribe.py +88 -0
  439. synapse/rest/synapse/mas/__init__.py +71 -0
  440. synapse/rest/synapse/mas/_base.py +55 -0
  441. synapse/rest/synapse/mas/devices.py +239 -0
  442. synapse/rest/synapse/mas/users.py +469 -0
  443. synapse/rest/well_known.py +148 -0
  444. synapse/server.py +1258 -0
  445. synapse/server_notices/__init__.py +0 -0
  446. synapse/server_notices/consent_server_notices.py +136 -0
  447. synapse/server_notices/resource_limits_server_notices.py +215 -0
  448. synapse/server_notices/server_notices_manager.py +388 -0
  449. synapse/server_notices/server_notices_sender.py +67 -0
  450. synapse/server_notices/worker_server_notices_sender.py +46 -0
  451. synapse/spam_checker_api/__init__.py +31 -0
  452. synapse/state/__init__.py +1022 -0
  453. synapse/state/v1.py +370 -0
  454. synapse/state/v2.py +985 -0
  455. synapse/static/client/login/index.html +47 -0
  456. synapse/static/client/login/js/jquery-3.4.1.min.js +2 -0
  457. synapse/static/client/login/js/login.js +291 -0
  458. synapse/static/client/login/spinner.gif +0 -0
  459. synapse/static/client/login/style.css +79 -0
  460. synapse/static/index.html +63 -0
  461. synapse/storage/__init__.py +43 -0
  462. synapse/storage/_base.py +245 -0
  463. synapse/storage/admin_client_config.py +26 -0
  464. synapse/storage/background_updates.py +1189 -0
  465. synapse/storage/controllers/__init__.py +57 -0
  466. synapse/storage/controllers/persist_events.py +1239 -0
  467. synapse/storage/controllers/purge_events.py +456 -0
  468. synapse/storage/controllers/state.py +954 -0
  469. synapse/storage/controllers/stats.py +119 -0
  470. synapse/storage/database.py +2720 -0
  471. synapse/storage/databases/__init__.py +175 -0
  472. synapse/storage/databases/main/__init__.py +424 -0
  473. synapse/storage/databases/main/account_data.py +1060 -0
  474. synapse/storage/databases/main/appservice.py +473 -0
  475. synapse/storage/databases/main/cache.py +911 -0
  476. synapse/storage/databases/main/censor_events.py +225 -0
  477. synapse/storage/databases/main/client_ips.py +817 -0
  478. synapse/storage/databases/main/delayed_events.py +560 -0
  479. synapse/storage/databases/main/deviceinbox.py +1272 -0
  480. synapse/storage/databases/main/devices.py +2581 -0
  481. synapse/storage/databases/main/directory.py +212 -0
  482. synapse/storage/databases/main/e2e_room_keys.py +690 -0
  483. synapse/storage/databases/main/end_to_end_keys.py +1896 -0
  484. synapse/storage/databases/main/event_federation.py +2509 -0
  485. synapse/storage/databases/main/event_push_actions.py +1937 -0
  486. synapse/storage/databases/main/events.py +3746 -0
  487. synapse/storage/databases/main/events_bg_updates.py +2910 -0
  488. synapse/storage/databases/main/events_forward_extremities.py +126 -0
  489. synapse/storage/databases/main/events_worker.py +2784 -0
  490. synapse/storage/databases/main/experimental_features.py +130 -0
  491. synapse/storage/databases/main/filtering.py +231 -0
  492. synapse/storage/databases/main/keys.py +291 -0
  493. synapse/storage/databases/main/lock.py +553 -0
  494. synapse/storage/databases/main/media_repository.py +1070 -0
  495. synapse/storage/databases/main/metrics.py +460 -0
  496. synapse/storage/databases/main/monthly_active_users.py +443 -0
  497. synapse/storage/databases/main/openid.py +61 -0
  498. synapse/storage/databases/main/presence.py +511 -0
  499. synapse/storage/databases/main/profile.py +541 -0
  500. synapse/storage/databases/main/purge_events.py +511 -0
  501. synapse/storage/databases/main/push_rule.py +972 -0
  502. synapse/storage/databases/main/pusher.py +794 -0
  503. synapse/storage/databases/main/receipts.py +1342 -0
  504. synapse/storage/databases/main/registration.py +3076 -0
  505. synapse/storage/databases/main/rejections.py +38 -0
  506. synapse/storage/databases/main/relations.py +1118 -0
  507. synapse/storage/databases/main/room.py +2781 -0
  508. synapse/storage/databases/main/roommember.py +2112 -0
  509. synapse/storage/databases/main/search.py +941 -0
  510. synapse/storage/databases/main/session.py +151 -0
  511. synapse/storage/databases/main/signatures.py +94 -0
  512. synapse/storage/databases/main/sliding_sync.py +603 -0
  513. synapse/storage/databases/main/state.py +1006 -0
  514. synapse/storage/databases/main/state_deltas.py +329 -0
  515. synapse/storage/databases/main/stats.py +791 -0
  516. synapse/storage/databases/main/stream.py +2580 -0
  517. synapse/storage/databases/main/tags.py +360 -0
  518. synapse/storage/databases/main/task_scheduler.py +225 -0
  519. synapse/storage/databases/main/thread_subscriptions.py +591 -0
  520. synapse/storage/databases/main/transactions.py +681 -0
  521. synapse/storage/databases/main/ui_auth.py +420 -0
  522. synapse/storage/databases/main/user_directory.py +1331 -0
  523. synapse/storage/databases/main/user_erasure_store.py +117 -0
  524. synapse/storage/databases/state/__init__.py +22 -0
  525. synapse/storage/databases/state/bg_updates.py +499 -0
  526. synapse/storage/databases/state/deletion.py +558 -0
  527. synapse/storage/databases/state/store.py +949 -0
  528. synapse/storage/engines/__init__.py +70 -0
  529. synapse/storage/engines/_base.py +154 -0
  530. synapse/storage/engines/postgres.py +261 -0
  531. synapse/storage/engines/sqlite.py +199 -0
  532. synapse/storage/invite_rule.py +112 -0
  533. synapse/storage/keys.py +40 -0
  534. synapse/storage/prepare_database.py +731 -0
  535. synapse/storage/push_rule.py +28 -0
  536. synapse/storage/roommember.py +89 -0
  537. synapse/storage/schema/README.md +4 -0
  538. synapse/storage/schema/__init__.py +182 -0
  539. synapse/storage/schema/common/delta/25/00background_updates.sql +40 -0
  540. synapse/storage/schema/common/delta/35/00background_updates_add_col.sql +36 -0
  541. synapse/storage/schema/common/delta/58/00background_update_ordering.sql +38 -0
  542. synapse/storage/schema/common/full_schemas/72/full.sql.postgres +8 -0
  543. synapse/storage/schema/common/full_schemas/72/full.sql.sqlite +6 -0
  544. synapse/storage/schema/common/schema_version.sql +60 -0
  545. synapse/storage/schema/main/delta/12/v12.sql +82 -0
  546. synapse/storage/schema/main/delta/13/v13.sql +38 -0
  547. synapse/storage/schema/main/delta/14/v14.sql +42 -0
  548. synapse/storage/schema/main/delta/15/appservice_txns.sql +50 -0
  549. synapse/storage/schema/main/delta/15/presence_indices.sql +2 -0
  550. synapse/storage/schema/main/delta/15/v15.sql +24 -0
  551. synapse/storage/schema/main/delta/16/events_order_index.sql +4 -0
  552. synapse/storage/schema/main/delta/16/remote_media_cache_index.sql +2 -0
  553. synapse/storage/schema/main/delta/16/remove_duplicates.sql +9 -0
  554. synapse/storage/schema/main/delta/16/room_alias_index.sql +3 -0
  555. synapse/storage/schema/main/delta/16/unique_constraints.sql +72 -0
  556. synapse/storage/schema/main/delta/16/users.sql +56 -0
  557. synapse/storage/schema/main/delta/17/drop_indexes.sql +37 -0
  558. synapse/storage/schema/main/delta/17/server_keys.sql +43 -0
  559. synapse/storage/schema/main/delta/17/user_threepids.sql +9 -0
  560. synapse/storage/schema/main/delta/18/server_keys_bigger_ints.sql +51 -0
  561. synapse/storage/schema/main/delta/19/event_index.sql +38 -0
  562. synapse/storage/schema/main/delta/20/dummy.sql +1 -0
  563. synapse/storage/schema/main/delta/20/pushers.py +93 -0
  564. synapse/storage/schema/main/delta/21/end_to_end_keys.sql +53 -0
  565. synapse/storage/schema/main/delta/21/receipts.sql +57 -0
  566. synapse/storage/schema/main/delta/22/receipts_index.sql +41 -0
  567. synapse/storage/schema/main/delta/22/user_threepids_unique.sql +19 -0
  568. synapse/storage/schema/main/delta/24/stats_reporting.sql +37 -0
  569. synapse/storage/schema/main/delta/25/fts.py +81 -0
  570. synapse/storage/schema/main/delta/25/guest_access.sql +44 -0
  571. synapse/storage/schema/main/delta/25/history_visibility.sql +44 -0
  572. synapse/storage/schema/main/delta/25/tags.sql +57 -0
  573. synapse/storage/schema/main/delta/26/account_data.sql +36 -0
  574. synapse/storage/schema/main/delta/27/account_data.sql +55 -0
  575. synapse/storage/schema/main/delta/27/forgotten_memberships.sql +45 -0
  576. synapse/storage/schema/main/delta/27/ts.py +61 -0
  577. synapse/storage/schema/main/delta/28/event_push_actions.sql +46 -0
  578. synapse/storage/schema/main/delta/28/events_room_stream.sql +39 -0
  579. synapse/storage/schema/main/delta/28/public_roms_index.sql +39 -0
  580. synapse/storage/schema/main/delta/28/receipts_user_id_index.sql +41 -0
  581. synapse/storage/schema/main/delta/28/upgrade_times.sql +40 -0
  582. synapse/storage/schema/main/delta/28/users_is_guest.sql +41 -0
  583. synapse/storage/schema/main/delta/29/push_actions.sql +54 -0
  584. synapse/storage/schema/main/delta/30/alias_creator.sql +35 -0
  585. synapse/storage/schema/main/delta/30/as_users.py +82 -0
  586. synapse/storage/schema/main/delta/30/deleted_pushers.sql +44 -0
  587. synapse/storage/schema/main/delta/30/presence_stream.sql +49 -0
  588. synapse/storage/schema/main/delta/30/public_rooms.sql +42 -0
  589. synapse/storage/schema/main/delta/30/push_rule_stream.sql +57 -0
  590. synapse/storage/schema/main/delta/30/threepid_guest_access_tokens.sql +43 -0
  591. synapse/storage/schema/main/delta/31/invites.sql +61 -0
  592. synapse/storage/schema/main/delta/31/local_media_repository_url_cache.sql +46 -0
  593. synapse/storage/schema/main/delta/31/pushers_0.py +92 -0
  594. synapse/storage/schema/main/delta/31/pushers_index.sql +41 -0
  595. synapse/storage/schema/main/delta/31/search_update.py +65 -0
  596. synapse/storage/schema/main/delta/32/events.sql +35 -0
  597. synapse/storage/schema/main/delta/32/openid.sql +9 -0
  598. synapse/storage/schema/main/delta/32/pusher_throttle.sql +42 -0
  599. synapse/storage/schema/main/delta/32/remove_indices.sql +52 -0
  600. synapse/storage/schema/main/delta/32/reports.sql +44 -0
  601. synapse/storage/schema/main/delta/33/access_tokens_device_index.sql +36 -0
  602. synapse/storage/schema/main/delta/33/devices.sql +40 -0
  603. synapse/storage/schema/main/delta/33/devices_for_e2e_keys.sql +38 -0
  604. synapse/storage/schema/main/delta/33/devices_for_e2e_keys_clear_unknown_device.sql +39 -0
  605. synapse/storage/schema/main/delta/33/event_fields.py +61 -0
  606. synapse/storage/schema/main/delta/33/remote_media_ts.py +43 -0
  607. synapse/storage/schema/main/delta/33/user_ips_index.sql +36 -0
  608. synapse/storage/schema/main/delta/34/appservice_stream.sql +42 -0
  609. synapse/storage/schema/main/delta/34/cache_stream.py +50 -0
  610. synapse/storage/schema/main/delta/34/device_inbox.sql +43 -0
  611. synapse/storage/schema/main/delta/34/push_display_name_rename.sql +39 -0
  612. synapse/storage/schema/main/delta/34/received_txn_purge.py +36 -0
  613. synapse/storage/schema/main/delta/35/contains_url.sql +36 -0
  614. synapse/storage/schema/main/delta/35/device_outbox.sql +58 -0
  615. synapse/storage/schema/main/delta/35/device_stream_id.sql +40 -0
  616. synapse/storage/schema/main/delta/35/event_push_actions_index.sql +36 -0
  617. synapse/storage/schema/main/delta/35/public_room_list_change_stream.sql +52 -0
  618. synapse/storage/schema/main/delta/35/stream_order_to_extrem.sql +56 -0
  619. synapse/storage/schema/main/delta/36/readd_public_rooms.sql +45 -0
  620. synapse/storage/schema/main/delta/37/remove_auth_idx.py +89 -0
  621. synapse/storage/schema/main/delta/37/user_threepids.sql +71 -0
  622. synapse/storage/schema/main/delta/38/postgres_fts_gist.sql +38 -0
  623. synapse/storage/schema/main/delta/39/appservice_room_list.sql +48 -0
  624. synapse/storage/schema/main/delta/39/device_federation_stream_idx.sql +35 -0
  625. synapse/storage/schema/main/delta/39/event_push_index.sql +36 -0
  626. synapse/storage/schema/main/delta/39/federation_out_position.sql +41 -0
  627. synapse/storage/schema/main/delta/39/membership_profile.sql +39 -0
  628. synapse/storage/schema/main/delta/40/current_state_idx.sql +36 -0
  629. synapse/storage/schema/main/delta/40/device_inbox.sql +40 -0
  630. synapse/storage/schema/main/delta/40/device_list_streams.sql +79 -0
  631. synapse/storage/schema/main/delta/40/event_push_summary.sql +57 -0
  632. synapse/storage/schema/main/delta/40/pushers.sql +58 -0
  633. synapse/storage/schema/main/delta/41/device_list_stream_idx.sql +36 -0
  634. synapse/storage/schema/main/delta/41/device_outbound_index.sql +35 -0
  635. synapse/storage/schema/main/delta/41/event_search_event_id_idx.sql +36 -0
  636. synapse/storage/schema/main/delta/41/ratelimit.sql +41 -0
  637. synapse/storage/schema/main/delta/42/current_state_delta.sql +48 -0
  638. synapse/storage/schema/main/delta/42/device_list_last_id.sql +52 -0
  639. synapse/storage/schema/main/delta/42/event_auth_state_only.sql +36 -0
  640. synapse/storage/schema/main/delta/42/user_dir.py +88 -0
  641. synapse/storage/schema/main/delta/43/blocked_rooms.sql +40 -0
  642. synapse/storage/schema/main/delta/43/quarantine_media.sql +36 -0
  643. synapse/storage/schema/main/delta/43/url_cache.sql +35 -0
  644. synapse/storage/schema/main/delta/43/user_share.sql +52 -0
  645. synapse/storage/schema/main/delta/44/expire_url_cache.sql +60 -0
  646. synapse/storage/schema/main/delta/45/group_server.sql +186 -0
  647. synapse/storage/schema/main/delta/45/profile_cache.sql +47 -0
  648. synapse/storage/schema/main/delta/46/drop_refresh_tokens.sql +36 -0
  649. synapse/storage/schema/main/delta/46/drop_unique_deleted_pushers.sql +54 -0
  650. synapse/storage/schema/main/delta/46/group_server.sql +51 -0
  651. synapse/storage/schema/main/delta/46/local_media_repository_url_idx.sql +43 -0
  652. synapse/storage/schema/main/delta/46/user_dir_null_room_ids.sql +54 -0
  653. synapse/storage/schema/main/delta/46/user_dir_typos.sql +43 -0
  654. synapse/storage/schema/main/delta/47/last_access_media.sql +35 -0
  655. synapse/storage/schema/main/delta/47/postgres_fts_gin.sql +36 -0
  656. synapse/storage/schema/main/delta/47/push_actions_staging.sql +47 -0
  657. synapse/storage/schema/main/delta/48/add_user_consent.sql +37 -0
  658. synapse/storage/schema/main/delta/48/add_user_ips_last_seen_index.sql +36 -0
  659. synapse/storage/schema/main/delta/48/deactivated_users.sql +44 -0
  660. synapse/storage/schema/main/delta/48/group_unique_indexes.py +67 -0
  661. synapse/storage/schema/main/delta/48/groups_joinable.sql +41 -0
  662. synapse/storage/schema/main/delta/49/add_user_consent_server_notice_sent.sql +39 -0
  663. synapse/storage/schema/main/delta/49/add_user_daily_visits.sql +40 -0
  664. synapse/storage/schema/main/delta/49/add_user_ips_last_seen_only_index.sql +36 -0
  665. synapse/storage/schema/main/delta/50/add_creation_ts_users_index.sql +38 -0
  666. synapse/storage/schema/main/delta/50/erasure_store.sql +40 -0
  667. synapse/storage/schema/main/delta/50/make_event_content_nullable.py +102 -0
  668. synapse/storage/schema/main/delta/51/e2e_room_keys.sql +58 -0
  669. synapse/storage/schema/main/delta/51/monthly_active_users.sql +46 -0
  670. synapse/storage/schema/main/delta/52/add_event_to_state_group_index.sql +38 -0
  671. synapse/storage/schema/main/delta/52/device_list_streams_unique_idx.sql +55 -0
  672. synapse/storage/schema/main/delta/52/e2e_room_keys.sql +72 -0
  673. synapse/storage/schema/main/delta/53/add_user_type_to_users.sql +38 -0
  674. synapse/storage/schema/main/delta/53/drop_sent_transactions.sql +35 -0
  675. synapse/storage/schema/main/delta/53/event_format_version.sql +35 -0
  676. synapse/storage/schema/main/delta/53/user_dir_populate.sql +49 -0
  677. synapse/storage/schema/main/delta/53/user_ips_index.sql +49 -0
  678. synapse/storage/schema/main/delta/53/user_share.sql +63 -0
  679. synapse/storage/schema/main/delta/53/user_threepid_id.sql +48 -0
  680. synapse/storage/schema/main/delta/53/users_in_public_rooms.sql +47 -0
  681. synapse/storage/schema/main/delta/54/account_validity_with_renewal.sql +49 -0
  682. synapse/storage/schema/main/delta/54/add_validity_to_server_keys.sql +42 -0
  683. synapse/storage/schema/main/delta/54/delete_forward_extremities.sql +42 -0
  684. synapse/storage/schema/main/delta/54/drop_legacy_tables.sql +49 -0
  685. synapse/storage/schema/main/delta/54/drop_presence_list.sql +35 -0
  686. synapse/storage/schema/main/delta/54/relations.sql +46 -0
  687. synapse/storage/schema/main/delta/54/stats.sql +99 -0
  688. synapse/storage/schema/main/delta/54/stats2.sql +47 -0
  689. synapse/storage/schema/main/delta/55/access_token_expiry.sql +37 -0
  690. synapse/storage/schema/main/delta/55/track_threepid_validations.sql +50 -0
  691. synapse/storage/schema/main/delta/55/users_alter_deactivated.sql +38 -0
  692. synapse/storage/schema/main/delta/56/add_spans_to_device_lists.sql +39 -0
  693. synapse/storage/schema/main/delta/56/current_state_events_membership.sql +41 -0
  694. synapse/storage/schema/main/delta/56/current_state_events_membership_mk2.sql +43 -0
  695. synapse/storage/schema/main/delta/56/delete_keys_from_deleted_backups.sql +44 -0
  696. synapse/storage/schema/main/delta/56/destinations_failure_ts.sql +44 -0
  697. synapse/storage/schema/main/delta/56/destinations_retry_interval_type.sql.postgres +18 -0
  698. synapse/storage/schema/main/delta/56/device_stream_id_insert.sql +39 -0
  699. synapse/storage/schema/main/delta/56/devices_last_seen.sql +43 -0
  700. synapse/storage/schema/main/delta/56/drop_unused_event_tables.sql +39 -0
  701. synapse/storage/schema/main/delta/56/event_expiry.sql +40 -0
  702. synapse/storage/schema/main/delta/56/event_labels.sql +49 -0
  703. synapse/storage/schema/main/delta/56/event_labels_background_update.sql +36 -0
  704. synapse/storage/schema/main/delta/56/fix_room_keys_index.sql +37 -0
  705. synapse/storage/schema/main/delta/56/hidden_devices.sql +37 -0
  706. synapse/storage/schema/main/delta/56/hidden_devices_fix.sql.sqlite +42 -0
  707. synapse/storage/schema/main/delta/56/nuke_empty_communities_from_db.sql +48 -0
  708. synapse/storage/schema/main/delta/56/public_room_list_idx.sql +35 -0
  709. synapse/storage/schema/main/delta/56/redaction_censor.sql +35 -0
  710. synapse/storage/schema/main/delta/56/redaction_censor2.sql +41 -0
  711. synapse/storage/schema/main/delta/56/redaction_censor3_fix_update.sql.postgres +25 -0
  712. synapse/storage/schema/main/delta/56/redaction_censor4.sql +35 -0
  713. synapse/storage/schema/main/delta/56/remove_tombstoned_rooms_from_directory.sql +38 -0
  714. synapse/storage/schema/main/delta/56/room_key_etag.sql +36 -0
  715. synapse/storage/schema/main/delta/56/room_membership_idx.sql +37 -0
  716. synapse/storage/schema/main/delta/56/room_retention.sql +52 -0
  717. synapse/storage/schema/main/delta/56/signing_keys.sql +75 -0
  718. synapse/storage/schema/main/delta/56/signing_keys_nonunique_signatures.sql +41 -0
  719. synapse/storage/schema/main/delta/56/stats_separated.sql +175 -0
  720. synapse/storage/schema/main/delta/56/unique_user_filter_index.py +46 -0
  721. synapse/storage/schema/main/delta/56/user_external_ids.sql +43 -0
  722. synapse/storage/schema/main/delta/56/users_in_public_rooms_idx.sql +36 -0
  723. synapse/storage/schema/main/delta/57/delete_old_current_state_events.sql +41 -0
  724. synapse/storage/schema/main/delta/57/device_list_remote_cache_stale.sql +44 -0
  725. synapse/storage/schema/main/delta/57/local_current_membership.py +111 -0
  726. synapse/storage/schema/main/delta/57/remove_sent_outbound_pokes.sql +40 -0
  727. synapse/storage/schema/main/delta/57/rooms_version_column.sql +43 -0
  728. synapse/storage/schema/main/delta/57/rooms_version_column_2.sql.postgres +35 -0
  729. synapse/storage/schema/main/delta/57/rooms_version_column_2.sql.sqlite +22 -0
  730. synapse/storage/schema/main/delta/57/rooms_version_column_3.sql.postgres +39 -0
  731. synapse/storage/schema/main/delta/57/rooms_version_column_3.sql.sqlite +23 -0
  732. synapse/storage/schema/main/delta/58/02remove_dup_outbound_pokes.sql +41 -0
  733. synapse/storage/schema/main/delta/58/03persist_ui_auth.sql +55 -0
  734. synapse/storage/schema/main/delta/58/05cache_instance.sql.postgres +30 -0
  735. synapse/storage/schema/main/delta/58/06dlols_unique_idx.py +83 -0
  736. synapse/storage/schema/main/delta/58/07add_method_to_thumbnail_constraint.sql.postgres +33 -0
  737. synapse/storage/schema/main/delta/58/07add_method_to_thumbnail_constraint.sql.sqlite +44 -0
  738. synapse/storage/schema/main/delta/58/07persist_ui_auth_ips.sql +44 -0
  739. synapse/storage/schema/main/delta/58/08_media_safe_from_quarantine.sql.postgres +18 -0
  740. synapse/storage/schema/main/delta/58/08_media_safe_from_quarantine.sql.sqlite +18 -0
  741. synapse/storage/schema/main/delta/58/09shadow_ban.sql +37 -0
  742. synapse/storage/schema/main/delta/58/10_pushrules_enabled_delete_obsolete.sql +47 -0
  743. synapse/storage/schema/main/delta/58/10drop_local_rejections_stream.sql +41 -0
  744. synapse/storage/schema/main/delta/58/10federation_pos_instance_name.sql +41 -0
  745. synapse/storage/schema/main/delta/58/11dehydration.sql +39 -0
  746. synapse/storage/schema/main/delta/58/11fallback.sql +43 -0
  747. synapse/storage/schema/main/delta/58/11user_id_seq.py +38 -0
  748. synapse/storage/schema/main/delta/58/12room_stats.sql +51 -0
  749. synapse/storage/schema/main/delta/58/13remove_presence_allow_inbound.sql +36 -0
  750. synapse/storage/schema/main/delta/58/14events_instance_name.sql +35 -0
  751. synapse/storage/schema/main/delta/58/14events_instance_name.sql.postgres +28 -0
  752. synapse/storage/schema/main/delta/58/15_catchup_destination_rooms.sql +61 -0
  753. synapse/storage/schema/main/delta/58/15unread_count.sql +45 -0
  754. synapse/storage/schema/main/delta/58/16populate_stats_process_rooms_fix.sql +41 -0
  755. synapse/storage/schema/main/delta/58/17_catchup_last_successful.sql +40 -0
  756. synapse/storage/schema/main/delta/58/18stream_positions.sql +41 -0
  757. synapse/storage/schema/main/delta/58/19instance_map.sql.postgres +25 -0
  758. synapse/storage/schema/main/delta/58/19txn_id.sql +59 -0
  759. synapse/storage/schema/main/delta/58/20instance_name_event_tables.sql +36 -0
  760. synapse/storage/schema/main/delta/58/20user_daily_visits.sql +37 -0
  761. synapse/storage/schema/main/delta/58/21as_device_stream.sql +36 -0
  762. synapse/storage/schema/main/delta/58/21drop_device_max_stream_id.sql +1 -0
  763. synapse/storage/schema/main/delta/58/22puppet_token.sql +36 -0
  764. synapse/storage/schema/main/delta/58/22users_have_local_media.sql +2 -0
  765. synapse/storage/schema/main/delta/58/23e2e_cross_signing_keys_idx.sql +36 -0
  766. synapse/storage/schema/main/delta/58/24drop_event_json_index.sql +38 -0
  767. synapse/storage/schema/main/delta/58/25user_external_ids_user_id_idx.sql +36 -0
  768. synapse/storage/schema/main/delta/58/26access_token_last_validated.sql +37 -0
  769. synapse/storage/schema/main/delta/58/27local_invites.sql +37 -0
  770. synapse/storage/schema/main/delta/58/28drop_last_used_column.sql.postgres +16 -0
  771. synapse/storage/schema/main/delta/58/28drop_last_used_column.sql.sqlite +62 -0
  772. synapse/storage/schema/main/delta/59/01ignored_user.py +85 -0
  773. synapse/storage/schema/main/delta/59/02shard_send_to_device.sql +37 -0
  774. synapse/storage/schema/main/delta/59/03shard_send_to_device_sequence.sql.postgres +25 -0
  775. synapse/storage/schema/main/delta/59/04_event_auth_chains.sql +71 -0
  776. synapse/storage/schema/main/delta/59/04_event_auth_chains.sql.postgres +16 -0
  777. synapse/storage/schema/main/delta/59/04drop_account_data.sql +36 -0
  778. synapse/storage/schema/main/delta/59/05cache_invalidation.sql +36 -0
  779. synapse/storage/schema/main/delta/59/06chain_cover_index.sql +36 -0
  780. synapse/storage/schema/main/delta/59/06shard_account_data.sql +39 -0
  781. synapse/storage/schema/main/delta/59/06shard_account_data.sql.postgres +32 -0
  782. synapse/storage/schema/main/delta/59/07shard_account_data_fix.sql +37 -0
  783. synapse/storage/schema/main/delta/59/08delete_pushers_for_deactivated_accounts.sql +39 -0
  784. synapse/storage/schema/main/delta/59/08delete_stale_pushers.sql +39 -0
  785. synapse/storage/schema/main/delta/59/09rejected_events_metadata.sql +45 -0
  786. synapse/storage/schema/main/delta/59/10delete_purged_chain_cover.sql +36 -0
  787. synapse/storage/schema/main/delta/59/11add_knock_members_to_stats.sql +39 -0
  788. synapse/storage/schema/main/delta/59/11drop_thumbnail_constraint.sql.postgres +22 -0
  789. synapse/storage/schema/main/delta/59/12account_validity_token_used_ts_ms.sql +37 -0
  790. synapse/storage/schema/main/delta/59/12presence_stream_instance.sql +37 -0
  791. synapse/storage/schema/main/delta/59/12presence_stream_instance_seq.sql.postgres +20 -0
  792. synapse/storage/schema/main/delta/59/13users_to_send_full_presence_to.sql +53 -0
  793. synapse/storage/schema/main/delta/59/14refresh_tokens.sql +53 -0
  794. synapse/storage/schema/main/delta/59/15locks.sql +56 -0
  795. synapse/storage/schema/main/delta/59/16federation_inbound_staging.sql +51 -0
  796. synapse/storage/schema/main/delta/60/01recreate_stream_ordering.sql.postgres +45 -0
  797. synapse/storage/schema/main/delta/60/02change_stream_ordering_columns.sql.postgres +30 -0
  798. synapse/storage/schema/main/delta/61/01change_appservices_txns.sql.postgres +23 -0
  799. synapse/storage/schema/main/delta/61/01insertion_event_lookups.sql +68 -0
  800. synapse/storage/schema/main/delta/61/02drop_redundant_room_depth_index.sql +37 -0
  801. synapse/storage/schema/main/delta/61/03recreate_min_depth.py +74 -0
  802. synapse/storage/schema/main/delta/62/01insertion_event_extremities.sql +43 -0
  803. synapse/storage/schema/main/delta/63/01create_registration_tokens.sql +42 -0
  804. synapse/storage/schema/main/delta/63/02delete_unlinked_email_pushers.sql +39 -0
  805. synapse/storage/schema/main/delta/63/02populate-rooms-creator.sql +36 -0
  806. synapse/storage/schema/main/delta/63/03session_store.sql +42 -0
  807. synapse/storage/schema/main/delta/63/04add_presence_stream_not_offline_index.sql +37 -0
  808. synapse/storage/schema/main/delta/64/01msc2716_chunk_to_batch_rename.sql.postgres +23 -0
  809. synapse/storage/schema/main/delta/64/01msc2716_chunk_to_batch_rename.sql.sqlite +37 -0
  810. synapse/storage/schema/main/delta/65/01msc2716_insertion_event_edges.sql +38 -0
  811. synapse/storage/schema/main/delta/65/03remove_hidden_devices_from_device_inbox.sql +41 -0
  812. synapse/storage/schema/main/delta/65/04_local_group_updates.sql +37 -0
  813. synapse/storage/schema/main/delta/65/05_remove_room_stats_historical_and_user_stats_historical.sql +38 -0
  814. synapse/storage/schema/main/delta/65/06remove_deleted_devices_from_device_inbox.sql +53 -0
  815. synapse/storage/schema/main/delta/65/07_arbitrary_relations.sql +37 -0
  816. synapse/storage/schema/main/delta/65/08_device_inbox_background_updates.sql +37 -0
  817. synapse/storage/schema/main/delta/65/10_expirable_refresh_tokens.sql +47 -0
  818. synapse/storage/schema/main/delta/65/11_devices_auth_provider_session.sql +46 -0
  819. synapse/storage/schema/main/delta/67/01drop_public_room_list_stream.sql +37 -0
  820. synapse/storage/schema/main/delta/68/01event_columns.sql +45 -0
  821. synapse/storage/schema/main/delta/68/02_msc2409_add_device_id_appservice_stream_type.sql +40 -0
  822. synapse/storage/schema/main/delta/68/03_delete_account_data_for_deactivated_accounts.sql +39 -0
  823. synapse/storage/schema/main/delta/68/04_refresh_tokens_index_next_token_id.sql +47 -0
  824. synapse/storage/schema/main/delta/68/04partial_state_rooms.sql +60 -0
  825. synapse/storage/schema/main/delta/68/05_delete_non_strings_from_event_search.sql.sqlite +22 -0
  826. synapse/storage/schema/main/delta/68/05partial_state_rooms_triggers.py +80 -0
  827. synapse/storage/schema/main/delta/68/06_msc3202_add_device_list_appservice_stream_type.sql +42 -0
  828. synapse/storage/schema/main/delta/69/01as_txn_seq.py +54 -0
  829. synapse/storage/schema/main/delta/69/01device_list_oubound_by_room.sql +57 -0
  830. synapse/storage/schema/main/delta/69/02cache_invalidation_index.sql +37 -0
  831. synapse/storage/schema/main/delta/70/01clean_table_purged_rooms.sql +39 -0
  832. synapse/storage/schema/main/delta/71/01rebuild_event_edges.sql.postgres +43 -0
  833. synapse/storage/schema/main/delta/71/01rebuild_event_edges.sql.sqlite +47 -0
  834. synapse/storage/schema/main/delta/71/01remove_noop_background_updates.sql +80 -0
  835. synapse/storage/schema/main/delta/71/02event_push_summary_unique.sql +37 -0
  836. synapse/storage/schema/main/delta/72/01add_room_type_to_state_stats.sql +38 -0
  837. synapse/storage/schema/main/delta/72/01event_push_summary_receipt.sql +54 -0
  838. synapse/storage/schema/main/delta/72/02event_push_actions_index.sql +38 -0
  839. synapse/storage/schema/main/delta/72/03bg_populate_events_columns.py +57 -0
  840. synapse/storage/schema/main/delta/72/03drop_event_reference_hashes.sql +36 -0
  841. synapse/storage/schema/main/delta/72/03remove_groups.sql +50 -0
  842. synapse/storage/schema/main/delta/72/04drop_column_application_services_state_last_txn.sql.postgres +17 -0
  843. synapse/storage/schema/main/delta/72/04drop_column_application_services_state_last_txn.sql.sqlite +40 -0
  844. synapse/storage/schema/main/delta/72/05receipts_event_stream_ordering.sql +38 -0
  845. synapse/storage/schema/main/delta/72/05remove_unstable_private_read_receipts.sql +38 -0
  846. synapse/storage/schema/main/delta/72/06add_consent_ts_to_users.sql +35 -0
  847. synapse/storage/schema/main/delta/72/06thread_notifications.sql +49 -0
  848. synapse/storage/schema/main/delta/72/07force_update_current_state_events_membership.py +67 -0
  849. synapse/storage/schema/main/delta/72/07thread_receipts.sql.postgres +30 -0
  850. synapse/storage/schema/main/delta/72/07thread_receipts.sql.sqlite +70 -0
  851. synapse/storage/schema/main/delta/72/08begin_cache_invalidation_seq_at_2.sql.postgres +23 -0
  852. synapse/storage/schema/main/delta/72/08thread_receipts.sql +39 -0
  853. synapse/storage/schema/main/delta/72/09partial_indices.sql.sqlite +56 -0
  854. synapse/storage/schema/main/delta/73/01event_failed_pull_attempts.sql +48 -0
  855. synapse/storage/schema/main/delta/73/02add_pusher_enabled.sql +35 -0
  856. synapse/storage/schema/main/delta/73/02room_id_indexes_for_purging.sql +41 -0
  857. synapse/storage/schema/main/delta/73/03pusher_device_id.sql +39 -0
  858. synapse/storage/schema/main/delta/73/03users_approved_column.sql +39 -0
  859. synapse/storage/schema/main/delta/73/04partial_join_details.sql +42 -0
  860. synapse/storage/schema/main/delta/73/04pending_device_list_updates.sql +47 -0
  861. synapse/storage/schema/main/delta/73/05old_push_actions.sql.postgres +22 -0
  862. synapse/storage/schema/main/delta/73/05old_push_actions.sql.sqlite +24 -0
  863. synapse/storage/schema/main/delta/73/06thread_notifications_thread_id_idx.sql +42 -0
  864. synapse/storage/schema/main/delta/73/08thread_receipts_non_null.sql.postgres +23 -0
  865. synapse/storage/schema/main/delta/73/08thread_receipts_non_null.sql.sqlite +76 -0
  866. synapse/storage/schema/main/delta/73/09partial_joined_via_destination.sql +37 -0
  867. synapse/storage/schema/main/delta/73/09threads_table.sql +49 -0
  868. synapse/storage/schema/main/delta/73/10_update_sqlite_fts4_tokenizer.py +71 -0
  869. synapse/storage/schema/main/delta/73/10login_tokens.sql +54 -0
  870. synapse/storage/schema/main/delta/73/11event_search_room_id_n_distinct.sql.postgres +33 -0
  871. synapse/storage/schema/main/delta/73/12refactor_device_list_outbound_pokes.sql +72 -0
  872. synapse/storage/schema/main/delta/73/13add_device_lists_index.sql +39 -0
  873. synapse/storage/schema/main/delta/73/20_un_partial_stated_room_stream.sql +51 -0
  874. synapse/storage/schema/main/delta/73/21_un_partial_stated_room_stream_seq.sql.postgres +20 -0
  875. synapse/storage/schema/main/delta/73/22_rebuild_user_dir_stats.sql +48 -0
  876. synapse/storage/schema/main/delta/73/22_un_partial_stated_event_stream.sql +53 -0
  877. synapse/storage/schema/main/delta/73/23_fix_thread_index.sql +52 -0
  878. synapse/storage/schema/main/delta/73/23_un_partial_stated_room_stream_seq.sql.postgres +20 -0
  879. synapse/storage/schema/main/delta/73/24_events_jump_to_date_index.sql +36 -0
  880. synapse/storage/schema/main/delta/73/25drop_presence.sql +36 -0
  881. synapse/storage/schema/main/delta/74/01_user_directory_stale_remote_users.sql +58 -0
  882. synapse/storage/schema/main/delta/74/02_set_device_id_for_pushers_bg_update.sql +38 -0
  883. synapse/storage/schema/main/delta/74/03_membership_tables_event_stream_ordering.sql.postgres +29 -0
  884. synapse/storage/schema/main/delta/74/03_membership_tables_event_stream_ordering.sql.sqlite +23 -0
  885. synapse/storage/schema/main/delta/74/03_room_membership_index.sql +38 -0
  886. synapse/storage/schema/main/delta/74/04_delete_e2e_backup_keys_for_deactivated_users.sql +36 -0
  887. synapse/storage/schema/main/delta/74/04_membership_tables_event_stream_ordering_triggers.py +87 -0
  888. synapse/storage/schema/main/delta/74/05_events_txn_id_device_id.sql +72 -0
  889. synapse/storage/schema/main/delta/74/90COMMENTS_destinations.sql.postgres +52 -0
  890. synapse/storage/schema/main/delta/76/01_add_profiles_full_user_id_column.sql +39 -0
  891. synapse/storage/schema/main/delta/76/02_add_user_filters_full_user_id_column.sql +39 -0
  892. synapse/storage/schema/main/delta/76/03_per_user_experimental_features.sql +46 -0
  893. synapse/storage/schema/main/delta/76/04_add_room_forgetter.sql +43 -0
  894. synapse/storage/schema/main/delta/77/01_add_profiles_not_valid_check.sql.postgres +16 -0
  895. synapse/storage/schema/main/delta/77/02_add_user_filters_not_valid_check.sql.postgres +16 -0
  896. synapse/storage/schema/main/delta/77/03bg_populate_full_user_id_profiles.sql +35 -0
  897. synapse/storage/schema/main/delta/77/04bg_populate_full_user_id_user_filters.sql +35 -0
  898. synapse/storage/schema/main/delta/77/05thread_notifications_backfill.sql +67 -0
  899. synapse/storage/schema/main/delta/77/06thread_notifications_not_null.sql.sqlite +102 -0
  900. synapse/storage/schema/main/delta/77/06thread_notifications_not_null_event_push_actions.sql.postgres +27 -0
  901. synapse/storage/schema/main/delta/77/06thread_notifications_not_null_event_push_actions_staging.sql.postgres +27 -0
  902. synapse/storage/schema/main/delta/77/06thread_notifications_not_null_event_push_summary.sql.postgres +29 -0
  903. synapse/storage/schema/main/delta/77/14bg_indices_event_stream_ordering.sql +39 -0
  904. synapse/storage/schema/main/delta/78/01_validate_and_update_profiles.py +99 -0
  905. synapse/storage/schema/main/delta/78/02_validate_and_update_user_filters.py +100 -0
  906. synapse/storage/schema/main/delta/78/03_remove_unused_indexes_user_filters.py +72 -0
  907. synapse/storage/schema/main/delta/78/03event_extremities_constraints.py +65 -0
  908. synapse/storage/schema/main/delta/78/04_add_full_user_id_index_user_filters.py +32 -0
  909. synapse/storage/schema/main/delta/79/03_read_write_locks_triggers.sql.postgres +102 -0
  910. synapse/storage/schema/main/delta/79/03_read_write_locks_triggers.sql.sqlite +72 -0
  911. synapse/storage/schema/main/delta/79/04_mitigate_stream_ordering_update_race.py +70 -0
  912. synapse/storage/schema/main/delta/79/05_read_write_locks_triggers.sql.postgres +69 -0
  913. synapse/storage/schema/main/delta/79/05_read_write_locks_triggers.sql.sqlite +65 -0
  914. synapse/storage/schema/main/delta/80/01_users_alter_locked.sql +35 -0
  915. synapse/storage/schema/main/delta/80/02_read_write_locks_unlogged.sql.postgres +30 -0
  916. synapse/storage/schema/main/delta/80/02_scheduled_tasks.sql +47 -0
  917. synapse/storage/schema/main/delta/80/03_read_write_locks_triggers.sql.postgres +37 -0
  918. synapse/storage/schema/main/delta/80/04_read_write_locks_deadlock.sql.postgres +71 -0
  919. synapse/storage/schema/main/delta/82/02_scheduled_tasks_index.sql +35 -0
  920. synapse/storage/schema/main/delta/82/04_add_indices_for_purging_rooms.sql +39 -0
  921. synapse/storage/schema/main/delta/82/05gaps.sql +44 -0
  922. synapse/storage/schema/main/delta/83/01_drop_old_tables.sql +43 -0
  923. synapse/storage/schema/main/delta/83/03_instance_name_receipts.sql.sqlite +17 -0
  924. synapse/storage/schema/main/delta/83/05_cross_signing_key_update_grant.sql +34 -0
  925. synapse/storage/schema/main/delta/83/06_event_push_summary_room.sql +36 -0
  926. synapse/storage/schema/main/delta/84/01_auth_links_stats.sql.postgres +20 -0
  927. synapse/storage/schema/main/delta/84/02_auth_links_index.sql +16 -0
  928. synapse/storage/schema/main/delta/84/03_auth_links_analyze.sql.postgres +16 -0
  929. synapse/storage/schema/main/delta/84/04_access_token_index.sql +15 -0
  930. synapse/storage/schema/main/delta/85/01_add_suspended.sql +14 -0
  931. synapse/storage/schema/main/delta/85/02_add_instance_names.sql +27 -0
  932. synapse/storage/schema/main/delta/85/03_new_sequences.sql.postgres +54 -0
  933. synapse/storage/schema/main/delta/85/04_cleanup_device_federation_outbox.sql +15 -0
  934. synapse/storage/schema/main/delta/85/05_add_instance_names_converted_pos.sql +16 -0
  935. synapse/storage/schema/main/delta/85/06_add_room_reports.sql +20 -0
  936. synapse/storage/schema/main/delta/86/01_authenticate_media.sql +15 -0
  937. synapse/storage/schema/main/delta/86/02_receipts_event_id_index.sql +15 -0
  938. synapse/storage/schema/main/delta/87/01_sliding_sync_memberships.sql +169 -0
  939. synapse/storage/schema/main/delta/87/02_per_connection_state.sql +81 -0
  940. synapse/storage/schema/main/delta/87/03_current_state_index.sql +19 -0
  941. synapse/storage/schema/main/delta/88/01_add_delayed_events.sql +43 -0
  942. synapse/storage/schema/main/delta/88/01_custom_profile_fields.sql +15 -0
  943. synapse/storage/schema/main/delta/88/02_fix_sliding_sync_membership_snapshots_forgotten_column.sql +21 -0
  944. synapse/storage/schema/main/delta/88/03_add_otk_ts_added_index.sql +18 -0
  945. synapse/storage/schema/main/delta/88/04_current_state_delta_index.sql +18 -0
  946. synapse/storage/schema/main/delta/88/05_drop_old_otks.sql.postgres +19 -0
  947. synapse/storage/schema/main/delta/88/05_drop_old_otks.sql.sqlite +19 -0
  948. synapse/storage/schema/main/delta/88/05_sliding_sync_room_config_index.sql +20 -0
  949. synapse/storage/schema/main/delta/88/06_events_received_ts_index.sql +17 -0
  950. synapse/storage/schema/main/delta/89/01_sliding_sync_membership_snapshot_index.sql +15 -0
  951. synapse/storage/schema/main/delta/90/01_add_column_participant_room_memberships_table.sql +16 -0
  952. synapse/storage/schema/main/delta/91/01_media_hash.sql +28 -0
  953. synapse/storage/schema/main/delta/92/01_remove_trigger.sql.postgres +16 -0
  954. synapse/storage/schema/main/delta/92/01_remove_trigger.sql.sqlite +16 -0
  955. synapse/storage/schema/main/delta/92/02_remove_populate_participant_bg_update.sql +17 -0
  956. synapse/storage/schema/main/delta/92/04_ss_membership_snapshot_idx.sql +16 -0
  957. synapse/storage/schema/main/delta/92/04_thread_subscriptions.sql +59 -0
  958. synapse/storage/schema/main/delta/92/04_thread_subscriptions_seq.sql.postgres +19 -0
  959. synapse/storage/schema/main/delta/92/05_fixup_max_depth_cap.sql +17 -0
  960. synapse/storage/schema/main/delta/92/05_thread_subscriptions_comments.sql.postgres +18 -0
  961. synapse/storage/schema/main/delta/92/06_device_federation_inbox_index.sql +16 -0
  962. synapse/storage/schema/main/delta/92/06_threads_last_sent_stream_ordering_comments.sql.postgres +24 -0
  963. synapse/storage/schema/main/delta/92/07_add_user_reports.sql +22 -0
  964. synapse/storage/schema/main/delta/92/07_event_txn_id_device_id_txn_id2.sql +15 -0
  965. synapse/storage/schema/main/delta/92/08_room_ban_redactions.sql +21 -0
  966. synapse/storage/schema/main/delta/92/08_thread_subscriptions_seq_fixup.sql.postgres +19 -0
  967. synapse/storage/schema/main/delta/92/09_thread_subscriptions_update.sql +20 -0
  968. synapse/storage/schema/main/delta/92/09_thread_subscriptions_update.sql.postgres +18 -0
  969. synapse/storage/schema/main/full_schemas/72/full.sql.postgres +1344 -0
  970. synapse/storage/schema/main/full_schemas/72/full.sql.sqlite +646 -0
  971. synapse/storage/schema/state/delta/23/drop_state_index.sql +35 -0
  972. synapse/storage/schema/state/delta/32/remove_state_indices.sql +38 -0
  973. synapse/storage/schema/state/delta/35/add_state_index.sql +36 -0
  974. synapse/storage/schema/state/delta/35/state.sql +41 -0
  975. synapse/storage/schema/state/delta/35/state_dedupe.sql +36 -0
  976. synapse/storage/schema/state/delta/47/state_group_seq.py +38 -0
  977. synapse/storage/schema/state/delta/56/state_group_room_idx.sql +36 -0
  978. synapse/storage/schema/state/delta/61/02state_groups_state_n_distinct.sql.postgres +34 -0
  979. synapse/storage/schema/state/delta/70/08_state_group_edges_unique.sql +36 -0
  980. synapse/storage/schema/state/delta/89/01_state_groups_deletion.sql +39 -0
  981. synapse/storage/schema/state/delta/90/02_delete_unreferenced_state_groups.sql +16 -0
  982. synapse/storage/schema/state/delta/90/03_remove_old_deletion_bg_update.sql +15 -0
  983. synapse/storage/schema/state/full_schemas/72/full.sql.postgres +30 -0
  984. synapse/storage/schema/state/full_schemas/72/full.sql.sqlite +20 -0
  985. synapse/storage/types.py +185 -0
  986. synapse/storage/util/__init__.py +20 -0
  987. synapse/storage/util/id_generators.py +909 -0
  988. synapse/storage/util/partial_state_events_tracker.py +194 -0
  989. synapse/storage/util/sequence.py +315 -0
  990. synapse/streams/__init__.py +43 -0
  991. synapse/streams/config.py +92 -0
  992. synapse/streams/events.py +203 -0
  993. synapse/synapse_rust/__init__.pyi +3 -0
  994. synapse/synapse_rust/acl.pyi +20 -0
  995. synapse/synapse_rust/events.pyi +136 -0
  996. synapse/synapse_rust/http_client.pyi +32 -0
  997. synapse/synapse_rust/push.pyi +86 -0
  998. synapse/synapse_rust/rendezvous.pyi +30 -0
  999. synapse/synapse_rust/segmenter.pyi +1 -0
  1000. synapse/synapse_rust.abi3.so +0 -0
  1001. synapse/types/__init__.py +1600 -0
  1002. synapse/types/handlers/__init__.py +93 -0
  1003. synapse/types/handlers/policy_server.py +16 -0
  1004. synapse/types/handlers/sliding_sync.py +909 -0
  1005. synapse/types/rest/__init__.py +25 -0
  1006. synapse/types/rest/client/__init__.py +415 -0
  1007. synapse/types/state.py +635 -0
  1008. synapse/types/storage/__init__.py +66 -0
  1009. synapse/util/__init__.py +170 -0
  1010. synapse/util/async_helpers.py +1067 -0
  1011. synapse/util/batching_queue.py +202 -0
  1012. synapse/util/caches/__init__.py +300 -0
  1013. synapse/util/caches/cached_call.py +143 -0
  1014. synapse/util/caches/deferred_cache.py +530 -0
  1015. synapse/util/caches/descriptors.py +694 -0
  1016. synapse/util/caches/dictionary_cache.py +350 -0
  1017. synapse/util/caches/expiringcache.py +251 -0
  1018. synapse/util/caches/lrucache.py +977 -0
  1019. synapse/util/caches/response_cache.py +323 -0
  1020. synapse/util/caches/stream_change_cache.py +370 -0
  1021. synapse/util/caches/treecache.py +189 -0
  1022. synapse/util/caches/ttlcache.py +197 -0
  1023. synapse/util/cancellation.py +63 -0
  1024. synapse/util/check_dependencies.py +335 -0
  1025. synapse/util/clock.py +500 -0
  1026. synapse/util/constants.py +22 -0
  1027. synapse/util/daemonize.py +165 -0
  1028. synapse/util/distributor.py +159 -0
  1029. synapse/util/events.py +134 -0
  1030. synapse/util/file_consumer.py +164 -0
  1031. synapse/util/frozenutils.py +57 -0
  1032. synapse/util/gai_resolver.py +180 -0
  1033. synapse/util/hash.py +38 -0
  1034. synapse/util/httpresourcetree.py +108 -0
  1035. synapse/util/iterutils.py +189 -0
  1036. synapse/util/json.py +56 -0
  1037. synapse/util/linked_list.py +156 -0
  1038. synapse/util/logcontext.py +46 -0
  1039. synapse/util/logformatter.py +28 -0
  1040. synapse/util/macaroons.py +325 -0
  1041. synapse/util/manhole.py +191 -0
  1042. synapse/util/metrics.py +340 -0
  1043. synapse/util/module_loader.py +116 -0
  1044. synapse/util/msisdn.py +51 -0
  1045. synapse/util/patch_inline_callbacks.py +250 -0
  1046. synapse/util/pydantic_models.py +56 -0
  1047. synapse/util/ratelimitutils.py +420 -0
  1048. synapse/util/retryutils.py +339 -0
  1049. synapse/util/rlimit.py +42 -0
  1050. synapse/util/rust.py +134 -0
  1051. synapse/util/sentinel.py +21 -0
  1052. synapse/util/stringutils.py +293 -0
  1053. synapse/util/task_scheduler.py +493 -0
  1054. synapse/util/templates.py +126 -0
  1055. synapse/util/threepids.py +123 -0
  1056. synapse/util/wheel_timer.py +112 -0
  1057. synapse/visibility.py +836 -0
@@ -0,0 +1,1331 @@
1
+ #
2
+ # This file is licensed under the Affero General Public License (AGPL) version 3.
3
+ #
4
+ # Copyright 2017 Vector Creations Ltd
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
+
22
+ import logging
23
+ import re
24
+ import unicodedata
25
+ from typing import (
26
+ TYPE_CHECKING,
27
+ Collection,
28
+ Iterable,
29
+ Optional,
30
+ Sequence,
31
+ TypedDict,
32
+ cast,
33
+ )
34
+
35
+ import attr
36
+
37
+ from synapse.api.errors import StoreError
38
+ from synapse.synapse_rust import segmenter as icu
39
+ from synapse.util.stringutils import non_null_str_or_none
40
+
41
+ if TYPE_CHECKING:
42
+ from synapse.server import HomeServer
43
+
44
+ from synapse.api.constants import EventTypes, HistoryVisibility, JoinRules, UserTypes
45
+ from synapse.storage.database import (
46
+ DatabasePool,
47
+ LoggingDatabaseConnection,
48
+ LoggingTransaction,
49
+ )
50
+ from synapse.storage.databases.main.state import StateFilter
51
+ from synapse.storage.databases.main.state_deltas import StateDeltasStore
52
+ from synapse.storage.engines import PostgresEngine, Sqlite3Engine
53
+ from synapse.types import (
54
+ JsonDict,
55
+ UserID,
56
+ UserProfile,
57
+ get_domain_from_id,
58
+ get_localpart_from_id,
59
+ )
60
+
61
+ logger = logging.getLogger(__name__)
62
+
63
+ TEMP_TABLE = "_temp_populate_user_directory"
64
+
65
+
66
+ @attr.s(auto_attribs=True, frozen=True)
67
+ class _UserDirProfile:
68
+ """Helper type for the user directory code for an entry to be inserted into
69
+ the directory.
70
+ """
71
+
72
+ user_id: str
73
+
74
+ # If the display name or avatar URL are unexpected types, replace with None
75
+ display_name: Optional[str] = attr.ib(default=None, converter=non_null_str_or_none)
76
+ avatar_url: Optional[str] = attr.ib(default=None, converter=non_null_str_or_none)
77
+
78
+
79
+ class UserDirectoryBackgroundUpdateStore(StateDeltasStore):
80
+ # How many records do we calculate before sending it to
81
+ # add_users_who_share_private_rooms?
82
+ SHARE_PRIVATE_WORKING_SET = 500
83
+
84
+ def __init__(
85
+ self,
86
+ database: DatabasePool,
87
+ db_conn: LoggingDatabaseConnection,
88
+ hs: "HomeServer",
89
+ ) -> None:
90
+ super().__init__(database, db_conn, hs)
91
+
92
+ self.server_name: str = hs.hostname
93
+
94
+ self.db_pool.updates.register_background_update_handler(
95
+ "populate_user_directory_createtables",
96
+ self._populate_user_directory_createtables,
97
+ )
98
+ self.db_pool.updates.register_background_update_handler(
99
+ "populate_user_directory_process_rooms",
100
+ self._populate_user_directory_process_rooms,
101
+ )
102
+ self.db_pool.updates.register_background_update_handler(
103
+ "populate_user_directory_process_users",
104
+ self._populate_user_directory_process_users,
105
+ )
106
+ self.db_pool.updates.register_background_update_handler(
107
+ "populate_user_directory_cleanup", self._populate_user_directory_cleanup
108
+ )
109
+
110
+ async def _populate_user_directory_createtables(
111
+ self, progress: JsonDict, batch_size: int
112
+ ) -> int:
113
+ # Get all the rooms that we want to process.
114
+ def _make_staging_area(txn: LoggingTransaction) -> None:
115
+ sql = f"""
116
+ CREATE TABLE IF NOT EXISTS {TEMP_TABLE}_rooms AS
117
+ SELECT room_id, count(*) AS events
118
+ FROM current_state_events
119
+ GROUP BY room_id
120
+ """
121
+ txn.execute(sql)
122
+ txn.execute(
123
+ f"CREATE INDEX IF NOT EXISTS {TEMP_TABLE}_rooms_rm ON {TEMP_TABLE}_rooms (room_id)"
124
+ )
125
+ txn.execute(
126
+ f"CREATE INDEX IF NOT EXISTS {TEMP_TABLE}_rooms_evs ON {TEMP_TABLE}_rooms (events)"
127
+ )
128
+
129
+ sql = f"""
130
+ CREATE TABLE IF NOT EXISTS {TEMP_TABLE}_position (
131
+ position TEXT NOT NULL
132
+ )
133
+ """
134
+ txn.execute(sql)
135
+
136
+ sql = f"""
137
+ CREATE TABLE IF NOT EXISTS {TEMP_TABLE}_users AS
138
+ SELECT name AS user_id FROM users
139
+ """
140
+ txn.execute(sql)
141
+ txn.execute(
142
+ f"CREATE INDEX IF NOT EXISTS {TEMP_TABLE}_users_idx ON {TEMP_TABLE}_users (user_id)"
143
+ )
144
+
145
+ new_pos = await self.get_max_stream_id_in_current_state_deltas()
146
+ await self.db_pool.runInteraction(
147
+ "populate_user_directory_temp_build", _make_staging_area
148
+ )
149
+ await self.db_pool.simple_insert(
150
+ TEMP_TABLE + "_position", {"position": new_pos}
151
+ )
152
+
153
+ await self.db_pool.updates._end_background_update(
154
+ "populate_user_directory_createtables"
155
+ )
156
+ return 1
157
+
158
+ async def _populate_user_directory_cleanup(
159
+ self,
160
+ progress: JsonDict,
161
+ batch_size: int,
162
+ ) -> int:
163
+ """
164
+ Update the user directory stream position, then clean up the old tables.
165
+ """
166
+ position = await self.db_pool.simple_select_one_onecol(
167
+ TEMP_TABLE + "_position", {}, "position"
168
+ )
169
+ await self.update_user_directory_stream_pos(position)
170
+
171
+ def _delete_staging_area(txn: LoggingTransaction) -> None:
172
+ txn.execute("DROP TABLE IF EXISTS " + TEMP_TABLE + "_rooms")
173
+ txn.execute("DROP TABLE IF EXISTS " + TEMP_TABLE + "_users")
174
+ txn.execute("DROP TABLE IF EXISTS " + TEMP_TABLE + "_position")
175
+
176
+ await self.db_pool.runInteraction(
177
+ "populate_user_directory_cleanup", _delete_staging_area
178
+ )
179
+
180
+ await self.db_pool.updates._end_background_update(
181
+ "populate_user_directory_cleanup"
182
+ )
183
+ return 1
184
+
185
+ async def _populate_user_directory_process_rooms(
186
+ self, progress: JsonDict, batch_size: int
187
+ ) -> int:
188
+ """
189
+ Rescan the state of all rooms so we can track
190
+
191
+ - who's in a public room;
192
+ - which local users share a private room with other users (local
193
+ and remote); and
194
+ - who should be in the user_directory.
195
+
196
+ Args:
197
+ progress
198
+ batch_size: Maximum number of state events to process per cycle.
199
+
200
+ Returns:
201
+ number of events processed.
202
+ """
203
+ # If we don't have progress filed, delete everything.
204
+ if not progress:
205
+ await self.delete_all_from_user_dir()
206
+
207
+ def _get_next_batch(
208
+ txn: LoggingTransaction,
209
+ ) -> Optional[Sequence[tuple[str, int]]]:
210
+ # Only fetch 250 rooms, so we don't fetch too many at once, even
211
+ # if those 250 rooms have less than batch_size state events.
212
+ sql = """
213
+ SELECT room_id, events FROM %s
214
+ ORDER BY events DESC
215
+ LIMIT 250
216
+ """ % (TEMP_TABLE + "_rooms",)
217
+ txn.execute(sql)
218
+ rooms_to_work_on = cast(list[tuple[str, int]], txn.fetchall())
219
+
220
+ if not rooms_to_work_on:
221
+ return None
222
+
223
+ if "remaining" not in progress:
224
+ # Get how many are left to process, so we can give status on how
225
+ # far we are in processing
226
+ txn.execute("SELECT COUNT(*) FROM " + TEMP_TABLE + "_rooms")
227
+ result = txn.fetchone()
228
+ assert result is not None
229
+ progress["remaining"] = result[0]
230
+
231
+ return rooms_to_work_on
232
+
233
+ rooms_to_work_on = await self.db_pool.runInteraction(
234
+ "populate_user_directory_temp_read", _get_next_batch
235
+ )
236
+
237
+ # No more rooms -- complete the transaction.
238
+ if not rooms_to_work_on:
239
+ await self.db_pool.updates._end_background_update(
240
+ "populate_user_directory_process_rooms"
241
+ )
242
+ return 1
243
+
244
+ logger.debug(
245
+ "Processing the next %d rooms of %d remaining",
246
+ len(rooms_to_work_on),
247
+ progress["remaining"],
248
+ )
249
+
250
+ processed_event_count = 0
251
+
252
+ for room_id, event_count in rooms_to_work_on:
253
+ is_in_room = await self.is_host_joined(room_id, self.server_name) # type: ignore[attr-defined]
254
+
255
+ if is_in_room:
256
+ users_with_profile = await self.get_users_in_room_with_profiles(room_id) # type: ignore[attr-defined]
257
+ # Throw away users excluded from the directory.
258
+ users_with_profile = {
259
+ user_id: profile
260
+ for user_id, profile in users_with_profile.items()
261
+ if not self.hs.is_mine_id(user_id)
262
+ or await self.should_include_local_user_in_dir(user_id)
263
+ }
264
+
265
+ # Upsert a user_directory record for each remote user we see.
266
+ for user_id, profile in users_with_profile.items():
267
+ # Local users are processed separately in
268
+ # `_populate_user_directory_users`; there we can read from
269
+ # the `profiles` table to ensure we don't leak their per-room
270
+ # profiles. It also means we write local users to this table
271
+ # exactly once, rather than once for every room they're in.
272
+ if self.hs.is_mine_id(user_id):
273
+ continue
274
+ # TODO `users_with_profile` above reads from the `user_directory`
275
+ # table, meaning that `profile` is bespoke to this room.
276
+ # and this leaks remote users' per-room profiles to the user directory.
277
+ await self.update_profile_in_user_dir(
278
+ user_id, profile.display_name, profile.avatar_url
279
+ )
280
+
281
+ # Now update the room sharing tables to include this room.
282
+ is_public = await self.is_room_world_readable_or_publicly_joinable(
283
+ room_id
284
+ )
285
+ if is_public:
286
+ if users_with_profile:
287
+ await self.add_users_in_public_rooms(
288
+ room_id, users_with_profile.keys()
289
+ )
290
+ else:
291
+ to_insert = set()
292
+ for user_id in users_with_profile:
293
+ # We want the set of pairs (L, M) where L and M are
294
+ # in `users_with_profile` and L is local.
295
+ # Do so by looking for the local user L first.
296
+ if not self.hs.is_mine_id(user_id):
297
+ continue
298
+
299
+ for other_user_id in users_with_profile:
300
+ if user_id == other_user_id:
301
+ continue
302
+
303
+ user_set = (user_id, other_user_id)
304
+ to_insert.add(user_set)
305
+
306
+ # If it gets too big, stop and write to the database
307
+ # to prevent storing too much in RAM.
308
+ if len(to_insert) >= self.SHARE_PRIVATE_WORKING_SET:
309
+ await self.add_users_who_share_private_room(
310
+ room_id, to_insert
311
+ )
312
+ to_insert.clear()
313
+
314
+ if to_insert:
315
+ await self.add_users_who_share_private_room(room_id, to_insert)
316
+ to_insert.clear()
317
+
318
+ # We've finished a room. Delete it from the table.
319
+ await self.db_pool.simple_delete_one(
320
+ TEMP_TABLE + "_rooms", {"room_id": room_id}
321
+ )
322
+ # Update the remaining counter.
323
+ progress["remaining"] -= 1
324
+ await self.db_pool.runInteraction(
325
+ "populate_user_directory",
326
+ self.db_pool.updates._background_update_progress_txn,
327
+ "populate_user_directory_process_rooms",
328
+ progress,
329
+ )
330
+
331
+ processed_event_count += event_count
332
+
333
+ if processed_event_count > batch_size:
334
+ # Don't process any more rooms, we've hit our batch size.
335
+ break
336
+
337
+ await self.db_pool.runInteraction(
338
+ "populate_user_directory",
339
+ self.db_pool.updates._background_update_progress_txn,
340
+ "populate_user_directory_process_rooms",
341
+ progress,
342
+ )
343
+
344
+ return processed_event_count
345
+
346
+ async def _populate_user_directory_process_users(
347
+ self, progress: JsonDict, batch_size: int
348
+ ) -> int:
349
+ """
350
+ Add all local users to the user directory.
351
+ """
352
+
353
+ def _populate_user_directory_process_users_txn(
354
+ txn: LoggingTransaction,
355
+ ) -> Optional[int]:
356
+ # Note: we use an ORDER BY in the SELECT to force usage of an
357
+ # index. Otherwise, postgres does a sequential scan that is
358
+ # surprisingly slow (I think due to the fact it will read/skip
359
+ # over lots of already deleted rows).
360
+ sql = f"""
361
+ DELETE FROM {TEMP_TABLE + "_users"}
362
+ WHERE user_id IN (
363
+ SELECT user_id FROM {TEMP_TABLE + "_users"} ORDER BY user_id LIMIT ?
364
+ )
365
+ RETURNING user_id
366
+ """
367
+ txn.execute(sql, (batch_size,))
368
+ user_result = cast(list[tuple[str]], txn.fetchall())
369
+
370
+ if not user_result:
371
+ return None
372
+
373
+ users_to_work_on = [x[0] for x in user_result]
374
+
375
+ if "remaining" not in progress:
376
+ # Get how many are left to process, so we can give status on how
377
+ # far we are in processing
378
+ sql = "SELECT COUNT(*) FROM " + TEMP_TABLE + "_users"
379
+ txn.execute(sql)
380
+ count_result = txn.fetchone()
381
+ assert count_result is not None
382
+ progress["remaining"] = count_result[0]
383
+
384
+ if not users_to_work_on:
385
+ return None
386
+
387
+ logger.debug(
388
+ "Processing the next %d users of %d remaining",
389
+ len(users_to_work_on),
390
+ progress["remaining"],
391
+ )
392
+
393
+ # First filter down to users we want to insert into the user directory.
394
+ users_to_insert = self._filter_local_users_for_dir_txn(
395
+ txn, users_to_work_on
396
+ )
397
+
398
+ # Next fetch their profiles. Note that not all users have profiles.
399
+ profile_rows = cast(
400
+ list[tuple[str, Optional[str], Optional[str]]],
401
+ self.db_pool.simple_select_many_txn(
402
+ txn,
403
+ table="profiles",
404
+ column="full_user_id",
405
+ iterable=list(users_to_insert),
406
+ retcols=(
407
+ "full_user_id",
408
+ "displayname",
409
+ "avatar_url",
410
+ ),
411
+ keyvalues={},
412
+ ),
413
+ )
414
+ profiles = {
415
+ full_user_id: _UserDirProfile(full_user_id, displayname, avatar_url)
416
+ for full_user_id, displayname, avatar_url in profile_rows
417
+ }
418
+
419
+ profiles_to_insert = [
420
+ profiles.get(user_id) or _UserDirProfile(user_id)
421
+ for user_id in users_to_insert
422
+ ]
423
+
424
+ # Actually insert the users with their profiles into the directory.
425
+ self._update_profiles_in_user_dir_txn(txn, profiles_to_insert)
426
+
427
+ # Update the remaining counter.
428
+ progress["remaining"] -= len(users_to_work_on)
429
+ self.db_pool.updates._background_update_progress_txn(
430
+ txn, "populate_user_directory_process_users", progress
431
+ )
432
+ return len(users_to_work_on)
433
+
434
+ processed_count = await self.db_pool.runInteraction(
435
+ "populate_user_directory_temp", _populate_user_directory_process_users_txn
436
+ )
437
+
438
+ # No more users -- complete the transaction.
439
+ if not processed_count:
440
+ await self.db_pool.updates._end_background_update(
441
+ "populate_user_directory_process_users"
442
+ )
443
+ return 1
444
+
445
+ return processed_count
446
+
447
+ async def should_include_local_user_in_dir(self, user: str) -> bool:
448
+ """Certain classes of local user are omitted from the user directory.
449
+ Is this user one of them?
450
+ """
451
+ # We're opting to exclude the appservice sender (user defined by the
452
+ # `sender_localpart` in the appservice registration) even though
453
+ # technically it could be DM-able. In the future, this could potentially
454
+ # be configurable per-appservice whether the appservice sender can be
455
+ # contacted.
456
+ if self.get_app_service_by_user_id(user) is not None: # type: ignore[attr-defined]
457
+ return False
458
+
459
+ # We're opting to exclude appservice users (anyone matching the user
460
+ # namespace regex in the appservice registration) even though technically
461
+ # they could be DM-able. In the future, this could potentially
462
+ # be configurable per-appservice whether the appservice users can be
463
+ # contacted.
464
+ if self.get_if_app_services_interested_in_user(user): # type: ignore[attr-defined]
465
+ # TODO we might want to make this configurable for each app service
466
+ return False
467
+
468
+ # Support users are for diagnostics and should not appear in the user directory.
469
+ if await self.is_support_user(user): # type: ignore[attr-defined]
470
+ return False
471
+
472
+ # Deactivated users aren't contactable, so should not appear in the user directory.
473
+ try:
474
+ if await self.get_user_deactivated_status(user): # type: ignore[attr-defined]
475
+ return False
476
+ except StoreError:
477
+ # No such user in the users table. No need to do this when calling
478
+ # is_support_user---that returns False if the user is missing.
479
+ return False
480
+
481
+ return True
482
+
483
+ def _filter_local_users_for_dir_txn(
484
+ self, txn: LoggingTransaction, users: Collection[str]
485
+ ) -> Collection[str]:
486
+ """A batched version of `should_include_local_user_in_dir`"""
487
+ users = [
488
+ user
489
+ for user in users
490
+ if self.get_app_service_by_user_id(user) is None # type: ignore[attr-defined]
491
+ and not self.get_if_app_services_interested_in_user(user) # type: ignore[attr-defined]
492
+ ]
493
+
494
+ rows = cast(
495
+ list[tuple[str, Optional[str]]],
496
+ self.db_pool.simple_select_many_txn(
497
+ txn,
498
+ table="users",
499
+ column="name",
500
+ iterable=users,
501
+ keyvalues={
502
+ "deactivated": 0,
503
+ },
504
+ retcols=("name", "user_type"),
505
+ ),
506
+ )
507
+
508
+ return [name for name, user_type in rows if user_type != UserTypes.SUPPORT]
509
+
510
+ async def is_room_world_readable_or_publicly_joinable(self, room_id: str) -> bool:
511
+ """Check if the room is either world_readable or publically joinable"""
512
+
513
+ # Create a state filter that only queries join and history state event
514
+ types_to_filter = (
515
+ (EventTypes.JoinRules, ""),
516
+ (EventTypes.RoomHistoryVisibility, ""),
517
+ )
518
+
519
+ # Getting the partial state is fine, as we're not looking at membership
520
+ # events.
521
+ current_state_ids = await self.get_partial_filtered_current_state_ids( # type: ignore[attr-defined]
522
+ room_id, StateFilter.from_types(types_to_filter)
523
+ )
524
+
525
+ join_rules_id = current_state_ids.get((EventTypes.JoinRules, ""))
526
+ if join_rules_id:
527
+ join_rule_ev = await self.get_event(join_rules_id, allow_none=True) # type: ignore[attr-defined]
528
+ if join_rule_ev:
529
+ if join_rule_ev.content.get("join_rule") == JoinRules.PUBLIC:
530
+ return True
531
+
532
+ hist_vis_id = current_state_ids.get((EventTypes.RoomHistoryVisibility, ""))
533
+ if hist_vis_id:
534
+ hist_vis_ev = await self.get_event(hist_vis_id, allow_none=True) # type: ignore[attr-defined]
535
+ if hist_vis_ev:
536
+ if (
537
+ hist_vis_ev.content.get("history_visibility")
538
+ == HistoryVisibility.WORLD_READABLE
539
+ ):
540
+ return True
541
+
542
+ return False
543
+
544
+ async def set_remote_user_profile_in_user_dir_stale(
545
+ self, user_id: str, next_try_at_ms: int, retry_counter: int
546
+ ) -> None:
547
+ """
548
+ Marks a remote user as having a possibly-stale user directory profile.
549
+
550
+ Args:
551
+ user_id: the remote user who may have a stale profile on this server.
552
+ next_try_at_ms: timestamp in ms after which the user directory profile can be
553
+ refreshed.
554
+ retry_counter: number of failures in refreshing the profile so far. Used for
555
+ exponential backoff calculations.
556
+ """
557
+ assert not self.hs.is_mine_id(user_id), (
558
+ "Can't mark a local user as a stale remote user."
559
+ )
560
+
561
+ server_name = UserID.from_string(user_id).domain
562
+
563
+ await self.db_pool.simple_upsert(
564
+ table="user_directory_stale_remote_users",
565
+ keyvalues={"user_id": user_id},
566
+ values={
567
+ "next_try_at_ts": next_try_at_ms,
568
+ "retry_counter": retry_counter,
569
+ "user_server_name": server_name,
570
+ },
571
+ desc="set_remote_user_profile_in_user_dir_stale",
572
+ )
573
+
574
+ async def clear_remote_user_profile_in_user_dir_stale(self, user_id: str) -> None:
575
+ """
576
+ Marks a remote user as no longer having a possibly-stale user directory profile.
577
+
578
+ Args:
579
+ user_id: the remote user who no longer has a stale profile on this server.
580
+ """
581
+ await self.db_pool.simple_delete(
582
+ table="user_directory_stale_remote_users",
583
+ keyvalues={"user_id": user_id},
584
+ desc="clear_remote_user_profile_in_user_dir_stale",
585
+ )
586
+
587
+ async def get_remote_servers_with_profiles_to_refresh(
588
+ self, now_ts: int, limit: int
589
+ ) -> list[str]:
590
+ """
591
+ Get a list of up to `limit` server names which have users whose
592
+ locally-cached profiles we believe to be stale
593
+ and are refreshable given the current time `now_ts` in milliseconds.
594
+ """
595
+
596
+ def _get_remote_servers_with_refreshable_profiles_txn(
597
+ txn: LoggingTransaction,
598
+ ) -> list[str]:
599
+ sql = """
600
+ SELECT user_server_name
601
+ FROM user_directory_stale_remote_users
602
+ WHERE next_try_at_ts < ?
603
+ GROUP BY user_server_name
604
+ ORDER BY MIN(next_try_at_ts), user_server_name
605
+ LIMIT ?
606
+ """
607
+ txn.execute(sql, (now_ts, limit))
608
+ return [row[0] for row in txn]
609
+
610
+ return await self.db_pool.runInteraction(
611
+ "get_remote_servers_with_profiles_to_refresh",
612
+ _get_remote_servers_with_refreshable_profiles_txn,
613
+ )
614
+
615
+ async def get_remote_users_to_refresh_on_server(
616
+ self, server_name: str, now_ts: int, limit: int
617
+ ) -> list[tuple[str, int, int]]:
618
+ """
619
+ Get a list of up to `limit` user IDs from the server `server_name`
620
+ whose locally-cached profiles we believe to be stale
621
+ and are refreshable given the current time `now_ts` in milliseconds.
622
+
623
+ Returns:
624
+ tuple of:
625
+ - User ID
626
+ - Retry counter (number of failures so far)
627
+ - Time the retry is scheduled for, in milliseconds
628
+ """
629
+
630
+ def _get_remote_users_to_refresh_on_server_txn(
631
+ txn: LoggingTransaction,
632
+ ) -> list[tuple[str, int, int]]:
633
+ sql = """
634
+ SELECT user_id, retry_counter, next_try_at_ts
635
+ FROM user_directory_stale_remote_users
636
+ WHERE user_server_name = ? AND next_try_at_ts < ?
637
+ ORDER BY next_try_at_ts
638
+ LIMIT ?
639
+ """
640
+ txn.execute(sql, (server_name, now_ts, limit))
641
+ return cast(list[tuple[str, int, int]], txn.fetchall())
642
+
643
+ return await self.db_pool.runInteraction(
644
+ "get_remote_users_to_refresh_on_server",
645
+ _get_remote_users_to_refresh_on_server_txn,
646
+ )
647
+
648
+ async def update_profile_in_user_dir(
649
+ self, user_id: str, display_name: Optional[str], avatar_url: Optional[str]
650
+ ) -> None:
651
+ """
652
+ Update or add a user's profile in the user directory.
653
+ If the user is remote, the profile will be marked as not stale.
654
+ """
655
+ await self.db_pool.runInteraction(
656
+ "update_profiles_in_user_dir",
657
+ self._update_profiles_in_user_dir_txn,
658
+ [_UserDirProfile(user_id, display_name, avatar_url)],
659
+ )
660
+
661
+ def _update_profiles_in_user_dir_txn(
662
+ self,
663
+ txn: LoggingTransaction,
664
+ profiles: Sequence[_UserDirProfile],
665
+ ) -> None:
666
+ self.db_pool.simple_upsert_many_txn(
667
+ txn,
668
+ table="user_directory",
669
+ key_names=("user_id",),
670
+ key_values=[(p.user_id,) for p in profiles],
671
+ value_names=("display_name", "avatar_url"),
672
+ value_values=[
673
+ (
674
+ p.display_name,
675
+ p.avatar_url,
676
+ )
677
+ for p in profiles
678
+ ],
679
+ )
680
+
681
+ # Remote users: Make sure the profile is not marked as stale anymore.
682
+ remote_users = [
683
+ p.user_id for p in profiles if not self.hs.is_mine_id(p.user_id)
684
+ ]
685
+ if remote_users:
686
+ self.db_pool.simple_delete_many_txn(
687
+ txn,
688
+ table="user_directory_stale_remote_users",
689
+ column="user_id",
690
+ values=remote_users,
691
+ keyvalues={},
692
+ )
693
+
694
+ if isinstance(self.database_engine, PostgresEngine):
695
+ # We weight the localpart most highly, then display name and finally
696
+ # server name
697
+ template = """
698
+ (
699
+ %s,
700
+ setweight(to_tsvector('simple', %s), 'A')
701
+ || setweight(to_tsvector('simple', %s), 'D')
702
+ || setweight(to_tsvector('simple', COALESCE(%s, '')), 'B')
703
+ )
704
+ """
705
+
706
+ sql = """
707
+ INSERT INTO user_directory_search(user_id, vector)
708
+ VALUES ? ON CONFLICT (user_id) DO UPDATE SET vector=EXCLUDED.vector
709
+ """
710
+ txn.execute_values(
711
+ sql,
712
+ [
713
+ (
714
+ p.user_id,
715
+ get_localpart_from_id(p.user_id),
716
+ get_domain_from_id(p.user_id),
717
+ (
718
+ _filter_text_for_index(p.display_name)
719
+ if p.display_name
720
+ else None
721
+ ),
722
+ )
723
+ for p in profiles
724
+ ],
725
+ template=template,
726
+ fetch=False,
727
+ )
728
+ elif isinstance(self.database_engine, Sqlite3Engine):
729
+ values = []
730
+ for p in profiles:
731
+ if p.display_name is not None:
732
+ index_display_name = _filter_text_for_index(p.display_name)
733
+ value = f"{p.user_id} {index_display_name}"
734
+ else:
735
+ value = p.user_id
736
+
737
+ values.append((value,))
738
+
739
+ self.db_pool.simple_upsert_many_txn(
740
+ txn,
741
+ table="user_directory_search",
742
+ key_names=("user_id",),
743
+ key_values=[(p.user_id,) for p in profiles],
744
+ value_names=("value",),
745
+ value_values=values,
746
+ )
747
+ else:
748
+ # This should be unreachable.
749
+ raise Exception("Unrecognized database engine")
750
+
751
+ async def add_users_who_share_private_room(
752
+ self, room_id: str, user_id_tuples: Iterable[tuple[str, str]]
753
+ ) -> None:
754
+ """Insert entries into the users_who_share_private_rooms table. The first
755
+ user should be a local user.
756
+
757
+ Args:
758
+ room_id
759
+ user_id_tuples: iterable of 2-tuple of user IDs.
760
+ """
761
+
762
+ await self.db_pool.simple_upsert_many(
763
+ table="users_who_share_private_rooms",
764
+ key_names=["user_id", "other_user_id", "room_id"],
765
+ key_values=[
766
+ (user_id, other_user_id, room_id)
767
+ for user_id, other_user_id in user_id_tuples
768
+ ],
769
+ value_names=(),
770
+ value_values=(),
771
+ desc="add_users_who_share_room",
772
+ )
773
+
774
+ async def add_users_in_public_rooms(
775
+ self, room_id: str, user_ids: Iterable[str]
776
+ ) -> None:
777
+ """Insert entries into the users_in_public_rooms table.
778
+
779
+ Args:
780
+ room_id
781
+ user_ids
782
+ """
783
+
784
+ await self.db_pool.simple_upsert_many(
785
+ table="users_in_public_rooms",
786
+ key_names=["user_id", "room_id"],
787
+ key_values=[(user_id, room_id) for user_id in user_ids],
788
+ value_names=(),
789
+ value_values=(),
790
+ desc="add_users_in_public_rooms",
791
+ )
792
+
793
+ async def delete_all_from_user_dir(self) -> None:
794
+ """Delete the entire user directory"""
795
+
796
+ def _delete_all_from_user_dir_txn(txn: LoggingTransaction) -> None:
797
+ # SQLite doesn't support TRUNCATE.
798
+ # On Postgres, DELETE FROM does a table scan but TRUNCATE is more efficient.
799
+ truncate = (
800
+ "DELETE FROM"
801
+ if isinstance(self.database_engine, Sqlite3Engine)
802
+ else "TRUNCATE"
803
+ )
804
+ txn.execute(f"{truncate} user_directory")
805
+ txn.execute(f"{truncate} user_directory_search")
806
+ txn.execute(f"{truncate} users_in_public_rooms")
807
+ txn.execute(f"{truncate} users_who_share_private_rooms")
808
+
809
+ await self.db_pool.runInteraction(
810
+ "delete_all_from_user_dir", _delete_all_from_user_dir_txn
811
+ )
812
+
813
+ async def _get_user_in_directory(
814
+ self, user_id: str
815
+ ) -> Optional[tuple[Optional[str], Optional[str]]]:
816
+ """
817
+ Fetch the user information in the user directory.
818
+
819
+ Returns:
820
+ None if the user is unknown, otherwise a tuple of display name and
821
+ avatar URL (both of which may be None).
822
+ """
823
+ return cast(
824
+ Optional[tuple[Optional[str], Optional[str]]],
825
+ await self.db_pool.simple_select_one(
826
+ table="user_directory",
827
+ keyvalues={"user_id": user_id},
828
+ retcols=("display_name", "avatar_url"),
829
+ allow_none=True,
830
+ desc="get_user_in_directory",
831
+ ),
832
+ )
833
+
834
+ async def update_user_directory_stream_pos(self, stream_id: Optional[int]) -> None:
835
+ await self.db_pool.simple_update_one(
836
+ table="user_directory_stream_pos",
837
+ keyvalues={},
838
+ updatevalues={"stream_id": stream_id},
839
+ desc="update_user_directory_stream_pos",
840
+ )
841
+
842
+
843
+ class SearchResult(TypedDict):
844
+ limited: bool
845
+ results: list[UserProfile]
846
+
847
+
848
+ class UserDirectoryStore(UserDirectoryBackgroundUpdateStore):
849
+ # How many records do we calculate before sending it to
850
+ # add_users_who_share_private_rooms?
851
+ SHARE_PRIVATE_WORKING_SET = 500
852
+
853
+ def __init__(
854
+ self,
855
+ database: DatabasePool,
856
+ db_conn: LoggingDatabaseConnection,
857
+ hs: "HomeServer",
858
+ ) -> None:
859
+ super().__init__(database, db_conn, hs)
860
+
861
+ self._prefer_local_users_in_search = (
862
+ hs.config.userdirectory.user_directory_search_prefer_local_users
863
+ )
864
+ self._server_name = hs.config.server.server_name
865
+
866
+ async def remove_from_user_dir(self, user_id: str) -> None:
867
+ def _remove_from_user_dir_txn(txn: LoggingTransaction) -> None:
868
+ self.db_pool.simple_delete_txn(
869
+ txn, table="user_directory", keyvalues={"user_id": user_id}
870
+ )
871
+ self.db_pool.simple_delete_txn(
872
+ txn, table="user_directory_search", keyvalues={"user_id": user_id}
873
+ )
874
+ self.db_pool.simple_delete_txn(
875
+ txn, table="users_in_public_rooms", keyvalues={"user_id": user_id}
876
+ )
877
+ self.db_pool.simple_delete_txn(
878
+ txn,
879
+ table="users_who_share_private_rooms",
880
+ keyvalues={"user_id": user_id},
881
+ )
882
+ self.db_pool.simple_delete_txn(
883
+ txn,
884
+ table="users_who_share_private_rooms",
885
+ keyvalues={"other_user_id": user_id},
886
+ )
887
+
888
+ await self.db_pool.runInteraction(
889
+ "remove_from_user_dir", _remove_from_user_dir_txn
890
+ )
891
+
892
+ async def get_users_in_dir_due_to_room(self, room_id: str) -> set[str]:
893
+ """Get all user_ids that are in the room directory because they're
894
+ in the given room_id
895
+ """
896
+ user_ids_share_pub = await self.db_pool.simple_select_onecol(
897
+ table="users_in_public_rooms",
898
+ keyvalues={"room_id": room_id},
899
+ retcol="user_id",
900
+ desc="get_users_in_dir_due_to_room",
901
+ )
902
+
903
+ user_ids_share_priv = await self.db_pool.simple_select_onecol(
904
+ table="users_who_share_private_rooms",
905
+ keyvalues={"room_id": room_id},
906
+ retcol="other_user_id",
907
+ desc="get_users_in_dir_due_to_room",
908
+ )
909
+
910
+ user_ids = set(user_ids_share_pub)
911
+ user_ids.update(user_ids_share_priv)
912
+
913
+ return user_ids
914
+
915
+ async def remove_user_who_share_room(self, user_id: str, room_id: str) -> None:
916
+ """
917
+ Deletes entries in the users_who_share_*_rooms table. The first
918
+ user should be a local user.
919
+
920
+ Args:
921
+ user_id
922
+ room_id
923
+ """
924
+
925
+ def _remove_user_who_share_room_txn(txn: LoggingTransaction) -> None:
926
+ self.db_pool.simple_delete_txn(
927
+ txn,
928
+ table="users_who_share_private_rooms",
929
+ keyvalues={"user_id": user_id, "room_id": room_id},
930
+ )
931
+ self.db_pool.simple_delete_txn(
932
+ txn,
933
+ table="users_who_share_private_rooms",
934
+ keyvalues={"other_user_id": user_id, "room_id": room_id},
935
+ )
936
+ self.db_pool.simple_delete_txn(
937
+ txn,
938
+ table="users_in_public_rooms",
939
+ keyvalues={"user_id": user_id, "room_id": room_id},
940
+ )
941
+
942
+ await self.db_pool.runInteraction(
943
+ "remove_user_who_share_room", _remove_user_who_share_room_txn
944
+ )
945
+
946
+ async def get_user_dir_rooms_user_is_in(self, user_id: str) -> list[str]:
947
+ """
948
+ Returns the rooms that a user is in.
949
+
950
+ Args:
951
+ user_id: Must be a local user
952
+
953
+ Returns:
954
+ List of room IDs
955
+ """
956
+ rows = await self.db_pool.simple_select_onecol(
957
+ table="users_who_share_private_rooms",
958
+ keyvalues={"user_id": user_id},
959
+ retcol="room_id",
960
+ desc="get_rooms_user_is_in",
961
+ )
962
+
963
+ pub_rows = await self.db_pool.simple_select_onecol(
964
+ table="users_in_public_rooms",
965
+ keyvalues={"user_id": user_id},
966
+ retcol="room_id",
967
+ desc="get_rooms_user_is_in",
968
+ )
969
+
970
+ users = set(pub_rows)
971
+ users.update(rows)
972
+ return list(users)
973
+
974
+ async def get_user_directory_stream_pos(self) -> Optional[int]:
975
+ """
976
+ Get the stream ID of the user directory stream.
977
+
978
+ Returns:
979
+ The stream token or None if the initial background update hasn't happened yet.
980
+ """
981
+ return await self.db_pool.simple_select_one_onecol(
982
+ table="user_directory_stream_pos",
983
+ keyvalues={},
984
+ retcol="stream_id",
985
+ desc="get_user_directory_stream_pos",
986
+ )
987
+
988
+ async def search_user_dir(
989
+ self,
990
+ user_id: str,
991
+ search_term: str,
992
+ limit: int,
993
+ show_locked_users: bool = False,
994
+ ) -> SearchResult:
995
+ """Searches for users in directory
996
+
997
+ Returns:
998
+ dict of the form::
999
+
1000
+ {
1001
+ "limited": <bool>, # whether there were more results or not
1002
+ "results": [ # Ordered by best match first
1003
+ {
1004
+ "user_id": <user_id>,
1005
+ "display_name": <display_name>,
1006
+ "avatar_url": <avatar_url>
1007
+ }
1008
+ ]
1009
+ }
1010
+ """
1011
+
1012
+ join_args: tuple[str, ...] = (user_id,)
1013
+
1014
+ if self.hs.config.userdirectory.user_directory_search_all_users:
1015
+ where_clause = "user_id != ?"
1016
+ else:
1017
+ where_clause = """
1018
+ (
1019
+ EXISTS (select 1 from users_in_public_rooms WHERE user_id = t.user_id)
1020
+ OR EXISTS (
1021
+ SELECT 1 FROM users_who_share_private_rooms
1022
+ WHERE user_id = ? AND other_user_id = t.user_id
1023
+ )
1024
+ )
1025
+ """
1026
+
1027
+ if not show_locked_users:
1028
+ where_clause += " AND (u.locked IS NULL OR u.locked = FALSE)"
1029
+
1030
+ # Adjust the JOIN type based on the exclude_remote_users flag (the users
1031
+ # table only contains local users so an inner join is a good way to
1032
+ # to exclude remote users)
1033
+ if self.hs.config.userdirectory.user_directory_exclude_remote_users:
1034
+ join_type = "JOIN"
1035
+ else:
1036
+ join_type = "LEFT JOIN"
1037
+
1038
+ # We allow manipulating the ranking algorithm by injecting statements
1039
+ # based on config options.
1040
+ additional_ordering_statements = []
1041
+ ordering_arguments: tuple[str, ...] = ()
1042
+
1043
+ if isinstance(self.database_engine, PostgresEngine):
1044
+ full_query, exact_query, prefix_query = _parse_query_postgres(search_term)
1045
+
1046
+ # If enabled, this config option will rank local users higher than those on
1047
+ # remote instances.
1048
+ if self._prefer_local_users_in_search:
1049
+ # This statement checks whether a given user's user ID contains a server name
1050
+ # that matches the local server
1051
+ statement = "* (CASE WHEN user_id LIKE ? THEN 2.0 ELSE 1.0 END)"
1052
+ additional_ordering_statements.append(statement)
1053
+
1054
+ ordering_arguments += ("%:" + self._server_name,)
1055
+
1056
+ # We order by rank and then if they have profile info
1057
+ # The ranking algorithm is hand tweaked for "best" results. Broadly
1058
+ # the idea is we give a higher weight to exact matches.
1059
+ # The array of numbers are the weights for the various part of the
1060
+ # search: (domain, _, display name, localpart)
1061
+ sql = """
1062
+ WITH matching_users AS (
1063
+ SELECT user_id, vector FROM user_directory_search WHERE vector @@ to_tsquery('simple', ?)
1064
+ LIMIT 10000
1065
+ )
1066
+ SELECT d.user_id AS user_id, display_name, avatar_url
1067
+ FROM matching_users as t
1068
+ INNER JOIN user_directory AS d USING (user_id)
1069
+ %(join_type)s users AS u ON t.user_id = u.name
1070
+ WHERE
1071
+ %(where_clause)s
1072
+ ORDER BY
1073
+ (CASE WHEN d.user_id IS NOT NULL THEN 4.0 ELSE 1.0 END)
1074
+ * (CASE WHEN display_name IS NOT NULL THEN 1.2 ELSE 1.0 END)
1075
+ * (CASE WHEN avatar_url IS NOT NULL THEN 1.2 ELSE 1.0 END)
1076
+ * (
1077
+ 3 * ts_rank_cd(
1078
+ '{0.1, 0.1, 0.9, 1.0}',
1079
+ vector,
1080
+ to_tsquery('simple', ?),
1081
+ 8
1082
+ )
1083
+ + ts_rank_cd(
1084
+ '{0.1, 0.1, 0.9, 1.0}',
1085
+ vector,
1086
+ to_tsquery('simple', ?),
1087
+ 8
1088
+ )
1089
+ )
1090
+ %(order_case_statements)s
1091
+ DESC,
1092
+ display_name IS NULL,
1093
+ avatar_url IS NULL
1094
+ LIMIT ?
1095
+ """ % {
1096
+ "where_clause": where_clause,
1097
+ "order_case_statements": " ".join(additional_ordering_statements),
1098
+ "join_type": join_type,
1099
+ }
1100
+ args = (
1101
+ (full_query,)
1102
+ + join_args
1103
+ + (exact_query, prefix_query)
1104
+ + ordering_arguments
1105
+ + (limit + 1,)
1106
+ )
1107
+ elif isinstance(self.database_engine, Sqlite3Engine):
1108
+ search_query = _parse_query_sqlite(search_term)
1109
+
1110
+ # If enabled, this config option will rank local users higher than those on
1111
+ # remote instances.
1112
+ if self._prefer_local_users_in_search:
1113
+ # This statement checks whether a given user's user ID contains a server name
1114
+ # that matches the local server
1115
+ #
1116
+ # Note that we need to include a comma at the end for valid SQL
1117
+ statement = "user_id LIKE ? DESC,"
1118
+ additional_ordering_statements.append(statement)
1119
+
1120
+ ordering_arguments += ("%:" + self._server_name,)
1121
+
1122
+ sql = """
1123
+ SELECT d.user_id AS user_id, display_name, avatar_url
1124
+ FROM user_directory_search as t
1125
+ INNER JOIN user_directory AS d USING (user_id)
1126
+ %(join_type)s users AS u ON t.user_id = u.name
1127
+ WHERE
1128
+ %(where_clause)s
1129
+ AND value MATCH ?
1130
+ ORDER BY
1131
+ rank(matchinfo(user_directory_search)) DESC,
1132
+ %(order_statements)s
1133
+ display_name IS NULL,
1134
+ avatar_url IS NULL
1135
+ LIMIT ?
1136
+ """ % {
1137
+ "where_clause": where_clause,
1138
+ "order_statements": " ".join(additional_ordering_statements),
1139
+ "join_type": join_type,
1140
+ }
1141
+ args = join_args + (search_query,) + ordering_arguments + (limit + 1,)
1142
+ else:
1143
+ # This should be unreachable.
1144
+ raise Exception("Unrecognized database engine")
1145
+
1146
+ results = cast(
1147
+ list[tuple[str, Optional[str], Optional[str]]],
1148
+ await self.db_pool.execute("search_user_dir", sql, *args),
1149
+ )
1150
+
1151
+ limited = len(results) > limit
1152
+
1153
+ return {
1154
+ "limited": limited,
1155
+ "results": [
1156
+ {"user_id": r[0], "display_name": r[1], "avatar_url": r[2]}
1157
+ for r in results[0:limit]
1158
+ ],
1159
+ }
1160
+
1161
+
1162
+ def _filter_text_for_index(text: str) -> str:
1163
+ """Transforms text before it is inserted into the user directory index, or searched
1164
+ for in the user directory index.
1165
+
1166
+ Note that the user directory search table needs to be rebuilt whenever this function
1167
+ changes.
1168
+ """
1169
+ # Lowercase the text, to make searches case-insensitive.
1170
+ # This is necessary for both PostgreSQL and SQLite. PostgreSQL's
1171
+ # `to_tsquery/to_tsvector` functions don't lowercase non-ASCII characters when using
1172
+ # the "C" collation, while SQLite just doesn't lowercase non-ASCII characters at
1173
+ # all.
1174
+ text = text.lower()
1175
+
1176
+ # Normalize the text. NFKC normalization has two effects:
1177
+ # 1. It canonicalizes the text, ie. maps all visually identical strings to the same
1178
+ # string. For example, ["e", "◌́"] is mapped to ["é"].
1179
+ # 2. It maps strings that are roughly equivalent to the same string.
1180
+ # For example, ["dž"] is mapped to ["d", "ž"], ["①"] to ["1"] and ["i⁹"] to
1181
+ # ["i", "9"].
1182
+ text = unicodedata.normalize("NFKC", text)
1183
+
1184
+ # Note that nothing is done to make searches accent-insensitive.
1185
+ # That could be achieved by converting to NFKD form instead (with combining accents
1186
+ # split out) and filtering out combining accents using `unicodedata.combining(c)`.
1187
+ # The downside of this may be noisier search results, since search terms with
1188
+ # explicit accents will match characters with no accents, or completely different
1189
+ # accents.
1190
+ #
1191
+ # text = unicodedata.normalize("NFKD", text)
1192
+ # text = "".join([c for c in text if not unicodedata.combining(c)])
1193
+
1194
+ return text
1195
+
1196
+
1197
+ def _parse_query_sqlite(search_term: str) -> str:
1198
+ """Takes a plain unicode string from the user and converts it into a form
1199
+ that can be passed to the database.
1200
+ We use this so that we can add prefix matching, which isn't something
1201
+ that is supported by default.
1202
+
1203
+ We specifically add both a prefix and non prefix matching term so that
1204
+ exact matches get ranked higher.
1205
+ """
1206
+ search_term = _filter_text_for_index(search_term)
1207
+
1208
+ # Pull out the individual words, discarding any non-word characters.
1209
+ results = _parse_words(search_term)
1210
+ return " & ".join("(%s* OR %s)" % (result, result) for result in results)
1211
+
1212
+
1213
+ def _parse_query_postgres(search_term: str) -> tuple[str, str, str]:
1214
+ """Takes a plain unicode string from the user and converts it into a form
1215
+ that can be passed to the database.
1216
+ We use this so that we can add prefix matching, which isn't something
1217
+ that is supported by default.
1218
+ """
1219
+ search_term = _filter_text_for_index(search_term)
1220
+
1221
+ escaped_words = []
1222
+ for index, word in enumerate(_parse_words(search_term)):
1223
+ if index >= 10:
1224
+ # We limit how many terms we include, as otherwise it can use
1225
+ # excessive database time if people accidentally search for large
1226
+ # strings.
1227
+ break
1228
+
1229
+ # Postgres tsvector and tsquery quoting rules:
1230
+ # words potentially containing punctuation should be quoted
1231
+ # and then existing quotes and backslashes should be doubled
1232
+ # See: https://www.postgresql.org/docs/current/datatype-textsearch.html#DATATYPE-TSQUERY
1233
+
1234
+ quoted_word = word.replace("'", "''").replace("\\", "\\\\")
1235
+ escaped_words.append(f"'{quoted_word}'")
1236
+
1237
+ both = " & ".join("(%s:* | %s)" % (word, word) for word in escaped_words)
1238
+ exact = " & ".join("%s" % (word,) for word in escaped_words)
1239
+ prefix = " & ".join("%s:*" % (word,) for word in escaped_words)
1240
+
1241
+ return both, exact, prefix
1242
+
1243
+
1244
+ def _parse_words(search_term: str) -> list[str]:
1245
+ """Split the provided search string into a list of its words using ICU.
1246
+
1247
+ Args:
1248
+ search_term: The search string.
1249
+
1250
+ Returns:
1251
+ A list of the words in the search string.
1252
+ """
1253
+ return _parse_words_with_icu(search_term)
1254
+
1255
+
1256
+ def _parse_words_with_icu(search_term: str) -> list[str]:
1257
+ """Break down the provided search string into its individual words using ICU
1258
+ (International Components for Unicode).
1259
+
1260
+ Args:
1261
+ search_term: The search string.
1262
+
1263
+ Returns:
1264
+ A list of the words in the search string.
1265
+ """
1266
+ results = []
1267
+ for part in icu.parse_words(search_term):
1268
+ # We want to make sure that we split on `@` and `:` specifically, as
1269
+ # they occur in user IDs.
1270
+ for result in re.split(r"[@:]+", part):
1271
+ results.append(result.strip())
1272
+
1273
+ # icu will break up words that have punctuation in them, but to handle
1274
+ # cases where user IDs have '-', '.' and '_' in them we want to *not* break
1275
+ # those into words and instead allow the DB to tokenise them how it wants.
1276
+ #
1277
+ # In particular, user-71 in postgres gets tokenised to "user, -71", and this
1278
+ # will not match a query for "user, 71".
1279
+ new_results: list[str] = []
1280
+ i = 0
1281
+ while i < len(results):
1282
+ curr = results[i]
1283
+
1284
+ prev = None
1285
+ next = None
1286
+ if i > 0:
1287
+ prev = results[i - 1]
1288
+ if i + 1 < len(results):
1289
+ next = results[i + 1]
1290
+
1291
+ i += 1
1292
+
1293
+ # libicu considers spaces and punctuation between words as words, but we don't
1294
+ # want to include those in results as they would result in syntax errors in SQL
1295
+ # queries (e.g. "foo bar" would result in the search query including "foo & &
1296
+ # bar").
1297
+ if not curr:
1298
+ continue
1299
+
1300
+ if curr in ["-", ".", "_"]:
1301
+ prefix = ""
1302
+ suffix = ""
1303
+
1304
+ # Check if the next item is a word, and if so use it as the suffix.
1305
+ # We check for if its a word as we don't want to concatenate
1306
+ # multiple punctuation marks.
1307
+ if next is not None and re.match(r"\w", next):
1308
+ suffix = next
1309
+ i += 1 # We're using next, so we skip it in the outer loop.
1310
+ else:
1311
+ # We want to avoid creating terms like "user-", as we should
1312
+ # strip trailing punctuation.
1313
+ continue
1314
+
1315
+ if prev and re.match(r"\w", prev) and new_results:
1316
+ prefix = new_results[-1]
1317
+ new_results.pop()
1318
+
1319
+ # We might not have a prefix here, but that's fine as we want to
1320
+ # ensure that we don't strip preceding punctuation e.g. '-71'
1321
+ # shouldn't be converted to '71'.
1322
+
1323
+ new_results.append(f"{prefix}{curr}{suffix}")
1324
+ continue
1325
+ elif not re.match(r"\w", curr):
1326
+ # Ignore other punctuation
1327
+ continue
1328
+
1329
+ new_results.append(curr)
1330
+
1331
+ return new_results