diff --git a/pages/api/file/getawaitingsubmissionfromblob.js b/pages/api/file/getawaitingsubmissionfromblob.js index 86f0a0f0..c1949040 100644 --- a/pages/api/file/getawaitingsubmissionfromblob.js +++ b/pages/api/file/getawaitingsubmissionfromblob.js @@ -14,16 +14,21 @@ ApiProxy.get(async (req, res) => { var containerName = req.query.container; var checkHash = req.query.hash; + if ( + typeof containerName === "undefined" || + containerName.length === 0 || + typeof checkHash === "undefined" || + checkHash.length === 0 + ) { + return res.status(400).json(); + } + var checkquerypath = "/api/file/getawaitingsubmissionfromblob?container=" + containerName; - // console.log( - // "///////////////////////\ngetawaitingsubmissionblob url :", - // req.url, - // "\n///////////////////////\n" - // ); - //console.log(hashAPIPath(checkquerypath), checkHash); - //console.log(hashAPIPath(checkquerypath) == "&hash=" + checkHash); + if (hashAPIPath(checkquerypath) != "&hash=" + checkHash) { + return res.status(400).json(); + } if (hashAPIPath(checkquerypath) == "&hash=" + checkHash) { const blobObj = await getAllProgressBlobs(containerName) @@ -33,8 +38,6 @@ ApiProxy.get(async (req, res) => { .then((data) => { return res.status(200).json(data); }); - } else { - return res.status(400).json(); } }); diff --git a/pages/api/file/getprogressobjblob.js b/pages/api/file/getprogressobjblob.js index aac8bfd5..8f5ef041 100644 --- a/pages/api/file/getprogressobjblob.js +++ b/pages/api/file/getprogressobjblob.js @@ -15,23 +15,31 @@ ApiProxy.get(async (req, res) => { var casefolderID = req.query.casefolderID; var checkHash = req.query.hash; + + if ( + typeof containerName === "undefined" || + containerName.length === 0 || + typeof casefolderID === "undefined" || + casefolderID.length === 0 || + typeof checkHash === "undefined" || + checkHash.length === 0 + ) { + return res.status(400).json(); + } + var checkquerypath = "/api/file/getprogressobjblob?container=" + containerName + "&casefolderID=" + casefolderID; - // console.log("-----", casefolderID); - // console.log("-----", req.query); - // console.log("-----", checkquerypath); - // console.log("-----", hashAPIPath(checkquerypath)); - // console.log("-----", checkHash); - // console.log(hashAPIPath(checkquerypath) == "&hash=" + checkHash); + if (hashAPIPath(checkquerypath) != "&hash=" + checkHash) { + return res.status(400).json(); + } if (hashAPIPath(checkquerypath) == "&hash=" + checkHash) { const blobObj = await getProgressBlobs(containerName, casefolderID) .then((data) => { - //console.log("Progress blob path:", data.path); return downloadProgressFile( containerName, data.path, @@ -41,8 +49,6 @@ ApiProxy.get(async (req, res) => { .then((data) => { return res.status(200).json(data); }); - } else { - return res.status(400).json(); } }); diff --git a/pages/api/file/getrepsblob.js b/pages/api/file/getrepsblob.js index 51bf1df3..2a9116e7 100644 --- a/pages/api/file/getrepsblob.js +++ b/pages/api/file/getrepsblob.js @@ -47,14 +47,23 @@ ApiProxy.get(async (req, res) => { var casefolderID = req.query.casefolderID; var checkHash = req.query.hash; + + if ( + typeof containerName === "undefined" || + containerName.length === 0 || + typeof casefolderID === "undefined" || + casefolderID.length === 0 || + typeof checkHash === "undefined" || + checkHash.length === 0 + ) { + return res.status(400).json(); + } + var checkquerypath = "/api/file/getrepsblob?container=" + containerName; - //console.log("-----", casefolderID); - //console.log("-----", req.query); - //console.log("-----", checkquerypath); - //console.log("-----", hashAPIPath(checkquerypath)); - //console.log("-----", checkHash); - //console.log(hashAPIPath(checkquerypath) == "&hash=" + checkHash); + if (hashAPIPath(checkquerypath) != "&hash=" + checkHash) { + return res.status(400).json(); + } if (hashAPIPath(checkquerypath) == "&hash=" + checkHash) { const blobObj = await getRepsBlobs(containerName, casefolderID) @@ -72,8 +81,6 @@ ApiProxy.get(async (req, res) => { .catch((error) => { consoleLogger(error); }); - } else { - return res.status(400).json(); } }); diff --git a/tests/phase10/service-behaviour.test.cjs b/tests/phase10/service-behaviour.test.cjs new file mode 100644 index 00000000..c034b001 --- /dev/null +++ b/tests/phase10/service-behaviour.test.cjs @@ -0,0 +1,236 @@ +const fs = require("fs"); +const path = require("path"); +const vm = require("vm"); +const assert = require("assert"); + +const rootDir = path.resolve(__dirname, "..", ".."); + +const loadModule = (relativePath, injected = {}) => { + const filePath = path.join(rootDir, relativePath); + let source = fs.readFileSync(filePath, "utf8"); + + source = source.replace(/import[\s\S]*?from\s+"[^"]+";\n?/g, ""); + source = source.replace( + /export default async function\s+(\w+)\s*\(/, + "async function $1(" + ); + source = source.replace(/export const\s+/g, "const "); + source = source.replace( + /export default\s+(\w+);/g, + "module.exports.default = $1;" + ); + + source += + '\nif (typeof ApiProxy !== "undefined" && !module.exports.default) module.exports.default = ApiProxy;\n'; + + const context = { + module: { exports: {} }, + exports: {}, + require, + process, + console: { + log: () => {}, + info: () => {}, + warn: () => {}, + error: () => {} + }, + ...injected + }; + + vm.runInNewContext(source, context, { filename: filePath }); + return context.module.exports; +}; + +const createNextConnectMock = () => { + const router = { + handler: null, + use: () => {}, + get(fn) { + this.handler = fn; + } + }; + + return () => router; +}; + +const createRes = () => { + const state = { + statusCode: null, + jsonBody: undefined + }; + + return { + state, + setHeader: () => {}, + status(code) { + state.statusCode = code; + return this; + }, + json(payload) { + state.jsonBody = payload; + return payload; + } + }; +}; + +const tests = []; +const test = (name, fn) => tests.push({ name, fn }); + +test("getawaitingsubmissionfromblob rejects missing hash with 400", async () => { + const calls = []; + const nextConnect = createNextConnectMock(); + + const mod = loadModule("pages/api/file/getawaitingsubmissionfromblob.js", { + hashAPIPath: () => "&hash=expected", + getAllProgressBlobs: async (...args) => { + calls.push(args); + return []; + }, + downloadAllProgressFiles: async () => [], + _: { isEmpty: (value) => !value }, + nextConnect, + middleware: () => {} + }); + + const req = { query: { container: "c1" } }; + const res = createRes(); + + await mod.default.handler(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual(calls.length, 0); +}); + +test("getprogressobjblob rejects missing casefolderID with 400", async () => { + const calls = []; + const nextConnect = createNextConnectMock(); + + const mod = loadModule("pages/api/file/getprogressobjblob.js", { + hashAPIPath: () => "&hash=expected", + getProgressBlobs: async (...args) => { + calls.push(args); + return { path: "x" }; + }, + downloadProgressFile: async () => ({}), + _: { isEmpty: (value) => !value }, + nextConnect, + middleware: () => {} + }); + + const req = { + query: { container: "c1", hash: "expected" } + }; + const res = createRes(); + + await mod.default.handler(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual(calls.length, 0); +}); + +test("getbloblist rejects invalid hash with 400", async () => { + const calls = []; + const nextConnect = createNextConnectMock(); + + const mod = loadModule("pages/api/file/getbloblist.js", { + hashAPIPath: () => "&hash=expected", + getBlobs: async (...args) => { + calls.push(args); + return []; + }, + getRepsFilesBlobs: async () => [], + nextConnect, + middleware: () => {} + }); + + const req = { + query: { + container: "c1", + casefolderID: "case-1", + hash: "wrong" + } + }; + const res = createRes(); + + await mod.default.handler(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual(calls.length, 0); +}); + +test("getrepsblob rejects missing hash with 400", async () => { + const calls = []; + const nextConnect = createNextConnectMock(); + + const mod = loadModule("pages/api/file/getrepsblob.js", { + hashAPIPath: () => "&hash=expected", + getRepsBlobs: async (...args) => { + calls.push(args); + return []; + }, + downloadAllRepsFiles: async () => [], + consoleLogger: () => {}, + _: { isEmpty: (value) => !value }, + nextConnect, + middleware: () => {} + }); + + const req = { + query: { + container: "c1", + casefolderID: "case-1" + } + }; + const res = createRes(); + + await mod.default.handler(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual(calls.length, 0); +}); + +test("getbloblist happy path with valid hash returns 200", async () => { + const nextConnect = createNextConnectMock(); + + const mod = loadModule("pages/api/file/getbloblist.js", { + hashAPIPath: () => "&hash=expected", + getBlobs: async () => ["file-1"], + getRepsFilesBlobs: async () => ["file-rep"], + nextConnect, + middleware: () => {} + }); + + const req = { + query: { + container: "c1", + casefolderID: "case-1", + hash: "expected" + } + }; + const res = createRes(); + + await mod.default.handler(req, res); + + assert.strictEqual(res.state.statusCode, 200); + assert.deepStrictEqual(JSON.parse(JSON.stringify(res.state.jsonBody)), { + value: [["file-1"]] + }); +}); + +const run = async () => { + let passed = 0; + + for (const currentTest of tests) { + await currentTest.fn(); + passed += 1; + } + + console.log( + `Phase 10 behavioural tests passed (${passed}/${tests.length}).` + ); +}; + +run().catch((error) => { + console.error(error); + process.exit(1); +});