refactor: async/await socket.io/admin

v1.18.x
Barış Soner Uşaklı 6 years ago
parent 516b62ea68
commit 88dfbf213f

@ -1,22 +1,21 @@
'use strict'; 'use strict';
var async = require('async'); const groups = require('../../groups');
var groups = require('../../groups');
var Groups = module.exports; const Groups = module.exports;
Groups.create = function (socket, data, callback) { Groups.create = async function (socket, data) {
if (!data) { if (!data) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
} else if (groups.isPrivilegeGroup(data.name)) { } else if (groups.isPrivilegeGroup(data.name)) {
return callback(new Error('[[error:invalid-group-name]]')); throw new Error('[[error:invalid-group-name]]');
} }
groups.create({ return await groups.create({
name: data.name, name: data.name,
description: data.description, description: data.description,
ownerUid: socket.uid, ownerUid: socket.uid,
}, callback); });
}; };
Groups.join = async (socket, data) => { Groups.join = async (socket, data) => {
@ -32,32 +31,25 @@ Groups.join = async (socket, data) => {
return await groups.join(data.groupName, data.uid); return await groups.join(data.groupName, data.uid);
}; };
Groups.leave = function (socket, data, callback) { Groups.leave = async function (socket, data) {
if (!data) { if (!data) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
} }
if (socket.uid === parseInt(data.uid, 10) && data.groupName === 'administrators') { if (socket.uid === parseInt(data.uid, 10) && data.groupName === 'administrators') {
return callback(new Error('[[error:cant-remove-self-as-admin]]')); throw new Error('[[error:cant-remove-self-as-admin]]');
} }
const isMember = await groups.isMember(data.uid, data.groupName);
async.waterfall([ if (!isMember) {
function (next) { throw new Error('[[error:group-not-member]]');
groups.isMember(data.uid, data.groupName, next); }
}, await groups.leave(data.groupName, data.uid);
function (isMember, next) {
if (!isMember) {
return next(new Error('[[error:group-not-member]]'));
}
groups.leave(data.groupName, data.uid, next);
},
], callback);
}; };
Groups.update = function (socket, data, callback) { Groups.update = async function (socket, data) {
if (!data) { if (!data) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
} }
groups.update(data.groupName, data.values, callback); await groups.update(data.groupName, data.values);
}; };

@ -1,8 +1,8 @@
'use strict'; 'use strict';
var navigationAdmin = require('../../navigation/admin'); const navigationAdmin = require('../../navigation/admin');
var SocketNavigation = module.exports; const SocketNavigation = module.exports;
SocketNavigation.save = function (socket, data, callback) { SocketNavigation.save = async function (socket, data) {
navigationAdmin.save(data, callback); await navigationAdmin.save(data);
}; };

@ -1,12 +1,12 @@
'use strict'; 'use strict';
var rewardsAdmin = require('../../rewards/admin'); const rewardsAdmin = require('../../rewards/admin');
var SocketRewards = module.exports; const SocketRewards = module.exports;
SocketRewards.save = function (socket, data, callback) { SocketRewards.save = async function (socket, data) {
rewardsAdmin.save(data, callback); await rewardsAdmin.save(data);
}; };
SocketRewards.delete = function (socket, data, callback) { SocketRewards.delete = async function (socket, data) {
rewardsAdmin.delete(data, callback); await rewardsAdmin.delete(data);
}; };

