async def on_GET(self, request: SynapseRequest, user_id: str, account_data_type: str) -> Tuple[int, JsonDict]: requester = await self.auth.get_user_by_req(request) if user_id != requester.user.to_string(): raise AuthError(403, "Cannot get account data for other users.") event = await self.store.get_global_account_data_by_type_for_user( user_id, account_data_type) if event is None: raise NotFoundError("Account data not found") return 200, event
def on_GET(self, request, user_id, account_data_type): requester = yield self.auth.get_user_by_req(request) if user_id != requester.user.to_string(): raise AuthError(403, "Cannot get account data for other users.") event = yield self.store.get_global_account_data_by_type_for_user( account_data_type, user_id, ) if event is None: raise NotFoundError("Account data not found") defer.returnValue((200, event))
async def on_DELETE(self, request: SynapseRequest, user_id: str) -> Tuple[int, JsonDict]: await assert_requester_is_admin(self.auth, request) if not self.hs.is_mine_id(user_id): raise SynapseError(400, "Only local users can be ratelimited") if not await self.store.get_user_by_id(user_id): raise NotFoundError("User not found") await self.store.delete_ratelimit_for_user(user_id) return 200, {}
async def on_GET(self, request, user_id): await assert_requester_is_admin(self.auth, request) if not self.is_mine(UserID.from_string(user_id)): raise SynapseError(400, "Can only lookup local users") user = await self.store.get_user_by_id(user_id) if user is None: raise NotFoundError("Unknown user") room_ids = await self.store.get_rooms_for_user(user_id) ret = {"joined_rooms": list(room_ids), "total": len(room_ids)} return 200, ret
async def on_GET(self, request, user_id): await assert_requester_is_admin(self.auth, request) target_user = UserID.from_string(user_id) if not self.hs.is_mine(target_user): raise SynapseError(400, "Can only lookup local users") ret = await self.admin_handler.get_user(target_user) if not ret: raise NotFoundError("User not found") return 200, ret
async def _async_render_GET(self, request): """ Args: request (twisted.web.http.Request): """ version = parse_string(request, "v", default=self._default_consent_version) username = parse_string(request, "u", required=False, default="") userhmac = None has_consented = False public_version = username == "" if not public_version: userhmac_bytes = parse_string(request, "h", required=True, encoding=None) self._check_hash(username, userhmac_bytes) if username.startswith("@"): qualified_user_id = username else: qualified_user_id = UserID(username, self.hs.hostname).to_string() u = await self.store.get_user_by_id(qualified_user_id) if u is None: raise NotFoundError("Unknown user") has_consented = u["consent_version"] == version userhmac = userhmac_bytes.decode("ascii") try: self._render_template( request, "%s.html" % (version,), user=username, userhmac=userhmac, version=version, has_consented=has_consented, public_version=public_version, ) except TemplateNotFound: raise NotFoundError("Unknown policy version")
async def on_GET(self, request: SynapseRequest, room_id: str) -> Tuple[int, JsonDict]: await assert_requester_is_admin(self.auth, request) ret = await self.store.get_room_with_stats(room_id) if not ret: raise NotFoundError("Room not found") members = await self.store.get_users_in_room(room_id) ret["joined_local_devices"] = await self.store.count_devices_by_users( members) return (200, ret)
async def on_query(self, query_type: str, args: dict): handler = self.query_handlers.get(query_type) if handler: return await handler(args) # Check if we can route it somewhere else that isn't us if self._instance_name == "master": return await self._get_query_client(query_type=query_type, args=args) # Uh oh, no handler! Let's raise an exception so the request returns an # error. logger.warning("No handler registered for query type %s", query_type) raise NotFoundError("No handler for Query type '%s'" % (query_type,))
def delete_association(self, requester, room_alias): """Remove an alias from the directory (this is only meant for human users; AS users should call delete_appservice_association) Args: requester (Requester): room_alias (RoomAlias): Returns: Deferred[unicode]: room id that the alias used to point to Raises: NotFoundError: if the alias doesn't exist AuthError: if the user doesn't have perms to delete the alias (ie, the user is neither the creator of the alias, nor a server admin. SynapseError: if the alias belongs to an AS """ user_id = requester.user.to_string() try: can_delete = yield self._user_can_delete_alias(room_alias, user_id) except StoreError as e: if e.code == 404: raise NotFoundError("Unknown room alias") raise if not can_delete: raise AuthError(403, "You don't have permission to delete the alias.") can_delete = yield self.can_modify_alias(room_alias, user_id=user_id) if not can_delete: raise SynapseError( 400, "This alias is reserved by an application service.", errcode=Codes.EXCLUSIVE, ) room_id = yield self._delete_association(room_alias) try: yield self._update_canonical_alias( requester, requester.user.to_string(), room_id, room_alias ) except AuthError as e: logger.info("Failed to update alias events: %s", e) return room_id
async def on_DELETE(self, request, server_name: str, media_id: str): await assert_requester_is_admin(self.auth, request) if self.server_name != server_name: raise SynapseError(400, "Can only delete local media") if await self.store.get_local_media(media_id) is None: raise NotFoundError("Unknown media") logging.info("Deleting local media by ID: %s", media_id) deleted_media, total = await self.media_repository.delete_local_media( media_id) return 200, {"deleted_media": deleted_media, "total": total}
async def on_GET(self, request: SynapseRequest, user_id: str) -> Tuple[int, JsonDict]: await assert_requester_is_admin(self.auth, request) target_user = UserID.from_string(user_id) if not self.hs.is_mine(target_user): raise SynapseError(HTTPStatus.BAD_REQUEST, "Can only look up local users") user_info_dict = await self.admin_handler.get_user(target_user) if not user_info_dict: raise NotFoundError("User not found") return HTTPStatus.OK, user_info_dict
async def on_DELETE(self, request, user_id, device_id): await assert_requester_is_admin(self.auth, request) target_user = UserID.from_string(user_id) if not self.hs.is_mine(target_user): raise SynapseError(400, "Can only lookup local users") u = await self.store.get_user_by_id(target_user.to_string()) if u is None: raise NotFoundError("Unknown user") await self.device_handler.delete_device(target_user.to_string(), device_id) return 200, {}
async def on_GET(self, request, user_id): await assert_requester_is_admin(self.auth, request) target_user = UserID.from_string(user_id) if not self.hs.is_mine(target_user): raise SynapseError(400, "Can only lookup local users") u = await self.store.get_user_by_id(target_user.to_string()) if u is None: raise NotFoundError("Unknown user") devices = await self.device_handler.get_devices_by_user( target_user.to_string()) return 200, {"devices": devices, "total": len(devices)}
async def on_PUT(self, request: SynapseRequest, token: str) -> Tuple[int, JsonDict]: """Update a registration token.""" await assert_requester_is_admin(self.auth, request) body = parse_json_object_from_request(request) new_attributes = {} # Only add uses_allowed to new_attributes if it is present and valid if "uses_allowed" in body: uses_allowed = body["uses_allowed"] if not ( uses_allowed is None or (isinstance(uses_allowed, int) and uses_allowed >= 0) ): raise SynapseError( HTTPStatus.BAD_REQUEST, "uses_allowed must be a non-negative integer or null", Codes.INVALID_PARAM, ) new_attributes["uses_allowed"] = uses_allowed if "expiry_time" in body: expiry_time = body["expiry_time"] if not isinstance(expiry_time, (int, type(None))): raise SynapseError( HTTPStatus.BAD_REQUEST, "expiry_time must be an integer or null", Codes.INVALID_PARAM, ) if isinstance(expiry_time, int) and expiry_time < self.clock.time_msec(): raise SynapseError( HTTPStatus.BAD_REQUEST, "expiry_time must not be in the past", Codes.INVALID_PARAM, ) new_attributes["expiry_time"] = expiry_time if len(new_attributes) == 0: # Nothing to update, get token info to return token_info = await self.store.get_one_registration_token(token) else: token_info = await self.store.update_registration_token( token, new_attributes ) # If no result return a 404 if token_info is None: raise NotFoundError(f"No such registration token: {token}") return HTTPStatus.OK, token_info
async def on_DELETE( self, request: SynapseRequest, user_id: str, device_id: str ) -> Tuple[int, JsonDict]: await assert_requester_is_admin(self.auth, request) target_user = UserID.from_string(user_id) if not self.is_mine(target_user): raise SynapseError(HTTPStatus.BAD_REQUEST, "Can only lookup local users") u = await self.store.get_user_by_id(target_user.to_string()) if u is None: raise NotFoundError("Unknown user") await self.device_handler.delete_device(target_user.to_string(), device_id) return HTTPStatus.OK, {}
async def on_GET(self, request: SynapseRequest, user_id, device_id: str) -> Tuple[int, JsonDict]: await assert_requester_is_admin(self.auth, request) target_user = UserID.from_string(user_id) if not self.hs.is_mine(target_user): raise SynapseError(400, "Can only lookup local users") u = await self.store.get_user_by_id(target_user.to_string()) if u is None: raise NotFoundError("Unknown user") device = await self.device_handler.get_device(target_user.to_string(), device_id) return 200, device
async def on_PUT(self, request, user_id, device_id): await assert_requester_is_admin(self.auth, request) target_user = UserID.from_string(user_id) if not self.hs.is_mine(target_user): raise SynapseError(400, "Can only lookup local users") u = await self.store.get_user_by_id(target_user.to_string()) if u is None: raise NotFoundError("Unknown user") body = parse_json_object_from_request(request, allow_empty_body=True) await self.device_handler.update_device(target_user.to_string(), device_id, body) return 200, {}
async def on_DELETE(self, request: SynapseRequest, server_name: str, media_id: str) -> Tuple[int, JsonDict]: await assert_requester_is_admin(self.auth, request) if self.server_name != server_name: raise SynapseError(HTTPStatus.BAD_REQUEST, "Can only delete local media") if await self.store.get_local_media(media_id) is None: raise NotFoundError("Unknown media") logging.info("Deleting local media by ID: %s", media_id) deleted_media, total = await self.media_repository.delete_local_media_ids( [media_id]) return HTTPStatus.OK, {"deleted_media": deleted_media, "total": total}
async def on_GET( self, request: SynapseRequest, user_id: str ) -> Tuple[int, JsonDict]: await assert_requester_is_admin(self.auth, request) if not self.is_mine(UserID.from_string(user_id)): raise SynapseError(400, "Can only lookup local users") if not await self.store.get_user_by_id(user_id): raise NotFoundError("User not found") pushers = await self.store.get_pushers_by_user_id(user_id) filtered_pushers = [p.as_dict() for p in pushers] return 200, {"pushers": filtered_pushers, "total": len(filtered_pushers)}
async def on_GET(self, request: SynapseRequest, room_id: str) -> Tuple[int, JsonDict]: await assert_requester_is_admin(self.auth, request) ret = await self.store.get_room(room_id) if not ret: raise NotFoundError("Room not found") event_ids = await self.store.get_current_state_ids(room_id) events = await self.store.get_events(event_ids.values()) now = self.clock.time_msec() room_state = self._event_serializer.serialize_events( events.values(), now) ret = {"state": room_state} return HTTPStatus.OK, ret
def _get_remote_media_impl(self, server_name, media_id): media_info = yield self.store.get_cached_remote_media( server_name, media_id ) if not media_info: media_info = yield self._download_remote_file( server_name, media_id ) elif media_info["quarantined_by"]: raise NotFoundError() else: self.recently_accessed_remotes.add((server_name, media_id)) yield self.store.update_cached_last_access_time( [(server_name, media_id)], self.clock.time_msec() ) defer.returnValue(media_info)
async def on_GET(self, request: SynapseRequest, user_id: str) -> Tuple[int, JsonDict]: await assert_requester_is_admin(self.auth, request) target_user = UserID.from_string(user_id) if not self.hs.is_mine(target_user): raise SynapseError(HTTPStatus.BAD_REQUEST, "Can only lookup local users") u = await self.store.get_user_by_id(target_user.to_string()) if u is None: raise NotFoundError("Unknown user") devices = await self.device_handler.get_devices_by_user( target_user.to_string()) return HTTPStatus.OK, {"devices": devices, "total": len(devices)}
def on_DELETE(self, request): spec = _rule_spec_from_path(request.postpath) user, _ = yield self.auth.get_user_by_req(request) namespaced_rule_id = _namespaced_rule_id_from_spec(spec) try: yield self.hs.get_datastore().delete_push_rule( user.to_string(), namespaced_rule_id) defer.returnValue((200, {})) except StoreError as e: if e.code == 404: raise NotFoundError() else: raise
async def set_rule_attr(self, user_id: str, spec: RuleSpec, val: Union[bool, JsonDict]) -> None: if spec.attr not in ("enabled", "actions"): # for the sake of potential future expansion, shouldn't report # 404 in the case of an unknown request so check it corresponds to # a known attribute first. raise UnrecognizedRequestError() namespaced_rule_id = _namespaced_rule_id_from_spec(spec) rule_id = spec.rule_id is_default_rule = rule_id.startswith(".") if is_default_rule: if namespaced_rule_id not in BASE_RULE_IDS: raise NotFoundError("Unknown rule %s" % (namespaced_rule_id, )) if spec.attr == "enabled": if isinstance(val, dict) and "enabled" in val: val = val["enabled"] if not isinstance(val, bool): # Legacy fallback # This should *actually* take a dict, but many clients pass # bools directly, so let's not break them. raise SynapseError(400, "Value for 'enabled' must be boolean") await self.store.set_push_rule_enabled(user_id, namespaced_rule_id, val, is_default_rule) elif spec.attr == "actions": if not isinstance(val, dict): raise SynapseError(400, "Value must be a dict") actions = val.get("actions") if not isinstance(actions, list): raise SynapseError(400, "Value for 'actions' must be dict") _check_actions(actions) namespaced_rule_id = _namespaced_rule_id_from_spec(spec) rule_id = spec.rule_id is_default_rule = rule_id.startswith(".") if is_default_rule: if user_id in self._users_new_default_push_rules: rule_ids = NEW_RULE_IDS else: rule_ids = BASE_RULE_IDS if namespaced_rule_id not in rule_ids: raise SynapseError( 404, "Unknown rule %r" % (namespaced_rule_id, )) await self.store.set_push_rule_actions(user_id, namespaced_rule_id, actions, is_default_rule) else: raise UnrecognizedRequestError()
def get_event( self, event_id, check_redacted=True, get_prev_content=False, allow_rejected=False, allow_none=False, check_room_id=None, ): """Get an event from the database by event_id. Args: event_id (str): The event_id of the event to fetch check_redacted (bool): If True, check if event has been redacted and redact it. get_prev_content (bool): If True and event is a state event, include the previous states content in the unsigned field. allow_rejected (bool): If True return rejected events. allow_none (bool): If True, return None if no event found, if False throw a NotFoundError check_room_id (str|None): if not None, check the room of the found event. If there is a mismatch, behave as per allow_none. Returns: Deferred[EventBase|None] """ if not isinstance(event_id, str): raise TypeError("Invalid event event_id %r" % (event_id, )) events = yield self.get_events_as_list( [event_id], check_redacted=check_redacted, get_prev_content=get_prev_content, allow_rejected=allow_rejected, ) event = events[0] if events else None if event is not None and check_room_id is not None: if event.room_id != check_room_id: event = None if event is None and not allow_none: raise NotFoundError("Could not find event %s" % (event_id, )) return event
async def on_PUT(self, request: SynapseRequest, user_id: str, device_id: str) -> Tuple[int, JsonDict]: await assert_requester_is_admin(self.auth, request) target_user = UserID.from_string(user_id) if not self.is_mine(target_user): raise SynapseError(HTTPStatus.BAD_REQUEST, "Can only lookup local users") u = await self.store.get_user_by_id(target_user.to_string()) if u is None: raise NotFoundError("Unknown user") body = parse_json_object_from_request(request, allow_empty_body=True) await self.device_handler.update_device(target_user.to_string(), device_id, body) return HTTPStatus.OK, {}
async def ensure_media_is_in_local_cache(self, file_info: FileInfo) -> str: """Ensures that the given file is in the local cache. Attempts to download it from storage providers if it isn't. Args: file_info Returns: Full path to local file """ path = self._file_info_to_path(file_info) local_path = os.path.join(self.local_media_directory, path) if os.path.exists(local_path): return local_path # Fallback for paths without method names # Should be removed in the future if file_info.thumbnail and file_info.server_name: legacy_path = self.filepaths.remote_media_thumbnail_rel_legacy( server_name=file_info.server_name, file_id=file_info.file_id, width=file_info.thumbnail_width, height=file_info.thumbnail_height, content_type=file_info.thumbnail_type, ) legacy_local_path = os.path.join(self.local_media_directory, legacy_path) if os.path.exists(legacy_local_path): return legacy_local_path dirname = os.path.dirname(local_path) if not os.path.exists(dirname): os.makedirs(dirname) for provider in self.storage_providers: res = await provider.fetch(path, file_info) # type: Any if res: with res: consumer = BackgroundFileConsumer(open(local_path, "wb"), self.reactor) await res.write_to_consumer(consumer) await consumer.wait() return local_path raise NotFoundError()
def delete_association(self, requester, room_alias): # association deletion for human users user_id = requester.user.to_string() try: can_delete = yield self._user_can_delete_alias(room_alias, user_id) except StoreError as e: if e.code == 404: raise NotFoundError("Unknown room alias") raise if not can_delete: raise AuthError( 403, "You don't have permission to delete the alias.", ) can_delete = yield self.can_modify_alias( room_alias, user_id=user_id ) if not can_delete: raise SynapseError( 400, "This alias is reserved by an application service.", errcode=Codes.EXCLUSIVE ) room_id = yield self._delete_association(room_alias) try: yield self.send_room_alias_update_event( requester, room_id ) yield self._update_canonical_alias( requester, requester.user.to_string(), room_id, room_alias, ) except AuthError as e: logger.info("Failed to update alias events: %s", e) defer.returnValue(room_id)
async def delete_room_keys( self, user_id: str, version: str, room_id: Optional[str] = None, session_id: Optional[str] = None, ) -> JsonDict: """Bulk delete the E2E room keys for a given backup, optionally filtered to a given room or a given session. See EndToEndRoomKeyStore.delete_e2e_room_keys for full details. Args: user_id: the user whose backup we're deleting version: the version ID of the backup we're deleting room_id: room ID to delete keys for, for None to delete keys for all rooms session_id: session ID to delete keys for, for None to delete keys for all sessions Raises: NotFoundError: if the backup version does not exist Returns: A dict containing the count and etag for the backup version """ # lock for consistency with uploading with (await self._upload_linearizer.queue(user_id)): # make sure the backup version exists try: version_info = await self.store.get_e2e_room_keys_version_info( user_id, version) except StoreError as e: if e.code == 404: raise NotFoundError("Unknown backup version") else: raise await self.store.delete_e2e_room_keys(user_id, version, room_id, session_id) version_etag = version_info["etag"] + 1 await self.store.update_e2e_room_keys_version( user_id, version, None, version_etag) count = await self.store.count_e2e_room_keys(user_id, version) return {"etag": str(version_etag), "count": count}
def set_push_rule_actions_txn(txn, stream_id, event_stream_ordering): if is_default_rule: # Add a dummy rule to the rules table with the user specified # actions. priority_class = -1 priority = 1 self._upsert_push_rule_txn( txn, stream_id, event_stream_ordering, user_id, rule_id, priority_class, priority, "[]", actions_json, update_stream=False, ) else: try: self.db_pool.simple_update_one_txn( txn, "push_rules", { "user_name": user_id, "rule_id": rule_id }, {"actions": actions_json}, ) except StoreError as serr: if serr.code == 404: # this sets the NOT_FOUND error Code raise NotFoundError("Push rule does not exist") else: raise self._insert_push_rules_update_txn( txn, stream_id, event_stream_ordering, user_id, rule_id, op="ACTIONS", data={"actions": actions_json}, )