refactor: async/await admin/controllers

v1.18.x
Barış Soner Uşaklı 6 years ago
parent 592d9c82c5
commit 6f375482a0

@ -7,10 +7,10 @@ define('admin/manage/users', ['translator', 'benchpress'], function (translator,
Users.init = function () { Users.init = function () {
var navPills = $('.nav-pills li'); var navPills = $('.nav-pills li');
var pathname = window.location.pathname; var pathname = window.location.pathname;
if (!navPills.find('a[href="' + pathname + '"]').length) { if (!navPills.find('a[href^="' + pathname + '"]').length) {
pathname = config.relative_path + '/admin/manage/users/latest'; pathname = config.relative_path + '/admin/manage/users/latest';
} }
navPills.removeClass('active').find('a[href="' + pathname + '"]').parent().addClass('active'); navPills.removeClass('active').find('a[href^="' + pathname + '"]').parent().addClass('active');
$('#results-per-page').val(ajaxify.data.resultsPerPage).on('change', function () { $('#results-per-page').val(ajaxify.data.resultsPerPage).on('change', function () {
var query = utils.params(); var query = utils.params();

@ -1,19 +1,10 @@
'use strict'; 'use strict';
var async = require('async'); const admin = require('../../rewards/admin');
var rewardsController = module.exports; const rewardsController = module.exports;
rewardsController.get = function (req, res, next) { rewardsController.get = async function (req, res) {
async.waterfall([ const data = await admin.get();
function (next) {
require('../../rewards/admin').get(next);
},
function (data) {
res.render('admin/extend/rewards', data); res.render('admin/extend/rewards', data);
},
], next);
}; };
module.exports = rewardsController;

@ -1,56 +1,41 @@
'use strict'; 'use strict';
var async = require('async'); const meta = require('../../meta');
const emailer = require('../../emailer');
const notifications = require('../../notifications');
var meta = require('../../meta'); const settingsController = module.exports;
var emailer = require('../../emailer');
var notifications = require('../../notifications');
var settingsController = module.exports; settingsController.get = async function (req, res, next) {
const term = req.params.term ? req.params.term : 'general';
settingsController.get = function (req, res, next) { if (term === 'email') {
var term = req.params.term ? req.params.term : 'general'; await renderEmail(req, res, next);
} else if (term === 'user') {
switch (req.params.term) { await renderUser(req, res, next);
case 'email': } else {
renderEmail(req, res, next);
break;
case 'user':
renderUser(req, res, next);
break;
default:
res.render('admin/settings/' + term); res.render('admin/settings/' + term);
} }
}; };
function renderEmail(req, res, next) { async function renderEmail(req, res) {
async.waterfall([ const [emails, services] = await Promise.all([
function (next) { emailer.getTemplates(meta.config),
async.parallel({ emailer.listServices(),
emails: async.apply(emailer.getTemplates, meta.config), ]);
services: emailer.listServices,
}, next);
},
function (results) {
res.render('admin/settings/email', { res.render('admin/settings/email', {
emails: results.emails, emails: emails,
sendable: results.emails.filter(function (email) { sendable: emails.filter(function (email) {
return !email.path.includes('_plaintext') && !email.path.includes('partials'); return !email.path.includes('_plaintext') && !email.path.includes('partials');
}), }),
services: results.services, services: services,
}); });
},
], next);
} }
function renderUser(req, res, next) { async function renderUser(req, res) {
async.waterfall([ const notificationTypes = await notifications.getAllNotificationTypes();
function (next) { const notificationSettings = notificationTypes.map(function (type) {
notifications.getAllNotificationTypes(next);
},
function (notificationTypes) {
var notificationSettings = notificationTypes.map(function (type) {
return { return {
name: type, name: type,
label: '[[notifications:' + type + ']]', label: '[[notifications:' + type + ']]',
@ -59,6 +44,4 @@ function renderUser(req, res, next) {
res.render('admin/settings/user', { res.render('admin/settings/user', {
notificationSettings: notificationSettings, notificationSettings: notificationSettings,
}); });
},
], next);
} }

@ -1,20 +1,12 @@
'use strict'; 'use strict';
var async = require('async'); const social = require('../../social');
var social = require('../../social'); const socialController = module.exports;
var socialController = module.exports; socialController.get = async function (req, res) {
const posts = await social.getPostSharing();
socialController.get = function (req, res, next) {
async.waterfall([
function (next) {
social.getPostSharing(next);
},
function (posts) {
res.render('admin/general/social', { res.render('admin/general/social', {
posts: posts, posts: posts,
}); });
},
], next);
}; };

@ -1,25 +1,17 @@
'use strict'; 'use strict';
var async = require('async'); const plugins = require('../../plugins');
const meta = require('../../meta');
var plugins = require('../../plugins'); const soundsController = module.exports;
var meta = require('../../meta');
var soundsController = module.exports; soundsController.get = async function (req, res) {
const types = [
soundsController.get = function (req, res, next) {
var types = [
'notification', 'notification',
'chat-incoming', 'chat-incoming',
'chat-outgoing', 'chat-outgoing',
]; ];
async.waterfall([ const settings = await meta.configs.getFields(types) || {};
function (next) {
meta.configs.getFields(types, next);
},
function (settings) {
settings = settings || {};
var output = {}; var output = {};
types.forEach(function (type) { types.forEach(function (type) {
@ -43,6 +35,4 @@ soundsController.get = function (req, res, next) {
}); });
res.render('admin/general/sounds', output); res.render('admin/general/sounds', output);
},
], next);
}; };

@ -1,18 +1,10 @@
'use strict'; 'use strict';
var async = require('async'); const topics = require('../../topics');
var topics = require('../../topics'); const tagsController = module.exports;
var tagsController = module.exports; tagsController.get = async function (req, res) {
const tags = await topics.getTags(0, 199);
tagsController.get = function (req, res, next) {
async.waterfall([
function (next) {
topics.getTags(0, 199, next);
},
function (tags) {
res.render('admin/manage/tags', { tags: tags }); res.render('admin/manage/tags', { tags: tags });
},
], next);
}; };

@ -1,48 +1,32 @@
'use strict'; 'use strict';
var path = require('path'); const path = require('path');
var fs = require('fs'); const fs = require('fs');
var async = require('async'); const util = require('util');
const readFileAsync = util.promisify(fs.readFile);
var file = require('../../file'); const file = require('../../file');
var themesController = module.exports; const themesController = module.exports;
var defaultScreenshotPath = path.join(__dirname, '../../../public/images/themes/default.png'); const defaultScreenshotPath = path.join(__dirname, '../../../public/images/themes/default.png');
themesController.get = function (req, res, next) { themesController.get = async function (req, res, next) {
var themeDir = path.join(__dirname, '../../../node_modules', req.params.theme); const themeDir = path.join(__dirname, '../../../node_modules', req.params.theme);
var themeConfigPath = path.join(themeDir, 'theme.json'); const themeConfigPath = path.join(themeDir, 'theme.json');
var screenshotPath;
async.waterfall([ let themeConfig;
function (next) { try {
fs.readFile(themeConfigPath, 'utf8', function (err, config) { themeConfig = await readFileAsync(themeConfigPath, 'utf8');
if (err) { themeConfig = JSON.parse(themeConfig);
} catch (err) {
if (err.code === 'ENOENT') { if (err.code === 'ENOENT') {
return next(Error('invalid-data')); return next(Error('invalid-data'));
} }
return next(err); return next(err);
} }
return next(null, config); const screenshotPath = themeConfig.screenshot ? path.join(themeDir, themeConfig.screenshot) : defaultScreenshotPath;
}); const exists = await file.exists(screenshotPath);
},
function (themeConfig, next) {
try {
themeConfig = JSON.parse(themeConfig);
} catch (e) {
return next(e);
}
next(null, themeConfig.screenshot ? path.join(themeDir, themeConfig.screenshot) : defaultScreenshotPath);
},
function (_screenshotPath, next) {
screenshotPath = _screenshotPath;
file.exists(screenshotPath, next);
},
function (exists) {
res.sendFile(exists ? screenshotPath : defaultScreenshotPath); res.sendFile(exists ? screenshotPath : defaultScreenshotPath);
},
], next);
}; };

@ -1,47 +1,41 @@
'use strict'; 'use strict';
var path = require('path'); const path = require('path');
var async = require('async'); const nconf = require('nconf');
var nconf = require('nconf'); const mime = require('mime');
var mime = require('mime'); const fs = require('fs');
var fs = require('fs'); const util = require('util');
const readdirAsync = util.promisify(fs.readdir);
var meta = require('../../meta'); const statAsync = util.promisify(fs.stat);
var posts = require('../../posts');
var file = require('../../file'); const meta = require('../../meta');
var image = require('../../image'); const posts = require('../../posts');
var plugins = require('../../plugins'); const file = require('../../file');
var pagination = require('../../pagination'); const image = require('../../image');
const plugins = require('../../plugins');
var allowedImageTypes = ['image/png', 'image/jpeg', 'image/pjpeg', 'image/jpg', 'image/gif', 'image/svg+xml']; const pagination = require('../../pagination');
var uploadsController = module.exports; const allowedImageTypes = ['image/png', 'image/jpeg', 'image/pjpeg', 'image/jpg', 'image/gif', 'image/svg+xml'];
uploadsController.get = function (req, res, next) { const uploadsController = module.exports;
var currentFolder = path.join(nconf.get('upload_path'), req.query.dir || '');
uploadsController.get = async function (req, res, next) {
const currentFolder = path.join(nconf.get('upload_path'), req.query.dir || '');
if (!currentFolder.startsWith(nconf.get('upload_path'))) { if (!currentFolder.startsWith(nconf.get('upload_path'))) {
return next(new Error('[[error:invalid-path]]')); return next(new Error('[[error:invalid-path]]'));
} }
var itemsPerPage = 20; const itemsPerPage = 20;
var itemCount = 0; const page = parseInt(req.query.page, 10) || 1;
var page = parseInt(req.query.page, 10) || 1; try {
async.waterfall([ let files = await readdirAsync(currentFolder);
function (next) { files = files.filter(filename => filename !== '.gitignore');
fs.readdir(currentFolder, next); const itemCount = files.length;
},
function (files, next) {
files = files.filter(function (filename) {
return filename !== '.gitignore';
});
itemCount = files.length;
var start = Math.max(0, (page - 1) * itemsPerPage); var start = Math.max(0, (page - 1) * itemsPerPage);
var stop = start + itemsPerPage; var stop = start + itemsPerPage;
files = files.slice(start, stop); files = files.slice(start, stop);
filesToData(currentFolder, files, next); files = await filesToData(currentFolder, files);
},
function (files, next) {
// Float directories to the top // Float directories to the top
files.sort(function (a, b) { files.sort(function (a, b) {
if (a.isDirectory && !b.isDirectory) { if (a.isDirectory && !b.isDirectory) {
@ -57,18 +51,11 @@ uploadsController.get = function (req, res, next) {
// Add post usage info if in /files // Add post usage info if in /files
if (req.query.dir === '/files') { if (req.query.dir === '/files') {
posts.uploads.getUsage(files, function (err, usage) { const usage = await posts.uploads.getUsage(files);
files.forEach(function (file, idx) { files.forEach(function (file, idx) {
file.inPids = usage[idx].map(pid => parseInt(pid, 10)); file.inPids = usage[idx].map(pid => parseInt(pid, 10));
}); });
next(err, files);
});
} else {
setImmediate(next, null, files);
} }
},
function (files) {
res.render('admin/manage/uploads', { res.render('admin/manage/uploads', {
currentFolder: currentFolder.replace(nconf.get('upload_path'), ''), currentFolder: currentFolder.replace(nconf.get('upload_path'), ''),
showPids: files.length && files[0].hasOwnProperty('inPids'), showPids: files.length && files[0].hasOwnProperty('inPids'),
@ -76,8 +63,9 @@ uploadsController.get = function (req, res, next) {
breadcrumbs: buildBreadcrumbs(currentFolder), breadcrumbs: buildBreadcrumbs(currentFolder),
pagination: pagination.create(page, Math.ceil(itemCount / itemsPerPage), req.query), pagination: pagination.create(page, Math.ceil(itemCount / itemsPerPage), req.query),
}); });
}, } catch (err) {
], next); next(err);
}
}; };
function buildBreadcrumbs(currentFolder) { function buildBreadcrumbs(currentFolder) {
@ -98,24 +86,18 @@ function buildBreadcrumbs(currentFolder) {
return crumbs; return crumbs;
} }
function filesToData(currentDir, files, callback) { async function filesToData(currentDir, files) {
async.map(files, function (file, next) { return await Promise.all(files.map(file => getFileData(currentDir, file)));
var stat; }
async.waterfall([
function (next) { async function getFileData(currentDir, file) {
fs.stat(path.join(currentDir, file), next); const stat = await statAsync(path.join(currentDir, file));
}, let filesInDir = [];
function (_stat, next) {
stat = _stat;
if (stat.isDirectory()) { if (stat.isDirectory()) {
fs.readdir(path.join(currentDir, file), next); filesInDir = await readdirAsync(path.join(currentDir, file));
} else {
next(null, []);
} }
}, const url = nconf.get('upload_url') + currentDir.replace(nconf.get('upload_path'), '') + '/' + file;
function (filesInDir, next) { return {
var url = nconf.get('upload_url') + currentDir.replace(nconf.get('upload_path'), '') + '/' + file;
next(null, {
name: file, name: file,
path: path.join(currentDir, file).replace(nconf.get('upload_path'), ''), path: path.join(currentDir, file).replace(nconf.get('upload_path'), ''),
url: url, url: url,
@ -125,15 +107,12 @@ function filesToData(currentDir, files, callback) {
isDirectory: stat.isDirectory(), isDirectory: stat.isDirectory(),
isFile: stat.isFile(), isFile: stat.isFile(),
mtime: stat.mtimeMs, mtime: stat.mtimeMs,
}); };
},
], next);
}, callback);
} }
uploadsController.uploadCategoryPicture = function (req, res, next) { uploadsController.uploadCategoryPicture = async function (req, res, next) {
var uploadedFile = req.files.files[0]; const uploadedFile = req.files.files[0];
var params = null; let params = null;
try { try {
params = JSON.parse(req.body.params); params = JSON.parse(req.body.params);
@ -142,91 +121,80 @@ uploadsController.uploadCategoryPicture = function (req, res, next) {
return next(new Error('[[error:invalid-json]]')); return next(new Error('[[error:invalid-json]]'));
} }
if (validateUpload(req, res, next, uploadedFile, allowedImageTypes)) { if (validateUpload(res, uploadedFile, allowedImageTypes)) {
var filename = 'category-' + params.cid + path.extname(uploadedFile.name); const filename = 'category-' + params.cid + path.extname(uploadedFile.name);
uploadImage(filename, 'category', uploadedFile, req, res, next); await uploadImage(filename, 'category', uploadedFile, req, res, next);
} }
}; };
uploadsController.uploadFavicon = function (req, res, next) { uploadsController.uploadFavicon = async function (req, res, next) {
var uploadedFile = req.files.files[0]; const uploadedFile = req.files.files[0];
var allowedTypes = ['image/x-icon', 'image/vnd.microsoft.icon']; const allowedTypes = ['image/x-icon', 'image/vnd.microsoft.icon'];
if (validateUpload(req, res, next, uploadedFile, allowedTypes)) { if (validateUpload(res, uploadedFile, allowedTypes)) {
file.saveFileToLocal('favicon.ico', 'system', uploadedFile.path, function (err, image) { try {
const imageObj = await file.saveFileToLocal('favicon.ico', 'system', uploadedFile.path);
res.json([{ name: uploadedFile.name, url: imageObj.url }]);
} catch (err) {
next(err);
} finally {
file.delete(uploadedFile.path); file.delete(uploadedFile.path);
if (err) {
return next(err);
} }
res.json([{ name: uploadedFile.name, url: image.url }]);
});
} }
}; };
uploadsController.uploadTouchIcon = function (req, res, next) { uploadsController.uploadTouchIcon = async function (req, res, next) {
var uploadedFile = req.files.files[0]; const uploadedFile = req.files.files[0];
var allowedTypes = ['image/png']; const allowedTypes = ['image/png'];
var sizes = [36, 48, 72, 96, 144, 192]; const sizes = [36, 48, 72, 96, 144, 192];
if (validateUpload(req, res, next, uploadedFile, allowedTypes)) {
file.saveFileToLocal('touchicon-orig.png', 'system', uploadedFile.path, function (err, imageObj) {
if (err) {
return next(err);
}
if (validateUpload(res, uploadedFile, allowedTypes)) {
try {
const imageObj = await file.saveFileToLocal('touchicon-orig.png', 'system', uploadedFile.path);
// Resize the image into squares for use as touch icons at various DPIs // Resize the image into squares for use as touch icons at various DPIs
async.eachSeries(sizes, function (size, next) { for (const size of sizes) {
image.resizeImage({ /* eslint-disable no-await-in-loop */
await image.resizeImage({
path: uploadedFile.path, path: uploadedFile.path,
target: path.join(nconf.get('upload_path'), 'system', 'touchicon-' + size + '.png'), target: path.join(nconf.get('upload_path'), 'system', 'touchicon-' + size + '.png'),
width: size, width: size,
height: size, height: size,
}, next); });
}, function (err) {
file.delete(uploadedFile.path);
if (err) {
return next(err);
} }
res.json([{ name: uploadedFile.name, url: imageObj.url }]); res.json([{ name: uploadedFile.name, url: imageObj.url }]);
}); } catch (err) {
}); next(err);
} finally {
file.delete(uploadedFile.path);
}
} }
}; };
uploadsController.uploadLogo = function (req, res, next) { uploadsController.uploadLogo = async function (req, res, next) {
upload('site-logo', req, res, next); await upload('site-logo', req, res, next);
}; };
uploadsController.uploadSound = function (req, res, next) { uploadsController.uploadSound = async function (req, res, next) {
var uploadedFile = req.files.files[0]; const uploadedFile = req.files.files[0];
var mimeType = mime.getType(uploadedFile.name); const mimeType = mime.getType(uploadedFile.name);
if (!/^audio\//.test(mimeType)) { if (!/^audio\//.test(mimeType)) {
return next(Error('[[error:invalid-data]]')); return next(Error('[[error:invalid-data]]'));
} }
try {
async.waterfall([ await file.saveFileToLocal(uploadedFile.name, 'sounds', uploadedFile.path);
function (next) { await meta.sounds.build();
file.saveFileToLocal(uploadedFile.name, 'sounds', uploadedFile.path, next); res.json([{}]);
}, } catch (err) {
function (uploadedSound, next) { next(err);
meta.sounds.build(next); } finally {
},
], function (err) {
file.delete(uploadedFile.path); file.delete(uploadedFile.path);
if (err) {
return next(err);
} }
res.json([{}]);
});
}; };
uploadsController.uploadFile = function (req, res, next) { uploadsController.uploadFile = async function (req, res, next) {
var uploadedFile = req.files.files[0]; const uploadedFile = req.files.files[0];
var params; let params;
try { try {
params = JSON.parse(req.body.params); params = JSON.parse(req.body.params);
} catch (e) { } catch (e) {
@ -234,33 +202,34 @@ uploadsController.uploadFile = function (req, res, next) {
return next(new Error('[[error:invalid-json]]')); return next(new Error('[[error:invalid-json]]'));
} }
file.saveFileToLocal(uploadedFile.name, params.folder, uploadedFile.path, function (err, data) { try {
const data = await file.saveFileToLocal(uploadedFile.name, params.folder, uploadedFile.path);
res.json([{ url: data.url }]);
} catch (err) {
next(err);
} finally {
file.delete(uploadedFile.path); file.delete(uploadedFile.path);
if (err) {
return next(err);
} }
res.json([{ url: data.url }]);
});
}; };
uploadsController.uploadDefaultAvatar = function (req, res, next) { uploadsController.uploadDefaultAvatar = async function (req, res, next) {
upload('avatar-default', req, res, next); await upload('avatar-default', req, res, next);
}; };
uploadsController.uploadOgImage = function (req, res, next) { uploadsController.uploadOgImage = async function (req, res, next) {
upload('og:image', req, res, next); await upload('og:image', req, res, next);
}; };
function upload(name, req, res, next) { async function upload(name, req, res, next) {
var uploadedFile = req.files.files[0]; const uploadedFile = req.files.files[0];
if (validateUpload(req, res, next, uploadedFile, allowedImageTypes)) { if (validateUpload(res, uploadedFile, allowedImageTypes)) {
var filename = name + path.extname(uploadedFile.name); const filename = name + path.extname(uploadedFile.name);
uploadImage(filename, 'system', uploadedFile, req, res, next); await uploadImage(filename, 'system', uploadedFile, req, res, next);
} }
} }
function validateUpload(req, res, next, uploadedFile, allowedTypes) { function validateUpload(res, uploadedFile, allowedTypes) {
if (!allowedTypes.includes(uploadedFile.type)) { if (!allowedTypes.includes(uploadedFile.type)) {
file.delete(uploadedFile.path); file.delete(uploadedFile.path);
res.json({ error: '[[error:invalid-image-type, ' + allowedTypes.join(', ') + ']]' }); res.json({ error: '[[error:invalid-image-type, ' + allowedTypes.join(', ') + ']]' });
@ -270,64 +239,39 @@ function validateUpload(req, res, next, uploadedFile, allowedTypes) {
return true; return true;
} }
function uploadImage(filename, folder, uploadedFile, req, res, next) { async function uploadImage(filename, folder, uploadedFile, req, res, next) {
async.waterfall([ let imageData;
function (next) { try {
if (plugins.hasListeners('filter:uploadImage')) { if (plugins.hasListeners('filter:uploadImage')) {
plugins.fireHook('filter:uploadImage', { image: uploadedFile, uid: req.uid }, next); imageData = await plugins.fireHook('filter:uploadImage', { image: uploadedFile, uid: req.uid });
} else { } else {
file.saveFileToLocal(filename, folder, uploadedFile.path, next); imageData = await file.saveFileToLocal(filename, folder, uploadedFile.path);
} }
},
function (imageData, next) {
// Post-processing for site-logo
if (path.basename(filename, path.extname(filename)) === 'site-logo' && folder === 'system') { if (path.basename(filename, path.extname(filename)) === 'site-logo' && folder === 'system') {
var uploadPath = path.join(nconf.get('upload_path'), folder, 'site-logo-x50.png'); const uploadPath = path.join(nconf.get('upload_path'), folder, 'site-logo-x50.png');
async.series([ await image.resizeImage({
async.apply(image.resizeImage, {
path: uploadedFile.path, path: uploadedFile.path,
target: uploadPath, target: uploadPath,
height: 50, height: 50,
}), });
async.apply(meta.configs.set, 'brand:emailLogo', path.join(nconf.get('upload_url'), 'system/site-logo-x50.png')), await meta.configs.set('brand:emailLogo', path.join(nconf.get('upload_url'), 'system/site-logo-x50.png'));
function (next) { const size = await image.size(uploadedFile.path);
image.size(uploadedFile.path, function (err, size) { await meta.configs.setMultiple({
if (err) {
return next(err);
}
meta.configs.setMultiple({
'brand:logo:width': size.width, 'brand:logo:width': size.width,
'brand:logo:height': size.height, 'brand:logo:height': size.height,
}, function (err) {
next(err);
});
});
},
], function (err) {
next(err, imageData);
}); });
} else if (path.basename(filename, path.extname(filename)) === 'og:image' && folder === 'system') { } else if (path.basename(filename, path.extname(filename)) === 'og:image' && folder === 'system') {
image.size(uploadedFile.path, function (err, size) { const size = await image.size(uploadedFile.path);
if (err) { await meta.configs.setMultiple({
next(err);
}
meta.configs.setMultiple({
'og:image:width': size.width, 'og:image:width': size.width,
'og:image:height': size.height, 'og:image:height': size.height,
}, function (err) {
next(err, imageData);
});
}); });
} else {
setImmediate(next, null, imageData);
} }
}, res.json([{ name: uploadedFile.name, url: imageData.url.startsWith('http') ? imageData.url : nconf.get('relative_path') + imageData.url }]);
], function (err, image) { } catch (err) {
next(err);
} finally {
file.delete(uploadedFile.path); file.delete(uploadedFile.path);
if (err) {
return next(err);
} }
res.json([{ name: uploadedFile.name, url: image.url.startsWith('http') ? image.url : nconf.get('relative_path') + image.url }]);
});
} }

@ -1,18 +1,18 @@
'use strict'; 'use strict';
var async = require('async'); const nconf = require('nconf');
var nconf = require('nconf');
var user = require('../../user'); const user = require('../../user');
var meta = require('../../meta'); const meta = require('../../meta');
var db = require('../../database'); const db = require('../../database');
var pagination = require('../../pagination'); const pagination = require('../../pagination');
var events = require('../../events'); const events = require('../../events');
var plugins = require('../../plugins'); const plugins = require('../../plugins');
const utils = require('../../utils');
var usersController = module.exports; const usersController = module.exports;
var userFields = ['uid', 'username', 'userslug', 'email', 'postcount', 'joindate', 'banned', const userFields = ['uid', 'username', 'userslug', 'email', 'postcount', 'joindate', 'banned',
'reputation', 'picture', 'flags', 'lastonline', 'email:confirmed']; 'reputation', 'picture', 'flags', 'lastonline', 'email:confirmed'];
usersController.search = function (req, res) { usersController.search = function (req, res) {
@ -22,79 +22,76 @@ usersController.search = function (req, res) {
}); });
}; };
usersController.sortByJoinDate = function (req, res, next) { usersController.sortByJoinDate = async function (req, res) {
getUsers('users:joindate', 'latest', undefined, undefined, req, res, next); await getUsers('users:joindate', 'latest', undefined, undefined, req, res);
}; };
usersController.notValidated = function (req, res, next) { usersController.notValidated = async function (req, res) {
getUsers('users:notvalidated', 'notvalidated', undefined, undefined, req, res, next); await getUsers('users:notvalidated', 'notvalidated', undefined, undefined, req, res);
}; };
usersController.noPosts = function (req, res, next) { usersController.noPosts = async function (req, res) {
getUsers('users:postcount', 'noposts', '-inf', 0, req, res, next); await getUsers('users:postcount', 'noposts', '-inf', 0, req, res);
}; };
usersController.topPosters = function (req, res, next) { usersController.topPosters = async function (req, res) {
getUsers('users:postcount', 'topposts', 0, '+inf', req, res, next); await getUsers('users:postcount', 'topposts', 0, '+inf', req, res);
}; };
usersController.mostReputaion = function (req, res, next) { usersController.mostReputaion = async function (req, res) {
getUsers('users:reputation', 'mostreputation', 0, '+inf', req, res, next); await getUsers('users:reputation', 'mostreputation', 0, '+inf', req, res);
}; };
usersController.flagged = function (req, res, next) { usersController.flagged = async function (req, res) {
getUsers('users:flags', 'mostflags', 1, '+inf', req, res, next); await getUsers('users:flags', 'mostflags', 1, '+inf', req, res);
}; };
usersController.inactive = function (req, res, next) { usersController.inactive = async function (req, res) {
var timeRange = 1000 * 60 * 60 * 24 * 30 * (parseInt(req.query.months, 10) || 3); const timeRange = 1000 * 60 * 60 * 24 * 30 * (parseInt(req.query.months, 10) || 3);
var cutoff = Date.now() - timeRange; const cutoff = Date.now() - timeRange;
getUsers('users:online', 'inactive', '-inf', cutoff, req, res, next); await getUsers('users:online', 'inactive', '-inf', cutoff, req, res);
}; };
usersController.banned = function (req, res, next) { usersController.banned = async function (req, res) {
getUsers('users:banned', 'banned', undefined, undefined, req, res, next); await getUsers('users:banned', 'banned', undefined, undefined, req, res);
}; };
usersController.registrationQueue = function (req, res, next) { usersController.registrationQueue = async function (req, res) {
var page = parseInt(req.query.page, 10) || 1; const page = parseInt(req.query.page, 10) || 1;
var itemsPerPage = 20; const itemsPerPage = 20;
var start = (page - 1) * 20; const start = (page - 1) * 20;
var stop = start + itemsPerPage - 1; const stop = start + itemsPerPage - 1;
var invitations;
const data = await utils.promiseParallel({
async.waterfall([ registrationQueueCount: db.sortedSetCard('registration:queue'),
function (next) { users: user.getRegistrationQueue(start, stop),
async.parallel({ customHeaders: plugins.fireHook('filter:admin.registrationQueue.customHeaders', { headers: [] }),
registrationQueueCount: function (next) { invites: getInvites(),
db.sortedSetCard('registration:queue', next); });
}, var pageCount = Math.max(1, Math.ceil(data.registrationQueueCount / itemsPerPage));
users: function (next) { data.pagination = pagination.create(page, pageCount);
user.getRegistrationQueue(start, stop, next); data.customHeaders = data.customHeaders.headers;
}, res.render('admin/manage/registration', data);
customHeaders: function (next) { };
plugins.fireHook('filter:admin.registrationQueue.customHeaders', { headers: [] }, next);
}, async function getInvites() {
invites: function (next) { const invitations = await user.getAllInvites();
async.waterfall([ const uids = invitations.map(invite => invite.uid);
function (next) { let usernames = await user.getUsersFields(uids, ['username']);
user.getAllInvites(next); usernames = usernames.map(user => user.username);
},
function (_invitations, next) {
invitations = _invitations;
async.map(invitations, function (invites, next) {
user.getUserField(invites.uid, 'username', next);
}, next);
},
function (usernames, next) {
invitations.forEach(function (invites, index) { invitations.forEach(function (invites, index) {
invites.username = usernames[index]; invites.username = usernames[index];
}); });
async.map(invitations, function (invites, next) {
async.map(invites.invitations, user.getUsernameByEmail, next); async function getUsernamesByEmails(emails) {
}, next); const uids = await db.sortedSetScore('email:uid', emails.map(email => String(email).toLowerCase()));
}, const usernames = await user.getUsersFields(uids, ['username']);
function (usernames, next) { return usernames.map(user => user.username);
}
usernames = await Promise.all(invitations.map(invites => getUsernamesByEmails(invites.invitations)));
invitations.forEach(function (invites, index) { invitations.forEach(function (invites, index) {
invites.invitations = invites.invitations.map(function (email, i) { invites.invitations = invites.invitations.map(function (email, i) {
return { return {
@ -103,73 +100,51 @@ usersController.registrationQueue = function (req, res, next) {
}; };
}); });
}); });
next(null, invitations); return invitations;
}, }
], next);
},
}, next);
},
function (data) {
var pageCount = Math.max(1, Math.ceil(data.registrationQueueCount / itemsPerPage));
data.pagination = pagination.create(page, pageCount);
data.customHeaders = data.customHeaders.headers;
res.render('admin/manage/registration', data);
},
], next);
};
function getUsers(set, section, min, max, req, res, next) { async function getUsers(set, section, min, max, req, res) {
var page = parseInt(req.query.page, 10) || 1; const page = parseInt(req.query.page, 10) || 1;
var resultsPerPage = parseInt(req.query.resultsPerPage, 10) || 50; let resultsPerPage = parseInt(req.query.resultsPerPage, 10) || 50;
if (![50, 100, 250, 500].includes(resultsPerPage)) { if (![50, 100, 250, 500].includes(resultsPerPage)) {
resultsPerPage = 50; resultsPerPage = 50;
} }
var start = Math.max(0, page - 1) * resultsPerPage; const start = Math.max(0, page - 1) * resultsPerPage;
var stop = start + resultsPerPage - 1; const stop = start + resultsPerPage - 1;
var byScore = min !== undefined && max !== undefined; const byScore = min !== undefined && max !== undefined;
async.waterfall([ async function getCount() {
function (next) {
async.parallel({
count: function (next) {
if (byScore) { if (byScore) {
db.sortedSetCount(set, min, max, next); return await db.sortedSetCount(set, min, max);
} else if (set === 'users:banned' || set === 'users:notvalidated') { } else if (set === 'users:banned' || set === 'users:notvalidated') {
db.sortedSetCard(set, next); return await db.sortedSetCard(set);
} else {
db.getObjectField('global', 'userCount', next);
} }
}, return await db.getObjectField('global', 'userCount');
users: function (next) { }
async.waterfall([
function (next) { async function getUsersWithFields() {
let uids;
if (byScore) { if (byScore) {
db.getSortedSetRevRangeByScore(set, start, resultsPerPage, max, min, next); uids = await db.getSortedSetRevRangeByScore(set, start, resultsPerPage, max, min);
} else { } else {
user.getUidsFromSet(set, start, stop, next); uids = await user.getUidsFromSet(set, start, stop);
} }
}, return await user.getUsersWithFields(uids, userFields, req.uid);
function (uids, next) { }
user.getUsersWithFields(uids, userFields, req.uid, next);
}, const [count, users] = await Promise.all([
], next); getCount(),
}, getUsersWithFields(),
}, next); ]);
},
function (results) { const data = {
results.users = results.users.filter(function (user) { users: users.filter(user => user && parseInt(user.uid, 10)),
return user && parseInt(user.uid, 10);
});
var data = {
users: results.users,
page: page, page: page,
pageCount: Math.max(1, Math.ceil(results.count / resultsPerPage)), pageCount: Math.max(1, Math.ceil(count / resultsPerPage)),
resultsPerPage: resultsPerPage, resultsPerPage: resultsPerPage,
}; };
data[section] = true; data[section] = true;
render(req, res, data); render(req, res, data);
},
], next);
} }
function render(req, res, data) { function render(req, res, data) {
@ -185,7 +160,7 @@ function render(req, res, data) {
res.render('admin/manage/users', data); res.render('admin/manage/users', data);
} }
usersController.getCSV = function (req, res, next) { usersController.getCSV = async function (req, res) {
var referer = req.headers.referer; var referer = req.headers.referer;
if (!referer || !referer.replace(nconf.get('url'), '').startsWith('/admin/manage/users')) { if (!referer || !referer.replace(nconf.get('url'), '').startsWith('/admin/manage/users')) {
@ -196,14 +171,8 @@ usersController.getCSV = function (req, res, next) {
uid: req.uid, uid: req.uid,
ip: req.ip, ip: req.ip,
}); });
async.waterfall([ const data = await user.getUsersCSV();
function (next) {
user.getUsersCSV(next);
},
function (data) {
res.attachment('users.csv'); res.attachment('users.csv');
res.setHeader('Content-Type', 'text/csv'); res.setHeader('Content-Type', 'text/csv');
res.end(data); res.end(data);
},
], next);
}; };

@ -1,16 +1,9 @@
'use strict'; 'use strict';
var async = require('async'); const widgetsController = module.exports;
const admin = require('../../widgets/admin');
var widgetsController = module.exports; widgetsController.get = async function (req, res) {
const data = await admin.get();
widgetsController.get = function (req, res, next) {
async.waterfall([
function (next) {
require('../../widgets/admin').get(next);
},
function (data) {
res.render('admin/extend/widgets', data); res.render('admin/extend/widgets', data);
},
], next);
}; };

@ -139,3 +139,5 @@ function getActiveRewards(callback) {
}); });
}); });
} }
require('../promisify')(rewards);

Loading…
Cancel
Save