From ef1ca8e5539ebdc01ddebc47bc216d6542f1e8cc Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Thu, 6 Feb 2025 21:16:37 +0000 Subject: [PATCH] Update behaviour of `?case=original` query to `/service/javascript-app` - return raw contents (#6813) --- src/node/gov/handlers/service_state.h | 19 ++++++++++++-- tests/js-modules/basic-module-import/app.json | 4 +-- tests/js-modules/modules.py | 25 +++++++++++++++++-- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/node/gov/handlers/service_state.h b/src/node/gov/handlers/service_state.h index 31b77c69e047..7fe0e3f6a636 100644 --- a/src/node/gov/handlers/service_state.h +++ b/src/node/gov/handlers/service_state.h @@ -335,8 +335,15 @@ namespace ccf::gov::endpoints auto js_endpoints_handle = ctx.tx.template ro( ccf::endpoints::Tables::ENDPOINTS); + + using RawEndpointsMap = ccf::kv::RawCopySerialisedMap< + ccf::endpoints::EndpointsMap::Key, + std::vector>; + auto raw_js_endpoints_handle = ctx.tx.template ro( + ccf::endpoints::Tables::ENDPOINTS); + js_endpoints_handle->foreach( - [&endpoints, original_case]( + [&endpoints, &raw_js_endpoints_handle, original_case]( const ccf::endpoints::EndpointKey& key, const ccf::endpoints::EndpointProperties& properties) { auto ib = @@ -347,7 +354,15 @@ namespace ccf::gov::endpoints if (original_case) { - operation = properties; + const auto raw_value_opt = raw_js_endpoints_handle->get(key); + if (!raw_value_opt.has_value()) + { + throw std::runtime_error( + "Table inconsistency: Cannot access key via raw handle?"); + } + const auto& raw_value = raw_value_opt.value(); + operation = + nlohmann::json::parse(raw_value.begin(), raw_value.end()); } else { diff --git a/tests/js-modules/basic-module-import/app.json b/tests/js-modules/basic-module-import/app.json index 2f2fec1b1811..8382ac31d5d5 100644 --- a/tests/js-modules/basic-module-import/app.json +++ b/tests/js-modules/basic-module-import/app.json @@ -5,10 +5,8 @@ "js_module": "test_module.js", "js_function": "test_module", "forwarding_required": "sometimes", - "redirection_strategy": "none", "authn_policies": ["user_cert"], - "mode": "readonly", - "openapi": {} + "mode": "readonly" } } } diff --git a/tests/js-modules/modules.py b/tests/js-modules/modules.py index d9b5f39a9379..0ad389239127 100644 --- a/tests/js-modules/modules.py +++ b/tests/js-modules/modules.py @@ -69,6 +69,20 @@ def compare_app_metadata(expected, actual, api_key_renames, route=[]): ), f"Mismatch at {path}, expected {expected} and found {actual}" +def canonicalise(orig, renames): + if isinstance(orig, dict): + o = {} + for k, v in orig.items(): + if k in renames: + k = renames[k] + o[k] = canonicalise(v, renames) + return o + elif isinstance(orig, str) and orig in renames: + return renames[orig] + else: + return orig + + @reqs.description("Test module access") def test_module_access(network, args): primary, _ = network.find_nodes() @@ -98,16 +112,23 @@ def test_module_access(network, args): } with primary.api_versioned_client(api_version=args.gov_api_version) as c: + # The response with ?case=original should be almost exactly what was + # submitted (including exactly which fields are present/omitted). The + # only changes are the casing of HTTP verbs, and the prefixing of module + # names. r = c.get("/gov/service/javascript-app?case=original") assert r.status_code == http.HTTPStatus.OK, r.status_code - compare_app_metadata( + actual = r.body.json() + expected = canonicalise( expected_metadata, - r.body.json(), { **http_methods_renamed, **module_names_prefixed, }, ) + assert ( + expected == actual + ), f"{json.dumps(expected, indent=2)}\nvs\n{json.dumps(actual, indent=2)}" r = c.get("/gov/service/javascript-app") assert r.status_code == http.HTTPStatus.OK, r.status_code