From 9043007b3ff4a1d6d74e1137320c55c11f1c23af Mon Sep 17 00:00:00 2001 From: Clint Zirker Date: Mon, 27 Oct 2025 10:46:20 -0600 Subject: [PATCH 1/3] Adding converters for passed context as query parameters --- index.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/index.js b/index.js index af2cb7a..576f7b5 100644 --- a/index.js +++ b/index.js @@ -219,6 +219,11 @@ function createRequest(event, resource) { }; +const typeConverters = { + number: (value) => parseFloat(value), + int: (value) => parseInt(value, 10) +} + function getPassedContext(event, body) { body = body || event.body || {}; if (typeof body === 'string') { @@ -232,6 +237,17 @@ function getPassedContext(event, body) { (ctx, [key, value]) => { let k; if ((k = key.match(/^ctx[_-](.*)$/))) { + + // Check for any type conversions on the query parameter + let type = event.queryStringParameters["t_" + key]; + let converter = typeConverters[type]; + if (converter) { + if (Array.isArray(value)) { + value = value.map(v => converter(v)); + } else { + value = converter(v); + } + } ctx[k[1]] = value; } return ctx; @@ -243,6 +259,8 @@ function getPassedContext(event, body) { } module.exports = { + typeConverters, + getPassedContext, configuration: { LeoAuth: AUTH_TABLE, LeoAuthUser: USER_TABLE From e6702ea0069664afa2acf43b86701ebb6f1200ee Mon Sep 17 00:00:00 2001 From: Lynn Mecham Date: Mon, 27 Oct 2025 12:26:54 -0600 Subject: [PATCH 2/3] Enhanced context handling by adding support for custom typing on query_param context values and multi-value query parameters in the request processing logic. Updated unit tests to validate new functionality. --- index.js | 28 +++++++++++++++------ test/index.utest.ts | 61 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index 576f7b5..381fc13 100644 --- a/index.js +++ b/index.js @@ -221,7 +221,8 @@ function createRequest(event, resource) { const typeConverters = { number: (value) => parseFloat(value), - int: (value) => parseInt(value, 10) + int: (value) => parseInt(value, 10), + boolean: (value) => value === 'true' || value === '1', } function getPassedContext(event, body) { @@ -242,11 +243,7 @@ function getPassedContext(event, body) { let type = event.queryStringParameters["t_" + key]; let converter = typeConverters[type]; if (converter) { - if (Array.isArray(value)) { - value = value.map(v => converter(v)); - } else { - value = converter(v); - } + value = converter(value); } ctx[k[1]] = value; } @@ -254,6 +251,22 @@ function getPassedContext(event, body) { }, body._context || {} ); + + // Multi value query parameters support (arrays) this is the default for HTTP requests to the API Gateway + if(event.multiValueQueryStringParameters) { + Object.entries(event.multiValueQueryStringParameters).forEach(([key, values]) => { + let k; + if ((k = key.match(/^ctx[_-](.*)$/))) { + + let type = event.multiValueQueryStringParameters["t_" + key]; + let converter = typeConverters[type]; + if (converter) { + values = values.map(v => converter(v)); + } + context[k[1]] = values; + } + }); + } //delete body._context; return context; } @@ -294,7 +307,8 @@ module.exports = { context: Object.assign(passedContext, { key: id.identity.caller }), - identities: ["role/aws_key"] + //prepend possible other passed in identities + identities: (Array.isArray(passedContext.identities) ? passedContext.identities.concat(["role/aws_key"]) : ["role/aws_key"]) }); } else { if (id && id.identity) { diff --git a/test/index.utest.ts b/test/index.utest.ts index 10a9cb3..9a8cd9a 100644 --- a/test/index.utest.ts +++ b/test/index.utest.ts @@ -228,6 +228,67 @@ describe('index', function () { assert.deepEqual(user.identities, ["awesome-again"]); assert.deepEqual(user.identity_id, "cognitoId-1234"); }); + + it("get user - custom querystring context with types", async () => { + + let sdk = require(".."); + let user = await sdk.getUser({ + queryStringParameters: { + ctx_account: "98765", + "ctx-value": 3453, + ctx_account_id: "12345678910", + t_ctx_account_id: "int", + ctx_float_value: "1.23456789", + t_ctx_float_value: "number", + ctx_boolean_value: "true", + t_ctx_boolean_value: "boolean", + ctx_boolean_value_false: "false", + t_ctx_boolean_value_false: "boolean", + ctx_invalid_type: "test123", + t_ctx_invalid_type: "scalar", + }, + requestContext: { + identity: { + caller: "identity-1234" + } + } + }); + + assert.deepEqual(user.context, { key: "identity-1234", account: "98765", value: 3453, account_id: 12345678910, float_value: 1.23456789, boolean_value: true, boolean_value_false: false, invalid_type: "test123" }); + }); + + it("get user - custom multiValueQueryStringParameters with types", async() => { + let sdk = require(".."); + let user = await sdk.getUser({ + multiValueQueryStringParameters: { + ctx_array: ["1", "2"], + t_ctx_array: "int", + ctx_array_invalid: ["test123", "test456"], + t_ctx_array_invalid: "scalar" + }, + requestContext: { + identity: { + caller: "identity-1234" + } + } + }); + assert.deepEqual(user.context, { key: "identity-1234", array: [1, 2], array_invalid: ["test123", "test456"] }); + }); + + it("get user - custom identities", async() => { + let sdk = require(".."); + let user = await sdk.getUser({ + requestContext: { + identity: { + caller: "identity-1234" + } + }, + multiValueQueryStringParameters: { + ctx_identities: ["role/test2", "role/test3"] + } + }); + assert.deepEqual(user.identities, [ "role/test2", "role/test3", "role/aws_key" ]); + }); }); describe("auth user", () => { From 5462a5913980f37346589be4635c1a448c2c5bc8 Mon Sep 17 00:00:00 2001 From: Lynn Mecham Date: Mon, 27 Oct 2025 12:29:26 -0600 Subject: [PATCH 3/3] bumping package version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4b0a161..1b315e9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "leo-auth", - "version": "4.0.1", + "version": "4.0.2", "description": "Auth sdk", "homepage": "https://leoplatform.io", "main": "index.js",