@ -1,30 +1,23 @@
'use strict'; 'use strict';
const os = require('os');
const nconf = require('nconf');
var async = require('async'); const topics = require('../../topics');
var os = require('os'); const pubsub = require('../../pubsub');
var nconf = require('nconf'); const utils = require('../../utils');
var winston = require('winston');
var topics = require('../../topics'); const stats = {};
var pubsub = require('../../pubsub'); const totals = {};
var utils = require('../../utils');
var stats = {}; const SocketRooms = module.exports;
var totals = {};
var SocketRooms = module.exports;
SocketRooms.stats = stats; SocketRooms.stats = stats;
SocketRooms.totals = totals; SocketRooms.totals = totals;
pubsub.on('sync:stats:start', function () { pubsub.on('sync:stats:start', function () {
SocketRooms.getLocalStats(function (err, stats) { const stats = SocketRooms.getLocalStats();
if (err) { pubsub.publish('sync:stats:end', { stats: stats, id: os.hostname() + ':' + nconf.get('port') });
return winston.error(err);
}
pubsub.publish('sync:stats:end', { stats: stats, id: os.hostname() + ':' + nconf.get('port') });
});
}); });
pubsub.on('sync:stats:end', function (data) { pubsub.on('sync:stats:end', function (data) {
@ -54,7 +47,7 @@ SocketRooms.getTotalGuestCount = function (callback) {
}; };
SocketRooms.getAll = function (socket, data, callback) { SocketRooms.getAll = async function () {
pubsub.publish('sync:stats:start'); pubsub.publish('sync:stats:start');
totals.onlineGuestCount = 0; totals.onlineGuestCount = 0;
@ -92,27 +85,16 @@ SocketRooms.getAll = function (socket, data, callback) {
topTenTopics.push({ tid: tid, count: totals.topics[tid].count || 0 }); topTenTopics.push({ tid: tid, count: totals.topics[tid].count || 0 });
}); });
topTenTopics = topTenTopics.sort(function (a, b) { topTenTopics = topTenTopics.sort((a, b) => b.count - a.count).slice(0, 10);
return b.count - a.count;
}).slice(0, 10);
var topTenTids = topTenTopics.map(function (topic) {
return topic.tid;
});
async.waterfall([ var topTenTids = topTenTopics.map(topic => topic.tid);
function (next) {
topics.getTopicsFields(topTenTids, ['title'], next);
},
function (titles, next) {
totals.topTenTopics = topTenTopics.map(function (topic, index) {
topic.title = titles[index].title;
return topic;
});
next(null, totals); const titles = await topics.getTopicsFields(topTenTids, ['title']);
}, totals.topTenTopics = topTenTopics.map(function (topic, index) {
], callback); topic.title = titles[index].title;
return topic;
});
return totals;
}; };
SocketRooms.getOnlineUserCount = function (io) { SocketRooms.getOnlineUserCount = function (io) {
@ -129,7 +111,7 @@ SocketRooms.getOnlineUserCount = function (io) {
return count; return count;
}; };
SocketRooms.getLocalStats = function (callback) { SocketRooms.getLocalStats = function () {
var io = require('../index').server; var io = require('../index').server;
var socketData = { var socketData = {
@ -170,14 +152,11 @@ SocketRooms.getLocalStats = function (callback) {
} }
} }
topTenTopics = topTenTopics.sort(function (a, b) { topTenTopics = topTenTopics.sort((a, b) => b.count - a.count).slice(0, 10);
return b.count - a.count;
}).slice(0, 10);
socketData.topics = topTenTopics; socketData.topics = topTenTopics;
} }
callback(null, socketData); return socketData;
}; };
require('../../promisify')(SocketRooms); require('../../promisify')(SocketRooms);

@ -1,8 +1,8 @@
'use strict'; 'use strict';
var social = require('../../social'); const social = require('../../social');
var SocketSocial = module.exports; const SocketSocial = module.exports;
SocketSocial.savePostSharingNetworks = function (socket, data, callback) { SocketSocial.savePostSharingNetworks = async function (socket, data) {
social.setActivePostSharingNetworks(data, callback); await social.setActivePostSharingNetworks(data);
}; };

@ -1,37 +1,37 @@
'use strict'; 'use strict';
var topics = require('../../topics'); const topics = require('../../topics');
var Tags = module.exports; const Tags = module.exports;
Tags.create = function (socket, data, callback) { Tags.create = async function (socket, data) {
if (!data) { if (!data) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
} }
topics.createEmptyTag(data.tag, callback); await topics.createEmptyTag(data.tag);
}; };
Tags.update = function (socket, data, callback) { Tags.update = async function (socket, data) {
if (!Array.isArray(data)) { if (!Array.isArray(data)) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
} }
topics.updateTags(data, callback); await topics.updateTags(data);
}; };
Tags.rename = function (socket, data, callback) { Tags.rename = async function (socket, data) {
if (!Array.isArray(data)) { if (!Array.isArray(data)) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
} }
topics.renameTags(data, callback); await topics.renameTags(data);
}; };
Tags.deleteTags = function (socket, data, callback) { Tags.deleteTags = async function (socket, data) {
if (!data) { if (!data) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
} }
topics.deleteTags(data.tags, callback); await topics.deleteTags(data.tags);
}; };

