Пример #1
0
def get_claims(security_scopes: SecurityScopes, token: str = Depends(oauth2_scheme)):
    if security_scopes.scopes:
        authenticate_value = f'Bearer scope="{security_scopes.scope_str}"'
    else:
        authenticate_value = f"Bearer"
    try:
        claims = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.TOKEN_ALGORITHM])
        token = TokenSchema.parse_obj(claims)
        if token.type != TokenType.access:
            raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Requires access token")

    except JWTError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Could not validate credentials",
            headers={"WWW-Authenticate": authenticate_value},
        )
    logger.debug(f"Required scope: {security_scopes.scopes}, Token Scopes: {token.scopes}")
    for scope in security_scopes.scopes:
        if scope not in token.scopes:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Insufficient permissions",
                headers={"WWW-Authenticate": authenticate_value},
            )
    return claims
Пример #2
0
def get_room(room_id):
    try:
        room = Room.get(room_id)
        logger.debug(room)
        return room
    except InstanceNotFound:
        raise HTTPException(status_code=404, detail="Could not find lobby")
Пример #3
0
 async def on_join(self, sid: PlayerSID, msg: JoinMessage) -> None:
     """
     Player requests to join a game room
     """
     # TODO: Fix join ID
     identity = {"id": "FIXME"}
     player: Player = Player.create(
         name=msg.name,
         room=msg.roomid,
         user_id=identity["id"] if identity is not None else None,
         sid=sid,
     )
     logger.debug("Player requested to join a room")
     player_id = player.id
     try:
         room: Room = Room.get(msg.roomid)
     except InstanceNotFound as e:
         raise NoSuchRoom from e
     if room.status != "lobby":
         raise GameAlreadyStarted
     elif room.private:
         raise NoSuchRoom
     else:
         logger.debug(f"Registering user")
         await RegisterMessage(roomid=msg.roomid,
                               playerid=player_id).send(self,
                                                        to=room.server_sid)
Пример #4
0
    def make_move(self, player_id: PlayerId, player_role: Optional[GameRole], move: Move):
        logger.debug(f"Making move for role: {player_role}")
        col: int = move["col"]
        row: int = move["row"]
        grid: List[List[Optional[GameRole]]] = self.board["grid"]
        if grid[row][col] is not None:
            raise IllegalMove(details="Attempted to play in square that is already occupied")
        grid[row][col] = player_role

        if (
            all(grid[row][i] == player_role for i in range(3))
            or all(grid[i][col] == player_role for i in range(3))
            or all(grid[i][i] == player_role for i in range(3))
            or all(grid[i][2 - i] == player_role for i in range(3))
        ):
            # Player won
            self.winner = player_id
            raise GameCompleted
        elif all(cell is not None for row in grid for cell in row):
            # Match is a draw
            self.winner = None
            raise GameCompleted
        else:
            next_role = player_o if player_role == player_x else player_x
            self.turn = self.roles[next_role]
Пример #5
0
 async def callback(self, msgtype=None, *args):
     if msgtype == "fail":
         error = args[0]
         raise all_exceptions[error["error"]](
             f"{error['details']!r},\nReceived in response to: {self!r}")
     elif self._callback:
         logger.debug(f"Recv Callback: msgtype={msgtype!r}, args={args!r}")
         await self._callback(*args)
Пример #6
0
    async def on_playermove(self, msg: PlayerMoveMessage):
        """
        Player sends a move
        """
        with self.lock:
            assert self.room_id is not None
            try:
                logger.debug("Starting player move")
                self.game.move(msg.playerid, msg.move)
                logger.debug("Finished player move")
                await GameUpdateMessage(
                    visibility="broadcast",
                    roomid=msg.roomid,
                    board=self.game.show_board(),
                    turn=self.game.turn,
                    epoch=self.game.movenumber,
                    stateid=msg.stateid,
                ).send(sio=self)
            except GameCompleted:
                self.game.playing = False
                await GameUpdateMessage(
                    visibility="broadcast",
                    roomid=msg.roomid,
                    board=self.game.show_board(),
                    turn=None,
                    epoch=self.game.movenumber,
                    stateid=msg.stateid,
                    finish=Finish(
                        normal=True,
                        scores=self.game.score(),
                    ),
                ).send(sio=self)

                if settings.RUN_ONCE:
                    await self.disconnect()
                else:
                    self.game = all_games[self.game_name]()
                    await self.initialize()

            except IllegalMove as e:
                logger.exception(e)
                await GameUpdateMessage(
                    roomid=self.room_id,
                    visibility="broadcast",
                    epoch=self.game.movenumber,
                    board=self.game.show_board(),
                    turn=None,
                    finish=Finish(
                        normal=False,
                        reason=e.details,
                        fault=msg.playerid,
                        scores={
                            p: (-1 if p == msg.playerid else 1)
                            for p in self.game.players
                        },
                    ),
                ).send(sio=self)
