async def join( game: GameBaseJoin, session: Session = Depends(get_session), user: UserBaseSession = Depends(JWTBearer()) ) -> Message: """Join game request""" TokenValidator.check_token(session, user.id) # Check if user is in another game db_game = ControllerGame.get_by_username(session, user.username) if db_game is not None: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="User is in another game.") # Fetch game object db_game = ControllerGame.get_by_id(session, game.id) # Check if given game id is valid if db_game is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Invalid game id.") # Check if game has open place for joining if db_game.second_user_id is not None: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Game is full.") # Check if game has password -> Verify password if db_game.password is not None: if game.password is None or Security.verify_pwd(game.password, db_game.password) is False: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid password.") ControllerGame.join(session, game.id, user.id) return Message(detail="Joining is successful.")
async def turn(self, turn: WebsocketTurn) -> None: """Process turn info""" self.session.refresh(self.game) # Check if it is user's turn to act if self.game.turn != self.user.id: # Turn is not on this user await WebsocketManager.send(self.user.id, WebsocketResponse(type=WebsocketResponseEnum.INVALID, status=status.HTTP_400_BAD_REQUEST).dict()) return # Fetch boards of users other_user_id = ControllerGame.get_other_user_id(self.game, self.user.id) self_board = GameManager.get_board(self.user.id) other_board = GameManager.get_board(other_user_id) if self_board is None or other_board is None: raise KeyError # Record hit response = WebsocketTurnResponse( type=WebsocketResponseEnum.TURN, status=status.HTTP_200_OK, hit=other_board.hit(turn.x, turn.y), x=turn.x, y=turn.y ) await WebsocketManager.send(self.user.id, response.dict()) await WebsocketManager.send(other_user_id, response.dict()) # Change turn await self.send_turn(other_user_id) self.session.commit()
async def message(self, message: WebsocketMessage) -> None: """Process incoming messages from users""" self.session.refresh(self.game) other_user_id = ControllerGame.get_other_user_id(self.game, self.user.id) if other_user_id is not None: await WebsocketManager.send(other_user_id, message.dict()) await WebsocketManager.send(self.user.id, WebsocketResponse(type=WebsocketResponseEnum.MESSAGE, status=status.HTTP_200_OK).dict())
async def create( game: GameBaseCreate, session: Session = Depends(get_session), user: UserBaseSession = Depends(JWTBearer()) ) -> GameBaseCreateResponse: """Create game request""" TokenValidator.check_token(session, user.id) # Check if user is in another game db_game = ControllerGame.get_by_username(session, user.username) if db_game is not None: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="User is in another game.") if game.name is None: game.name = f"{user.username}'s Game" if game.password is not None: game.password = Security.get_pwd_hash(game.password) db_game = ControllerGame.create(session, game, user.id) return GameBaseCreateResponse(id=db_game.id)
async def get( game_id: int = Path(..., ge=0), session: Session = Depends(get_session), user: UserBaseSession = Depends(JWTBearer()) ) -> Any: """Get info on given game""" TokenValidator.check_token(session, user.id) return ControllerGame.get(session, game_id)
async def list( game_params: GameBaseList, session: Session = Depends(get_session), user: UserBaseSession = Depends(JWTBearer()) ) -> List[Games]: """List games""" TokenValidator.check_token(session, user.id) game_list = ControllerGame.list(session, game_params) for game in game_list: if game.password is None: game.with_password = False else: game.with_password = True return game_list
async def authorize_user(self, token: WebsocketToken) -> None: """Authorize user to websocket connection -> This must be the first action in websocket""" # Check if token is valid self.user = TokenValidator.authorize_socket(token) TokenValidator.check_token(self.session, self.user.id) # Check if user is in a game self.game = ControllerGame.get_by_user_id(self.session, self.user.id) if self.game is None: raise KeyError(f"User({self.user.id}) is not in a game.") WebsocketManager.add_connection(self.user.id, self.websocket) self.authenticated = True # Check if user is secondary player -> Notify game creator if self.game.second_user_id == self.user.id: user_in = WebsocketUser(type=WebsocketResponseEnum.USER_IN, username=self.game.second_user.username) await WebsocketManager.send(self.game.creator_user_id, user_in.dict()) # Return token response that authentication is successful await WebsocketManager.send(self.user.id, WebsocketResponse(type=WebsocketResponseEnum.TOKEN, status=status.HTTP_200_OK).dict())