import { downloadFile } from "../../../actions/azurestorage"; import nextConnect from "next-connect"; import { hashAPIPath } from "../../../actions/core/hash"; import middleware from "../middleware/middleware"; import { respondError } from "../middleware/apiResponse"; const ApiProxy = nextConnect(); ApiProxy.use(middleware); ApiProxy.get(async (req, res) => { const containerName = req.query.container; const casefolderID = req.query.casefolderID; const blobName = req.query.blobname; const checkHash = req.query.hash; if ( typeof containerName === "undefined" || containerName.length === 0 || typeof casefolderID === "undefined" || casefolderID.length === 0 || typeof blobName === "undefined" || blobName.length === 0 || typeof checkHash === "undefined" || checkHash.length === 0 ) { return respondError(res, { status: 400, code: "MISSING_REQUIRED_QUERY", message: "container, casefolderID, blobname and hash are required" }); } const blobNameTrimmed = blobName.trim(); const hashCandidatePaths = [ "/api/file/downloadblob?container=" + containerName + "&casefolderID=" + casefolderID + "&blobname=" + blobNameTrimmed, "/api/file/downloadblob?container=" + containerName + "&casefolderID=" + encodeURIComponent(casefolderID) + "&blobname=" + blobNameTrimmed, "/api/file/downloadblob?container=" + containerName + "&casefolderID=" + casefolderID + "&blobname=" + encodeURIComponent(blobNameTrimmed), "/api/file/downloadblob?container=" + containerName + "&casefolderID=" + encodeURIComponent(casefolderID) + "&blobname=" + encodeURIComponent(blobNameTrimmed) ]; const isHashValid = hashCandidatePaths.some( (candidatePath) => hashAPIPath(candidatePath) == "&hash=" + checkHash ); if (!isHashValid) { return respondError(res, { status: 400, code: "INVALID_HASH", message: "Invalid hash" }); } try { const decodedBlobName = decodeURI(blobName); const normalizedBlobName = decodedBlobName.startsWith( casefolderID + "/" ) ? decodedBlobName : casefolderID + (decodedBlobName.indexOf(".json") > 0 ? "/" : "/files/") + decodedBlobName; const downloaded = await downloadFile( containerName, normalizedBlobName ); const responseFileName = decodedBlobName.split("/").pop(); res.setHeader( "content-disposition", "attachment; filename=" + responseFileName ); return res.status(200).send(downloaded); } catch (error) { return respondError(res, { status: 400, code: "DOWNLOAD_BLOB_FAILED", message: "Unable to download blob" }); } }); export const config = { api: { bodyParser: false } }; export default ApiProxy;