Пример #7
0
 def get_move(self) -> Move:
     assert self.board is not None
     assert self.gamerole is not None
     player_pits = self.board[f"pits_{self.gamerole}"]
     legal_moves = [{
         "move": idx
     } for idx, pits in enumerate(player_pits) if pits > 0]
     logger.debug(self.board)
     if logger.isEnabledFor(logging.DEBUG):
         sleep(1.5)
     return Move(random.choice(legal_moves))
Пример #8
0
 async def on_createroom(self, sid: GameServerSID,
                         msg: CreateRoomMessage) -> None:
     """
     Server requests to create a game room
     """
     room = Room.create(name=msg.name,
                        game=msg.game,
                        maxplayers=msg.maxplayers,
                        server_sid=sid)
     logger.debug(f"Registered Gameserver with room: {room.id}")
     await RoomCreatedMessage(roomid=room.id).send(self, to=sid)
Пример #9
0
 def update(self, board: Board, turn: Optional[PlayerId] = None) -> Optional[Move]:
     """
     Can be overridden to do processing even when not the player's turn
     Also can be overridden if players want to keep track of previous states
     :param turn: ID of player who'd turn it is
     :param board: New board state
     """
     self.board = board
     if turn == self.player_id and turn is not None:
         logger.debug("Our move to play")
         return self.get_move()
     else:
         return None
Пример #10
0
 def make_move(self, player_id: PlayerId, player_role: Optional[GameRole],
               move: Move):
     m: str = move["move"]
     if m not in ["scissors", "paper", "rock"]:
         raise ValueError
     logger.debug(f"Player Role: {player_role}")
     if player_role == player_a:
         self.board[player_a] = m
         self.turn = self.roles[player_b]
     elif m == self.board[player_b]:
         self.board = Board({player_a: None, player_b: None})
         self.turn = self.roles[player_a]
     else:
         self.board[player_b] = m
         raise GameCompleted
Пример #11
0
 async def send(self,
                sio,
                to: Optional[SioSID] = None,
                callback: Optional[Callable] = None):
     message_name = self.__class__.__name__[:-7].lower()
     self._callback = callback
     if to is None:
         logger.debug(f"Sending message {message_name}:\n{self!r}")
         await sio.emit(message_name,
                        self.to_dict(),
                        callback=self.callback)
     else:
         logger.debug(
             f"Sending message {message_name} to {to!r}:\n{self!r}")
         await sio.emit(message_name,
                        self.to_dict(),
                        room=to,
                        callback=self.callback)
Пример #12
0
def refresh(response: Response, refresh_token: Optional[str] = Cookie(None)):
    if refresh_token is None:
        logger.debug("No refresh token")
        return {"success": False}
    try:
        claims = jwt.decode(refresh_token,
                            settings.SECRET_KEY,
                            algorithms=[settings.TOKEN_ALGORITHM])
        if claims["type"] != "refresh":
            logger.warning("Attempted refresh with not refresh token")
            return {"success": False}
        try:
            user = User.get(claims["sub"])
            return set_tokens(response, user)
        except InstanceNotFound:
            logger.warning(
                f"User from refresh token not found: {claims['sub']}")
            return {"success": False}
    except JWTError as e:
        logger.warning(f"JWT Error in refresh token: {e!r}")
        return {"success": False}
Пример #13
0
        async def wrapper(sio: SocketioType, *args):
            if len(args) == 1:
                [data] = args
                sid = None
            else:
                [sid, data] = args
            if data is None:
                data = dict()
            m = {k: v for k, v in data.items() if v is not None}
            try:
                msg = message_type.parse_obj(m)
            except ValidationError as e:
                logger.debug(
                    f"Receieved invalid data:\n{json.dumps(data, indent=2)}")
                logger.warning(
                    f"Validation encountered for {f.__name__}: {e!r}")
                return (
                    "fail",
                    {
                        "error": "InputValidationError",
                        "details": e.json(),
                    },
                )

            try:
                if sid is None:
                    await f(sio, msg=msg)
                else:
                    return await f(sio, sid=sid, msg=msg)

            except AsimovErrorBase as e:
                logger.exception(e)
                return (
                    "fail",
                    {
                        "error": e.__class__.__name__,
                        "details": e.details,
                    },
                )
