admin.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2014-2016 OpenMarket Ltd
  3. # Copyright 2018 New Vector Ltd
  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 hashlib
  17. import hmac
  18. import logging
  19. from six import text_type
  20. from six.moves import http_client
  21. from twisted.internet import defer
  22. from synapse.api.constants import Membership, UserTypes
  23. from synapse.api.errors import AuthError, Codes, NotFoundError, SynapseError
  24. from synapse.http.servlet import (
  25. assert_params_in_dict,
  26. parse_integer,
  27. parse_json_object_from_request,
  28. parse_string,
  29. )
  30. from synapse.types import UserID, create_requester
  31. from .base import ClientV1RestServlet, client_path_patterns
  32. logger = logging.getLogger(__name__)
  33. class UsersRestServlet(ClientV1RestServlet):
  34. PATTERNS = client_path_patterns("/admin/users/(?P<user_id>[^/]*)")
  35. def __init__(self, hs):
  36. super(UsersRestServlet, self).__init__(hs)
  37. self.handlers = hs.get_handlers()
  38. @defer.inlineCallbacks
  39. def on_GET(self, request, user_id):
  40. target_user = UserID.from_string(user_id)
  41. requester = yield self.auth.get_user_by_req(request)
  42. is_admin = yield self.auth.is_server_admin(requester.user)
  43. if not is_admin:
  44. raise AuthError(403, "You are not a server admin")
  45. # To allow all users to get the users list
  46. # if not is_admin and target_user != auth_user:
  47. # raise AuthError(403, "You are not a server admin")
  48. if not self.hs.is_mine(target_user):
  49. raise SynapseError(400, "Can only users a local user")
  50. ret = yield self.handlers.admin_handler.get_users()
  51. defer.returnValue((200, ret))
  52. class UserRegisterServlet(ClientV1RestServlet):
  53. """
  54. Attributes:
  55. NONCE_TIMEOUT (int): Seconds until a generated nonce won't be accepted
  56. nonces (dict[str, int]): The nonces that we will accept. A dict of
  57. nonce to the time it was generated, in int seconds.
  58. """
  59. PATTERNS = client_path_patterns("/admin/register")
  60. NONCE_TIMEOUT = 60
  61. def __init__(self, hs):
  62. super(UserRegisterServlet, self).__init__(hs)
  63. self.handlers = hs.get_handlers()
  64. self.reactor = hs.get_reactor()
  65. self.nonces = {}
  66. self.hs = hs
  67. def _clear_old_nonces(self):
  68. """
  69. Clear out old nonces that are older than NONCE_TIMEOUT.
  70. """
  71. now = int(self.reactor.seconds())
  72. for k, v in list(self.nonces.items()):
  73. if now - v > self.NONCE_TIMEOUT:
  74. del self.nonces[k]
  75. def on_GET(self, request):
  76. """
  77. Generate a new nonce.
  78. """
  79. self._clear_old_nonces()
  80. nonce = self.hs.get_secrets().token_hex(64)
  81. self.nonces[nonce] = int(self.reactor.seconds())
  82. return (200, {"nonce": nonce})
  83. @defer.inlineCallbacks
  84. def on_POST(self, request):
  85. self._clear_old_nonces()
  86. if not self.hs.config.registration_shared_secret:
  87. raise SynapseError(400, "Shared secret registration is not enabled")
  88. body = parse_json_object_from_request(request)
  89. if "nonce" not in body:
  90. raise SynapseError(
  91. 400, "nonce must be specified", errcode=Codes.BAD_JSON,
  92. )
  93. nonce = body["nonce"]
  94. if nonce not in self.nonces:
  95. raise SynapseError(
  96. 400, "unrecognised nonce",
  97. )
  98. # Delete the nonce, so it can't be reused, even if it's invalid
  99. del self.nonces[nonce]
  100. if "username" not in body:
  101. raise SynapseError(
  102. 400, "username must be specified", errcode=Codes.BAD_JSON,
  103. )
  104. else:
  105. if (
  106. not isinstance(body['username'], text_type)
  107. or len(body['username']) > 512
  108. ):
  109. raise SynapseError(400, "Invalid username")
  110. username = body["username"].encode("utf-8")
  111. if b"\x00" in username:
  112. raise SynapseError(400, "Invalid username")
  113. if "password" not in body:
  114. raise SynapseError(
  115. 400, "password must be specified", errcode=Codes.BAD_JSON,
  116. )
  117. else:
  118. if (
  119. not isinstance(body['password'], text_type)
  120. or len(body['password']) > 512
  121. ):
  122. raise SynapseError(400, "Invalid password")
  123. password = body["password"].encode("utf-8")
  124. if b"\x00" in password:
  125. raise SynapseError(400, "Invalid password")
  126. admin = body.get("admin", None)
  127. user_type = body.get("user_type", None)
  128. if user_type is not None and user_type not in UserTypes.ALL_USER_TYPES:
  129. raise SynapseError(400, "Invalid user type")
  130. got_mac = body["mac"]
  131. want_mac = hmac.new(
  132. key=self.hs.config.registration_shared_secret.encode(),
  133. digestmod=hashlib.sha1,
  134. )
  135. want_mac.update(nonce.encode('utf8'))
  136. want_mac.update(b"\x00")
  137. want_mac.update(username)
  138. want_mac.update(b"\x00")
  139. want_mac.update(password)
  140. want_mac.update(b"\x00")
  141. want_mac.update(b"admin" if admin else b"notadmin")
  142. if user_type:
  143. want_mac.update(b"\x00")
  144. want_mac.update(user_type.encode('utf8'))
  145. want_mac = want_mac.hexdigest()
  146. if not hmac.compare_digest(
  147. want_mac.encode('ascii'),
  148. got_mac.encode('ascii')
  149. ):
  150. raise SynapseError(403, "HMAC incorrect")
  151. # Reuse the parts of RegisterRestServlet to reduce code duplication
  152. from synapse.rest.client.v2_alpha.register import RegisterRestServlet
  153. register = RegisterRestServlet(self.hs)
  154. (user_id, _) = yield register.registration_handler.register(
  155. localpart=body['username'].lower(),
  156. password=body["password"],
  157. admin=bool(admin),
  158. generate_token=False,
  159. user_type=user_type,
  160. )
  161. result = yield register._create_registration_details(user_id, body)
  162. defer.returnValue((200, result))
  163. class WhoisRestServlet(ClientV1RestServlet):
  164. PATTERNS = client_path_patterns("/admin/whois/(?P<user_id>[^/]*)")
  165. def __init__(self, hs):
  166. super(WhoisRestServlet, self).__init__(hs)
  167. self.handlers = hs.get_handlers()
  168. @defer.inlineCallbacks
  169. def on_GET(self, request, user_id):
  170. target_user = UserID.from_string(user_id)
  171. requester = yield self.auth.get_user_by_req(request)
  172. auth_user = requester.user
  173. is_admin = yield self.auth.is_server_admin(requester.user)
  174. if not is_admin and target_user != auth_user:
  175. raise AuthError(403, "You are not a server admin")
  176. if not self.hs.is_mine(target_user):
  177. raise SynapseError(400, "Can only whois a local user")
  178. ret = yield self.handlers.admin_handler.get_whois(target_user)
  179. defer.returnValue((200, ret))
  180. class PurgeMediaCacheRestServlet(ClientV1RestServlet):
  181. PATTERNS = client_path_patterns("/admin/purge_media_cache")
  182. def __init__(self, hs):
  183. self.media_repository = hs.get_media_repository()
  184. super(PurgeMediaCacheRestServlet, self).__init__(hs)
  185. @defer.inlineCallbacks
  186. def on_POST(self, request):
  187. requester = yield self.auth.get_user_by_req(request)
  188. is_admin = yield self.auth.is_server_admin(requester.user)
  189. if not is_admin:
  190. raise AuthError(403, "You are not a server admin")
  191. before_ts = parse_integer(request, "before_ts", required=True)
  192. logger.info("before_ts: %r", before_ts)
  193. ret = yield self.media_repository.delete_old_remote_media(before_ts)
  194. defer.returnValue((200, ret))
  195. class PurgeHistoryRestServlet(ClientV1RestServlet):
  196. PATTERNS = client_path_patterns(
  197. "/admin/purge_history/(?P<room_id>[^/]*)(/(?P<event_id>[^/]+))?"
  198. )
  199. def __init__(self, hs):
  200. """
  201. Args:
  202. hs (synapse.server.HomeServer)
  203. """
  204. super(PurgeHistoryRestServlet, self).__init__(hs)
  205. self.pagination_handler = hs.get_pagination_handler()
  206. self.store = hs.get_datastore()
  207. @defer.inlineCallbacks
  208. def on_POST(self, request, room_id, event_id):
  209. requester = yield self.auth.get_user_by_req(request)
  210. is_admin = yield self.auth.is_server_admin(requester.user)
  211. if not is_admin:
  212. raise AuthError(403, "You are not a server admin")
  213. body = parse_json_object_from_request(request, allow_empty_body=True)
  214. delete_local_events = bool(body.get("delete_local_events", False))
  215. # establish the topological ordering we should keep events from. The
  216. # user can provide an event_id in the URL or the request body, or can
  217. # provide a timestamp in the request body.
  218. if event_id is None:
  219. event_id = body.get('purge_up_to_event_id')
  220. if event_id is not None:
  221. event = yield self.store.get_event(event_id)
  222. if event.room_id != room_id:
  223. raise SynapseError(400, "Event is for wrong room.")
  224. token = yield self.store.get_topological_token_for_event(event_id)
  225. logger.info(
  226. "[purge] purging up to token %s (event_id %s)",
  227. token, event_id,
  228. )
  229. elif 'purge_up_to_ts' in body:
  230. ts = body['purge_up_to_ts']
  231. if not isinstance(ts, int):
  232. raise SynapseError(
  233. 400, "purge_up_to_ts must be an int",
  234. errcode=Codes.BAD_JSON,
  235. )
  236. stream_ordering = (
  237. yield self.store.find_first_stream_ordering_after_ts(ts)
  238. )
  239. r = (
  240. yield self.store.get_room_event_after_stream_ordering(
  241. room_id, stream_ordering,
  242. )
  243. )
  244. if not r:
  245. logger.warn(
  246. "[purge] purging events not possible: No event found "
  247. "(received_ts %i => stream_ordering %i)",
  248. ts, stream_ordering,
  249. )
  250. raise SynapseError(
  251. 404,
  252. "there is no event to be purged",
  253. errcode=Codes.NOT_FOUND,
  254. )
  255. (stream, topo, _event_id) = r
  256. token = "t%d-%d" % (topo, stream)
  257. logger.info(
  258. "[purge] purging up to token %s (received_ts %i => "
  259. "stream_ordering %i)",
  260. token, ts, stream_ordering,
  261. )
  262. else:
  263. raise SynapseError(
  264. 400,
  265. "must specify purge_up_to_event_id or purge_up_to_ts",
  266. errcode=Codes.BAD_JSON,
  267. )
  268. purge_id = yield self.pagination_handler.start_purge_history(
  269. room_id, token,
  270. delete_local_events=delete_local_events,
  271. )
  272. defer.returnValue((200, {
  273. "purge_id": purge_id,
  274. }))
  275. class PurgeHistoryStatusRestServlet(ClientV1RestServlet):
  276. PATTERNS = client_path_patterns(
  277. "/admin/purge_history_status/(?P<purge_id>[^/]+)"
  278. )
  279. def __init__(self, hs):
  280. """
  281. Args:
  282. hs (synapse.server.HomeServer)
  283. """
  284. super(PurgeHistoryStatusRestServlet, self).__init__(hs)
  285. self.pagination_handler = hs.get_pagination_handler()
  286. @defer.inlineCallbacks
  287. def on_GET(self, request, purge_id):
  288. requester = yield self.auth.get_user_by_req(request)
  289. is_admin = yield self.auth.is_server_admin(requester.user)
  290. if not is_admin:
  291. raise AuthError(403, "You are not a server admin")
  292. purge_status = self.pagination_handler.get_purge_status(purge_id)
  293. if purge_status is None:
  294. raise NotFoundError("purge id '%s' not found" % purge_id)
  295. defer.returnValue((200, purge_status.asdict()))
  296. class DeactivateAccountRestServlet(ClientV1RestServlet):
  297. PATTERNS = client_path_patterns("/admin/deactivate/(?P<target_user_id>[^/]*)")
  298. def __init__(self, hs):
  299. super(DeactivateAccountRestServlet, self).__init__(hs)
  300. self._deactivate_account_handler = hs.get_deactivate_account_handler()
  301. @defer.inlineCallbacks
  302. def on_POST(self, request, target_user_id):
  303. body = parse_json_object_from_request(request, allow_empty_body=True)
  304. erase = body.get("erase", False)
  305. if not isinstance(erase, bool):
  306. raise SynapseError(
  307. http_client.BAD_REQUEST,
  308. "Param 'erase' must be a boolean, if given",
  309. Codes.BAD_JSON,
  310. )
  311. UserID.from_string(target_user_id)
  312. requester = yield self.auth.get_user_by_req(request)
  313. is_admin = yield self.auth.is_server_admin(requester.user)
  314. if not is_admin:
  315. raise AuthError(403, "You are not a server admin")
  316. result = yield self._deactivate_account_handler.deactivate_account(
  317. target_user_id, erase,
  318. )
  319. if result:
  320. id_server_unbind_result = "success"
  321. else:
  322. id_server_unbind_result = "no-support"
  323. defer.returnValue((200, {
  324. "id_server_unbind_result": id_server_unbind_result,
  325. }))
  326. class ShutdownRoomRestServlet(ClientV1RestServlet):
  327. """Shuts down a room by removing all local users from the room and blocking
  328. all future invites and joins to the room. Any local aliases will be repointed
  329. to a new room created by `new_room_user_id` and kicked users will be auto
  330. joined to the new room.
  331. """
  332. PATTERNS = client_path_patterns("/admin/shutdown_room/(?P<room_id>[^/]+)")
  333. DEFAULT_MESSAGE = (
  334. "Sharing illegal content on this server is not permitted and rooms in"
  335. " violation will be blocked."
  336. )
  337. def __init__(self, hs):
  338. super(ShutdownRoomRestServlet, self).__init__(hs)
  339. self.store = hs.get_datastore()
  340. self.state = hs.get_state_handler()
  341. self._room_creation_handler = hs.get_room_creation_handler()
  342. self.event_creation_handler = hs.get_event_creation_handler()
  343. self.room_member_handler = hs.get_room_member_handler()
  344. @defer.inlineCallbacks
  345. def on_POST(self, request, room_id):
  346. requester = yield self.auth.get_user_by_req(request)
  347. is_admin = yield self.auth.is_server_admin(requester.user)
  348. if not is_admin:
  349. raise AuthError(403, "You are not a server admin")
  350. content = parse_json_object_from_request(request)
  351. assert_params_in_dict(content, ["new_room_user_id"])
  352. new_room_user_id = content["new_room_user_id"]
  353. room_creator_requester = create_requester(new_room_user_id)
  354. message = content.get("message", self.DEFAULT_MESSAGE)
  355. room_name = content.get("room_name", "Content Violation Notification")
  356. info = yield self._room_creation_handler.create_room(
  357. room_creator_requester,
  358. config={
  359. "preset": "public_chat",
  360. "name": room_name,
  361. "power_level_content_override": {
  362. "users_default": -10,
  363. },
  364. },
  365. ratelimit=False,
  366. )
  367. new_room_id = info["room_id"]
  368. yield self.event_creation_handler.create_and_send_nonmember_event(
  369. room_creator_requester,
  370. {
  371. "type": "m.room.message",
  372. "content": {"body": message, "msgtype": "m.text"},
  373. "room_id": new_room_id,
  374. "sender": new_room_user_id,
  375. },
  376. ratelimit=False,
  377. )
  378. requester_user_id = requester.user.to_string()
  379. logger.info("Shutting down room %r", room_id)
  380. yield self.store.block_room(room_id, requester_user_id)
  381. users = yield self.state.get_current_user_in_room(room_id)
  382. kicked_users = []
  383. for user_id in users:
  384. if not self.hs.is_mine_id(user_id):
  385. continue
  386. logger.info("Kicking %r from %r...", user_id, room_id)
  387. target_requester = create_requester(user_id)
  388. yield self.room_member_handler.update_membership(
  389. requester=target_requester,
  390. target=target_requester.user,
  391. room_id=room_id,
  392. action=Membership.LEAVE,
  393. content={},
  394. ratelimit=False
  395. )
  396. yield self.room_member_handler.forget(target_requester.user, room_id)
  397. yield self.room_member_handler.update_membership(
  398. requester=target_requester,
  399. target=target_requester.user,
  400. room_id=new_room_id,
  401. action=Membership.JOIN,
  402. content={},
  403. ratelimit=False
  404. )
  405. kicked_users.append(user_id)
  406. aliases_for_room = yield self.store.get_aliases_for_room(room_id)
  407. yield self.store.update_aliases_for_room(
  408. room_id, new_room_id, requester_user_id
  409. )
  410. defer.returnValue((200, {
  411. "kicked_users": kicked_users,
  412. "local_aliases": aliases_for_room,
  413. "new_room_id": new_room_id,
  414. }))
  415. class QuarantineMediaInRoom(ClientV1RestServlet):
  416. """Quarantines all media in a room so that no one can download it via
  417. this server.
  418. """
  419. PATTERNS = client_path_patterns("/admin/quarantine_media/(?P<room_id>[^/]+)")
  420. def __init__(self, hs):
  421. super(QuarantineMediaInRoom, self).__init__(hs)
  422. self.store = hs.get_datastore()
  423. @defer.inlineCallbacks
  424. def on_POST(self, request, room_id):
  425. requester = yield self.auth.get_user_by_req(request)
  426. is_admin = yield self.auth.is_server_admin(requester.user)
  427. if not is_admin:
  428. raise AuthError(403, "You are not a server admin")
  429. num_quarantined = yield self.store.quarantine_media_ids_in_room(
  430. room_id, requester.user.to_string(),
  431. )
  432. defer.returnValue((200, {"num_quarantined": num_quarantined}))
  433. class ListMediaInRoom(ClientV1RestServlet):
  434. """Lists all of the media in a given room.
  435. """
  436. PATTERNS = client_path_patterns("/admin/room/(?P<room_id>[^/]+)/media")
  437. def __init__(self, hs):
  438. super(ListMediaInRoom, self).__init__(hs)
  439. self.store = hs.get_datastore()
  440. @defer.inlineCallbacks
  441. def on_GET(self, request, room_id):
  442. requester = yield self.auth.get_user_by_req(request)
  443. is_admin = yield self.auth.is_server_admin(requester.user)
  444. if not is_admin:
  445. raise AuthError(403, "You are not a server admin")
  446. local_mxcs, remote_mxcs = yield self.store.get_media_mxcs_in_room(room_id)
  447. defer.returnValue((200, {"local": local_mxcs, "remote": remote_mxcs}))
  448. class ResetPasswordRestServlet(ClientV1RestServlet):
  449. """Post request to allow an administrator reset password for a user.
  450. This needs user to have administrator access in Synapse.
  451. Example:
  452. http://localhost:8008/_matrix/client/api/v1/admin/reset_password/
  453. @user:to_reset_password?access_token=admin_access_token
  454. JsonBodyToSend:
  455. {
  456. "new_password": "secret"
  457. }
  458. Returns:
  459. 200 OK with empty object if success otherwise an error.
  460. """
  461. PATTERNS = client_path_patterns("/admin/reset_password/(?P<target_user_id>[^/]*)")
  462. def __init__(self, hs):
  463. self.store = hs.get_datastore()
  464. super(ResetPasswordRestServlet, self).__init__(hs)
  465. self.hs = hs
  466. self.auth = hs.get_auth()
  467. self._set_password_handler = hs.get_set_password_handler()
  468. @defer.inlineCallbacks
  469. def on_POST(self, request, target_user_id):
  470. """Post request to allow an administrator reset password for a user.
  471. This needs user to have administrator access in Synapse.
  472. """
  473. UserID.from_string(target_user_id)
  474. requester = yield self.auth.get_user_by_req(request)
  475. is_admin = yield self.auth.is_server_admin(requester.user)
  476. if not is_admin:
  477. raise AuthError(403, "You are not a server admin")
  478. params = parse_json_object_from_request(request)
  479. assert_params_in_dict(params, ["new_password"])
  480. new_password = params['new_password']
  481. logger.info("new_password: %r", new_password)
  482. yield self._set_password_handler.set_password(
  483. target_user_id, new_password, requester
  484. )
  485. defer.returnValue((200, {}))
  486. class GetUsersPaginatedRestServlet(ClientV1RestServlet):
  487. """Get request to get specific number of users from Synapse.
  488. This needs user to have administrator access in Synapse.
  489. Example:
  490. http://localhost:8008/_matrix/client/api/v1/admin/users_paginate/
  491. @admin:user?access_token=admin_access_token&start=0&limit=10
  492. Returns:
  493. 200 OK with json object {list[dict[str, Any]], count} or empty object.
  494. """
  495. PATTERNS = client_path_patterns("/admin/users_paginate/(?P<target_user_id>[^/]*)")
  496. def __init__(self, hs):
  497. self.store = hs.get_datastore()
  498. super(GetUsersPaginatedRestServlet, self).__init__(hs)
  499. self.hs = hs
  500. self.auth = hs.get_auth()
  501. self.handlers = hs.get_handlers()
  502. @defer.inlineCallbacks
  503. def on_GET(self, request, target_user_id):
  504. """Get request to get specific number of users from Synapse.
  505. This needs user to have administrator access in Synapse.
  506. """
  507. target_user = UserID.from_string(target_user_id)
  508. requester = yield self.auth.get_user_by_req(request)
  509. is_admin = yield self.auth.is_server_admin(requester.user)
  510. if not is_admin:
  511. raise AuthError(403, "You are not a server admin")
  512. # To allow all users to get the users list
  513. # if not is_admin and target_user != auth_user:
  514. # raise AuthError(403, "You are not a server admin")
  515. if not self.hs.is_mine(target_user):
  516. raise SynapseError(400, "Can only users a local user")
  517. order = "name" # order by name in user table
  518. start = parse_integer(request, "start", required=True)
  519. limit = parse_integer(request, "limit", required=True)
  520. logger.info("limit: %s, start: %s", limit, start)
  521. ret = yield self.handlers.admin_handler.get_users_paginate(
  522. order, start, limit
  523. )
  524. defer.returnValue((200, ret))
  525. @defer.inlineCallbacks
  526. def on_POST(self, request, target_user_id):
  527. """Post request to get specific number of users from Synapse..
  528. This needs user to have administrator access in Synapse.
  529. Example:
  530. http://localhost:8008/_matrix/client/api/v1/admin/users_paginate/
  531. @admin:user?access_token=admin_access_token
  532. JsonBodyToSend:
  533. {
  534. "start": "0",
  535. "limit": "10
  536. }
  537. Returns:
  538. 200 OK with json object {list[dict[str, Any]], count} or empty object.
  539. """
  540. UserID.from_string(target_user_id)
  541. requester = yield self.auth.get_user_by_req(request)
  542. is_admin = yield self.auth.is_server_admin(requester.user)
  543. if not is_admin:
  544. raise AuthError(403, "You are not a server admin")
  545. order = "name" # order by name in user table
  546. params = parse_json_object_from_request(request)
  547. assert_params_in_dict(params, ["limit", "start"])
  548. limit = params['limit']
  549. start = params['start']
  550. logger.info("limit: %s, start: %s", limit, start)
  551. ret = yield self.handlers.admin_handler.get_users_paginate(
  552. order, start, limit
  553. )
  554. defer.returnValue((200, ret))
  555. class SearchUsersRestServlet(ClientV1RestServlet):
  556. """Get request to search user table for specific users according to
  557. search term.
  558. This needs user to have administrator access in Synapse.
  559. Example:
  560. http://localhost:8008/_matrix/client/api/v1/admin/search_users/
  561. @admin:user?access_token=admin_access_token&term=alice
  562. Returns:
  563. 200 OK with json object {list[dict[str, Any]], count} or empty object.
  564. """
  565. PATTERNS = client_path_patterns("/admin/search_users/(?P<target_user_id>[^/]*)")
  566. def __init__(self, hs):
  567. self.store = hs.get_datastore()
  568. super(SearchUsersRestServlet, self).__init__(hs)
  569. self.hs = hs
  570. self.auth = hs.get_auth()
  571. self.handlers = hs.get_handlers()
  572. @defer.inlineCallbacks
  573. def on_GET(self, request, target_user_id):
  574. """Get request to search user table for specific users according to
  575. search term.
  576. This needs user to have a administrator access in Synapse.
  577. """
  578. target_user = UserID.from_string(target_user_id)
  579. requester = yield self.auth.get_user_by_req(request)
  580. is_admin = yield self.auth.is_server_admin(requester.user)
  581. if not is_admin:
  582. raise AuthError(403, "You are not a server admin")
  583. # To allow all users to get the users list
  584. # if not is_admin and target_user != auth_user:
  585. # raise AuthError(403, "You are not a server admin")
  586. if not self.hs.is_mine(target_user):
  587. raise SynapseError(400, "Can only users a local user")
  588. term = parse_string(request, "term", required=True)
  589. logger.info("term: %s ", term)
  590. ret = yield self.handlers.admin_handler.search_users(
  591. term
  592. )
  593. defer.returnValue((200, ret))
  594. def register_servlets(hs, http_server):
  595. WhoisRestServlet(hs).register(http_server)
  596. PurgeMediaCacheRestServlet(hs).register(http_server)
  597. PurgeHistoryStatusRestServlet(hs).register(http_server)
  598. DeactivateAccountRestServlet(hs).register(http_server)
  599. PurgeHistoryRestServlet(hs).register(http_server)
  600. UsersRestServlet(hs).register(http_server)
  601. ResetPasswordRestServlet(hs).register(http_server)
  602. GetUsersPaginatedRestServlet(hs).register(http_server)
  603. SearchUsersRestServlet(hs).register(http_server)
  604. ShutdownRoomRestServlet(hs).register(http_server)
  605. QuarantineMediaInRoom(hs).register(http_server)
  606. ListMediaInRoom(hs).register(http_server)
  607. UserRegisterServlet(hs).register(http_server)