wildduck/lib/tasks/audit.js

194 lines
5.8 KiB
JavaScript
Raw Normal View History

2019-09-25 21:39:48 +08:00
'use strict';
const log = require('npmlog');
const db = require('../db');
2021-06-20 18:40:04 +08:00
let run = async (task, data, options) => {
2021-06-15 15:47:18 +08:00
const { auditHandler, messageHandler } = options;
2019-09-25 21:39:48 +08:00
let query = {
2021-06-20 18:40:04 +08:00
user: data.user
2019-09-25 21:39:48 +08:00
};
2021-06-20 18:40:04 +08:00
if (data.start) {
let start = data.start;
2019-09-25 21:39:48 +08:00
if (['number', 'string'].includes(typeof start)) {
start = new Date(start);
}
query.idate = query.idate || {};
query.idate.$gte = start;
}
2021-06-20 18:40:04 +08:00
if (data.end) {
let end = data.end;
2019-09-25 21:39:48 +08:00
if (['number', 'string'].includes(typeof end)) {
end = new Date(end);
}
query.idate = query.idate || {};
query.idate.$lte = end;
}
2019-10-01 16:22:10 +08:00
let mailboxes = new Map(
2021-06-20 18:40:04 +08:00
(await db.database.collection('mailboxes').find({ user: data.user }).toArray()).map(mailboxData => [mailboxData._id.toString(), mailboxData])
2019-10-01 16:22:10 +08:00
);
2019-09-25 21:39:48 +08:00
let processMessage = async messageData => {
let builder = messageHandler.indexer.rebuild(messageData.mimeTree);
if (!builder || builder.type !== 'stream' || !builder.value) {
return false;
}
2019-10-01 16:22:10 +08:00
let mailboxData = messageData.mailbox ? mailboxes.get(messageData.mailbox.toString()) : false;
2020-07-01 15:37:28 +08:00
let auditMessage = await auditHandler.store(
2021-06-20 18:40:04 +08:00
data.audit,
2020-07-01 15:37:28 +08:00
builder.value,
{
date: messageData.idate,
msgid: messageData.msgid,
header: messageData.mimeTree && messageData.mimeTree.parsedHeader,
ha: messageData.ha,
mailbox: messageData.mailbox,
mailboxPath: mailboxData ? mailboxData.path : false,
info: messageData.meta,
draft: messageData.draft,
imported: true
},
true
);
2019-09-29 20:00:44 +08:00
2019-09-25 21:39:48 +08:00
return auditMessage;
};
2019-09-29 20:00:44 +08:00
let copied = 0;
let failed = 0;
let status = 'imported'; //expect to complete successfully
2019-09-25 21:39:48 +08:00
let processMessages = async collection => {
2019-11-21 17:37:00 +08:00
let cursor = await db.database.collection(collection).find(query, {
2021-04-16 18:31:50 +08:00
noCursorTimeout: true,
2019-09-25 21:39:48 +08:00
projection: {
_id: true,
user: true,
2019-10-01 16:22:10 +08:00
mimeTree: true,
meta: true,
mailbox: true,
idate: true,
msgid: true,
ha: true,
draft: true
2019-09-25 21:39:48 +08:00
}
});
let messageData;
try {
while ((messageData = await cursor.next())) {
try {
let auditMessage = await processMessage(messageData);
log.verbose(
'Tasks',
'task=audit id=%s user=%s coll=%s message=%s src=%s dst=%s',
2021-06-20 18:40:04 +08:00
task._id,
data.user,
2019-09-25 21:39:48 +08:00
collection,
'Stored message to audit base',
messageData._id,
auditMessage
);
2019-09-29 20:00:44 +08:00
copied++;
2019-10-01 16:22:10 +08:00
try {
await db.database.collection('audits').updateOne(
2021-06-20 18:40:04 +08:00
{ _id: data.audit },
2019-10-01 16:22:10 +08:00
{
$inc: {
2020-07-01 15:37:28 +08:00
'import.copied': 1,
audited: 1
},
$set: {
lastAuditedMessage: new Date()
2019-10-01 16:22:10 +08:00
}
}
);
} catch (e) {
//ignore
}
2019-09-25 21:39:48 +08:00
} catch (err) {
log.error(
'Tasks',
'task=audit id=%s user=%s coll=%s message=%s error=%s',
2021-06-20 18:40:04 +08:00
task._id,
data.user,
2019-09-25 21:39:48 +08:00
collection,
'Failed to process message',
err.message
);
2019-09-29 20:00:44 +08:00
failed++;
2019-10-01 16:22:10 +08:00
try {
await db.database.collection('audits').updateOne(
2021-06-20 18:40:04 +08:00
{ _id: data.audit },
2019-10-01 16:22:10 +08:00
{
$inc: {
'import.failed': 1
}
}
);
} catch (e) {
//ignore
}
2019-09-25 21:39:48 +08:00
}
}
await cursor.close();
} catch (err) {
log.error(
'Tasks',
'task=audit id=%s user=%s coll=%s message=%s error=%s',
2021-06-20 18:40:04 +08:00
task._id,
data.user,
2019-09-25 21:39:48 +08:00
collection,
'Failed to fetch stored messages',
err.message
);
2019-09-29 20:00:44 +08:00
2019-09-25 21:39:48 +08:00
err.code = 'InternalDatabaseError';
throw err;
}
};
2019-10-01 16:22:10 +08:00
await db.database.collection('audits').updateOne(
2021-06-20 18:40:04 +08:00
{ _id: data.audit },
2019-10-01 16:22:10 +08:00
{
$set: {
'import.status': 'importing'
}
}
);
2019-09-29 20:00:44 +08:00
try {
await processMessages('messages');
} catch (err) {
2019-10-01 16:22:10 +08:00
status = 'failed';
2019-09-29 20:00:44 +08:00
}
try {
await processMessages('archive');
} catch (err) {
2019-10-01 16:22:10 +08:00
status = 'failed';
2019-09-29 20:00:44 +08:00
}
await db.database.collection('audits').updateOne(
2021-06-20 18:40:04 +08:00
{ _id: data.audit },
2019-09-29 20:00:44 +08:00
{
$set: {
2019-10-01 16:22:10 +08:00
'import.status': status
2019-09-29 20:00:44 +08:00
}
}
);
2019-09-25 21:39:48 +08:00
2021-06-20 18:40:04 +08:00
log.verbose('Tasks', 'task=audit id=%s user=%s message=%s copied=%s failed=%s', task._id, data.user, `Copied user messages for auditing`, copied, failed);
2019-09-25 21:39:48 +08:00
return true;
};
2021-06-20 18:40:04 +08:00
module.exports = (task, data, options, callback) => {
run(task, data, options)
2019-09-25 21:39:48 +08:00
.then(response => callback(null, response))
.catch(callback);
};