From cfc97b8101aaa7a09ebd0f329016e143fff2f868 Mon Sep 17 00:00:00 2001 From: some random guy Date: Mon, 3 Aug 2020 20:42:00 +0200 Subject: [PATCH 1/4] do not read session when not needed --- controllers/forms.js | 53 ++++++++++++++++++++++--------------------- controllers/pages.js | 40 ++++++++++++++++---------------- helpers/usesession.js | 24 ++++++++++++++++++++ server.js | 26 +++------------------ 4 files changed, 74 insertions(+), 69 deletions(-) create mode 100644 helpers/usesession.js diff --git a/controllers/forms.js b/controllers/forms.js index b0c69d0a..68446209 100644 --- a/controllers/forms.js +++ b/controllers/forms.js @@ -14,6 +14,7 @@ const express = require('express') , isLoggedIn = require(__dirname+'/../helpers/checks/isloggedin.js') , verifyCaptcha = require(__dirname+'/../helpers/captcha/captchaverify.js') , csrf = require(__dirname+'/../helpers/checks/csrfmiddleware.js') + , useSession = require(__dirname+'/../helpers/usesession.js') , sessionRefresh = require(__dirname+'/../helpers/sessionrefresh.js') , dnsblCheck = require(__dirname+'/../helpers/checks/dnsbl.js') , blockBypassCheck = require(__dirname+'/../helpers/checks/blockbypass.js') @@ -82,45 +83,45 @@ const express = require('express') , logout = require(__dirname+'/../models/forms/logout.js'); //make new post -router.post('/board/:board/post', processIp, sessionRefresh, Boards.exists, calcPerms, banCheck, postFiles, +router.post('/board/:board/post', processIp, useSession, sessionRefresh, Boards.exists, calcPerms, banCheck, postFiles, paramConverter, verifyCaptcha, numFiles, blockBypassCheck, dnsblCheck, makePostController); -router.post('/board/:board/modpost', processIp, sessionRefresh, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(3), postFiles, +router.post('/board/:board/modpost', processIp, useSession, sessionRefresh, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(3), postFiles, paramConverter, csrf, numFiles, blockBypassCheck, dnsblCheck, makePostController); //mod post has token instead of captcha //post actions -router.post('/board/:board/actions', processIp, sessionRefresh, Boards.exists, calcPerms, banCheck, paramConverter, verifyCaptcha, actionController); //public, with captcha -router.post('/board/:board/modactions', processIp, sessionRefresh, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(3), paramConverter, actionController); //board manage page -router.post('/global/actions', processIp, sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(1), paramConverter, globalActionController); //global manage page +router.post('/board/:board/actions', processIp, useSession, sessionRefresh, Boards.exists, calcPerms, banCheck, paramConverter, verifyCaptcha, actionController); //public, with captcha +router.post('/board/:board/modactions', processIp, useSession, sessionRefresh, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(3), paramConverter, actionController); //board manage page +router.post('/global/actions', processIp, useSession, sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(1), paramConverter, globalActionController); //global manage page //appeal ban -router.post('/appeal', processIp, sessionRefresh, paramConverter, verifyCaptcha, appealController); +router.post('/appeal', processIp, useSession, sessionRefresh, paramConverter, verifyCaptcha, appealController); //edit post -router.post('/editpost', processIp, sessionRefresh, csrf, paramConverter, Boards.bodyExists, calcPerms, hasPerms(3), editPostController); +router.post('/editpost', processIp, useSession, sessionRefresh, csrf, paramConverter, Boards.bodyExists, calcPerms, hasPerms(3), editPostController); //board management forms -router.post('/board/:board/transfer', processIp, sessionRefresh, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(2), paramConverter, transferController); -router.post('/board/:board/settings', processIp, sessionRefresh, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(2), paramConverter, boardSettingsController); -router.post('/board/:board/addbanners', processIp, sessionRefresh, bannerFiles, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(2), paramConverter, numFiles, uploadBannersController); //add banners -router.post('/board/:board/deletebanners', processIp, sessionRefresh, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(2), paramConverter, deleteBannersController); //delete banners -router.post('/board/:board/addban', processIp, sessionRefresh, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(3), paramConverter, addBanController); //add ban manually without post -router.post('/board/:board/editbans', processIp, sessionRefresh, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(3), paramConverter, editBansController); //edit bans -router.post('/board/:board/deleteboard', processIp, sessionRefresh, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(2), deleteBoardController); //delete board +router.post('/board/:board/transfer', processIp, useSession, sessionRefresh, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(2), paramConverter, transferController); +router.post('/board/:board/settings', processIp, useSession, sessionRefresh, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(2), paramConverter, boardSettingsController); +router.post('/board/:board/addbanners', processIp, useSession, sessionRefresh, bannerFiles, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(2), paramConverter, numFiles, uploadBannersController); //add banners +router.post('/board/:board/deletebanners', processIp, useSession, sessionRefresh, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(2), paramConverter, deleteBannersController); //delete banners +router.post('/board/:board/addban', processIp, useSession, sessionRefresh, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(3), paramConverter, addBanController); //add ban manually without post +router.post('/board/:board/editbans', processIp, useSession, sessionRefresh, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(3), paramConverter, editBansController); //edit bans +router.post('/board/:board/deleteboard', processIp, useSession, sessionRefresh, csrf, Boards.exists, calcPerms, banCheck, isLoggedIn, hasPerms(2), deleteBoardController); //delete board //global management forms -router.post('/global/editbans', sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(1), paramConverter, editBansController); //remove bans -router.post('/global/addban', processIp, sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(1), paramConverter, addBanController); //add ban manually without post -router.post('/global/deleteboard', sessionRefresh, csrf, paramConverter, calcPerms, isLoggedIn, hasPerms(1), deleteBoardController); //delete board -router.post('/global/addnews', sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(0), addNewsController); //add new newspost -router.post('/global/deletenews', sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(0), paramConverter, deleteNewsController); //delete news -router.post('/global/editaccounts', sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(0), paramConverter, editAccountsController); //account editing -router.post('/global/settings', sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(0), paramConverter, globalSettingsController); //global settings +router.post('/global/editbans', useSession, sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(1), paramConverter, editBansController); //remove bans +router.post('/global/addban', processIp, useSession, sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(1), paramConverter, addBanController); //add ban manually without post +router.post('/global/deleteboard', useSession, sessionRefresh, csrf, paramConverter, calcPerms, isLoggedIn, hasPerms(1), deleteBoardController); //delete board +router.post('/global/addnews', useSession, sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(0), addNewsController); //add new newspost +router.post('/global/deletenews', useSession, sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(0), paramConverter, deleteNewsController); //delete news +router.post('/global/editaccounts', useSession, sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(0), paramConverter, editAccountsController); //account editing +router.post('/global/settings', useSession, sessionRefresh, csrf, calcPerms, isLoggedIn, hasPerms(0), paramConverter, globalSettingsController); //global settings //create board -router.post('/create', processIp, sessionRefresh, isLoggedIn, verifyCaptcha, calcPerms, hasPerms(4), createBoardController); +router.post('/create', processIp, useSession, sessionRefresh, isLoggedIn, verifyCaptcha, calcPerms, hasPerms(4), createBoardController); //accounts -router.post('/login', loginController); -router.post('/logout', logout); -router.post('/register', processIp, verifyCaptcha, calcPerms, registerController); -router.post('/changepassword', processIp, verifyCaptcha, changePasswordController); +router.post('/login', useSession, loginController); +router.post('/logout', useSession, logout); +router.post('/register', processIp, useSession, sessionRefresh, verifyCaptcha, calcPerms, registerController); +router.post('/changepassword', processIp, useSession, sessionRefresh, verifyCaptcha, changePasswordController); //removes captcha cookie, for refreshing for noscript users router.post('/newcaptcha', newCaptcha); diff --git a/controllers/pages.js b/controllers/pages.js index 0faacfd9..c2431d6f 100644 --- a/controllers/pages.js +++ b/controllers/pages.js @@ -10,6 +10,7 @@ const express = require('express') , hasPerms = require(__dirname+'/../helpers/checks/haspermsmiddleware.js') , isLoggedIn = require(__dirname+'/../helpers/checks/isloggedin.js') , paramConverter = require(__dirname+'/../helpers/paramconverter.js') + , useSession = require(__dirname+'/../helpers/usesession.js') , sessionRefresh = require(__dirname+'/../helpers/sessionrefresh.js') , csrf = require(__dirname+'/../helpers/checks/csrfmiddleware.js') , setMinimal = require(__dirname+'/../helpers/setminimal.js') @@ -29,7 +30,7 @@ router.get('/index.html', home); router.get('/news.html', news); //board list -router.get('/boards.html', sessionRefresh, calcPerms, boardlist); +router.get('/boards.html', useSession, sessionRefresh, calcPerms, boardlist); //board pages router.get('/:board/:page(1[0-9]{1,}|[2-9][0-9]{0,}|index).html', Boards.exists, paramConverter, board); //index @@ -39,29 +40,29 @@ router.get('/:board/logs.html', Boards.exists, modloglist);//modlog list router.get('/:board/logs/:date(\\d{2}-\\d{2}-\\d{4}).html', Boards.exists, paramConverter, modlog); //daily log router.get('/:board/banners.html', Boards.exists, banners); //banners router.get('/all.html', overboard); //overboard -router.get('/create.html', sessionRefresh, isLoggedIn, create); //create new board +router.get('/create.html', useSession, sessionRefresh, isLoggedIn, create); //create new board router.get('/randombanner', randombanner); //random banner //board manage pages -router.get('/:board/manage/reports.html', sessionRefresh, isLoggedIn, Boards.exists, calcPerms, hasPerms(3), csrf, manageReports); -router.get('/:board/manage/recent.html', sessionRefresh, isLoggedIn, Boards.exists, calcPerms, hasPerms(3), csrf, manageRecent); -router.get('/:board/manage/bans.html', sessionRefresh, isLoggedIn, Boards.exists, calcPerms, hasPerms(3), csrf, manageBans); -router.get('/:board/manage/logs.html', sessionRefresh, isLoggedIn, Boards.exists, calcPerms, hasPerms(3), csrf, manageLogs); -router.get('/:board/manage/settings.html', sessionRefresh, isLoggedIn, Boards.exists, calcPerms, hasPerms(2), csrf, manageSettings); -router.get('/:board/manage/banners.html', sessionRefresh, isLoggedIn, Boards.exists, calcPerms, hasPerms(2), csrf, manageBanners); +router.get('/:board/manage/reports.html', useSession, sessionRefresh, isLoggedIn, Boards.exists, calcPerms, hasPerms(3), csrf, manageReports); +router.get('/:board/manage/recent.html', useSession, sessionRefresh, isLoggedIn, Boards.exists, calcPerms, hasPerms(3), csrf, manageRecent); +router.get('/:board/manage/bans.html', useSession, sessionRefresh, isLoggedIn, Boards.exists, calcPerms, hasPerms(3), csrf, manageBans); +router.get('/:board/manage/logs.html', useSession, sessionRefresh, isLoggedIn, Boards.exists, calcPerms, hasPerms(3), csrf, manageLogs); +router.get('/:board/manage/settings.html', useSession, sessionRefresh, isLoggedIn, Boards.exists, calcPerms, hasPerms(2), csrf, manageSettings); +router.get('/:board/manage/banners.html', useSession, sessionRefresh, isLoggedIn, Boards.exists, calcPerms, hasPerms(2), csrf, manageBanners); // if (mod view enabled) { -router.get('/:board/manage/catalog.html', sessionRefresh, isLoggedIn, Boards.exists, calcPerms, hasPerms(3), csrf, manageCatalog); -router.get('/:board/manage/:page(1[0-9]{1,}|[2-9][0-9]{0,}|index).html', sessionRefresh, isLoggedIn, Boards.exists, paramConverter, calcPerms, hasPerms(3), csrf, manageBoard); -router.get('/:board/manage/thread/:id([1-9][0-9]{0,}).html', sessionRefresh, isLoggedIn, Boards.exists, paramConverter, calcPerms, hasPerms(3), csrf, Posts.exists, manageThread); +router.get('/:board/manage/catalog.html', useSession, sessionRefresh, isLoggedIn, Boards.exists, calcPerms, hasPerms(3), csrf, manageCatalog); +router.get('/:board/manage/:page(1[0-9]{1,}|[2-9][0-9]{0,}|index).html', useSession, sessionRefresh, isLoggedIn, Boards.exists, paramConverter, calcPerms, hasPerms(3), csrf, manageBoard); +router.get('/:board/manage/thread/:id([1-9][0-9]{0,}).html', useSession, sessionRefresh, isLoggedIn, Boards.exists, paramConverter, calcPerms, hasPerms(3), csrf, Posts.exists, manageThread); //global manage pages -router.get('/globalmanage/reports.html', sessionRefresh, isLoggedIn, calcPerms, hasPerms(1), csrf, globalManageReports); -router.get('/globalmanage/bans.html', sessionRefresh, isLoggedIn, calcPerms, hasPerms(1), csrf, globalManageBans); -router.get('/globalmanage/recent.html', sessionRefresh, isLoggedIn, calcPerms, hasPerms(1), csrf, globalManageRecent); -router.get('/globalmanage/globallogs.html', sessionRefresh, isLoggedIn, calcPerms, hasPerms(1), csrf, globalManageLogs); -router.get('/globalmanage/news.html', sessionRefresh, isLoggedIn, calcPerms, hasPerms(0), csrf, globalManageNews); -router.get('/globalmanage/accounts.html', sessionRefresh, isLoggedIn, calcPerms, hasPerms(0), csrf, globalManageAccounts); -router.get('/globalmanage/settings.html', sessionRefresh, isLoggedIn, calcPerms, hasPerms(0), csrf, globalManageSettings); +router.get('/globalmanage/reports.html', useSession, sessionRefresh, isLoggedIn, calcPerms, hasPerms(1), csrf, globalManageReports); +router.get('/globalmanage/bans.html', useSession, sessionRefresh, isLoggedIn, calcPerms, hasPerms(1), csrf, globalManageBans); +router.get('/globalmanage/recent.html', useSession, sessionRefresh, isLoggedIn, calcPerms, hasPerms(1), csrf, globalManageRecent); +router.get('/globalmanage/globallogs.html', useSession, sessionRefresh, isLoggedIn, calcPerms, hasPerms(1), csrf, globalManageLogs); +router.get('/globalmanage/news.html', useSession, sessionRefresh, isLoggedIn, calcPerms, hasPerms(0), csrf, globalManageNews); +router.get('/globalmanage/accounts.html', useSession, sessionRefresh, isLoggedIn, calcPerms, hasPerms(0), csrf, globalManageAccounts); +router.get('/globalmanage/settings.html', useSession, sessionRefresh, isLoggedIn, calcPerms, hasPerms(0), csrf, globalManageSettings); //captcha router.get('/captcha', processIp, captcha); //get captcha image and cookie @@ -70,10 +71,9 @@ router.get('/bypass.html', blockBypass); //block bypass page router.get('/bypass_minimal.html', setMinimal, blockBypass); //block bypass page //accounts -router.get('/account.html', sessionRefresh, isLoggedIn, account); //page showing boards you are mod/owner of, links to password rese, logout, etc +router.get('/account.html', useSession, sessionRefresh, isLoggedIn, account); //page showing boards you are mod/owner of, links to password rese, logout, etc router.get('/login.html', login); router.get('/register.html', register); router.get('/changepassword.html', changePassword); module.exports = router; - diff --git a/helpers/usesession.js b/helpers/usesession.js new file mode 100644 index 00000000..052754ed --- /dev/null +++ b/helpers/usesession.js @@ -0,0 +1,24 @@ +'use strict'; + +const session = require('express-session') + , redisStore = require('connect-redis')(session) + , { sessionSecret, secureCookies } = require(__dirname+'/../configs/main.js') + , { redisClient } = require(__dirname+'/../redis.js') + , production = process.env.NODE_ENV === 'production' + , { DAY } = require(__dirname+'/timeutils.js'); + +module.exports = session({ + secret: sessionSecret, + store: new redisStore({ + client: redisClient, + }), + resave: false, + saveUninitialized: false, + rolling: true, + cookie: { + httpOnly: true, + secure: secureCookies && production, + sameSite: 'strict', + maxAge: DAY, + } +}); diff --git a/server.js b/server.js index 31c6fe2d..bd84b3ff 100644 --- a/server.js +++ b/server.js @@ -5,14 +5,12 @@ process .on('unhandledRejection', console.error); const express = require('express') - , session = require('express-session') - , redisStore = require('connect-redis')(session) , path = require('path') , app = express() , server = require('http').createServer(app) , cookieParser = require('cookie-parser') - , { cacheTemplates, boardDefaults, sessionSecret, globalLimits, - enableUserBoardCreation, enableUserAccountCreation, secureCookies, + , { cacheTemplates, boardDefaults, globalLimits, + enableUserBoardCreation, enableUserAccountCreation, debugLogs, ipHashPermLevel, meta, port, enableWebring } = require(__dirname+'/configs/main.js') , referrerCheck = require(__dirname+'/helpers/referrercheck.js') , { themes, codeThemes } = require(__dirname+'/helpers/themes.js') @@ -20,7 +18,6 @@ const express = require('express') , Socketio = require(__dirname+'/socketio.js') , commit = require(__dirname+'/helpers/commit.js') , dynamicResponse = require(__dirname+'/helpers/dynamic.js') - , { DAY } = require(__dirname+'/helpers/timeutils.js') , CachePugTemplates = require('cache-pug-templates'); (async () => { @@ -46,24 +43,7 @@ const express = require('express') app.use(cookieParser()); // session store - const sessionMiddleware = session({ - secret: sessionSecret, - store: new redisStore({ - client: redisClient, - }), - resave: false, - saveUninitialized: false, - rolling: true, - cookie: { - httpOnly: true, - secure: secureCookies && production, - sameSite: 'strict', - maxAge: DAY, - } - }); - - //add session middleware to express - app.use(sessionMiddleware); + const sessionMiddleware = require(__dirname+'/helpers/usesession.js'); // connect socketio debugLogs && console.log('STARTING WEBSOCKET'); From 0190ae5a0b57c9a02ab239cfb85208e30d7f9470 Mon Sep 17 00:00:00 2001 From: some random guy Date: Mon, 3 Aug 2020 21:01:01 +0200 Subject: [PATCH 2/4] less garbage is session store authenticated: same as `user != null` user.authLevel, user.ownedBoards, user.modBoards: refreshed by sessionrefresh on each request anyways, so it doesn't make much sense to store them in the session store too. --- helpers/checks/hasperms.js | 4 ++-- helpers/checks/isloggedin.js | 2 +- helpers/sessionrefresh.js | 4 ++-- models/forms/login.js | 8 +------- models/pages/account.js | 2 +- 5 files changed, 7 insertions(+), 13 deletions(-) diff --git a/helpers/checks/hasperms.js b/helpers/checks/hasperms.js index 547feeae..9dac4576 100644 --- a/helpers/checks/hasperms.js +++ b/helpers/checks/hasperms.js @@ -2,8 +2,8 @@ module.exports = (req, res) => { if (req.session) { - const { authenticated, user } = req.session; - if (authenticated === true && user != null) { + const { user } = res.locals; + if (user != null) { if (user.authLevel < 4) { //assigned levels return user.authLevel; } diff --git a/helpers/checks/isloggedin.js b/helpers/checks/isloggedin.js index f338b969..493aad1a 100644 --- a/helpers/checks/isloggedin.js +++ b/helpers/checks/isloggedin.js @@ -1,7 +1,7 @@ 'use strict'; module.exports = async (req, res, next) => { - if (req.session && req.session.authenticated === true) { + if (res.locals.user) { return next(); } let goto; diff --git a/helpers/sessionrefresh.js b/helpers/sessionrefresh.js index 68bf67c4..95bca7b4 100644 --- a/helpers/sessionrefresh.js +++ b/helpers/sessionrefresh.js @@ -3,13 +3,13 @@ const { Accounts } = require(__dirname+'/../db/'); module.exports = async (req, res, next) => { - if (req.session && req.session.authenticated === true) { + if (req.session && req.session.user) { // keeping session updated incase user updated on global manage const account = await Accounts.findOne(req.session.user.username); if (!account) { req.session.destroy(); } else { - req.session.user = { + res.locals.user = { 'username': account._id, 'authLevel': account.authLevel, 'modBoards': account.modBoards, diff --git a/models/forms/login.js b/models/forms/login.js index b65a4211..886f7921 100644 --- a/models/forms/login.js +++ b/models/forms/login.js @@ -30,13 +30,7 @@ module.exports = async (req, res, next) => { if (passwordMatch === true) { // add the account to the session and authenticate if password was correct - req.session.user = { - 'username': account._id, - 'authLevel': account.authLevel, - 'ownedBoards': account.ownedBoards, - 'modBoards': account.modBoards, - }; - req.session.authenticated = true; + req.session.user = { 'username': account._id } //successful login return res.redirect(goto); diff --git a/models/pages/account.js b/models/pages/account.js index 81aad6ae..4d9506c9 100644 --- a/models/pages/account.js +++ b/models/pages/account.js @@ -5,7 +5,7 @@ module.exports = async (req, res, next) => { res .set('Cache-Control', 'private, max-age=5') .render('account', { - user: req.session.user, + user: res.locals.user, }); } From cd789dba0c7f9eb49b2158e34f46ecf20a0a8f50 Mon Sep 17 00:00:00 2001 From: some random guy Date: Tue, 4 Aug 2020 00:52:30 +0200 Subject: [PATCH 3/4] remove unnecessary user object from session It only had a single property, username. --- controllers/forms/editpost.js | 2 +- helpers/sessionrefresh.js | 2 +- models/forms/actionhandler.js | 2 +- models/forms/addban.js | 6 +++--- models/forms/banposter.js | 4 ++-- models/forms/create.js | 2 +- models/forms/editpost.js | 4 ++-- models/forms/login.js | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/controllers/forms/editpost.js b/controllers/forms/editpost.js index ff286ca6..60bcd398 100644 --- a/controllers/forms/editpost.js +++ b/controllers/forms/editpost.js @@ -48,7 +48,7 @@ module.exports = async (req, res, next) => { } if (res.locals.permLevel > 1) { //if not global staff or above - const ratelimitUser = await Ratelimits.incrmentQuota(req.session.user.username, 'edit', rateLimitCost.editPost); + const ratelimitUser = await Ratelimits.incrmentQuota(req.session.user, 'edit', rateLimitCost.editPost); const ratelimitIp = await Ratelimits.incrmentQuota(res.locals.ip.single, 'edit', rateLimitCost.editPost); if (ratelimitUser > 100 || ratelimitIp > 100) { return dynamicResponse(req, res, 429, 'message', { diff --git a/helpers/sessionrefresh.js b/helpers/sessionrefresh.js index 95bca7b4..042220c7 100644 --- a/helpers/sessionrefresh.js +++ b/helpers/sessionrefresh.js @@ -5,7 +5,7 @@ const { Accounts } = require(__dirname+'/../db/'); module.exports = async (req, res, next) => { if (req.session && req.session.user) { // keeping session updated incase user updated on global manage - const account = await Accounts.findOne(req.session.user.username); + const account = await Accounts.findOne(req.session.user); if (!account) { req.session.destroy(); } else { diff --git a/models/forms/actionhandler.js b/models/forms/actionhandler.js index 4bf5e6dd..02bef52a 100644 --- a/models/forms/actionhandler.js +++ b/models/forms/actionhandler.js @@ -277,7 +277,7 @@ module.exports = async (req, res, next) => { const message = req.body.log_message || null; let logUser; if (res.locals.permLevel < 4) { //if staff - logUser = req.session.user.username; + logUser = req.session.user; } else { logUser = 'Unregistered User'; } diff --git a/models/forms/addban.js b/models/forms/addban.js index 66f80971..80ba290b 100644 --- a/models/forms/addban.js +++ b/models/forms/addban.js @@ -12,7 +12,7 @@ module.exports = async (req, res, redirect) => { const actionDate = new Date(); const banPromise = Bans.insertOne({ - //note: raw ip and type single because of + //note: raw ip and type single because of 'type': 'single', 'ip': { 'single': isIP(req.body.ip) ? hashIp(req.body.ip) : req.body.ip, @@ -21,7 +21,7 @@ module.exports = async (req, res, redirect) => { 'reason': req.body.ban_reason || req.body.log_message || 'No reason specified', 'board': req.params.board || null, 'posts': null, - 'issuer': req.session.user.username, + 'issuer': req.session.user, 'date': actionDate, 'expireAt': new Date(actionDate.getTime() + (req.body.ban_duration || defaultBanDuration)), 'allowAppeal': req.body.no_appeal ? false : true, @@ -36,7 +36,7 @@ module.exports = async (req, res, redirect) => { 'date': actionDate, 'showUser': !req.body.hide_name || res.locals.permLevel >= 4 ? true : false, 'message': req.body.log_message || null, - 'user': res.locals.permLevel < 4 ? req.session.user.username : 'Unregistered User', + 'user': res.locals.permLevel < 4 ? req.session.user : 'Unregistered User', 'ip': { 'single': res.locals.ip.single, 'raw': res.locals.ip.raw diff --git a/models/forms/banposter.js b/models/forms/banposter.js index 1d19a2d3..0cd0d38c 100644 --- a/models/forms/banposter.js +++ b/models/forms/banposter.js @@ -41,7 +41,7 @@ module.exports = async (req, res, next) => { 'reason': banReason, 'board': banBoard, 'posts': req.body.preserve_post ? thisIpPosts : null, - 'issuer': req.session.user.username, + 'issuer': req.session.user, 'date': banDate, 'expireAt': banExpiry, allowAppeal, @@ -78,7 +78,7 @@ module.exports = async (req, res, next) => { 'reason': banReason, 'board': banBoard, 'posts': null, - 'issuer': req.session.user.username, + 'issuer': req.session.user, 'date': banDate, 'expireAt': banExpiry, allowAppeal, diff --git a/models/forms/create.js b/models/forms/create.js index 641c2410..7340560e 100644 --- a/models/forms/create.js +++ b/models/forms/create.js @@ -12,7 +12,7 @@ module.exports = async (req, res, next) => { const { name, description } = req.body , uri = req.body.uri.toLowerCase() , tags = req.body.tags.split('\n').filter(n => n) - , owner = req.session.user.username; + , owner = req.session.user; if (restrictedURIs.has(uri)) { return dynamicResponse(req, res, 400, 'message', { diff --git a/models/forms/editpost.js b/models/forms/editpost.js index fbe743c8..8716d278 100644 --- a/models/forms/editpost.js +++ b/models/forms/editpost.js @@ -122,7 +122,7 @@ todo: handle some more situations }, { '$set': { edited: { - username: req.body.hide_name ? 'Hidden User' : req.session.user.username, + username: req.body.hide_name ? 'Hidden User' : req.session.user, date: new Date(), }, message, @@ -144,7 +144,7 @@ todo: handle some more situations date: new Date(), showUser: req.body.hide_name ? false : true, message: req.body.log_message || null, - user: req.session.user.username, + user: req.session.user, ip: { single: res.locals.ip.single, raw: res.locals.ip.raw, diff --git a/models/forms/login.js b/models/forms/login.js index 886f7921..e13fd958 100644 --- a/models/forms/login.js +++ b/models/forms/login.js @@ -30,7 +30,7 @@ module.exports = async (req, res, next) => { if (passwordMatch === true) { // add the account to the session and authenticate if password was correct - req.session.user = { 'username': account._id } + req.session.user = account._id; //successful login return res.redirect(goto); From 5dc3fe9504c3b8196f871e116f17908236c3a8ba Mon Sep 17 00:00:00 2001 From: some random guy Date: Wed, 5 Aug 2020 20:34:00 +0200 Subject: [PATCH 4/4] cache account info in redis db --- db/accounts.js | 47 ++++++++++++++++++++++++++------------- gulpfile.js | 1 + helpers/sessionrefresh.js | 7 +++--- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/db/accounts.js b/db/accounts.js index 72a004f1..f2455f8d 100644 --- a/db/accounts.js +++ b/db/accounts.js @@ -2,7 +2,8 @@ const Mongo = require(__dirname+'/db.js') , db = Mongo.client.db('jschan').collection('accounts') - , bcrypt = require('bcrypt'); + , bcrypt = require('bcrypt') + , cache = require(__dirname+'/../redis.js'); module.exports = { @@ -32,7 +33,7 @@ module.exports = { // hash the password const passwordHash = await bcrypt.hash(password, 12); //add to db - return db.insertOne({ + const res = await db.insertOne({ '_id': username, original, authLevel, @@ -40,17 +41,21 @@ module.exports = { 'ownedBoards': [], 'modBoards': [] }); + cache.del(`users:${username}`); + return res; }, changePassword: async (username, newPassword) => { const passwordHash = await bcrypt.hash(newPassword, 12); - return db.updateOne({ + const res = await db.updateOne({ '_id': username }, { '$set': { 'passwordHash': passwordHash } }); + cache.del(`users:${username}`); + return res; }, find: (filter, skip=0, limit=0) => { @@ -63,36 +68,42 @@ module.exports = { }).skip(skip).limit(limit).toArray(); }, - deleteMany: (usernames) => { - return db.deleteMany({ + deleteMany: async (usernames) => { + const res = await db.deleteMany({ '_id': { '$in': usernames } }); + cache.del(usernames.map(n => `users:${n}`)); + return res; }, - addOwnedBoard: (username, board) => { - return db.updateOne({ + addOwnedBoard: async (username, board) => { + const res = await db.updateOne({ '_id': username }, { '$addToSet': { 'ownedBoards': board } }); + cache.del(`users:${username}`); + return res; }, - removeOwnedBoard: (username, board) => { - return db.updateOne({ + removeOwnedBoard: async (username, board) => { + const res = await db.updateOne({ '_id': username }, { '$pull': { 'ownedBoards': board } }); + cache.del(`users:${username}`); + return res; }, - addModBoard: (usernames, board) => { - return db.updateMany({ + addModBoard: async (usernames, board) => { + const res = await db.updateMany({ '_id': { '$in': usernames } @@ -101,10 +112,12 @@ module.exports = { 'modBoards': board } }); + cache.del(`users:${username}`); + return res; }, - removeModBoard: (usernames, board) => { - return db.updateMany({ + removeModBoard: async (usernames, board) => { + const res = await db.updateMany({ '_id': { '$in': usernames } @@ -113,6 +126,8 @@ module.exports = { 'modBoards': board } }); + cache.del(`users:${username}`); + return res; }, getOwnedOrModBoards: (usernames) => { @@ -140,9 +155,9 @@ module.exports = { }).toArray(); }, - setLevel: (usernames, level) => { + setLevel: async (usernames, level) => { //increase users auth level - return db.updateMany({ + const res = await db.updateMany({ '_id': { '$in': usernames } @@ -151,6 +166,8 @@ module.exports = { 'authLevel': level } }); + cache.del(`users:${username}`); + return res; }, deleteAll: () => { diff --git a/gulpfile.js b/gulpfile.js index 53a3b97b..55a166be 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -164,6 +164,7 @@ async function cache() { Redis.deletePattern('boards:listed'), Redis.deletePattern('board:*'), Redis.deletePattern('banners:*'), + Redis.deletePattern('users:*'), Redis.deletePattern('blacklisted:*'), ]); Redis.redisClient.quit(); diff --git a/helpers/sessionrefresh.js b/helpers/sessionrefresh.js index 042220c7..98a5a0bb 100644 --- a/helpers/sessionrefresh.js +++ b/helpers/sessionrefresh.js @@ -1,10 +1,10 @@ 'use strict'; -const { Accounts } = require(__dirname+'/../db/'); +const { Accounts } = require(__dirname+'/../db/') + , cache = require(__dirname+'/../redis.js'); module.exports = async (req, res, next) => { - if (req.session && req.session.user) { - // keeping session updated incase user updated on global manage + if (req.session && req.session.user && !res.locals.user) { const account = await Accounts.findOne(req.session.user); if (!account) { req.session.destroy(); @@ -15,6 +15,7 @@ module.exports = async (req, res, next) => { 'modBoards': account.modBoards, 'ownedBoards': account.ownedBoards, }; + cache.set(`users:${req.session.user}`, res.locals.user, 3600); } } next();