1
0

Remove use of sessionParser and build cookies directly

Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
James Ketrenos 2022-03-13 14:08:32 -07:00
parent 94eb98ee37
commit 5db9139b5c
4 changed files with 62 additions and 119 deletions

View File

@ -225,6 +225,7 @@ const Table = () => {
}); });
}, [ gameId, setGameId ]); }, [ gameId, setGameId ]);
/* Once a game id is known, create the sole WebSocket connection /* Once a game id is known, create the sole WebSocket connection
* to the backend. This WebSocket is then shared with any component * to the backend. This WebSocket is then shared with any component
* that performs game state updates. Those components should * that performs game state updates. Those components should
@ -319,6 +320,39 @@ const Table = () => {
}; };
const App = () => { const App = () => {
const [playerId, setPlayerId] = useState(undefined);
const [error, setError] = useState(undefined);
useEffect(() => {
if (playerId) {
return;
}
window.fetch(`${base}/api/v1/games/`, {
method: 'GET',
cache: 'no-cache',
credentials: 'same-origin', /* include cookies */
headers: {
'Content-Type': 'application/json'
},
}).then((res) => {
if (res.status >= 400) {
const error = `Unable to connect to Ketr Ketran game server! ` +
`Try refreshing your browser in a few seconds.`;
console.error(error);
setError(error);
}
console.log(res.headers);
return res.json();
}).then((data) => {
setPlayerId(data.player);
}).catch((error) => {
});
}, [playerId, setPlayerId]);
if (!playerId) {
return <>{ error }</>;
}
return ( return (
<Router> <Router>
<Routes> <Routes>

View File

@ -8,22 +8,14 @@ const express = require("express"),
bodyParser = require("body-parser"), bodyParser = require("body-parser"),
config = require("config"), config = require("config"),
session = require('express-session'), session = require('express-session'),
hb = require("handlebars"),
SQLiteStore = require('connect-sqlite3')(session),
basePath = require("./basepath"), basePath = require("./basepath"),
cookieParser = require("cookie-parser"),
app = express(), app = express(),
fs = require('fs'); fs = require('fs');
let server; const server = require("http").createServer(app);
if (0) { app.use(cookieParser());
const key = fs.readFileSync("ssl/server-key.pem", "utf8"),
cert = fs.readFileSync("ssl/server-cert.pem", "utf8"),
credentials = { key, cert };
server = require("https").createServer(credentials, app);
} else {
server = require("http").createServer(app);
}
const ws = require('express-ws')(app, server); const ws = require('express-ws')(app, server);
@ -38,7 +30,6 @@ let userDB, gameDB;
app.use(bodyParser.json()); app.use(bodyParser.json());
/* App is behind an nginx proxy which we trust, so use the remote address /* App is behind an nginx proxy which we trust, so use the remote address
* set in the headers */ * set in the headers */
app.set("trust proxy", true); app.set("trust proxy", true);
@ -49,39 +40,6 @@ app.use(basePath, require("./routes/basepath.js"));
/* Handle static files first so excessive logging doesn't occur */ /* Handle static files first so excessive logging doesn't occur */
app.use(basePath, express.static(frontendPath, { index: false })); app.use(basePath, express.static(frontendPath, { index: false }));
/*
app.use(bodyParser.urlencoded({
extended: false
}));
*/
/* body-parser does not support text/*, so add support for that here */
if (0) app.use(function(req, res, next){
if (!req.is('text/*')) {
return next();
}
req.setEncoding('utf8');
let text = '';
req.on('data', function(chunk) {
text += chunk;
});
req.on('end', function() {
req.text = text;
next();
});
});
const sessionParser = session({
store: new SQLiteStore({ db: config.get("sessions.db") }),
secret: config.get("sessions.store-secret"),
cookie: { maxAge: 21 * 24 * 60 * 60 * 1000 }, // 3 weeks
saveUninitialized: false,
resave: true
});
app.use(sessionParser);
app.locals.sessionParser = sessionParser;
const index = require("./routes/index"); const index = require("./routes/index");
if (config.has("admin")) { if (config.has("admin")) {
@ -95,7 +53,6 @@ app.use(basePath, index);
/* /games loads the default index */ /* /games loads the default index */
app.use(basePath + "games", index); app.use(basePath + "games", index);
/* Allow access to the 'users' API w/out being logged in */ /* Allow access to the 'users' API w/out being logged in */
/* /*
const users = require("./routes/users"); const users = require("./routes/users");
@ -110,24 +67,6 @@ app.use(function(err, req, res, next) {
}); });
}); });
if (0) {
/* Check authentication */
app.use(basePath, function(req, res, next) {
return users.getSessionUser(req).then(function(user) {
if (user.restriction) {
return res.status(401).send(user.restriction);
}
req.user = user;
return next();
}).catch(function(error) {
return res.status(403).send(error);
});
});
}
/* Everything below here requires a successful authentication */
app.use(basePath, express.static(frontendPath, { index: false }));
app.use(`${basePath}api/v1/games`, require("./routes/games")); app.use(`${basePath}api/v1/games`, require("./routes/games"));
/* Declare the "catch all" index route last; the final route is a 404 dynamic router */ /* Declare the "catch all" index route last; the final route is a 404 dynamic router */

View File

@ -14,7 +14,7 @@
"body-parser": "^1.19.2", "body-parser": "^1.19.2",
"config": "^3.1.0", "config": "^3.1.0",
"connect-sqlite3": "^0.9.11", "connect-sqlite3": "^0.9.11",
"cookie-parser": "^1.4.4", "cookie-parser": "^1.4.6",
"core-js": "^3.2.1", "core-js": "^3.2.1",
"express": "^4.17.1", "express": "^4.17.1",
"express-session": "^1.17.1", "express-session": "^1.17.1",

View File

@ -437,17 +437,11 @@ const newPlayer = (color) => {
}; };
} }
const getSession = (game, reqSession) => { const getSession = (game, id) => {
if (!game.sessions) { if (!game.sessions) {
game.sessions = {}; game.sessions = {};
} }
if (!reqSession.player_id) {
throw Error(`No session id for ${game.id}`);
}
const id = reqSession.player_id;
/* If this session is not yet in the game, add it and set the player's name */ /* If this session is not yet in the game, add it and set the player's name */
if (!(id in game.sessions)) { if (!(id in game.sessions)) {
game.sessions[id] = { game.sessions[id] = {
@ -2803,7 +2797,7 @@ const ping = (session) => {
} }
const wsInactive = (game, req) => { const wsInactive = (game, req) => {
const session = getSession(game, req.session); const session = getSession(game, req.cookies.player);
if (session && session.ws) { if (session && session.ws) {
console.log(`Closing WebSocket to ${session.name} due to inactivity.`); console.log(`Closing WebSocket to ${session.name} due to inactivity.`);
@ -3086,19 +3080,6 @@ const sendWarning = (session, warning) => {
session.ws.send(JSON.stringify({ type: 'warning', warning })); session.ws.send(JSON.stringify({ type: 'warning', warning }));
} }
router.ws("/ws/:id", (ws, req) => {
/* Connect the WebSocket to the app's sessionParser */
req.app.locals.sessionParser(req, {}, () => {
if (!req.session.player_id) {
req.session.player_id = crypto.randomBytes(16).toString('hex');
console.log(`[${req.session.player_id.substring(0, 8)}]: wss - New session connected`);
} else {
console.log(`[${req.session.player_id.substring(0, 8)}]: wss - Existing session being used`);
}
wsConnect(ws, req);
});
});
const getFilteredPlayers = (game) => { const getFilteredPlayers = (game) => {
const filtered = {}; const filtered = {};
for (let color in game.players) { for (let color in game.players) {
@ -3117,13 +3098,16 @@ const getFilteredPlayers = (game) => {
return filtered; return filtered;
}; };
const wsConnect = async (ws, req) => { router.ws("/ws/:id", async (ws, req) => {
if (!req.cookies || !req.cookies.player) {
ws.send({ type: 'error', error: `Unable to set session cookie` });
return;
}
const { id } = req.params; const { id } = req.params;
const gameId = id; const gameId = id;
if (!req.session.player_id) {
throw new Error(`player_id not set from http load`); const short = `[${req.cookies.player.substring(0, 8)}]`;
}
const short = `[${req.session.player_id.substring(0, 8)}]`;
ws.id = short; ws.id = short;
console.log(`${short}: Game ${gameId} - New connection from client.`); console.log(`${short}: Game ${gameId} - New connection from client.`);
@ -3142,7 +3126,7 @@ const wsConnect = async (ws, req) => {
if (!game) { if (!game) {
return; return;
} }
const session = getSession(game, req.session); const session = getSession(game, req.cookies.player);
session.live = false; session.live = false;
if (session.ws) { if (session.ws) {
session.ws.close(); session.ws.close();
@ -3157,7 +3141,7 @@ const wsConnect = async (ws, req) => {
if (!game) { if (!game) {
return; return;
} }
const session = getSession(game, req.session); const session = getSession(game, req.cookies.player);
if (session.player) { if (session.player) {
session.player.live = false; session.player.live = false;
} }
@ -3186,7 +3170,7 @@ const wsConnect = async (ws, req) => {
return; return;
} }
const game = await loadGame(gameId); const game = await loadGame(gameId);
const session = getSession(game, req.session); const session = getSession(game, req.cookies.player);
if (!session.ws) { if (!session.ws) {
session.ws = ws; session.ws = ws;
} }
@ -3504,7 +3488,7 @@ const wsConnect = async (ws, req) => {
return; return;
} }
const session = getSession(game, req.session); const session = getSession(game, req.cookies.player);
session.ws = ws; session.ws = ws;
if (session.player) { if (session.player) {
session.player.live = true; session.player.live = true;
@ -3534,7 +3518,7 @@ const wsConnect = async (ws, req) => {
clearTimeout(session.keepAlive); clearTimeout(session.keepAlive);
} }
session.keepAlive = setTimeout(() => { ping(session); }, 2500); session.keepAlive = setTimeout(() => { ping(session); }, 2500);
}; });
const debugChat = (game, preamble) => { const debugChat = (game, preamble) => {
preamble = `Degug ${preamble.trim()}`; preamble = `Degug ${preamble.trim()}`;
@ -3825,7 +3809,7 @@ router.post("/", (req, res/*, next*/) => {
} else { } else {
console.log(`[${req.session.player_id.substring(0, 8)}]: https - Existing session being used`); console.log(`[${req.session.player_id.substring(0, 8)}]: https - Existing session being used`);
} }
const session = getSession(game, req.session); const session = getSession(game, req.cookies.player);
saveGame(game); saveGame(game);
return res.status(200).send(getFilteredGameForPlayer(game, session)); return res.status(200).send(getFilteredGameForPlayer(game, session));
}); });
@ -3911,28 +3895,14 @@ const shuffleBoard = (game) => {
game.signature = gameSignature(game); game.signature = gameSignature(game);
} }
/* /* Simple NO-OP to set session cookie so player-id can use it as the
return gameDB.sequelize.query("SELECT " + * index */
"photos.*,albums.path AS path,photohashes.hash,modified,(albums.path || photos.filename) AS filepath FROM photos " + router.get("/", (req, res/*, next*/) => {
"LEFT JOIN albums ON albums.id=photos.albumId " + if (!req.cookies.player) {
"LEFT JOIN photohashes ON photohashes.photoId=photos.id " + res.cookie('player', crypto.randomBytes(16).toString('hex'));
"WHERE photos.id=:id", { }
replacements: { console.log(`[${req.cookies.player.substring(0, 8)}]: Browser hand-shake has started.`)
id: id return res.status(200).send({ player: req.cookies.player });
}, type: gameDB.Sequelize.QueryTypes.SELECT,
raw: true
}).then(function(photos) {
if (photos.length == 0) {
return null;
}
*/
if (0) {
router.get("/*", (req, res/*, next*/) => {
return gameDB.sequelize.query(query, {
replacements: replacements, type: gameDB.Sequelize.QueryTypes.SELECT
}).then((photos) => {
});
}); });
}
module.exports = router; module.exports = router;