2024-07-18 21:35:17 +03:00
|
|
|
import becca from "../becca/becca.js";
|
|
|
|
import eu from "./etapi_utils.js";
|
|
|
|
import mappers from "./mappers.js";
|
|
|
|
import v from "./validators.js";
|
|
|
|
import utils from "../services/utils.js";
|
2025-01-09 18:07:02 +02:00
|
|
|
import { Router } from "express";
|
|
|
|
import { AttachmentRow } from "../becca/entities/rows.js";
|
|
|
|
import { ValidatorMap } from "./etapi-interface.js";
|
2024-04-07 15:13:34 +03:00
|
|
|
|
|
|
|
function register(router: Router) {
|
|
|
|
const ALLOWED_PROPERTIES_FOR_CREATE_ATTACHMENT: ValidatorMap = {
|
2025-01-09 18:07:02 +02:00
|
|
|
ownerId: [v.notNull, v.isNoteId],
|
|
|
|
role: [v.notNull, v.isString],
|
|
|
|
mime: [v.notNull, v.isString],
|
|
|
|
title: [v.notNull, v.isString],
|
|
|
|
position: [v.notNull, v.isInteger],
|
|
|
|
content: [v.isString]
|
2023-06-05 09:23:42 +02:00
|
|
|
};
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
eu.route(router, "post", "/etapi/attachments", (req, res, next) => {
|
2024-04-07 15:13:34 +03:00
|
|
|
const _params: Partial<AttachmentRow> = {};
|
|
|
|
eu.validateAndPatch(_params, req.body, ALLOWED_PROPERTIES_FOR_CREATE_ATTACHMENT);
|
|
|
|
const params = _params as AttachmentRow;
|
2023-06-05 09:23:42 +02:00
|
|
|
|
|
|
|
try {
|
2024-04-07 15:13:34 +03:00
|
|
|
if (!params.ownerId) {
|
|
|
|
throw new Error("Missing owner ID.");
|
|
|
|
}
|
2023-07-14 17:01:56 +02:00
|
|
|
const note = becca.getNoteOrThrow(params.ownerId);
|
2023-06-05 09:23:42 +02:00
|
|
|
const attachment = note.saveAttachment(params);
|
|
|
|
|
|
|
|
res.status(201).json(mappers.mapAttachmentToPojo(attachment));
|
2025-01-09 18:07:02 +02:00
|
|
|
} catch (e: any) {
|
2023-06-05 09:23:42 +02:00
|
|
|
throw new eu.EtapiError(500, eu.GENERIC_CODE, e.message);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
eu.route(router, "get", "/etapi/attachments/:attachmentId", (req, res, next) => {
|
2023-06-05 09:23:42 +02:00
|
|
|
const attachment = eu.getAndCheckAttachment(req.params.attachmentId);
|
|
|
|
|
|
|
|
res.json(mappers.mapAttachmentToPojo(attachment));
|
|
|
|
});
|
|
|
|
|
|
|
|
const ALLOWED_PROPERTIES_FOR_PATCH = {
|
2025-01-09 18:07:02 +02:00
|
|
|
role: [v.notNull, v.isString],
|
|
|
|
mime: [v.notNull, v.isString],
|
|
|
|
title: [v.notNull, v.isString],
|
|
|
|
position: [v.notNull, v.isInteger]
|
2023-06-05 09:23:42 +02:00
|
|
|
};
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
eu.route(router, "patch", "/etapi/attachments/:attachmentId", (req, res, next) => {
|
2023-06-05 09:23:42 +02:00
|
|
|
const attachment = eu.getAndCheckAttachment(req.params.attachmentId);
|
|
|
|
|
|
|
|
if (attachment.isProtected) {
|
|
|
|
throw new eu.EtapiError(400, "ATTACHMENT_IS_PROTECTED", `Attachment '${req.params.attachmentId}' is protected and cannot be modified through ETAPI.`);
|
|
|
|
}
|
|
|
|
|
|
|
|
eu.validateAndPatch(attachment, req.body, ALLOWED_PROPERTIES_FOR_PATCH);
|
|
|
|
attachment.save();
|
|
|
|
|
|
|
|
res.json(mappers.mapAttachmentToPojo(attachment));
|
|
|
|
});
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
eu.route(router, "get", "/etapi/attachments/:attachmentId/content", (req, res, next) => {
|
2023-06-05 09:23:42 +02:00
|
|
|
const attachment = eu.getAndCheckAttachment(req.params.attachmentId);
|
|
|
|
|
|
|
|
if (attachment.isProtected) {
|
|
|
|
throw new eu.EtapiError(400, "ATTACHMENT_IS_PROTECTED", `Attachment '${req.params.attachmentId}' is protected and content cannot be read through ETAPI.`);
|
|
|
|
}
|
|
|
|
|
2023-06-29 23:32:19 +02:00
|
|
|
const filename = utils.formatDownloadTitle(attachment.title, attachment.role, attachment.mime);
|
2023-06-05 09:23:42 +02:00
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
res.setHeader("Content-Disposition", utils.getContentDisposition(filename));
|
2023-06-05 09:23:42 +02:00
|
|
|
|
|
|
|
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
2025-01-09 18:07:02 +02:00
|
|
|
res.setHeader("Content-Type", attachment.mime);
|
2023-06-05 09:23:42 +02:00
|
|
|
|
|
|
|
res.send(attachment.getContent());
|
|
|
|
});
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
eu.route(router, "put", "/etapi/attachments/:attachmentId/content", (req, res, next) => {
|
2023-06-05 09:23:42 +02:00
|
|
|
const attachment = eu.getAndCheckAttachment(req.params.attachmentId);
|
|
|
|
|
|
|
|
if (attachment.isProtected) {
|
|
|
|
throw new eu.EtapiError(400, "ATTACHMENT_IS_PROTECTED", `Attachment '${req.params.attachmentId}' is protected and cannot be modified through ETAPI.`);
|
|
|
|
}
|
|
|
|
|
|
|
|
attachment.setContent(req.body);
|
|
|
|
|
|
|
|
return res.sendStatus(204);
|
|
|
|
});
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
eu.route(router, "delete", "/etapi/attachments/:attachmentId", (req, res, next) => {
|
2023-06-05 09:23:42 +02:00
|
|
|
const attachment = becca.getAttachment(req.params.attachmentId);
|
|
|
|
|
|
|
|
if (!attachment) {
|
|
|
|
return res.sendStatus(204);
|
|
|
|
}
|
|
|
|
|
|
|
|
attachment.markAsDeleted();
|
|
|
|
|
|
|
|
res.sendStatus(204);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-07-18 21:42:44 +03:00
|
|
|
export default {
|
2023-06-05 09:23:42 +02:00
|
|
|
register
|
|
|
|
};
|