Пример #14
0
def add_player(bot: Bot, tournament: Tournament) -> Participant:
    logger.debug("Getting tournament lock: %s", tournament.id)
    with tournament.lock():
        logger.debug("Got lock for tournament: %s", tournament.id)
        participants = tournament.participants
        participant_ids = {participant.bot.id for participant in participants}
        if bot.id in participant_ids:
            raise AlreadyInTournament
        index = max(x.index for x in participants) + 1 if participants else 1
        participant = Participant.create(index=index,
                                         bot=bot,
                                         tournament=tournament)
        for opponent in participants:
            if opponent.disqualified:
                continue
            Match.create(
                index=100000 * index + opponent.index,
                tournament=tournament,
                players=[participant, opponent],
                state=MatchState.pending,
            )
        return participant
Пример #15
0
 def asign_role(self, player_id: PlayerId) -> Optional[GameRole]:
     logger.debug(f"Currently assigned roles: {self.roles}")
     available = list({player_o, player_x} - set(self.roles))
     logger.debug(f"Available roles: {available}")
     role = random.choice(available)
     logger.debug(f"Assigning role {player_id} -> {role}")
     self.players[player_id] = role
     self.roles[role] = player_id
     return role
Пример #16
0
 def show_board(self) -> Board:
     board_repr = "\n -+-+-\n ".join(
         "|".join(" " if cell is None else cell for cell in row) for row in self.board["grid"]
     )
     logger.debug(f"Board:\n {board_repr}")
     return self.board
Пример #17
0
 async def on_gameupdate(self, sid: GameServerSID,
                         msg: GameUpdateMessage) -> None:
     """
     Server notifies of a game state change
     """
     if msg.visibility == "private":
         if msg.playerid is None:
             raise InputValidationError(
                 details=
                 "error: 'playerid' must be provided when visibility is private"
             )
     else:
         if msg.playerid is not None:
             raise InputValidationError(
                 details=
                 "error: 'playerid' cannot be provided unless visibility is private"
             )
         if msg.epoch is None:
             raise InputValidationError(
                 details=
                 "error: 'epoch' is required for non-private messages")
     room, player = get_room_player(sid, msg.roomid, msg.playerid)
     with room.lock(timeout=0.5, sleep=0.02):
         if msg.finish is not None:
             logger.info("Game finished")
             await GamestateMessage.parse_obj(msg.to_dict()
                                              ).send(self,
                                                     to=room.broadcast_sid)
             room.update(status="finished")
         new_status = "finished" if room.status == "finished" else "playing"
         if msg.visibility == "private":
             room.update(status=new_status, turn=msg.turn)
             assert player is not None
             await GamestateMessage(
                 board=msg.board,
                 turn=msg.turn,
                 roomid=msg.roomid,
                 playerid=msg.playerid,
                 epoch=msg.epoch,
             ).send(self, to=player.sid)
         else:
             if room.status == "finished":
                 room.update(board=msg.board, turn=None)
             else:
                 room.update(status=new_status, turn=msg.turn)
             if msg.visibility == "broadcast":
                 r = GamestateMessage(
                     board=msg.board,
                     turn=msg.turn,
                     roomid=msg.roomid,
                     playerid=msg.playerid,
                     epoch=msg.epoch,
                 )
                 logger.debug(
                     f"room.id={room.id}, room.broadcast_sid={room.broadcast_sid}"
                 )
                 await r.send(sio=self, to=room.broadcast_sid)
             try:
                 state = GameState.get(msg.stateid)
                 if state.room is not None and state.room.id != msg.roomid:
                     raise InstanceNotFound
             except InstanceNotFound:
                 state_args = {
                     "room_id": msg.roomid,
                     "epoch": msg.epoch,
                     "board": msg.board,
                     "turn": msg.turn,
                 }
                 GameState.create(
                     **{k: v
                        for k, v in state_args.items() if v is None})
             else:
                 state.update(epoch=msg.epoch,
                              board=msg.board,
                              turn=msg.turn)
             room.update(
                 status=new_status,
                 board=msg.board,
                 turn=msg.turn,
             )