Files
NodeBB/src/socket.io/admin/user.js

174 lines
4.5 KiB
JavaScript
Raw Normal View History

2017-02-18 01:56:23 -07:00
'use strict';
2014-04-15 02:25:42 -04:00
2019-09-07 18:22:03 -04:00
const async = require('async');
2020-11-27 15:38:22 -05:00
const winston = require('winston');
2016-09-27 13:31:50 +03:00
2019-09-07 18:22:03 -04:00
const db = require('../../database');
const groups = require('../../groups');
const user = require('../../user');
const events = require('../../events');
const translator = require('../../translator');
const sockets = require('..');
2014-04-15 02:25:42 -04:00
2019-09-07 18:22:03 -04:00
const User = module.exports;
2014-04-15 02:25:42 -04:00
2019-09-07 18:22:03 -04:00
User.makeAdmins = async function (socket, uids) {
if (!Array.isArray(uids)) {
2019-09-07 18:22:03 -04:00
throw new Error('[[error:invalid-data]]');
}
2020-12-14 09:20:41 +03:00
const isMembersOfBanned = await groups.isMembers(uids, groups.BANNED_USERS);
if (isMembersOfBanned.includes(true)) {
throw new Error('[[error:cant-make-banned-users-admin]]');
}
2019-09-07 18:22:03 -04:00
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,
});
}
2014-04-15 02:25:42 -04:00
};
2019-09-07 18:22:03 -04:00
User.removeAdmins = async function (socket, uids) {
if (!Array.isArray(uids)) {
2019-09-07 18:22:03 -04:00
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,
});
}
};
2019-09-07 18:22:03 -04:00
User.resetLockouts = async function (socket, uids) {
2014-08-14 08:34:38 -04:00
if (!Array.isArray(uids)) {
2019-09-07 18:22:03 -04:00
throw new Error('[[error:invalid-data]]');
2014-08-14 08:34:38 -04:00
}
2019-09-07 18:22:03 -04:00
await Promise.all(uids.map(uid => user.auth.resetLockout(uid)));
2014-08-14 08:34:38 -04:00
};
2019-09-07 18:22:03 -04:00
User.validateEmail = async function (socket, uids) {
2014-10-06 13:11:12 -04:00
if (!Array.isArray(uids)) {
2019-09-07 18:22:03 -04:00
throw new Error('[[error:invalid-data]]');
2014-10-06 13:11:12 -04:00
}
for (const uid of uids) {
const email = await user.email.getEmailForValidation(uid);
if (email) {
await user.setUserField(uid, 'email', email);
}
await user.email.confirmByUid(uid);
}
2014-11-03 15:31:41 -05:00
};
2019-09-07 18:22:03 -04:00
User.sendValidationEmail = async function (socket, uids) {
2015-02-11 14:44:56 -05:00
if (!Array.isArray(uids)) {
2019-09-07 18:22:03 -04:00
throw new Error('[[error:invalid-data]]');
2015-02-11 14:44:56 -05:00
}
2015-04-13 17:29:43 -04:00
const failed = [];
let errorLogged = false;
2021-02-04 00:01:39 -07:00
await async.eachLimit(uids, 50, async (uid) => {
const email = await user.email.getEmailForValidation(uid);
await user.email.sendValidationEmail(uid, {
force: true,
email: email,
}).catch((err) => {
if (!errorLogged) {
winston.error(`[user.create] Validation email failed to send\n[emailer.send] ${err.stack}`);
errorLogged = true;
}
failed.push(uid);
});
2019-09-07 18:22:03 -04:00
});
if (failed.length) {
throw Error(`Email sending failed for the following uids, check server logs for more info: ${failed.join(',')}`);
}
2015-02-11 14:44:56 -05:00
};
2019-09-07 18:22:03 -04:00
User.sendPasswordResetEmail = async function (socket, uids) {
2014-11-03 15:31:41 -05:00
if (!Array.isArray(uids)) {
2019-09-07 18:22:03 -04:00
throw new Error('[[error:invalid-data]]');
2014-11-03 15:31:41 -05:00
}
2018-11-05 08:20:43 -05:00
uids = uids.filter(uid => parseInt(uid, 10));
2014-11-03 15:31:41 -05:00
2021-02-04 00:01:39 -07:00
await Promise.all(uids.map(async (uid) => {
2019-09-07 18:22:03 -04:00
const userData = await user.getUserFields(uid, ['email', 'username']);
if (!userData.email) {
2021-02-03 23:59:08 -07:00
throw new Error(`[[error:user-doesnt-have-email, ${userData.username}]]`);
2019-09-07 18:22:03 -04:00
}
await user.reset.send(userData.email);
}));
2014-10-06 13:11:12 -04:00
};
2019-09-07 18:22:03 -04:00
User.forcePasswordReset = async function (socket, uids) {
if (!Array.isArray(uids)) {
2019-09-07 18:22:03 -04:00
throw new Error('[[error:invalid-data]]');
}
uids = uids.filter(uid => parseInt(uid, 10));
2021-02-03 23:59:08 -07:00
await db.setObjectField(uids.map(uid => `user:${uid}`), 'passwordExpiry', Date.now());
2019-09-07 18:22:03 -04:00
await user.auth.revokeAllSessions(uids);
2021-02-03 23:59:08 -07:00
uids.forEach(uid => sockets.in(`uid_${uid}`).emit('event:logout'));
};
2019-09-07 18:22:03 -04:00
User.restartJobs = async function () {
user.startJobs();
2016-08-26 10:04:38 -04:00
};
User.loadGroups = async function (socket, uids) {
const [userData, groupData] = await Promise.all([
user.getUsersData(uids),
groups.getUserGroupsFromSet('groups:createtime', uids),
]);
userData.forEach((data, index) => {
data.groups = groupData[index].filter(group => !groups.isPrivilegeGroup(group.name));
data.groups.forEach((group) => {
group.nameEscaped = translator.escape(group.displayName);
});
});
return { users: userData };
};
2020-11-27 15:38:22 -05:00
User.exportUsersCSV = async function (socket) {
await events.log({
type: 'exportUsersCSV',
uid: socket.uid,
ip: socket.ip,
});
2021-02-04 00:01:39 -07:00
setTimeout(async () => {
2020-11-27 15:38:22 -05:00
try {
await user.exportUsersCSV();
if (socket.emit) {
socket.emit('event:export-users-csv');
}
2020-11-27 15:38:22 -05:00
const notifications = require('../../notifications');
const n = await notifications.create({
bodyShort: '[[notifications:users-csv-exported]]',
path: '/api/admin/users/csv',
nid: 'users:csv:export',
from: socket.uid,
});
await notifications.push(n, [socket.uid]);
} catch (err) {
winston.error(err.stack);
2020-11-27 15:38:22 -05:00
}
}, 0);
};