wildduck/lib/api/audit.js
2022-11-24 12:26:10 +02:00

161 lines
5 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');
module.exports = (db, server, auditHandler) => {
server.post(
'/audit',
tools.responseWrapper(async (req, res) => {
res.charSet('utf-8');
const schema = Joi.object().keys({
user: Joi.string().hex().lowercase().length(24).required(),
start: Joi.date().empty('').allow(false),
end: Joi.date().empty('').allow(false),
expires: Joi.date().empty('').greater('now').required(),
sess: sessSchema,
ip: sessIPSchema
});
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(
'/audit/:audit',
tools.responseWrapper(async (req, res) => {
res.charSet('utf-8');
const schema = Joi.object().keys({
audit: Joi.string().hex().lowercase().length(24).required()
});
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(
'/audit/:audit/export.mbox',
tools.responseWrapper(async (req, res) => {
res.charSet('utf-8');
const schema = Joi.object().keys({
audit: Joi.string().hex().lowercase().length(24).required()
});
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-Dispositon', '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);
})
);
};