wildduck/lib/tasks/user-delete.js

222 lines
7.2 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-01-08 16:31:43 +08:00
const deleteMessages = async taskData => {
let rdate = new Date(Date.now() + consts.DELETED_USER_MESSAGE_RETENTION).getTime();
let lastId;
2021-01-08 16:31:43 +08:00
let markedAsDeleted = 0;
2018-10-11 16:48:12 +08:00
try {
2021-01-08 16:31:43 +08:00
let done = false;
while (!done) {
let query = {
user: taskData.user,
userDeleted: { $ne: true }
};
if (lastId) {
query._id = { $gt: lastId };
}
let messages = await db.users
.collection('messages')
.find(query, {
sort: { _id: 1 },
projection: {
_id: true
},
2021-01-08 16:31:43 +08:00
limit: BATCH_SIZE
})
.toArray();
if (!messages.length) {
// all done
done = true;
break;
}
messages = messages.map(messageData => messageData._id);
lastId = messages[messages.length - 1];
let updateEntries = [];
messages.forEach(message => {
updateEntries.push({
updateOne: {
filter: {
_id: message
},
update: {
$set: {
exp: true,
rdate,
userDeleted: true
}
}
}
2021-01-08 16:31:43 +08:00
});
});
let bulkResult = await db.database.collection('messages').bulkWrite(updateEntries, {
ordered: false,
w: 1
});
2018-10-11 16:48:12 +08:00
2021-01-08 16:31:43 +08:00
markedAsDeleted += (bulkResult && bulkResult.modifiedCount) || 0;
}
} catch (err) {
2021-01-08 16:31:43 +08:00
err.markedAsDeleted = markedAsDeleted;
throw err;
2021-01-08 16:31:43 +08:00
} finally {
log.verbose('Tasks', 'task=user-delete id=%s user=%s message=%s', taskData._id, taskData.user, `Marked ${markedAsDeleted} messages for deletion`);
}
2021-01-08 16:31:43 +08:00
return markedAsDeleted;
};
const deleteRegistryAddresses = async taskData => {
let lastId;
let deleted = 0;
try {
let done = false;
while (!done) {
let query = {
user: taskData.user
};
if (lastId) {
query._id = { $gt: lastId };
}
2018-10-11 16:48:12 +08:00
2021-01-08 16:31:43 +08:00
let addresses = await db.users
.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
}
}
});
});
let bulkResult = await db.database.collection('messages').bulkWrite(updateEntries, {
ordered: false,
w: 1
});
deleted += (bulkResult && bulkResult.deletedCount) || 0;
}
} catch (err) {
err.deleted = deleted;
throw err;
} finally {
log.verbose('Tasks', 'task=user-delete id=%s user=%s message=%s', taskData._id, taskData.user, `Deleted ${deleted} addresses from registry`);
}
2021-01-08 16:31:43 +08:00
return deleted;
};
const run = async taskData => {
let result = {};
2018-10-11 16:48:12 +08:00
try {
2021-01-08 16:31:43 +08:00
let delRes = await db.database.collection('mailboxes').deleteMany({ user: taskData.user });
result.mailboxes = { deleted: delRes.deletedCount };
} catch (err) {
log.error('Tasks', 'task=user-delete id=%s user=%s message=%s error=%s', taskData._id, taskData.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-01-08 16:31:43 +08:00
let delRes = await db.users.collection('asps').deleteMany({ user: taskData.user });
result.asps = { deleted: delRes.deletedCount };
} catch (err) {
log.error('Tasks', 'task=user-delete id=%s user=%s message=%s error=%s', taskData._id, taskData.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-01-08 16:31:43 +08:00
let delRes = await db.users.collection('filters').deleteMany({ user: taskData.user });
result.filters = { deleted: delRes.deletedCount };
} catch (err) {
log.error('Tasks', 'task=user-delete id=%s user=%s message=%s error=%s', taskData._id, taskData.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-01-08 16:31:43 +08:00
let delRes = await db.users.collection('autoreplies').deleteMany({ user: taskData.user });
result.autoreplies = { deleted: delRes.deletedCount };
} catch (err) {
log.error('Tasks', 'task=user-delete id=%s user=%s message=%s error=%s', taskData._id, taskData.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-01-08 16:31:43 +08:00
let deleted = await deleteRegistryAddresses(taskData);
result.addressregister = { deleted };
} catch (err) {
log.error('Tasks', 'task=user-delete id=%s user=%s message=%s error=%s', taskData._id, taskData.user, 'Failed to delete autoreplies', 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
let markedAsDeleted = await deleteMessages(taskData);
result.messages = { deleted: markedAsDeleted };
} catch (err) {
log.error('Tasks', 'task=user-delete id=%s user=%s message=%s error=%s', taskData._id, taskData.user, 'Failed to fetch messages', err.message);
err.code = 'InternalDatabaseError';
result.messages = { error: err.message, deleted: err.markedAsDeleted };
throw err;
}
log.verbose('Tasks', 'task=user-delete id=%s user=%s message=%s', taskData._id, taskData.user, `Cleared user specific data`);
2021-01-08 16:31:43 +08:00
result.task = taskData._id.toString();
await publish(db.redis, {
ev: USER_DELETE_COMPLETED,
user: taskData.user,
result
});
return true;
};
module.exports = (taskData, options, callback) => {
run(taskData)
.then(response => callback(null, response))
.catch(callback);
2018-10-11 16:48:12 +08:00
};