mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-12-22 00:10:25 +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 () {
|
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);
|
||||||
|
const statAsync = util.promisify(fs.stat);
|
||||||
|
|
||||||
var meta = require('../../meta');
|
const meta = require('../../meta');
|
||||||
var posts = require('../../posts');
|
const posts = require('../../posts');
|
||||||
var file = require('../../file');
|
const file = require('../../file');
|
||||||
var image = require('../../image');
|
const image = require('../../image');
|
||||||
var plugins = require('../../plugins');
|
const plugins = require('../../plugins');
|
||||||
var pagination = require('../../pagination');
|
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) {
|
uploadsController.get = async function (req, res, next) {
|
||||||
var currentFolder = path.join(nconf.get('upload_path'), req.query.dir || '');
|
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);
|
|
||||||
},
|
|
||||||
function (uploadedSound, next) {
|
|
||||||
meta.sounds.build(next);
|
|
||||||
},
|
|
||||||
], function (err) {
|
|
||||||
file.delete(uploadedFile.path);
|
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
res.json([{}]);
|
res.json([{}]);
|
||||||
});
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
} finally {
|
||||||
|
file.delete(uploadedFile.path);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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 {
|
||||||
file.delete(uploadedFile.path);
|
const data = await file.saveFileToLocal(uploadedFile.name, params.folder, uploadedFile.path);
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
res.json([{ url: data.url }]);
|
res.json([{ url: data.url }]);
|
||||||
});
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
} finally {
|
||||||
|
file.delete(uploadedFile.path);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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({
|
||||||
|
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) {
|
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);
|
||||||
|
|||||||
Reference in New Issue
Block a user