2014-03-12 20:53:42 -04:00
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
2020-11-27 15:38:22 -05:00
|
|
|
const fs = require('fs');
|
|
|
|
|
const path = require('path');
|
2019-10-03 23:31:42 -04:00
|
|
|
const winston = require('winston');
|
|
|
|
|
const validator = require('validator');
|
2024-03-11 11:29:05 -04:00
|
|
|
const json2csvAsync = require('json2csv').parseAsync;
|
2017-11-30 14:24:13 -05:00
|
|
|
|
2020-11-27 15:38:22 -05:00
|
|
|
const { baseDir } = require('../constants').paths;
|
2019-10-03 23:31:42 -04:00
|
|
|
const db = require('../database');
|
|
|
|
|
const plugins = require('../plugins');
|
2020-03-05 11:03:49 -05:00
|
|
|
const batch = require('../batch');
|
2014-03-12 20:53:42 -04:00
|
|
|
|
2016-10-13 11:43:39 +02:00
|
|
|
module.exports = function (User) {
|
2019-07-09 22:23:10 -04:00
|
|
|
User.logIP = async function (uid, ip) {
|
2018-12-14 00:09:15 -05:00
|
|
|
if (!(parseInt(uid, 10) > 0)) {
|
2019-07-09 22:23:10 -04:00
|
|
|
return;
|
2018-12-14 00:09:15 -05:00
|
|
|
}
|
2019-10-03 23:31:42 -04:00
|
|
|
const now = Date.now();
|
2019-06-24 21:36:20 -04:00
|
|
|
const bulk = [
|
2021-02-03 23:59:08 -07:00
|
|
|
[`uid:${uid}:ip`, now, ip || 'Unknown'],
|
2019-06-24 21:36:20 -04:00
|
|
|
];
|
|
|
|
|
if (ip) {
|
2021-02-03 23:59:08 -07:00
|
|
|
bulk.push([`ip:${ip}:uid`, now, uid]);
|
2019-06-24 21:36:20 -04:00
|
|
|
}
|
2019-07-09 22:23:10 -04:00
|
|
|
await db.sortedSetAddBulk(bulk);
|
2014-03-12 20:53:42 -04:00
|
|
|
};
|
|
|
|
|
|
2019-07-09 22:23:10 -04:00
|
|
|
User.getIPs = async function (uid, stop) {
|
2021-02-03 23:59:08 -07:00
|
|
|
const ips = await db.getSortedSetRevRange(`uid:${uid}:ip`, 0, stop);
|
2019-07-09 22:23:10 -04:00
|
|
|
return ips.map(ip => validator.escape(String(ip)));
|
2014-03-12 20:53:42 -04:00
|
|
|
};
|
|
|
|
|
|
2019-07-09 22:23:10 -04:00
|
|
|
User.getUsersCSV = async function () {
|
2016-11-23 17:15:31 +03:00
|
|
|
winston.verbose('[user/getUsersCSV] Compiling User CSV data');
|
2020-03-05 11:03:49 -05:00
|
|
|
|
2020-11-20 16:06:26 -05:00
|
|
|
const data = await plugins.hooks.fire('filter:user.csvFields', { fields: ['uid', 'email', 'username'] });
|
2021-02-03 23:59:08 -07:00
|
|
|
let csvContent = `${data.fields.join(',')}\n`;
|
2020-03-05 11:03:49 -05:00
|
|
|
await batch.processSortedSet('users:joindate', async (uids) => {
|
|
|
|
|
const usersData = await User.getUsersFields(uids, data.fields);
|
|
|
|
|
csvContent += usersData.reduce((memo, user) => {
|
2021-02-03 23:59:08 -07:00
|
|
|
memo += `${data.fields.map(field => user[field]).join(',')}\n`;
|
2020-03-05 11:03:49 -05:00
|
|
|
return memo;
|
|
|
|
|
}, '');
|
|
|
|
|
}, {});
|
|
|
|
|
|
2019-07-09 22:23:10 -04:00
|
|
|
return csvContent;
|
2014-03-12 20:53:42 -04:00
|
|
|
};
|
2020-11-27 15:38:22 -05:00
|
|
|
|
2024-03-11 11:29:05 -04:00
|
|
|
User.exportUsersCSV = async function (fieldsToExport = ['email', 'username', 'uid', 'ip']) {
|
2020-11-27 15:38:22 -05:00
|
|
|
winston.verbose('[user/exportUsersCSV] Exporting User CSV data');
|
|
|
|
|
|
2022-07-13 10:58:43 -04:00
|
|
|
const { fields, showIps } = await plugins.hooks.fire('filter:user.csvFields', {
|
2024-03-11 11:29:05 -04:00
|
|
|
fields: fieldsToExport,
|
|
|
|
|
showIps: fieldsToExport.includes('ip'),
|
2022-07-13 10:58:43 -04:00
|
|
|
});
|
2024-03-11 11:29:05 -04:00
|
|
|
|
|
|
|
|
if (!showIps && fields.includes('ip')) {
|
|
|
|
|
fields.splice(fields.indexOf('ip'), 1);
|
|
|
|
|
}
|
2020-11-27 15:38:22 -05:00
|
|
|
const fd = await fs.promises.open(
|
|
|
|
|
path.join(baseDir, 'build/export', 'users.csv'),
|
|
|
|
|
'w'
|
|
|
|
|
);
|
2024-03-11 11:29:05 -04:00
|
|
|
fs.promises.appendFile(fd, `${fields.map(f => `"${f}"`).join(',')}\n`);
|
|
|
|
|
await batch.processSortedSet('group:administrators:members', async (uids) => {
|
|
|
|
|
const userFieldsToLoad = fields.filter(field => field !== 'ip' && field !== 'password');
|
|
|
|
|
const usersData = await User.getUsersFields(uids, userFieldsToLoad);
|
|
|
|
|
let userIps = [];
|
2022-07-13 10:58:43 -04:00
|
|
|
if (showIps) {
|
2024-03-11 11:29:05 -04:00
|
|
|
userIps = await db.getSortedSetsMembers(uids.map(uid => `uid:${uid}:ip`));
|
2022-07-13 10:58:43 -04:00
|
|
|
}
|
|
|
|
|
|
2021-06-08 11:50:52 -04:00
|
|
|
usersData.forEach((user, index) => {
|
2024-03-11 11:29:05 -04:00
|
|
|
if (Array.isArray(userIps[index])) {
|
|
|
|
|
user.ip = userIps[index].join(',');
|
2022-07-13 10:58:43 -04:00
|
|
|
}
|
2020-11-27 15:38:22 -05:00
|
|
|
});
|
|
|
|
|
|
2024-03-11 11:29:05 -04:00
|
|
|
const opts = { fields, header: false };
|
|
|
|
|
const csv = await json2csvAsync(usersData, opts);
|
|
|
|
|
await fs.promises.appendFile(fd, csv);
|
2020-11-27 15:38:22 -05:00
|
|
|
}, {
|
|
|
|
|
batch: 5000,
|
|
|
|
|
interval: 250,
|
|
|
|
|
});
|
|
|
|
|
await fd.close();
|
|
|
|
|
};
|
2014-03-14 19:07:50 -04:00
|
|
|
};
|