def test_decode_data(self): self.assertEqual(decode_data(self.encoded_data), self.data) self.assertEqual(decode_data("[malformed data]"), None)
def test_decode_data(self): self.assertEqual(decode_data(self.encoded_data), self.data)
def post(self, project_id): """ Handle API HTTP requests. """ if not self.request.body: raise tornado.web.HTTPError(400, log_message="empty request") if self.request.headers.get("Content-Type", "").startswith("application/json"): # handle JSON requests if corresponding Content-Type specified try: request_data = json_decode(self.request.body) except ValueError: raise tornado.web.HTTPError(400, log_message="malformed json") if not isinstance(request_data, dict): raise tornado.web.HTTPError(400, log_message="object expected") sign = request_data.get("sign") encoded_data = request_data.get("data") else: # handle application/x-www-form-urlencoded request sign = self.get_argument('sign', None) encoded_data = self.get_argument('data', None) if not sign: raise tornado.web.HTTPError(400, log_message="no data sign") if not encoded_data: raise tornado.web.HTTPError(400, log_message="no data") is_owner_request = False if project_id == self.application.OWNER_API_PROJECT_ID: # API request aims to be from superuser is_owner_request = True if is_owner_request: # use api secret key from configuration to check sign secret = self.application.config.get("api_secret") if not secret: raise tornado.web.HTTPError(501, log_message="no api_secret in configuration file") project = None else: project, error = yield self.application.structure.get_project_by_id(project_id) if error: raise tornado.web.HTTPError(500, log_message=str(error)) if not project: raise tornado.web.HTTPError(404, log_message="project not found") # use project secret key to validate sign secret = project['secret_key'] is_valid = auth.check_sign( secret, project_id, encoded_data, sign ) if not is_valid: raise tornado.web.HTTPError(401, log_message="unauthorized") data = auth.decode_data(encoded_data) if not data: raise tornado.web.HTTPError(400, log_message="malformed data") multi_response = MultiResponse() if isinstance(data, dict): # single object request response = yield self.process_object(data, project, is_owner_request) multi_response.add(response) elif isinstance(data, list): # multiple object request if len(data) > self.application.ADMIN_API_MESSAGE_LIMIT: raise tornado.web.HTTPError( 400, log_message="admin API message limit exceeded (received {0} messages)".format( len(data) ) ) for obj in data: response = yield self.process_object(obj, project, is_owner_request) multi_response.add(response) else: raise tornado.web.HTTPError(400, log_message="data not a list or dictionary") if self.application.collector: self.application.collector.incr('api') self.json_response(multi_response.as_message())
def post(self, project_id): """ Handle API HTTP requests. """ if not self.request.body: raise tornado.web.HTTPError(400, log_message="empty request") sign = self.get_argument('sign', None) if not sign: raise tornado.web.HTTPError(400, log_message="no data sign") encoded_data = self.get_argument('data', None) if not encoded_data: raise tornado.web.HTTPError(400, log_message="no data") is_owner_request = False if project_id == self.application.MAGIC_PROJECT_ID: # API request aims to be from superuser is_owner_request = True if is_owner_request: # use api secret key from configuration to check sign secret = self.application.settings["config"].get("api_secret") if not secret: raise tornado.web.HTTPError(501, log_message="no api_secret in configuration file") project = None else: project, error = yield self.application.structure.get_project_by_id(project_id) if error: raise tornado.web.HTTPError(500, log_message=str(error)) if not project: raise tornado.web.HTTPError(404, log_message="project not found") # use project secret key to validate sign secret = project['secret_key'] is_valid = auth.check_sign( secret, project_id, encoded_data, sign ) if not is_valid: raise tornado.web.HTTPError(401, log_message="unauthorized") data = auth.decode_data(encoded_data) if not data: raise tornado.web.HTTPError(400, log_message="malformed data") response = Response() try: validate(data, req_schema) except ValidationError as e: response.error = str(e) else: req_id = data.get("uid", None) method = data.get("method") params = data.get("params") response.uid = req_id response.method = method schema = server_api_schema if is_owner_request and self.application.MAGIC_PROJECT_PARAM in params: project_id = params[self.application.MAGIC_PROJECT_PARAM] project, error = yield self.application.structure.get_project_by_id( project_id ) if error: logger.error(error) response.error = self.application.INTERNAL_SERVER_ERROR if not project: response.error = self.application.PROJECT_NOT_FOUND try: params.pop(self.application.MAGIC_PROJECT_PARAM) except KeyError: pass if not is_owner_request and method in owner_api_methods: response.error = self.application.PERMISSION_DENIED if not response.error: if method not in schema: response.error = self.application.METHOD_NOT_FOUND else: try: validate(params, schema[method]) except ValidationError as e: response.error = str(e) else: result, error = yield self.application.process_call( project, method, params ) response.body = result response.error = error self.json_response(response.as_message())
def post(self, project_id): """ Handle API HTTP requests. """ if not self.request.body: raise tornado.web.HTTPError(400, log_message="empty request") sign = self.get_argument('sign', None) if not sign: raise tornado.web.HTTPError(400, log_message="no data sign") encoded_data = self.get_argument('data', None) if not encoded_data: raise tornado.web.HTTPError(400, log_message="no data") is_owner_request = False if project_id == self.application.OWNER_API_PROJECT_ID: # API request aims to be from superuser is_owner_request = True if is_owner_request: # use api secret key from configuration to check sign secret = self.application.settings["config"].get("api_secret") if not secret: raise tornado.web.HTTPError( 501, log_message="no api_secret in configuration file") project = None else: project, error = yield self.application.structure.get_project_by_id( project_id) if error: raise tornado.web.HTTPError(500, log_message=str(error)) if not project: raise tornado.web.HTTPError(404, log_message="project not found") # use project secret key to validate sign secret = project['secret_key'] is_valid = auth.check_sign(secret, project_id, encoded_data, sign) if not is_valid: raise tornado.web.HTTPError(401, log_message="unauthorized") data = auth.decode_data(encoded_data) if not data: raise tornado.web.HTTPError(400, log_message="malformed data") multi_response = MultiResponse() if isinstance(data, dict): # single object request response = yield self.process_object(data, project, is_owner_request) multi_response.add(response) elif isinstance(data, list): # multiple object request if len(data) > self.application.ADMIN_API_MESSAGE_LIMIT: raise tornado.web.HTTPError( 400, log_message= "admin API message limit exceeded (received {0} messages)". format(len(data))) for obj in data: response = yield self.process_object(obj, project, is_owner_request) multi_response.add(response) else: raise tornado.web.HTTPError( 400, log_message="data not a list or dictionary") if self.application.collector: self.application.collector.incr('api') self.json_response(multi_response.as_message())
def post(self, project_id): """ Handle API HTTP requests. """ if not self.request.body: raise tornado.web.HTTPError(400, log_message="empty request") sign = self.get_argument('sign', None) if not sign: raise tornado.web.HTTPError(400, log_message="no data sign") encoded_data = self.get_argument('data', None) if not encoded_data: raise tornado.web.HTTPError(400, log_message="no data") is_owner_request = False if project_id == self.application.MAGIC_PROJECT_ID: # API request aims to be from superuser is_owner_request = True if is_owner_request: # use api secret key from configuration to check sign secret = self.application.settings["config"].get("api_secret") if not secret: raise tornado.web.HTTPError( 501, log_message="no api_secret in configuration file") project = None else: project, error = yield self.application.structure.get_project_by_id( project_id) if error: raise tornado.web.HTTPError(500, log_message=str(error)) if not project: raise tornado.web.HTTPError(404, log_message="project not found") # use project secret key to validate sign secret = project['secret_key'] is_valid = auth.check_sign(secret, project_id, encoded_data, sign) if not is_valid: raise tornado.web.HTTPError(401, log_message="unauthorized") data = auth.decode_data(encoded_data) if not data: raise tornado.web.HTTPError(400, log_message="malformed data") response = Response() try: validate(data, req_schema) except ValidationError as e: response.error = str(e) else: req_id = data.get("uid", None) method = data.get("method") params = data.get("params") response.uid = req_id response.method = method schema = server_api_schema if is_owner_request and self.application.MAGIC_PROJECT_PARAM in params: project_id = params[self.application.MAGIC_PROJECT_PARAM] project, error = yield self.application.structure.get_project_by_id( project_id) if error: logger.error(error) response.error = self.application.INTERNAL_SERVER_ERROR if not project: response.error = self.application.PROJECT_NOT_FOUND try: params.pop(self.application.MAGIC_PROJECT_PARAM) except KeyError: pass if not is_owner_request and method in owner_api_methods: response.error = self.application.PERMISSION_DENIED if not response.error: if method not in schema: response.error = self.application.METHOD_NOT_FOUND else: try: validate(params, schema[method]) except ValidationError as e: response.error = str(e) else: result, error = yield self.application.process_call( project, method, params) response.body = result response.error = error self.json_response(response.as_message())