def fetch_events(query): # type: (Mapping[str, Any]) -> Dict[str, Any] queue_id = query["queue_id"] # type: str dont_block = query["dont_block"] # type: bool last_event_id = query["last_event_id"] # type: int user_profile_id = query["user_profile_id"] # type: int new_queue_data = query.get("new_queue_data") # type: Optional[MutableMapping[str, Any]] user_profile_email = query["user_profile_email"] # type: Text client_type_name = query["client_type_name"] # type: Text handler_id = query["handler_id"] # type: int try: was_connected = False orig_queue_id = queue_id extra_log_data = "" if queue_id is None: if dont_block: client = allocate_client_descriptor(new_queue_data) queue_id = client.event_queue.id else: raise JsonableError(_("Missing 'queue_id' argument")) else: if last_event_id is None: raise JsonableError(_("Missing 'last_event_id' argument")) client = get_client_descriptor(queue_id) if client is None: raise BadEventQueueIdError(queue_id) if user_profile_id != client.user_profile_id: raise JsonableError(_("You are not authorized to get events from this queue")) client.event_queue.prune(last_event_id) was_connected = client.finish_current_handler() if not client.event_queue.empty() or dont_block: response = dict(events=client.event_queue.contents(), handler_id=handler_id) # type: Dict[str, Any] if orig_queue_id is None: response['queue_id'] = queue_id if len(response["events"]) == 1: extra_log_data = "[%s/%s/%s]" % (queue_id, len(response["events"]), response["events"][0]["type"]) else: extra_log_data = "[%s/%s]" % (queue_id, len(response["events"])) if was_connected: extra_log_data += " [was connected]" return dict(type="response", response=response, extra_log_data=extra_log_data) # After this point, dont_block=False, the queue is empty, and we # have a pre-existing queue, so we wait for new events. if was_connected: logging.info("Disconnected handler for queue %s (%s/%s)" % (queue_id, user_profile_email, client_type_name)) except JsonableError as e: return dict(type="error", exception=e) client.connect_handler(handler_id, client_type_name) return dict(type="async")
def cleanup_event_queue(request: HttpRequest, user_profile: UserProfile, queue_id: str=REQ()) -> HttpResponse: client = get_client_descriptor(str(queue_id)) if client is None: raise BadEventQueueIdError(queue_id) if user_profile.id != client.user_profile_id: return json_error(_("You are not authorized to access this queue")) request._log_data['extra'] = "[%s]" % (queue_id,) client.cleanup() return json_success()
def authenticate_client(self, msg: Dict[str, Any]) -> None: if self.authenticated: self.session.send_message({'req_id': msg['req_id'], 'type': 'response', 'response': {'result': 'error', 'msg': 'Already authenticated'}}) return user_profile = get_user_profile(self.browser_session_id) if user_profile is None: raise JsonableError(_('Unknown or missing session')) self.session.user_profile = user_profile if 'csrf_token' not in msg['request']: # Debugging code to help with understanding #6961 logging.error("Invalid websockets auth request: %s" % (msg['request'],)) raise JsonableError(_('CSRF token entry missing from request')) if not _compare_salted_tokens(msg['request']['csrf_token'], self.csrf_token): raise JsonableError(_('CSRF token does not match that in cookie')) if 'queue_id' not in msg['request']: raise JsonableError(_("Missing 'queue_id' argument")) queue_id = msg['request']['queue_id'] client = get_client_descriptor(queue_id) if client is None: raise BadEventQueueIdError(queue_id) if user_profile.id != client.user_profile_id: raise JsonableError(_("You are not the owner of the queue with id '%s'") % (queue_id,)) self.authenticated = True register_connection(queue_id, self) response = {'req_id': msg['req_id'], 'type': 'response', 'response': {'result': 'success', 'msg': ''}} status_inquiries = msg['request'].get('status_inquiries') if status_inquiries is not None: results = {} # type: Dict[str, Dict[str, str]] for inquiry in status_inquiries: status = redis_client.hgetall(req_redis_key(inquiry)) # type: Dict[bytes, bytes] if len(status) == 0: result = {'status': 'not_received'} elif b'response' not in status: result = {'status': status[b'status'].decode('utf-8')} else: result = {'status': status[b'status'].decode('utf-8'), 'response': ujson.loads(status[b'response'])} results[str(inquiry)] = result response['response']['status_inquiries'] = results self.session.send_message(response) ioloop = tornado.ioloop.IOLoop.instance() ioloop.remove_timeout(self.timeout_handle)
def cleanup_event_queue( request: HttpRequest, user_profile: UserProfile, queue_id: str = REQ() ) -> HttpResponse: client = get_client_descriptor(str(queue_id)) if client is None: raise BadEventQueueIdError(queue_id) if user_profile.id != client.user_profile_id: raise JsonableError(_("You are not authorized to access this queue")) log_data = get_request_notes(request).log_data assert log_data is not None log_data["extra"] = f"[{queue_id}]" client.cleanup() return json_success()
def authenticate_client(self, msg): # type: (Dict[str, Any]) -> None if self.authenticated: self.session.send_message({'req_id': msg['req_id'], 'type': 'response', 'response': {'result': 'error', 'msg': 'Already authenticated'}}) return user_profile = get_user_profile(self.browser_session_id) if user_profile is None: raise JsonableError(_('Unknown or missing session')) self.session.user_profile = user_profile if not _compare_salted_tokens(msg['request']['csrf_token'], self.csrf_token): raise JsonableError(_('CSRF token does not match that in cookie')) if 'queue_id' not in msg['request']: raise JsonableError(_("Missing 'queue_id' argument")) queue_id = msg['request']['queue_id'] client = get_client_descriptor(queue_id) if client is None: raise BadEventQueueIdError(queue_id) if user_profile.id != client.user_profile_id: raise JsonableError(_("You are not the owner of the queue with id '%s'") % (queue_id,)) self.authenticated = True register_connection(queue_id, self) response = {'req_id': msg['req_id'], 'type': 'response', 'response': {'result': 'success', 'msg': ''}} status_inquiries = msg['request'].get('status_inquiries') if status_inquiries is not None: results = {} for inquiry in status_inquiries: status = redis_client.hgetall(req_redis_key(inquiry)) if len(status) == 0: status['status'] = 'not_received' if 'response' in status: status['response'] = ujson.loads(status['response']) results[str(inquiry)] = status response['response']['status_inquiries'] = results self.session.send_message(response) ioloop = tornado.ioloop.IOLoop.instance() ioloop.remove_timeout(self.timeout_handle)
def get_client_descriptor(queue_id: str) -> ClientDescriptor: try: return clients[queue_id] except KeyError: raise BadEventQueueIdError(queue_id)
def fetch_events(query: Mapping[str, Any]) -> Dict[str, Any]: queue_id: str = query["queue_id"] dont_block: bool = query["dont_block"] last_event_id: int = query["last_event_id"] user_profile_id: int = query["user_profile_id"] new_queue_data: Optional[MutableMapping[str, Any]] = query.get("new_queue_data") client_type_name: str = query["client_type_name"] handler_id: int = query["handler_id"] try: was_connected = False orig_queue_id = queue_id extra_log_data = "" if queue_id is None: if dont_block: client = allocate_client_descriptor(new_queue_data) queue_id = client.event_queue.id else: raise JsonableError(_("Missing 'queue_id' argument")) else: if last_event_id is None: raise JsonableError(_("Missing 'last_event_id' argument")) client = get_client_descriptor(queue_id) if client is None: raise BadEventQueueIdError(queue_id) if user_profile_id != client.user_profile_id: raise JsonableError(_("You are not authorized to get events from this queue")) if ( client.event_queue.newest_pruned_id is not None and last_event_id < client.event_queue.newest_pruned_id ): raise JsonableError(_("An event newer than %s has already been pruned!") % (last_event_id,)) client.event_queue.prune(last_event_id) if ( client.event_queue.newest_pruned_id is not None and last_event_id != client.event_queue.newest_pruned_id ): raise JsonableError(_("Event %s was not in this queue") % (last_event_id,)) was_connected = client.finish_current_handler() if not client.event_queue.empty() or dont_block: response: Dict[str, Any] = dict( events=client.event_queue.contents(), handler_id=handler_id, ) if orig_queue_id is None: response['queue_id'] = queue_id if len(response["events"]) == 1: extra_log_data = "[{}/{}/{}]".format(queue_id, len(response["events"]), response["events"][0]["type"]) else: extra_log_data = "[{}/{}]".format(queue_id, len(response["events"])) if was_connected: extra_log_data += " [was connected]" return dict(type="response", response=response, extra_log_data=extra_log_data) # After this point, dont_block=False, the queue is empty, and we # have a pre-existing queue, so we wait for new events. if was_connected: logging.info("Disconnected handler for queue %s (%s/%s)", queue_id, user_profile_id, client_type_name) except JsonableError as e: return dict(type="error", exception=e) client.connect_handler(handler_id, client_type_name) return dict(type="async")