mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-10 16:05:49 +01:00
* feat: wip * feat: wrap middlewares * feat: middleware errors * feat: more middleware changes * fix: remove unused async * fix: prevent version errors from blocking acp render * feat: wrap more middlewares
This commit is contained in:
committed by
GitHub
parent
023942da7d
commit
dcb85ee7a1
@@ -52,7 +52,7 @@ Analytics.increment = function (keys, callback) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Analytics.pageView = function (payload) {
|
Analytics.pageView = async function (payload) {
|
||||||
pageViews += 1;
|
pageViews += 1;
|
||||||
|
|
||||||
if (payload.uid > 0) {
|
if (payload.uid > 0) {
|
||||||
@@ -71,20 +71,16 @@ Analytics.pageView = function (payload) {
|
|||||||
ipCache.set(payload.ip + nconf.get('secret'), hash);
|
ipCache.set(payload.ip + nconf.get('secret'), hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
db.sortedSetScore('ip:recent', hash, function (err, score) {
|
const score = await db.sortedSetScore('ip:recent', hash);
|
||||||
if (err) {
|
if (!score) {
|
||||||
return;
|
uniqueIPCount += 1;
|
||||||
}
|
}
|
||||||
if (!score) {
|
const today = new Date();
|
||||||
uniqueIPCount += 1;
|
today.setHours(today.getHours(), 0, 0, 0);
|
||||||
}
|
if (!score || score < today.getTime()) {
|
||||||
var today = new Date();
|
uniquevisitors += 1;
|
||||||
today.setHours(today.getHours(), 0, 0, 0);
|
await db.sortedSetAdd('ip:recent', Date.now(), hash);
|
||||||
if (!score || score < today.getTime()) {
|
}
|
||||||
uniquevisitors += 1;
|
|
||||||
db.sortedSetAdd('ip:recent', Date.now(), hash);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var async = require('async');
|
|
||||||
var winston = require('winston');
|
var winston = require('winston');
|
||||||
var jsesc = require('jsesc');
|
var jsesc = require('jsesc');
|
||||||
var nconf = require('nconf');
|
var nconf = require('nconf');
|
||||||
@@ -11,6 +10,7 @@ var meta = require('../meta');
|
|||||||
var plugins = require('../plugins');
|
var plugins = require('../plugins');
|
||||||
var utils = require('../../public/src/utils');
|
var utils = require('../../public/src/utils');
|
||||||
var versions = require('../admin/versions');
|
var versions = require('../admin/versions');
|
||||||
|
var helpers = require('./helpers');
|
||||||
|
|
||||||
var controllers = {
|
var controllers = {
|
||||||
api: require('../controllers/api'),
|
api: require('../controllers/api'),
|
||||||
@@ -19,24 +19,16 @@ var controllers = {
|
|||||||
|
|
||||||
module.exports = function (middleware) {
|
module.exports = function (middleware) {
|
||||||
middleware.admin = {};
|
middleware.admin = {};
|
||||||
middleware.admin.isAdmin = function (req, res, next) {
|
middleware.admin.isAdmin = helpers.try(async function (req, res, next) {
|
||||||
winston.warn('[middleware.admin.isAdmin] deprecation warning, no need to use this from plugins!');
|
winston.warn('[middleware.admin.isAdmin] deprecation warning, no need to use this from plugins!');
|
||||||
middleware.isAdmin(req, res, next);
|
await middleware.isAdmin(req, res, next);
|
||||||
};
|
});
|
||||||
|
|
||||||
middleware.admin.buildHeader = function (req, res, next) {
|
middleware.admin.buildHeader = helpers.try(async function (req, res, next) {
|
||||||
res.locals.renderAdminHeader = true;
|
res.locals.renderAdminHeader = true;
|
||||||
|
res.locals.config = await controllers.api.loadConfig(req);
|
||||||
async.waterfall([
|
next();
|
||||||
function (next) {
|
});
|
||||||
controllers.api.loadConfig(req, next);
|
|
||||||
},
|
|
||||||
function (config, next) {
|
|
||||||
res.locals.config = config;
|
|
||||||
next();
|
|
||||||
},
|
|
||||||
], next);
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.admin.renderHeader = async (req, res, data) => {
|
middleware.admin.renderHeader = async (req, res, data) => {
|
||||||
var custom_header = {
|
var custom_header = {
|
||||||
@@ -50,7 +42,7 @@ module.exports = function (middleware) {
|
|||||||
scripts: getAdminScripts(),
|
scripts: getAdminScripts(),
|
||||||
custom_header: plugins.fireHook('filter:admin.header.build', custom_header),
|
custom_header: plugins.fireHook('filter:admin.header.build', custom_header),
|
||||||
configs: meta.configs.list(),
|
configs: meta.configs.list(),
|
||||||
latestVersion: versions.getLatestVersion(),
|
latestVersion: getLatestVersion(),
|
||||||
});
|
});
|
||||||
|
|
||||||
var userData = results.userData;
|
var userData = results.userData;
|
||||||
@@ -98,6 +90,16 @@ module.exports = function (middleware) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getLatestVersion() {
|
||||||
|
try {
|
||||||
|
const result = await versions.getLatestVersion();
|
||||||
|
return result;
|
||||||
|
} catch (err) {
|
||||||
|
winston.error('[acp] Failed to fetch latest version' + err.stack);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
middleware.admin.renderFooter = async function (req, res, data) {
|
middleware.admin.renderFooter = async function (req, res, data) {
|
||||||
return await req.app.renderAsync('admin/footer', data);
|
return await req.app.renderAsync('admin/footer', data);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var async = require('async');
|
|
||||||
var nconf = require('nconf');
|
var nconf = require('nconf');
|
||||||
var jsesc = require('jsesc');
|
var jsesc = require('jsesc');
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
@@ -16,6 +15,7 @@ var translator = require('../translator');
|
|||||||
var privileges = require('../privileges');
|
var privileges = require('../privileges');
|
||||||
var languages = require('../languages');
|
var languages = require('../languages');
|
||||||
var utils = require('../utils');
|
var utils = require('../utils');
|
||||||
|
var helpers = require('./helpers');
|
||||||
|
|
||||||
var controllers = {
|
var controllers = {
|
||||||
api: require('../controllers/api'),
|
api: require('../controllers/api'),
|
||||||
@@ -23,34 +23,19 @@ var controllers = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.exports = function (middleware) {
|
module.exports = function (middleware) {
|
||||||
middleware.buildHeader = function buildHeader(req, res, next) {
|
middleware.buildHeader = helpers.try(async function buildHeader(req, res, next) {
|
||||||
res.locals.renderHeader = true;
|
res.locals.renderHeader = true;
|
||||||
res.locals.isAPI = false;
|
res.locals.isAPI = false;
|
||||||
async.waterfall([
|
if (req.uid >= 0) {
|
||||||
function (next) {
|
await middleware.applyCSRFAsync(req, res);
|
||||||
if (req.uid >= 0) {
|
}
|
||||||
middleware.applyCSRF(req, res, next);
|
const [config] = await Promise.all([
|
||||||
} else {
|
controllers.api.loadConfig(req),
|
||||||
setImmediate(next);
|
plugins.fireHook('filter:middleware.buildHeader', { req: req, locals: res.locals }),
|
||||||
}
|
]);
|
||||||
},
|
res.locals.config = config;
|
||||||
function (next) {
|
next();
|
||||||
async.parallel({
|
});
|
||||||
config: function (next) {
|
|
||||||
controllers.api.loadConfig(req, next);
|
|
||||||
},
|
|
||||||
plugins: function (next) {
|
|
||||||
plugins.fireHook('filter:middleware.buildHeader', { req: req, locals: res.locals }, next);
|
|
||||||
},
|
|
||||||
}, next);
|
|
||||||
},
|
|
||||||
function (results, next) {
|
|
||||||
res.locals.config = results.config;
|
|
||||||
// Return no arguments
|
|
||||||
setImmediate(next);
|
|
||||||
},
|
|
||||||
], next);
|
|
||||||
};
|
|
||||||
|
|
||||||
async function generateHeader(req, res, data) {
|
async function generateHeader(req, res, data) {
|
||||||
var registrationType = meta.config.registrationType || 'normal';
|
var registrationType = meta.config.registrationType || 'normal';
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ var _ = require('lodash');
|
|||||||
|
|
||||||
var meta = require('../meta');
|
var meta = require('../meta');
|
||||||
var languages = require('../languages');
|
var languages = require('../languages');
|
||||||
|
var helpers = require('./helpers');
|
||||||
|
|
||||||
module.exports = function (middleware) {
|
module.exports = function (middleware) {
|
||||||
middleware.addHeaders = function addHeaders(req, res, next) {
|
middleware.addHeaders = helpers.try(function addHeaders(req, res, next) {
|
||||||
var headers = {
|
var headers = {
|
||||||
'X-Powered-By': encodeURI(meta.config['powered-by'] || 'NodeBB'),
|
'X-Powered-By': encodeURI(meta.config['powered-by'] || 'NodeBB'),
|
||||||
'X-Frame-Options': meta.config['allow-from-uri'] ? 'ALLOW-FROM ' + encodeURI(meta.config['allow-from-uri']) : 'SAMEORIGIN',
|
'X-Frame-Options': meta.config['allow-from-uri'] ? 'ALLOW-FROM ' + encodeURI(meta.config['allow-from-uri']) : 'SAMEORIGIN',
|
||||||
@@ -61,31 +62,30 @@ module.exports = function (middleware) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
next();
|
next();
|
||||||
};
|
});
|
||||||
|
|
||||||
let langs = [];
|
middleware.autoLocale = helpers.try(async function autoLocale(req, res, next) {
|
||||||
middleware.autoLocale = function autoLocale(req, res, next) {
|
|
||||||
if (parseInt(req.uid, 10) > 0 || !meta.config.autoDetectLang || req.query.lang) {
|
if (parseInt(req.uid, 10) > 0 || !meta.config.autoDetectLang || req.query.lang) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
const langs = await listCodes();
|
||||||
const lang = req.acceptsLanguages(langs);
|
const lang = req.acceptsLanguages(langs);
|
||||||
if (!lang) {
|
if (!lang) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
req.query.lang = lang;
|
req.query.lang = lang;
|
||||||
next();
|
next();
|
||||||
};
|
|
||||||
|
|
||||||
languages.listCodes(function (err, codes) {
|
|
||||||
if (err) {
|
|
||||||
winston.error('[middleware/autoLocale] Could not retrieve languages codes list!');
|
|
||||||
codes = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
winston.verbose('[middleware/autoLocale] Retrieves languages list for middleware');
|
|
||||||
var defaultLang = meta.config.defaultLang || 'en-GB';
|
|
||||||
|
|
||||||
langs = _.uniq([defaultLang, ...codes]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function listCodes() {
|
||||||
|
const defaultLang = meta.config.defaultLang || 'en-GB';
|
||||||
|
try {
|
||||||
|
const codes = await languages.listCodes();
|
||||||
|
winston.verbose('[middleware/autoLocale] Retrieves languages list for middleware');
|
||||||
|
return _.uniq([defaultLang, ...codes]);
|
||||||
|
} catch (err) {
|
||||||
|
winston.error('[middleware/autoLocale] Could not retrieve languages codes list! ' + err.stack);
|
||||||
|
return [defaultLang];
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
22
src/middleware/helpers.js
Normal file
22
src/middleware/helpers.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const helpers = module.exports;
|
||||||
|
|
||||||
|
helpers.try = function (middleware) {
|
||||||
|
if (middleware && middleware.constructor && middleware.constructor.name === 'AsyncFunction') {
|
||||||
|
return async function (req, res, next) {
|
||||||
|
try {
|
||||||
|
await middleware(req, res, next);
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return function (req, res, next) {
|
||||||
|
try {
|
||||||
|
middleware(req, res, next);
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -8,6 +8,7 @@ var nconf = require('nconf');
|
|||||||
var ensureLoggedIn = require('connect-ensure-login');
|
var ensureLoggedIn = require('connect-ensure-login');
|
||||||
var toobusy = require('toobusy-js');
|
var toobusy = require('toobusy-js');
|
||||||
var LRU = require('lru-cache');
|
var LRU = require('lru-cache');
|
||||||
|
var util = require('util');
|
||||||
|
|
||||||
var plugins = require('../plugins');
|
var plugins = require('../plugins');
|
||||||
var meta = require('../meta');
|
var meta = require('../meta');
|
||||||
@@ -15,6 +16,7 @@ var user = require('../user');
|
|||||||
var groups = require('../groups');
|
var groups = require('../groups');
|
||||||
var analytics = require('../analytics');
|
var analytics = require('../analytics');
|
||||||
var privileges = require('../privileges');
|
var privileges = require('../privileges');
|
||||||
|
var helpers = require('./helpers');
|
||||||
|
|
||||||
var controllers = {
|
var controllers = {
|
||||||
api: require('../controllers/api'),
|
api: require('../controllers/api'),
|
||||||
@@ -39,6 +41,8 @@ middleware.applyCSRF = csrf({
|
|||||||
} : true,
|
} : true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
middleware.applyCSRFAsync = util.promisify(middleware.applyCSRF);
|
||||||
|
|
||||||
middleware.ensureLoggedIn = ensureLoggedIn.ensureLoggedIn(nconf.get('relative_path') + '/login');
|
middleware.ensureLoggedIn = ensureLoggedIn.ensureLoggedIn(nconf.get('relative_path') + '/login');
|
||||||
|
|
||||||
require('./admin')(middleware);
|
require('./admin')(middleware);
|
||||||
@@ -51,56 +55,39 @@ require('./headers')(middleware);
|
|||||||
middleware.stripLeadingSlashes = function stripLeadingSlashes(req, res, next) {
|
middleware.stripLeadingSlashes = function stripLeadingSlashes(req, res, next) {
|
||||||
var target = req.originalUrl.replace(nconf.get('relative_path'), '');
|
var target = req.originalUrl.replace(nconf.get('relative_path'), '');
|
||||||
if (target.startsWith('//')) {
|
if (target.startsWith('//')) {
|
||||||
res.redirect(nconf.get('relative_path') + target.replace(/^\/+/, '/'));
|
return res.redirect(nconf.get('relative_path') + target.replace(/^\/+/, '/'));
|
||||||
} else {
|
|
||||||
setImmediate(next);
|
|
||||||
}
|
}
|
||||||
|
next();
|
||||||
};
|
};
|
||||||
|
|
||||||
middleware.pageView = function pageView(req, res, next) {
|
middleware.pageView = helpers.try(async function pageView(req, res, next) {
|
||||||
analytics.pageView({
|
const promises = [
|
||||||
ip: req.ip,
|
analytics.pageView({ ip: req.ip, uid: req.uid }),
|
||||||
uid: req.uid,
|
];
|
||||||
|
if (req.loggedIn) {
|
||||||
|
promises.push(user.updateOnlineUsers(req.uid));
|
||||||
|
promises.push(user.updateLastOnlineTime(req.uid));
|
||||||
|
}
|
||||||
|
await Promise.all(promises);
|
||||||
|
plugins.fireHook('action:middleware.pageView', { req: req });
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
middleware.pluginHooks = helpers.try(async function pluginHooks(req, res, next) {
|
||||||
|
// TODO: Deprecate in v2.0
|
||||||
|
await async.each(plugins.loadedHooks['filter:router.page'] || [], function (hookObj, next) {
|
||||||
|
hookObj.method(req, res, next);
|
||||||
});
|
});
|
||||||
|
|
||||||
plugins.fireHook('action:middleware.pageView', { req: req });
|
await plugins.fireHook('response:router.page', {
|
||||||
|
req: req,
|
||||||
if (req.loggedIn) {
|
res: res,
|
||||||
if (req.path.startsWith('/api/users') || req.path.startsWith('/users')) {
|
});
|
||||||
async.parallel([
|
|
||||||
async.apply(user.updateOnlineUsers, req.uid),
|
|
||||||
async.apply(user.updateLastOnlineTime, req.uid),
|
|
||||||
], next);
|
|
||||||
} else {
|
|
||||||
user.updateOnlineUsers(req.uid);
|
|
||||||
user.updateLastOnlineTime(req.uid);
|
|
||||||
setImmediate(next);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setImmediate(next);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
middleware.pluginHooks = async function pluginHooks(req, res, next) {
|
|
||||||
// TODO: Deprecate in v2.0
|
|
||||||
try {
|
|
||||||
await async.each(plugins.loadedHooks['filter:router.page'] || [], function (hookObj, next) {
|
|
||||||
hookObj.method(req, res, next);
|
|
||||||
});
|
|
||||||
|
|
||||||
await plugins.fireHook('response:router.page', {
|
|
||||||
req: req,
|
|
||||||
res: res,
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!res.headersSent) {
|
if (!res.headersSent) {
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
middleware.validateFiles = function validateFiles(req, res, next) {
|
middleware.validateFiles = function validateFiles(req, res, next) {
|
||||||
if (!Array.isArray(req.files.files) || !req.files.files.length) {
|
if (!Array.isArray(req.files.files) || !req.files.files.length) {
|
||||||
@@ -131,36 +118,28 @@ middleware.routeTouchIcon = function routeTouchIcon(req, res) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
middleware.privateTagListing = function privateTagListing(req, res, next) {
|
middleware.privateTagListing = helpers.try(async function privateTagListing(req, res, next) {
|
||||||
privileges.global.can('view:tags', req.uid, function (err, canView) {
|
const canView = await privileges.global.can('view:tags', req.uid);
|
||||||
if (err || canView) {
|
if (!canView) {
|
||||||
return next(err);
|
return controllers.helpers.notAllowed(req, res);
|
||||||
}
|
}
|
||||||
controllers.helpers.notAllowed(req, res);
|
next();
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
middleware.exposeGroupName = function exposeGroupName(req, res, next) {
|
middleware.exposeGroupName = helpers.try(async function exposeGroupName(req, res, next) {
|
||||||
expose('groupName', groups.getGroupNameByGroupSlug, 'slug', req, res, next);
|
await expose('groupName', groups.getGroupNameByGroupSlug, 'slug', req, res, next);
|
||||||
};
|
});
|
||||||
|
|
||||||
middleware.exposeUid = function exposeUid(req, res, next) {
|
middleware.exposeUid = helpers.try(async function exposeUid(req, res, next) {
|
||||||
expose('uid', user.getUidByUserslug, 'userslug', req, res, next);
|
await expose('uid', user.getUidByUserslug, 'userslug', req, res, next);
|
||||||
};
|
});
|
||||||
|
|
||||||
function expose(exposedField, method, field, req, res, next) {
|
async function expose(exposedField, method, field, req, res, next) {
|
||||||
if (!req.params.hasOwnProperty(field)) {
|
if (!req.params.hasOwnProperty(field)) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
async.waterfall([
|
res.locals[exposedField] = await method(req.params[field]);
|
||||||
function (next) {
|
next();
|
||||||
method(req.params[field], next);
|
|
||||||
},
|
|
||||||
function (id, next) {
|
|
||||||
res.locals[exposedField] = id;
|
|
||||||
next();
|
|
||||||
},
|
|
||||||
], next);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
middleware.privateUploads = function privateUploads(req, res, next) {
|
middleware.privateUploads = function privateUploads(req, res, next) {
|
||||||
@@ -188,10 +167,13 @@ middleware.busyCheck = function busyCheck(req, res, next) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
middleware.applyBlacklist = function applyBlacklist(req, res, next) {
|
middleware.applyBlacklist = async function applyBlacklist(req, res, next) {
|
||||||
meta.blacklist.test(req.ip, function (err) {
|
try {
|
||||||
|
await meta.blacklist.test(req.ip);
|
||||||
|
next();
|
||||||
|
} catch (err) {
|
||||||
next(err);
|
next(err);
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
middleware.delayLoading = function delayLoading(req, res, next) {
|
middleware.delayLoading = function delayLoading(req, res, next) {
|
||||||
@@ -207,25 +189,19 @@ middleware.delayLoading = function delayLoading(req, res, next) {
|
|||||||
setTimeout(next, 1000);
|
setTimeout(next, 1000);
|
||||||
};
|
};
|
||||||
|
|
||||||
middleware.buildSkinAsset = function buildSkinAsset(req, res, next) {
|
middleware.buildSkinAsset = helpers.try(async function buildSkinAsset(req, res, next) {
|
||||||
// If this middleware is reached, a skin was requested, so it is built on-demand
|
// If this middleware is reached, a skin was requested, so it is built on-demand
|
||||||
var target = path.basename(req.originalUrl).match(/(client-[a-z]+)/);
|
const target = path.basename(req.originalUrl).match(/(client-[a-z]+)/);
|
||||||
if (target) {
|
if (!target) {
|
||||||
async.waterfall([
|
return next();
|
||||||
async.apply(plugins.prepareForBuild, ['client side styles']),
|
|
||||||
async.apply(meta.css.buildBundle, target[0], true),
|
|
||||||
], function (err, css) {
|
|
||||||
if (err) {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
require('../meta/minifier').killAll();
|
|
||||||
res.status(200).type('text/css').send(css);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setImmediate(next);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
await plugins.prepareForBuild(['client side styles']);
|
||||||
|
const buildBundle = util.promisify(meta.css.buildBundle);
|
||||||
|
const css = await buildBundle(target[0], true);
|
||||||
|
require('../meta/minifier').killAll();
|
||||||
|
res.status(200).type('text/css').send(css);
|
||||||
|
});
|
||||||
|
|
||||||
middleware.trimUploadTimestamps = function trimUploadTimestamps(req, res, next) {
|
middleware.trimUploadTimestamps = function trimUploadTimestamps(req, res, next) {
|
||||||
// Check match
|
// Check match
|
||||||
@@ -238,19 +214,18 @@ middleware.trimUploadTimestamps = function trimUploadTimestamps(req, res, next)
|
|||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
|
||||||
middleware.validateAuth = function validateAuth(req, res, next) {
|
middleware.validateAuth = helpers.try(async function validateAuth(req, res, next) {
|
||||||
plugins.fireHook('static:auth.validate', {
|
try {
|
||||||
user: res.locals.user,
|
await plugins.fireHook('static:auth.validate', {
|
||||||
strategy: res.locals.strategy,
|
user: res.locals.user,
|
||||||
}, function (err) {
|
strategy: res.locals.strategy,
|
||||||
if (err) {
|
});
|
||||||
return req.session.regenerate(function () {
|
|
||||||
req.uid = 0;
|
|
||||||
req.loggedIn = false;
|
|
||||||
next(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
} catch (err) {
|
||||||
};
|
const regenerateSession = util.promisify(cb => req.session.regenerate(cb));
|
||||||
|
await regenerateSession();
|
||||||
|
req.uid = 0;
|
||||||
|
req.loggedIn = false;
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ const util = require('util');
|
|||||||
const nconf = require('nconf');
|
const nconf = require('nconf');
|
||||||
const meta = require('../meta');
|
const meta = require('../meta');
|
||||||
const user = require('../user');
|
const user = require('../user');
|
||||||
|
const helpers = require('./helpers');
|
||||||
|
|
||||||
module.exports = function (middleware) {
|
module.exports = function (middleware) {
|
||||||
middleware.maintenanceMode = async function maintenanceMode(req, res, next) {
|
middleware.maintenanceMode = helpers.try(async function maintenanceMode(req, res, next) {
|
||||||
if (!meta.config.maintenanceMode) {
|
if (!meta.config.maintenanceMode) {
|
||||||
return setImmediate(next);
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
const hooksAsync = util.promisify(middleware.pluginHooks);
|
const hooksAsync = util.promisify(middleware.pluginHooks);
|
||||||
@@ -16,12 +17,12 @@ module.exports = function (middleware) {
|
|||||||
|
|
||||||
const url = req.url.replace(nconf.get('relative_path'), '');
|
const url = req.url.replace(nconf.get('relative_path'), '');
|
||||||
if (url.startsWith('/login') || url.startsWith('/api/login')) {
|
if (url.startsWith('/login') || url.startsWith('/api/login')) {
|
||||||
return setImmediate(next);
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
const isAdmin = await user.isAdministrator(req.uid);
|
const isAdmin = await user.isAdministrator(req.uid);
|
||||||
if (isAdmin) {
|
if (isAdmin) {
|
||||||
return setImmediate(next);
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
res.status(meta.config.maintenanceModeStatus);
|
res.status(meta.config.maintenanceModeStatus);
|
||||||
@@ -37,5 +38,5 @@ module.exports = function (middleware) {
|
|||||||
const buildHeaderAsync = util.promisify(middleware.buildHeader);
|
const buildHeaderAsync = util.promisify(middleware.buildHeader);
|
||||||
await buildHeaderAsync(req, res);
|
await buildHeaderAsync(req, res);
|
||||||
res.render('503', data);
|
res.render('503', data);
|
||||||
};
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const util = require('util');
|
|
||||||
const nconf = require('nconf');
|
const nconf = require('nconf');
|
||||||
const winston = require('winston');
|
const winston = require('winston');
|
||||||
|
|
||||||
@@ -8,7 +7,7 @@ const meta = require('../meta');
|
|||||||
const user = require('../user');
|
const user = require('../user');
|
||||||
const privileges = require('../privileges');
|
const privileges = require('../privileges');
|
||||||
const plugins = require('../plugins');
|
const plugins = require('../plugins');
|
||||||
|
const helpers = require('./helpers');
|
||||||
const auth = require('../routes/authentication');
|
const auth = require('../routes/authentication');
|
||||||
|
|
||||||
const controllers = {
|
const controllers = {
|
||||||
@@ -16,9 +15,9 @@ const controllers = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.exports = function (middleware) {
|
module.exports = function (middleware) {
|
||||||
async function authenticate(req, res, next, callback) {
|
async function authenticate(req, res) {
|
||||||
if (req.loggedIn) {
|
if (req.loggedIn) {
|
||||||
return next();
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
await plugins.fireHook('response:middleware.authenticate', {
|
await plugins.fireHook('response:middleware.authenticate', {
|
||||||
@@ -28,35 +27,35 @@ module.exports = function (middleware) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!res.headersSent) {
|
if (!res.headersSent) {
|
||||||
auth.setAuthVars(req, res, function () {
|
auth.setAuthVars(req);
|
||||||
if (req.loggedIn && req.user && req.user.uid) {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
return !res.headersSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
middleware.authenticate = function middlewareAuthenticate(req, res, next) {
|
middleware.authenticate = helpers.try(async function middlewareAuthenticate(req, res, next) {
|
||||||
authenticate(req, res, next, function () {
|
if (!await authenticate(req, res)) {
|
||||||
controllers.helpers.notAllowed(req, res, next);
|
return;
|
||||||
});
|
}
|
||||||
};
|
if (!req.loggedIn) {
|
||||||
|
return controllers.helpers.notAllowed(req, res);
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
const authenticateAsync = util.promisify(middleware.authenticate);
|
middleware.authenticateOrGuest = helpers.try(async function authenticateOrGuest(req, res, next) {
|
||||||
|
if (!await authenticate(req, res)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
middleware.authenticateOrGuest = function authenticateOrGuest(req, res, next) {
|
middleware.ensureSelfOrGlobalPrivilege = helpers.try(async function ensureSelfOrGlobalPrivilege(req, res, next) {
|
||||||
authenticate(req, res, next, next);
|
await ensureSelfOrMethod(user.isAdminOrGlobalMod, req, res, next);
|
||||||
};
|
});
|
||||||
|
|
||||||
middleware.ensureSelfOrGlobalPrivilege = function ensureSelfOrGlobalPrivilege(req, res, next) {
|
middleware.ensureSelfOrPrivileged = helpers.try(async function ensureSelfOrPrivileged(req, res, next) {
|
||||||
ensureSelfOrMethod(user.isAdminOrGlobalMod, req, res, next);
|
await ensureSelfOrMethod(user.isPrivileged, req, res, next);
|
||||||
};
|
});
|
||||||
|
|
||||||
middleware.ensureSelfOrPrivileged = function ensureSelfOrPrivileged(req, res, next) {
|
|
||||||
ensureSelfOrMethod(user.isPrivileged, req, res, next);
|
|
||||||
};
|
|
||||||
|
|
||||||
async function ensureSelfOrMethod(method, req, res, next) {
|
async function ensureSelfOrMethod(method, req, res, next) {
|
||||||
/*
|
/*
|
||||||
@@ -67,7 +66,7 @@ module.exports = function (middleware) {
|
|||||||
return controllers.helpers.notAllowed(req, res);
|
return controllers.helpers.notAllowed(req, res);
|
||||||
}
|
}
|
||||||
if (req.uid === parseInt(res.locals.uid, 10)) {
|
if (req.uid === parseInt(res.locals.uid, 10)) {
|
||||||
return setImmediate(next);
|
return next();
|
||||||
}
|
}
|
||||||
const allowed = await method(req.uid);
|
const allowed = await method(req.uid);
|
||||||
if (!allowed) {
|
if (!allowed) {
|
||||||
@@ -77,12 +76,12 @@ module.exports = function (middleware) {
|
|||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
middleware.checkGlobalPrivacySettings = function checkGlobalPrivacySettings(req, res, next) {
|
middleware.checkGlobalPrivacySettings = helpers.try(async function checkGlobalPrivacySettings(req, res, next) {
|
||||||
winston.warn('[middleware], checkGlobalPrivacySettings deprecated, use canViewUsers or canViewGroups');
|
winston.warn('[middleware], checkGlobalPrivacySettings deprecated, use canViewUsers or canViewGroups');
|
||||||
middleware.canViewUsers(req, res, next);
|
await middleware.canViewUsers(req, res, next);
|
||||||
};
|
});
|
||||||
|
|
||||||
middleware.canViewUsers = async function canViewUsers(req, res, next) {
|
middleware.canViewUsers = helpers.try(async function canViewUsers(req, res, next) {
|
||||||
if (parseInt(res.locals.uid, 10) === req.uid) {
|
if (parseInt(res.locals.uid, 10) === req.uid) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
@@ -91,19 +90,24 @@ module.exports = function (middleware) {
|
|||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
controllers.helpers.notAllowed(req, res);
|
controllers.helpers.notAllowed(req, res);
|
||||||
};
|
});
|
||||||
|
|
||||||
middleware.canViewGroups = async function canViewGroups(req, res, next) {
|
middleware.canViewGroups = helpers.try(async function canViewGroups(req, res, next) {
|
||||||
const canView = await privileges.global.can('view:groups', req.uid);
|
const canView = await privileges.global.can('view:groups', req.uid);
|
||||||
if (canView) {
|
if (canView) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
controllers.helpers.notAllowed(req, res);
|
controllers.helpers.notAllowed(req, res);
|
||||||
};
|
});
|
||||||
|
|
||||||
middleware.checkAccountPermissions = async function checkAccountPermissions(req, res, next) {
|
middleware.checkAccountPermissions = helpers.try(async function checkAccountPermissions(req, res, next) {
|
||||||
// This middleware ensures that only the requested user and admins can pass
|
// This middleware ensures that only the requested user and admins can pass
|
||||||
await authenticateAsync(req, res);
|
if (!await authenticate(req, res)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!req.loggedIn) {
|
||||||
|
return controllers.helpers.notAllowed(req, res);
|
||||||
|
}
|
||||||
const uid = await user.getUidByUserslug(req.params.userslug);
|
const uid = await user.getUidByUserslug(req.params.userslug);
|
||||||
let allowed = await privileges.users.canEdit(req.uid, uid);
|
let allowed = await privileges.users.canEdit(req.uid, uid);
|
||||||
if (allowed) {
|
if (allowed) {
|
||||||
@@ -117,17 +121,17 @@ module.exports = function (middleware) {
|
|||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
controllers.helpers.notAllowed(req, res);
|
controllers.helpers.notAllowed(req, res);
|
||||||
};
|
});
|
||||||
|
|
||||||
middleware.redirectToAccountIfLoggedIn = async function redirectToAccountIfLoggedIn(req, res, next) {
|
middleware.redirectToAccountIfLoggedIn = helpers.try(async function redirectToAccountIfLoggedIn(req, res, next) {
|
||||||
if (req.session.forceLogin || req.uid <= 0) {
|
if (req.session.forceLogin || req.uid <= 0) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
const userslug = await user.getUserField(req.uid, 'userslug');
|
const userslug = await user.getUserField(req.uid, 'userslug');
|
||||||
controllers.helpers.redirect(res, '/user/' + userslug);
|
controllers.helpers.redirect(res, '/user/' + userslug);
|
||||||
};
|
});
|
||||||
|
|
||||||
middleware.redirectUidToUserslug = async function redirectUidToUserslug(req, res, next) {
|
middleware.redirectUidToUserslug = helpers.try(async function redirectUidToUserslug(req, res, next) {
|
||||||
const uid = parseInt(req.params.uid, 10);
|
const uid = parseInt(req.params.uid, 10);
|
||||||
if (uid <= 0) {
|
if (uid <= 0) {
|
||||||
return next();
|
return next();
|
||||||
@@ -140,18 +144,18 @@ module.exports = function (middleware) {
|
|||||||
.replace('uid', 'user')
|
.replace('uid', 'user')
|
||||||
.replace(uid, function () { return userslug; });
|
.replace(uid, function () { return userslug; });
|
||||||
controllers.helpers.redirect(res, path);
|
controllers.helpers.redirect(res, path);
|
||||||
};
|
});
|
||||||
|
|
||||||
middleware.redirectMeToUserslug = async function redirectMeToUserslug(req, res) {
|
middleware.redirectMeToUserslug = helpers.try(async function redirectMeToUserslug(req, res) {
|
||||||
const userslug = await user.getUserField(req.uid, 'userslug');
|
const userslug = await user.getUserField(req.uid, 'userslug');
|
||||||
if (!userslug) {
|
if (!userslug) {
|
||||||
return controllers.helpers.notAllowed(req, res);
|
return controllers.helpers.notAllowed(req, res);
|
||||||
}
|
}
|
||||||
const path = req.path.replace(/^(\/api)?\/me/, '/user/' + userslug);
|
const path = req.path.replace(/^(\/api)?\/me/, '/user/' + userslug);
|
||||||
controllers.helpers.redirect(res, path);
|
controllers.helpers.redirect(res, path);
|
||||||
};
|
});
|
||||||
|
|
||||||
middleware.isAdmin = async function isAdmin(req, res, next) {
|
middleware.isAdmin = helpers.try(async function isAdmin(req, res, next) {
|
||||||
const isAdmin = await user.isAdministrator(req.uid);
|
const isAdmin = await user.isAdministrator(req.uid);
|
||||||
if (!isAdmin) {
|
if (!isAdmin) {
|
||||||
return controllers.helpers.notAllowed(req, res);
|
return controllers.helpers.notAllowed(req, res);
|
||||||
@@ -186,7 +190,7 @@ module.exports = function (middleware) {
|
|||||||
} else {
|
} else {
|
||||||
res.redirect(nconf.get('relative_path') + '/login?local=1');
|
res.redirect(nconf.get('relative_path') + '/login?local=1');
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
middleware.requireUser = function (req, res, next) {
|
middleware.requireUser = function (req, res, next) {
|
||||||
if (req.loggedIn) {
|
if (req.loggedIn) {
|
||||||
|
|||||||
@@ -23,14 +23,17 @@ Auth.initialize = function (app, middleware) {
|
|||||||
passportSessionMiddleware(req, res, next);
|
passportSessionMiddleware(req, res, next);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use(Auth.setAuthVars);
|
app.use(function (req, res, next) {
|
||||||
|
Auth.setAuthVars(req, res);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
Auth.app = app;
|
Auth.app = app;
|
||||||
Auth.middleware = middleware;
|
Auth.middleware = middleware;
|
||||||
};
|
};
|
||||||
|
|
||||||
Auth.setAuthVars = function setAuthVars(req, res, next) {
|
Auth.setAuthVars = function setAuthVars(req) {
|
||||||
var isSpider = req.isSpider();
|
const isSpider = req.isSpider();
|
||||||
req.loggedIn = !isSpider && !!req.user;
|
req.loggedIn = !isSpider && !!req.user;
|
||||||
if (req.user) {
|
if (req.user) {
|
||||||
req.uid = parseInt(req.user.uid, 10);
|
req.uid = parseInt(req.user.uid, 10);
|
||||||
@@ -39,7 +42,6 @@ Auth.setAuthVars = function setAuthVars(req, res, next) {
|
|||||||
} else {
|
} else {
|
||||||
req.uid = 0;
|
req.uid = 0;
|
||||||
}
|
}
|
||||||
next();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Auth.getLoginStrategies = function () {
|
Auth.getLoginStrategies = function () {
|
||||||
|
|||||||
Reference in New Issue
Block a user