選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 
 
 

156 行
5.2 KiB

  1. # Copyright 2022 The Matrix.org Foundation C.I.C.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from typing import TYPE_CHECKING, Dict, List, Tuple
  15. from synapse.api.errors import Codes, SynapseError
  16. from synapse.types import JsonDict, UserID
  17. if TYPE_CHECKING:
  18. from synapse.server import HomeServer
  19. class AccountHandler:
  20. def __init__(self, hs: "HomeServer"):
  21. self._main_store = hs.get_datastores().main
  22. self._is_mine = hs.is_mine
  23. self._federation_client = hs.get_federation_client()
  24. self._use_account_validity_in_account_status = (
  25. hs.config.server.use_account_validity_in_account_status
  26. )
  27. self._account_validity_handler = hs.get_account_validity_handler()
  28. async def get_account_statuses(
  29. self,
  30. user_ids: List[str],
  31. allow_remote: bool,
  32. ) -> Tuple[JsonDict, List[str]]:
  33. """Get account statuses for a list of user IDs.
  34. If one or more account(s) belong to remote homeservers, retrieve their status(es)
  35. over federation if allowed.
  36. Args:
  37. user_ids: The list of accounts to retrieve the status of.
  38. allow_remote: Whether to try to retrieve the status of remote accounts, if
  39. any.
  40. Returns:
  41. The account statuses as well as the list of users whose statuses could not be
  42. retrieved.
  43. Raises:
  44. SynapseError if a required parameter is missing or malformed, or if one of
  45. the accounts isn't local to this homeserver and allow_remote is False.
  46. """
  47. statuses = {}
  48. failures = []
  49. remote_users: List[UserID] = []
  50. for raw_user_id in user_ids:
  51. try:
  52. user_id = UserID.from_string(raw_user_id)
  53. except SynapseError:
  54. raise SynapseError(
  55. 400,
  56. f"Not a valid Matrix user ID: {raw_user_id}",
  57. Codes.INVALID_PARAM,
  58. )
  59. if self._is_mine(user_id):
  60. status = await self._get_local_account_status(user_id)
  61. statuses[user_id.to_string()] = status
  62. else:
  63. if not allow_remote:
  64. raise SynapseError(
  65. 400,
  66. f"Not a local user: {raw_user_id}",
  67. Codes.INVALID_PARAM,
  68. )
  69. remote_users.append(user_id)
  70. if allow_remote and len(remote_users) > 0:
  71. remote_statuses, remote_failures = await self._get_remote_account_statuses(
  72. remote_users,
  73. )
  74. statuses.update(remote_statuses)
  75. failures += remote_failures
  76. return statuses, failures
  77. async def _get_local_account_status(self, user_id: UserID) -> JsonDict:
  78. """Retrieve the status of a local account.
  79. Args:
  80. user_id: The account to retrieve the status of.
  81. Returns:
  82. The account's status.
  83. """
  84. status = {"exists": False}
  85. userinfo = await self._main_store.get_user_by_id(user_id.to_string())
  86. if userinfo is not None:
  87. status = {
  88. "exists": True,
  89. "deactivated": userinfo.is_deactivated,
  90. }
  91. if self._use_account_validity_in_account_status:
  92. status[
  93. "org.matrix.expired"
  94. ] = await self._account_validity_handler.is_user_expired(
  95. user_id.to_string()
  96. )
  97. return status
  98. async def _get_remote_account_statuses(
  99. self, remote_users: List[UserID]
  100. ) -> Tuple[JsonDict, List[str]]:
  101. """Send out federation requests to retrieve the statuses of remote accounts.
  102. Args:
  103. remote_users: The accounts to retrieve the statuses of.
  104. Returns:
  105. The statuses of the accounts, and a list of accounts for which no status
  106. could be retrieved.
  107. """
  108. # Group remote users by destination, so we only send one request per remote
  109. # homeserver.
  110. by_destination: Dict[str, List[str]] = {}
  111. for user in remote_users:
  112. if user.domain not in by_destination:
  113. by_destination[user.domain] = []
  114. by_destination[user.domain].append(user.to_string())
  115. # Retrieve the statuses and failures for remote accounts.
  116. final_statuses: JsonDict = {}
  117. final_failures: List[str] = []
  118. for destination, users in by_destination.items():
  119. statuses, failures = await self._federation_client.get_account_status(
  120. destination,
  121. users,
  122. )
  123. final_statuses.update(statuses)
  124. final_failures += failures
  125. return final_statuses, final_failures