wildduck/lib/tasks/restore.js

176 lines
7.8 KiB
JavaScript
Raw Normal View History

2018-10-11 16:48:12 +08:00
'use strict';
const log = require('npmlog');
const db = require('../db');
module.exports = (taskData, options, callback) => {
const messageHandler = options.messageHandler;
2018-11-01 01:00:41 +08:00
db.users.collection('users').findOne({ _id: taskData.user }, (err, userData) => {
2018-10-11 16:48:12 +08:00
if (err) {
log.error('Tasks', 'task=restore id=%s user=%s error=%s', taskData._id, taskData.user, err.message);
return callback(err);
}
if (!userData) {
// no such user anymore
log.error('Tasks', 'task=restore id=%s user=%s error=%s', taskData._id, taskData.user, 'No such user');
return callback(null, true);
}
db.database
.collection('mailboxes')
.find({
user: taskData.user
})
.toArray((err, mailboxesList) => {
if (err) {
log.error('Tasks', 'task=restore id=%s user=%s error=%s', taskData._id, taskData.user, err.message);
return callback(err);
}
let mailboxes = new Map();
let trashMailbox;
let inboxMailbox;
2019-05-21 19:00:47 +08:00
mailboxes = new Map();
(mailboxesList || []).forEach(mailboxData => {
2018-10-11 16:48:12 +08:00
mailboxes.set(mailboxData._id.toString(), mailboxData);
if (mailboxData.specialUse === '\\Trash') {
trashMailbox = mailboxData._id;
} else if (mailboxData.path === 'INBOX') {
inboxMailbox = mailboxData._id;
}
});
2018-11-06 16:36:26 +08:00
let cursor = db.database.collection('archived').find({
user: taskData.user,
archived: {
$gte: taskData.start,
$lte: taskData.end
}
});
2018-10-11 16:48:12 +08:00
let processNext = () => {
cursor.next((err, messageData) => {
if (err) {
log.error('Tasks', 'task=restore id=%s user=%s error=%s', taskData._id, taskData.user, err.message);
return callback(err);
}
if (!messageData) {
return cursor.close(() => callback(null, true));
}
// move messages from Trash and non-existing mailboxes to INBOX
if (messageData.mailbox && (messageData.mailbox.equals(trashMailbox) || !mailboxes.has(messageData.mailbox.toString()))) {
messageData.mailbox = inboxMailbox;
}
2019-05-21 19:00:47 +08:00
const archived = messageData._id;
2018-10-11 16:48:12 +08:00
delete messageData.archived;
delete messageData.exp;
delete messageData.rdate;
2019-05-21 20:41:28 +08:00
// mark message as not deleted
messageData.flags = (messageData.flags || []).filter(flag => flag !== '\\Deleted');
messageData.undeleted = true;
2018-10-11 16:48:12 +08:00
log.info(
'Tasks',
'task=restore id=%s user=%s message=%s action=restoring target=%s',
taskData._id,
taskData.user,
2019-05-21 19:00:47 +08:00
archived,
2018-10-11 16:48:12 +08:00
messageData.mailbox
);
messageHandler.put(messageData, (err, response) => {
if (err) {
2018-11-26 16:02:39 +08:00
log.error(
'Tasks',
'task=restore id=%s user=%s message=%s error=%s',
taskData._id,
taskData.user,
2019-05-21 19:00:47 +08:00
archived,
2018-11-26 16:02:39 +08:00
'Failed to restore message. ' + err.message
);
2018-10-11 16:48:12 +08:00
return setTimeout(processNext, 5000);
} else if (!response) {
log.error(
'Tasks',
'task=restore id=%s user=%s message=%s error=%s',
taskData._id,
taskData.user,
2019-05-21 19:00:47 +08:00
archived,
2018-10-11 16:48:12 +08:00
'Failed to restore message'
);
return setTimeout(processNext, 1000);
}
2018-11-26 16:02:39 +08:00
db.users.collection('users').updateOne(
{
_id: taskData.user
},
{
$inc: {
storageUsed: messageData.size
}
},
err => {
if (err) {
// just log the error, nothing more
log.error(
'Tasks',
'task=restore id=%s user=%s message=%s error=%s',
taskData._id,
taskData.user,
2019-05-21 19:00:47 +08:00
archived,
2018-11-26 16:02:39 +08:00
'Failed to update user quota. ' + err.message
);
}
log.info(
'Tasks',
2019-05-21 19:00:47 +08:00
'task=restore id=%s user=%s message=%s mailbox=%s uid=%s action=restored',
2018-11-26 16:02:39 +08:00
taskData._id,
taskData.user,
2019-05-21 19:00:47 +08:00
response.message,
2018-11-26 16:02:39 +08:00
response.mailbox,
response.uid
);
2019-05-21 19:00:47 +08:00
return db.database.collection('archived').deleteOne({ _id: archived }, (err, r) => {
if (err) {
log.error(
'Tasks',
'task=restore id=%s user=%s message=%s error=%s',
taskData._id,
taskData.user,
archived,
'Failed to delete archived message. ' + err.message
);
} else {
log.info(
'Tasks',
'task=restore id=%s user=%s message=%s action=deleted count=%s',
taskData._id,
taskData.user,
archived,
r.deletedCount
);
}
processNext();
});
2018-11-26 16:02:39 +08:00
}
2018-10-11 16:48:12 +08:00
);
});
});
};
processNext();
});
});
};