From f9a804e0143e7e5c0167badce6c68c38daa0b7fe Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Fri, 23 Aug 2019 15:46:10 -0400 Subject: [PATCH] refactor: async/await users --- src/controllers/users.js | 308 +++++++++++++++------------------------ 1 file changed, 120 insertions(+), 188 deletions(-) diff --git a/src/controllers/users.js b/src/controllers/users.js index cf57829546..2856bdd85c 100644 --- a/src/controllers/users.js +++ b/src/controllers/users.js @@ -1,19 +1,18 @@ 'use strict'; -var async = require('async'); -var user = require('../user'); -var meta = require('../meta'); +const user = require('../user'); +const meta = require('../meta'); -var db = require('../database'); -var pagination = require('../pagination'); -var privileges = require('../privileges'); -var helpers = require('./helpers'); +const db = require('../database'); +const pagination = require('../pagination'); +const privileges = require('../privileges'); +const helpers = require('./helpers'); -var usersController = module.exports; +const usersController = module.exports; -usersController.index = function (req, res, next) { - var section = req.query.section || 'joindate'; - var sectionToController = { +usersController.index = async function (req, res, next) { + const section = req.query.section || 'joindate'; + const sectionToController = { joindate: usersController.getUsersSortedByJoinDate, online: usersController.getOnlineUsers, 'sort-posts': usersController.getUsersSortedByPosts, @@ -23,133 +22,99 @@ usersController.index = function (req, res, next) { }; if (req.query.term) { - usersController.search(req, res, next); + await usersController.search(req, res, next); } else if (sectionToController[section]) { - sectionToController[section](req, res, next); + await sectionToController[section](req, res, next); } else { - usersController.getUsersSortedByJoinDate(req, res, next); + await usersController.getUsersSortedByJoinDate(req, res, next); } }; -usersController.search = function (req, res, next) { - async.waterfall([ - function (next) { - privileges.global.can('search:users', req.uid, next); - }, - function (allowed, next) { - if (!allowed) { - return next(new Error('[[error:no-privileges]]')); +usersController.search = async function (req, res, next) { + const allowed = await privileges.global.can('search:users', req.uid); + if (!allowed) { + return next(new Error('[[error:no-privileges]]')); + } + const [searchData, isAdminOrGlobalMod] = await Promise.all([ + user.search({ + query: req.query.term, + searchBy: req.query.searchBy || 'username', + page: req.query.page || 1, + sortBy: req.query.sortBy || 'joindate', + onlineOnly: req.query.onlineOnly === 'true', + bannedOnly: req.query.bannedOnly === 'true', + flaggedOnly: req.query.flaggedOnly === 'true', + }), + user.isAdminOrGlobalMod(req.uid), + ]); + const section = req.query.section || 'joindate'; + + searchData.isAdminOrGlobalMod = isAdminOrGlobalMod; + searchData.pagination = pagination.create(req.query.page, searchData.pageCount, req.query); + searchData['section_' + section] = true; + searchData.displayUserSearch = true; + await render(req, res, searchData); +}; + +usersController.getOnlineUsers = async function (req, res) { + const [userData, guests] = await Promise.all([ + usersController.getUsers('users:online', req.uid, req.query), + require('../socket.io/admin/rooms').getTotalGuestCount(), + ]); + + let hiddenCount = 0; + if (!userData.isAdminOrGlobalMod) { + userData.users = userData.users.filter(function (user) { + if (user && user.status === 'offline') { + hiddenCount += 1; } - async.parallel({ - search: function (next) { - user.search({ - query: req.query.term, - searchBy: req.query.searchBy || 'username', - page: req.query.page || 1, - sortBy: req.query.sortBy || 'joindate', - onlineOnly: req.query.onlineOnly === 'true', - bannedOnly: req.query.bannedOnly === 'true', - flaggedOnly: req.query.flaggedOnly === 'true', - }, next); - }, - isAdminOrGlobalMod: function (next) { - user.isAdminOrGlobalMod(req.uid, next); - }, - }, next); - }, - function (results, next) { - var section = req.query.section || 'joindate'; + return user && user.status !== 'offline'; + }); + } - results.search.isAdminOrGlobalMod = results.isAdminOrGlobalMod; - results.search.pagination = pagination.create(req.query.page, results.search.pageCount, req.query); - results.search['section_' + section] = true; - results.displayUserSearch = true; - render(req, res, results.search, next); - }, - ], next); + userData.anonymousUserCount = guests + hiddenCount; + + await render(req, res, userData); }; -usersController.getOnlineUsers = function (req, res, next) { - async.waterfall([ - function (next) { - async.parallel({ - users: function (next) { - usersController.getUsers('users:online', req.uid, req.query, next); - }, - guests: function (next) { - require('../socket.io/admin/rooms').getTotalGuestCount(next); - }, - }, next); - }, - function (results, next) { - var userData = results.users; - var hiddenCount = 0; - if (!userData.isAdminOrGlobalMod) { - userData.users = userData.users.filter(function (user) { - if (user && user.status === 'offline') { - hiddenCount += 1; - } - return user && user.status !== 'offline'; - }); - } - - userData.anonymousUserCount = results.guests + hiddenCount; - - render(req, res, userData, next); - }, - ], next); +usersController.getUsersSortedByPosts = async function (req, res) { + await usersController.renderUsersPage('users:postcount', req, res); }; -usersController.getUsersSortedByPosts = function (req, res, next) { - usersController.renderUsersPage('users:postcount', req, res, next); -}; - -usersController.getUsersSortedByReputation = function (req, res, next) { +usersController.getUsersSortedByReputation = async function (req, res, next) { if (meta.config['reputation:disabled']) { return next(); } - usersController.renderUsersPage('users:reputation', req, res, next); + await usersController.renderUsersPage('users:reputation', req, res); }; -usersController.getUsersSortedByJoinDate = function (req, res, next) { - usersController.renderUsersPage('users:joindate', req, res, next); +usersController.getUsersSortedByJoinDate = async function (req, res) { + await usersController.renderUsersPage('users:joindate', req, res); }; -usersController.getBannedUsers = function (req, res, next) { - renderIfAdminOrGlobalMod('users:banned', req, res, next); +usersController.getBannedUsers = async function (req, res) { + await renderIfAdminOrGlobalMod('users:banned', req, res); }; -usersController.getFlaggedUsers = function (req, res, next) { - renderIfAdminOrGlobalMod('users:flags', req, res, next); +usersController.getFlaggedUsers = async function (req, res) { + await renderIfAdminOrGlobalMod('users:flags', req, res); }; -function renderIfAdminOrGlobalMod(set, req, res, next) { - async.waterfall([ - function (next) { - user.isAdminOrGlobalMod(req.uid, next); - }, - function (isAdminOrGlobalMod, next) { - if (!isAdminOrGlobalMod) { - return helpers.notAllowed(req, res); - } - usersController.renderUsersPage(set, req, res, next); - }, - ], next); +async function renderIfAdminOrGlobalMod(set, req, res) { + const isAdminOrGlobalMod = await user.isAdminOrGlobalMod(req.uid); + if (!isAdminOrGlobalMod) { + return helpers.notAllowed(req, res); + } + await usersController.renderUsersPage(set, req, res); } -usersController.renderUsersPage = function (set, req, res, next) { - async.waterfall([ - function (next) { - usersController.getUsers(set, req.uid, req.query, next); - }, - function (userData, next) { - render(req, res, userData, next); - }, - ], next); +usersController.renderUsersPage = async function (set, req, res) { + const userData = await usersController.getUsers(set, req.uid, req.query); + render(req, res, userData); }; -usersController.getUsers = function (set, uid, query, callback) { - var setToData = { +usersController.getUsers = async function (set, uid, query) { + const setToData = { 'users:postcount': { title: '[[pages:users/sort-posts]]', crumb: '[[users:top_posters]]' }, 'users:reputation': { title: '[[pages:users/sort-reputation]]', crumb: '[[users:most_reputation]]' }, 'users:joindate': { title: '[[pages:users/latest]]', crumb: '[[global:users]]' }, @@ -162,96 +127,63 @@ usersController.getUsers = function (set, uid, query, callback) { setToData[set] = { title: '', crumb: '' }; } - var breadcrumbs = [{ text: setToData[set].crumb }]; + const breadcrumbs = [{ text: setToData[set].crumb }]; if (set !== 'users:joindate') { breadcrumbs.unshift({ text: '[[global:users]]', url: '/users' }); } - var page = parseInt(query.page, 10) || 1; - var resultsPerPage = meta.config.userSearchResultsPerPage; - var start = Math.max(0, page - 1) * resultsPerPage; - var stop = start + resultsPerPage - 1; + const page = parseInt(query.page, 10) || 1; + const resultsPerPage = meta.config.userSearchResultsPerPage; + const start = Math.max(0, page - 1) * resultsPerPage; + const stop = start + resultsPerPage - 1; - async.waterfall([ - function (next) { - async.parallel({ - isAdminOrGlobalMod: function (next) { - user.isAdminOrGlobalMod(uid, next); - }, - canSearch: function (next) { - privileges.global.can('search:users', uid, next); - }, - usersData: function (next) { - usersController.getUsersAndCount(set, uid, start, stop, next); - }, - }, next); - }, - function (results, next) { - var pageCount = Math.ceil(results.usersData.count / resultsPerPage); - var userData = { - users: results.usersData.users, - pagination: pagination.create(page, pageCount, query), - userCount: results.usersData.count, - title: setToData[set].title || '[[pages:users/latest]]', - breadcrumbs: helpers.buildBreadcrumbs(breadcrumbs), - isAdminOrGlobalMod: results.isAdminOrGlobalMod, - displayUserSearch: results.canSearch, - }; - userData['section_' + (query.section || 'joindate')] = true; - next(null, userData); - }, - ], callback); + const [isAdminOrGlobalMod, canSearch, usersData] = await Promise.all([ + user.isAdminOrGlobalMod(uid), + privileges.global.can('search:users', uid), + usersController.getUsersAndCount(set, uid, start, stop), + ]); + const pageCount = Math.ceil(usersData.count / resultsPerPage); + return { + users: usersData.users, + pagination: pagination.create(page, pageCount, query), + userCount: usersData.count, + title: setToData[set].title || '[[pages:users/latest]]', + breadcrumbs: helpers.buildBreadcrumbs(breadcrumbs), + isAdminOrGlobalMod: isAdminOrGlobalMod, + displayUserSearch: canSearch, + ['section_' + (query.section || 'joindate')]: true, + }; }; -usersController.getUsersAndCount = function (set, uid, start, stop, callback) { - async.waterfall([ - function (next) { - async.parallel({ - users: function (next) { - user.getUsersFromSet(set, uid, start, stop, next); - }, - count: function (next) { - if (set === 'users:online') { - var now = Date.now(); - db.sortedSetCount('users:online', now - 300000, '+inf', next); - } else if (set === 'users:banned') { - db.sortedSetCard('users:banned', next); - } else if (set === 'users:flags') { - db.sortedSetCard('users:flags', next); - } else { - db.getObjectField('global', 'userCount', next); - } - }, - }, next); - }, - function (results, next) { - results.users = results.users.filter(function (user) { - return user && parseInt(user.uid, 10); - }); - - next(null, results); - }, - ], callback); +usersController.getUsersAndCount = async function (set, uid, start, stop) { + async function getCount() { + if (set === 'users:online') { + return await db.sortedSetCount('users:online', Date.now() - 300000, '+inf'); + } else if (set === 'users:banned' || set === 'users:flags') { + return await db.sortedSetCard(set); + } + return await db.getObjectField('global', 'userCount'); + } + const [usersData, count] = await Promise.all([ + user.getUsersFromSet(set, uid, start, stop), + getCount(), + ]); + return { + users: usersData.filter(user => user && parseInt(user.uid, 10)), + count: count, + }; }; -function render(req, res, data, next) { - var registrationType = meta.config.registrationType; +async function render(req, res, data) { + const registrationType = meta.config.registrationType; data.maximumInvites = meta.config.maximumInvites; data.inviteOnly = registrationType === 'invite-only' || registrationType === 'admin-invite-only'; data.adminInviteOnly = registrationType === 'admin-invite-only'; data['reputation:disabled'] = meta.config['reputation:disabled']; + data.invites = await user.getInvitesNumber(req.uid); - async.waterfall([ - function (next) { - user.getInvitesNumber(req.uid, next); - }, - function (numInvites) { - res.append('X-Total-Count', data.userCount); - data.invites = numInvites; - - res.render('users', data); - }, - ], next); + res.append('X-Total-Count', data.userCount); + res.render('users', data); }