mirror of
https://github.com/nodemailer/wildduck.git
synced 2025-11-21 17:38:46 +08:00
236 lines
8.4 KiB
JavaScript
236 lines
8.4 KiB
JavaScript
'use strict';
|
|
|
|
const log = require('npmlog');
|
|
const Joi = require('joi');
|
|
const tools = require('../tools');
|
|
const roles = require('../roles');
|
|
const mboxExport = require('../mbox-export');
|
|
const ObjectId = require('mongodb').ObjectId;
|
|
const { sessSchema, sessIPSchema } = require('../schemas');
|
|
const { userId } = require('../schemas/request/general-schemas');
|
|
const { successRes } = require('../schemas/response/general-schemas');
|
|
|
|
module.exports = (db, server, auditHandler) => {
|
|
server.post(
|
|
{
|
|
path: '/audit',
|
|
tags: ['Audit'],
|
|
summary: 'Create new audit',
|
|
description: 'Initiates a message audit',
|
|
validationObjs: {
|
|
requestBody: {
|
|
user: userId,
|
|
start: Joi.date().empty('').allow(false).description('Start time as ISO date'),
|
|
end: Joi.date().empty('').allow(false).description('End time as ISO date'),
|
|
expires: Joi.date().empty('').greater('now').required().description('Expiration date. Audit data is deleted after this date'),
|
|
sess: sessSchema,
|
|
ip: sessIPSchema
|
|
},
|
|
queryParams: {},
|
|
pathParams: {},
|
|
response: {
|
|
200: {
|
|
description: 'Success',
|
|
model: Joi.object({ success: successRes, id: Joi.string().required().description('ID for the created Audit') })
|
|
}
|
|
}
|
|
}
|
|
},
|
|
tools.responseWrapper(async (req, res) => {
|
|
res.charSet('utf-8');
|
|
|
|
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;
|
|
|
|
const schema = Joi.object({
|
|
...pathParams,
|
|
...requestBody,
|
|
...queryParams
|
|
});
|
|
|
|
const result = schema.validate(req.params, {
|
|
abortEarly: false,
|
|
convert: true
|
|
});
|
|
|
|
if (result.error) {
|
|
res.status(400);
|
|
return res.json({
|
|
error: result.error.message,
|
|
code: 'InputValidationError',
|
|
details: tools.validationErrors(result)
|
|
});
|
|
}
|
|
|
|
// permissions check
|
|
req.validate(roles.can(req.role).updateAny('audit'));
|
|
|
|
let user = new ObjectId(result.value.user);
|
|
let start = result.value.start;
|
|
let end = result.value.end;
|
|
let expires = result.value.expires;
|
|
|
|
let audit = await auditHandler.create({
|
|
user,
|
|
start,
|
|
end,
|
|
expires
|
|
});
|
|
|
|
return res.json({
|
|
success: true,
|
|
id: audit
|
|
});
|
|
})
|
|
);
|
|
|
|
server.get(
|
|
{
|
|
path: '/audit/:audit',
|
|
tags: ['Audit'],
|
|
summary: 'Request Audit Info',
|
|
description: 'This method returns information about stored audit',
|
|
validationObjs: {
|
|
requestBody: {},
|
|
pathParams: {
|
|
audit: Joi.string().hex().lowercase().length(24).required().description('ID of the Audit')
|
|
},
|
|
queryParams: {},
|
|
response: {
|
|
200: {
|
|
description: 'Success',
|
|
model: Joi.object({
|
|
success: successRes,
|
|
id: Joi.string().required().description('ID of the Audit'),
|
|
user: userId,
|
|
start: Joi.date().empty('').allow(false).description('Start time as ISO date'),
|
|
end: Joi.date().empty('').allow(false).description('End time as ISO date'),
|
|
expires: Joi.date().empty('').greater('now').required().description('Expiration date. Audit data is deleted after this date'),
|
|
import: Joi.object({
|
|
status: Joi.string().required().description('Status of the audit'),
|
|
failed: Joi.number().required().description('How many messages failed'),
|
|
copied: Joi.number().required().description('How many messages copied')
|
|
})
|
|
.required()
|
|
.description('Audit import data')
|
|
})
|
|
}
|
|
}
|
|
}
|
|
},
|
|
tools.responseWrapper(async (req, res) => {
|
|
res.charSet('utf-8');
|
|
|
|
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;
|
|
|
|
const schema = Joi.object({
|
|
...pathParams,
|
|
...requestBody,
|
|
...queryParams
|
|
});
|
|
|
|
const result = schema.validate(req.params, {
|
|
abortEarly: false,
|
|
convert: true
|
|
});
|
|
|
|
if (result.error) {
|
|
res.status(400);
|
|
return res.json({
|
|
error: result.error.message,
|
|
code: 'InputValidationError',
|
|
details: tools.validationErrors(result)
|
|
});
|
|
}
|
|
|
|
// permissions check
|
|
req.validate(roles.can(req.role).readAny('audit'));
|
|
|
|
let auditData = await db.database.collection('audits').findOne({ _id: new ObjectId(req.params.audit) });
|
|
if (!auditData) {
|
|
res.status(404);
|
|
return res.json({
|
|
error: 'Audit not found',
|
|
code: 'AuditNotFoundError'
|
|
});
|
|
}
|
|
|
|
res.status(200);
|
|
return res.json({
|
|
success: true,
|
|
id: auditData._id.toString(),
|
|
user: auditData.user,
|
|
start: auditData.start && auditData.start.toISOString(),
|
|
end: auditData.end && auditData.end.toISOString(),
|
|
expires: auditData.expires && auditData.expires.toISOString(),
|
|
import: auditData.import
|
|
});
|
|
})
|
|
);
|
|
|
|
server.get(
|
|
{
|
|
path: '/audit/:audit/export.mbox',
|
|
tags: ['Audit'],
|
|
summary: 'Export Audited Emails',
|
|
description: 'This method returns a mailbox file that contains all audited emails',
|
|
validationObjs: {
|
|
requestBody: {},
|
|
queryParams: {},
|
|
pathParams: { audit: Joi.string().hex().lowercase().length(24).required().description('ID of the Audit') },
|
|
response: { 200: { description: 'Success', model: Joi.binary() } }
|
|
},
|
|
responseType: 'application/octet-stream'
|
|
},
|
|
tools.responseWrapper(async (req, res) => {
|
|
res.charSet('utf-8');
|
|
|
|
const { pathParams, requestBody, queryParams } = req.route.spec.validationObjs;
|
|
|
|
const schema = Joi.object({
|
|
...pathParams,
|
|
...requestBody,
|
|
...queryParams
|
|
});
|
|
|
|
const result = schema.validate(req.params, {
|
|
abortEarly: false,
|
|
convert: true
|
|
});
|
|
|
|
if (result.error) {
|
|
res.status(400);
|
|
return res.json({
|
|
error: result.error.message,
|
|
code: 'InputValidationError',
|
|
details: tools.validationErrors(result)
|
|
});
|
|
}
|
|
|
|
// permissions check
|
|
req.validate(roles.can(req.role).readAny('audit'));
|
|
|
|
let output = await mboxExport(auditHandler, new ObjectId(req.params.audit));
|
|
if (!output) {
|
|
res.status(404);
|
|
return res.json({
|
|
error: 'Audit not found',
|
|
code: 'AuditNotFoundError'
|
|
});
|
|
}
|
|
|
|
res.setHeader('Content-Type', 'application/octet-stream');
|
|
res.setHeader('Content-Disposition', 'attachment; filename=export.mbox');
|
|
|
|
output.on('error', err => {
|
|
log.error('Audit', `Failed processing audit ${req.params.audit}: ${err.message}`);
|
|
try {
|
|
res.end();
|
|
} catch (err) {
|
|
//ignore
|
|
}
|
|
});
|
|
|
|
output.pipe(res);
|
|
})
|
|
);
|
|
};
|