wildduck/lib/tasks/user-delete.js

232 lines
7.4 KiB
JavaScript
Raw Normal View History

2018-10-11 16:48:12 +08:00
'use strict';
const log = require('npmlog');
const db = require('../db');
const consts = require('../consts');
2021-01-08 16:31:43 +08:00
const { publish, USER_DELETE_COMPLETED } = require('../events');
2021-01-08 16:31:43 +08:00
const BATCH_SIZE = 500;
2021-06-20 18:40:04 +08:00
const deleteMessages = async (task, data) => {
2021-01-15 16:40:03 +08:00
let cursor = await db.database.collection('messages').find(
{
2021-06-20 18:40:04 +08:00
user: data.user
2021-01-15 16:40:03 +08:00
},
{
projection: {
_id: true
}
}
);
2021-01-08 16:31:43 +08:00
let rdate = new Date(Date.now() + consts.DELETED_USER_MESSAGE_RETENTION).getTime();
2021-01-15 16:40:03 +08:00
let messageData;
let updateEntries = [];
2021-01-08 16:31:43 +08:00
let markedAsDeleted = 0;
2018-10-11 16:48:12 +08:00
2021-01-15 16:40:03 +08:00
let executeBatchUpdate = async () => {
let bulkResult = await db.database.collection('messages').bulkWrite(updateEntries, {
ordered: false,
2021-02-26 20:00:13 +08:00
writeConcern: 1
2021-01-15 16:40:03 +08:00
});
2021-06-20 18:40:04 +08:00
log.verbose('Tasks', 'task=user-delete id=%s user=%s message=%s', task._id, data.user, `Marked ${updateEntries.length} messages for deletion`);
2021-01-15 16:40:03 +08:00
updateEntries = [];
2021-01-08 16:31:43 +08:00
2021-01-15 16:40:03 +08:00
markedAsDeleted += (bulkResult && bulkResult.modifiedCount) || 0;
};
2021-01-08 16:31:43 +08:00
2021-01-15 16:40:03 +08:00
try {
while ((messageData = await cursor.next())) {
updateEntries.push({
updateOne: {
filter: {
_id: messageData._id
},
2021-01-15 16:40:03 +08:00
update: {
$set: {
exp: true,
rdate,
userDeleted: true
}
}
2021-01-15 16:40:03 +08:00
}
});
2018-10-11 16:48:12 +08:00
2021-01-15 16:40:03 +08:00
if (updateEntries.length >= BATCH_SIZE) {
try {
await executeBatchUpdate();
} catch (err) {
await cursor.close();
throw err;
}
}
}
await cursor.close();
if (updateEntries.length) {
await executeBatchUpdate();
}
} catch (err) {
2021-01-08 16:31:43 +08:00
err.markedAsDeleted = markedAsDeleted;
throw err;
2021-01-08 16:31:43 +08:00
} finally {
2021-06-21 15:49:31 +08:00
log.verbose('Tasks', 'task=user-delete id=%s user=%s message=%s', task._id, data.user, `Marked total of ${markedAsDeleted} messages for deletion`);
}
2021-01-15 16:40:03 +08:00
2021-01-08 16:31:43 +08:00
return markedAsDeleted;
};
2021-06-21 15:49:31 +08:00
const deleteRegistryAddresses = async (task, data) => {
2021-01-08 16:31:43 +08:00
let lastId;
let deleted = 0;
try {
let done = false;
while (!done) {
let query = {
2021-06-20 18:40:04 +08:00
user: data.user
2021-01-08 16:31:43 +08:00
};
if (lastId) {
query._id = { $gt: lastId };
}
2018-10-11 16:48:12 +08:00
2021-01-08 16:35:01 +08:00
let addresses = await db.database
2021-01-08 16:31:43 +08:00
.collection('addressregister')
.find(query, {
sort: { _id: 1 },
projection: {
_id: true
},
limit: BATCH_SIZE
})
.toArray();
if (!addresses.length) {
// all done
done = true;
break;
}
addresses = addresses.map(addresseData => addresseData._id);
lastId = addresses[addresses.length - 1];
let updateEntries = [];
addresses.forEach(message => {
updateEntries.push({
deleteOne: {
filter: {
_id: message
}
}
});
});
2021-01-08 16:35:01 +08:00
let bulkResult = await db.database.collection('addressregister').bulkWrite(updateEntries, {
2021-01-08 16:31:43 +08:00
ordered: false,
2021-02-26 20:00:13 +08:00
writeConcern: 1
2021-01-08 16:31:43 +08:00
});
deleted += (bulkResult && bulkResult.deletedCount) || 0;
}
} catch (err) {
err.deleted = deleted;
throw err;
} finally {
2021-06-20 18:40:04 +08:00
log.verbose('Tasks', 'task=user-delete id=%s user=%s message=%s', task._id, data.user, `Deleted ${deleted} addresses from registry`);
}
2021-01-08 16:31:43 +08:00
return deleted;
};
2021-06-20 18:40:04 +08:00
const run = async (task, data) => {
2021-01-08 16:31:43 +08:00
let result = {};
2018-10-11 16:48:12 +08:00
try {
2021-06-20 18:40:04 +08:00
let delRes = await db.database.collection('mailboxes').deleteMany({ user: data.user });
2021-01-08 16:31:43 +08:00
result.mailboxes = { deleted: delRes.deletedCount };
} catch (err) {
2021-06-20 18:40:04 +08:00
log.error('Tasks', 'task=user-delete id=%s user=%s message=%s error=%s', task._id, data.user, 'Failed to delete mailboxes', err.message);
err.code = 'InternalDatabaseError';
2021-01-08 16:31:43 +08:00
result.mailboxes = { error: err.message };
throw err;
}
2018-10-11 16:48:12 +08:00
try {
2021-06-20 18:40:04 +08:00
let delRes = await db.users.collection('asps').deleteMany({ user: data.user });
2021-01-08 16:31:43 +08:00
result.asps = { deleted: delRes.deletedCount };
} catch (err) {
2021-06-20 18:40:04 +08:00
log.error('Tasks', 'task=user-delete id=%s user=%s message=%s error=%s', task._id, data.user, 'Failed to delete asps', err.message);
err.code = 'InternalDatabaseError';
2021-01-08 16:31:43 +08:00
result.asps = { error: err.message };
throw err;
}
try {
2021-06-20 18:40:04 +08:00
let delRes = await db.database.collection('filters').deleteMany({ user: data.user });
2021-01-08 16:31:43 +08:00
result.filters = { deleted: delRes.deletedCount };
} catch (err) {
2021-06-20 18:40:04 +08:00
log.error('Tasks', 'task=user-delete id=%s user=%s message=%s error=%s', task._id, data.user, 'Failed to delete filters', err.message);
err.code = 'InternalDatabaseError';
2021-01-08 16:31:43 +08:00
result.filters = { error: err.message };
throw err;
}
try {
2021-06-20 18:40:04 +08:00
let delRes = await db.database.collection('autoreplies').deleteMany({ user: data.user });
2021-01-08 16:31:43 +08:00
result.autoreplies = { deleted: delRes.deletedCount };
} catch (err) {
2021-06-20 18:40:04 +08:00
log.error('Tasks', 'task=user-delete id=%s user=%s message=%s error=%s', task._id, data.user, 'Failed to delete autoreplies', err.message);
err.code = 'InternalDatabaseError';
2021-01-08 16:31:43 +08:00
result.autoreplies = { error: err.message };
throw err;
}
try {
2021-06-21 15:49:31 +08:00
let deleted = await deleteRegistryAddresses(task, data);
2021-01-08 16:31:43 +08:00
result.addressregister = { deleted };
} catch (err) {
2021-06-21 15:49:31 +08:00
log.error('Tasks', 'task=user-delete id=%s user=%s message=%s error=%s', task._id, data.user, 'Failed to delete registry addresses', err.message);
err.code = 'InternalDatabaseError';
2021-01-08 16:31:43 +08:00
result.addressregister = { error: err.message, deleted: err.deleted };
throw err;
}
try {
// mark messages for deletion
2021-06-20 18:40:04 +08:00
let markedAsDeleted = await deleteMessages(task, data);
2021-01-08 16:31:43 +08:00
result.messages = { deleted: markedAsDeleted };
} catch (err) {
2021-06-20 18:40:04 +08:00
log.error('Tasks', 'task=user-delete id=%s user=%s message=%s error=%s', task._id, data.user, 'Failed to fetch messages', err.message);
2021-01-08 16:31:43 +08:00
err.code = 'InternalDatabaseError';
result.messages = { error: err.message, deleted: err.markedAsDeleted };
throw err;
}
try {
// delete recoverable user placeholder
2021-06-20 18:40:04 +08:00
await db.users.collection('deletedusers').deleteOne({ _id: data.user });
} catch (err) {
2021-06-20 18:40:04 +08:00
log.error('Tasks', 'task=user-delete id=%s user=%s message=%s error=%s', task._id, data.user, 'Failed to delete user placeholder', err.message);
err.code = 'InternalDatabaseError';
throw err;
}
2021-06-20 18:40:04 +08:00
log.verbose('Tasks', 'task=user-delete id=%s user=%s message=%s', task._id, data.user, `Cleared user specific data`);
2021-01-08 16:31:43 +08:00
2021-06-20 18:40:04 +08:00
result.task = task._id.toString();
2021-01-08 16:31:43 +08:00
await publish(db.redis, {
ev: USER_DELETE_COMPLETED,
2021-06-20 18:40:04 +08:00
user: data.user,
2021-01-08 16:31:43 +08:00
result
});
return true;
};
2021-06-20 18:40:04 +08:00
module.exports = (task, data, options, callback) => {
run(task, data)
.then(response => callback(null, response))
.catch(callback);
2018-10-11 16:48:12 +08:00
};