diff --git a/src/controllers/index.js b/src/controllers/index.js index 200d7c9070..90514a6d99 100644 --- a/src/controllers/index.js +++ b/src/controllers/index.js @@ -1,16 +1,15 @@ 'use strict'; -var async = require('async'); -var nconf = require('nconf'); -var validator = require('validator'); +const nconf = require('nconf'); +const validator = require('validator'); -var meta = require('../meta'); -var user = require('../user'); -var plugins = require('../plugins'); -var privileges = require('../privileges'); -var helpers = require('./helpers'); +const meta = require('../meta'); +const user = require('../user'); +const plugins = require('../plugins'); +const privileges = require('../privileges'); +const helpers = require('./helpers'); -var Controllers = module.exports; +const Controllers = module.exports; Controllers.ping = require('./ping'); Controllers.home = require('./home'); @@ -154,94 +153,77 @@ Controllers.login = function (req, res, next) { }); }; -Controllers.register = function (req, res, next) { - var registrationType = meta.config.registrationType || 'normal'; +Controllers.register = async function (req, res, next) { + const registrationType = meta.config.registrationType || 'normal'; if (registrationType === 'disabled') { return setImmediate(next); } - var errorText; + let errorText; if (req.query.error === 'csrf-invalid') { errorText = '[[error:csrf-invalid]]'; } - - async.waterfall([ - function (next) { - if (registrationType === 'invite-only' || registrationType === 'admin-invite-only') { - user.verifyInvitation(req.query, next); - } else { - next(); - } - }, - function (next) { - plugins.fireHook('filter:parse.post', { - postData: { - content: meta.config.termsOfUse || '', - }, - }, next); - }, - function (termsOfUse) { - var loginStrategies = require('../routes/authentication').getLoginStrategies(); - var data = { - 'register_window:spansize': loginStrategies.length ? 'col-md-6' : 'col-md-12', - alternate_logins: !!loginStrategies.length, - }; - - data.authentication = loginStrategies; - - data.minimumUsernameLength = meta.config.minimumUsernameLength; - data.maximumUsernameLength = meta.config.maximumUsernameLength; - data.minimumPasswordLength = meta.config.minimumPasswordLength; - data.minimumPasswordStrength = meta.config.minimumPasswordStrength; - data.termsOfUse = termsOfUse.postData.content; - data.breadcrumbs = helpers.buildBreadcrumbs([{ + try { + if (registrationType === 'invite-only' || registrationType === 'admin-invite-only') { + await user.verifyInvitation(req.query); + } + const termsOfUse = await plugins.fireHook('filter:parse.post', { + postData: { + content: meta.config.termsOfUse || '', + }, + }); + const loginStrategies = require('../routes/authentication').getLoginStrategies(); + res.render('register', { + 'register_window:spansize': loginStrategies.length ? 'col-md-6' : 'col-md-12', + alternate_logins: !!loginStrategies.length, + authentication: loginStrategies, + + minimumUsernameLength: meta.config.minimumUsernameLength, + maximumUsernameLength: meta.config.maximumUsernameLength, + minimumPasswordLength: meta.config.minimumPasswordLength, + minimumPasswordStrength: meta.config.minimumPasswordStrength, + termsOfUse: termsOfUse.postData.content, + breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[register:register]]', - }]); - data.regFormEntry = []; - data.error = req.flash('error')[0] || errorText; - data.title = '[[pages:register]]'; - - res.render('register', data); - }, - ], next); + }]), + regFormEntry: [], + error: req.flash('error')[0] || errorText, + title: '[[pages:register]]', + }); + } catch (err) { + next(err); + } }; -Controllers.registerInterstitial = function (req, res, next) { +Controllers.registerInterstitial = async function (req, res, next) { if (!req.session.hasOwnProperty('registration')) { return res.redirect(nconf.get('relative_path') + '/register'); } + try { + const data = await plugins.fireHook('filter:register.interstitial', { + userData: req.session.registration, + interstitials: [], + }); - async.waterfall([ - function (next) { - plugins.fireHook('filter:register.interstitial', { - userData: req.session.registration, - interstitials: [], - }, next); - }, - function (data, next) { - if (!data.interstitials.length) { - // No interstitials, redirect to home - const returnTo = req.session.returnTo || req.session.registration.returnTo; - delete req.session.registration; - return helpers.redirect(res, returnTo || '/'); - } - var renders = data.interstitials.map(function (interstitial) { - return async.apply(req.app.render.bind(req.app), interstitial.template, interstitial.data || {}); - }); + if (!data.interstitials.length) { + // No interstitials, redirect to home + const returnTo = req.session.returnTo || req.session.registration.returnTo; + delete req.session.registration; + return helpers.redirect(res, returnTo || '/'); + } + const renders = data.interstitials.map(interstitial => req.app.renderAsync(interstitial.template, interstitial.data || {})); + const sections = await Promise.all(renders); - async.parallel(renders, next); - }, - function (sections) { - var errors = req.flash('errors'); - res.render('registerComplete', { - title: '[[pages:registration-complete]]', - errors: errors, - sections: sections, - }); - }, - ], next); + res.render('registerComplete', { + title: '[[pages:registration-complete]]', + errors: req.flash('errors'), + sections: sections, + }); + } catch (err) { + next(err); + } }; Controllers.confirmEmail = function (req, res) { diff --git a/src/controllers/mods.js b/src/controllers/mods.js index 7dc2b32b76..ddcd695ccc 100644 --- a/src/controllers/mods.js +++ b/src/controllers/mods.js @@ -1,159 +1,142 @@ 'use strict'; -var async = require('async'); - -var user = require('../user'); -var categories = require('../categories'); -var flags = require('../flags'); -var analytics = require('../analytics'); -var plugins = require('../plugins'); -var pagination = require('../pagination'); - -var adminPostQueueController = require('./admin/postqueue'); -var modsController = module.exports; +const user = require('../user'); +const categories = require('../categories'); +const flags = require('../flags'); +const analytics = require('../analytics'); +const plugins = require('../plugins'); +const pagination = require('../pagination'); +const utils = require('../utils'); + +const adminPostQueueController = require('./admin/postqueue'); +const modsController = module.exports; modsController.flags = {}; -modsController.flags.list = function (req, res, next) { - var filters; - var hasFilter; - var validFilters = ['assignee', 'state', 'reporterId', 'type', 'targetUid', 'cid', 'quick', 'page', 'perPage']; +modsController.flags.list = async function (req, res, next) { + let validFilters = ['assignee', 'state', 'reporterId', 'type', 'targetUid', 'cid', 'quick', 'page', 'perPage']; // Reset filters if explicitly requested if (parseInt(req.query.reset, 10) === 1) { delete req.session.flags_filters; } - async.waterfall([ - function (next) { - async.parallel({ - isAdminOrGlobalMod: async.apply(user.isAdminOrGlobalMod, req.uid), - moderatedCids: async.apply(user.getModeratedCids, req.uid), - validFilters: async.apply(plugins.fireHook, 'filter:flags.validateFilters', { filters: validFilters }), - }, next); - }, - function (results, next) { - if (!(results.isAdminOrGlobalMod || !!results.moderatedCids.length)) { - return next(new Error('[[error:no-privileges]]')); - } + const [isAdminOrGlobalMod, moderatedCids, data] = await Promise.all([ + user.isAdminOrGlobalMod(req.uid), + user.getModeratedCids(req.uid), + plugins.fireHook('filter:flags.validateFilters', { filters: validFilters }), + ]); - if (!results.isAdminOrGlobalMod && results.moderatedCids.length) { - res.locals.cids = results.moderatedCids; - } + if (!(isAdminOrGlobalMod || !!moderatedCids.length)) { + return next(new Error('[[error:no-privileges]]')); + } - validFilters = results.validFilters.filters; + if (!isAdminOrGlobalMod && moderatedCids.length) { + res.locals.cids = moderatedCids; + } - // Parse query string params for filters - hasFilter = false; + validFilters = data.filters; - filters = validFilters.reduce(function (memo, cur) { - if (req.query.hasOwnProperty(cur)) { - memo[cur] = req.query[cur]; - } + // Parse query string params for filters + let filters = validFilters.reduce(function (memo, cur) { + if (req.query.hasOwnProperty(cur)) { + memo[cur] = req.query[cur]; + } - return memo; - }, {}); - hasFilter = !!Object.keys(filters).length; + return memo; + }, {}); + let hasFilter = !!Object.keys(filters).length; - if (!hasFilter && req.session.hasOwnProperty('flags_filters')) { - // Load filters from session object - filters = req.session.flags_filters; - hasFilter = true; - } + if (!hasFilter && req.session.hasOwnProperty('flags_filters')) { + // Load filters from session object + filters = req.session.flags_filters; + hasFilter = true; + } - if (res.locals.cids) { - if (!filters.cid) { - // If mod and no cid filter, add filter for their modded categories - filters.cid = res.locals.cids; - } else if (Array.isArray(filters.cid)) { - // Remove cids they do not moderate - filters.cid = filters.cid.filter(function (cid) { - return res.locals.cids.includes(String(cid)); - }); - } else if (!res.locals.cids.includes(String(filters.cid))) { - filters.cid = res.locals.cids; - hasFilter = false; - } - } + if (res.locals.cids) { + if (!filters.cid) { + // If mod and no cid filter, add filter for their modded categories + filters.cid = res.locals.cids; + } else if (Array.isArray(filters.cid)) { + // Remove cids they do not moderate + filters.cid = filters.cid.filter(cid => res.locals.cids.includes(String(cid))); + } else if (!res.locals.cids.includes(String(filters.cid))) { + filters.cid = res.locals.cids; + hasFilter = false; + } + } - // Pagination doesn't count as a filter - if (Object.keys(filters).length === 2 && filters.hasOwnProperty('page') && filters.hasOwnProperty('perPage')) { - hasFilter = false; - } + // Pagination doesn't count as a filter + if (Object.keys(filters).length === 2 && filters.hasOwnProperty('page') && filters.hasOwnProperty('perPage')) { + hasFilter = false; + } - // Save filters into session unless removed - req.session.flags_filters = filters; - - async.parallel({ - flags: async.apply(flags.list, filters, req.uid), - analytics: async.apply(analytics.getDailyStatsForSet, 'analytics:flags', Date.now(), 30), - categories: async.apply(categories.buildForSelect, req.uid, 'read'), - }, next); - }, - function (data) { - data.categories = filterCategories(res.locals.cids, data.categories); - - res.render('flags/list', { - flags: data.flags.flags, - analytics: data.analytics, - categories: data.categories, - hasFilter: hasFilter, - filters: filters, - title: '[[pages:flags]]', - pagination: pagination.create(data.flags.page, data.flags.pageCount, req.query), - }); - }, - ], next); + // Save filters into session unless removed + req.session.flags_filters = filters; + + const [flagsData, analyticsData, categoriesData] = await Promise.all([ + flags.list(filters, req.uid), + analytics.getDailyStatsForSet('analytics:flags', Date.now(), 30), + categories.buildForSelect(req.uid, 'read'), + ]); + + res.render('flags/list', { + flags: flagsData.flags, + analytics: analyticsData, + categories: filterCategories(res.locals.cids, categoriesData), + hasFilter: hasFilter, + filters: filters, + title: '[[pages:flags]]', + pagination: pagination.create(flagsData.page, flagsData.pageCount, req.query), + }); }; -modsController.flags.detail = function (req, res, next) { - async.parallel({ - isAdminOrGlobalMod: async.apply(user.isAdminOrGlobalMod, req.uid), - moderatedCids: async.apply(user.getModeratedCids, req.uid), - flagData: async.apply(flags.get, req.params.flagId), - assignees: async.apply(user.getAdminsandGlobalModsandModerators), - categories: async.apply(categories.buildForSelect, req.uid, 'read'), - }, function (err, results) { - if (err || !results.flagData) { - return next(err || new Error('[[error:invalid-data]]')); - } else if (!(results.isAdminOrGlobalMod || !!results.moderatedCids.length)) { - return next(new Error('[[error:no-privileges]]')); - } +modsController.flags.detail = async function (req, res, next) { + const results = await utils.promiseParallel({ + isAdminOrGlobalMod: user.isAdminOrGlobalMod(req.uid), + moderatedCids: user.getModeratedCids(req.uid), + flagData: flags.get(req.params.flagId), + assignees: user.getAdminsandGlobalModsandModerators(), + categories: categories.buildForSelect(req.uid, 'read'), + }); - if (!results.isAdminOrGlobalMod && results.moderatedCids.length) { - res.locals.cids = results.moderatedCids; - } + if (!results.flagData) { + return next(new Error('[[error:invalid-data]]')); + } else if (!(results.isAdminOrGlobalMod || !!results.moderatedCids.length)) { + return next(new Error('[[error:no-privileges]]')); + } - results.categories = filterCategories(res.locals.cids, results.categories); + if (!results.isAdminOrGlobalMod && results.moderatedCids.length) { + res.locals.cids = results.moderatedCids; + } - if (results.flagData.type === 'user') { - results.flagData.type_path = 'uid'; - } else if (results.flagData.type === 'post') { - results.flagData.type_path = 'post'; - } + results.categories = filterCategories(res.locals.cids, results.categories); - res.render('flags/detail', Object.assign(results.flagData, { - assignees: results.assignees, - type_bool: ['post', 'user', 'empty'].reduce(function (memo, cur) { - if (cur !== 'empty') { - memo[cur] = results.flagData.type === cur && (!results.flagData.target || !!Object.keys(results.flagData.target).length); - } else { - memo[cur] = !Object.keys(results.flagData.target).length; - } - - return memo; - }, {}), - title: '[[pages:flag-details, ' + req.params.flagId + ']]', - categories: results.categories, - })); - }); + if (results.flagData.type === 'user') { + results.flagData.type_path = 'uid'; + } else if (results.flagData.type === 'post') { + results.flagData.type_path = 'post'; + } + + res.render('flags/detail', Object.assign(results.flagData, { + assignees: results.assignees, + type_bool: ['post', 'user', 'empty'].reduce(function (memo, cur) { + if (cur !== 'empty') { + memo[cur] = results.flagData.type === cur && (!results.flagData.target || !!Object.keys(results.flagData.target).length); + } else { + memo[cur] = !Object.keys(results.flagData.target).length; + } + + return memo; + }, {}), + title: '[[pages:flag-details, ' + req.params.flagId + ']]', + categories: results.categories, + })); }; function filterCategories(moderatedCids, categories) { // If cids is populated, then slim down the categories list if (moderatedCids) { - categories = categories.filter(function (category) { - return moderatedCids.includes(String(category.cid)); - }); + categories = categories.filter(category => moderatedCids.includes(String(category.cid))); } return categories.reduce(function (memo, cur) { @@ -171,16 +154,10 @@ function filterCategories(moderatedCids, categories) { }, {}); } -modsController.postQueue = function (req, res, next) { - async.waterfall([ - function (next) { - user.isPrivileged(req.uid, next); - }, - function (isPrivileged, next) { - if (!isPrivileged) { - return next(); - } - adminPostQueueController.get(req, res, next); - }, - ], next); +modsController.postQueue = async function (req, res, next) { + const isPrivileged = await user.isPrivileged(req.uid); + if (!isPrivileged) { + return next(); + } + await adminPostQueueController.get(req, res, next); }; diff --git a/src/controllers/osd.js b/src/controllers/osd.js index 856d956ef5..58fa13a8e1 100644 --- a/src/controllers/osd.js +++ b/src/controllers/osd.js @@ -1,10 +1,10 @@ 'use strict'; -var xml = require('xml'); -var nconf = require('nconf'); +const xml = require('xml'); +const nconf = require('nconf'); -var plugins = require('../plugins'); -var meta = require('../meta'); +const plugins = require('../plugins'); +const meta = require('../meta'); module.exports.handle = function (req, res, next) { if (plugins.hasListeners('filter:search.query')) { diff --git a/src/controllers/sitemap.js b/src/controllers/sitemap.js index 36dd89fba5..098fe035ff 100644 --- a/src/controllers/sitemap.js +++ b/src/controllers/sitemap.js @@ -1,28 +1,18 @@ 'use strict'; -var async = require('async'); +const sitemap = require('../sitemap'); +const meta = require('../meta'); -var sitemap = require('../sitemap'); -var meta = require('../meta'); +const sitemapController = module.exports; -var sitemapController = module.exports; - -sitemapController.render = function (req, res, next) { +sitemapController.render = async function (req, res, next) { if (meta.config['feeds:disableSitemap']) { return setImmediate(next); } - async.waterfall([ - function (next) { - sitemap.render(next); - }, - function (tplData, next) { - req.app.render('sitemap', tplData, next); - }, - function (xml) { - res.header('Content-Type', 'application/xml'); - res.send(xml); - }, - ], next); + const tplData = await sitemap.render(); + const xml = await req.app.renderAsync('sitemap', tplData); + res.header('Content-Type', 'application/xml'); + res.send(xml); }; sitemapController.getPages = function (req, res, next) { @@ -34,26 +24,19 @@ sitemapController.getCategories = function (req, res, next) { }; sitemapController.getTopicPage = function (req, res, next) { - sendSitemap(function (callback) { - sitemap.getTopicPage(parseInt(req.params[0], 10), callback); + sendSitemap(async function () { + return await sitemap.getTopicPage(parseInt(req.params[0], 10)); }, res, next); }; -function sendSitemap(method, res, callback) { +async function sendSitemap(method, res, callback) { if (meta.config['feeds:disableSitemap']) { return setImmediate(callback); } - async.waterfall([ - function (next) { - method(next); - }, - function (xml) { - if (!xml) { - return callback(); - } - - res.header('Content-Type', 'application/xml'); - res.send(xml); - }, - ], callback); + const xml = await method(); + if (!xml) { + return callback(); + } + res.header('Content-Type', 'application/xml'); + res.send(xml); } diff --git a/src/controllers/unread.js b/src/controllers/unread.js index 710428dbc0..63a7fcb12c 100644 --- a/src/controllers/unread.js +++ b/src/controllers/unread.js @@ -1,113 +1,91 @@ 'use strict'; -var async = require('async'); -var nconf = require('nconf'); -var querystring = require('querystring'); +const nconf = require('nconf'); +const querystring = require('querystring'); -var meta = require('../meta'); -var pagination = require('../pagination'); -var user = require('../user'); -var categories = require('../categories'); -var topics = require('../topics'); -var plugins = require('../plugins'); -var helpers = require('./helpers'); +const meta = require('../meta'); +const pagination = require('../pagination'); +const user = require('../user'); +const categories = require('../categories'); +const topics = require('../topics'); +const plugins = require('../plugins'); +const helpers = require('./helpers'); -var unreadController = module.exports; +const unreadController = module.exports; -unreadController.get = function (req, res, next) { - var page = parseInt(req.query.page, 10) || 1; - var results; - var cid = req.query.cid; - var filter = req.query.filter || ''; - var settings; +unreadController.get = async function (req, res, next) { + const cid = req.query.cid; + const filter = req.query.filter || ''; - async.waterfall([ - function (next) { - plugins.fireHook('filter:unread.getValidFilters', { filters: { ...helpers.validFilters } }, next); - }, - function (data, _next) { - if (!data.filters[filter]) { - return next(); - } + const filterData = await plugins.fireHook('filter:unread.getValidFilters', { filters: { ...helpers.validFilters } }); + if (!filterData.filters[filter]) { + return next(); + } + const [watchedCategories, userSettings] = await Promise.all([ + getWatchedCategories(req.uid, cid, filter), + user.getSettings(req.uid), + ]); - async.parallel({ - watchedCategories: function (next) { - if (plugins.hasListeners('filter:unread.categories')) { - plugins.fireHook('filter:unread.categories', { uid: req.uid, cid: cid }, next); - } else { - const states = [categories.watchStates.watching]; - if (filter === 'watched') { - states.push(categories.watchStates.notwatching, categories.watchStates.ignoring); - } - helpers.getCategoriesByStates(req.uid, cid, states, next); - } - }, - settings: function (next) { - user.getSettings(req.uid, next); - }, - }, _next); - }, - function (_results, next) { - results = _results; - settings = results.settings; - var start = Math.max(0, (page - 1) * settings.topicsPerPage); - var stop = start + settings.topicsPerPage - 1; - var cutoff = req.session.unreadCutoff ? req.session.unreadCutoff : topics.unreadCutoff(); - topics.getUnreadTopics({ - cid: cid, - uid: req.uid, - start: start, - stop: stop, - filter: filter, - cutoff: cutoff, - }, next); - }, - function (data) { - data.title = meta.config.homePageTitle || '[[pages:home]]'; - data.pageCount = Math.max(1, Math.ceil(data.topicCount / settings.topicsPerPage)); - data.pagination = pagination.create(page, data.pageCount, req.query); + const page = parseInt(req.query.page, 10) || 1; + const start = Math.max(0, (page - 1) * userSettings.topicsPerPage); + const stop = start + userSettings.topicsPerPage - 1; + const cutoff = req.session.unreadCutoff ? req.session.unreadCutoff : topics.unreadCutoff(); + const data = await topics.getUnreadTopics({ + cid: cid, + uid: req.uid, + start: start, + stop: stop, + filter: filter, + cutoff: cutoff, + }); - if (settings.usePagination && (page < 1 || page > data.pageCount)) { - req.query.page = Math.max(1, Math.min(data.pageCount, page)); - return helpers.redirect(res, '/unread?' + querystring.stringify(req.query)); - } + data.title = meta.config.homePageTitle || '[[pages:home]]'; + data.pageCount = Math.max(1, Math.ceil(data.topicCount / userSettings.topicsPerPage)); + data.pagination = pagination.create(page, data.pageCount, req.query); - data.categories = results.watchedCategories.categories; - data.allCategoriesUrl = 'unread' + helpers.buildQueryString('', filter, ''); - data.selectedCategory = results.watchedCategories.selectedCategory; - data.selectedCids = results.watchedCategories.selectedCids; - if (req.originalUrl.startsWith(nconf.get('relative_path') + '/api/unread') || req.originalUrl.startsWith(nconf.get('relative_path') + '/unread')) { - data.title = '[[pages:unread]]'; - data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[unread:title]]' }]); - } + if (userSettings.usePagination && (page < 1 || page > data.pageCount)) { + req.query.page = Math.max(1, Math.min(data.pageCount, page)); + return helpers.redirect(res, '/unread?' + querystring.stringify(req.query)); + } - data.filters = helpers.buildFilters('unread', filter, req.query); + data.categories = watchedCategories.categories; + data.allCategoriesUrl = 'unread' + helpers.buildQueryString('', filter, ''); + data.selectedCategory = watchedCategories.selectedCategory; + data.selectedCids = watchedCategories.selectedCids; + if (req.originalUrl.startsWith(nconf.get('relative_path') + '/api/unread') || req.originalUrl.startsWith(nconf.get('relative_path') + '/unread')) { + data.title = '[[pages:unread]]'; + data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[unread:title]]' }]); + } - data.selectedFilter = data.filters.find(function (filter) { - return filter && filter.selected; - }); + data.filters = helpers.buildFilters('unread', filter, req.query); - res.render('unread', data); - }, - ], next); + data.selectedFilter = data.filters.find(filter => filter && filter.selected); + + res.render('unread', data); }; -unreadController.unreadTotal = function (req, res, next) { - var filter = req.query.filter || ''; +async function getWatchedCategories(uid, cid, filter) { + if (plugins.hasListeners('filter:unread.categories')) { + return await plugins.fireHook('filter:unread.categories', { uid: uid, cid: cid }); + } + const states = [categories.watchStates.watching]; + if (filter === 'watched') { + states.push(categories.watchStates.notwatching, categories.watchStates.ignoring); + } + return await helpers.getCategoriesByStates(uid, cid, states); +} - async.waterfall([ - function (next) { - plugins.fireHook('filter:unread.getValidFilters', { filters: { ...helpers.validFilters } }, next); - }, - function (data, _next) { - if (!data.filters[filter]) { - return next(); - } - topics.getTotalUnread(req.uid, filter, _next); - }, - function (data) { - res.json(data); - }, - ], next); +unreadController.unreadTotal = async function (req, res, next) { + const filter = req.query.filter || ''; + try { + const data = await plugins.fireHook('filter:unread.getValidFilters', { filters: { ...helpers.validFilters } }); + if (!data.filters[filter]) { + return next(); + } + const unreadCount = await topics.getTotalUnread(req.uid, filter); + res.json(unreadCount); + } catch (err) { + next(err); + } }; diff --git a/src/sitemap.js b/src/sitemap.js index c980fc1d22..183a91c4a2 100644 --- a/src/sitemap.js +++ b/src/sitemap.js @@ -12,10 +12,9 @@ var meta = require('./meta'); var plugins = require('./plugins'); var utils = require('./utils'); -var sitemap = { - maps: { - topics: [], - }, +var sitemap = module.exports; +sitemap.maps = { + topics: [], }; sitemap.render = function (callback) { @@ -174,4 +173,4 @@ sitemap.clearCache = function () { } }; -module.exports = sitemap; +require('./promisify')(sitemap); diff --git a/src/webserver.js b/src/webserver.js index b880fc3590..39d627877d 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -115,6 +115,8 @@ function setupExpressApp(app) { const relativePath = nconf.get('relative_path'); const viewsDir = nconf.get('views_dir'); + app.renderAsync = util.promisify((tpl, data, callback) => app.render(tpl, data, callback)); + app.engine('tpl', function (filepath, data, next) { filepath = filepath.replace(/\.tpl$/, '.js');