@ -1,265 +1,192 @@
'use strict'; 'use strict';
var async = require('async'); const async = require('async');
var winston = require('winston'); const winston = require('winston');
var db = require('../../database'); const db = require('../../database');
var groups = require('../../groups'); const groups = require('../../groups');
var user = require('../../user'); const user = require('../../user');
var events = require('../../events'); const events = require('../../events');
var meta = require('../../meta'); const meta = require('../../meta');
var plugins = require('../../plugins'); const plugins = require('../../plugins');
var User = module.exports; const User = module.exports;
User.makeAdmins = function (socket, uids, callback) { User.makeAdmins = async function (socket, uids) {
if (!Array.isArray(uids)) { if (!Array.isArray(uids)) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
}
const userData = await user.getUsersFields(uids, ['banned']);
userData.forEach((userData) => {
if (userData && userData.banned) {
throw new Error('[[error:cant-make-banned-users-admin]]');
}
});
for (const uid of uids) {
/* eslint-disable no-await-in-loop */
await groups.join('administrators', uid);
await events.log({
type: 'user-makeAdmin',
uid: socket.uid,
targetUid: uid,
ip: socket.ip,
});
} }
async.waterfall([
function (next) {
user.getUsersFields(uids, ['banned'], next);
},
function (userData, next) {
for (var i = 0; i < userData.length; i += 1) {
if (userData[i] && userData[i].banned) {
return callback(new Error('[[error:cant-make-banned-users-admin]]'));
}
}
async.eachSeries(uids, function (uid, next) {
async.waterfall([
function (next) {
groups.join('administrators', uid, next);
},
function (next) {
events.log({
type: 'user-makeAdmin',
uid: socket.uid,
targetUid: uid,
ip: socket.ip,
}, next);
},
], next);
}, next);
},
], callback);
}; };
User.removeAdmins = function (socket, uids, callback) { User.removeAdmins = async function (socket, uids) {
if (!Array.isArray(uids)) { if (!Array.isArray(uids)) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
}
for (const uid of uids) {
/* eslint-disable no-await-in-loop */
const count = await groups.getMemberCount('administrators');
if (count === 1) {
throw new Error('[[error:cant-remove-last-admin]]');
}
await groups.leave('administrators', uid);
await events.log({
type: 'user-removeAdmin',
uid: socket.uid,
targetUid: uid,
ip: socket.ip,
});
} }
async.eachSeries(uids, function (uid, next) {
async.waterfall([
function (next) {
groups.getMemberCount('administrators', next);
},
function (count, next) {
if (count === 1) {
return next(new Error('[[error:cant-remove-last-admin]]'));
}
groups.leave('administrators', uid, next);
},
function (next) {
events.log({
type: 'user-removeAdmin',
uid: socket.uid,
targetUid: uid,
ip: socket.ip,
}, next);
},
], next);
}, callback);
}; };
User.createUser = function (socket, userData, callback) { User.createUser = async function (socket, userData) {
if (!userData) { if (!userData) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
} }
user.create(userData, callback); return await user.create(userData);
}; };
User.resetLockouts = function (socket, uids, callback) { User.resetLockouts = async function (socket, uids) {
if (!Array.isArray(uids)) { if (!Array.isArray(uids)) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
} }
await Promise.all(uids.map(uid => user.auth.resetLockout(uid)));
async.each(uids, user.auth.resetLockout, callback);
}; };
User.validateEmail = function (socket, uids, callback) { User.validateEmail = async function (socket, uids) {
if (!Array.isArray(uids)) { if (!Array.isArray(uids)) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
} }
uids = uids.filter(uid => parseInt(uid, 10)); uids = uids.filter(uid => parseInt(uid, 10));
await db.setObjectField(uids.map(uid => 'user:' + uid), 'email:confirmed', 1);
async.waterfall([ await db.sortedSetRemove('users:notvalidated', uids);
function (next) {
async.each(uids, function (uid, next) {
user.setUserField(uid, 'email:confirmed', 1, next);
}, next);
},
function (next) {
db.sortedSetRemove('users:notvalidated', uids, next);
},
], callback);
}; };
User.sendValidationEmail = function (socket, uids, callback) { User.sendValidationEmail = async function (socket, uids) {
if (!Array.isArray(uids)) { if (!Array.isArray(uids)) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
} }
if (!meta.config.requireEmailConfirmation) { if (!meta.config.requireEmailConfirmation) {
return callback(new Error('[[error:email-confirmations-are-disabled]]')); throw new Error('[[error:email-confirmations-are-disabled]]');
} }
async.eachLimit(uids, 50, function (uid, next) { await async.eachLimit(uids, 50, async function (uid) {
user.email.sendValidationEmail(uid, next); await user.email.sendValidationEmail(uid);
}, callback); });
}; };
User.sendPasswordResetEmail = function (socket, uids, callback) { User.sendPasswordResetEmail = async function (socket, uids) {
if (!Array.isArray(uids)) { if (!Array.isArray(uids)) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
} }
uids = uids.filter(uid => parseInt(uid, 10)); uids = uids.filter(uid => parseInt(uid, 10));
async.each(uids, function (uid, next) { await Promise.all(uids.map(async function (uid) {
async.waterfall([ const userData = await user.getUserFields(uid, ['email', 'username']);
function (next) { if (!userData.email) {
user.getUserFields(uid, ['email', 'username'], next); throw new Error('[[error:user-doesnt-have-email, ' + userData.username + ']]');
}, }
function (userData, next) { await user.reset.send(userData.email);
if (!userData.email) { }));
return next(new Error('[[error:user-doesnt-have-email, ' + userData.username + ']]'));
}
user.reset.send(userData.email, next);
},
], next);
}, callback);
}; };
User.forcePasswordReset = function (socket, uids, callback) { User.forcePasswordReset = async function (socket, uids) {
if (!Array.isArray(uids)) { if (!Array.isArray(uids)) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
} }
uids = uids.filter(uid => parseInt(uid, 10)); uids = uids.filter(uid => parseInt(uid, 10));
async.each(uids, function (uid, next) { await db.setObjectField(uids.map(uid => 'user:' + uid), 'passwordExpiry', Date.now());
async.waterfall([ await user.auth.revokeAllSessions(uids);
function (next) {
user.setUserField(uid, 'passwordExpiry', Date.now(), next);
},
function (next) {
user.auth.revokeAllSessions(uid, next);
},
], next);
}, callback);
}; };
User.deleteUsers = function (socket, uids, callback) { User.deleteUsers = async function (socket, uids) {
deleteUsers(socket, uids, function (uid, next) { deleteUsers(socket, uids, async function (uid) {
user.deleteAccount(uid, next); await user.deleteAccount(uid);
}, callback); });
}; };
User.deleteUsersAndContent = function (socket, uids, callback) { User.deleteUsersAndContent = async function (socket, uids) {
deleteUsers(socket, uids, function (uid, next) { deleteUsers(socket, uids, async function (uid) {
user.delete(socket.uid, uid, next); await user.delete(socket.uid, uid);
}, callback); });
}; };
function deleteUsers(socket, uids, method, callback) { async function deleteUsers(socket, uids, method) {
if (!Array.isArray(uids)) { if (!Array.isArray(uids)) {
return callback(new Error('[[error:invalid-data]]')); throw new Error('[[error:invalid-data]]');
} }
async.waterfall([ const isMembers = await groups.isMembers(uids, 'administrators');
function (next) { if (isMembers.includes(true)) {
groups.isMembers(uids, 'administrators', next); throw new Error('[[error:cant-delete-other-admins]]');
}, }
function (isMembers, next) { async function doDelete(uid) {
if (isMembers.includes(true)) { const userData = await method(uid);
return callback(new Error('[[error:cant-delete-other-admins]]')); await events.log({
} type: 'user-delete',
uid: socket.uid,
callback(); targetUid: uid,
ip: socket.ip,
username: userData.username,
email: userData.email,
});
plugins.fireHook('action:user.delete', {
callerUid: socket.uid,
uid: uid,
ip: socket.ip,
});
}
try {
await Promise.all(uids.map(uid => doDelete(uid)));
} catch (err) {
winston.error(err);
}
}
async.each(uids, function (uid, next) { User.search = async function (socket, data) {
async.waterfall([ const searchData = await user.search({
function (next) { query: data.query,
method(uid, next); searchBy: data.searchBy,
}, uid: socket.uid,
function (userData, next) {
events.log({
type: 'user-delete',
uid: socket.uid,
targetUid: uid,
ip: socket.ip,
username: userData.username,
email: userData.email,
}, next);
},
function (next) {
plugins.fireHook('action:user.delete', {
callerUid: socket.uid,
uid: uid,
ip: socket.ip,
});
next();
},
], next);
}, next);
},
], function (err) {
if (err) {
winston.error(err);
}
}); });
}
User.search = function (socket, data, callback) { if (!searchData.users.length) {
var searchData; return searchData;
async.waterfall([ }
function (next) {
user.search({
query: data.query,
searchBy: data.searchBy,
uid: socket.uid,
}, next);
},
function (_searchData, next) {
searchData = _searchData;
if (!searchData.users.length) {
return callback(null, searchData);
}
var uids = searchData.users.map(user => user && user.uid); const uids = searchData.users.map(user => user && user.uid);
const userInfo = await user.getUsersFields(uids, ['email', 'flags', 'lastonline', 'joindate']);
user.getUsersFields(uids, ['email', 'flags', 'lastonline', 'joindate'], next); searchData.users.forEach(function (user, index) {
}, if (user && userInfo[index]) {
function (userInfo, next) { user.email = userInfo[index].email;
searchData.users.forEach(function (user, index) { user.flags = userInfo[index].flags || 0;
if (user && userInfo[index]) { user.lastonlineISO = userInfo[index].lastonlineISO;
user.email = userInfo[index].email; user.joindateISO = userInfo[index].joindateISO;
user.flags = userInfo[index].flags || 0; }
user.lastonlineISO = userInfo[index].lastonlineISO; });
user.joindateISO = userInfo[index].joindateISO; return searchData;
}
});
next(null, searchData);
},
], callback);
}; };
User.restartJobs = function (socket, data, callback) { User.restartJobs = async function () {
user.startJobs(); user.startJobs();
callback();
}; };

