def get(self, dataset_id, **kwargs): # pylint: disable=unused-argument """ :param dataset_id:dataset identifier :return: partitons pertaining to dataset """ try: result = yield self.__get_datasets__() if result is None: raise APIError(503, log_message="Server internal error") dataset_found = [i for i in result if i['id'] == dataset_id] for dataset in dataset_found: logging.info(u'Partition request for dataset:{%s} received', dataset_id) result = yield self.__get_parts__(dataset["path"]) if result is None: raise APIError( 503, log_message="Not able to retrieve partitons") raise Return(result) raise APIError(404, log_message="Dataset by that name not found") except Return as return_value: raise return_value except Exception as exception: logging.warn("Exeception thrown in /parts API-> exception msg{%s}", exception.message) raise APIError(500, log_message="Server Internal error")
def delete(self): try: result = self.path_service.end_path() except SampleException as e: raise APIError(400, e.message) except DBException as e: raise APIError(500, e.message) self.success(result)
def delete(self): try: self.sample_service.end_sample() except SampleException as e: raise APIError(400, e.message) except DBException as e: raise APIError(500, e.message) self.success('ok')
def get(self, *args, **kwargs): # pylint: disable=unused-argument try: result = yield self.__get_datasets__() if result is None: raise APIError(503, log_message="Server internal error") # reformat response depending on policy raise Return(result) except Return as return_value: raise return_value except Exception as exception: logging.warn("Exception thrown in /list API %s", exception.message) raise APIError(500, log_message="Server Internal error")
def delete(self): """ DELETE to leave current room. If the room owner leaves, the room will be deleted. """ player_name = self.get_current_user() player = Player(self.db_conn, "name", player_name) room_name = player["current_room"] if room_name: room = Room(self.db_conn, "name", room_name) else: raise APIError(409, log_message="You are currently not in a room.") with DBLock(): if room["owner"] == player_name: # Set all players' current_room to None for pname in room["current_players"]: p = Player(self.db_conn, "name", pname) p["current_room"] = None # Delete the room self.db_conn["rooms"].delete(name=room_name) return "{} successfully deleted {}".format(player_name, room_name) else: # Set player's current_room to None and remove from room's # current_players list player["current_room"] = None room["current_players"] = [ p for p in room["current_players"] if p != player_name] return "{} successfully left {}".format(player_name, room_name)
def post(self): api_assert(self.body['data'], 400, 'empty data') try: ap_datas = [] router_mac = Mac.correct(self.body['apMac']) signal = Signal(band='2.4', channel=self.body['band']) created_at = Time(int(self.body['time'])) for item in self.body['data']: device_mac = Mac.correct(item['clientMac']) rssis = {} if item.get('rss1') is not None: rssis['1'] = RSSI(float(item['rss1'])) if item.get('rss2') is not None: rssis['2'] = RSSI(float(item['rss2'])) if item.get('rss3') is not None: rssis['3'] = RSSI(float(item['rss3'])) if len(rssis) > 0: ap_datas.append( APData(router_mac=router_mac, device_mac=device_mac, created_at=created_at, rssis=rssis, signal=signal)) for ap_data in ap_datas: self.ap_data_dao.save(ap_data) except DBException as e: raise APIError(500, e.message) return 'ok'
def get(self, name): """ Get team with `name` """ with db_session: team = TeamEntity.get(name=name) if team is None: raise APIError( 400, log_message="Team with name {} does not exist!".format( name)) team_dict = team.to_dict(with_collections=True) team_dict["usernames"] = team_dict.pop("users") rankings = { k: i for i, (k, v) in enumerate( sorted(get_team_rankings( team, filter_for_matchmaking=False).items(), key=lambda x: x[1])) } my_ranking = rankings[team.name] team_dict["ranking"] = "{}/{}".format(my_ranking + 1, len(rankings)) return team_dict
def get_game_winner(db, game_id): """Get winner of game ``game_id`` :returns: Game winner if there is one otherwise empty string :rtype: str """ game = get_game(db, game_id) # If winner already known, return if game["winner"]: return game["winner"] # Otherwise, determine winner players_with_balls = [] for pname in game["players"]: p = get_player(db, pname) if p["balls"]: players_with_balls.append(pname) if len(players_with_balls) > 1: winner = "" break else: if players_with_balls: winner = players_with_balls[0] else: raise APIError( 409, log_message="No player currently has balls on the table." ) return winner
def post(self): """ POST the required credentials to get back a cookie * `username`: Username * `password`: Password """ api_assert(self.body['username'], 400, log_message="Username field is empty!") with db_session: player = PlayerEntity.get(username=self.body['username']) api_assert(player is not None, 400, log_message="No such player {}".format( self.body['username'])) password = self.body['password'] # Check if the given password hashed with the player's known # salt matches the stored password password_match = bcrypt.hashpw( password.encode(), player.salt.encode()) == player.password.encode() if password_match: self.set_secure_cookie( "user", self.body['username'], self.settings['app_config'].session_timeout_days) return {"username": player.username} else: raise APIError(400, log_message="Bad username/password combo")
def _wrapper(self, *args, **kwargs): # In case the specified input_schema is ``None``, we # don't json.loads the input, but just set it to ``None`` # instead. if input_schema is not None: # Attempt to json.loads the input try: # TODO: Assuming UTF-8 encoding for all requests, # find a nice way of determining this from charset # in headers if provided encoding = "UTF-8" input_ = json.loads(self.request.body.decode(encoding)) except ValueError as e: raise jsonschema.ValidationError( "Input is malformed; could not decode JSON object.") # Validate the received input jsonschema.validate(input_, input_schema, cls=validator_cls, format_checker=format_checker) else: input_ = None # A json.loads'd version of self.request["body"] is now available # as self.body setattr(self, "body", input_) # Call the requesthandler method output = rh_method(self, *args, **kwargs) # If the rh_method returned a Future a la `raise Return(value)` # we grab the output. if is_future(output): output = yield output # if output is empty, auto return the error 404. if not output and on_empty_404: raise APIError(404, "Resource not found.") if output_schema is not None: # We wrap output in an object before validating in case # output is a string (and ergo not a validatable JSON object) try: jsonschema.validate({"result": output}, { "type": "object", "properties": { "result": output_schema }, "required": ["result"] }) except jsonschema.ValidationError as e: # We essentially re-raise this as a TypeError because # we don't want this error data passed back to the client # because it's a fault on our end. The client should # only see a 500 - Inteal Server Error. raise TypeError(str(e)) # If no ValidationError has been raised up until here, and # we have not already written a response, write output if not self._finished: self.success(output)
def post(self): try: sample = PathStamp(mac=Mac(self.body['mac']), name=self.body["name"]) self.path_service.set_path_stamp(sample) except SampleException as e: raise APIError(400, e.message) return 'ok'
def put(self, dataset_id, **kwargs): # pylint: disable=unused-argument """ Update or Create dataset. In case of creation, dataset is validated against input schema :param dataset_id:Dataset identifier :return: """ try: result = yield self.__get_datasets__() if result is None: raise APIError(500, log_message="Server internal error") dataset_found = [ item for item in result if item[DATASET.ID] == dataset_id ] if dataset_found: request_data = escape.json_decode(self.request.body) self.__update_dataset(dataset_found[0], request_data) else: item = escape.json_decode(self.request.body) item["id"] = dataset_id try: jsonschema.validate(item, DATASET_SCHEMA) retention = self.__update_policy(item, item) self.__persist_dataset(item, retention) raise Return(item) except jsonschema.ValidationError as ex: logging.error("Failed to validate input schema {msg:%s}", ex.message) raise APIError(400, log_message="Malformed request") except jsonschema.SchemaError as ex: logging.error("Failed to validate input schema {msg:%s}", ex.message) raise APIError(400, log_message="Malformed request") except Return as return_exception: raise return_exception except APIError as api_error: raise api_error except Exception as exception: logging.warn( 'Dataset updated returned with following error ' 'on server->%s', exception.message) raise APIError(500, log_message="Internal Server Error")
def get(self, id): id_int = int(id) if id_int == 9999: raise APIError(404, '{} is not found'.format(id)) return { "id" : id_int, "gtype": self.get_query_argument("type") }
def get(self, dataset_id, **kwargs): # pylint: disable=unused-argument """ :param dataset_id: :return: """ try: result = yield self.__get_datasets__() if result is None: raise APIError(500, log_message="Server internal error") dataset_found = [i for i in result if i['id'] == dataset_id] if len(dataset_found) == 0: raise APIError(404, log_message="Dataset by that name not found.") logging.info("dataset found %s", dataset_found) raise Return(dataset_found.pop()) except Return as return_value: raise return_value except Exception as exception: logging.warn("Exception thrown in /id API %s", exception.message) raise APIError(500, log_message="Server Internal error")
def get(self): """GET to check if authenticated. Should be obvious from status code (403 vs. 200). """ if not self.get_current_user(): raise APIError( 403, log_message="Please post to {} to get a cookie".format( "/api/auth/login")) else: return "You are already logged in."
def post(self): try: sample = SampleStamp(mac=Mac(self.body['mac']), location=Location( x=self.body['location']['x'], y=self.body['location']['y'], z=self.body['location']['z'])) self.set_stamp(sample) except SampleException as e: raise APIError(400, e.message) return 'ok'
def get_player(db, player_name, err_code=409): """Get player ``player_name`` :returns: Player with ``player_name`` :raises APIError: If no Player with ``player_name`` found """ try: player = Player(db, "name", player_name) except NotFoundError: raise APIError( err_code, log_message="No user {} exists.".format(player_name) ) return player
def get_game(db, game_id, err_code=409): """Get game with ``game_id`` :returns: Game with game_id ``game_id`` :raises APIError: If no Game with game_id ``game_id`` found """ try: game = Game(db, "game_id", game_id) except NotFoundError: raise APIError( err_code, log_message="No game with game_id {} exists.".format(game_id) ) return game
def get_room(db, room_name, err_code=409): """Get room ``room_name`` :returns: Room with ``room_name`` :raises APIError: If no Room with ``room_name`` found """ try: room = Room(db, "name", room_name) except NotFoundError: raise APIError( err_code, log_message="No room {} exists.".format(room_name) ) return room
def delete(self): """ DELETE to end the game; this endpoint should only be triggered if GameState indicates there is a winner. """ player_name = self.get_current_user() player = get_player(self.db_conn, player_name) game_id = player["current_game_id"] api_assert(game_id, 400, log_message="You are not currently in" " a game.") game = get_game(self.db_conn, game_id) with DBLock(): is_gamemaster = game["gamemaster"] == player_name gamemaster_has_closed = game["gamemaster"] is None winner_name = get_game_winner(self.db_conn, game_id) # If there is no current winner, return an error if not winner_name: raise APIError(409, log_message="The game currently has no winner.") # Otherwise, clean up everything else: # We want the gamemaster to FIRST to do the cleanup if is_gamemaster: # Record the win for the player who won winner = get_player(self.db_conn, winner_name) winner["games_won"] += [game_id] game["winner"] = winner_name # Remove all players from game for pname in game["players"]: p = get_player(self.db_conn, pname) p["balls"] = [] p["orig_balls"] = [] # Clear the game's "current" attributes game["players"] = [] game["gamemaster"] = None # Remove the gamemaster's current_game_id player["current_game_id"] = None # Then the remainder of the players can truly leave the game # so they have a chance to query who the winner was from GameState # before having their current_game_id set to None elif gamemaster_has_closed: player["current_game_id"] = None return "Game {} was completed; {} was the winner.".format( game_id, winner_name)
def __update_policy(dataset, request_data): policy = request_data[DATASET.POLICY] if policy == POLICY.AGE and DATASET.MAX_AGE in request_data: dataset[DATASET.POLICY] = policy remove_keys_from_dict(dataset, [DATASET.MAX_SIZE]) retention = str(request_data[DATASET.MAX_AGE]) dataset[DATASET.MAX_AGE] = request_data[DATASET.MAX_AGE] elif policy == POLICY.SIZE and DATASET.MAX_SIZE in request_data: dataset[DATASET.POLICY] = policy retention = str(request_data[DATASET.MAX_SIZE]) remove_keys_from_dict(dataset, [DATASET.MAX_AGE]) dataset[DATASET.MAX_SIZE] = request_data[DATASET.MAX_SIZE] else: raise APIError(400, log_message="Not a valid request") return retention
def _wrapper(self, *args, **kwargs): validation_ruleset = getattr(self, "validation_ruleset") input_schema = create_object_schema_from_validation_ruleset(validation_ruleset) if input_schema is not None: try: encoding = "UTF-8" input_ = json.loads(self.request.body.decode(encoding)) except ValueError: raise jsonschema.ValidationError( "Input is malformed; could not decode JSON object." ) if use_defaults: input_ = input_schema_clean(input_, input_schema) jsonschema.validate( input_, input_schema, cls=validator_cls, format_checker=format_checker ) else: input_ = None setattr(self, "body", input_) output = rh_method(self, *args, **kwargs) if is_future(output): output = yield output if not output and on_empty_404: raise APIError(404, "Resource not found.") if output_schema is not None: try: jsonschema.validate( {"result": output}, { "type": "object", "properties": { "result": output_schema }, "required": ["result"] } ) except jsonschema.ValidationError as error: raise TypeError(str(error)) self.success(output)
def __update_dataset(self, dataset, request_data): logging.info(u'Update request for api:{%s} received', dataset) retention = "" # Handle policy change # When time permits, refactor this one.Violates DRY if DATASET.POLICY in request_data: retention = self.__update_policy(dataset, request_data) # Handle mode change if DATASET.MODE in request_data: if request_data[DATASET.MODE] in MODE_ENUM_LIST: dataset[DATASET.MODE] = request_data[DATASET.MODE] else: raise APIError( 400, log_message="Not a valid request with invalid mode") self.__persist_dataset(dataset, retention) raise Return(dataset)
def put(self): """ PUT the required parameters to permanently register a new player * `username` * `first`: First name * `last`: Last name * `password`: Password for future logins * `gender`: M/F * `birthday`: e.g., "1993-05-16" * `city` * `country` * `bio` """ attrs = dict(self.body) # Set salt and password salt = bcrypt.gensalt(rounds=12) attrs['password'] = bcrypt.hashpw( password=attrs['password'].encode(), salt=salt ).decode() attrs['salt'] = salt.decode() # Create player with db_session: api_assert( attrs['username'], 400, log_message="Provided username is empty!" ) if PlayerEntity.get(username=attrs['username']): raise APIError( 409, log_message="Player with username {} already exists!" .format(attrs['username']) ) player = PlayerEntity(**attrs) # Log the user in self.set_secure_cookie( "user", attrs['username'], self.settings['app_config'].session_timeout_days ) return {"username": player.username}
def get_team_rankings(myteam, filter_for_matchmaking=True): team_name = myteam.name sport_name = myteam.sport.name if myteam is None: raise APIError( 400, log_message="Team with name {} does not exist!".format(team_name)) ### Figure out rival team # Find teams that are of the same sport and also # that they don't contain any players from myteam sport_teams = select(team for team in TeamEntity if team.sport.name == sport_name)[:] print sport_teams, [[player.username for player in team.users] for team in sport_teams] if filter_for_matchmaking: myteam_names = [player.username for player in myteam.users] print myteam_names sport_teams = [ team for team in sport_teams if all( player.username not in myteam_names for player in team.users) ] print sport_teams sport_teams.append(myteam) num_teams = len(sport_teams) api_assert(num_teams > 1, 409, "There are no other teams with all different people!") overall_rankings = defaultdict(lambda: 0) teams_wlratio = sorted([(team, float(team.wins) / (team.losses or 1)) for team in sport_teams], key=lambda t: t[1], reverse=True) for i, (team, wlratio) in enumerate(teams_wlratio): overall_rankings[team.name] += i teams_pointsratio = sorted([(team, team.points_ratio) for team in sport_teams], key=lambda t: t[1], reverse=True) for i, (team, points_ratio) in enumerate(teams_pointsratio): overall_rankings[team.name] += i return overall_rankings
def post(self): """POST the required credentials to get back a cookie * `username`: Username * `password`: Password """ player_name = self.body["username"] password = self.body["password"] player = get_player(self.db_conn, player_name, err_code=400) # Check if the given password hashed with the player's known # salt matches the stored password password_match = bcrypt.hashpw(str(password), str( player["salt"])) == player['password'] if password_match: self.set_secure_cookie("user", player_name, options.session_timeout_days) return {"username": player_name} else: raise APIError(400, log_message="Bad username/password combo")
def put(self): """ PUT to create a team * `name` * `usernames`: list of players in team (INCLUDING YOURSELF!!) * `sport`: One of "Basketball" or "Soccer" """ attrs = dict(self.body) with db_session: if TeamEntity.get(name=attrs['name']): raise APIError( 409, log_message="Team with name {} already exists!".format( attrs['name'])) # Add team mates players = [] for pname in attrs["usernames"]: player = PlayerEntity.get(username=pname) api_assert( player is not None, 400, log_message="No player exists with name {}!".format(pname)) players.append(player) # Get sport sport = SportEntity[attrs['sport']] # Create team team = TeamEntity(name=attrs['name'], users=players, sport=sport, wins=0, losses=0, ties=0, points_ratio=0.0) return {'name': team.name}
def post(self): """(Game host only) Update date and location of game * `date`: Must be in YYYY-MM-DD format * `location` * `id`: ID of game to change """ attrs = dict(self.body) with db_session: game = GameEntity.get(id=attrs['id']) api_assert(game is not None, 400, log_message="No such game {} exists!".format( attrs['id'])) api_assert(game.host.username == self.get_current_user(), 403, log_message="Only the host of this game may edit it!") try: validate_date_text(attrs['date']) except ValueError as err: raise APIError(400, log_message=str(err)) game.location = attrs['location'] game.date = attrs['date'] commit() game_dict = { k: v for k, v in game.to_dict().items() if k in ["id", "date", "location"] } game_dict["date"] = str(game_dict["date"]) return game_dict
def delete(self): try: self.benchmark_service.kill_current_benchmark() except BenchmarkException as e: raise APIError(400, e.message) self.success("ok")
def post(self): try: self.benchmark_service.start_new_benchmark() except BenchmarkException as e: raise APIError(400, e.message) return "ok"