From 46cfa0f92b3c93b75d9b0c961850b6bdcf97aa2e Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Fri, 28 Jan 2022 14:36:33 -0800 Subject: [PATCH] Added kick and admin Signed-off-by: James Ketrenos --- server/app.js | 6 +++ server/kick | 13 +++++ server/routes/games.js | 108 +++++++++++++++++++++++++++-------------- 3 files changed, 90 insertions(+), 37 deletions(-) create mode 100755 server/kick diff --git a/server/app.js b/server/app.js index 05c1ada..271a76b 100755 --- a/server/app.js +++ b/server/app.js @@ -92,6 +92,11 @@ app.use(session({ const index = require("./routes/index"); +if (config.has("admin")) { + const admin = config.get("admin"); + app.set("admin", admin); +} + if (config.has("admin.mail") && config.has("smtp.host") && config.has("smtp.sender")) { @@ -259,6 +264,7 @@ app.use(basePath, function(req, res, next) { /* Everything below here requires a successful authentication */ app.use(basePath, express.static(frontendPath, { index: false })); + app.use(basePath + "api/v1/games", require("./routes/games")); /* Declare the "catch all" index route last; the final route is a 404 dynamic router */ diff --git a/server/kick b/server/kick new file mode 100755 index 0000000..43099d0 --- /dev/null +++ b/server/kick @@ -0,0 +1,13 @@ +#!/bin/bash +ADMIN="ui2qNb8PYo6NaPVcLuFXx2nQD6U7Alsm" + +id=$1 +user=$2 + +curl --noproxy '*' -s -L \ + --request PUT \ + --header "PRIVATE-TOKEN: ${ADMIN}" \ + --header "Content-Type: application/json" \ + http://localhost:8930/ketr.ketran/api/v1/games/${id}/kick/${user} | + jq .status + diff --git a/server/routes/games.js b/server/routes/games.js index 64d1b37..6cd1d04 100755 --- a/server/routes/games.js +++ b/server/routes/games.js @@ -129,20 +129,72 @@ const roll = (game, player) => { return error; } -router.put("/:id/:action/:value?", (req, res) => { - console.log(`PUT games/${req.params.id}/${req.params.action}`); - if (!(req.params.id in games)) { - const error = `Game not found: ${req.params.id}`; +const loadGame = async (id) => { + if (/^\.|\//.exec(id)) { + return undefined; + } + + if (id in games) { + return games[id]; + } + + const game = await readFile(`games/${id}`) + .catch(() => { + return; + }); + + if (!game) { + return undefined; + } + + games[id] = JSON.parse(game); + + return games[id]; +}; + +router.put("/:id/:action/:value?", async (req, res) => { + const { action, id, value } = req.params; + console.log(`PUT games/${id}/${action}/${value}`); + + const game = await loadGame(id); + if (!game) { + const error = `Game not found and cannot be created: ${id}`; return res.status(404).send(error); } - const game = games[req.params.id], - color = req.session && req.session.playerColor in game.players ? req.session.playerColor : undefined; + const color = req.session && req.session.playerColor in game.players ? + req.session.playerColor : undefined; let player; let error; - if (req.params.action == "player-name") { + if ('private-token' in req.headers) { + if (req.headers['private-token'] !== req.app.get('admin')) { + error = `Invalid admin credentials.`; + } + switch (action) { + case "kick": + error = `Unable to find player ${value}` + for (let color in game.players) { + player = game.players[color]; + if (player.name.toLowerCase() === value.toLowerCase()) { + console.log(`Kicking ${value} from ${id}.`); + game.chat.push({ date: Date.now(), message: `${player.name} has been kicked from game.` }); + player.session = ''; + player.name = ''; + player.status = 'Not active'; + player.lastActive = 0; + error = undefined; + break; + } + } + break; + } + + return sendGame(res, req, game, error); + } + + if (action == "player-name") { const name = req.params.value; if (!name) { error = `No name provided`; @@ -151,7 +203,7 @@ router.put("/:id/:action/:value?", (req, res) => { error = `You cannot change your name while you are in game.`; } else { if (game) for (let key in game.players) { - if (game.players[key].name === name) { + if (game.players[key].name.toLowerCase() === name.toLowerCase()) { error = `${name} is already taken by ${key}`; } } @@ -167,7 +219,7 @@ router.put("/:id/:action/:value?", (req, res) => { return sendGame(res, req, game, error); } - if (req.params.action == "player-selected") { + if (action == "player-selected") { if (!game) { error = `No game found`; return sendGame(res, req, game, error); @@ -243,7 +295,7 @@ router.put("/:id/:action/:value?", (req, res) => { player = game.players[req.session.playerColor]; const name = player.name; - switch (req.params.action) { + switch (action) { case "roll": error = roll(game, player); break; @@ -275,36 +327,18 @@ router.put("/:id/:action/:value?", (req, res) => { }) router.get("/:id", async (req, res/*, next*/) => { - const id = req.params.id; + const { id } = req.params; console.log("GET games/" + id); - let error, game; + let error; - if (id in games) { - game = games[id]; + const game = await loadGame(id); + if (game) { return sendGame(res, req, game) } - if (/^\.|\//.exec(id)) { - error = `Requested game ID is invalid`; - console.log(error, id); - return res.status(400).send(error); - } - - game = await readFile(`games/${id}`) - .catch(() => { - return; - }); - - if (!game) { - error = `Game ${id} not found -- returning invalid game state.`; - console.warn(error); - game = { id: id, state: 'invalid' }; - } else { - game = JSON.parse(game); - } - - games[id] = game; - return sendGame(res, req, game, error); + error = `Game ${id} not found -- returning invalid game state.`; + console.warn(error); + return sendGame(res, req, { id: id, state: 'invalid' }, error); }); router.put("/:id", (req, res/*, next*/) => { @@ -360,7 +394,7 @@ const sendGame = async (res, req, game, error) => { await writeFile(`games/${game.id}`, JSON.stringify(game, null, 2)) .catch((error) => { - console.error(`Unable to write to games/${games.id}`); + console.error(`Unable to write to games/${game.id}`); console.error(error); }); const playerGame = Object.assign({}, game, { @@ -377,7 +411,7 @@ const sendGame = async (res, req, game, error) => { router.post("/:id?", (req, res/*, next*/) => { console.log("POST games/"); - const id = req.params.id; + const { id } = req.params; if (id && id in games) { const error = `Can not create new game for ${id} -- it already exists.` console.error(error);