diff --git a/src/controllers/user.js b/src/controllers/user.js index ea3ba03083..69d52ffddf 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -1,152 +1,110 @@ 'use strict'; -var async = require('async'); -var path = require('path'); -var fs = require('fs'); -var winston = require('winston'); -var converter = require('json-2-csv'); -var archiver = require('archiver'); - -var db = require('../database'); -var user = require('../user'); -var meta = require('../meta'); -var posts = require('../posts'); -var batch = require('../batch'); -var events = require('../events'); -var privileges = require('../privileges'); -var accountHelpers = require('./accounts/helpers'); - -var userController = module.exports; - -userController.getCurrentUser = function (req, res, next) { +const path = require('path'); +const fs = require('fs'); +const winston = require('winston'); +const converter = require('json-2-csv'); +const archiver = require('archiver'); +const util = require('util'); + +const db = require('../database'); +const user = require('../user'); +const meta = require('../meta'); +const posts = require('../posts'); +const batch = require('../batch'); +const events = require('../events'); +const privileges = require('../privileges'); +const accountHelpers = require('./accounts/helpers'); + +const userController = module.exports; + +userController.getCurrentUser = async function (req, res) { if (!req.loggedIn) { return res.status(401).json('not-authorized'); } - async.waterfall([ - function (next) { - user.getUserField(req.uid, 'userslug', next); - }, - function (userslug, next) { - accountHelpers.getUserDataByUserSlug(userslug, req.uid, next); - }, - function (userData) { - res.json(userData); - }, - ], next); + const userslug = await user.getUserField(req.uid, 'userslug'); + const userData = await accountHelpers.getUserDataByUserSlug(userslug, req.uid); + res.json(userData); }; - -userController.getUserByUID = function (req, res, next) { - byType('uid', req, res, next); +userController.getUserByUID = async function (req, res, next) { + await byType('uid', req, res, next); }; -userController.getUserByUsername = function (req, res, next) { - byType('username', req, res, next); +userController.getUserByUsername = async function (req, res, next) { + await byType('username', req, res, next); }; -userController.getUserByEmail = function (req, res, next) { - byType('email', req, res, next); +userController.getUserByEmail = async function (req, res, next) { + await byType('email', req, res, next); }; -function byType(type, req, res, next) { - async.waterfall([ - function (next) { - userController.getUserDataByField(req.uid, type, req.params[type], next); - }, - function (data, next) { - if (!data) { - return next(); - } - res.json(data); - }, - ], next); +async function byType(type, req, res, next) { + const userData = await userController.getUserDataByField(req.uid, type, req.params[type]); + if (!userData) { + return next(); + } + res.json(userData); } -userController.getUserDataByField = function (callerUid, field, fieldValue, callback) { - async.waterfall([ - function (next) { - if (field === 'uid') { - next(null, fieldValue); - } else if (field === 'username') { - user.getUidByUsername(fieldValue, next); - } else if (field === 'email') { - user.getUidByEmail(fieldValue, next); - } else { - next(null, null); - } - }, - function (uid, next) { - if (!uid) { - return next(null, null); - } - userController.getUserDataByUID(callerUid, uid, next); - }, - ], callback); +userController.getUserDataByField = async function (callerUid, field, fieldValue) { + let uid = null; + if (field === 'uid') { + uid = fieldValue; + } else if (field === 'username') { + uid = await user.getUidByUsername(fieldValue); + } else if (field === 'email') { + uid = await user.getUidByEmail(fieldValue); + } + if (!uid) { + return null; + } + return await userController.getUserDataByUID(callerUid, uid); }; -userController.getUserDataByUID = function (callerUid, uid, callback) { +userController.getUserDataByUID = async function (callerUid, uid) { if (!parseInt(uid, 10)) { - return callback(new Error('[[error:no-user]]')); + throw new Error('[[error:no-user]]'); + } + const canView = await privileges.global.can('view:users', callerUid); + if (!canView) { + throw new Error('[[error:no-privileges]]'); + } + const [userData, settings] = await Promise.all([ + user.getUserData(uid), + user.getSettings(uid), + ]); + + if (!userData) { + throw new Error('[[error:no-user]]'); } - async.waterfall([ - function (next) { - privileges.global.can('view:users', callerUid, next); - }, - function (canView, next) { - if (!canView) { - return next(new Error('[[error:no-privileges]]')); - } - async.parallel({ - userData: async.apply(user.getUserData, uid), - settings: async.apply(user.getSettings, uid), - }, next); - }, - function (results, next) { - if (!results.userData) { - return next(new Error('[[error:no-user]]')); - } - - results.userData.email = results.settings.showemail && !meta.config.hideEmail ? results.userData.email : undefined; - results.userData.fullname = results.settings.showfullname && !meta.config.hideFullname ? results.userData.fullname : undefined; - - next(null, results.userData); - }, - ], callback); + + userData.email = settings.showemail && !meta.config.hideEmail ? userData.email : undefined; + userData.fullname = settings.showfullname && !meta.config.hideFullname ? userData.fullname : undefined; + + return userData; }; -userController.exportPosts = function (req, res, next) { - async.waterfall([ - function (next) { - var payload = []; - batch.processSortedSet('uid:' + res.locals.uid + ':posts', function (pids, next) { - posts.getPostsData(pids, function (err, posts) { - if (err) { - return next(err); - } - - // Remove empty post references and convert newlines in content - posts = posts.filter(Boolean).map(function (post) { - post.content = '"' + post.content.replace(/\n/g, '\\n').replace(/"/g, '\\"') + '"'; - return post; - }); - - payload = payload.concat(posts); - next(); - }); - }, function (err) { - next(err, payload); - }); - }, - function (payload, next) { - converter.json2csv(payload, next, { - checkSchemaDifferences: false, - emptyFieldValue: '', - }); - }, - function (csv) { - res.set('Content-Type', 'text/csv').set('Content-Disposition', 'attachment; filename="' + req.params.uid + '_posts.csv"').send(csv); - }, - ], next); +const json2csv = util.promisify(function (payload, options, callback) { + converter.json2csv(payload, callback, options); +}); + +userController.exportPosts = async function (req, res) { + var payload = []; + await batch.processSortedSet('uid:' + res.locals.uid + ':posts', async function (pids) { + let postData = await posts.getPostsData(pids); + // Remove empty post references and convert newlines in content + postData = postData.filter(Boolean).map(function (post) { + post.content = '"' + post.content.replace(/\n/g, '\\n').replace(/"/g, '\\"') + '"'; + return post; + }); + payload = payload.concat(postData); + }); + const csv = await json2csv(payload, { + checkSchemaDifferences: false, + emptyFieldValue: '', + }); + res.set('Content-Type', 'text/csv').set('Content-Disposition', 'attachment; filename="' + req.params.uid + '_posts.csv"').send(csv); }; userController.exportUploads = function (req, res, next) { @@ -230,18 +188,17 @@ userController.exportUploads = function (req, res, next) { }); }; -userController.exportProfile = function (req, res, next) { +userController.exportProfile = async function (req, res) { const targetUid = res.locals.uid; - async.waterfall([ - async.apply(db.getObjects.bind(db), ['user:' + targetUid, 'user:' + targetUid + ':settings']), - function (objects, next) { - Object.assign(objects[0], objects[1]); - delete objects[0].password; - - converter.json2csv(objects[0], next); - }, - function (csv) { - res.set('Content-Type', 'text/csv').set('Content-Disposition', 'attachment; filename="' + targetUid + '_profile.csv"').send(csv); - }, - ], next); + const objects = await db.getObjects(['user:' + targetUid, 'user:' + targetUid + ':settings']); + Object.assign(objects[0], objects[1]); + delete objects[0].password; + + const csv = await json2csv(objects[0], {}); + res.set('Content-Type', 'text/csv').set('Content-Disposition', 'attachment; filename="' + targetUid + '_profile.csv"').send(csv); }; + +require('../promisify')(userController, [ + 'getCurrentUser', 'getUserByUID', 'getUserByUsername', 'getUserByEmail', + 'exportPosts', 'exportUploads', 'exportProfile', +]);