@ -97,7 +97,7 @@ function onMessage(socket, payload) {
} }
var eventName = payload.data[0]; var eventName = payload.data[0];
var params = payload.data[1]; var params = typeof payload.data[1] === 'function' ? {} : payload.data[1];
var callback = typeof payload.data[payload.data.length - 1] === 'function' ? payload.data[payload.data.length - 1] : function () {}; var callback = typeof payload.data[payload.data.length - 1] === 'function' ? payload.data[payload.data.length - 1] : function () {};
if (!eventName) { if (!eventName) {

@ -124,9 +124,13 @@ module.exports = function (User) {
]); ]);
}; };
User.auth.revokeAllSessions = async function (uid) { User.auth.revokeAllSessions = async function (uids) {
const sids = await db.getSortedSetRange('uid:' + uid + ':sessions', 0, -1); uids = Array.isArray(uids) ? uids : [uids];
const promises = sids.map(s => User.auth.revokeSession(s, uid)); const sids = await db.getSortedSetsMembers(uids.map(uid => 'uid:' + uid + ':sessions'));
const promises = [];
uids.forEach((uid, index) => {
promises.push(sids[index].map(s => User.auth.revokeSession(s, uid)));
});
await Promise.all(promises); await Promise.all(promises);
}; };

Loading…
Cancel
Save