From f96b37aad37e6b4f47a6db4354ef8082096ebf54 Mon Sep 17 00:00:00 2001 From: Chord Date: Thu, 9 Jan 2020 21:22:07 +0100 Subject: [PATCH] Fix admin/session middleware to prevent casade on to later routes --- README.md | 2 ++ api/admin.js | 18 +++++++++--------- api/index.js | 45 ++++++++++----------------------------------- api/user.js | 8 ++++---- api/util.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 67 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index c07647c..d72b015 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,8 @@ Please note that Webpack (dev) will proxy all API requests (/api) to the host `h **Finally, connect to http://localhost:8081** (webpack, not the raw express server) +Register an account to start and grant it GM privileges using `UPDATE accounts SET gm=true WHERE id=your_id`. + ### Troubleshooting 1. Database SELECT/INSERTs are failing, but I can connect to the DB diff --git a/api/admin.js b/api/admin.js index 6e07c6d..5b49b52 100644 --- a/api/admin.js +++ b/api/admin.js @@ -1,12 +1,12 @@ import express from 'express' import * as db from './db.js' -import { get_pagination, get_filter, get_sort, fetch_user_middleware } from './util.js' +import { NEED_ADMIN, get_pagination, get_filter, get_sort, fetch_user_middleware } from './util.js' const api = express.Router(); api.param("user", fetch_user_middleware); -api.get('/users', async (req, res, next) => { +api.get('/users', NEED_ADMIN, async (req, res, next) => { const pagination = get_pagination(req); const filter = get_filter(req, { @@ -41,7 +41,7 @@ api.get('/users', async (req, res, next) => { } }); -api.post('/search', async (req, res, next) => { +api.post('/search', NEED_ADMIN, async (req, res, next) => { const pagination = get_pagination(req); let search = req.body.search; @@ -60,13 +60,13 @@ api.post('/search', async (req, res, next) => { } }); -api.get('/user/:user', async (req, res, next) => { +api.get('/user/:user', NEED_ADMIN, async (req, res, next) => { const account = req.user; res.status(200).json({ id : account.id, name: account.username }); }); -api.post('/user/:user/add_gm', async (req, res, next) => { +api.post('/user/:user/add_gm', NEED_ADMIN, async (req, res, next) => { const account = req.user; try { @@ -78,7 +78,7 @@ api.post('/user/:user/add_gm', async (req, res, next) => { } }); -api.post('/user/:user/remove_gm', async (req, res, next) => { +api.post('/user/:user/remove_gm', NEED_ADMIN, async (req, res, next) => { const account = req.user; try { @@ -90,7 +90,7 @@ api.post('/user/:user/remove_gm', async (req, res, next) => { } }); -api.post('/user/:user/ban', async (req, res, next) => { +api.post('/user/:user/ban', NEED_ADMIN, async (req, res, next) => { const account = req.user; try { @@ -103,7 +103,7 @@ api.post('/user/:user/ban', async (req, res, next) => { } }); -api.post('/user/:user/unban', async (req, res, next) => { +api.post('/user/:user/unban', NEED_ADMIN, async (req, res, next) => { const account = req.user; try { @@ -115,7 +115,7 @@ api.post('/user/:user/unban', async (req, res, next) => { }); -api.get('/characters', async (req, res, next) => { +api.get('/characters', NEED_ADMIN, async (req, res, next) => { const pagination = get_pagination(req); try { diff --git a/api/index.js b/api/index.js index f30ef46..d0c5a74 100644 --- a/api/index.js +++ b/api/index.js @@ -1,3 +1,4 @@ +import fs from 'fs' import express from 'express' import bodyParser from 'body-parser' import * as db from './db.js' @@ -6,6 +7,7 @@ import api_user from './user.js' import api_info from './info.js' import api_admin from './admin.js' +const VERSION = JSON.parse(fs.readFileSync('package.json', 'utf8')).version; const api = express.Router(); if (process.env.NODE_ENV !== "production") { @@ -17,46 +19,19 @@ if (process.env.NODE_ENV !== "production") { }); } -async function sessionRequired(req, res, next) { - if (!req.session || !req.session.account_id) { - res.status(403).json({message: 'session required'}) - } else { - try { - const account = await db.get_account_by_id(req.session.account_id); - - if (!account) { - console.log("ERROR: failed to lookup account from session!") - res.status(500).json({message: 'error'}); - } else { - req.session_account = account; - next(); - } - } catch (e) { - console.log(e) - res.status(500).json({message: 'error'}); - } - } -} -async function adminRequired(req, res, next) { - if (!req.session_account) { - console.log("ERROR: sessionRequired needs to be called before adminRequired") - res.status(500).json({message: ''}) - } else { - if (req.session_account.gm === true && req.session_account.inactive === false) { - next(); - } else { - res.status(403).json({message : 'admin required'}) - } - } -} - api.use(bodyParser.json()); api.use(bodyParser.urlencoded({ extended: true })); api.use(api_auth) api.use(api_info) -api.use(sessionRequired, api_user) -api.use(sessionRequired, adminRequired, api_admin) + +// These calls are gated within their respective routers +api.use(api_user) +api.use(api_admin) + +api.get("/", async (req, res, next) => { + res.status(200).json({message : 'PSFPortal ' + VERSION + ' API base. Created by Chord for the PSForever Project: https://psforever.net'}) +}); api.post("/bad_route", async (req, res, next) => { console.log("BAD APP ROUTE:", req.body.route) diff --git a/api/user.js b/api/user.js index 684b936..39da8ae 100644 --- a/api/user.js +++ b/api/user.js @@ -1,12 +1,12 @@ import express from 'express' import * as db from './db.js' -import { get_pagination, fetch_user_middleware } from './util.js' +import { NEED_SESSION, get_pagination, fetch_user_middleware } from './util.js' const api = express.Router(); api.param("user", fetch_user_middleware); -api.get('/user', async (req, res, next) => { +api.get('/user', NEED_SESSION, async (req, res, next) => { try { const account = await db.get_account_by_id(req.session.account_id); res.status(200).json({ id : account.id, name: account.username, admin : account.gm }); @@ -16,7 +16,7 @@ api.get('/user', async (req, res, next) => { } }); -api.get('/user/:user/profile', async (req, res, next) => { +api.get('/user/:user/profile', NEED_SESSION, async (req, res, next) => { const target_account = req.user; if (target_account.id !== req.session.account_id && !req.session_account.gm) { @@ -44,7 +44,7 @@ api.get('/user/:user/profile', async (req, res, next) => { } }); -api.get('/user/:user/logins', async (req, res, next) => { +api.get('/user/:user/logins', NEED_SESSION, async (req, res, next) => { const account = req.user; const pagination = get_pagination(req); diff --git a/api/util.js b/api/util.js index c89e51c..a062a3d 100644 --- a/api/util.js +++ b/api/util.js @@ -133,3 +133,45 @@ export async function fetch_user_middleware(req, res, next, id) { res.status(500).json({message: 'error'}); } } + +async function sessionRequired(req, res, next) { + console.log("SESSION REQUIRED") + if (!req.session || !req.session.account_id) { + res.status(403).json({message: 'session required'}) + } else { + if (req.session_account) { + next() + } else { + try { + const account = await db.get_account_by_id(req.session.account_id); + + if (!account) { + console.log("ERROR: failed to lookup account from session!") + res.status(500).json({message: 'error'}); + } else { + req.session_account = account; + next(); + } + } catch (e) { + console.log(e) + res.status(500).json({message: 'error'}); + } + } + } +} + +async function adminRequired(req, res, next) { + if (!req.session_account) { + console.log("ERROR: sessionRequired needs to be called before adminRequired") + res.status(403).json({message: 'session required'}) + } else { + if (req.session_account.gm === true && req.session_account.inactive === false) { + next(); + } else { + res.status(403).json({message : 'admin required'}) + } + } +} + +export const NEED_SESSION = sessionRequired; +export const NEED_ADMIN = [sessionRequired, adminRequired];