refactor: async/await socket.io

This commit is contained in:
Barış Soner Uşaklı
2019-09-15 02:14:51 -04:00
parent 9d41955bca
commit a7d2b8a1fe
17 changed files with 916 additions and 1446 deletions

View File

@@ -1,149 +1,101 @@
'use strict';
var async = require('async');
var winston = require('winston');
const winston = require('winston');
var db = require('../../database');
var user = require('../../user');
var meta = require('../../meta');
var websockets = require('../index');
var events = require('../../events');
var privileges = require('../../privileges');
var plugins = require('../../plugins');
var emailer = require('../../emailer');
var translator = require('../../translator');
var utils = require('../../../public/src/utils');
const db = require('../../database');
const user = require('../../user');
const meta = require('../../meta');
const websockets = require('../index');
const events = require('../../events');
const privileges = require('../../privileges');
const plugins = require('../../plugins');
const emailer = require('../../emailer');
const translator = require('../../translator');
const utils = require('../../../public/src/utils');
module.exports = function (SocketUser) {
SocketUser.banUsers = function (socket, data, callback) {
SocketUser.banUsers = async function (socket, data) {
if (!data || !Array.isArray(data.uids)) {
return callback(new Error('[[error:invalid-data]]'));
throw new Error('[[error:invalid-data]]');
}
toggleBan(socket.uid, data.uids, function (uid, next) {
async.waterfall([
function (next) {
banUser(socket.uid, uid, data.until || 0, data.reason || '', next);
},
function (next) {
events.log({
type: 'user-ban',
uid: socket.uid,
targetUid: uid,
ip: socket.ip,
reason: data.reason || undefined,
}, next);
},
function (next) {
plugins.fireHook('action:user.banned', {
callerUid: socket.uid,
ip: socket.ip,
uid: uid,
until: data.until > 0 ? data.until : undefined,
reason: data.reason || undefined,
});
next();
},
function (next) {
user.auth.revokeAllSessions(uid, next);
},
], next);
}, callback);
await toggleBan(socket.uid, data.uids, async function (uid) {
await banUser(socket.uid, uid, data.until || 0, data.reason || '');
await events.log({
type: 'user-ban',
uid: socket.uid,
targetUid: uid,
ip: socket.ip,
reason: data.reason || undefined,
});
plugins.fireHook('action:user.banned', {
callerUid: socket.uid,
ip: socket.ip,
uid: uid,
until: data.until > 0 ? data.until : undefined,
reason: data.reason || undefined,
});
await user.auth.revokeAllSessions(uid);
});
};
SocketUser.unbanUsers = function (socket, uids, callback) {
toggleBan(socket.uid, uids, function (uid, next) {
async.waterfall([
function (next) {
user.bans.unban(uid, next);
},
function (next) {
events.log({
type: 'user-unban',
uid: socket.uid,
targetUid: uid,
ip: socket.ip,
}, next);
},
function (next) {
plugins.fireHook('action:user.unbanned', {
callerUid: socket.uid,
ip: socket.ip,
uid: uid,
});
next();
},
], next);
}, callback);
SocketUser.unbanUsers = async function (socket, uids) {
await toggleBan(socket.uid, uids, async function (uid) {
await user.bans.unban(uid);
await events.log({
type: 'user-unban',
uid: socket.uid,
targetUid: uid,
ip: socket.ip,
});
plugins.fireHook('action:user.unbanned', {
callerUid: socket.uid,
ip: socket.ip,
uid: uid,
});
});
};
function toggleBan(uid, uids, method, callback) {
async function toggleBan(uid, uids, method) {
if (!Array.isArray(uids)) {
return callback(new Error('[[error:invalid-data]]'));
throw new Error('[[error:invalid-data]]');
}
const hasBanPrivilege = await privileges.users.hasBanPrivilege(uid);
if (!hasBanPrivilege) {
throw new Error('[[error:no-privileges]]');
}
async.waterfall([
function (next) {
privileges.users.hasBanPrivilege(uid, next);
},
function (hasBanPrivilege, next) {
if (!hasBanPrivilege) {
return next(new Error('[[error:no-privileges]]'));
}
async.each(uids, method, next);
},
], callback);
await Promise.all(uids.map(uid => method(uid)));
}
function banUser(callerUid, uid, until, reason, callback) {
async.waterfall([
function (next) {
user.isAdministrator(uid, next);
},
function (isAdmin, next) {
if (isAdmin) {
return next(new Error('[[error:cant-ban-other-admins]]'));
}
async function banUser(callerUid, uid, until, reason) {
const isAdmin = await user.isAdministrator(uid);
if (isAdmin) {
throw new Error('[[error:cant-ban-other-admins]]');
}
const username = await user.getUserField(uid, 'username');
const siteTitle = meta.config.title || 'NodeBB';
const data = {
subject: '[[email:banned.subject, ' + siteTitle + ']]',
username: username,
until: until ? utils.toISOString(until) : false,
reason: reason,
};
try {
await emailer.send('banned', uid, data);
} catch (err) {
winston.error('[emailer.send] ' + err.message);
}
const banData = await user.bans.ban(uid, until, reason);
await db.setObjectField('uid:' + uid + ':ban:' + banData.timestamp, 'fromUid', callerUid);
user.getUserField(uid, 'username', next);
},
function (username, next) {
var siteTitle = meta.config.title || 'NodeBB';
var data = {
subject: '[[email:banned.subject, ' + siteTitle + ']]',
username: username,
until: until ? utils.toISOString(until) : false,
reason: reason,
};
if (!reason) {
reason = await translator.translate('[[user:info.banned-no-reason]]');
}
emailer.send('banned', uid, data, function (err) {
if (err) {
winston.error('[emailer.send] ' + err.message);
}
next();
});
},
function (next) {
user.bans.ban(uid, until, reason, next);
},
function (banData, next) {
db.setObjectField('uid:' + uid + ':ban:' + banData.timestamp, 'fromUid', callerUid, next);
},
function (next) {
if (reason) {
return next(null, reason);
}
translator.translate('[[user:info.banned-no-reason]]', function (translated) {
next(null, translated);
});
},
function (_reason, next) {
websockets.in('uid_' + uid).emit('event:banned', {
until: until,
reason: _reason,
});
next();
},
], callback);
websockets.in('uid_' + uid).emit('event:banned', {
until: until,
reason: reason,
});
}
};

View File

@@ -1,110 +1,82 @@
'use strict';
var async = require('async');
var path = require('path');
var nconf = require('nconf');
const path = require('path');
const nconf = require('nconf');
var user = require('../../user');
var plugins = require('../../plugins');
var file = require('../../file');
const user = require('../../user');
const plugins = require('../../plugins');
const file = require('../../file');
module.exports = function (SocketUser) {
SocketUser.changePicture = function (socket, data, callback) {
SocketUser.changePicture = async function (socket, data) {
if (!socket.uid) {
return callback(new Error('[[error:invalid-uid]]'));
throw new Error('[[error:invalid-uid]]');
}
if (!data) {
return callback(new Error('[[error:invalid-data]]'));
throw new Error('[[error:invalid-data]]');
}
var type = data.type;
const type = data.type;
let picture = '';
await user.isAdminOrGlobalModOrSelf(socket.uid, data.uid);
if (type === 'default') {
picture = '';
} else if (type === 'uploaded') {
picture = await user.getUserField(data.uid, 'uploadedpicture');
} else {
const returnData = await plugins.fireHook('filter:user.getPicture', {
uid: socket.uid,
type: type,
picture: undefined,
});
picture = returnData && returnData.picture;
}
async.waterfall([
function (next) {
user.isAdminOrGlobalModOrSelf(socket.uid, data.uid, next);
},
function (next) {
switch (type) {
case 'default':
next(null, '');
break;
case 'uploaded':
user.getUserField(data.uid, 'uploadedpicture', next);
break;
default:
plugins.fireHook('filter:user.getPicture', {
uid: socket.uid,
type: type,
picture: undefined,
}, function (err, returnData) {
next(err, returnData && returnData.picture);
});
break;
}
},
function (picture, next) {
user.setUserField(data.uid, 'picture', picture, next);
},
], callback);
await user.setUserField(data.uid, 'picture', picture);
};
SocketUser.removeUploadedPicture = function (socket, data, callback) {
SocketUser.removeUploadedPicture = async function (socket, data) {
if (!socket.uid || !data || !data.uid) {
return callback(new Error('[[error:invalid-data]]'));
throw new Error('[[error:invalid-data]]');
}
async.waterfall([
function (next) {
user.isAdminOrSelf(socket.uid, data.uid, next);
},
function (next) {
user.getUserFields(data.uid, ['uploadedpicture', 'picture'], next);
},
function (userData, next) {
if (userData.uploadedpicture && !userData.uploadedpicture.startsWith('http')) {
var pathToFile = path.join(nconf.get('base_dir'), 'public', userData.uploadedpicture);
if (pathToFile.startsWith(nconf.get('upload_path'))) {
file.delete(pathToFile);
}
}
user.setUserFields(data.uid, {
uploadedpicture: '',
picture: userData.uploadedpicture === userData.picture ? '' : userData.picture, // if current picture is uploaded picture, reset to user icon
}, next);
},
function (next) {
plugins.fireHook('action:user.removeUploadedPicture', { callerUid: socket.uid, uid: data.uid }, next);
},
], callback);
await user.isAdminOrSelf(socket.uid, data.uid);
const userData = await user.getUserFields(data.uid, ['uploadedpicture', 'picture']);
if (userData.uploadedpicture && !userData.uploadedpicture.startsWith('http')) {
const pathToFile = path.join(nconf.get('base_dir'), 'public', userData.uploadedpicture);
if (pathToFile.startsWith(nconf.get('upload_path'))) {
file.delete(pathToFile);
}
}
await user.setUserFields(data.uid, {
uploadedpicture: '',
// if current picture is uploaded picture, reset to user icon
picture: userData.uploadedpicture === userData.picture ? '' : userData.picture,
});
plugins.fireHook('action:user.removeUploadedPicture', { callerUid: socket.uid, uid: data.uid });
};
SocketUser.getProfilePictures = function (socket, data, callback) {
SocketUser.getProfilePictures = async function (socket, data) {
if (!data || !data.uid) {
return callback(new Error('[[error:invalid-data]]'));
throw new Error('[[error:invalid-data]]');
}
async.waterfall([
function (next) {
async.parallel({
list: async.apply(plugins.fireHook, 'filter:user.listPictures', {
uid: data.uid,
pictures: [],
}),
uploaded: async.apply(user.getUserField, data.uid, 'uploadedpicture'),
}, next);
},
function (data, next) {
if (data.uploaded) {
data.list.pictures.push({
type: 'uploaded',
url: data.uploaded,
text: '[[user:uploaded_picture]]',
});
}
next(null, data.list.pictures);
},
], callback);
const [list, uploaded] = await Promise.all([
plugins.fireHook('filter:user.listPictures', {
uid: data.uid,
pictures: [],
}),
user.getUserField(data.uid, 'uploadedpicture'),
]);
if (uploaded) {
list.pictures.push({
type: 'uploaded',
url: data.uploaded,
text: '[[user:uploaded_picture]]',
});
}
return list.pictures;
};
};

View File

@@ -1,229 +1,143 @@
'use strict';
var async = require('async');
var user = require('../../user');
var meta = require('../../meta');
var events = require('../../events');
var privileges = require('../../privileges');
const user = require('../../user');
const meta = require('../../meta');
const events = require('../../events');
const privileges = require('../../privileges');
module.exports = function (SocketUser) {
SocketUser.changeUsernameEmail = function (socket, data, callback) {
SocketUser.changeUsernameEmail = async function (socket, data) {
if (!data || !data.uid || !socket.uid) {
return callback(new Error('[[error:invalid-data]]'));
throw new Error('[[error:invalid-data]]');
}
async.waterfall([
function (next) {
isPrivilegedOrSelfAndPasswordMatch(socket, data, next);
},
function (next) {
SocketUser.updateProfile(socket, data, next);
},
], callback);
await isPrivilegedOrSelfAndPasswordMatch(socket, data);
return await SocketUser.updateProfile(socket, data);
};
SocketUser.updateCover = function (socket, data, callback) {
SocketUser.updateCover = async function (socket, data) {
if (!socket.uid) {
return callback(new Error('[[error:no-privileges]]'));
throw new Error('[[error:no-privileges]]');
}
async.waterfall([
function (next) {
user.isAdminOrGlobalModOrSelf(socket.uid, data.uid, next);
},
function (next) {
user.checkMinReputation(socket.uid, data.uid, 'min:rep:cover-picture', next);
},
function (next) {
user.updateCoverPicture(data, next);
},
], callback);
await user.isAdminOrGlobalModOrSelf(socket.uid, data.uid);
await user.checkMinReputation(socket.uid, data.uid, 'min:rep:cover-picture');
return await user.updateCoverPicture(data);
};
SocketUser.uploadCroppedPicture = function (socket, data, callback) {
SocketUser.uploadCroppedPicture = async function (socket, data) {
if (!socket.uid) {
return callback(new Error('[[error:no-privileges]]'));
throw new Error('[[error:no-privileges]]');
}
async.waterfall([
function (next) {
user.isAdminOrGlobalModOrSelf(socket.uid, data.uid, next);
},
function (next) {
user.checkMinReputation(socket.uid, data.uid, 'min:rep:profile-picture', next);
},
function (next) {
user.uploadCroppedPicture(data, next);
},
], callback);
await user.isAdminOrGlobalModOrSelf(socket.uid, data.uid);
await user.checkMinReputation(socket.uid, data.uid, 'min:rep:profile-picture');
return await user.uploadCroppedPicture(data);
};
SocketUser.removeCover = function (socket, data, callback) {
SocketUser.removeCover = async function (socket, data) {
if (!socket.uid) {
return callback(new Error('[[error:no-privileges]]'));
throw new Error('[[error:no-privileges]]');
}
async.waterfall([
function (next) {
user.isAdminOrGlobalModOrSelf(socket.uid, data.uid, next);
},
function (next) {
user.removeCoverPicture(data, next);
},
], callback);
await user.isAdminOrGlobalModOrSelf(socket.uid, data.uid);
await user.removeCoverPicture(data);
};
function isPrivilegedOrSelfAndPasswordMatch(socket, data, callback) {
async function isPrivilegedOrSelfAndPasswordMatch(socket, data) {
const uid = socket.uid;
const isSelf = parseInt(uid, 10) === parseInt(data.uid, 10);
async.waterfall([
function (next) {
async.parallel({
isAdmin: async.apply(user.isAdministrator, uid),
isTargetAdmin: async.apply(user.isAdministrator, data.uid),
isGlobalMod: async.apply(user.isGlobalModerator, uid),
}, next);
},
function (results, next) {
if (results.isTargetAdmin && !results.isAdmin) {
return next(new Error('[[error:no-privileges]]'));
}
const [isAdmin, isTargetAdmin, isGlobalMod] = await Promise.all([
user.isAdministrator(uid),
user.isAdministrator(data.uid),
user.isGlobalModerator(uid),
]);
if (!isSelf && !(results.isAdmin || results.isGlobalMod)) {
return next(new Error('[[error:no-privileges]]'));
}
if ((isTargetAdmin && !isAdmin) || (!isSelf && !(isAdmin || isGlobalMod))) {
throw new Error('[[error:no-privileges]]');
}
const [hasPassword, passwordMatch] = await Promise.all([
user.hasPassword(data.uid),
data.password ? user.isPasswordCorrect(data.uid, data.password, socket.ip) : false,
]);
async.parallel({
hasPassword: async.apply(user.hasPassword, data.uid),
passwordMatch: function (next) {
if (data.password) {
user.isPasswordCorrect(data.uid, data.password, socket.ip, next);
} else {
next(null, false);
}
},
}, next);
}, function (results, next) {
if (isSelf && results.hasPassword && !results.passwordMatch) {
return next(new Error('[[error:invalid-password]]'));
}
next();
},
], callback);
if (isSelf && hasPassword && !passwordMatch) {
throw new Error('[[error:invalid-password]]');
}
}
SocketUser.changePassword = function (socket, data, callback) {
SocketUser.changePassword = async function (socket, data) {
if (!socket.uid) {
return callback(new Error('[[error:invalid-uid]]'));
throw new Error('[[error:invalid-uid]]');
}
if (!data || !data.uid) {
return callback(new Error('[[error:invalid-data]]'));
throw new Error('[[error:invalid-data]]');
}
async.waterfall([
function (next) {
user.changePassword(socket.uid, Object.assign(data, { ip: socket.ip }), next);
},
function (next) {
events.log({
type: 'password-change',
uid: socket.uid,
targetUid: data.uid,
ip: socket.ip,
});
next();
},
], callback);
};
SocketUser.updateProfile = function (socket, data, callback) {
if (!socket.uid) {
return callback(new Error('[[error:invalid-uid]]'));
}
if (!data || !data.uid) {
return callback(new Error('[[error:invalid-data]]'));
}
var oldUserData;
async.waterfall([
function (next) {
user.getUserFields(data.uid, ['email', 'username'], next);
},
function (_oldUserData, next) {
oldUserData = _oldUserData;
if (!oldUserData || !oldUserData.username) {
return next(new Error('[[error:invalid-data]]'));
}
async.parallel({
isAdminOrGlobalMod: function (next) {
user.isAdminOrGlobalMod(socket.uid, next);
},
canEdit: function (next) {
privileges.users.canEdit(socket.uid, data.uid, next);
},
}, next);
},
function (results, next) {
if (!results.canEdit) {
return next(new Error('[[error:no-privileges]]'));
}
if (!results.isAdminOrGlobalMod && meta.config['username:disableEdit']) {
data.username = oldUserData.username;
}
if (!results.isAdminOrGlobalMod && meta.config['email:disableEdit']) {
data.email = oldUserData.email;
}
user.updateProfile(socket.uid, data, next);
},
function (userData, next) {
function log(type, eventData) {
eventData.type = type;
eventData.uid = socket.uid;
eventData.targetUid = data.uid;
eventData.ip = socket.ip;
events.log(eventData);
}
if (userData.email !== oldUserData.email) {
log('email-change', { oldEmail: oldUserData.email, newEmail: userData.email });
}
if (userData.username !== oldUserData.username) {
log('username-change', { oldUsername: oldUserData.username, newUsername: userData.username });
}
next(null, userData);
},
], callback);
};
SocketUser.toggleBlock = function (socket, data, callback) {
let isBlocked;
async.waterfall([
function (next) {
async.parallel({
can: function (next) {
user.blocks.can(socket.uid, data.blockerUid, data.blockeeUid, next);
},
is: function (next) {
user.blocks.is(data.blockeeUid, data.blockerUid, next);
},
}, next);
},
function (results, next) {
isBlocked = results.is;
user.blocks[isBlocked ? 'remove' : 'add'](data.blockeeUid, data.blockerUid, next);
},
], function (err) {
callback(err, !isBlocked);
await user.changePassword(socket.uid, Object.assign(data, { ip: socket.ip }));
await events.log({
type: 'password-change',
uid: socket.uid,
targetUid: data.uid,
ip: socket.ip,
});
};
SocketUser.updateProfile = async function (socket, data) {
if (!socket.uid) {
throw new Error('[[error:invalid-uid]]');
}
if (!data || !data.uid) {
throw new Error('[[error:invalid-data]]');
}
const oldUserData = await user.getUserFields(data.uid, ['email', 'username']);
if (!oldUserData || !oldUserData.username) {
throw new Error('[[error:invalid-data]]');
}
const [isAdminOrGlobalMod, canEdit] = await Promise.all([
user.isAdminOrGlobalMod(socket.uid),
privileges.users.canEdit(socket.uid, data.uid),
]);
if (!canEdit) {
throw new Error('[[error:no-privileges]]');
}
if (!isAdminOrGlobalMod && meta.config['username:disableEdit']) {
data.username = oldUserData.username;
}
if (!isAdminOrGlobalMod && meta.config['email:disableEdit']) {
data.email = oldUserData.email;
}
const userData = await user.updateProfile(socket.uid, data);
async function log(type, eventData) {
eventData.type = type;
eventData.uid = socket.uid;
eventData.targetUid = data.uid;
eventData.ip = socket.ip;
await events.log(eventData);
}
if (userData.email !== oldUserData.email) {
await log('email-change', { oldEmail: oldUserData.email, newEmail: userData.email });
}
if (userData.username !== oldUserData.username) {
await log('username-change', { oldUsername: oldUserData.username, newUsername: userData.username });
}
return userData;
};
SocketUser.toggleBlock = async function (socket, data) {
const [is] = await Promise.all([
user.blocks.is(data.blockeeUid, data.blockerUid),
user.blocks.can(socket.uid, data.blockerUid, data.blockeeUid),
]);
const isBlocked = is;
await user.blocks[isBlocked ? 'remove' : 'add'](data.blockeeUid, data.blockerUid);
return !isBlocked;
};
};

View File

@@ -1,70 +1,43 @@
'use strict';
var async = require('async');
var user = require('../../user');
var events = require('../../events');
const user = require('../../user');
const events = require('../../events');
module.exports = function (SocketUser) {
SocketUser.acceptRegistration = function (socket, data, callback) {
async.waterfall([
function (next) {
user.isAdminOrGlobalMod(socket.uid, next);
},
function (isAdminOrGlobalMod, next) {
if (!isAdminOrGlobalMod) {
return next(new Error('[[error:no-privileges]]'));
}
user.acceptRegistration(data.username, next);
},
function (uid, next) {
events.log({
type: 'registration-approved',
uid: socket.uid,
ip: socket.ip,
targetUid: uid,
});
next(null, uid);
},
], callback);
SocketUser.acceptRegistration = async function (socket, data) {
const isAdminOrGlobalMod = await user.isAdminOrGlobalMod(socket.uid);
if (!isAdminOrGlobalMod) {
throw new Error('[[error:no-privileges]]');
}
const uid = await user.acceptRegistration(data.username);
await events.log({
type: 'registration-approved',
uid: socket.uid,
ip: socket.ip,
targetUid: uid,
});
return uid;
};
SocketUser.rejectRegistration = function (socket, data, callback) {
async.waterfall([
function (next) {
user.isAdminOrGlobalMod(socket.uid, next);
},
function (isAdminOrGlobalMod, next) {
if (!isAdminOrGlobalMod) {
return next(new Error('[[error:no-privileges]]'));
}
user.rejectRegistration(data.username, next);
},
function (next) {
events.log({
type: 'registration-rejected',
uid: socket.uid,
ip: socket.ip,
username: data.username,
});
next();
},
], callback);
SocketUser.rejectRegistration = async function (socket, data) {
const isAdminOrGlobalMod = await user.isAdminOrGlobalMod(socket.uid);
if (!isAdminOrGlobalMod) {
throw new Error('[[error:no-privileges]]');
}
await user.rejectRegistration(data.username);
await events.log({
type: 'registration-rejected',
uid: socket.uid,
ip: socket.ip,
username: data.username,
});
};
SocketUser.deleteInvitation = function (socket, data, callback) {
async.waterfall([
function (next) {
user.isAdminOrGlobalMod(socket.uid, next);
},
function (isAdminOrGlobalMod, next) {
if (!isAdminOrGlobalMod) {
return next(new Error('[[error:no-privileges]]'));
}
user.deleteInvitation(data.invitedBy, data.email, next);
},
], callback);
SocketUser.deleteInvitation = async function (socket, data) {
const isAdminOrGlobalMod = await user.isAdminOrGlobalMod(socket.uid);
if (!isAdminOrGlobalMod) {
throw new Error('[[error:no-privileges]]');
}
await user.deleteInvitation(data.invitedBy, data.email);
};
};

View File

@@ -1,42 +1,31 @@
'use strict';
var async = require('async');
var user = require('../../user');
var pagination = require('../../pagination');
var privileges = require('../../privileges');
const user = require('../../user');
const pagination = require('../../pagination');
const privileges = require('../../privileges');
module.exports = function (SocketUser) {
SocketUser.search = function (socket, data, callback) {
SocketUser.search = async function (socket, data) {
if (!data) {
return callback(new Error('[[error:invalid-data]]'));
throw new Error('[[error:invalid-data]]');
}
async.waterfall([
function (next) {
privileges.global.can('search:users', socket.uid, next);
},
function (allowed, next) {
if (!allowed) {
return next(new Error('[[error:no-privileges]]'));
}
user.search({
query: data.query,
page: data.page,
searchBy: data.searchBy,
sortBy: data.sortBy,
onlineOnly: data.onlineOnly,
bannedOnly: data.bannedOnly,
flaggedOnly: data.flaggedOnly,
paginate: data.paginate,
uid: socket.uid,
}, next);
},
function (result, next) {
result.pagination = pagination.create(data.page, result.pageCount);
result['route_users:' + data.sortBy] = true;
next(null, result);
},
], callback);
const allowed = await privileges.global.can('search:users', socket.uid);
if (!allowed) {
throw new Error('[[error:no-privileges]]');
}
const result = await user.search({
query: data.query,
page: data.page,
searchBy: data.searchBy,
sortBy: data.sortBy,
onlineOnly: data.onlineOnly,
bannedOnly: data.bannedOnly,
flaggedOnly: data.flaggedOnly,
paginate: data.paginate,
uid: socket.uid,
});
result.pagination = pagination.create(data.page, result.pageCount);
result['route_users:' + data.sortBy] = true;
return result;
};
};

View File

@@ -1,59 +1,40 @@
'use strict';
var async = require('async');
var user = require('../../user');
var websockets = require('../index');
const user = require('../../user');
const websockets = require('../index');
module.exports = function (SocketUser) {
SocketUser.checkStatus = function (socket, uid, callback) {
SocketUser.checkStatus = async function (socket, uid) {
if (!socket.uid) {
return callback(new Error('[[error:invalid-uid]]'));
throw new Error('[[error:invalid-uid]]');
}
async.waterfall([
function (next) {
user.getUserFields(uid, ['lastonline', 'status'], next);
},
function (userData, next) {
next(null, user.getStatus(userData));
},
], callback);
const userData = await user.getUserFields(uid, ['lastonline', 'status']);
return user.getStatus(userData);
};
SocketUser.setStatus = function (socket, status, callback) {
SocketUser.setStatus = async function (socket, status) {
if (socket.uid <= 0) {
return callback(new Error('[[error:invalid-uid]]'));
throw new Error('[[error:invalid-uid]]');
}
var allowedStatus = ['online', 'offline', 'dnd', 'away'];
const allowedStatus = ['online', 'offline', 'dnd', 'away'];
if (!allowedStatus.includes(status)) {
return callback(new Error('[[error:invalid-user-status]]'));
throw new Error('[[error:invalid-user-status]]');
}
var data = { status: status };
const userData = { status: status };
if (status !== 'offline') {
data.lastonline = Date.now();
userData.lastonline = Date.now();
}
async.waterfall([
function (next) {
user.setUserFields(socket.uid, data, next);
},
function (next) {
if (status !== 'offline') {
user.updateOnlineUsers(socket.uid, next);
} else {
next();
}
},
function (next) {
var data = {
uid: socket.uid,
status: status,
};
websockets.server.emit('event:user_status_change', data);
next(null, data);
},
], callback);
await user.setUserFields(socket.uid, userData);
if (status !== 'offline') {
await user.updateOnlineUsers(socket.uid);
}
const eventData = {
uid: socket.uid,
status: status,
};
websockets.server.emit('event:user_status_change', eventData);
return eventData;
};
};