diff --git a/cli/src/commands/flows.js b/cli/src/commands/flows.js index e6dd2d6..f75ec46 100644 --- a/cli/src/commands/flows.js +++ b/cli/src/commands/flows.js @@ -18,6 +18,11 @@ function parseTime(timeStr) { return date.getTime() / 1000; } +const buildFlowQuery = (gid, query) => { + const boxQuery = `box.id:${gid}`; + return query ? `${boxQuery} ${query}` : boxQuery; +}; + const Flows = { report: async (options) => { const gid = await resolveBoxGid(options.box, options); @@ -104,7 +109,7 @@ const Flows = { const gid = await resolveBoxGid(options.box, options); const client = getClient(options); - let apiParams = { gid }; + let apiParams = {}; let queryParts = []; // Build query from convenience flags @@ -163,6 +168,11 @@ const Flows = { }); } + // GET /v2/flows is MSP-wide. Enforce the selected box using the + // documented flow search qualifier after all caller-provided filters + // have been applied, so raw params cannot remove the box boundary. + apiParams.query = buildFlowQuery(gid, apiParams.query); + try { // Auto-pagination when limit > 500 or --all flag const shouldPaginate = options.all || (targetLimit && targetLimit > 500); @@ -277,4 +287,5 @@ function computeStats(flows) { return stats; } -module.exports = Flows; \ No newline at end of file +module.exports = Flows; +module.exports.buildFlowQuery = buildFlowQuery; \ No newline at end of file diff --git a/package.json b/package.json index 6bbf6ac..2de1b1c 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "fw": "./src/index.js" }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "node --test" }, "dependencies": { "axios": "^1.6.0", diff --git a/test/flows.test.js b/test/flows.test.js new file mode 100644 index 0000000..d45f7b5 --- /dev/null +++ b/test/flows.test.js @@ -0,0 +1,22 @@ +const test = require('node:test'); +const assert = require('node:assert/strict'); + +const { buildFlowQuery } = require('../cli/src/commands/flows'); + +test('scopes flow queries to the selected box', () => { + assert.equal(buildFlowQuery('box-a'), 'box.id:box-a'); +}); + +test('preserves additional flow filters while enforcing box scope', () => { + assert.equal( + buildFlowQuery('box-a', 'direction:outbound ts:>123'), + 'box.id:box-a direction:outbound ts:>123' + ); +}); + +test('does not allow a caller query to replace the selected box', () => { + assert.equal( + buildFlowQuery('box-a', 'box.id:box-b'), + 'box.id:box-a box.id:box-b' + ); +});