__init__.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. # Copyright 2014-2016 OpenMarket Ltd
  2. # Copyright 2018-2019 New Vector Ltd
  3. # Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. import logging
  17. import platform
  18. from http import HTTPStatus
  19. from typing import TYPE_CHECKING, Optional, Tuple
  20. from synapse.api.errors import Codes, NotFoundError, SynapseError
  21. from synapse.http.server import HttpServer, JsonResource
  22. from synapse.http.servlet import RestServlet, parse_json_object_from_request
  23. from synapse.http.site import SynapseRequest
  24. from synapse.rest.admin._base import admin_patterns, assert_requester_is_admin
  25. from synapse.rest.admin.background_updates import (
  26. BackgroundUpdateEnabledRestServlet,
  27. BackgroundUpdateRestServlet,
  28. BackgroundUpdateStartJobRestServlet,
  29. )
  30. from synapse.rest.admin.devices import (
  31. DeleteDevicesRestServlet,
  32. DeviceRestServlet,
  33. DevicesRestServlet,
  34. )
  35. from synapse.rest.admin.event_reports import (
  36. EventReportDetailRestServlet,
  37. EventReportsRestServlet,
  38. )
  39. from synapse.rest.admin.federation import (
  40. DestinationMembershipRestServlet,
  41. DestinationResetConnectionRestServlet,
  42. DestinationRestServlet,
  43. ListDestinationsRestServlet,
  44. )
  45. from synapse.rest.admin.media import ListMediaInRoom, register_servlets_for_media_repo
  46. from synapse.rest.admin.registration_tokens import (
  47. ListRegistrationTokensRestServlet,
  48. NewRegistrationTokenRestServlet,
  49. RegistrationTokenRestServlet,
  50. )
  51. from synapse.rest.admin.rooms import (
  52. BlockRoomRestServlet,
  53. DeleteRoomStatusByDeleteIdRestServlet,
  54. DeleteRoomStatusByRoomIdRestServlet,
  55. ForwardExtremitiesRestServlet,
  56. JoinRoomAliasServlet,
  57. ListRoomRestServlet,
  58. MakeRoomAdminRestServlet,
  59. RoomEventContextServlet,
  60. RoomMembersRestServlet,
  61. RoomRestServlet,
  62. RoomRestV2Servlet,
  63. RoomStateRestServlet,
  64. )
  65. from synapse.rest.admin.server_notice_servlet import SendServerNoticeServlet
  66. from synapse.rest.admin.statistics import UserMediaStatisticsRestServlet
  67. from synapse.rest.admin.username_available import UsernameAvailableRestServlet
  68. from synapse.rest.admin.users import (
  69. AccountDataRestServlet,
  70. AccountValidityRenewServlet,
  71. DeactivateAccountRestServlet,
  72. PushersRestServlet,
  73. RateLimitRestServlet,
  74. ResetPasswordRestServlet,
  75. SearchUsersRestServlet,
  76. ShadowBanRestServlet,
  77. UserAdminServlet,
  78. UserMembershipRestServlet,
  79. UserRegisterServlet,
  80. UserRestServletV2,
  81. UsersRestServletV2,
  82. UserTokenRestServlet,
  83. WhoisRestServlet,
  84. )
  85. from synapse.types import JsonDict, RoomStreamToken
  86. from synapse.util import SYNAPSE_VERSION
  87. if TYPE_CHECKING:
  88. from synapse.server import HomeServer
  89. logger = logging.getLogger(__name__)
  90. class VersionServlet(RestServlet):
  91. PATTERNS = admin_patterns("/server_version$")
  92. def __init__(self, hs: "HomeServer"):
  93. self.res = {
  94. "server_version": SYNAPSE_VERSION,
  95. "python_version": platform.python_version(),
  96. }
  97. def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
  98. return HTTPStatus.OK, self.res
  99. class PurgeHistoryRestServlet(RestServlet):
  100. PATTERNS = admin_patterns(
  101. "/purge_history/(?P<room_id>[^/]*)(/(?P<event_id>[^/]*))?$"
  102. )
  103. def __init__(self, hs: "HomeServer"):
  104. self.pagination_handler = hs.get_pagination_handler()
  105. self.store = hs.get_datastores().main
  106. self.auth = hs.get_auth()
  107. async def on_POST(
  108. self, request: SynapseRequest, room_id: str, event_id: Optional[str]
  109. ) -> Tuple[int, JsonDict]:
  110. await assert_requester_is_admin(self.auth, request)
  111. body = parse_json_object_from_request(request, allow_empty_body=True)
  112. delete_local_events = bool(body.get("delete_local_events", False))
  113. # establish the topological ordering we should keep events from. The
  114. # user can provide an event_id in the URL or the request body, or can
  115. # provide a timestamp in the request body.
  116. if event_id is None:
  117. event_id = body.get("purge_up_to_event_id")
  118. if event_id is not None:
  119. event = await self.store.get_event(event_id)
  120. if event.room_id != room_id:
  121. raise SynapseError(HTTPStatus.BAD_REQUEST, "Event is for wrong room.")
  122. # RoomStreamToken expects [int] not Optional[int]
  123. assert event.internal_metadata.stream_ordering is not None
  124. room_token = RoomStreamToken(
  125. event.depth, event.internal_metadata.stream_ordering
  126. )
  127. token = await room_token.to_string(self.store)
  128. logger.info("[purge] purging up to token %s (event_id %s)", token, event_id)
  129. elif "purge_up_to_ts" in body:
  130. ts = body["purge_up_to_ts"]
  131. if not isinstance(ts, int):
  132. raise SynapseError(
  133. HTTPStatus.BAD_REQUEST,
  134. "purge_up_to_ts must be an int",
  135. errcode=Codes.BAD_JSON,
  136. )
  137. stream_ordering = await self.store.find_first_stream_ordering_after_ts(ts)
  138. r = await self.store.get_room_event_before_stream_ordering(
  139. room_id, stream_ordering
  140. )
  141. if not r:
  142. logger.warning(
  143. "[purge] purging events not possible: No event found "
  144. "(received_ts %i => stream_ordering %i)",
  145. ts,
  146. stream_ordering,
  147. )
  148. raise SynapseError(
  149. HTTPStatus.NOT_FOUND,
  150. "there is no event to be purged",
  151. errcode=Codes.NOT_FOUND,
  152. )
  153. (stream, topo, _event_id) = r
  154. token = "t%d-%d" % (topo, stream)
  155. logger.info(
  156. "[purge] purging up to token %s (received_ts %i => "
  157. "stream_ordering %i)",
  158. token,
  159. ts,
  160. stream_ordering,
  161. )
  162. else:
  163. raise SynapseError(
  164. HTTPStatus.BAD_REQUEST,
  165. "must specify purge_up_to_event_id or purge_up_to_ts",
  166. errcode=Codes.BAD_JSON,
  167. )
  168. purge_id = self.pagination_handler.start_purge_history(
  169. room_id, token, delete_local_events=delete_local_events
  170. )
  171. return HTTPStatus.OK, {"purge_id": purge_id}
  172. class PurgeHistoryStatusRestServlet(RestServlet):
  173. PATTERNS = admin_patterns("/purge_history_status/(?P<purge_id>[^/]*)$")
  174. def __init__(self, hs: "HomeServer"):
  175. self.pagination_handler = hs.get_pagination_handler()
  176. self.auth = hs.get_auth()
  177. async def on_GET(
  178. self, request: SynapseRequest, purge_id: str
  179. ) -> Tuple[int, JsonDict]:
  180. await assert_requester_is_admin(self.auth, request)
  181. purge_status = self.pagination_handler.get_purge_status(purge_id)
  182. if purge_status is None:
  183. raise NotFoundError("purge id '%s' not found" % purge_id)
  184. return HTTPStatus.OK, purge_status.asdict()
  185. ########################################################################################
  186. #
  187. # please don't add more servlets here: this file is already long and unwieldy. Put
  188. # them in separate files within the 'admin' package.
  189. #
  190. ########################################################################################
  191. class AdminRestResource(JsonResource):
  192. """The REST resource which gets mounted at /_synapse/admin"""
  193. def __init__(self, hs: "HomeServer"):
  194. JsonResource.__init__(self, hs, canonical_json=False)
  195. register_servlets(hs, self)
  196. def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
  197. """
  198. Register all the admin servlets.
  199. """
  200. register_servlets_for_client_rest_resource(hs, http_server)
  201. BlockRoomRestServlet(hs).register(http_server)
  202. ListRoomRestServlet(hs).register(http_server)
  203. RoomStateRestServlet(hs).register(http_server)
  204. RoomRestServlet(hs).register(http_server)
  205. RoomRestV2Servlet(hs).register(http_server)
  206. RoomMembersRestServlet(hs).register(http_server)
  207. DeleteRoomStatusByDeleteIdRestServlet(hs).register(http_server)
  208. DeleteRoomStatusByRoomIdRestServlet(hs).register(http_server)
  209. JoinRoomAliasServlet(hs).register(http_server)
  210. VersionServlet(hs).register(http_server)
  211. UserAdminServlet(hs).register(http_server)
  212. UserMembershipRestServlet(hs).register(http_server)
  213. UserTokenRestServlet(hs).register(http_server)
  214. UserRestServletV2(hs).register(http_server)
  215. UsersRestServletV2(hs).register(http_server)
  216. DeviceRestServlet(hs).register(http_server)
  217. DevicesRestServlet(hs).register(http_server)
  218. DeleteDevicesRestServlet(hs).register(http_server)
  219. UserMediaStatisticsRestServlet(hs).register(http_server)
  220. EventReportDetailRestServlet(hs).register(http_server)
  221. EventReportsRestServlet(hs).register(http_server)
  222. AccountDataRestServlet(hs).register(http_server)
  223. PushersRestServlet(hs).register(http_server)
  224. MakeRoomAdminRestServlet(hs).register(http_server)
  225. ShadowBanRestServlet(hs).register(http_server)
  226. ForwardExtremitiesRestServlet(hs).register(http_server)
  227. RoomEventContextServlet(hs).register(http_server)
  228. RateLimitRestServlet(hs).register(http_server)
  229. UsernameAvailableRestServlet(hs).register(http_server)
  230. ListRegistrationTokensRestServlet(hs).register(http_server)
  231. NewRegistrationTokenRestServlet(hs).register(http_server)
  232. RegistrationTokenRestServlet(hs).register(http_server)
  233. DestinationMembershipRestServlet(hs).register(http_server)
  234. DestinationResetConnectionRestServlet(hs).register(http_server)
  235. DestinationRestServlet(hs).register(http_server)
  236. ListDestinationsRestServlet(hs).register(http_server)
  237. # Some servlets only get registered for the main process.
  238. if hs.config.worker.worker_app is None:
  239. SendServerNoticeServlet(hs).register(http_server)
  240. BackgroundUpdateEnabledRestServlet(hs).register(http_server)
  241. BackgroundUpdateRestServlet(hs).register(http_server)
  242. BackgroundUpdateStartJobRestServlet(hs).register(http_server)
  243. def register_servlets_for_client_rest_resource(
  244. hs: "HomeServer", http_server: HttpServer
  245. ) -> None:
  246. """Register only the servlets which need to be exposed on /_matrix/client/xxx"""
  247. WhoisRestServlet(hs).register(http_server)
  248. PurgeHistoryStatusRestServlet(hs).register(http_server)
  249. DeactivateAccountRestServlet(hs).register(http_server)
  250. PurgeHistoryRestServlet(hs).register(http_server)
  251. ResetPasswordRestServlet(hs).register(http_server)
  252. SearchUsersRestServlet(hs).register(http_server)
  253. UserRegisterServlet(hs).register(http_server)
  254. AccountValidityRenewServlet(hs).register(http_server)
  255. # Load the media repo ones if we're using them. Otherwise load the servlets which
  256. # don't need a media repo (typically readonly admin APIs).
  257. if hs.config.media.can_load_media_repo:
  258. register_servlets_for_media_repo(hs, http_server)
  259. else:
  260. ListMediaInRoom(hs).register(http_server)
  261. # don't add more things here: new servlets should only be exposed on
  262. # /_synapse/admin so should not go here. Instead register them in AdminRestResource.