diff --git a/src/middleware/index.js b/src/middleware/index.js index dbe16fc9fd..90e5cee1cd 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -11,67 +11,8 @@ var templates = require('./../../public/src/templates'), winston = require('winston'); -/* -* todo: move out into their own file(s) -*/ var middleware = {}; -middleware.processRender = function(req, res, next) { - // res.render post-processing, modified from here: https://gist.github.com/mrlannigan/5051687 - var render = res.render; - res.render = function(template, options, fn) { - var self = this, - options = options || {}, - req = this.req, - app = req.app, - defaultFn = function(err, str){ - if (err) { - return req.next(err); - } - - self.send(str); - }; - - if ('function' == typeof options) { - fn = options, options = {}; - } - - if ('function' != typeof fn) { - fn = defaultFn; - } - - render.call(self, template, options, function(err, str) { - if (res.locals.header) { - str = res.locals.header + str; - } - - if (res.locals.footer) { - str = str + res.locals.footer; - } - - if (str) { - translator.translate(str, function(translated) { - fn(err, translated); - }); - } else { - fn(err, str); - } - }); - }; - - next(); -}; - -middleware.routeTouchIcon = function(req, res) { - if (meta.config['brand:logo'] && validator.isURL(meta.config['brand:logo'])) { - return res.redirect(meta.config['brand:logo']); - } else { - return res.sendfile(path.join(__dirname, '../../public', meta.config['brand:logo'] || nconf.get('relative_path') + '/logo.png'), { - maxAge: app.enabled('cache') ? 5184000000 : 0 - }); - } -} - /* * Helper functions */ @@ -187,7 +128,8 @@ function catch404(req, res, next) { } module.exports = function(app, data) { - // Middlewares + middleware = require('./middleware')(app); + app.configure(function() { app.engine('tpl', templates.__express); app.set('view engine', 'tpl'); @@ -248,4 +190,6 @@ module.exports = function(app, data) { app.use(catch404); app.use(handleErrors); }); + + return middleware; }; \ No newline at end of file diff --git a/src/middleware/middleware.js b/src/middleware/middleware.js new file mode 100644 index 0000000000..cdb48f576a --- /dev/null +++ b/src/middleware/middleware.js @@ -0,0 +1,284 @@ +var app, + middleware = {}; + +middleware.prepareAPI = function(req, res, next) { + res.locals.isAPI = true; + next(); +}; + +middleware.authenticate = function(req, res, next) { + if(!req.user) { + if (res.locals.isAPI) { + return res.json(403, 'not-allowed'); + } else { + return res.redirect('403'); + } + } else { + next(); + } +}; + +middleware.checkGlobalPrivacySettings = function(req, res, next) { + var callerUID = req.user ? parseInt(req.user.uid, 10) : 0; + + if (!callerUID && !!parseInt(meta.config.privateUserInfo, 10)) { + if (res.locals.isAPI) { + return res.json(403, 'not-allowed'); + } else { + return res.redirect('403'); + } + } + + next(); +}; + +middleware.checkAccountPermissions = function(req, res, next) { + var callerUID = req.user ? parseInt(req.user.uid, 10) : 0; + + // this function requires userslug to be passed in. todo: /user/uploadpicture should pass in userslug I think + user.getUidByUserslug(req.params.userslug, function (err, uid) { + if (err) { + return next(err); + } + + // not sure if this check really should belong here. also make sure we're not doing this check again in the actual method + if (!uid) { + if (res.locals.isAPI) { + return res.json(404); + } else { + return res.redirect('404'); + } + } + + if (parseInt(uid, 10) === callerUID) { + return next(); + } + + user.isAdministrator(callerUID, function(err, isAdmin) { + if(err) { + return next(err); + } + + if(isAdmin) { + next(); + } + + if (res.locals.isAPI) { + return res.json(403, 'not-allowed'); + } else { + return res.redirect('403'); + } + }); + }); +}; + +middleware.buildHeader = function(req, res, next) { + async.parallel([ + function(next) { + // temp, don't forget to set metaTags and linkTags to res.locals.header + middleware.build_header({ + req: req, + res: res + }, function(err, template) { + res.locals.header = template; + next(err); + }); + }, + function(next) { + // this is slower than the original implementation because the rendered template is not cached + // but I didn't bother to fix this because we will deprecate [filter:footer.build] in favour of the widgets system by 0.4x + plugins.fireHook('filter:footer.build', '', function(err, appendHTML) { + app.render('footer', {footerHTML: appendHTML}, function(err, template) { + translator.translate(template, function(parsedTemplate) { + res.locals.footer = template; + next(err); + }); + }); + }); + } + ], function(err) { + next(); + }); +}; + +/** + * `options` object requires: req, res + * accepts: metaTags, linkTags + */ +middleware.build_header = function (options, callback) { + var custom_header = { + 'navigation': [] + }; + + plugins.fireHook('filter:header.build', custom_header, function(err, custom_header) { + var defaultMetaTags = [{ + name: 'viewport', + content: 'width=device-width, initial-scale=1.0, user-scalable=no' + }, { + name: 'content-type', + content: 'text/html; charset=UTF-8' + }, { + name: 'apple-mobile-web-app-capable', + content: 'yes' + }, { + property: 'og:site_name', + content: meta.config.title || 'NodeBB' + }, { + property: 'keywords', + content: meta.config.keywords || '' + }], + defaultLinkTags = [{ + rel: 'apple-touch-icon', + href: '/apple-touch-icon' + }], + templateValues = { + bootswatchCSS: meta.config['theme:src'], + pluginCSS: plugins.cssFiles.map(function(file) { return { path: nconf.get('relative_path') + file.replace(/\\/g, '/') }; }), + title: meta.config.title || '', + description: meta.config.description || '', + 'brand:logo': meta.config['brand:logo'] || '', + 'brand:logo:display': meta.config['brand:logo']?'':'hide', + csrf: options.res.locals.csrf_token, + relative_path: nconf.get('relative_path'), + clientScripts: clientScripts, + navigation: custom_header.navigation, + 'cache-buster': meta.config['cache-buster'] ? 'v=' + meta.config['cache-buster'] : '', + allowRegistration: meta.config.allowRegistration === undefined || parseInt(meta.config.allowRegistration, 10) === 1, + searchEnabled: plugins.hasListeners('filter:search.query') ? true : false + }, + escapeList = { + '&': '&', + '<': '<', + '>': '>', + "'": ''', + '"': '"' + }; + + var uid = '0'; + + // Meta Tags + /*templateValues.metaTags = defaultMetaTags.concat(options.metaTags || []).map(function(tag) { + if(!tag || typeof tag.content !== 'string') { + winston.warn('Invalid meta tag. ', tag); + return tag; + } + + tag.content = tag.content.replace(/[&<>'"]/g, function(tag) { + return escapeList[tag] || tag; + }); + return tag; + });*/ + + // Link Tags + /*templateValues.linkTags = defaultLinkTags.concat(options.linkTags || []); + templateValues.linkTags.push({ + rel: "icon", + type: "image/x-icon", + href: nconf.get('relative_path') + '/favicon.ico' + });*/ + + if(options.req.user && options.req.user.uid) { + uid = options.req.user.uid; + } + + // Custom CSS + templateValues.useCustomCSS = false; + if (meta.config.useCustomCSS === '1') { + templateValues.useCustomCSS = true; + templateValues.customCSS = meta.config.customCSS; + } + + async.parallel([ + function(next) { + translator.get('pages:' + path.basename(options.req.url), function(translated) { + /*var metaTitle = templateValues.metaTags.filter(function(tag) { + return tag.name === 'title'; + }); + if (translated) { + templateValues.browserTitle = translated; + } else if (metaTitle.length > 0 && metaTitle[0].content) { + templateValues.browserTitle = metaTitle[0].content; + } else { + templateValues.browserTitle = meta.config.browserTitle || 'NodeBB'; + }*/ + + next(); + }); + }, + function(next) { + user.isAdministrator(uid, function(err, isAdmin) { + templateValues.isAdmin = isAdmin || false; + next(); + }); + } + ], function() { + /*translator.translate(templates.header.parse(templateValues), function(template) { + callback(null, template); + });*/ + app.render('header', templateValues, function(err, template) { + callback(null, template) + }); + }); + }); +}; + +middleware.processRender = function(req, res, next) { + // res.render post-processing, modified from here: https://gist.github.com/mrlannigan/5051687 + var render = res.render; + res.render = function(template, options, fn) { + var self = this, + options = options || {}, + req = this.req, + app = req.app, + defaultFn = function(err, str){ + if (err) { + return req.next(err); + } + + self.send(str); + }; + + if ('function' == typeof options) { + fn = options, options = {}; + } + + if ('function' != typeof fn) { + fn = defaultFn; + } + + render.call(self, template, options, function(err, str) { + if (res.locals.header) { + str = res.locals.header + str; + } + + if (res.locals.footer) { + str = str + res.locals.footer; + } + + if (str) { + translator.translate(str, function(translated) { + fn(err, translated); + }); + } else { + fn(err, str); + } + }); + }; + + next(); +}; + +middleware.routeTouchIcon = function(req, res) { + if (meta.config['brand:logo'] && validator.isURL(meta.config['brand:logo'])) { + return res.redirect(meta.config['brand:logo']); + } else { + return res.sendfile(path.join(__dirname, '../../public', meta.config['brand:logo'] || nconf.get('relative_path') + '/logo.png'), { + maxAge: app.enabled('cache') ? 5184000000 : 0 + }); + } +} + +module.exports = function(webserver) { + app = webserver; + return middleware; +} \ No newline at end of file diff --git a/src/routes/index.js b/src/routes/index.js index 11ca7bc1eb..09e5de7415 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -1,4 +1,6 @@ -var controllers = require('./../controllers'), +var nconf = require('nconf'), + controllers = require('./../controllers'), + middleware = {}, /*temp*/ plugins = require('./../plugins'), @@ -8,8 +10,8 @@ var controllers = require('./../controllers'), feedsRoute = require('./feeds'); -module.exports = function(app, relativePath) { - app.namespace(relativePath, function() { +module.exports = function(app, middleware) { + app.namespace(nconf.get('relative_path'), function() { //temp metaRoute.createRoutes(app); admin.createRoutes(app); @@ -38,102 +40,102 @@ module.exports = function(app, relativePath) { }());*/ /* Main */ - app.get('/', app.buildHeader, controllers.home); - app.get('/api/home', app.prepareAPI, controllers.home); + app.get('/', middleware.buildHeader, controllers.home); + app.get('/api/home', middleware.prepareAPI, controllers.home); - app.get('/login', app.buildHeader, controllers.login); - app.get('/api/login', app.prepareAPI, controllers.login); + app.get('/login', middleware.buildHeader, controllers.login); + app.get('/api/login', middleware.prepareAPI, controllers.login); - app.get('/register', app.buildHeader, controllers.register); - app.get('/api/register', app.prepareAPI, controllers.register); + app.get('/register', middleware.buildHeader, controllers.register); + app.get('/api/register', middleware.prepareAPI, controllers.register); - app.get('/confirm/:code', app.buildHeader, controllers.confirmEmail); - app.get('/api/confirm/:code', app.prepareAPI, controllers.confirmEmail); + app.get('/confirm/:code', middleware.buildHeader, controllers.confirmEmail); + app.get('/api/confirm/:code', middleware.prepareAPI, controllers.confirmEmail); app.get('/sitemap.xml', controllers.sitemap); app.get('/robots.txt', controllers.robots); - app.get('/outgoing', app.buildHeader, controllers.outgoing); - app.get('/api/outgoing', app.prepareAPI, controllers.outgoing); + app.get('/outgoing', middleware.buildHeader, controllers.outgoing); + app.get('/api/outgoing', middleware.prepareAPI, controllers.outgoing); /* Static Pages */ - app.get('/404', app.buildHeader, controllers.static['404']); - app.get('/api/404', app.prepareAPI, controllers.static['404']); + app.get('/404', middleware.buildHeader, controllers.static['404']); + app.get('/api/404', middleware.prepareAPI, controllers.static['404']); - app.get('/403', app.buildHeader, controllers.static['403']); - app.get('/api/403', app.prepareAPI, controllers.static['403']); + app.get('/403', middleware.buildHeader, controllers.static['403']); + app.get('/api/403', middleware.prepareAPI, controllers.static['403']); - app.get('/500', app.buildHeader, controllers.static['500']); - app.get('/api/500', app.prepareAPI, controllers.static['500']); + app.get('/500', middleware.buildHeader, controllers.static['500']); + app.get('/api/500', middleware.prepareAPI, controllers.static['500']); /* Topics */ - app.get('/topic/:topic_id/:slug?', app.buildHeader, controllers.topics.get); - app.get('/api/topic/:topic_id/:slug?', app.prepareAPI, controllers.topics.get); + app.get('/topic/:topic_id/:slug?', middleware.buildHeader, controllers.topics.get); + app.get('/api/topic/:topic_id/:slug?', middleware.prepareAPI, controllers.topics.get); /* Categories */ - app.get('/popular/:set?', app.buildHeader, controllers.categories.popular); - app.get('/api/popular/:set?', app.prepareAPI, controllers.categories.popular); + app.get('/popular/:set?', middleware.buildHeader, controllers.categories.popular); + app.get('/api/popular/:set?', middleware.prepareAPI, controllers.categories.popular); - app.get('/recent/:term?', app.buildHeader, controllers.categories.recent); - app.get('/api/recent/:term?', app.prepareAPI, controllers.categories.recent); + app.get('/recent/:term?', middleware.buildHeader, controllers.categories.recent); + app.get('/api/recent/:term?', middleware.prepareAPI, controllers.categories.recent); - app.get('/unread/', app.buildHeader, app.authenticate, controllers.categories.unread); - app.get('/api/unread/', app.prepareAPI, app.authenticate, controllers.categories.unread); + app.get('/unread/', middleware.buildHeader, middleware.authenticate, controllers.categories.unread); + app.get('/api/unread/', middleware.prepareAPI, middleware.authenticate, controllers.categories.unread); - app.get('/unread/total', app.buildHeader, app.authenticate, controllers.categories.unreadTotal); - app.get('/api/unread/total', app.prepareAPI, app.authenticate, controllers.categories.unreadTotal); + app.get('/unread/total', middleware.buildHeader, middleware.authenticate, controllers.categories.unreadTotal); + app.get('/api/unread/total', middleware.prepareAPI, middleware.authenticate, controllers.categories.unreadTotal); - app.get('/category/:category_id/:slug?', app.buildHeader, controllers.categories.get); - app.get('/api/category/:category_id/:slug?', app.prepareAPI, controllers.categories.get); + app.get('/category/:category_id/:slug?', middleware.buildHeader, controllers.categories.get); + app.get('/api/category/:category_id/:slug?', middleware.prepareAPI, controllers.categories.get); /* Accounts */ - app.get('/user/:userslug', app.buildHeader, app.checkGlobalPrivacySettings, controllers.accounts.getAccount); - app.get('/api/user/:userslug', app.prepareAPI, app.checkGlobalPrivacySettings, controllers.accounts.getAccount); + app.get('/user/:userslug', middleware.buildHeader, middleware.checkGlobalPrivacySettings, controllers.accounts.getAccount); + app.get('/api/user/:userslug', middleware.prepareAPI, middleware.checkGlobalPrivacySettings, controllers.accounts.getAccount); - app.get('/user/:userslug/following', app.buildHeader, app.checkGlobalPrivacySettings, controllers.accounts.getFollowing); - app.get('/api/user/:userslug/following', app.prepareAPI, app.checkGlobalPrivacySettings, controllers.accounts.getFollowing); + app.get('/user/:userslug/following', middleware.buildHeader, middleware.checkGlobalPrivacySettings, controllers.accounts.getFollowing); + app.get('/api/user/:userslug/following', middleware.prepareAPI, middleware.checkGlobalPrivacySettings, controllers.accounts.getFollowing); - app.get('/user/:userslug/followers', app.buildHeader, app.checkGlobalPrivacySettings, controllers.accounts.getFollowers); - app.get('/api/user/:userslug/followers', app.prepareAPI, app.checkGlobalPrivacySettings, controllers.accounts.getFollowers); + app.get('/user/:userslug/followers', middleware.buildHeader, middleware.checkGlobalPrivacySettings, controllers.accounts.getFollowers); + app.get('/api/user/:userslug/followers', middleware.prepareAPI, middleware.checkGlobalPrivacySettings, controllers.accounts.getFollowers); - app.get('/user/:userslug/favourites', app.buildHeader, app.checkGlobalPrivacySettings, app.checkAccountPermissions, controllers.accounts.getFavourites); - app.get('/api/user/:userslug/favourites', app.prepareAPI, app.checkGlobalPrivacySettings, app.checkAccountPermissions, controllers.accounts.getFavourites); + app.get('/user/:userslug/favourites', middleware.buildHeader, middleware.checkGlobalPrivacySettings, middleware.checkAccountPermissions, controllers.accounts.getFavourites); + app.get('/api/user/:userslug/favourites', middleware.prepareAPI, middleware.checkGlobalPrivacySettings, middleware.checkAccountPermissions, controllers.accounts.getFavourites); - app.get('/user/:userslug/posts', app.buildHeader, app.checkGlobalPrivacySettings, controllers.accounts.getPosts); - app.get('/api/user/:userslug/posts', app.prepareAPI, app.checkGlobalPrivacySettings, controllers.accounts.getPosts); + app.get('/user/:userslug/posts', middleware.buildHeader, middleware.checkGlobalPrivacySettings, controllers.accounts.getPosts); + app.get('/api/user/:userslug/posts', middleware.prepareAPI, middleware.checkGlobalPrivacySettings, controllers.accounts.getPosts); - app.get('/user/:userslug/edit', app.buildHeader, app.checkGlobalPrivacySettings, app.checkAccountPermissions, controllers.accounts.accountEdit); - app.get('/api/user/:userslug/edit', app.prepareAPI, app.checkGlobalPrivacySettings, app.checkAccountPermissions, controllers.accounts.accountEdit); + app.get('/user/:userslug/edit', middleware.buildHeader, middleware.checkGlobalPrivacySettings, middleware.checkAccountPermissions, controllers.accounts.accountEdit); + app.get('/api/user/:userslug/edit', middleware.prepareAPI, middleware.checkGlobalPrivacySettings, middleware.checkAccountPermissions, controllers.accounts.accountEdit); // todo: admin recently gained access to this page, pls check if it actually works - app.get('/user/:userslug/settings', app.buildHeader, app.checkGlobalPrivacySettings, app.checkAccountPermissions, controllers.accounts.accountSettings); - app.get('/api/user/:userslug/settings', app.prepareAPI, app.checkGlobalPrivacySettings, app.checkAccountPermissions, controllers.accounts.accountSettings); + app.get('/user/:userslug/settings', middleware.buildHeader, middleware.checkGlobalPrivacySettings, middleware.checkAccountPermissions, controllers.accounts.accountSettings); + app.get('/api/user/:userslug/settings', middleware.prepareAPI, middleware.checkGlobalPrivacySettings, middleware.checkAccountPermissions, controllers.accounts.accountSettings); - app.get('/api/user/uid/:uid', app.checkGlobalPrivacySettings, controllers.accounts.getUserByUID); + app.get('/api/user/uid/:uid', middleware.checkGlobalPrivacySettings, controllers.accounts.getUserByUID); // this should have been in the API namespace // also, perhaps pass in :userslug so we can use checkAccountPermissions middleware, in future will allow admins to upload a picture for a user - app.post('/user/uploadpicture', app.prepareAPI, app.checkGlobalPrivacySettings, /*app.checkAccountPermissions,*/ controllers.accounts.uploadPicture); + app.post('/user/uploadpicture', middleware.prepareAPI, middleware.checkGlobalPrivacySettings, /*middleware.checkAccountPermissions,*/ controllers.accounts.uploadPicture); /* Users */ - app.get('/users', app.buildHeader, app.checkGlobalPrivacySettings, controllers.users.getOnlineUsers); - app.get('/api/users', app.prepareAPI, app.checkGlobalPrivacySettings, controllers.users.getOnlineUsers); + app.get('/users', middleware.buildHeader, middleware.checkGlobalPrivacySettings, controllers.users.getOnlineUsers); + app.get('/api/users', middleware.prepareAPI, middleware.checkGlobalPrivacySettings, controllers.users.getOnlineUsers); // was this duped by accident or purpose? - app.get('/users/online', app.buildHeader, app.checkGlobalPrivacySettings, controllers.users.getOnlineUsers); - app.get('/api/users/online', app.prepareAPI, app.checkGlobalPrivacySettings, controllers.users.getOnlineUsers); + app.get('/users/online', middleware.buildHeader, middleware.checkGlobalPrivacySettings, controllers.users.getOnlineUsers); + app.get('/api/users/online', middleware.prepareAPI, middleware.checkGlobalPrivacySettings, controllers.users.getOnlineUsers); - app.get('/users/sort-posts', app.buildHeader, app.checkGlobalPrivacySettings, controllers.users.getUsersSortedByPosts); - app.get('/api/users/sort-posts', app.prepareAPI, app.checkGlobalPrivacySettings, controllers.users.getUsersSortedByPosts); + app.get('/users/sort-posts', middleware.buildHeader, middleware.checkGlobalPrivacySettings, controllers.users.getUsersSortedByPosts); + app.get('/api/users/sort-posts', middleware.prepareAPI, middleware.checkGlobalPrivacySettings, controllers.users.getUsersSortedByPosts); - app.get('/users/sort-reputation', app.buildHeader, app.checkGlobalPrivacySettings, controllers.users.getUsersSortedByReputation); - app.get('/api/users/sort-reputation', app.prepareAPI, app.checkGlobalPrivacySettings, controllers.users.getUsersSortedByReputation); + app.get('/users/sort-reputation', middleware.buildHeader, middleware.checkGlobalPrivacySettings, controllers.users.getUsersSortedByReputation); + app.get('/api/users/sort-reputation', middleware.prepareAPI, middleware.checkGlobalPrivacySettings, controllers.users.getUsersSortedByReputation); - app.get('/users/latest', app.buildHeader, app.checkGlobalPrivacySettings, controllers.users.getUsersSortedByJoinDate); - app.get('/api/users/latest', app.prepareAPI, app.checkGlobalPrivacySettings, controllers.users.getUsersSortedByJoinDate); + app.get('/users/latest', middleware.buildHeader, middleware.checkGlobalPrivacySettings, controllers.users.getUsersSortedByJoinDate); + app.get('/api/users/latest', middleware.prepareAPI, middleware.checkGlobalPrivacySettings, controllers.users.getUsersSortedByJoinDate); - app.get('/users/search', app.buildHeader, app.checkGlobalPrivacySettings, controllers.users.getUsersForSearch); - app.get('/api/users/search', app.prepareAPI, app.checkGlobalPrivacySettings, controllers.users.getUsersForSearch); + app.get('/users/search', middleware.buildHeader, middleware.checkGlobalPrivacySettings, controllers.users.getUsersForSearch); + app.get('/api/users/search', middleware.prepareAPI, middleware.checkGlobalPrivacySettings, controllers.users.getUsersForSearch); diff --git a/src/webserver.js b/src/webserver.js index 810aa284b7..2a0434e458 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -64,8 +64,8 @@ if(nconf.get('ssl')) { db.getObjectFields('config', ['theme:type', 'theme:id', 'theme:staticDir', 'theme:templates'], next); } }, function(err, data) { - middleware(app, data); - routes(app, nconf.get('relative_path')); + middleware = middleware(app, data); + routes(app, middleware); if (err) { winston.error('Errors were encountered while attempting to initialise NodeBB.'); @@ -76,229 +76,6 @@ if(nconf.get('ssl')) { } } }); - - - - app.prepareAPI = function(req, res, next) { - res.locals.isAPI = true; - next(); - }; - - app.authenticate = function(req, res, next) { - if(!req.user) { - if (res.locals.isAPI) { - return res.json(403, 'not-allowed'); - } else { - return res.redirect('403'); - } - } else { - next(); - } - }; - - app.checkGlobalPrivacySettings = function(req, res, next) { - var callerUID = req.user ? parseInt(req.user.uid, 10) : 0; - - if (!callerUID && !!parseInt(meta.config.privateUserInfo, 10)) { - if (res.locals.isAPI) { - return res.json(403, 'not-allowed'); - } else { - return res.redirect('403'); - } - } - - next(); - }; - - app.checkAccountPermissions = function(req, res, next) { - var callerUID = req.user ? parseInt(req.user.uid, 10) : 0; - - // this function requires userslug to be passed in. todo: /user/uploadpicture should pass in userslug I think - user.getUidByUserslug(req.params.userslug, function (err, uid) { - if (err) { - return next(err); - } - - // not sure if this check really should belong here. also make sure we're not doing this check again in the actual method - if (!uid) { - if (res.locals.isAPI) { - return res.json(404); - } else { - return res.redirect('404'); - } - } - - if (parseInt(uid, 10) === callerUID) { - return next(); - } - - user.isAdministrator(callerUID, function(err, isAdmin) { - if(err) { - return next(err); - } - - if(isAdmin) { - next(); - } - - if (res.locals.isAPI) { - return res.json(403, 'not-allowed'); - } else { - return res.redirect('403'); - } - }); - }); - }; - - app.buildHeader = function(req, res, next) { - async.parallel([ - function(next) { - // temp, don't forget to set metaTags and linkTags to res.locals.header - app.build_header({ - req: req, - res: res - }, function(err, template) { - res.locals.header = template; - next(err); - }); - }, - function(next) { - // this is slower than the original implementation because the rendered template is not cached - // but I didn't bother to fix this because we will deprecate [filter:footer.build] in favour of the widgets system by 0.4x - plugins.fireHook('filter:footer.build', '', function(err, appendHTML) { - app.render('footer', {footerHTML: appendHTML}, function(err, template) { - translator.translate(template, function(parsedTemplate) { - res.locals.footer = template; - next(err); - }); - }); - }); - } - ], function(err) { - next(); - }); - }; - - /** - * `options` object requires: req, res - * accepts: metaTags, linkTags - */ - app.build_header = function (options, callback) { - var custom_header = { - 'navigation': [] - }; - - plugins.fireHook('filter:header.build', custom_header, function(err, custom_header) { - var defaultMetaTags = [{ - name: 'viewport', - content: 'width=device-width, initial-scale=1.0, user-scalable=no' - }, { - name: 'content-type', - content: 'text/html; charset=UTF-8' - }, { - name: 'apple-mobile-web-app-capable', - content: 'yes' - }, { - property: 'og:site_name', - content: meta.config.title || 'NodeBB' - }, { - property: 'keywords', - content: meta.config.keywords || '' - }], - defaultLinkTags = [{ - rel: 'apple-touch-icon', - href: '/apple-touch-icon' - }], - templateValues = { - bootswatchCSS: meta.config['theme:src'], - pluginCSS: plugins.cssFiles.map(function(file) { return { path: nconf.get('relative_path') + file.replace(/\\/g, '/') }; }), - title: meta.config.title || '', - description: meta.config.description || '', - 'brand:logo': meta.config['brand:logo'] || '', - 'brand:logo:display': meta.config['brand:logo']?'':'hide', - csrf: options.res.locals.csrf_token, - relative_path: nconf.get('relative_path'), - clientScripts: clientScripts, - navigation: custom_header.navigation, - 'cache-buster': meta.config['cache-buster'] ? 'v=' + meta.config['cache-buster'] : '', - allowRegistration: meta.config.allowRegistration === undefined || parseInt(meta.config.allowRegistration, 10) === 1, - searchEnabled: plugins.hasListeners('filter:search.query') ? true : false - }, - escapeList = { - '&': '&', - '<': '<', - '>': '>', - "'": ''', - '"': '"' - }; - - var uid = '0'; - - // Meta Tags - /*templateValues.metaTags = defaultMetaTags.concat(options.metaTags || []).map(function(tag) { - if(!tag || typeof tag.content !== 'string') { - winston.warn('Invalid meta tag. ', tag); - return tag; - } - - tag.content = tag.content.replace(/[&<>'"]/g, function(tag) { - return escapeList[tag] || tag; - }); - return tag; - });*/ - - // Link Tags - /*templateValues.linkTags = defaultLinkTags.concat(options.linkTags || []); - templateValues.linkTags.push({ - rel: "icon", - type: "image/x-icon", - href: nconf.get('relative_path') + '/favicon.ico' - });*/ - - if(options.req.user && options.req.user.uid) { - uid = options.req.user.uid; - } - - // Custom CSS - templateValues.useCustomCSS = false; - if (meta.config.useCustomCSS === '1') { - templateValues.useCustomCSS = true; - templateValues.customCSS = meta.config.customCSS; - } - - async.parallel([ - function(next) { - translator.get('pages:' + path.basename(options.req.url), function(translated) { - /*var metaTitle = templateValues.metaTags.filter(function(tag) { - return tag.name === 'title'; - }); - if (translated) { - templateValues.browserTitle = translated; - } else if (metaTitle.length > 0 && metaTitle[0].content) { - templateValues.browserTitle = metaTitle[0].content; - } else { - templateValues.browserTitle = meta.config.browserTitle || 'NodeBB'; - }*/ - - next(); - }); - }, - function(next) { - user.isAdministrator(uid, function(err, isAdmin) { - templateValues.isAdmin = isAdmin || false; - next(); - }); - } - ], function() { - /*translator.translate(templates.header.parse(templateValues), function(template) { - callback(null, template); - });*/ - app.render('header', templateValues, function(err, template) { - callback(null, template) - }); - }); - }); - }; // Cache static files on production if (global.env !== 'development') {