def on_get(self, req, resp, organization_code): """GETs a paged collection of security threats of an organization. :param req: See Falcon Request documentation. :param resp: See Falcon Response documentation. :param organization_code: The code of the organization. """ session = Session() try: organization = session.query(Organization).get(organization_code) if organization is None: raise falcon.HTTPNotFound() # Build query to fetch items query = session\ .query(OrganizationSecurityThreat)\ .join(SecurityThreat)\ .filter(OrganizationSecurityThreat.organization_id == organization_code)\ .order_by(SecurityThreat.name)\ data, paging = get_collection_page(req, query, custom_asdict) resp.media = {'data': data, 'paging': paging} finally: session.close()
def on_get(self, req, resp, project_id, queue_name, claim_id): LOG.debug( _(u'Claim item GET - claim: %(claim_id)s, ' u'queue: %(queue_name)s, project: %(project_id)s'), { 'queue_name': queue_name, 'project_id': project_id, 'claim_id': claim_id }) try: meta, msgs = self.claim_controller.get(queue_name, claim_id=claim_id, project=project_id) # Buffer claimed messages # TODO(kgriffs): Optimize along with serialization (see below) meta['messages'] = list(msgs) except storage_exceptions.DoesNotExist: raise falcon.HTTPNotFound() except Exception as ex: LOG.exception(ex) description = _(u'Claim could not be queried.') raise wsgi_exceptions.HTTPServiceUnavailable(description) # Serialize claimed messages # TODO(kgriffs): Optimize for msg in meta['messages']: msg['href'] = _msg_uri_from_claim( req.path.rsplit('/', 2)[0], msg['id'], meta['id']) del msg['id'] meta['href'] = req.path del meta['id'] resp.content_location = req.relative_uri resp.body = utils.to_json(meta)
def get_architecture_meta(self, req, resp, id): user_id = req.context['user'] logger.debug('Authorize user {id}'.format(id=user_id)) try: context = {'user_id': user_id} architecture = metadata.get_architecture(id, context) except metadata.DoesNotExist: logger.debug('Architecture {id} does not exist'.format(id=id)) raise falcon.HTTPNotFound( title="Architecture not found", description="Architecture metadata does not exist") resp.status = falcon.HTTP_200 architecture_dict = architecture.to_dict() result_keys = [ 'id', 'is_public', 'owner', 'title', 'description', 'category', 'architecture' ] resp.media = { key: architecture_dict[key] for key in result_keys if key in architecture_dict }
def on_get(self, request, response, project_id, pool): """Returns a JSON object for a single pool entry: :: {"weight": 100, "uri": "", options: {...}} :returns: HTTP | [200, 404] """ LOG.debug(u'GET pool - name: %s', pool) data = None detailed = request.get_param_as_bool('detailed') or False try: data = self._ctrl.get(pool, detailed) except errors.PoolDoesNotExist as ex: LOG.debug(ex) raise falcon.HTTPNotFound() data['href'] = request.path response.body = transport_utils.to_json(data) response.content_location = request.relative_uri
def _data(self, request, cleaned, *args, **kwargs): try: usr = User.objects.get(email=cleaned['email']) except User.DoesNotExist: raise falcon.HTTPNotFound(description=_('Account not found'), code='account_not_found') reset_token = usr.password_reset_token reset_path = settings.PASSWORD_RESET_PATH % reset_token link = "%s%s" % (settings.BASE_URL, reset_path) # TODO: this is specific for mcod-backend, we should implement more generic solution try: conn = get_connection(settings.EMAIL_BACKEND) msg_plain = render_to_string('mails/password-reset.txt', { 'link': link, 'host': settings.BASE_URL }) msg_html = render_to_string('mails/password-reset.html', { 'link': link, 'host': settings.BASE_URL }) send_mail('Reset hasła', msg_plain, config.ACCOUNTS_EMAIL, [ usr.email, ], connection=conn, html_message=msg_html) except SMTPException: raise falcon.HTTPInternalServerError( description=_('Email cannot be send'), code='email_send_error') return usr
def get_object(self, req, *args, **kwargs): modelselect = self.filter_modelselect(req, self.get_model_select()) # Perform the lookup filtering. lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field assert lookup_url_kwarg in kwargs, ( 'Expected view %s to be called with a URL keyword argument ' 'named "%s". Fix your URL conf, or set the `.lookup_field` ' 'attribute on the view correctly.' % (self.__class__.__name__, lookup_url_kwarg)) filter_kwargs = {self.lookup_field: kwargs[lookup_url_kwarg]} modelselect = modelselect.filter(**filter_kwargs) try: obj = self.prefetch_modelselect(modelselect)[0] except (peewee.DoesNotExist, IndexError): raise falcon.HTTPNotFound() # May raise a permission denied self.check_object_permissions(req, obj) return obj
def on_inbound(self, req, resp, tracking_id): user = req.context['session'].user parcel_type = req.media["parcel_type"] weight = req.media["weight"] has_battery = req.media.get("has_battery", False) has_liquid = req.media.get("has_liquid", False) sensitive_reason = req.media.get("sensitive_reason") try: InboundParcelUtil.inbound_parcel( tracking_id=tracking_id, parcel_type=parcel_type, weight=weight, has_battery=has_battery, has_liquid=has_liquid, has_sensitive=bool(sensitive_reason), sensitive_reason=sensitive_reason, user=user) except ValueError: raise falcon.HTTPNotFound(description="物流订单不存在!") except InvalidOperationException: raise falcon.HTTPBadRequest(description="非法操作!")
def on_delete(self, req, resp, **kwargs): """ Handles DELETE requests. Deletes a user resource. """ try: user_query = self.session.query(User)\ .options(FromCache('default'))\ .filter( User.id == kwargs.get('user_id') )\ # Invalidate the cache user = user_query.one() user_query.invalidate() self.session.delete(user) self.session.commit() except NoResultFound: raise falcon.HTTPNotFound( description='User does not exist' ) resp.status = falcon.HTTP_204
def get_dataset_meta(self, req, resp, id): user_id = req.context['user'] logger.debug('Authorize user {id}'.format(id=user_id)) try: context = {'user_id': user_id} dataset_meta = manager.get_dataset(id, context) except metadata.DoesNotExist: logger.debug('Dataset {id} does not exist'.format(id=id)) raise falcon.HTTPNotFound( title="Dataset not found", description="Dataset metadata does not exist") resp.status = falcon.HTTP_200 dataset_meta_dict = dataset_meta.to_dict() result_keys = [ 'id', 'status', 'is_public', 'owner', 'hash', 'size', 'date', 'title', 'description', 'category', 'labels' ] resp.media = { key: dataset_meta_dict[key] for key in result_keys if key in dataset_meta_dict }
def on_get(req, resp, device_id): HistoryUtil.check_mandatory_query_param(req.params, 'attr') collection = HistoryUtil.get_collection(req.context['related_service'], device_id) if isinstance(req.params['attr'], list): DeviceHistory.logger.info('got list of attrs') history = {} for attr in req.params['attr']: query = DeviceHistory.parse_request(req, attr) history[attr] = DeviceHistory.get_single_attr( collection, query) else: history = DeviceHistory.get_single_attr( collection, DeviceHistory.parse_request(req, req.params['attr'])) if len(history) == 0: msg = "No data for the given attribute could be found" raise falcon.HTTPNotFound(title="Attr not found", description=msg) resp.status = falcon.HTTP_200 resp.body = json.dumps(history)
def on_get(self, request, response, project_id, shard): """Returns a JSON object for a single shard entry: {"weight": 100, "uri": "", options: {...}} :returns: HTTP | [200, 404] """ LOG.debug(u'GET shard - name: %s', shard) data = None detailed = request.get_param_as_bool('detailed') or False try: data = self._ctrl.get(shard, detailed) except errors.ShardDoesNotExist as ex: LOG.debug(ex) raise falcon.HTTPNotFound() data['href'] = request.path # remove the name entry - it isn't needed on GET del data['name'] response.body = transport_utils.to_json(data) response.content_location = request.relative_uri
def on_patch(self, req, resp, organization_code, it_service_instance_id, it_asset_instance_id): """Updates (partially) the relationship IT service-IT asset requested. All entities that reference the relationship will be affected by the update. :param req: See Falcon Request documentation. :param resp: See Falcon Response documentation. :param organization_code: The code of the organization. :param it_service_instance_id: The id of the IT service instance to be patched. :param it_asset_instance_id: The id of the IT asset instance to be patched. """ session = Session() try: # Route params are checked in two steps: # 1st step: check if IT service is in organization # 2nd step: check if IT asset is in organization IT service it_service_instance = find_it_service_instance( it_service_instance_id, organization_code, session) it_service_asset = find_it_service_it_asset( it_asset_instance_id, it_service_instance_id, session) if it_service_instance is None or it_service_asset is None: raise falcon.HTTPNotFound() errors = validate_patch(req.media, organization_code, session) if errors: raise HTTPUnprocessableEntity(errors) patch_item(it_service_asset, req.media, only=['relevance_level_id']) session.commit() resp.status = falcon.HTTP_OK resp.media = {'data': custom_asdict(it_service_asset)} finally: session.close()
def on_patch(self, req, resp, organization_code): """Updates (partially) the organization. :param req: See Falcon Request documentation. :param resp: See Falcon Response documentation. :param organization_code: The code of organization to be patched. """ session = Session() try: organization = session.query(Organization).get(organization_code) if organization is None: raise falcon.HTTPNotFound() errors = validate_patch(req.media, session) if errors: raise HTTPUnprocessableEntity(errors) patch_item(organization, req.media, only=['tax_id', 'legal_name', 'trade_name']) session.commit() resp.status = falcon.HTTP_OK resp.media = {'data': organization.asdict()} finally: session.close()
def on_get(self, req, resp, pid, dsid): """ Dump the datastream history. """ xml_out = SpooledTemporaryFile() with etree.xmlfile(xml_out) as xf: with xf.element( '{{{}}}datastreamHistory'.format(FEDORA_MANAGEMENT_URI)): try: for datastream in self._get_datastream_versions(pid, dsid): _writeDatastreamProfile(xf, datastream) except DatastreamDoesNotExistError as e: resp.content_type = 'text/xml' logger.info(('Datastream history not retrieved for %s on ' '%s as datastream did not exist.'), dsid, pid) resp.body = ('Datastream history not retrieved for {} on ' '{} as datastream did not exist.').format( dsid, pid) raise falcon.HTTPNotFound() from e length = xml_out.tell() xml_out.seek(0) resp.set_stream(xml_out, length) resp.content_type = 'application/xml' logger.info('Retrieved DS history for %s on %s', dsid, pid)
def on_put(self, req: Request, resp: Response, primary_key: int): found_entity = self._resource_use_cases.find(primary_key=primary_key) if found_entity == None: raise falcon.HTTPNotFound() try: found_entity.fill( qty_of_terminals=req.media.get('qty_of_terminals'), was_canceled=req.media.get('was_canceled'), attendance_date=self._try_to_convert_date_json_to_datetime( req.media.get('attendance_date'))) attendance = self._resource_use_cases.update(found_entity) self._work_centers_use_case.update_calculated_values( attendance.work_center) attendance_updated = self._resource_use_cases.find(attendance.id) resp.media = attendance_updated.to_dict() resp.content_type = falcon.MEDIA_JSON resp.status = falcon.HTTP_OK except UseCaseException as ex: raise falcon.HTTPBadRequest(falcon.HTTP_400, str(ex)) except Exception as ex: raise falcon.HTTPError(falcon.HTTP_500, str(ex))
def on_delete(self, request, response): invite = request.invite try: song_id = int(request.media.get('song_id')) except: raise falcon.HTTPBadRequest response.response_json = {} for song in invite.song_requests[:]: if song.id == song_id: invite.song_requests.remove(song) response.response_json = { 'track': song.track, 'artist': song.artist, 'album': song.album, 'image_url': song.image_url, 'song_id': song.id } invite.save(self.db.session) return else: print("SONG ID DONT MATCH", song.id, song_id) raise falcon.HTTPNotFound()
def test_content_length_options(self, client): result = client.simulate_options() content_length = str(len(falcon.HTTPNotFound().to_json())) assert result.headers['Content-Length'] == content_length
def update_announcement(self, announcement_id: int, **kwargs) -> bool: """Update announcement. Args: announcement_id ([int]): announcement id. Kwargs: title [str]: Optional. img_url [str]: Optional. url [str]: URL, optional. weight [int]: announcement weight,optional. description [str]: Optional. expireTime [str]: ISO 8601, must have timezone at last character. 2019-09-2T11:33:29H 2019-09-2T11:33:29Z 2019-09-2T11:33:29A ... Returns: [bool]: True Raise: 400:miss param. 404:not found announcement. """ if announcement_id == None: raise falcon.HTTPMissingParam("announcement_id") try: announcement_name = self._get_announcement_key_name_by_id( announcement_id)[0] except IndexError: raise falcon.HTTPNotFound() origin_announcement = json.loads( self.redis_announcement.get(announcement_name)) announcement_data = {} for key, value in ANNOUNCEMENT_FIELD.items(): if isinstance(kwargs.get(key, None), value['type']) and value['allow_user_set']: announcement_data[key] = kwargs.get(key, None) continue if not isinstance(kwargs.get(key, None), value['type']) and value['allow_user_set']: if kwargs.get(key, None) is not None: logging.info("Add Announcements field type error :{key}") announcement_data[key] = origin_announcement.get( key, value['default']) announcement_data['publishedAt'] = datetime.datetime.utcnow( ).isoformat(timespec="seconds") + "Z" announcement_data['id'] = origin_announcement.get('id') if kwargs.get('tag', False): kwargs['tag'] = list(set(kwargs['tag'])) if len(kwargs['tag']) > MAX_TAGS_LIMIT: announcement_data['tag'] = kwargs['tag'][:MAX_TAGS_LIMIT] else: announcement_data['tag'] = kwargs['tag'] expire_time_seconds = None if kwargs.get('expireTime', False): utc = time_format_iso8601(kwargs.get('expireTime', False)) expire_time_seconds = int( (utc - datetime.datetime.utcnow()).total_seconds()) if expire_time_seconds < 0: raise falcon.HTTPBadRequest( description="expeire time set error") else: announcement_data["expireTime"] = time_format_iso8601( kwargs.get('expireTime', False)).isoformat(timespec="seconds") + "Z" data_dumps = json.dumps(announcement_data, ensure_ascii=False) self.redis_announcement.set(name=announcement_name, value=data_dumps, ex=expire_time_seconds) return True
def get_announcement_by_id(self, announcement_id) -> str: announcement_name = f"announcement_{announcement_id}" if self.redis_announcement.exists(announcement_name): return self.redis_announcement.get(announcement_name) raise falcon.HTTPNotFound()
def not_found(*args, **kwargs): """Redirects request handling to the not found render""" raise falcon.HTTPNotFound()
def on_post(self, req, resp, project_id, queue_name): LOG.debug( _(u'Messages collection POST - queue: %(queue)s, ' u'project: %(project)s') % { 'queue': queue_name, 'project': project_id }) uuid = req.get_header('Client-ID', required=True) # Place JSON size restriction before parsing if req.content_length > CFG.content_max_length: description = _(u'Message collection size is too large.') raise wsgi_exceptions.HTTPBadRequestBody(description) # Pull out just the fields we care about messages = wsgi_utils.filter_stream(req.stream, req.content_length, MESSAGE_POST_SPEC, doctype=wsgi_utils.JSONArray) # Enqueue the messages partial = False try: # No need to check each message's size if it # can not exceed the request size limit validate.message_posting( messages, check_size=(validate.CFG.message_size_uplimit < CFG.content_max_length)) message_ids = self.message_controller.post(queue_name, messages=messages, project=project_id, client_uuid=uuid) except input_exceptions.ValidationFailed as ex: raise wsgi_exceptions.HTTPBadRequestBody(str(ex)) except storage_exceptions.DoesNotExist: raise falcon.HTTPNotFound() except storage_exceptions.MessageConflict as ex: LOG.exception(ex) partial = True message_ids = ex.succeeded_ids if not message_ids: # TODO(kgriffs): Include error code that is different # from the code used in the generic case, below. description = _(u'No messages could be enqueued.') raise wsgi_exceptions.HTTPServiceUnavailable(description) except Exception as ex: LOG.exception(ex) description = _(u'Messages could not be enqueued.') raise wsgi_exceptions.HTTPServiceUnavailable(description) # Prepare the response ids_value = ','.join(message_ids) resp.location = req.path + '?ids=' + ids_value hrefs = [req.path + '/' + id for id in message_ids] body = {'resources': hrefs, 'partial': partial} resp.body = utils.to_json(body) resp.status = falcon.HTTP_201
def on_get(self, req, resp): raise falcon.HTTPNotFound(description='Not Found')
def on_get(self, req, resp, userid=None, method=None): server, store = _server_store(req, userid if userid != 'delta' else None, self.options) if not userid and req.path.split('/')[-1] != 'users': userid = kopano.Store(server=server, mapiobj = GetDefaultStore(server.mapisession)).user.userid if method and not store: raise falcon.HTTPNotFound(description="The user store has no store") if not method: if userid: if userid == 'delta': req.context['deltaid'] = '{userid}' self.delta(req, resp, server) return else: data = server.user(userid=userid) else: args = self.parse_qs(req) userid = kopano.Store(server=server, mapiobj = GetDefaultStore(server.mapisession)).user.userid company = server.user(userid=userid).company query = None if '$search' in args: query = args['$search'][0] def yielder(**kwargs): yield from company.users(hidden=False, inactive=False, query=query, **kwargs) data = self.generator(req, yielder) self.respond(req, resp, data) elif method == 'mailFolders': data = self.generator(req, store.mail_folders, 0) self.respond(req, resp, data, MailFolderResource.fields) elif method == 'contactFolders': data = self.generator(req, store.contact_folders, 0) self.respond(req, resp, data, ContactFolderResource.fields) elif method == 'messages': # TODO store-wide? data = self.folder_gen(req, store.inbox) self.respond(req, resp, data, MessageResource.fields) elif method == 'contacts': data = self.folder_gen(req, store.contacts) self.respond(req, resp, data, ContactResource.fields) elif method == 'calendars': data = self.generator(req, store.calendars, 0) self.respond(req, resp, data, CalendarResource.fields) elif method == 'events': # TODO multiple calendars? calendar = store.calendar data = self.generator(req, calendar.items, calendar.count) self.respond(req, resp, data, EventResource.fields) elif method == 'calendarView': # TODO multiple calendars? merge code with calendar.py start, end = _start_end(req) def yielder(**kwargs): for occ in store.calendar.occurrences(start, end, **kwargs): yield occ data = self.generator(req, yielder) self.respond(req, resp, data, EventResource.fields) elif method == 'reminderView': # TODO multiple calendars? # TODO use restriction in pyko: calendar.reminders(start, end)? start, end = _start_end(req) def yielder(**kwargs): for occ in store.calendar.occurrences(start, end): if occ.reminder: yield occ data = self.generator(req, yielder) self.respond(req, resp, data, ReminderResource.fields) elif method == 'memberOf': user = server.user(userid=userid) data = (user.groups(), DEFAULT_TOP, 0, 0) self.respond(req, resp, data, GroupResource.fields) elif method == 'photos': # TODO multiple photos? user = server.user(userid=userid) def yielder(**kwargs): photo = user.photo if photo: yield photo data = self.generator(req, yielder) self.respond(req, resp, data, ProfilePhotoResource.fields) elif method: raise HTTPBadRequest("Unsupported segment '%s'" % method)
def on_get(self, req, resp, **kwargs): # simulate that the endpoint is hit but raise a 404 because # the object isn't found in the database raise falcon.HTTPNotFound()
def on_get(self, req, resp): raise falcon.HTTPNotFound()
def test_decode_empty_result(self, app): client = testing.TestClient(app) response = client.simulate_request(path='/') assert response.json == falcon.HTTPNotFound().to_dict()
def on_get(self, req, resp, cn): preferred_type = req.client_prefers( ("application/json", "application/x-pem-file")) try: path, buf, cert, signed, expires = self.authority.get_signed(cn) except EnvironmentError: logger.warning("Failed to serve non-existant certificate %s to %s", cn, req.context.get("remote_addr")) raise falcon.HTTPNotFound() if preferred_type == "application/x-pem-file": resp.set_header("Content-Type", "application/x-pem-file") resp.set_header("Content-Disposition", ("attachment; filename=%s.pem" % cn)) resp.body = buf logger.debug( "Served certificate %s to %s as application/x-pem-file", cn, req.context.get("remote_addr")) elif preferred_type == "application/json": resp.set_header("Content-Type", "application/json") resp.set_header("Content-Disposition", ("attachment; filename=%s.json" % cn)) try: signer_username = getxattr( path, "user.signature.username").decode("ascii") except IOError: signer_username = None attributes = {} for key in listxattr(path): if key.startswith(b"user.machine."): attributes[key[13:].decode("ascii")] = getxattr( path, key).decode("ascii") # TODO: dedup resp.body = json.dumps( dict(common_name=cn, signer=signer_username, serial="%040x" % cert.serial_number, organizational_unit=cert.subject.native.get( "organizational_unit_name"), signed=cert["tbs_certificate"]["validity"]["not_before"]. native.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z", expires=cert["tbs_certificate"]["validity"]["not_after"]. native.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z", sha256sum=hashlib.sha256(buf).hexdigest(), attributes=attributes or None, lease=None, extensions=dict([ (e["extn_id"].native, e["extn_value"].native) for e in cert["tbs_certificate"]["extensions"] if e["extn_id"].native in ("extended_key_usage", ) ]))) logger.debug("Served certificate %s to %s as application/json", cn, req.context.get("remote_addr")) else: logger.debug( "Client did not accept application/json or application/x-pem-file" ) raise falcon.HTTPUnsupportedMediaType( "Client did not accept application/json or application/x-pem-file" )
def on_post(self, req, resp, project_id, queue_name): LOG.debug( u'Messages collection POST - queue: %(queue)s, ' u'project: %(project)s', { 'queue': queue_name, 'project': project_id }) client_uuid = wsgi_utils.get_client_uuid(req) try: # Place JSON size restriction before parsing self._validate.message_length(req.content_length) except validation.ValidationFailed as ex: LOG.debug(ex) raise wsgi_errors.HTTPBadRequestAPI(six.text_type(ex)) # Deserialize and validate the request body document = wsgi_utils.deserialize(req.stream, req.content_length) messages = wsgi_utils.sanitize(document, MESSAGE_POST_SPEC, doctype=wsgi_utils.JSONArray) try: self._validate.message_posting(messages) message_ids = self.message_controller.post(queue_name, messages=messages, project=project_id, client_uuid=client_uuid) except validation.ValidationFailed as ex: LOG.debug(ex) raise wsgi_errors.HTTPBadRequestAPI(six.text_type(ex)) except storage_errors.DoesNotExist as ex: LOG.debug(ex) raise falcon.HTTPNotFound() except storage_errors.MessageConflict as ex: LOG.exception(ex) message_ids = ex.succeeded_ids if not message_ids: # TODO(kgriffs): Include error code that is different # from the code used in the generic case, below. description = _(u'No messages could be enqueued.') raise wsgi_errors.HTTPServiceUnavailable(description) except Exception as ex: LOG.exception(ex) description = _(u'Messages could not be enqueued.') raise wsgi_errors.HTTPServiceUnavailable(description) # Prepare the response ids_value = ','.join(message_ids) resp.location = req.path + '?ids=' + ids_value hrefs = [req.path + '/' + id for id in message_ids] # NOTE(kgriffs): As of the Icehouse release, drivers are # no longer allowed to enqueue a subset of the messages # submitted by the client; it's all or nothing. Therefore, # 'partial' is now always False in the v1.0 API, and the # field has been removed in v1.1. body = {'resources': hrefs, 'partial': False} resp.body = utils.to_json(body) resp.status = falcon.HTTP_201
def validate_cart_id_exists(cart_id, cache, db_connection): """Raise 404 if given cart_id is not recognized.""" if cache.exists(cart_id) == 0: if not cart_id_db_exists(cart_id, db_connection): raise falcon.HTTPNotFound()
def on_put_my(self, req, resp, tournament_id): """ Handles the put method for the own score of a given tournment Parameters ---------- req : falcon.Request Contains the request resp: falcon.Response This object is used to issue the response to this call, if no error occurs, it returns a 204 if there was a score and it was improved and a 201 if it is the 1st score stored if there is already a log with better score, it returns a 409 - Conflict, you already have a better score response if the tournament is not accepting logs, it returns a 403 - Forbidden, tournament is not accepting gameplays if there is no tournament with the provided id, returns 404 tournament_id : str The id of the desired tournament Returns ------- NoneType This method has no return """ error = None try: logging.info("PUT score") #TODO: validate the json payload if not req.content_type: error = falcon.HTTPBadRequest(description="Provide a valid JSON as payload for this method") raise if 'application/json' not in req.content_type: error = falcon.HTTPUnsupportedMediaType(description="The payload must be sent in json format") raise #Check if the is a tournament with this id tour = self.tournaments_fetcher.get_tournament(tournament_id) except Exception as e: if error: logging.exception(error) raise error logging.exception(e) raise falcon.HTTPInternalServerError(description="Failed recovering tournament") if not tour: #Not found, return 404 raise falcon.HTTPNotFound(description="No tournament found with the provided id: {}".format(tournament_id)) # if server is in read-only mode, respond successfully as if score was submitted # this is for testing purposes, in the future we may support a real read-only mode, including the # front-end in the process, with proper user feedback if const.READ_ONLY: logging.info("Server in read-only mode, returning 201 and not submitting log") resp.body = json.dumps({"title":"201 Created","description":"Server in read-only mode"}) resp.status = falcon.HTTP_201 return #Checking the tournament is in the commit phase if tour.phase != TournamentPhase.COMMIT: #It isn't return 403 phase = None if tour.phase: phase = tour.phase.value raise falcon.HTTPForbidden(description="The tournament with id {} is not in the commit phase. Tournament phase: {}".format(tournament_id, phase)) try: #Getting request json req_json = req.media user_id = const.PLAYER_OWN_ADD score = req_json['score'] waves = req_json['waves'] log_bytes = json.dumps(req_json['log']).encode() #Check if there is already a score and log for this tournament in db log_entry = db_utilities.select_log_entry(user_id, tournament_id) if log_entry: previous_score = log_entry[2] #Check if score is higher than the one stored if (score > previous_score): #It is, store it db_utilities.update_log_entry(user_id, tournament_id, score, waves, log_bytes) #Commit the log error = self._commit_log(tournament_id, log_bytes) if error: raise resp.status = falcon.HTTP_204 else: #It isn't return 409 error = falcon.HTTPConflict(description="The given score is not higher than a previously submitted one") raise else: #No previous entry, store db_utilities.insert_log_entry(user_id, tournament_id, score, waves, log_bytes) #Commit the log error = self._commit_log(tournament_id, log_bytes) if error: raise resp.body = json.dumps({"title":"201 Created","description":"Score, wave number and log were created for tournament {}".format(tournament_id)}) resp.status = falcon.HTTP_201 except Exception as e: if error: logging.exception(error) raise error logging.exception(e) raise falcon.HTTPInternalServerError(description="Failed saving and committing game log")