From ec2d68539f467ed342a632f2cf66e7b32b909f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20W=C4=85sowski?= Date: Sat, 29 Apr 2023 13:12:52 +0200 Subject: [PATCH] Modify game (#36) This is a replacement for #34 --------- Co-authored-by: aetn23 --- src/app.ts | 3 ++ src/routes/modifyGame.ts | 95 ++++++++++++++++++++++++++++++++++++ src/tests/modifyGame.test.ts | 95 ++++++++++++++++++++++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100644 src/routes/modifyGame.ts create mode 100644 src/tests/modifyGame.test.ts diff --git a/src/app.ts b/src/app.ts index 9260dab..aec5eca 100644 --- a/src/app.ts +++ b/src/app.ts @@ -4,6 +4,7 @@ import { isCelebrateError } from 'celebrate' import kickPlayer from './routes/kickPlayer' import joinGame from './routes/joinGame' import createGame from './routes/createGame' +import modifyGame from './routes/modifyGame' import leaveGame from './routes/leaveGame' import { rateLimiter } from './utils/rateLimiter' @@ -48,6 +49,8 @@ app.use(joinGame) app.use(createGame) +app.use(modifyGame) + app.use(kickPlayer) app.use(leaveGame) diff --git a/src/routes/modifyGame.ts b/src/routes/modifyGame.ts new file mode 100644 index 0000000..ca42c26 --- /dev/null +++ b/src/routes/modifyGame.ts @@ -0,0 +1,95 @@ +import { getClient } from '../utils/databaseConnection' +import { rateLimiter } from '../utils/rateLimiter' +import { celebrate, Joi, Segments } from 'celebrate' +import { sendFirebaseMessage, verifyFCMToken } from '../utils/firebase' + +import express, { type Router } from 'express' +const router: Router = express.Router() + +router.post( + '/modifyGame', + rateLimiter, + celebrate({ + [Segments.QUERY]: Joi.object().keys({ + creatorToken: Joi.string() + .required() + .min(1) + .max(250) + .label('creatorToken'), + smallBlind: Joi.number().required().min(1).label('smallBlind'), + startingFunds: Joi.number().required().min(1).label('startingFunds'), + }), + }), + async (req, res) => { + if (!(await verifyFCMToken(req.query.creatorToken))) { + return res.sendStatus(400) + } + + const client = getClient() + client + .connect() + .then(async () => { + // Define queries + const getGameQuery = 'SELECT game_id FROM Games WHERE game_master=$1' + const getCurrentPlayerQuery = + 'SELECT current_player FROM Games WHERE game_id=$1 AND current_player IS NOT NULL' + const setNewSmallBlindStartingFunds = + 'UPDATE Games SET small_blind=$1, starting_funds=$2 WHERE game_id=$3' + const getPlayersQuery = 'SELECT token FROM Players WHERE game_id=$1' + + // Check if games exist + const getGameResult = await client.query(getGameQuery, [ + req.query.creatorToken, + ]) + + if (getGameResult.rowCount === 0) { + return res.sendStatus(400) + } + const gameId = getGameResult.rows[0].game_id + + // Check if the game has not started yet + const getCurrentPlayerResult = await client.query( + getCurrentPlayerQuery, + [gameId] + ) + if (getCurrentPlayerResult.rowCount !== 0) { + return res.sendStatus(400) + } + + // Update settings + await client.query(setNewSmallBlindStartingFunds, [ + req.query.smallBlind, + req.query.startingFunds, + gameId, + ]) + + // Notify players about the changes + const getPlayersResult = await client.query(getPlayersQuery, [gameId]) + + const message = { + data: { + type: 'settingsUpdated', + startingFunds: req.query.startingFunds, + smallBlind: req.query.smallBlind, + }, + token: '', + } + + getPlayersResult.rows.forEach(async (row) => { + message.token = row.token + await sendFirebaseMessage(message) + }) + + return res.sendStatus(200) + }) + .catch(async (err) => { + console.log(err.stack) + return res.sendStatus(500) + }) + .finally(async () => { + await client.end() + }) + } +) + +export default router diff --git a/src/tests/modifyGame.test.ts b/src/tests/modifyGame.test.ts new file mode 100644 index 0000000..01fe73f --- /dev/null +++ b/src/tests/modifyGame.test.ts @@ -0,0 +1,95 @@ +import { app } from '../app' +import request from 'supertest' +import { getClient } from '../utils/databaseConnection' + +test('Modify game, wrong args', async () => { + const client = getClient() + const insertGameCreator = + 'INSERT INTO Players (token, nickname, turn) VALUES ($1, $2, $3)' + const deletePlayerQuery = 'DELETE FROM Players WHERE token = $1' + await client + .connect() + .then(async () => { + await request(app).post('/modifyGame').expect(400) + await request(app).post('/modifyGame?creatorToken=2137').expect(400) + + await client.query(insertGameCreator, [2137, '2137', 0]) + + await request(app).post('/modifyGame?creatorToken=2137').expect(400) + await request(app) + .post('/modifyGame?creatorToken=2137&smallBlind=asd') + .expect(400) + await request(app) + .post('/modifyGame?creatorToken=2137&startingFunnds=dasdasd') + .expect(400) + await request(app) + .post('/modifyGame?creatorToken=2137&startingFunds=1&smallBlind=220') + .expect(400) + }) + .finally(async () => { + await client.query(deletePlayerQuery, [2137]) + await client.end() + }) +}) + +test('Modify game, correct arguments', async () => { + const gameMasterToken = 'TESTMODIFY' + const gameMasterNick = 'MODIFYNICK' + const newSmallBlind = 2137 + const newStartingFunds = 1337 + const findGameQuery = 'SELECT game_id FROM Games WHERE game_master=$1' + const deleteGameQuery = 'DELETE FROM Games WHERE game_id=$1' + const verifyGameWasModifiedQuery = + 'SELECT game_id FROM Games WHERE game_id=$1 AND small_blind=$2 AND starting_funds=$3' + const deletePlayerQuery = 'DELETE FROM Players WHERE token = $1' + let gameId + + const client = getClient() + await client.connect() + + await request(app) + .get( + '/createGame?creatorToken=' + .concat(gameMasterToken) + .concat('&nickname=') + .concat(gameMasterNick) + ) + .expect(200) + + await request(app) + .post( + '/modifyGame?creatorToken=' + .concat(gameMasterToken) + .concat('&smallBlind=') + .concat(newSmallBlind.toString()) + .concat('&startingFunds=') + .concat(newStartingFunds.toString()) + ) + .expect(200) + + await client + .query(findGameQuery, [gameMasterToken]) + .then(async (result) => { + gameId = result.rows[0].game_id.toString() + + await client + .query(verifyGameWasModifiedQuery, [ + gameId, + newSmallBlind, + newStartingFunds, + ]) + .then(async (modified) => { + expect(modified.rowCount).toEqual(1) + }) + }) + + .finally(async () => { + await client.query(deleteGameQuery, [gameId]).catch((err) => { + console.log(err.stack) + }) + await client.query(deletePlayerQuery, [gameMasterToken]).catch((err) => { + console.log(err.stack) + }) + await client.end() + }) +})