mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-12-21 16:00:26 +01:00
refactor: async/await admin/controllers
This commit is contained in:
@@ -7,10 +7,10 @@ define('admin/manage/users', ['translator', 'benchpress'], function (translator,
|
||||
Users.init = function () {
|
||||
var navPills = $('.nav-pills li');
|
||||
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';
|
||||
}
|
||||
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 () {
|
||||
var query = utils.params();
|
||||
|
||||
@@ -1,19 +1,10 @@
|
||||
'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) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
require('../../rewards/admin').get(next);
|
||||
},
|
||||
function (data) {
|
||||
rewardsController.get = async function (req, res) {
|
||||
const data = await admin.get();
|
||||
res.render('admin/extend/rewards', data);
|
||||
},
|
||||
], next);
|
||||
};
|
||||
|
||||
|
||||
module.exports = rewardsController;
|
||||
|
||||
@@ -1,56 +1,41 @@
|
||||
'use strict';
|
||||
|
||||
var async = require('async');
|
||||
const meta = require('../../meta');
|
||||
const emailer = require('../../emailer');
|
||||
const notifications = require('../../notifications');
|
||||
|
||||
var meta = require('../../meta');
|
||||
var emailer = require('../../emailer');
|
||||
var notifications = require('../../notifications');
|
||||
const settingsController = module.exports;
|
||||
|
||||
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) {
|
||||
var term = req.params.term ? req.params.term : 'general';
|
||||
|
||||
switch (req.params.term) {
|
||||
case 'email':
|
||||
renderEmail(req, res, next);
|
||||
break;
|
||||
case 'user':
|
||||
renderUser(req, res, next);
|
||||
break;
|
||||
default:
|
||||
if (term === 'email') {
|
||||
await renderEmail(req, res, next);
|
||||
} else if (term === 'user') {
|
||||
await renderUser(req, res, next);
|
||||
} else {
|
||||
res.render('admin/settings/' + term);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function renderEmail(req, res, next) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
async.parallel({
|
||||
emails: async.apply(emailer.getTemplates, meta.config),
|
||||
services: emailer.listServices,
|
||||
}, next);
|
||||
},
|
||||
function (results) {
|
||||
async function renderEmail(req, res) {
|
||||
const [emails, services] = await Promise.all([
|
||||
emailer.getTemplates(meta.config),
|
||||
emailer.listServices(),
|
||||
]);
|
||||
res.render('admin/settings/email', {
|
||||
emails: results.emails,
|
||||
sendable: results.emails.filter(function (email) {
|
||||
emails: emails,
|
||||
sendable: emails.filter(function (email) {
|
||||
return !email.path.includes('_plaintext') && !email.path.includes('partials');
|
||||
}),
|
||||
services: results.services,
|
||||
services: services,
|
||||
});
|
||||
},
|
||||
], next);
|
||||
}
|
||||
|
||||
function renderUser(req, res, next) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
notifications.getAllNotificationTypes(next);
|
||||
},
|
||||
function (notificationTypes) {
|
||||
var notificationSettings = notificationTypes.map(function (type) {
|
||||
async function renderUser(req, res) {
|
||||
const notificationTypes = await notifications.getAllNotificationTypes();
|
||||
const notificationSettings = notificationTypes.map(function (type) {
|
||||
return {
|
||||
name: type,
|
||||
label: '[[notifications:' + type + ']]',
|
||||
@@ -59,6 +44,4 @@ function renderUser(req, res, next) {
|
||||
res.render('admin/settings/user', {
|
||||
notificationSettings: notificationSettings,
|
||||
});
|
||||
},
|
||||
], next);
|
||||
}
|
||||
|
||||
@@ -1,20 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
var async = require('async');
|
||||
const social = require('../../social');
|
||||
|
||||
var social = require('../../social');
|
||||
const socialController = module.exports;
|
||||
|
||||
var socialController = module.exports;
|
||||
|
||||
socialController.get = function (req, res, next) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
social.getPostSharing(next);
|
||||
},
|
||||
function (posts) {
|
||||
socialController.get = async function (req, res) {
|
||||
const posts = await social.getPostSharing();
|
||||
res.render('admin/general/social', {
|
||||
posts: posts,
|
||||
});
|
||||
},
|
||||
], next);
|
||||
};
|
||||
|
||||
@@ -1,25 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
var async = require('async');
|
||||
const plugins = require('../../plugins');
|
||||
const meta = require('../../meta');
|
||||
|
||||
var plugins = require('../../plugins');
|
||||
var meta = require('../../meta');
|
||||
const soundsController = module.exports;
|
||||
|
||||
var soundsController = module.exports;
|
||||
|
||||
soundsController.get = function (req, res, next) {
|
||||
var types = [
|
||||
soundsController.get = async function (req, res) {
|
||||
const types = [
|
||||
'notification',
|
||||
'chat-incoming',
|
||||
'chat-outgoing',
|
||||
];
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
meta.configs.getFields(types, next);
|
||||
},
|
||||
function (settings) {
|
||||
settings = settings || {};
|
||||
|
||||
const settings = await meta.configs.getFields(types) || {};
|
||||
var output = {};
|
||||
|
||||
types.forEach(function (type) {
|
||||
@@ -43,6 +35,4 @@ soundsController.get = function (req, res, next) {
|
||||
});
|
||||
|
||||
res.render('admin/general/sounds', output);
|
||||
},
|
||||
], next);
|
||||
};
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
var async = require('async');
|
||||
const topics = require('../../topics');
|
||||
|
||||
var topics = require('../../topics');
|
||||
const tagsController = module.exports;
|
||||
|
||||
var tagsController = module.exports;
|
||||
|
||||
tagsController.get = function (req, res, next) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
topics.getTags(0, 199, next);
|
||||
},
|
||||
function (tags) {
|
||||
tagsController.get = async function (req, res) {
|
||||
const tags = await topics.getTags(0, 199);
|
||||
res.render('admin/manage/tags', { tags: tags });
|
||||
},
|
||||
], next);
|
||||
};
|
||||
|
||||
@@ -1,48 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var async = require('async');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
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) {
|
||||
var themeDir = path.join(__dirname, '../../../node_modules', req.params.theme);
|
||||
var themeConfigPath = path.join(themeDir, 'theme.json');
|
||||
var screenshotPath;
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
fs.readFile(themeConfigPath, 'utf8', function (err, config) {
|
||||
if (err) {
|
||||
themesController.get = async function (req, res, next) {
|
||||
const themeDir = path.join(__dirname, '../../../node_modules', req.params.theme);
|
||||
const themeConfigPath = path.join(themeDir, 'theme.json');
|
||||
|
||||
let themeConfig;
|
||||
try {
|
||||
themeConfig = await readFileAsync(themeConfigPath, 'utf8');
|
||||
themeConfig = JSON.parse(themeConfig);
|
||||
} catch (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
return next(Error('invalid-data'));
|
||||
}
|
||||
|
||||
return next(err);
|
||||
}
|
||||
|
||||
return next(null, config);
|
||||
});
|
||||
},
|
||||
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) {
|
||||
const screenshotPath = themeConfig.screenshot ? path.join(themeDir, themeConfig.screenshot) : defaultScreenshotPath;
|
||||
const exists = await file.exists(screenshotPath);
|
||||
res.sendFile(exists ? screenshotPath : defaultScreenshotPath);
|
||||
},
|
||||
], next);
|
||||
};
|
||||
|
||||
@@ -1,47 +1,41 @@
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
var async = require('async');
|
||||
var nconf = require('nconf');
|
||||
var mime = require('mime');
|
||||
var fs = require('fs');
|
||||
const path = require('path');
|
||||
const nconf = require('nconf');
|
||||
const mime = require('mime');
|
||||
const fs = require('fs');
|
||||
const util = require('util');
|
||||
const readdirAsync = util.promisify(fs.readdir);
|
||||
const statAsync = util.promisify(fs.stat);
|
||||
|
||||
var meta = require('../../meta');
|
||||
var posts = require('../../posts');
|
||||
var file = require('../../file');
|
||||
var image = require('../../image');
|
||||
var plugins = require('../../plugins');
|
||||
var pagination = require('../../pagination');
|
||||
const meta = require('../../meta');
|
||||
const posts = require('../../posts');
|
||||
const file = require('../../file');
|
||||
const image = require('../../image');
|
||||
const plugins = require('../../plugins');
|
||||
const pagination = require('../../pagination');
|
||||
|
||||
var allowedImageTypes = ['image/png', 'image/jpeg', 'image/pjpeg', 'image/jpg', 'image/gif', 'image/svg+xml'];
|
||||
const allowedImageTypes = ['image/png', 'image/jpeg', 'image/pjpeg', 'image/jpg', 'image/gif', 'image/svg+xml'];
|
||||
|
||||
var uploadsController = module.exports;
|
||||
const uploadsController = module.exports;
|
||||
|
||||
uploadsController.get = function (req, res, next) {
|
||||
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'))) {
|
||||
return next(new Error('[[error:invalid-path]]'));
|
||||
}
|
||||
var itemsPerPage = 20;
|
||||
var itemCount = 0;
|
||||
var page = parseInt(req.query.page, 10) || 1;
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
fs.readdir(currentFolder, next);
|
||||
},
|
||||
function (files, next) {
|
||||
files = files.filter(function (filename) {
|
||||
return filename !== '.gitignore';
|
||||
});
|
||||
|
||||
itemCount = files.length;
|
||||
const itemsPerPage = 20;
|
||||
const page = parseInt(req.query.page, 10) || 1;
|
||||
try {
|
||||
let files = await readdirAsync(currentFolder);
|
||||
files = files.filter(filename => filename !== '.gitignore');
|
||||
const itemCount = files.length;
|
||||
var start = Math.max(0, (page - 1) * itemsPerPage);
|
||||
var stop = start + itemsPerPage;
|
||||
files = files.slice(start, stop);
|
||||
|
||||
filesToData(currentFolder, files, next);
|
||||
},
|
||||
function (files, next) {
|
||||
files = await filesToData(currentFolder, files);
|
||||
|
||||
// Float directories to the top
|
||||
files.sort(function (a, b) {
|
||||
if (a.isDirectory && !b.isDirectory) {
|
||||
@@ -57,18 +51,11 @@ uploadsController.get = function (req, res, next) {
|
||||
|
||||
// Add post usage info if in /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) {
|
||||
file.inPids = usage[idx].map(pid => parseInt(pid, 10));
|
||||
});
|
||||
|
||||
next(err, files);
|
||||
});
|
||||
} else {
|
||||
setImmediate(next, null, files);
|
||||
}
|
||||
},
|
||||
function (files) {
|
||||
res.render('admin/manage/uploads', {
|
||||
currentFolder: currentFolder.replace(nconf.get('upload_path'), ''),
|
||||
showPids: files.length && files[0].hasOwnProperty('inPids'),
|
||||
@@ -76,8 +63,9 @@ uploadsController.get = function (req, res, next) {
|
||||
breadcrumbs: buildBreadcrumbs(currentFolder),
|
||||
pagination: pagination.create(page, Math.ceil(itemCount / itemsPerPage), req.query),
|
||||
});
|
||||
},
|
||||
], next);
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
};
|
||||
|
||||
function buildBreadcrumbs(currentFolder) {
|
||||
@@ -98,24 +86,18 @@ function buildBreadcrumbs(currentFolder) {
|
||||
return crumbs;
|
||||
}
|
||||
|
||||
function filesToData(currentDir, files, callback) {
|
||||
async.map(files, function (file, next) {
|
||||
var stat;
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
fs.stat(path.join(currentDir, file), next);
|
||||
},
|
||||
function (_stat, next) {
|
||||
stat = _stat;
|
||||
async function filesToData(currentDir, files) {
|
||||
return await Promise.all(files.map(file => getFileData(currentDir, file)));
|
||||
}
|
||||
|
||||
async function getFileData(currentDir, file) {
|
||||
const stat = await statAsync(path.join(currentDir, file));
|
||||
let filesInDir = [];
|
||||
if (stat.isDirectory()) {
|
||||
fs.readdir(path.join(currentDir, file), next);
|
||||
} else {
|
||||
next(null, []);
|
||||
filesInDir = await readdirAsync(path.join(currentDir, file));
|
||||
}
|
||||
},
|
||||
function (filesInDir, next) {
|
||||
var url = nconf.get('upload_url') + currentDir.replace(nconf.get('upload_path'), '') + '/' + file;
|
||||
next(null, {
|
||||
const url = nconf.get('upload_url') + currentDir.replace(nconf.get('upload_path'), '') + '/' + file;
|
||||
return {
|
||||
name: file,
|
||||
path: path.join(currentDir, file).replace(nconf.get('upload_path'), ''),
|
||||
url: url,
|
||||
@@ -125,15 +107,12 @@ function filesToData(currentDir, files, callback) {
|
||||
isDirectory: stat.isDirectory(),
|
||||
isFile: stat.isFile(),
|
||||
mtime: stat.mtimeMs,
|
||||
});
|
||||
},
|
||||
], next);
|
||||
}, callback);
|
||||
};
|
||||
}
|
||||
|
||||
uploadsController.uploadCategoryPicture = function (req, res, next) {
|
||||
var uploadedFile = req.files.files[0];
|
||||
var params = null;
|
||||
uploadsController.uploadCategoryPicture = async function (req, res, next) {
|
||||
const uploadedFile = req.files.files[0];
|
||||
let params = null;
|
||||
|
||||
try {
|
||||
params = JSON.parse(req.body.params);
|
||||
@@ -142,91 +121,80 @@ uploadsController.uploadCategoryPicture = function (req, res, next) {
|
||||
return next(new Error('[[error:invalid-json]]'));
|
||||
}
|
||||
|
||||
if (validateUpload(req, res, next, uploadedFile, allowedImageTypes)) {
|
||||
var filename = 'category-' + params.cid + path.extname(uploadedFile.name);
|
||||
uploadImage(filename, 'category', uploadedFile, req, res, next);
|
||||
if (validateUpload(res, uploadedFile, allowedImageTypes)) {
|
||||
const filename = 'category-' + params.cid + path.extname(uploadedFile.name);
|
||||
await uploadImage(filename, 'category', uploadedFile, req, res, next);
|
||||
}
|
||||
};
|
||||
|
||||
uploadsController.uploadFavicon = function (req, res, next) {
|
||||
var uploadedFile = req.files.files[0];
|
||||
var allowedTypes = ['image/x-icon', 'image/vnd.microsoft.icon'];
|
||||
uploadsController.uploadFavicon = async function (req, res, next) {
|
||||
const uploadedFile = req.files.files[0];
|
||||
const allowedTypes = ['image/x-icon', 'image/vnd.microsoft.icon'];
|
||||
|
||||
if (validateUpload(req, res, next, uploadedFile, allowedTypes)) {
|
||||
file.saveFileToLocal('favicon.ico', 'system', uploadedFile.path, function (err, image) {
|
||||
if (validateUpload(res, uploadedFile, allowedTypes)) {
|
||||
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);
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
res.json([{ name: uploadedFile.name, url: image.url }]);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
uploadsController.uploadTouchIcon = function (req, res, next) {
|
||||
var uploadedFile = req.files.files[0];
|
||||
var allowedTypes = ['image/png'];
|
||||
var 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);
|
||||
}
|
||||
uploadsController.uploadTouchIcon = async function (req, res, next) {
|
||||
const uploadedFile = req.files.files[0];
|
||||
const allowedTypes = ['image/png'];
|
||||
const sizes = [36, 48, 72, 96, 144, 192];
|
||||
|
||||
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
|
||||
async.eachSeries(sizes, function (size, next) {
|
||||
image.resizeImage({
|
||||
for (const size of sizes) {
|
||||
/* eslint-disable no-await-in-loop */
|
||||
await image.resizeImage({
|
||||
path: uploadedFile.path,
|
||||
target: path.join(nconf.get('upload_path'), 'system', 'touchicon-' + size + '.png'),
|
||||
width: size,
|
||||
height: size,
|
||||
}, next);
|
||||
}, function (err) {
|
||||
file.delete(uploadedFile.path);
|
||||
|
||||
if (err) {
|
||||
return next(err);
|
||||
});
|
||||
}
|
||||
|
||||
res.json([{ name: uploadedFile.name, url: imageObj.url }]);
|
||||
});
|
||||
});
|
||||
} catch (err) {
|
||||
next(err);
|
||||
} finally {
|
||||
file.delete(uploadedFile.path);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
uploadsController.uploadLogo = function (req, res, next) {
|
||||
upload('site-logo', req, res, next);
|
||||
uploadsController.uploadLogo = async function (req, res, next) {
|
||||
await upload('site-logo', req, res, next);
|
||||
};
|
||||
|
||||
uploadsController.uploadSound = function (req, res, next) {
|
||||
var uploadedFile = req.files.files[0];
|
||||
uploadsController.uploadSound = async function (req, res, next) {
|
||||
const uploadedFile = req.files.files[0];
|
||||
|
||||
var mimeType = mime.getType(uploadedFile.name);
|
||||
const mimeType = mime.getType(uploadedFile.name);
|
||||
if (!/^audio\//.test(mimeType)) {
|
||||
return next(Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
file.saveFileToLocal(uploadedFile.name, 'sounds', uploadedFile.path, next);
|
||||
},
|
||||
function (uploadedSound, next) {
|
||||
meta.sounds.build(next);
|
||||
},
|
||||
], function (err) {
|
||||
file.delete(uploadedFile.path);
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
try {
|
||||
await file.saveFileToLocal(uploadedFile.name, 'sounds', uploadedFile.path);
|
||||
await meta.sounds.build();
|
||||
res.json([{}]);
|
||||
});
|
||||
} catch (err) {
|
||||
next(err);
|
||||
} finally {
|
||||
file.delete(uploadedFile.path);
|
||||
}
|
||||
};
|
||||
|
||||
uploadsController.uploadFile = function (req, res, next) {
|
||||
var uploadedFile = req.files.files[0];
|
||||
var params;
|
||||
uploadsController.uploadFile = async function (req, res, next) {
|
||||
const uploadedFile = req.files.files[0];
|
||||
let params;
|
||||
try {
|
||||
params = JSON.parse(req.body.params);
|
||||
} catch (e) {
|
||||
@@ -234,33 +202,34 @@ uploadsController.uploadFile = function (req, res, next) {
|
||||
return next(new Error('[[error:invalid-json]]'));
|
||||
}
|
||||
|
||||
file.saveFileToLocal(uploadedFile.name, params.folder, uploadedFile.path, function (err, data) {
|
||||
file.delete(uploadedFile.path);
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
uploadsController.uploadDefaultAvatar = function (req, res, next) {
|
||||
upload('avatar-default', req, res, next);
|
||||
uploadsController.uploadDefaultAvatar = async function (req, res, next) {
|
||||
await upload('avatar-default', req, res, next);
|
||||
};
|
||||
|
||||
uploadsController.uploadOgImage = function (req, res, next) {
|
||||
upload('og:image', req, res, next);
|
||||
uploadsController.uploadOgImage = async function (req, res, next) {
|
||||
await upload('og:image', req, res, next);
|
||||
};
|
||||
|
||||
function upload(name, req, res, next) {
|
||||
var uploadedFile = req.files.files[0];
|
||||
async function upload(name, req, res, next) {
|
||||
const uploadedFile = req.files.files[0];
|
||||
|
||||
if (validateUpload(req, res, next, uploadedFile, allowedImageTypes)) {
|
||||
var filename = name + path.extname(uploadedFile.name);
|
||||
uploadImage(filename, 'system', uploadedFile, req, res, next);
|
||||
if (validateUpload(res, uploadedFile, allowedImageTypes)) {
|
||||
const filename = name + path.extname(uploadedFile.name);
|
||||
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)) {
|
||||
file.delete(uploadedFile.path);
|
||||
res.json({ error: '[[error:invalid-image-type, ' + allowedTypes.join(', ') + ']]' });
|
||||
@@ -270,64 +239,39 @@ function validateUpload(req, res, next, uploadedFile, allowedTypes) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function uploadImage(filename, folder, uploadedFile, req, res, next) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
async function uploadImage(filename, folder, uploadedFile, req, res, next) {
|
||||
let imageData;
|
||||
try {
|
||||
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 {
|
||||
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') {
|
||||
var uploadPath = path.join(nconf.get('upload_path'), folder, 'site-logo-x50.png');
|
||||
async.series([
|
||||
async.apply(image.resizeImage, {
|
||||
const uploadPath = path.join(nconf.get('upload_path'), folder, 'site-logo-x50.png');
|
||||
await image.resizeImage({
|
||||
path: uploadedFile.path,
|
||||
target: uploadPath,
|
||||
height: 50,
|
||||
}),
|
||||
async.apply(meta.configs.set, 'brand:emailLogo', path.join(nconf.get('upload_url'), 'system/site-logo-x50.png')),
|
||||
function (next) {
|
||||
image.size(uploadedFile.path, function (err, size) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
meta.configs.setMultiple({
|
||||
});
|
||||
await meta.configs.set('brand:emailLogo', path.join(nconf.get('upload_url'), 'system/site-logo-x50.png'));
|
||||
const size = await image.size(uploadedFile.path);
|
||||
await meta.configs.setMultiple({
|
||||
'brand:logo:width': size.width,
|
||||
'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') {
|
||||
image.size(uploadedFile.path, function (err, size) {
|
||||
if (err) {
|
||||
next(err);
|
||||
}
|
||||
meta.configs.setMultiple({
|
||||
const size = await image.size(uploadedFile.path);
|
||||
await meta.configs.setMultiple({
|
||||
'og:image:width': size.width,
|
||||
'og:image:height': size.height,
|
||||
}, function (err) {
|
||||
next(err, imageData);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
setImmediate(next, null, imageData);
|
||||
}
|
||||
},
|
||||
], function (err, image) {
|
||||
res.json([{ name: uploadedFile.name, url: imageData.url.startsWith('http') ? imageData.url : nconf.get('relative_path') + imageData.url }]);
|
||||
} catch (err) {
|
||||
next(err);
|
||||
} finally {
|
||||
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';
|
||||
|
||||
var async = require('async');
|
||||
var nconf = require('nconf');
|
||||
const nconf = require('nconf');
|
||||
|
||||
var user = require('../../user');
|
||||
var meta = require('../../meta');
|
||||
var db = require('../../database');
|
||||
var pagination = require('../../pagination');
|
||||
var events = require('../../events');
|
||||
var plugins = require('../../plugins');
|
||||
const user = require('../../user');
|
||||
const meta = require('../../meta');
|
||||
const db = require('../../database');
|
||||
const pagination = require('../../pagination');
|
||||
const events = require('../../events');
|
||||
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'];
|
||||
|
||||
usersController.search = function (req, res) {
|
||||
@@ -22,79 +22,76 @@ usersController.search = function (req, res) {
|
||||
});
|
||||
};
|
||||
|
||||
usersController.sortByJoinDate = function (req, res, next) {
|
||||
getUsers('users:joindate', 'latest', undefined, undefined, req, res, next);
|
||||
usersController.sortByJoinDate = async function (req, res) {
|
||||
await getUsers('users:joindate', 'latest', undefined, undefined, req, res);
|
||||
};
|
||||
|
||||
usersController.notValidated = function (req, res, next) {
|
||||
getUsers('users:notvalidated', 'notvalidated', undefined, undefined, req, res, next);
|
||||
usersController.notValidated = async function (req, res) {
|
||||
await getUsers('users:notvalidated', 'notvalidated', undefined, undefined, req, res);
|
||||
};
|
||||
|
||||
usersController.noPosts = function (req, res, next) {
|
||||
getUsers('users:postcount', 'noposts', '-inf', 0, req, res, next);
|
||||
usersController.noPosts = async function (req, res) {
|
||||
await getUsers('users:postcount', 'noposts', '-inf', 0, req, res);
|
||||
};
|
||||
|
||||
usersController.topPosters = function (req, res, next) {
|
||||
getUsers('users:postcount', 'topposts', 0, '+inf', req, res, next);
|
||||
usersController.topPosters = async function (req, res) {
|
||||
await getUsers('users:postcount', 'topposts', 0, '+inf', req, res);
|
||||
};
|
||||
|
||||
usersController.mostReputaion = function (req, res, next) {
|
||||
getUsers('users:reputation', 'mostreputation', 0, '+inf', req, res, next);
|
||||
usersController.mostReputaion = async function (req, res) {
|
||||
await getUsers('users:reputation', 'mostreputation', 0, '+inf', req, res);
|
||||
};
|
||||
|
||||
usersController.flagged = function (req, res, next) {
|
||||
getUsers('users:flags', 'mostflags', 1, '+inf', req, res, next);
|
||||
usersController.flagged = async function (req, res) {
|
||||
await getUsers('users:flags', 'mostflags', 1, '+inf', req, res);
|
||||
};
|
||||
|
||||
usersController.inactive = function (req, res, next) {
|
||||
var timeRange = 1000 * 60 * 60 * 24 * 30 * (parseInt(req.query.months, 10) || 3);
|
||||
var cutoff = Date.now() - timeRange;
|
||||
getUsers('users:online', 'inactive', '-inf', cutoff, req, res, next);
|
||||
usersController.inactive = async function (req, res) {
|
||||
const timeRange = 1000 * 60 * 60 * 24 * 30 * (parseInt(req.query.months, 10) || 3);
|
||||
const cutoff = Date.now() - timeRange;
|
||||
await getUsers('users:online', 'inactive', '-inf', cutoff, req, res);
|
||||
};
|
||||
|
||||
usersController.banned = function (req, res, next) {
|
||||
getUsers('users:banned', 'banned', undefined, undefined, req, res, next);
|
||||
usersController.banned = async function (req, res) {
|
||||
await getUsers('users:banned', 'banned', undefined, undefined, req, res);
|
||||
};
|
||||
|
||||
usersController.registrationQueue = function (req, res, next) {
|
||||
var page = parseInt(req.query.page, 10) || 1;
|
||||
var itemsPerPage = 20;
|
||||
var start = (page - 1) * 20;
|
||||
var stop = start + itemsPerPage - 1;
|
||||
var invitations;
|
||||
usersController.registrationQueue = async function (req, res) {
|
||||
const page = parseInt(req.query.page, 10) || 1;
|
||||
const itemsPerPage = 20;
|
||||
const start = (page - 1) * 20;
|
||||
const stop = start + itemsPerPage - 1;
|
||||
|
||||
const data = await utils.promiseParallel({
|
||||
registrationQueueCount: db.sortedSetCard('registration:queue'),
|
||||
users: user.getRegistrationQueue(start, stop),
|
||||
customHeaders: plugins.fireHook('filter:admin.registrationQueue.customHeaders', { headers: [] }),
|
||||
invites: getInvites(),
|
||||
});
|
||||
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);
|
||||
};
|
||||
|
||||
async function getInvites() {
|
||||
const invitations = await user.getAllInvites();
|
||||
const uids = invitations.map(invite => invite.uid);
|
||||
let usernames = await user.getUsersFields(uids, ['username']);
|
||||
usernames = usernames.map(user => user.username);
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
async.parallel({
|
||||
registrationQueueCount: function (next) {
|
||||
db.sortedSetCard('registration:queue', next);
|
||||
},
|
||||
users: function (next) {
|
||||
user.getRegistrationQueue(start, stop, next);
|
||||
},
|
||||
customHeaders: function (next) {
|
||||
plugins.fireHook('filter:admin.registrationQueue.customHeaders', { headers: [] }, next);
|
||||
},
|
||||
invites: function (next) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
user.getAllInvites(next);
|
||||
},
|
||||
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) {
|
||||
invites.username = usernames[index];
|
||||
});
|
||||
async.map(invitations, function (invites, next) {
|
||||
async.map(invites.invitations, user.getUsernameByEmail, next);
|
||||
}, next);
|
||||
},
|
||||
function (usernames, next) {
|
||||
|
||||
async function getUsernamesByEmails(emails) {
|
||||
const uids = await db.sortedSetScore('email:uid', emails.map(email => String(email).toLowerCase()));
|
||||
const usernames = await user.getUsersFields(uids, ['username']);
|
||||
return usernames.map(user => user.username);
|
||||
}
|
||||
|
||||
usernames = await Promise.all(invitations.map(invites => getUsernamesByEmails(invites.invitations)));
|
||||
|
||||
invitations.forEach(function (invites, index) {
|
||||
invites.invitations = invites.invitations.map(function (email, i) {
|
||||
return {
|
||||
@@ -103,73 +100,51 @@ usersController.registrationQueue = function (req, res, next) {
|
||||
};
|
||||
});
|
||||
});
|
||||
next(null, 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);
|
||||
};
|
||||
return invitations;
|
||||
}
|
||||
|
||||
function getUsers(set, section, min, max, req, res, next) {
|
||||
var page = parseInt(req.query.page, 10) || 1;
|
||||
var resultsPerPage = parseInt(req.query.resultsPerPage, 10) || 50;
|
||||
async function getUsers(set, section, min, max, req, res) {
|
||||
const page = parseInt(req.query.page, 10) || 1;
|
||||
let resultsPerPage = parseInt(req.query.resultsPerPage, 10) || 50;
|
||||
if (![50, 100, 250, 500].includes(resultsPerPage)) {
|
||||
resultsPerPage = 50;
|
||||
}
|
||||
var start = Math.max(0, page - 1) * resultsPerPage;
|
||||
var stop = start + resultsPerPage - 1;
|
||||
var byScore = min !== undefined && max !== undefined;
|
||||
const start = Math.max(0, page - 1) * resultsPerPage;
|
||||
const stop = start + resultsPerPage - 1;
|
||||
const byScore = min !== undefined && max !== undefined;
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
async.parallel({
|
||||
count: function (next) {
|
||||
async function getCount() {
|
||||
if (byScore) {
|
||||
db.sortedSetCount(set, min, max, next);
|
||||
return await db.sortedSetCount(set, min, max);
|
||||
} else if (set === 'users:banned' || set === 'users:notvalidated') {
|
||||
db.sortedSetCard(set, next);
|
||||
} else {
|
||||
db.getObjectField('global', 'userCount', next);
|
||||
return await db.sortedSetCard(set);
|
||||
}
|
||||
},
|
||||
users: function (next) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
return await db.getObjectField('global', 'userCount');
|
||||
}
|
||||
|
||||
async function getUsersWithFields() {
|
||||
let uids;
|
||||
if (byScore) {
|
||||
db.getSortedSetRevRangeByScore(set, start, resultsPerPage, max, min, next);
|
||||
uids = await db.getSortedSetRevRangeByScore(set, start, resultsPerPage, max, min);
|
||||
} else {
|
||||
user.getUidsFromSet(set, start, stop, next);
|
||||
uids = await user.getUidsFromSet(set, start, stop);
|
||||
}
|
||||
},
|
||||
function (uids, next) {
|
||||
user.getUsersWithFields(uids, userFields, req.uid, next);
|
||||
},
|
||||
], next);
|
||||
},
|
||||
}, next);
|
||||
},
|
||||
function (results) {
|
||||
results.users = results.users.filter(function (user) {
|
||||
return user && parseInt(user.uid, 10);
|
||||
});
|
||||
var data = {
|
||||
users: results.users,
|
||||
return await user.getUsersWithFields(uids, userFields, req.uid);
|
||||
}
|
||||
|
||||
const [count, users] = await Promise.all([
|
||||
getCount(),
|
||||
getUsersWithFields(),
|
||||
]);
|
||||
|
||||
const data = {
|
||||
users: users.filter(user => user && parseInt(user.uid, 10)),
|
||||
page: page,
|
||||
pageCount: Math.max(1, Math.ceil(results.count / resultsPerPage)),
|
||||
pageCount: Math.max(1, Math.ceil(count / resultsPerPage)),
|
||||
resultsPerPage: resultsPerPage,
|
||||
};
|
||||
data[section] = true;
|
||||
render(req, res, data);
|
||||
},
|
||||
], next);
|
||||
}
|
||||
|
||||
function render(req, res, data) {
|
||||
@@ -185,7 +160,7 @@ function render(req, res, data) {
|
||||
res.render('admin/manage/users', data);
|
||||
}
|
||||
|
||||
usersController.getCSV = function (req, res, next) {
|
||||
usersController.getCSV = async function (req, res) {
|
||||
var referer = req.headers.referer;
|
||||
|
||||
if (!referer || !referer.replace(nconf.get('url'), '').startsWith('/admin/manage/users')) {
|
||||
@@ -196,14 +171,8 @@ usersController.getCSV = function (req, res, next) {
|
||||
uid: req.uid,
|
||||
ip: req.ip,
|
||||
});
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
user.getUsersCSV(next);
|
||||
},
|
||||
function (data) {
|
||||
const data = await user.getUsersCSV();
|
||||
res.attachment('users.csv');
|
||||
res.setHeader('Content-Type', 'text/csv');
|
||||
res.end(data);
|
||||
},
|
||||
], next);
|
||||
};
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
var async = require('async');
|
||||
const widgetsController = module.exports;
|
||||
const admin = require('../../widgets/admin');
|
||||
|
||||
var widgetsController = module.exports;
|
||||
|
||||
widgetsController.get = function (req, res, next) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
require('../../widgets/admin').get(next);
|
||||
},
|
||||
function (data) {
|
||||
widgetsController.get = async function (req, res) {
|
||||
const data = await admin.get();
|
||||
res.render('admin/extend/widgets', data);
|
||||
},
|
||||
], next);
|
||||
};
|
||||
|
||||
@@ -139,3 +139,5 @@ function getActiveRewards(callback) {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
require('../promisify')(rewards);
|
||||
|
||||
Reference in New Issue
Block a user