From 6f7df55e740b807a985af26a35b45260ae126044 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Wed, 24 Jun 2020 18:28:17 +0100 Subject: [PATCH 01/53] Add to_upper and to_lower to nonstd.h --- src/ds/nonstd.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/ds/nonstd.h b/src/ds/nonstd.h index d44a1c59522..8f6ab93c4ae 100644 --- a/src/ds/nonstd.h +++ b/src/ds/nonstd.h @@ -3,6 +3,8 @@ #pragma once #include +#include +#include #include /** @@ -56,4 +58,20 @@ namespace nonstd template using remove_cvref_t = typename remove_cvref::type; + + /** converts strings to upper or lower case, in-place + */ + void to_upper(std::string& s) + { + std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { + return std::toupper(c); + }); + } + + void to_lower(std::string& s) + { + std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { + return std::tolower(c); + }); + } } \ No newline at end of file From af0ef44fcfa418c33d273001c3a903afd358b2e0 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Wed, 24 Jun 2020 18:46:27 +0100 Subject: [PATCH 02/53] Use nonstd::to_lower --- src/ds/nonstd.h | 5 +++-- src/http/http_builder.h | 4 +--- src/http/http_parser.h | 4 +--- src/http/http_sig.h | 5 +---- src/http/test/http_test.cpp | 4 +--- src/node/rpc/common_endpoint_registry.h | 6 +----- 6 files changed, 8 insertions(+), 20 deletions(-) diff --git a/src/ds/nonstd.h b/src/ds/nonstd.h index 8f6ab93c4ae..17639f671d2 100644 --- a/src/ds/nonstd.h +++ b/src/ds/nonstd.h @@ -2,6 +2,7 @@ // Licensed under the Apache 2.0 License. #pragma once +#include #include #include #include @@ -61,14 +62,14 @@ namespace nonstd /** converts strings to upper or lower case, in-place */ - void to_upper(std::string& s) + static void to_upper(std::string& s) { std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::toupper(c); }); } - void to_lower(std::string& s) + static void to_lower(std::string& s) { std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); diff --git a/src/http/http_builder.h b/src/http/http_builder.h index d1e6aa45f6d..18bbbd60a87 100644 --- a/src/http/http_builder.h +++ b/src/http/http_builder.h @@ -59,9 +59,7 @@ namespace http void set_header(std::string k, const std::string& v) { // Store all headers lower-cased to simplify case-insensitive lookup - std::transform(k.begin(), k.end(), k.begin(), [](unsigned char c) { - return std::tolower(c); - }); + nonstd::to_lower(k); headers[k] = v; } diff --git a/src/http/http_parser.h b/src/http/http_parser.h index b6c53e0d6bd..2682eec9a82 100644 --- a/src/http/http_parser.h +++ b/src/http/http_parser.h @@ -277,9 +277,7 @@ namespace http // HTTP headers are stored lowercase as it is easier to verify HTTP // signatures later on auto f = std::string(at, length); - std::transform(f.begin(), f.end(), f.begin(), [](unsigned char c) { - return std::tolower(c); - }); + nonstd::to_lower(f); partial_parsed_header.first.append(f); } diff --git a/src/http/http_sig.h b/src/http/http_sig.h index 5cc91ec9176..1c19014f2c8 100644 --- a/src/http/http_sig.h +++ b/src/http/http_sig.h @@ -33,10 +33,7 @@ namespace http if (f == auth::SIGN_HEADER_REQUEST_TARGET) { // Store verb as lowercase - std::transform( - verb.begin(), verb.end(), verb.begin(), [](unsigned char c) { - return std::tolower(c); - }); + nonstd::to_lower(verb); value = fmt::format("{} {}", verb, path); if (!query.empty()) { diff --git a/src/http/test/http_test.cpp b/src/http/test/http_test.cpp index 3fd74554a59..cd314befa42 100644 --- a/src/http/test/http_test.cpp +++ b/src/http/test/http_test.cpp @@ -22,9 +22,7 @@ std::vector s_to_v(char const* s) std::string to_lowercase(std::string s) { - std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { - return std::tolower(c); - }); + nonstd::to_lower(s); return s; } diff --git a/src/node/rpc/common_endpoint_registry.h b/src/node/rpc/common_endpoint_registry.h index bcad8c30012..f1ce913e8ad 100644 --- a/src/node/rpc/common_endpoint_registry.h +++ b/src/node/rpc/common_endpoint_registry.h @@ -248,11 +248,7 @@ namespace ccf for (auto& [verb, endpoint] : it->second) { std::string verb_name = http_method_str(verb); - std::transform( - verb_name.begin(), - verb_name.end(), - verb_name.begin(), - [](unsigned char c) { return std::tolower(c); }); + nonstd::to_lower(verb_name); j[verb_name] = GetSchema::Out{endpoint.params_schema, endpoint.result_schema}; } From 78e5e787707bb1e487afc44856018003547b9801 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Wed, 24 Jun 2020 18:46:44 +0100 Subject: [PATCH 03/53] WIP: Add types for OpenAPI doc --- CMakeLists.txt | 5 ++ src/ds/openapi_schema.h | 116 +++++++++++++++++++++++++++++++++ src/ds/test/openapi_schema.cpp | 39 +++++++++++ 3 files changed, 160 insertions(+) create mode 100644 src/ds/openapi_schema.h create mode 100644 src/ds/test/openapi_schema.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b6b1935223..7559b5d78ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -240,6 +240,11 @@ if(BUILD_TESTS) json_schema ${CMAKE_CURRENT_SOURCE_DIR}/src/ds/test/json_schema.cpp ) + add_unit_test( + openapi_schema ${CMAKE_CURRENT_SOURCE_DIR}/src/ds/test/openapi_schema.cpp + ) + target_link_libraries(openapi_schema PRIVATE http_parser.host) + add_unit_test( logger_json_test ${CMAKE_CURRENT_SOURCE_DIR}/src/ds/test/logger_json_test.cpp diff --git a/src/ds/openapi_schema.h b/src/ds/openapi_schema.h new file mode 100644 index 00000000000..4775015e170 --- /dev/null +++ b/src/ds/openapi_schema.h @@ -0,0 +1,116 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the Apache 2.0 License. +#pragma once + +#include "ds/json.h" +#include "ds/nonstd.h" + +#include +#include +#include + +namespace ds +{ + /** + * These structs contain the required fields to build the corresponding + * OpenAPI objects. They do not contain every field, but should be trivially + * extensible with any which are desired. + */ + namespace openapi + { + struct Info + { + std::string title; + std::string description; + std::string version; + }; + DECLARE_JSON_TYPE(Info); + DECLARE_JSON_REQUIRED_FIELDS(Info, title, description, version); + + struct Server + { + std::string url; + + bool operator==(const Server& rhs) const + { + return url == rhs.url; + } + }; + DECLARE_JSON_TYPE(Server); + DECLARE_JSON_REQUIRED_FIELDS(Server, url); + + struct Response + { + std::string description; + }; + DECLARE_JSON_TYPE(Response); + DECLARE_JSON_REQUIRED_FIELDS(Response, description); + + // Keys are really 'default' or a HTTP status code, but this is a quick + // approximation + using Responses = std::map; + + struct Operation + { + Responses responses; + }; + DECLARE_JSON_TYPE(Operation); + DECLARE_JSON_REQUIRED_FIELDS(Operation, responses); + + struct PathItem + { + std::map operations; + }; + + inline void to_json(nlohmann::json& j, const PathItem& pi) + { + j = nlohmann::json::object(); + for (const auto method : {HTTP_GET, HTTP_PUT, HTTP_POST, HTTP_DELETE}) + { + const auto it = pi.operations.find(method); + if (it != pi.operations.end()) + { + std::string method_s = http_method_str(method); + nonstd::to_lower(method_s); + j[method_s] = it->second; + } + } + } + + // TODO: This is a duplicate + static http_method http_method_from_str(const char* s) + { +#define XX(num, name, string) \ + if (strcmp(s, #string) == 0) \ + { \ + return http_method(num); \ + } + HTTP_METHOD_MAP(XX) +#undef XX + + throw std::logic_error(fmt::format("Unknown HTTP method '{}'", s)); + } + + inline void from_json(const nlohmann::json& j, PathItem& pi) + { + for (auto it = j.begin(); it != j.end(); ++it) + { + const auto method = http_method_from_str(it.key().c_str()); + pi.operations[method] = it.value(); + } + } + + using Paths = std::map; + + struct Document + { + std::string openapi = "3.0.0"; + Info info; + std::vector servers; + Paths paths; + }; + DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(Document); + DECLARE_JSON_REQUIRED_FIELDS(Document, openapi, info, paths); + DECLARE_JSON_OPTIONAL_FIELDS(Document, servers); + } +} diff --git a/src/ds/test/openapi_schema.cpp b/src/ds/test/openapi_schema.cpp new file mode 100644 index 00000000000..590f5c1eed1 --- /dev/null +++ b/src/ds/test/openapi_schema.cpp @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the Apache 2.0 License. +#include "ds/openapi_schema.h" + +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include + +void print_doc(const std::string& title, const nlohmann::json& doc) +{ + std::cout << title << std::endl; + std::cout << doc.dump(2) << std::endl; +} + +TEST_CASE("Basic doc") +{ + using namespace ds; + openapi::Document doc; + doc.info.title = "Test generated API"; + doc.info.description = "Some longer description enhance with **Markdown**"; + doc.info.version = "0.1.42"; + + print_doc("INITIAL", doc); + + { + openapi::Server mockup_server; + mockup_server.url = + "https://virtserver.swaggerhub.com/eddyashton/ccf-test/1.0.0"; + doc.servers.push_back(mockup_server); + } + print_doc("SERVERS", doc); + + { + doc.paths["/users/foo"] + .operations[HTTP_GET] + .responses[std::to_string(HTTP_STATUS_OK)] + .description = "Indicates that everything went ok"; + } + print_doc("PATHS", doc); +} \ No newline at end of file From 2f1a9658d7e8e951b0865ae1e3e5804f95f93bac Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Thu, 25 Jun 2020 12:00:42 +0100 Subject: [PATCH 04/53] WIP: "api" returns openapi, not method list --- src/apps/js_generic/js_generic.cpp | 17 ++++++++-------- src/apps/lua_generic/lua_generic.cpp | 23 +++++++++++----------- src/ds/test/openapi_schema.cpp | 5 +---- src/node/rpc/call_types.h | 8 +++----- src/node/rpc/common_endpoint_registry.h | 22 ++++++++++----------- src/node/rpc/endpoint_registry.h | 26 ++++++++++++++++--------- src/node/rpc/member_frontend.h | 5 ++++- src/node/rpc/node_frontend.h | 3 ++- src/node/rpc/serialization.h | 3 +-- src/node/rpc/test/frontend_test.cpp | 2 +- src/node/rpc/user_frontend.h | 5 +++-- tests/schema.py | 1 + 12 files changed, 64 insertions(+), 56 deletions(-) diff --git a/src/apps/js_generic/js_generic.cpp b/src/apps/js_generic/js_generic.cpp index b954a2d8023..3ba4d38acc8 100644 --- a/src/apps/js_generic/js_generic.cpp +++ b/src/apps/js_generic/js_generic.cpp @@ -285,15 +285,16 @@ namespace ccfapp // Since we do our own dispatch within the default handler, report the // supported methods here - void list_methods(kv::Tx& tx, ListMethods::Out& out) override + void build_api(ds::openapi::Document& document, kv::Tx& tx) override { - UserEndpointRegistry::list_methods(tx, out); - - auto scripts = tx.get_view(this->network.app_scripts); - scripts->foreach([&out](const auto& key, const auto&) { - out.methods.push_back(key); - return true; - }); + UserEndpointRegistry::build_api(document, tx); + + // TODO + // auto scripts = tx.get_view(this->network.app_scripts); + // scripts->foreach([&out](const auto& key, const auto&) { + // out.methods.push_back(key); + // return true; + // }); } }; diff --git a/src/apps/lua_generic/lua_generic.cpp b/src/apps/lua_generic/lua_generic.cpp index d85d5154206..a8d05a25c37 100644 --- a/src/apps/lua_generic/lua_generic.cpp +++ b/src/apps/lua_generic/lua_generic.cpp @@ -189,18 +189,19 @@ namespace ccfapp // Since we do our own dispatch within the default handler, report the // supported methods here - void list_methods(kv::Tx& tx, ListMethods::Out& out) override + void build_api(ds::openapi::Document& document, kv::Tx& tx) override { - UserEndpointRegistry::list_methods(tx, out); - - auto scripts = tx.get_view(this->network.app_scripts); - scripts->foreach([&out](const auto& key, const auto&) { - if (key != UserScriptIds::ENV_HANDLER) - { - out.methods.push_back(key); - } - return true; - }); + UserEndpointRegistry::build_api(document, tx); + + // TODO + // auto scripts = tx.get_view(this->network.app_scripts); + // scripts->foreach([&out](const auto& key, const auto&) { + // if (key != UserScriptIds::ENV_HANDLER) + // { + // out.methods.push_back(key); + // } + // return true; + // }); } }; diff --git a/src/ds/test/openapi_schema.cpp b/src/ds/test/openapi_schema.cpp index 590f5c1eed1..2fa0a1d7007 100644 --- a/src/ds/test/openapi_schema.cpp +++ b/src/ds/test/openapi_schema.cpp @@ -16,18 +16,15 @@ TEST_CASE("Basic doc") using namespace ds; openapi::Document doc; doc.info.title = "Test generated API"; - doc.info.description = "Some longer description enhance with **Markdown**"; + doc.info.description = "Some longer description enhanced with **Markdown**"; doc.info.version = "0.1.42"; - print_doc("INITIAL", doc); - { openapi::Server mockup_server; mockup_server.url = "https://virtserver.swaggerhub.com/eddyashton/ccf-test/1.0.0"; doc.servers.push_back(mockup_server); } - print_doc("SERVERS", doc); { doc.paths["/users/foo"] diff --git a/src/node/rpc/call_types.h b/src/node/rpc/call_types.h index 59580e3a4a2..971355f3579 100644 --- a/src/node/rpc/call_types.h +++ b/src/node/rpc/call_types.h @@ -117,12 +117,10 @@ namespace ccf using Out = CallerInfo; }; - struct ListMethods + struct GetAPI { - struct Out - { - std::vector methods; - }; + // TODO: This is a ds::openapi::Document? + using Out = nlohmann::json; }; struct GetSchema diff --git a/src/node/rpc/common_endpoint_registry.h b/src/node/rpc/common_endpoint_registry.h index f1ce913e8ad..a2591f81f44 100644 --- a/src/node/rpc/common_endpoint_registry.h +++ b/src/node/rpc/common_endpoint_registry.h @@ -24,8 +24,10 @@ namespace ccf public: CommonEndpointRegistry( - kv::Store& store, const std::string& certs_table_name = "") : - EndpointRegistry(store, certs_table_name), + const std::string& method_prefix_, + kv::Store& store, + const std::string& certs_table_name = "") : + EndpointRegistry(method_prefix_, store, certs_table_name), nodes(store.get(Tables::NODES)), tables(&store) {} @@ -219,17 +221,13 @@ namespace ccf .set_auto_schema() .install(); - auto list_methods_fn = [this](kv::Tx& tx, nlohmann::json&& params) { - ListMethods::Out out; - - list_methods(tx, out); - - std::sort(out.methods.begin(), out.methods.end()); - - return make_success(out); + auto openapi = [this](kv::Tx& tx, nlohmann::json&& params) { + ds::openapi::Document document; + build_api(document, tx); + return make_success(document); }; - make_endpoint("api", HTTP_GET, json_adapter(list_methods_fn)) - .set_auto_schema() + make_endpoint("api", HTTP_GET, json_adapter(openapi)) + .set_auto_schema() .install(); auto get_schema = [this](auto& args, nlohmann::json&& params) { diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index 0ce42b21075..d7974b6c168 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -4,6 +4,7 @@ #include "ds/ccf_deprecated.h" #include "ds/json_schema.h" +#include "ds/openapi_schema.h" #include "enclave/rpc_context.h" #include "http/http_consts.h" #include "kv/store.h" @@ -68,6 +69,8 @@ namespace ccf Write }; + const std::string method_prefix; + /** An Endpoint represents a user-defined resource that can be invoked by * authorised users via HTTP requests, over TLS. An Endpoint is accessible * at a specific verb and URI, e.g. POST /app/accounts or GET /app/records. @@ -305,7 +308,10 @@ namespace ccf public: EndpointRegistry( - kv::Store& tables, const std::string& certs_table_name = "") + const std::string& method_prefix_, + kv::Store& tables, + const std::string& certs_table_name = "") : + method_prefix(method_prefix_) { if (!certs_table_name.empty()) { @@ -432,17 +438,19 @@ namespace ccf return default_handler.value(); } - /** Populate out with all supported methods - * - * This is virtual since the default endpoint may do its own dispatch - * internally, so derived implementations must be able to populate the list - * with the supported methods however it constructs them. - */ - virtual void list_methods(kv::Tx& tx, ListMethods::Out& out) + // TODO: May want the entire rpc context, not just tx? + virtual void build_api(ds::openapi::Document& document, kv::Tx& tx) { for (const auto& [method, verb_handlers] : installed_handlers) { - out.methods.push_back(method); + const auto full_path = fmt::format("/{}/{}", method_prefix, method); + auto& path_object = document.paths[full_path]; + for (const auto& [verb, handler] : verb_handlers) + { + path_object.operations[verb] + .responses[std::to_string(HTTP_STATUS_OK)] + .description = "Auto-generated"; + } } } diff --git a/src/node/rpc/member_frontend.h b/src/node/rpc/member_frontend.h index eb62a4bb542..65332f125cf 100644 --- a/src/node/rpc/member_frontend.h +++ b/src/node/rpc/member_frontend.h @@ -549,7 +549,10 @@ namespace ccf NetworkTables& network, AbstractNodeState& node, ShareManager& share_manager) : - CommonEndpointRegistry(*network.tables, Tables::MEMBER_CERTS), + CommonEndpointRegistry( + get_actor_prefix(ActorsType::members), + *network.tables, + Tables::MEMBER_CERTS), network(network), node(node), share_manager(share_manager), diff --git a/src/node/rpc/node_frontend.h b/src/node/rpc/node_frontend.h index c922dadf819..733febdf1fb 100644 --- a/src/node/rpc/node_frontend.h +++ b/src/node/rpc/node_frontend.h @@ -138,7 +138,8 @@ namespace ccf public: NodeEndpoints(NetworkState& network, AbstractNodeState& node) : - CommonEndpointRegistry(*network.tables), + CommonEndpointRegistry( + get_actor_prefix(ActorsType::nodes), *network.tables), network(network), node(node) {} diff --git a/src/node/rpc/serialization.h b/src/node/rpc/serialization.h index 7bc80cd7731..06bd604dcd5 100644 --- a/src/node/rpc/serialization.h +++ b/src/node/rpc/serialization.h @@ -108,8 +108,7 @@ namespace ccf DECLARE_JSON_TYPE(GetUserId::In) DECLARE_JSON_REQUIRED_FIELDS(GetUserId::In, cert) - DECLARE_JSON_TYPE(ListMethods::Out) - DECLARE_JSON_REQUIRED_FIELDS(ListMethods::Out, methods) + DECLARE_JSON_TYPE(GetAPI::Out) DECLARE_JSON_TYPE(GetSchema::In) DECLARE_JSON_REQUIRED_FIELDS(GetSchema::In, method) diff --git a/src/node/rpc/test/frontend_test.cpp b/src/node/rpc/test/frontend_test.cpp index 4a964acec1a..010c02cc1b7 100644 --- a/src/node/rpc/test/frontend_test.cpp +++ b/src/node/rpc/test/frontend_test.cpp @@ -224,7 +224,7 @@ class TestNoCertsFrontend : public RpcFrontend public: TestNoCertsFrontend(kv::Store& tables) : RpcFrontend(tables, endpoints), - endpoints(tables) + endpoints("test", tables) { open(); diff --git a/src/node/rpc/user_frontend.h b/src/node/rpc/user_frontend.h index 3aa59448a42..f06b3fb05f9 100644 --- a/src/node/rpc/user_frontend.h +++ b/src/node/rpc/user_frontend.h @@ -81,11 +81,12 @@ namespace ccf { public: UserEndpointRegistry(kv::Store& store) : - CommonEndpointRegistry(store, Tables::USER_CERTS) + CommonEndpointRegistry( + get_actor_prefix(ActorsType::users), store, Tables::USER_CERTS) {} UserEndpointRegistry(NetworkTables& network) : - CommonEndpointRegistry(*network.tables, Tables::USER_CERTS) + UserEndpointRegistry(*network.tables) {} }; diff --git a/tests/schema.py b/tests/schema.py index 4abe07b255d..028a78d3612 100644 --- a/tests/schema.py +++ b/tests/schema.py @@ -33,6 +33,7 @@ def fetch_schema(client): check( list_response, error=lambda status, msg: status == http.HTTPStatus.OK.value ) + LOG.warning(list_response) methods = list_response.result["methods"] for method in methods: From 1510aafd1827cb2b9ce5cf118f10a2c1e705d650 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Thu, 25 Jun 2020 13:41:51 +0100 Subject: [PATCH 05/53] Prefer openapi to openapi_schema --- CMakeLists.txt | 4 ++-- src/ds/{openapi_schema.h => openapi.h} | 0 src/ds/test/{openapi_schema.cpp => openapi.cpp} | 2 +- src/node/rpc/endpoint_registry.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename src/ds/{openapi_schema.h => openapi.h} (100%) rename src/ds/test/{openapi_schema.cpp => openapi.cpp} (96%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7559b5d78ee..c8589118227 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -241,9 +241,9 @@ if(BUILD_TESTS) ) add_unit_test( - openapi_schema ${CMAKE_CURRENT_SOURCE_DIR}/src/ds/test/openapi_schema.cpp + openapi ${CMAKE_CURRENT_SOURCE_DIR}/src/ds/test/openapi.cpp ) - target_link_libraries(openapi_schema PRIVATE http_parser.host) + target_link_libraries(openapi PRIVATE http_parser.host) add_unit_test( logger_json_test diff --git a/src/ds/openapi_schema.h b/src/ds/openapi.h similarity index 100% rename from src/ds/openapi_schema.h rename to src/ds/openapi.h diff --git a/src/ds/test/openapi_schema.cpp b/src/ds/test/openapi.cpp similarity index 96% rename from src/ds/test/openapi_schema.cpp rename to src/ds/test/openapi.cpp index 2fa0a1d7007..2904bb4f43b 100644 --- a/src/ds/test/openapi_schema.cpp +++ b/src/ds/test/openapi.cpp @@ -1,6 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the Apache 2.0 License. -#include "ds/openapi_schema.h" +#include "ds/openapi.h" #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index d7974b6c168..5967676bc31 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -4,7 +4,7 @@ #include "ds/ccf_deprecated.h" #include "ds/json_schema.h" -#include "ds/openapi_schema.h" +#include "ds/openapi.h" #include "enclave/rpc_context.h" #include "http/http_consts.h" #include "kv/store.h" From fb3466ae52df807125aeced037358db3dc6cdefe Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Thu, 25 Jun 2020 14:36:17 +0100 Subject: [PATCH 06/53] WIP: Maybe a deadend... --- src/ds/openapi.h | 109 +++++++++++++++++++++---------- src/ds/test/openapi.cpp | 2 +- src/node/rpc/endpoint_registry.h | 2 +- 3 files changed, 76 insertions(+), 37 deletions(-) diff --git a/src/ds/openapi.h b/src/ds/openapi.h index 4775015e170..010a0076800 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -46,59 +46,98 @@ namespace ds DECLARE_JSON_TYPE(Response); DECLARE_JSON_REQUIRED_FIELDS(Response, description); - // Keys are really 'default' or a HTTP status code, but this is a quick - // approximation - using Responses = std::map; + inline void to_json(nlohmann::json& j, const http_status& status) + { + j = std::to_string(status); + } + + inline void from_json(const nlohmann::json& j, http_status& status) + { + const auto s = j.get(); + +#define XX(num, name, string) \ + if (s == #num) \ + { \ + status = HTTP_STATUS_##name; \ + } \ + else + + HTTP_STATUS_MAP(XX) + // else + { + throw std::runtime_error( + fmt::format("Unrecognsied key in OpenAPI Responses Object: {}", s)); + } +#undef XX + } + + inline void fill_enum_schema(nlohmann::json& j, const http_status&) + { + auto enums = nlohmann::json::array(); + +#define XX(num, name, string) enums.push_back(std::to_string(num)); + HTTP_STATUS_MAP(XX); +#undef XX + + j["enum"] = enums; + } struct Operation { - Responses responses; + std::map responses; }; DECLARE_JSON_TYPE(Operation); DECLARE_JSON_REQUIRED_FIELDS(Operation, responses); - struct PathItem + inline void to_json(nlohmann::json& j, const http_method& verb) { - std::map operations; - }; + std::string verb_s = http_method_str(verb); + nonstd::to_lower(verb_s); + j = verb_s; + } - inline void to_json(nlohmann::json& j, const PathItem& pi) + inline void from_json(const nlohmann::json& j, http_method& verb) { - j = nlohmann::json::object(); - for (const auto method : {HTTP_GET, HTTP_PUT, HTTP_POST, HTTP_DELETE}) + const auto s = j.get(); + if (s == "get") + { + verb = HTTP_GET; + } + else if (s == "put") + { + verb = HTTP_PUT; + } + else if (s == "post") { - const auto it = pi.operations.find(method); - if (it != pi.operations.end()) - { - std::string method_s = http_method_str(method); - nonstd::to_lower(method_s); - j[method_s] = it->second; - } + verb = HTTP_POST; + } + else if (s == "delete") + { + verb = HTTP_DELETE; + } + else + { + throw std::runtime_error( + fmt::format("Unexpected key in OpenAPI Path Item: {}", s)); } } - // TODO: This is a duplicate - static http_method http_method_from_str(const char* s) + inline void fill_enum_schema(nlohmann::json& j, const http_method&) { -#define XX(num, name, string) \ - if (strcmp(s, #string) == 0) \ - { \ - return http_method(num); \ - } - HTTP_METHOD_MAP(XX) -#undef XX - - throw std::logic_error(fmt::format("Unknown HTTP method '{}'", s)); + auto enums = nlohmann::json::array(); + enums.push_back("get"); + enums.push_back("put"); + enums.push_back("post"); + enums.push_back("delete"); + j["enum"] = enums; } - inline void from_json(const nlohmann::json& j, PathItem& pi) + struct PathItem { - for (auto it = j.begin(); it != j.end(); ++it) - { - const auto method = http_method_from_str(it.key().c_str()); - pi.operations[method] = it.value(); - } - } + std::map operations; + }; + DECLARE_JSON_TYPE(PathItem); + DECLARE_JSON_REQUIRED_FIELDS(PathItem, operations); using Paths = std::map; diff --git a/src/ds/test/openapi.cpp b/src/ds/test/openapi.cpp index 2904bb4f43b..2e12b34e339 100644 --- a/src/ds/test/openapi.cpp +++ b/src/ds/test/openapi.cpp @@ -29,7 +29,7 @@ TEST_CASE("Basic doc") { doc.paths["/users/foo"] .operations[HTTP_GET] - .responses[std::to_string(HTTP_STATUS_OK)] + .responses[HTTP_STATUS_OK] .description = "Indicates that everything went ok"; } print_doc("PATHS", doc); diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index 5967676bc31..535ae56f84f 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -448,7 +448,7 @@ namespace ccf for (const auto& [verb, handler] : verb_handlers) { path_object.operations[verb] - .responses[std::to_string(HTTP_STATUS_OK)] + .responses[HTTP_STATUS_OK] .description = "Auto-generated"; } } From ed846b7ec5857904e72326eeff6961267acd2bf3 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Thu, 25 Jun 2020 14:45:30 +0100 Subject: [PATCH 07/53] WIP: 3 cheers for operator[] --- src/ds/openapi.h | 90 +++++--------------------------- src/ds/test/openapi.cpp | 6 +-- src/node/rpc/endpoint_registry.h | 4 +- 3 files changed, 16 insertions(+), 84 deletions(-) diff --git a/src/ds/openapi.h b/src/ds/openapi.h index 010a0076800..ae2daa2bc8b 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -46,95 +46,31 @@ namespace ds DECLARE_JSON_TYPE(Response); DECLARE_JSON_REQUIRED_FIELDS(Response, description); - inline void to_json(nlohmann::json& j, const http_status& status) - { - j = std::to_string(status); - } - - inline void from_json(const nlohmann::json& j, http_status& status) + struct Operation { - const auto s = j.get(); - -#define XX(num, name, string) \ - if (s == #num) \ - { \ - status = HTTP_STATUS_##name; \ - } \ - else + std::map responses; - HTTP_STATUS_MAP(XX) - // else + Response& operator[](http_status status) { - throw std::runtime_error( - fmt::format("Unrecognsied key in OpenAPI Responses Object: {}", s)); + // HTTP_STATUS_OK (aka an int with value 200) becomes the string "200" + const auto s = std::to_string(status); + return responses[s]; } -#undef XX - } - - inline void fill_enum_schema(nlohmann::json& j, const http_status&) - { - auto enums = nlohmann::json::array(); - -#define XX(num, name, string) enums.push_back(std::to_string(num)); - HTTP_STATUS_MAP(XX); -#undef XX - - j["enum"] = enums; - } - - struct Operation - { - std::map responses; }; DECLARE_JSON_TYPE(Operation); DECLARE_JSON_REQUIRED_FIELDS(Operation, responses); - inline void to_json(nlohmann::json& j, const http_method& verb) + struct PathItem { - std::string verb_s = http_method_str(verb); - nonstd::to_lower(verb_s); - j = verb_s; - } + std::map operations; - inline void from_json(const nlohmann::json& j, http_method& verb) - { - const auto s = j.get(); - if (s == "get") + Operation& operator[](http_method verb) { - verb = HTTP_GET; + // HTTP_GET becomes the string "get" + std::string s = http_method_str(verb); + nonstd::to_lower(s); + return operations[s]; } - else if (s == "put") - { - verb = HTTP_PUT; - } - else if (s == "post") - { - verb = HTTP_POST; - } - else if (s == "delete") - { - verb = HTTP_DELETE; - } - else - { - throw std::runtime_error( - fmt::format("Unexpected key in OpenAPI Path Item: {}", s)); - } - } - - inline void fill_enum_schema(nlohmann::json& j, const http_method&) - { - auto enums = nlohmann::json::array(); - enums.push_back("get"); - enums.push_back("put"); - enums.push_back("post"); - enums.push_back("delete"); - j["enum"] = enums; - } - - struct PathItem - { - std::map operations; }; DECLARE_JSON_TYPE(PathItem); DECLARE_JSON_REQUIRED_FIELDS(PathItem, operations); diff --git a/src/ds/test/openapi.cpp b/src/ds/test/openapi.cpp index 2e12b34e339..ac890696c7e 100644 --- a/src/ds/test/openapi.cpp +++ b/src/ds/test/openapi.cpp @@ -27,10 +27,8 @@ TEST_CASE("Basic doc") } { - doc.paths["/users/foo"] - .operations[HTTP_GET] - .responses[HTTP_STATUS_OK] - .description = "Indicates that everything went ok"; + doc.paths["/users/foo"][HTTP_GET][HTTP_STATUS_OK].description = + "Indicates that everything went ok"; } print_doc("PATHS", doc); } \ No newline at end of file diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index 535ae56f84f..a3a01af7f17 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -447,9 +447,7 @@ namespace ccf auto& path_object = document.paths[full_path]; for (const auto& [verb, handler] : verb_handlers) { - path_object.operations[verb] - .responses[HTTP_STATUS_OK] - .description = "Auto-generated"; + path_object[verb][HTTP_STATUS_OK].description = "Auto-generated"; } } } From 32b9d465eac04d0377292d4645287a5e968733d0 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Thu, 25 Jun 2020 15:34:10 +0100 Subject: [PATCH 08/53] Is this what a helpful modifier looks like? --- src/ds/openapi.h | 68 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/src/ds/openapi.h b/src/ds/openapi.h index ae2daa2bc8b..a7494f2b2e6 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -39,12 +39,29 @@ namespace ds DECLARE_JSON_TYPE(Server); DECLARE_JSON_REQUIRED_FIELDS(Server, url); + struct MediaType + { + // May be a full in-place schema, but is generally a string containing a + // reference to a schema stored elsewhere + nlohmann::json schema; + + bool operator==(const MediaType& rhs) const + { + return schema == rhs.schema; + } + }; + DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(MediaType); + DECLARE_JSON_REQUIRED_FIELDS(MediaType); + DECLARE_JSON_OPTIONAL_FIELDS(MediaType, schema); + struct Response { std::string description; + std::map content; }; - DECLARE_JSON_TYPE(Response); + DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(Response); DECLARE_JSON_REQUIRED_FIELDS(Response, description); + DECLARE_JSON_OPTIONAL_FIELDS(Response, content); struct Operation { @@ -77,15 +94,62 @@ namespace ds using Paths = std::map; + struct Components + { + std::map schemas; + + bool operator!=(const Components& rhs) const + { + return schemas != rhs.schemas; + } + }; + DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(Components); + DECLARE_JSON_REQUIRED_FIELDS(Components); + DECLARE_JSON_OPTIONAL_FIELDS(Components, schemas); + struct Document { std::string openapi = "3.0.0"; Info info; std::vector servers; Paths paths; + Components components; + + void add_response_schema( + const std::string& uri, + http_method verb, + http_status status, + const std::string& content_type, + const nlohmann::json& schema, + const std::string& components_schema_name) + { + const auto schema_it = components.schemas.find(components_schema_name); + if (schema_it != components.schemas.end()) + { + // Check that the existing schema matches the new one being added with + // the same name + const auto& existing_schema = schema_it->second; + if (schema != existing_schema) + { + throw std::logic_error(fmt::format( + "Adding schema with name '{}'. Does not match previous schema " + "registered with this name: {} vs {}", + components_schema_name, + schema.dump(), + existing_schema.dump())); + } + } + else + { + components.schemas.emplace(components_schema_name, schema); + } + + paths[uri][verb][status].content[content_type].schema = + fmt::format("#/components/schemas/{}", components_schema_name); + } }; DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(Document); DECLARE_JSON_REQUIRED_FIELDS(Document, openapi, info, paths); - DECLARE_JSON_OPTIONAL_FIELDS(Document, servers); + DECLARE_JSON_OPTIONAL_FIELDS(Document, servers, components); } } From 325a59ccc406c5fee01a3ed4c42ff106103b71ea Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Thu, 25 Jun 2020 16:42:29 +0100 Subject: [PATCH 09/53] WIP: Helper method for adding response schema --- src/ds/openapi.h | 49 ++++++++++++++++++++++--- src/ds/test/openapi.cpp | 80 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 120 insertions(+), 9 deletions(-) diff --git a/src/ds/openapi.h b/src/ds/openapi.h index a7494f2b2e6..2ae3e396753 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -41,8 +41,7 @@ namespace ds struct MediaType { - // May be a full in-place schema, but is generally a string containing a - // reference to a schema stored elsewhere + // May be a full in-place schema, but is generally a reference object nlohmann::json schema; bool operator==(const MediaType& rhs) const @@ -89,11 +88,31 @@ namespace ds return operations[s]; } }; - DECLARE_JSON_TYPE(PathItem); - DECLARE_JSON_REQUIRED_FIELDS(PathItem, operations); + + // When converted to JSON, a PathItem is not an object containing an + // 'operations' field with an object value, it _is_ this operations object + // value + inline void to_json(nlohmann::json& j, const PathItem& pi) + { + j = pi.operations; + } + + inline void from_json(const nlohmann::json& j, PathItem& pi) + { + pi.operations = j.get(); + } using Paths = std::map; + void check_path_valid(const std::string& s) + { + if (s.rfind("/", 0) != 0) + { + throw std::logic_error( + fmt::format("'{}' is not a valid path - must begin with '/'", s)); + } + } + struct Components { std::map schemas; @@ -123,6 +142,8 @@ namespace ds const nlohmann::json& schema, const std::string& components_schema_name) { + check_path_valid(uri); + const auto schema_it = components.schemas.find(components_schema_name); if (schema_it != components.schemas.end()) { @@ -144,8 +165,26 @@ namespace ds components.schemas.emplace(components_schema_name, schema); } - paths[uri][verb][status].content[content_type].schema = + auto& response_object = paths[uri][verb][status]; + response_object.description = "Auto-generated"; + auto schema_ref_object = nlohmann::json::object(); + schema_ref_object["$ref"] = fmt::format("#/components/schemas/{}", components_schema_name); + response_object.content[content_type].schema = schema_ref_object; + } + + template + void add_response_schema( + const std::string& uri, + http_method verb, + http_status status, + const std::string& content_type, + const std::string& components_schema_name) + { + auto t_schema = nlohmann::json::object(); + ds::json::fill_schema(t_schema); + add_response_schema( + uri, verb, status, content_type, t_schema, components_schema_name); } }; DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(Document); diff --git a/src/ds/test/openapi.cpp b/src/ds/test/openapi.cpp index ac890696c7e..42bdb2df722 100644 --- a/src/ds/test/openapi.cpp +++ b/src/ds/test/openapi.cpp @@ -2,18 +2,48 @@ // Licensed under the Apache 2.0 License. #include "ds/openapi.h" +#include "http/http_consts.h" + #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include +using namespace ds; + void print_doc(const std::string& title, const nlohmann::json& doc) { std::cout << title << std::endl; std::cout << doc.dump(2) << std::endl; } -TEST_CASE("Basic doc") +#define REQUIRE_ELEMENT(j, name, type_fn) \ + { \ + const auto name##_it = j.find(#name); \ + REQUIRE(name##_it != j.end()); \ + REQUIRE(name##_it->type_fn()); \ + } + +static constexpr auto server_url = + "https://not.a.real.server.example.com/testing_only"; + +// TODO: Use some external verifier to do this properly. This is the basic +// stuff for initial compatibility +void required_doc_elements(const nlohmann::json& j) +{ + REQUIRE_ELEMENT(j, openapi, is_string); + REQUIRE_ELEMENT(j, info, is_object); + REQUIRE_ELEMENT(j, paths, is_object); +} + +TEST_CASE("Required elements") +{ + openapi::Document doc; + + const nlohmann::json j = doc; + required_doc_elements(j); +} + +TEST_CASE("Manual construction") { - using namespace ds; openapi::Document doc; doc.info.title = "Test generated API"; doc.info.description = "Some longer description enhanced with **Markdown**"; @@ -21,8 +51,7 @@ TEST_CASE("Basic doc") { openapi::Server mockup_server; - mockup_server.url = - "https://virtserver.swaggerhub.com/eddyashton/ccf-test/1.0.0"; + mockup_server.url = server_url; doc.servers.push_back(mockup_server); } @@ -30,5 +59,48 @@ TEST_CASE("Basic doc") doc.paths["/users/foo"][HTTP_GET][HTTP_STATUS_OK].description = "Indicates that everything went ok"; } + + const nlohmann::json j = doc; + required_doc_elements(j); + + const auto& info_element = j["info"]; + REQUIRE_ELEMENT(info_element, title, is_string); + REQUIRE_ELEMENT(info_element, description, is_string); + REQUIRE_ELEMENT(info_element, version, is_string); + + REQUIRE_ELEMENT(j, servers, is_array); + const auto& servers_element = j["servers"]; + REQUIRE(servers_element.size() == 1); + const auto& first_server = servers_element[0]; + REQUIRE_ELEMENT(first_server, url, is_string); + print_doc("PATHS", doc); +} + +TEST_CASE("Schema population") +{ + openapi::Document doc; + doc.info.title = "Test generated API"; + doc.info.description = "Some longer description enhanced with **Markdown**"; + doc.info.version = "0.1.42"; + + { + openapi::Server mockup_server; + mockup_server.url = server_url; + doc.servers.push_back(mockup_server); + } + + constexpr auto users_foo = "/users/foo"; + constexpr auto foo_schema_name = "foo_str"; + doc.add_response_schema( + users_foo, + HTTP_GET, + HTTP_STATUS_OK, + http::headervalues::contenttype::TEXT, + foo_schema_name); + + const nlohmann::json j = doc; + required_doc_elements(j); + + print_doc("SCHEMA", doc); } \ No newline at end of file From 8ad27d2acf9b9db73c5bf783048a7116d41fc1ea Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 26 Jun 2020 13:50:17 +0100 Subject: [PATCH 10/53] Add schema_name to generate sensible components fieldname --- src/ds/json.h | 17 +++++--- src/ds/json_schema.h | 97 +++++++++++++++++++++++++++++++++++++++++ src/ds/openapi.h | 51 +++++++++++++--------- src/ds/test/openapi.cpp | 20 +++++---- 4 files changed, 152 insertions(+), 33 deletions(-) diff --git a/src/ds/json.h b/src/ds/json.h index 22a5a4bb3c4..c400f23625b 100644 --- a/src/ds/json.h +++ b/src/ds/json.h @@ -376,16 +376,19 @@ namespace std # FIELD \ } -/** Defines from_json, to_json, and fill_json_schema functions for struct/class - * types, converting member fields to JSON elements. Missing elements will cause - * errors to be raised. This assumes that from_json, to_json, and - * fill_json_schema are implemented for each member field type, either manually - * or through these macros. +/** Defines from_json, to_json, fill_json_schema, and schema_name functions for + * struct/class types, converting member fields to JSON elements. Missing + * elements will cause errors to be raised. This assumes that from_json, + * to_json, and fill_json_schema are implemented for each member field type, + * either manually or through these macros. + * // clang-format off * ie, the following must compile, for each foo in T: * T t; nlohmann::json j, schema; * j["foo"] = t.foo; * t.foo = j["foo"].get(); * fill_json_schema(schema, t); + * std::string s = schema_name(t.foo); + * // clang-format on * * To use: * - Declare struct as normal @@ -498,6 +501,10 @@ namespace std PRE_FILL_SCHEMA; \ fill_json_schema_required_fields(j, t); \ POST_FILL_SCHEMA; \ + } \ + inline std::string schema_name(const TYPE& t) \ + { \ + return #TYPE; \ } #define DECLARE_JSON_TYPE(TYPE) DECLARE_JSON_TYPE_IMPL(TYPE, , , , , , ) diff --git a/src/ds/json_schema.h b/src/ds/json_schema.h index ccefe2a14b1..3362b8496b6 100644 --- a/src/ds/json_schema.h +++ b/src/ds/json_schema.h @@ -4,6 +4,8 @@ #include "ds/nonstd.h" +#define FMT_HEADER_ONLY +#include #include namespace ds @@ -36,6 +38,9 @@ namespace ds schema["maximum"] = std::numeric_limits::max(); } + template + std::string schema_name(); + template void fill_schema(nlohmann::json& schema); @@ -52,6 +57,13 @@ namespace ds namespace adl { + template + std::string schema_name() + { + T t; + return schema_name(t); + } + template void fill_schema(nlohmann::json& schema) { @@ -67,6 +79,91 @@ namespace ds } } + template + inline std::string schema_name() + { + if constexpr (nonstd::is_specialization::value) + { + return schema_name(); + } + else if constexpr (nonstd::is_specialization::value) + { + return fmt::format("{}_array", schema_name()); + } + else if constexpr ( + nonstd::is_specialization::value || + nonstd::is_specialization::value) + { + return fmt::format( + "{}_to_{}", + schema_name(), + schema_name()); + } + else if constexpr (nonstd::is_specialization::value) + { + return fmt::format( + "{}_to_{}", + schema_name(), + schema_name()); + } + else if constexpr (std::is_same::value) + { + return "string"; + } + else if constexpr (std::is_same::value) + { + return "boolean"; + } + else if constexpr (std::is_same::value) + { + return "uint8"; + } + else if constexpr (std::is_same::value) + { + return "uint16"; + } + else if constexpr (std::is_same::value) + { + return "uint32"; + } + else if constexpr (std::is_same::value) + { + return "uint64"; + } + else if constexpr (std::is_same::value) + { + return "int8"; + } + else if constexpr (std::is_same::value) + { + return "int16"; + } + else if constexpr (std::is_same::value) + { + return "int32"; + } + else if constexpr (std::is_same::value) + { + return "int64"; + } + else if constexpr (std::is_same::value) + { + return "float"; + } + else if constexpr (std::is_same::value) + { + return "double"; + } + else if constexpr (std::is_same::value) + { + return "json"; + } + else + { + return adl::schema_name(); + } + } + template inline void fill_schema(nlohmann::json& schema) { diff --git a/src/ds/openapi.h b/src/ds/openapi.h index 2ae3e396753..877c6aec015 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -104,7 +104,7 @@ namespace ds using Paths = std::map; - void check_path_valid(const std::string& s) + inline void check_path_valid(const std::string& s) { if (s.rfind("/", 0) != 0) { @@ -134,17 +134,10 @@ namespace ds Paths paths; Components components; - void add_response_schema( - const std::string& uri, - http_method verb, - http_status status, - const std::string& content_type, - const nlohmann::json& schema, - const std::string& components_schema_name) + nlohmann::json add_schema_to_components( + const std::string& element_name, const nlohmann::json& schema) { - check_path_valid(uri); - - const auto schema_it = components.schemas.find(components_schema_name); + const auto schema_it = components.schemas.find(element_name); if (schema_it != components.schemas.end()) { // Check that the existing schema matches the new one being added with @@ -155,36 +148,54 @@ namespace ds throw std::logic_error(fmt::format( "Adding schema with name '{}'. Does not match previous schema " "registered with this name: {} vs {}", - components_schema_name, + element_name, schema.dump(), existing_schema.dump())); } } else { - components.schemas.emplace(components_schema_name, schema); + components.schemas.emplace(element_name, schema); } - auto& response_object = paths[uri][verb][status]; - response_object.description = "Auto-generated"; auto schema_ref_object = nlohmann::json::object(); schema_ref_object["$ref"] = - fmt::format("#/components/schemas/{}", components_schema_name); - response_object.content[content_type].schema = schema_ref_object; + fmt::format("#/components/schemas/{}", element_name); + return schema_ref_object; } - template void add_response_schema( const std::string& uri, http_method verb, http_status status, const std::string& content_type, - const std::string& components_schema_name) + const std::string& schema_name, + const nlohmann::json& schema) + { + check_path_valid(uri); + + auto& response_object = paths[uri][verb][status]; + response_object.description = "Auto-generated"; + response_object.content[content_type].schema = + add_schema_to_components(schema_name, schema); + } + + template + void add_response_schema( + const std::string& uri, + http_method verb, + http_status status, + const std::string& content_type) { auto t_schema = nlohmann::json::object(); ds::json::fill_schema(t_schema); add_response_schema( - uri, verb, status, content_type, t_schema, components_schema_name); + uri, + verb, + status, + content_type, + ds::json::schema_name(), + t_schema); } }; DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(Document); diff --git a/src/ds/test/openapi.cpp b/src/ds/test/openapi.cpp index 42bdb2df722..25e2d72cb96 100644 --- a/src/ds/test/openapi.cpp +++ b/src/ds/test/openapi.cpp @@ -77,6 +77,14 @@ TEST_CASE("Manual construction") print_doc("PATHS", doc); } +struct Foo +{ + size_t n; + std::string s; +}; +DECLARE_JSON_TYPE(Foo); +DECLARE_JSON_REQUIRED_FIELDS(Foo, n, s); + TEST_CASE("Schema population") { openapi::Document doc; @@ -90,14 +98,10 @@ TEST_CASE("Schema population") doc.servers.push_back(mockup_server); } - constexpr auto users_foo = "/users/foo"; - constexpr auto foo_schema_name = "foo_str"; - doc.add_response_schema( - users_foo, - HTTP_GET, - HTTP_STATUS_OK, - http::headervalues::contenttype::TEXT, - foo_schema_name); + doc.add_response_schema( + "/app/foo", HTTP_GET, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); + doc.add_response_schema>( + "/app/foos", HTTP_GET, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); const nlohmann::json j = doc; required_doc_elements(j); From bd1eb1581e1abac05442633e7819b41e8626e070 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 26 Jun 2020 14:12:23 +0100 Subject: [PATCH 11/53] WIP --- src/ds/json_schema.h | 3 +++ src/ds/test/openapi.cpp | 12 +++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/ds/json_schema.h b/src/ds/json_schema.h index 3362b8496b6..f0123024651 100644 --- a/src/ds/json_schema.h +++ b/src/ds/json_schema.h @@ -181,12 +181,15 @@ namespace ds nonstd::is_specialization::value) { // Nlohmann serialises maps to an array of (K, V) pairs + // TODO: Unless the keys are strings! schema["type"] = "array"; auto items = nlohmann::json::object(); { items["type"] = "array"; auto sub_items = nlohmann::json::array(); + // TODO: OpenAPI doesn't like this tuple for "items", even though its + // valid JSON schema. Maybe fixed in a newer spec version? sub_items.push_back(schema_element()); sub_items.push_back(schema_element()); items["items"] = sub_items; diff --git a/src/ds/test/openapi.cpp b/src/ds/test/openapi.cpp index 25e2d72cb96..0e117daf2db 100644 --- a/src/ds/test/openapi.cpp +++ b/src/ds/test/openapi.cpp @@ -99,9 +99,15 @@ TEST_CASE("Schema population") } doc.add_response_schema( - "/app/foo", HTTP_GET, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); - doc.add_response_schema>( - "/app/foos", HTTP_GET, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); + "/app/foo", + HTTP_GET, + HTTP_STATUS_OK, + http::headervalues::contenttype::JSON); + doc.add_response_schema>( + "/app/foos", + HTTP_GET, + HTTP_STATUS_OK, + http::headervalues::contenttype::JSON); const nlohmann::json j = doc; required_doc_elements(j); From 0ef295151bf66de3bc7d33842b4d9afbeed0aff5 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 26 Jun 2020 14:31:11 +0100 Subject: [PATCH 12/53] WIP: add_request_body_schema --- src/ds/json.h | 5 ++++ src/ds/openapi.h | 58 ++++++++++++++++++++++++++++++++++++++--- src/ds/test/openapi.cpp | 2 ++ 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/ds/json.h b/src/ds/json.h index c400f23625b..9f8dd62ce1f 100644 --- a/src/ds/json.h +++ b/src/ds/json.h @@ -390,6 +390,11 @@ namespace std * std::string s = schema_name(t.foo); * // clang-format on * + * Optional fields will be inserted into the JSON object iff their value differs + * from the value in a default-constructed instance of T. So if optional fields + * are present, then T must be default-constructible and the optional fields + * must be distinguishable (have operator!= defined) + * * To use: * - Declare struct as normal * - Add DELARE_JSON_TYPE, or WITH_BASE or WITH_OPTIONAL variants as required diff --git a/src/ds/openapi.h b/src/ds/openapi.h index 877c6aec015..8a29fa5d3d8 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -53,10 +53,33 @@ namespace ds DECLARE_JSON_REQUIRED_FIELDS(MediaType); DECLARE_JSON_OPTIONAL_FIELDS(MediaType, schema); + using ContentMap = std::map; + + struct RequestBody + { + std::string description; + ContentMap content; + bool required = false; + + bool operator==(const RequestBody& rhs) const + { + return description == rhs.description && content == rhs.content && + required == rhs.required; + } + + bool operator!=(const RequestBody& rhs) const + { + return !(*this == rhs); + } + }; + DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(RequestBody); + DECLARE_JSON_REQUIRED_FIELDS(RequestBody, content); + DECLARE_JSON_OPTIONAL_FIELDS(RequestBody, description, required); + struct Response { std::string description; - std::map content; + ContentMap content; }; DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(Response); DECLARE_JSON_REQUIRED_FIELDS(Response, description); @@ -64,6 +87,7 @@ namespace ds struct Operation { + RequestBody requestBody; std::map responses; Response& operator[](http_status status) @@ -73,8 +97,9 @@ namespace ds return responses[s]; } }; - DECLARE_JSON_TYPE(Operation); + DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(Operation); DECLARE_JSON_REQUIRED_FIELDS(Operation, responses); + DECLARE_JSON_OPTIONAL_FIELDS(Operation, requestBody); struct PathItem { @@ -164,6 +189,33 @@ namespace ds return schema_ref_object; } + void add_request_body_schema( + const std::string& uri, + http_method verb, + const std::string& content_type, + const std::string& schema_name, + const nlohmann::json& schema) + { + check_path_valid(uri); + + auto& request_body = paths[uri][verb].requestBody; + request_body.description = "Auto-generated request body schema"; + request_body.content[content_type].schema = + add_schema_to_components(schema_name, schema); + } + + template + void add_request_body_schema( + const std::string& uri, + http_method verb, + const std::string& content_type) + { + auto t_schema = nlohmann::json::object(); + ds::json::fill_schema(t_schema); + add_request_body_schema( + uri, verb, content_type, ds::json::schema_name(), t_schema); + } + void add_response_schema( const std::string& uri, http_method verb, @@ -175,7 +227,7 @@ namespace ds check_path_valid(uri); auto& response_object = paths[uri][verb][status]; - response_object.description = "Auto-generated"; + response_object.description = "Auto-generated response schema"; response_object.content[content_type].schema = add_schema_to_components(schema_name, schema); } diff --git a/src/ds/test/openapi.cpp b/src/ds/test/openapi.cpp index 0e117daf2db..fb693a1ae07 100644 --- a/src/ds/test/openapi.cpp +++ b/src/ds/test/openapi.cpp @@ -98,6 +98,8 @@ TEST_CASE("Schema population") doc.servers.push_back(mockup_server); } + doc.add_request_body_schema( + "/app/foo", HTTP_POST, http::headervalues::contenttype::JSON); doc.add_response_schema( "/app/foo", HTTP_GET, From 964f863d8ed6ad4cc2b13a1d38c85ed8584bd93c Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Mon, 29 Jun 2020 17:44:13 +0100 Subject: [PATCH 13/53] WIP: Forgive me father for I have sinned --- src/ds/json.h | 34 +++++++++++++++++++ src/ds/json_schema.h | 15 +++++++++ src/ds/openapi.h | 74 +++++++++++++++++++++++++++++++++-------- src/ds/test/openapi.cpp | 11 ++++-- 4 files changed, 118 insertions(+), 16 deletions(-) diff --git a/src/ds/json.h b/src/ds/json.h index 9f8dd62ce1f..56814a5ba00 100644 --- a/src/ds/json.h +++ b/src/ds/json.h @@ -368,6 +368,19 @@ namespace std #define FILL_SCHEMA_OPTIONAL_FOR_JSON_FINAL(TYPE, FIELD) \ FILL_SCHEMA_OPTIONAL_WITH_RENAMES_FOR_JSON_FINAL(TYPE, FIELD, FIELD) +#define ADD_SCHEMA_COMPONENT_WITH_RENAMES_FOR_JSON_NEXT( \ + TYPE, C_FIELD, JSON_FIELD) \ + j["properties"][#JSON_FIELD] = \ + doc.template add_schema_component(); +#define ADD_SCHEMA_COMPONENT_WITH_RENAMES_FOR_JSON_FINAL( \ + TYPE, C_FIELD, JSON_FIELD) \ + ADD_SCHEMA_COMPONENT_WITH_RENAMES_FOR_JSON_NEXT(TYPE, C_FIELD, JSON_FIELD) + +#define ADD_SCHEMA_COMPONENT_FOR_JSON_NEXT(TYPE, FIELD) \ + ADD_SCHEMA_COMPONENT_WITH_RENAMES_FOR_JSON_NEXT(TYPE, FIELD, FIELD) +#define ADD_SCHEMA_COMPONENT_FOR_JSON_FINAL(TYPE, FIELD) \ + ADD_SCHEMA_COMPONENT_WITH_RENAMES_FOR_JSON_FINAL(TYPE, FIELD, FIELD) + #define JSON_FIELD_FOR_JSON_NEXT(TYPE, FIELD) \ JsonField{#FIELD}, #define JSON_FIELD_FOR_JSON_FINAL(TYPE, FIELD) \ @@ -489,6 +502,9 @@ namespace std void from_json_optional_fields(const nlohmann::json& j, TYPE& t); \ void fill_json_schema_required_fields(nlohmann::json& j, const TYPE& t); \ void fill_json_schema_optional_fields(nlohmann::json& j, const TYPE& t); \ + template \ + void add_schema_components_required_fields( \ + T& doc, nlohmann::json& j, const TYPE& t); \ inline void to_json(nlohmann::json& j, const TYPE& t) \ { \ PRE_TO_JSON; \ @@ -510,6 +526,16 @@ namespace std inline std::string schema_name(const TYPE& t) \ { \ return #TYPE; \ + } \ + template \ + nlohmann::json add_schema_components(T& doc, const TYPE& t) \ + { \ + auto& schema_element = doc.components.schemas[#TYPE]; \ + schema_element["type"] = "object"; \ + add_schema_components_required_fields(doc, schema_element, t); \ + auto schema_ref_object = nlohmann::json::object(); \ + schema_ref_object["$ref"] = "#/components/schemas/" #TYPE; \ + return schema_ref_object; \ } #define DECLARE_JSON_TYPE(TYPE) DECLARE_JSON_TYPE_IMPL(TYPE, , , , , , ) @@ -565,6 +591,14 @@ namespace std j["type"] = "object"; \ _FOR_JSON_COUNT_NN(__VA_ARGS__) \ (POP1)(FILL_SCHEMA_REQUIRED, TYPE, ##__VA_ARGS__) \ + } \ + template \ + void add_schema_components_required_fields( \ + T& doc, nlohmann::json& j, const TYPE& t) \ + { \ + auto& component_schema_properties = doc.components.schemas[#TYPE]; \ + _FOR_JSON_COUNT_NN(__VA_ARGS__) \ + (POP1)(ADD_SCHEMA_COMPONENT, TYPE, ##__VA_ARGS__); \ } #define DECLARE_JSON_REQUIRED_FIELDS_WITH_RENAMES(TYPE, ...) \ diff --git a/src/ds/json_schema.h b/src/ds/json_schema.h index f0123024651..f2589103b7b 100644 --- a/src/ds/json_schema.h +++ b/src/ds/json_schema.h @@ -55,6 +55,14 @@ namespace ds return element; } + template + nlohmann::json schema_element() + { + auto element = nlohmann::json::object(); + fill_schema(element); + return element; + } + namespace adl { template @@ -77,6 +85,13 @@ namespace ds fill_json_schema(schema, t); } } + + template + nlohmann::json add_schema_to_components(TDoc& doc) + { + T t; + return add_schema_components(doc, t); + } } template diff --git a/src/ds/openapi.h b/src/ds/openapi.h index 8a29fa5d3d8..22f5455753b 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -210,10 +210,12 @@ namespace ds http_method verb, const std::string& content_type) { - auto t_schema = nlohmann::json::object(); - ds::json::fill_schema(t_schema); - add_request_body_schema( - uri, verb, content_type, ds::json::schema_name(), t_schema); + check_path_valid(uri); + + auto& request_body = paths[uri][verb].requestBody; + request_body.description = "Auto-generated request body schema"; + request_body.content[content_type].schema = + add_schema_component(); } void add_response_schema( @@ -239,15 +241,61 @@ namespace ds http_status status, const std::string& content_type) { - auto t_schema = nlohmann::json::object(); - ds::json::fill_schema(t_schema); - add_response_schema( - uri, - verb, - status, - content_type, - ds::json::schema_name(), - t_schema); + check_path_valid(uri); + + auto& response_object = paths[uri][verb][status]; + response_object.description = "Auto-generated response schema"; + response_object.content[content_type].schema = + add_schema_component(); + } + + template + inline nlohmann::json add_schema_component() + { + nlohmann::json j; + // if constexpr (nonstd::is_specialization::value) + // { + // return schema_name(); + // } + // else if constexpr (nonstd::is_specialization::value) + // { + // return fmt::format("{}_array", schema_name()); + // } + // else if constexpr ( + // nonstd::is_specialization::value || + // nonstd::is_specialization::value) + // { + // return fmt::format( + // "{}_to_{}", + // schema_name(), + // schema_name()); + // } + // else if constexpr (nonstd::is_specialization::value) + // { + // return fmt::format( + // "{}_to_{}", + // schema_name(), + // schema_name()); + // } + // else + if constexpr ( + std::is_same::value || std::is_same::value || + std::is_same::value || std::is_same::value || + std::is_same::value || + std::is_same::value || std::is_same::value || + std::is_same::value || std::is_same::value || + std::is_same::value || std::is_same::value || + std::is_same::value || + std::is_same::value) + { + ds::json::fill_schema(j); + return add_schema_to_components(ds::json::schema_name(), j); + } + else + { + return ds::json::adl::add_schema_to_components(*this); + } } }; DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(Document); diff --git a/src/ds/test/openapi.cpp b/src/ds/test/openapi.cpp index fb693a1ae07..4f5464615ed 100644 --- a/src/ds/test/openapi.cpp +++ b/src/ds/test/openapi.cpp @@ -102,14 +102,19 @@ TEST_CASE("Schema population") "/app/foo", HTTP_POST, http::headervalues::contenttype::JSON); doc.add_response_schema( "/app/foo", - HTTP_GET, + HTTP_POST, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); - doc.add_response_schema>( - "/app/foos", + doc.add_response_schema( + "/app/bar", HTTP_GET, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); + // doc.add_response_schema>( + // "/app/foos", + // HTTP_GET, + // HTTP_STATUS_OK, + // http::headervalues::contenttype::JSON); const nlohmann::json j = doc; required_doc_elements(j); From b508e87f7a5bd30a59b0f343e00439063a2fb066 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Mon, 29 Jun 2020 17:57:29 +0100 Subject: [PATCH 14/53] WIP: Support optional fields --- src/ds/json.h | 69 +++++++++++++++++++++++++++++++---------- src/ds/test/openapi.cpp | 26 +++++++++++++++- 2 files changed, 77 insertions(+), 18 deletions(-) diff --git a/src/ds/json.h b/src/ds/json.h index 56814a5ba00..b58b7cc2d78 100644 --- a/src/ds/json.h +++ b/src/ds/json.h @@ -368,18 +368,34 @@ namespace std #define FILL_SCHEMA_OPTIONAL_FOR_JSON_FINAL(TYPE, FIELD) \ FILL_SCHEMA_OPTIONAL_WITH_RENAMES_FOR_JSON_FINAL(TYPE, FIELD, FIELD) -#define ADD_SCHEMA_COMPONENT_WITH_RENAMES_FOR_JSON_NEXT( \ +#define ADD_SCHEMA_COMPONENTS_REQUIRED_WITH_RENAMES_FOR_JSON_NEXT( \ + TYPE, C_FIELD, JSON_FIELD) \ + j["properties"][#JSON_FIELD] = \ + doc.template add_schema_component(); \ + j["required"].push_back(#JSON_FIELD); +#define ADD_SCHEMA_COMPONENTS_REQUIRED_WITH_RENAMES_FOR_JSON_FINAL( \ + TYPE, C_FIELD, JSON_FIELD) \ + ADD_SCHEMA_COMPONENTS_REQUIRED_WITH_RENAMES_FOR_JSON_NEXT( \ + TYPE, C_FIELD, JSON_FIELD) + +#define ADD_SCHEMA_COMPONENTS_REQUIRED_FOR_JSON_NEXT(TYPE, FIELD) \ + ADD_SCHEMA_COMPONENTS_REQUIRED_WITH_RENAMES_FOR_JSON_NEXT(TYPE, FIELD, FIELD) +#define ADD_SCHEMA_COMPONENTS_REQUIRED_FOR_JSON_FINAL(TYPE, FIELD) \ + ADD_SCHEMA_COMPONENTS_REQUIRED_WITH_RENAMES_FOR_JSON_FINAL(TYPE, FIELD, FIELD) + +#define ADD_SCHEMA_COMPONENTS_OPTIONAL_WITH_RENAMES_FOR_JSON_NEXT( \ TYPE, C_FIELD, JSON_FIELD) \ j["properties"][#JSON_FIELD] = \ doc.template add_schema_component(); -#define ADD_SCHEMA_COMPONENT_WITH_RENAMES_FOR_JSON_FINAL( \ +#define ADD_SCHEMA_COMPONENTS_OPTIONAL_WITH_RENAMES_FOR_JSON_FINAL( \ TYPE, C_FIELD, JSON_FIELD) \ - ADD_SCHEMA_COMPONENT_WITH_RENAMES_FOR_JSON_NEXT(TYPE, C_FIELD, JSON_FIELD) + ADD_SCHEMA_COMPONENTS_OPTIONAL_WITH_RENAMES_FOR_JSON_NEXT( \ + TYPE, C_FIELD, JSON_FIELD) -#define ADD_SCHEMA_COMPONENT_FOR_JSON_NEXT(TYPE, FIELD) \ - ADD_SCHEMA_COMPONENT_WITH_RENAMES_FOR_JSON_NEXT(TYPE, FIELD, FIELD) -#define ADD_SCHEMA_COMPONENT_FOR_JSON_FINAL(TYPE, FIELD) \ - ADD_SCHEMA_COMPONENT_WITH_RENAMES_FOR_JSON_FINAL(TYPE, FIELD, FIELD) +#define ADD_SCHEMA_COMPONENTS_OPTIONAL_FOR_JSON_NEXT(TYPE, FIELD) \ + ADD_SCHEMA_COMPONENTS_OPTIONAL_WITH_RENAMES_FOR_JSON_NEXT(TYPE, FIELD, FIELD) +#define ADD_SCHEMA_COMPONENTS_OPTIONAL_FOR_JSON_FINAL(TYPE, FIELD) \ + ADD_SCHEMA_COMPONENTS_OPTIONAL_WITH_RENAMES_FOR_JSON_FINAL(TYPE, FIELD, FIELD) #define JSON_FIELD_FOR_JSON_NEXT(TYPE, FIELD) \ JsonField{#FIELD}, @@ -495,7 +511,9 @@ namespace std PRE_FROM_JSON, \ POST_FROM_JSON, \ PRE_FILL_SCHEMA, \ - POST_FILL_SCHEMA) \ + POST_FILL_SCHEMA, \ + PRE_ADD_SCHEMA, \ + POST_ADD_SCHEMA) \ void to_json_required_fields(nlohmann::json& j, const TYPE& t); \ void to_json_optional_fields(nlohmann::json& j, const TYPE& t); \ void from_json_required_fields(const nlohmann::json& j, TYPE& t); \ @@ -505,6 +523,9 @@ namespace std template \ void add_schema_components_required_fields( \ T& doc, nlohmann::json& j, const TYPE& t); \ + template \ + void add_schema_components_optional_fields( \ + T& doc, nlohmann::json& j, const TYPE& t); \ inline void to_json(nlohmann::json& j, const TYPE& t) \ { \ PRE_TO_JSON; \ @@ -530,15 +551,16 @@ namespace std template \ nlohmann::json add_schema_components(T& doc, const TYPE& t) \ { \ - auto& schema_element = doc.components.schemas[#TYPE]; \ - schema_element["type"] = "object"; \ - add_schema_components_required_fields(doc, schema_element, t); \ + PRE_ADD_SCHEMA; \ + auto& j = doc.components.schemas[#TYPE]; \ + add_schema_components_required_fields(doc, j, t); \ + POST_ADD_SCHEMA; \ auto schema_ref_object = nlohmann::json::object(); \ schema_ref_object["$ref"] = "#/components/schemas/" #TYPE; \ return schema_ref_object; \ } -#define DECLARE_JSON_TYPE(TYPE) DECLARE_JSON_TYPE_IMPL(TYPE, , , , , , ) +#define DECLARE_JSON_TYPE(TYPE) DECLARE_JSON_TYPE_IMPL(TYPE, , , , , , , , ) #define DECLARE_JSON_TYPE_WITH_BASE(TYPE, BASE) \ DECLARE_JSON_TYPE_IMPL( \ @@ -547,7 +569,9 @@ namespace std , \ from_json(j, static_cast(t)), \ , \ - fill_json_schema(j, static_cast(t)), ) + fill_json_schema(j, static_cast(t)), \ + , \ + add_schema_components(doc, static_cast(t)), ) #define DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(TYPE) \ DECLARE_JSON_TYPE_IMPL( \ @@ -557,7 +581,9 @@ namespace std , \ from_json_optional_fields(j, t), \ , \ - fill_json_schema_optional_fields(j, t)) + fill_json_schema_optional_fields(j, t), \ + , \ + add_schema_components_optional_fields(doc, j, t)) #define DECLARE_JSON_TYPE_WITH_BASE_AND_OPTIONAL_FIELDS(TYPE, BASE) \ DECLARE_JSON_TYPE_IMPL( \ @@ -567,7 +593,9 @@ namespace std from_json(j, static_cast(t)), \ from_json_optional_fields(j, t), \ fill_json_schema(j, static_cast(t)), \ - fill_json_schema_optional_fields(j, t)) + fill_json_schema_optional_fields(j, t), \ + add_schema_components(doc, static_cast(t)), \ + add_schema_components_optional_fields(doc, j, t)) #define DECLARE_JSON_REQUIRED_FIELDS(TYPE, ...) \ inline void to_json_required_fields(nlohmann::json& j, const TYPE& t) \ @@ -596,9 +624,9 @@ namespace std void add_schema_components_required_fields( \ T& doc, nlohmann::json& j, const TYPE& t) \ { \ - auto& component_schema_properties = doc.components.schemas[#TYPE]; \ + j["type"] = "object"; \ _FOR_JSON_COUNT_NN(__VA_ARGS__) \ - (POP1)(ADD_SCHEMA_COMPONENT, TYPE, ##__VA_ARGS__); \ + (POP1)(ADD_SCHEMA_COMPONENTS_REQUIRED, TYPE, ##__VA_ARGS__); \ } #define DECLARE_JSON_REQUIRED_FIELDS_WITH_RENAMES(TYPE, ...) \ @@ -642,6 +670,13 @@ namespace std { \ _FOR_JSON_COUNT_NN(__VA_ARGS__) \ (POP1)(FILL_SCHEMA_OPTIONAL, TYPE, ##__VA_ARGS__) \ + } \ + template \ + void add_schema_components_optional_fields( \ + T& doc, nlohmann::json& j, const TYPE& t) \ + { \ + _FOR_JSON_COUNT_NN(__VA_ARGS__) \ + (POP1)(ADD_SCHEMA_COMPONENTS_REQUIRED, TYPE, ##__VA_ARGS__); \ } #define DECLARE_JSON_OPTIONAL_FIELDS_WITH_RENAMES(TYPE, ...) \ diff --git a/src/ds/test/openapi.cpp b/src/ds/test/openapi.cpp index 4f5464615ed..4d86cbdae78 100644 --- a/src/ds/test/openapi.cpp +++ b/src/ds/test/openapi.cpp @@ -85,6 +85,25 @@ struct Foo DECLARE_JSON_TYPE(Foo); DECLARE_JSON_REQUIRED_FIELDS(Foo, n, s); +struct Bar +{ + std::string name; + double f; +}; +DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(Bar); +DECLARE_JSON_REQUIRED_FIELDS(Bar, name); +DECLARE_JSON_OPTIONAL_FIELDS(Bar, f); + +struct Baz : public Bar +{ + uint16_t n; + double x; + double y; +}; +DECLARE_JSON_TYPE_WITH_BASE_AND_OPTIONAL_FIELDS(Baz, Bar); +DECLARE_JSON_REQUIRED_FIELDS(Baz, n); +DECLARE_JSON_OPTIONAL_FIELDS(Baz, x, y); + TEST_CASE("Schema population") { openapi::Document doc; @@ -105,11 +124,16 @@ TEST_CASE("Schema population") HTTP_POST, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); - doc.add_response_schema( + doc.add_response_schema( "/app/bar", HTTP_GET, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); + doc.add_response_schema( + "/app/baz", + HTTP_GET, + HTTP_STATUS_OK, + http::headervalues::contenttype::JSON); // doc.add_response_schema>( // "/app/foos", // HTTP_GET, From 89340ce881250df3665172361358dbef4b11ef92 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Mon, 29 Jun 2020 17:59:44 +0100 Subject: [PATCH 15/53] Fix for optional fields --- src/ds/json.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ds/json.h b/src/ds/json.h index b58b7cc2d78..b4227587289 100644 --- a/src/ds/json.h +++ b/src/ds/json.h @@ -676,7 +676,7 @@ namespace std T& doc, nlohmann::json& j, const TYPE& t) \ { \ _FOR_JSON_COUNT_NN(__VA_ARGS__) \ - (POP1)(ADD_SCHEMA_COMPONENTS_REQUIRED, TYPE, ##__VA_ARGS__); \ + (POP1)(ADD_SCHEMA_COMPONENTS_OPTIONAL, TYPE, ##__VA_ARGS__); \ } #define DECLARE_JSON_OPTIONAL_FIELDS_WITH_RENAMES(TYPE, ...) \ From da7039e12e1fd855e137faf0881a3ae7ebd4b0a9 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Mon, 29 Jun 2020 18:13:10 +0100 Subject: [PATCH 16/53] WIP: Add support for renames --- src/ds/json.h | 18 ++++++++++++++++++ src/ds/test/openapi.cpp | 26 +++++++++++++++++++++----- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/ds/json.h b/src/ds/json.h index b4227587289..f5f21c3f488 100644 --- a/src/ds/json.h +++ b/src/ds/json.h @@ -560,6 +560,9 @@ namespace std return schema_ref_object; \ } +// TODO: PRE_ADD_SCHEMA isn't right for adding base elements, think it adds them +// with the wrong name? + #define DECLARE_JSON_TYPE(TYPE) DECLARE_JSON_TYPE_IMPL(TYPE, , , , , , , , ) #define DECLARE_JSON_TYPE_WITH_BASE(TYPE, BASE) \ @@ -653,6 +656,14 @@ namespace std j["type"] = "object"; \ _FOR_JSON_COUNT_NN(__VA_ARGS__) \ (POP2)(FILL_SCHEMA_REQUIRED_WITH_RENAMES, TYPE, ##__VA_ARGS__) \ + } \ + template \ + void add_schema_components_required_fields( \ + T& doc, nlohmann::json& j, const TYPE& t) \ + { \ + j["type"] = "object"; \ + _FOR_JSON_COUNT_NN(__VA_ARGS__) \ + (POP2)(ADD_SCHEMA_COMPONENTS_REQUIRED_WITH_RENAMES, TYPE, ##__VA_ARGS__); \ } #define DECLARE_JSON_OPTIONAL_FIELDS(TYPE, ...) \ @@ -696,6 +707,13 @@ namespace std { \ _FOR_JSON_COUNT_NN(__VA_ARGS__) \ (POP2)(FILL_SCHEMA_OPTIONAL_WITH_RENAMES, TYPE, ##__VA_ARGS__) \ + } \ + template \ + void add_schema_components_optional_fields( \ + T& doc, nlohmann::json& j, const TYPE& t) \ + { \ + _FOR_JSON_COUNT_NN(__VA_ARGS__) \ + (POP2)(ADD_SCHEMA_COMPONENTS_OPTIONAL_WITH_RENAMES, TYPE, ##__VA_ARGS__); \ } #define DECLARE_JSON_ENUM(TYPE, ...) \ diff --git a/src/ds/test/openapi.cpp b/src/ds/test/openapi.cpp index 4d86cbdae78..9ec1be216b3 100644 --- a/src/ds/test/openapi.cpp +++ b/src/ds/test/openapi.cpp @@ -104,6 +104,17 @@ DECLARE_JSON_TYPE_WITH_BASE_AND_OPTIONAL_FIELDS(Baz, Bar); DECLARE_JSON_REQUIRED_FIELDS(Baz, n); DECLARE_JSON_OPTIONAL_FIELDS(Baz, x, y); +struct Buzz : public Baz +{ + Foo required_and_only_in_c; + uint16_t optional_and_only_in_c; +}; +DECLARE_JSON_TYPE_WITH_BASE_AND_OPTIONAL_FIELDS(Buzz, Baz); +DECLARE_JSON_REQUIRED_FIELDS_WITH_RENAMES( + Buzz, required_and_only_in_c, RequiredJsonField); +DECLARE_JSON_OPTIONAL_FIELDS_WITH_RENAMES( + Buzz, optional_and_only_in_c, OptionalJsonField); + TEST_CASE("Schema population") { openapi::Document doc; @@ -124,6 +135,11 @@ TEST_CASE("Schema population") HTTP_POST, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); + // doc.add_response_schema>( + // "/app/foos", + // HTTP_GET, + // HTTP_STATUS_OK, + // http::headervalues::contenttype::JSON); doc.add_response_schema( "/app/bar", HTTP_GET, @@ -134,11 +150,11 @@ TEST_CASE("Schema population") HTTP_GET, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); - // doc.add_response_schema>( - // "/app/foos", - // HTTP_GET, - // HTTP_STATUS_OK, - // http::headervalues::contenttype::JSON); + doc.add_response_schema( + "/app/buzz", + HTTP_GET, + HTTP_STATUS_OK, + http::headervalues::contenttype::JSON); const nlohmann::json j = doc; required_doc_elements(j); From 016c7df1a79e696e8c05a9b08feff8f1d1cb6a01 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Mon, 29 Jun 2020 18:24:44 +0100 Subject: [PATCH 17/53] WIP: Fix duplicate-required and missing-base-elements --- src/ds/json.h | 8 ++++---- src/ds/json_schema.h | 9 ++++++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/ds/json.h b/src/ds/json.h index f5f21c3f488..61cd7dbb7a9 100644 --- a/src/ds/json.h +++ b/src/ds/json.h @@ -549,10 +549,10 @@ namespace std return #TYPE; \ } \ template \ - nlohmann::json add_schema_components(T& doc, const TYPE& t) \ + nlohmann::json add_schema_components( \ + T& doc, nlohmann::json& j, const TYPE& t) \ { \ PRE_ADD_SCHEMA; \ - auto& j = doc.components.schemas[#TYPE]; \ add_schema_components_required_fields(doc, j, t); \ POST_ADD_SCHEMA; \ auto schema_ref_object = nlohmann::json::object(); \ @@ -574,7 +574,7 @@ namespace std , \ fill_json_schema(j, static_cast(t)), \ , \ - add_schema_components(doc, static_cast(t)), ) + add_schema_components(doc, j, static_cast(t)), ) #define DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(TYPE) \ DECLARE_JSON_TYPE_IMPL( \ @@ -597,7 +597,7 @@ namespace std from_json_optional_fields(j, t), \ fill_json_schema(j, static_cast(t)), \ fill_json_schema_optional_fields(j, t), \ - add_schema_components(doc, static_cast(t)), \ + add_schema_components(doc, j, static_cast(t)), \ add_schema_components_optional_fields(doc, j, t)) #define DECLARE_JSON_REQUIRED_FIELDS(TYPE, ...) \ diff --git a/src/ds/json_schema.h b/src/ds/json_schema.h index f2589103b7b..2ad69f1dbd9 100644 --- a/src/ds/json_schema.h +++ b/src/ds/json_schema.h @@ -90,7 +90,14 @@ namespace ds nlohmann::json add_schema_to_components(TDoc& doc) { T t; - return add_schema_components(doc, t); + const auto name = schema_name(t); + const auto ib = doc.components.schemas.try_emplace(name); + if (ib.second) + { + auto& j = ib.first->second; + return add_schema_components(doc, j, t); + } + return ib.first->second; } } From 7a8ebd3ff7d85d21dff814b034f2b862509174e0 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Tue, 30 Jun 2020 11:30:17 +0100 Subject: [PATCH 18/53] Support for vectors, fancy types --- src/ds/json.h | 5 +-- src/ds/json_schema.h | 8 +++-- src/ds/openapi.h | 78 ++++++++++++++++++++++++----------------- src/ds/test/openapi.cpp | 10 +++--- 4 files changed, 58 insertions(+), 43 deletions(-) diff --git a/src/ds/json.h b/src/ds/json.h index 61cd7dbb7a9..d1f44abf6cd 100644 --- a/src/ds/json.h +++ b/src/ds/json.h @@ -549,15 +549,12 @@ namespace std return #TYPE; \ } \ template \ - nlohmann::json add_schema_components( \ + void add_schema_components( \ T& doc, nlohmann::json& j, const TYPE& t) \ { \ PRE_ADD_SCHEMA; \ add_schema_components_required_fields(doc, j, t); \ POST_ADD_SCHEMA; \ - auto schema_ref_object = nlohmann::json::object(); \ - schema_ref_object["$ref"] = "#/components/schemas/" #TYPE; \ - return schema_ref_object; \ } // TODO: PRE_ADD_SCHEMA isn't right for adding base elements, think it adds them diff --git a/src/ds/json_schema.h b/src/ds/json_schema.h index 2ad69f1dbd9..d35b4bce0e4 100644 --- a/src/ds/json_schema.h +++ b/src/ds/json_schema.h @@ -95,9 +95,13 @@ namespace ds if (ib.second) { auto& j = ib.first->second; - return add_schema_components(doc, j, t); + add_schema_components(doc, j, t); } - return ib.first->second; + + auto schema_ref_object = nlohmann::json::object(); + schema_ref_object["$ref"] = + fmt::format("#/components/schemas/{}", name); + return schema_ref_object; } } diff --git a/src/ds/openapi.h b/src/ds/openapi.h index 22f5455753b..5c4483f5907 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -214,8 +214,7 @@ namespace ds auto& request_body = paths[uri][verb].requestBody; request_body.description = "Auto-generated request body schema"; - request_body.content[content_type].schema = - add_schema_component(); + request_body.content[content_type].schema = add_schema_component(); } void add_response_schema( @@ -252,34 +251,49 @@ namespace ds template inline nlohmann::json add_schema_component() { - nlohmann::json j; - // if constexpr (nonstd::is_specialization::value) - // { - // return schema_name(); - // } - // else if constexpr (nonstd::is_specialization::value) - // { - // return fmt::format("{}_array", schema_name()); - // } - // else if constexpr ( - // nonstd::is_specialization::value || - // nonstd::is_specialization::value) - // { - // return fmt::format( - // "{}_to_{}", - // schema_name(), - // schema_name()); - // } - // else if constexpr (nonstd::is_specialization::value) - // { - // return fmt::format( - // "{}_to_{}", - // schema_name(), - // schema_name()); - // } - // else - if constexpr ( + nlohmann::json schema; + if constexpr (nonstd::is_specialization::value) + { + return add_schema_component(); + } + else if constexpr (nonstd::is_specialization::value) + { + schema["type"] = "array"; + schema["items"] = add_schema_component(); + return schema; + } + else if constexpr ( + nonstd::is_specialization::value || + nonstd::is_specialization::value) + { + // Nlohmann serialises maps to an array of (K, V) pairs + // TODO: Unless the keys are strings! + schema["type"] = "array"; + auto items = nlohmann::json::object(); + { + items["type"] = "array"; + + auto sub_items = nlohmann::json::array(); + // TODO: OpenAPI doesn't like this tuple for "items", even though + // its valid JSON schema. Maybe fixed in a newer spec version? + sub_items.push_back(add_schema_component()); + sub_items.push_back( + add_schema_component()); + items["items"] = sub_items; + } + schema["items"] = items; + return schema; + } + else if constexpr (nonstd::is_specialization::value) + { + schema["type"] = "array"; + auto items = nlohmann::json::array(); + items.push_back(add_schema_component()); + items.push_back(add_schema_component()); + schema["items"] = items; + return schema; + } + else if constexpr ( std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || @@ -289,8 +303,8 @@ namespace ds std::is_same::value || std::is_same::value) { - ds::json::fill_schema(j); - return add_schema_to_components(ds::json::schema_name(), j); + ds::json::fill_schema(schema); + return add_schema_to_components(ds::json::schema_name(), schema); } else { diff --git a/src/ds/test/openapi.cpp b/src/ds/test/openapi.cpp index 9ec1be216b3..a9f2a473967 100644 --- a/src/ds/test/openapi.cpp +++ b/src/ds/test/openapi.cpp @@ -135,11 +135,11 @@ TEST_CASE("Schema population") HTTP_POST, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); - // doc.add_response_schema>( - // "/app/foos", - // HTTP_GET, - // HTTP_STATUS_OK, - // http::headervalues::contenttype::JSON); + doc.add_response_schema>( + "/app/foos", + HTTP_GET, + HTTP_STATUS_OK, + http::headervalues::contenttype::JSON); doc.add_response_schema( "/app/bar", HTTP_GET, From 1b9fc337797190fe3f51c2837f2390f8ee608a95 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Tue, 30 Jun 2020 13:32:33 +0100 Subject: [PATCH 19/53] Remove some fixed TODOs --- src/ds/json.h | 6 +----- src/node/rpc/call_types.h | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/ds/json.h b/src/ds/json.h index d1f44abf6cd..4b1780c2001 100644 --- a/src/ds/json.h +++ b/src/ds/json.h @@ -549,17 +549,13 @@ namespace std return #TYPE; \ } \ template \ - void add_schema_components( \ - T& doc, nlohmann::json& j, const TYPE& t) \ + void add_schema_components(T& doc, nlohmann::json& j, const TYPE& t) \ { \ PRE_ADD_SCHEMA; \ add_schema_components_required_fields(doc, j, t); \ POST_ADD_SCHEMA; \ } -// TODO: PRE_ADD_SCHEMA isn't right for adding base elements, think it adds them -// with the wrong name? - #define DECLARE_JSON_TYPE(TYPE) DECLARE_JSON_TYPE_IMPL(TYPE, , , , , , , , ) #define DECLARE_JSON_TYPE_WITH_BASE(TYPE, BASE) \ diff --git a/src/node/rpc/call_types.h b/src/node/rpc/call_types.h index 971355f3579..4f62d0375fd 100644 --- a/src/node/rpc/call_types.h +++ b/src/node/rpc/call_types.h @@ -119,7 +119,6 @@ namespace ccf struct GetAPI { - // TODO: This is a ds::openapi::Document? using Out = nlohmann::json; }; From e92bb37c199434a08a72c6782dc8864342758b0a Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Tue, 30 Jun 2020 13:42:23 +0100 Subject: [PATCH 20/53] Separate simple and complex test cases --- src/ds/test/openapi.cpp | 61 +++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/src/ds/test/openapi.cpp b/src/ds/test/openapi.cpp index a9f2a473967..0638dcb2d35 100644 --- a/src/ds/test/openapi.cpp +++ b/src/ds/test/openapi.cpp @@ -25,8 +25,9 @@ void print_doc(const std::string& title, const nlohmann::json& doc) static constexpr auto server_url = "https://not.a.real.server.example.com/testing_only"; -// TODO: Use some external verifier to do this properly. This is the basic -// stuff for initial compatibility +// TODO: Use some external verifier to check this. What we primarily care about +// is "is this a valid OpenAPI doc". We don't even really care about parsing it +// for specific elements, just producing it void required_doc_elements(const nlohmann::json& j) { REQUIRE_ELEMENT(j, openapi, is_string); @@ -85,6 +86,38 @@ struct Foo DECLARE_JSON_TYPE(Foo); DECLARE_JSON_REQUIRED_FIELDS(Foo, n, s); +TEST_CASE("Simple custom types") +{ + openapi::Document doc; + doc.info.title = "Test generated API"; + doc.info.description = "Some longer description enhanced with **Markdown**"; + doc.info.version = "0.1.42"; + + { + openapi::Server mockup_server; + mockup_server.url = server_url; + doc.servers.push_back(mockup_server); + } + + doc.add_request_body_schema( + "/app/foo", HTTP_POST, http::headervalues::contenttype::JSON); + doc.add_response_schema( + "/app/foo", + HTTP_POST, + HTTP_STATUS_OK, + http::headervalues::contenttype::JSON); + doc.add_response_schema( + "/app/foo", + HTTP_GET, + HTTP_STATUS_OK, + http::headervalues::contenttype::JSON); + + const nlohmann::json j = doc; + required_doc_elements(j); + + print_doc("SIMPLE", doc); +} + struct Bar { std::string name; @@ -115,26 +148,13 @@ DECLARE_JSON_REQUIRED_FIELDS_WITH_RENAMES( DECLARE_JSON_OPTIONAL_FIELDS_WITH_RENAMES( Buzz, optional_and_only_in_c, OptionalJsonField); -TEST_CASE("Schema population") +TEST_CASE("Complex custom types") { openapi::Document doc; doc.info.title = "Test generated API"; doc.info.description = "Some longer description enhanced with **Markdown**"; doc.info.version = "0.1.42"; - { - openapi::Server mockup_server; - mockup_server.url = server_url; - doc.servers.push_back(mockup_server); - } - - doc.add_request_body_schema( - "/app/foo", HTTP_POST, http::headervalues::contenttype::JSON); - doc.add_response_schema( - "/app/foo", - HTTP_POST, - HTTP_STATUS_OK, - http::headervalues::contenttype::JSON); doc.add_response_schema>( "/app/foos", HTTP_GET, @@ -155,9 +175,16 @@ TEST_CASE("Schema population") HTTP_GET, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); + doc.add_request_body_schema>( + "/app/complex", HTTP_GET, http::headervalues::contenttype::JSON); + doc.add_response_schema>>( + "/app/complex", + HTTP_GET, + HTTP_STATUS_OK, + http::headervalues::contenttype::JSON); const nlohmann::json j = doc; required_doc_elements(j); - print_doc("SCHEMA", doc); + print_doc("COMPLEX", doc); } \ No newline at end of file From 593005d4ac9a2292a5d5c705988d86aae585e17d Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Tue, 30 Jun 2020 16:02:33 +0100 Subject: [PATCH 21/53] Steps towards pure JSON doc --- src/ds/openapi.h | 91 +++++++++++++++++++++++++++++++++++++++-- src/ds/test/openapi.cpp | 48 ++++++++++++---------- 2 files changed, 114 insertions(+), 25 deletions(-) diff --git a/src/ds/openapi.h b/src/ds/openapi.h index 5c4483f5907..2fdabac5181 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -12,12 +12,97 @@ namespace ds { /** - * These structs contain the required fields to build the corresponding - * OpenAPI objects. They do not contain every field, but should be trivially - * extensible with any which are desired. + * This namespace contains helper functions, structs, and templates for + * modifying an OpenAPI JSON document. They do not set every field, but should + * fill every _required_ field, and the resulting object can be further + * modified by hand as required. */ namespace openapi { + namespace access + { + nlohmann::json& get_object(nlohmann::json& j, const std::string& k) + { + const auto ib = j.emplace(k, nlohmann::json::object()); + return ib.first.value(); + } + + nlohmann::json& get_array(nlohmann::json& j, const std::string& k) + { + const auto ib = j.emplace(k, nlohmann::json::array()); + return ib.first.value(); + } + } + + nlohmann::json create_document( + const std::string& title, + const std::string& description, + const std::string& document_version) + { + // TODO: Check document_version looks valid? + return nlohmann::json{{"openapi", "3.0.0"}, + {"info", + {{"title", title}, + {"description", description}, + {"version", document_version}}}, + {"servers", nlohmann::json::array()}, + {"paths", nlohmann::json::object()}}; + } + + nlohmann::json& server(nlohmann::json& document, const std::string& url) + { + auto& servers = access::get_object(document, "servers"); + servers.push_back({{"url", url}}); + return servers.back(); + } + + nlohmann::json& path(nlohmann::json& document, const std::string& path) + { + // TODO: Check that path starts with /? + auto& paths = access::get_object(document, "paths"); + return access::get_object(paths, path); + } + + nlohmann::json& path_operation(nlohmann::json& path, http_method verb) + { + // HTTP_GET becomes the string "get" + std::string s = http_method_str(verb); + nonstd::to_lower(s); + return access::get_object(path, s); + } + + nlohmann::json& response( + nlohmann::json& path_operation, + http_status status, + const std::string& description = "Default response description") + { + auto& responses = access::get_object(path_operation, "responses"); + // HTTP_STATUS_OK (aka an int-enum with value 200) becomes the string + // "200" + const auto s = std::to_string(status); + auto& response = access::get_object(responses, s); + response["description"] = description; + return response; + } + + nlohmann::json& request_body( + nlohmann::json& path_operation + ) + { + auto& request_body = access::get_object(path_operation, "requestBody"); + access::get_object(request_body, "content"); + return request_body; + } + + nlohmann::json& media_type( + nlohmann::json& j, + const std::string& mt + ) + { + auto& content = access::get_object(j, "content"); + return access::get_object(content, mt); + } + struct Info { std::string title; diff --git a/src/ds/test/openapi.cpp b/src/ds/test/openapi.cpp index 0638dcb2d35..2a42dd99ba3 100644 --- a/src/ds/test/openapi.cpp +++ b/src/ds/test/openapi.cpp @@ -45,32 +45,36 @@ TEST_CASE("Required elements") TEST_CASE("Manual construction") { - openapi::Document doc; - doc.info.title = "Test generated API"; - doc.info.description = "Some longer description enhanced with **Markdown**"; - doc.info.version = "0.1.42"; - - { - openapi::Server mockup_server; - mockup_server.url = server_url; - doc.servers.push_back(mockup_server); - } - - { - doc.paths["/users/foo"][HTTP_GET][HTTP_STATUS_OK].description = - "Indicates that everything went ok"; - } - - const nlohmann::json j = doc; - required_doc_elements(j); - - const auto& info_element = j["info"]; + auto doc = openapi::create_document( + "Test generated API", + "Some longer description enhanced with **Markdown**", + "0.1.42"); + + openapi::server(doc, server_url); + + const auto string_schema = nlohmann::json{{"type", "string"}}; + + auto& foo = openapi::path(doc, "/users/foo"); + auto& foo_post = openapi::path_operation(foo, HTTP_POST); + auto& foo_post_request = openapi::request_body(foo_post); + auto& foo_post_request_json = openapi::media_type( + foo_post_request, http::headervalues::contenttype::JSON); + foo_post_request_json["schema"] = string_schema; + auto& foo_post_response_ok = openapi::response( + foo_post, HTTP_STATUS_OK, "Indicates that everything went ok"); + auto& foo_post_response_ok_json = openapi::media_type( + foo_post_response_ok, http::headervalues::contenttype::JSON); + foo_post_response_ok_json["schema"] = string_schema; + + required_doc_elements(doc); + + const auto& info_element = doc["info"]; REQUIRE_ELEMENT(info_element, title, is_string); REQUIRE_ELEMENT(info_element, description, is_string); REQUIRE_ELEMENT(info_element, version, is_string); - REQUIRE_ELEMENT(j, servers, is_array); - const auto& servers_element = j["servers"]; + REQUIRE_ELEMENT(doc, servers, is_array); + const auto& servers_element = doc["servers"]; REQUIRE(servers_element.size() == 1); const auto& first_server = servers_element[0]; REQUIRE_ELEMENT(first_server, url, is_string); From a01d2c5c07a8efdc16ed5d8a8b0401bba51f18a4 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Wed, 9 Sep 2020 14:58:03 +0100 Subject: [PATCH 22/53] Partial compile fixes --- CMakeLists.txt | 9 +++++---- python/setup.py | 42 ++++++++++++++++++++++++++++++++++++++++++ src/ds/openapi.h | 18 +++++++++--------- 3 files changed, 56 insertions(+), 13 deletions(-) create mode 100644 python/setup.py diff --git a/CMakeLists.txt b/CMakeLists.txt index c8589118227..fc3d0839031 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -257,7 +257,7 @@ if(BUILD_TESTS) ) use_client_mbedtls(kv_test) target_link_libraries( - kv_test PRIVATE ${CMAKE_THREAD_LIBS_INIT} secp256k1.host + kv_test PRIVATE ${CMAKE_THREAD_LIBS_INIT} secp256k1.host http_parser.host ) add_unit_test( @@ -301,9 +301,10 @@ if(BUILD_TESTS) ) target_include_directories(history_test PRIVATE ${EVERCRYPT_INC}) target_link_libraries( - history_test PRIVATE ${CRYPTO_LIBRARY} evercrypt.host secp256k1.host + history_test PRIVATE ${CRYPTO_LIBRARY} evercrypt.host secp256k1.host http_parser.host ) + add_unit_test( secret_sharing_test ${CMAKE_CURRENT_SOURCE_DIR}/src/node/test/secret_share.cpp @@ -321,7 +322,7 @@ if(BUILD_TESTS) historical_queries_test ${CMAKE_CURRENT_SOURCE_DIR}/src/node/test/historical_queries.cpp ) - target_link_libraries(historical_queries_test PRIVATE secp256k1.host) + target_link_libraries(historical_queries_test PRIVATE secp256k1.host http_parser.host) add_unit_test( msgpack_serialization_test @@ -408,7 +409,7 @@ if(BUILD_TESTS) ${CMAKE_CURRENT_SOURCE_DIR}/src/lua_interp/test/lua_kv.cpp ) target_include_directories(lua_test PRIVATE ${LUA_DIR}) - target_link_libraries(lua_test PRIVATE lua.host) + target_link_libraries(lua_test PRIVATE lua.host http_parser.host) add_unit_test( merkle_test ${CMAKE_CURRENT_SOURCE_DIR}/src/node/test/merkle_test.cpp diff --git a/python/setup.py b/python/setup.py new file mode 100644 index 00000000000..b32f73f1f1c --- /dev/null +++ b/python/setup.py @@ -0,0 +1,42 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the Apache 2.0 License. + +from setuptools import setup # type: ignore +from os import path + +PACKAGE_NAME = "ccf" +UTILITIES_PATH = "utils" + +path_here = path.abspath(path.dirname(__file__)) + +with open(path.join(path_here, "README.md"), encoding="utf-8") as f: + long_description = f.read() + +with open('requirements.txt') as f: + requirements = f.read().splitlines() + +setup( + name=PACKAGE_NAME, + version="0.13.2", + description="Set of tools and utilities for the Confidential Consortium Framework (CCF)", + long_description=long_description, + long_description_content_type="text/markdown", + url="https://github.com/microsoft/CCF/tree/master/python", + license="Apache License 2.0", + author="CCF Team", + classifiers=[ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "Programming Language :: Python :: 3", + ], + packages=[PACKAGE_NAME], + python_requires=">=3.7", + install_requires=requirements, + scripts=[ + path.join(PACKAGE_NAME, "proposal_generator.py"), + path.join(UTILITIES_PATH, "keygenerator.sh"), + path.join(UTILITIES_PATH, "scurl.sh"), + path.join(UTILITIES_PATH, "submit_recovery_share.sh"), + ], + include_package_data=True, +) diff --git a/src/ds/openapi.h b/src/ds/openapi.h index 2fdabac5181..8c552149ad6 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -21,20 +21,20 @@ namespace ds { namespace access { - nlohmann::json& get_object(nlohmann::json& j, const std::string& k) + static nlohmann::json& get_object(nlohmann::json& j, const std::string& k) { const auto ib = j.emplace(k, nlohmann::json::object()); return ib.first.value(); } - nlohmann::json& get_array(nlohmann::json& j, const std::string& k) + static nlohmann::json& get_array(nlohmann::json& j, const std::string& k) { const auto ib = j.emplace(k, nlohmann::json::array()); return ib.first.value(); } } - nlohmann::json create_document( + static nlohmann::json create_document( const std::string& title, const std::string& description, const std::string& document_version) @@ -49,21 +49,21 @@ namespace ds {"paths", nlohmann::json::object()}}; } - nlohmann::json& server(nlohmann::json& document, const std::string& url) + static nlohmann::json& server(nlohmann::json& document, const std::string& url) { auto& servers = access::get_object(document, "servers"); servers.push_back({{"url", url}}); return servers.back(); } - nlohmann::json& path(nlohmann::json& document, const std::string& path) + static nlohmann::json& path(nlohmann::json& document, const std::string& path) { // TODO: Check that path starts with /? auto& paths = access::get_object(document, "paths"); return access::get_object(paths, path); } - nlohmann::json& path_operation(nlohmann::json& path, http_method verb) + static nlohmann::json& path_operation(nlohmann::json& path, http_method verb) { // HTTP_GET becomes the string "get" std::string s = http_method_str(verb); @@ -71,7 +71,7 @@ namespace ds return access::get_object(path, s); } - nlohmann::json& response( + static nlohmann::json& response( nlohmann::json& path_operation, http_status status, const std::string& description = "Default response description") @@ -85,7 +85,7 @@ namespace ds return response; } - nlohmann::json& request_body( + static nlohmann::json& request_body( nlohmann::json& path_operation ) { @@ -94,7 +94,7 @@ namespace ds return request_body; } - nlohmann::json& media_type( + static nlohmann::json& media_type( nlohmann::json& j, const std::string& mt ) From b7e75ea309a8872e2938aa053f3a6ac4b19275f5 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Wed, 9 Sep 2020 17:26:09 +0100 Subject: [PATCH 23/53] Get to compilation --- CMakeLists.txt | 4 +-- src/apps/js_generic/js_generic.cpp | 2 +- src/apps/lua_generic/lua_generic.cpp | 2 +- src/ds/json.h | 17 ++++++---- src/ds/nonstd.h | 4 +-- src/ds/openapi.h | 41 ++++++++++++++++--------- src/node/rpc/call_types.h | 12 +------- src/node/rpc/common_endpoint_registry.h | 10 +++--- src/node/rpc/endpoint_registry.h | 15 ++++++--- src/node/rpc/serialization.h | 6 ---- 10 files changed, 60 insertions(+), 53 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 13a0a2f6f69..51813ba3a22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -253,9 +253,9 @@ if(BUILD_TESTS) ) add_unit_test( - openapi ${CMAKE_CURRENT_SOURCE_DIR}/src/ds/test/openapi.cpp + openapi_test ${CMAKE_CURRENT_SOURCE_DIR}/src/ds/test/openapi.cpp ) - target_link_libraries(openapi PRIVATE http_parser.host) + target_link_libraries(openapi_test PRIVATE http_parser.host) add_unit_test( logger_json_test diff --git a/src/apps/js_generic/js_generic.cpp b/src/apps/js_generic/js_generic.cpp index d024962a42c..f2efb1eeabc 100644 --- a/src/apps/js_generic/js_generic.cpp +++ b/src/apps/js_generic/js_generic.cpp @@ -584,7 +584,7 @@ namespace ccfapp // Since we do our own dispatch within the default handler, report the // supported methods here - void build_api(ds::openapi::Document& document, kv::Tx& tx) override + void build_api(nlohmann::json& document, kv::Tx& tx) override { UserEndpointRegistry::build_api(document, tx); diff --git a/src/apps/lua_generic/lua_generic.cpp b/src/apps/lua_generic/lua_generic.cpp index 8b06c818f4d..0263d9d2ebf 100644 --- a/src/apps/lua_generic/lua_generic.cpp +++ b/src/apps/lua_generic/lua_generic.cpp @@ -187,7 +187,7 @@ namespace ccfapp // Since we do our own dispatch within the default handler, report the // supported methods here - void build_api(ds::openapi::Document& document, kv::Tx& tx) override + void build_api(nlohmann::json& document, kv::Tx& tx) override { UserEndpointRegistry::build_api(document, tx); diff --git a/src/ds/json.h b/src/ds/json.h index d27f9f1e112..27f7393d133 100644 --- a/src/ds/json.h +++ b/src/ds/json.h @@ -549,7 +549,7 @@ namespace std fill_json_schema_required_fields(j, t); \ POST_FILL_SCHEMA; \ } \ - inline std::string schema_name(const TYPE& t) \ + inline std::string schema_name(const TYPE&) \ { \ return #TYPE; \ } \ @@ -599,7 +599,8 @@ namespace std add_schema_components_optional_fields(doc, j, t)) #define DECLARE_JSON_REQUIRED_FIELDS(TYPE, ...) \ - inline void to_json_required_fields(nlohmann::json& j, const TYPE& t) \ + inline void to_json_required_fields( \ + nlohmann::json& j, [[maybe_unused]] const TYPE& t) \ { \ if (!j.is_object()) \ { \ @@ -607,7 +608,8 @@ namespace std } \ _FOR_JSON_COUNT_NN(__VA_ARGS__)(POP1)(WRITE_REQUIRED, TYPE, ##__VA_ARGS__) \ } \ - inline void from_json_required_fields(const nlohmann::json& j, TYPE& t) \ + inline void from_json_required_fields( \ + const nlohmann::json& j, [[maybe_unused]] TYPE& t) \ { \ if (!j.is_object()) \ { \ @@ -615,7 +617,8 @@ namespace std } \ _FOR_JSON_COUNT_NN(__VA_ARGS__)(POP1)(READ_REQUIRED, TYPE, ##__VA_ARGS__) \ } \ - inline void fill_json_schema_required_fields(nlohmann::json& j, const TYPE&) \ + inline void fill_json_schema_required_fields( \ + nlohmann::json& j, [[maybe_unused]] const TYPE& t) \ { \ j["type"] = "object"; \ _FOR_JSON_COUNT_NN(__VA_ARGS__) \ @@ -623,7 +626,9 @@ namespace std } \ template \ void add_schema_components_required_fields( \ - T& doc, nlohmann::json& j, const TYPE& t) \ + [[maybe_unused]] T& doc, \ + nlohmann::json& j, \ + [[maybe_unused]] const TYPE& t) \ { \ j["type"] = "object"; \ _FOR_JSON_COUNT_NN(__VA_ARGS__) \ @@ -681,7 +686,7 @@ namespace std } \ template \ void add_schema_components_optional_fields( \ - T& doc, nlohmann::json& j, const TYPE& t) \ + T& doc, nlohmann::json& j, const TYPE&) \ { \ _FOR_JSON_COUNT_NN(__VA_ARGS__) \ (POP1)(ADD_SCHEMA_COMPONENTS_OPTIONAL, TYPE, ##__VA_ARGS__); \ diff --git a/src/ds/nonstd.h b/src/ds/nonstd.h index 359107dac19..f5ac042be37 100644 --- a/src/ds/nonstd.h +++ b/src/ds/nonstd.h @@ -64,14 +64,14 @@ namespace nonstd /** converts strings to upper or lower case, in-place */ - static void to_upper(std::string& s) + static inline void to_upper(std::string& s) { std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::toupper(c); }); } - static void to_lower(std::string& s) + static inline void to_lower(std::string& s) { std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); diff --git a/src/ds/openapi.h b/src/ds/openapi.h index 8c552149ad6..669d093b75d 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -9,6 +9,9 @@ #include #include +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" + namespace ds { /** @@ -21,20 +24,22 @@ namespace ds { namespace access { - static nlohmann::json& get_object(nlohmann::json& j, const std::string& k) + static inline nlohmann::json& get_object( + nlohmann::json& j, const std::string& k) { const auto ib = j.emplace(k, nlohmann::json::object()); return ib.first.value(); } - static nlohmann::json& get_array(nlohmann::json& j, const std::string& k) + static inline nlohmann::json& get_array( + nlohmann::json& j, const std::string& k) { const auto ib = j.emplace(k, nlohmann::json::array()); return ib.first.value(); } } - static nlohmann::json create_document( + static inline nlohmann::json create_document( const std::string& title, const std::string& description, const std::string& document_version) @@ -49,21 +54,24 @@ namespace ds {"paths", nlohmann::json::object()}}; } - static nlohmann::json& server(nlohmann::json& document, const std::string& url) + static inline nlohmann::json& server( + nlohmann::json& document, const std::string& url) { auto& servers = access::get_object(document, "servers"); servers.push_back({{"url", url}}); return servers.back(); } - static nlohmann::json& path(nlohmann::json& document, const std::string& path) + static inline nlohmann::json& path( + nlohmann::json& document, const std::string& path) { // TODO: Check that path starts with /? auto& paths = access::get_object(document, "paths"); return access::get_object(paths, path); } - static nlohmann::json& path_operation(nlohmann::json& path, http_method verb) + static inline nlohmann::json& path_operation( + nlohmann::json& path, http_method verb) { // HTTP_GET becomes the string "get" std::string s = http_method_str(verb); @@ -71,7 +79,14 @@ namespace ds return access::get_object(path, s); } - static nlohmann::json& response( + static inline nlohmann::json& path_operation( + nlohmann::json& path, std::string s) + { + nonstd::to_lower(s); + return access::get_object(path, s); + } + + static inline nlohmann::json& response( nlohmann::json& path_operation, http_status status, const std::string& description = "Default response description") @@ -85,19 +100,15 @@ namespace ds return response; } - static nlohmann::json& request_body( - nlohmann::json& path_operation - ) + static inline nlohmann::json& request_body(nlohmann::json& path_operation) { auto& request_body = access::get_object(path_operation, "requestBody"); access::get_object(request_body, "content"); return request_body; } - static nlohmann::json& media_type( - nlohmann::json& j, - const std::string& mt - ) + static inline nlohmann::json& media_type( + nlohmann::json& j, const std::string& mt) { auto& content = access::get_object(j, "content"); return access::get_object(content, mt); @@ -402,3 +413,5 @@ namespace ds DECLARE_JSON_OPTIONAL_FIELDS(Document, servers, components); } } + +#pragma clang diagnostic pop diff --git a/src/node/rpc/call_types.h b/src/node/rpc/call_types.h index f880ead0461..97e66927cc3 100644 --- a/src/node/rpc/call_types.h +++ b/src/node/rpc/call_types.h @@ -134,18 +134,8 @@ namespace ccf struct GetAPI { - struct Endpoint - { - std::string verb; - std::string path; - }; - // TODO: What is the format of this now? - //using Out = nlohmann::json; - struct Out - { - std::vector endpoints; - }; + using Out = nlohmann::json; }; struct EndpointMetrics diff --git a/src/node/rpc/common_endpoint_registry.h b/src/node/rpc/common_endpoint_registry.h index cc3b0965d14..2dc53a8e582 100644 --- a/src/node/rpc/common_endpoint_registry.h +++ b/src/node/rpc/common_endpoint_registry.h @@ -218,7 +218,8 @@ namespace ccf .install(); auto openapi = [this](kv::Tx& tx, nlohmann::json&&) { - ds::openapi::Document document; + // TODO: Update these + auto document = ds::openapi::create_document("Placeholder title", "Placeholder description", "1.0.0"); build_api(document, tx); return make_success(document); }; @@ -276,10 +277,9 @@ namespace ccf if (j.empty()) { - std::string verb_name = http_method_str(verb); - nonstd::to_lower(verb_name); - j[verb_name] = - GetSchema::Out{endpoint.params_schema, endpoint.result_schema}; + return make_error( + HTTP_STATUS_BAD_REQUEST, + fmt::format("Method {} not recognised", in.method)); } return make_success(j); diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index d8521948c82..861f38ddf1c 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -449,15 +449,20 @@ namespace ccf * with the supported endpoints however it defines them. */ // TODO: May want the entire rpc context, not just tx? - virtual void build_api(ds::openapi::Document& document, kv::Tx& tx) + virtual void build_api(nlohmann::json& document, kv::Tx&) { for (const auto& [path, verb_endpoints] : fully_qualified_endpoints) { - const auto full_path = fmt::format("/{}/{}", method_prefix, method); - auto& path_object = document.paths[full_path]; - for (const auto& [verb, handler] : verb_handlers) + const auto full_path = fmt::format("/{}/{}", method_prefix, path); + auto& path_object = ds::openapi::path(document, "/users/foo"); + for (const auto& [verb, handler] : verb_endpoints) { - path_object[verb][HTTP_STATUS_OK].description = "Auto-generated"; + auto& path_operation = ds::openapi::path_operation(path_object, verb.c_str()); + auto& path_response_ok = ds::openapi::response( + path_operation, HTTP_STATUS_OK, "Auto-generated"); + auto& path_response_ok_json = ds::openapi::media_type( + path_response_ok, http::headervalues::contenttype::JSON); + path_response_ok_json["schema"] = "Placeholder"; } } diff --git a/src/node/rpc/serialization.h b/src/node/rpc/serialization.h index cd801c84c78..d4bdca1c51f 100644 --- a/src/node/rpc/serialization.h +++ b/src/node/rpc/serialization.h @@ -112,12 +112,6 @@ namespace ccf DECLARE_JSON_TYPE(GetUserId::In) DECLARE_JSON_REQUIRED_FIELDS(GetUserId::In, cert) - //DECLARE_JSON_TYPE(GetAPI::Out) - DECLARE_JSON_TYPE(ListMethods::Endpoint) - DECLARE_JSON_REQUIRED_FIELDS(ListMethods::Endpoint, verb, path) - DECLARE_JSON_TYPE(ListMethods::Out) - DECLARE_JSON_REQUIRED_FIELDS(ListMethods::Out, endpoints) - DECLARE_JSON_TYPE(EndpointMetrics::Metric) DECLARE_JSON_REQUIRED_FIELDS(EndpointMetrics::Metric, calls, errors, failures) DECLARE_JSON_TYPE(EndpointMetrics::Out) From 55a4f73254f22f2335f1b476067444a28fa84208 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Wed, 9 Sep 2020 18:11:35 +0100 Subject: [PATCH 24/53] Update schema.py to just validate that the result is a valid OpenAPI doc --- src/ds/openapi.h | 7 --- src/enclave/rpc_context.h | 10 +++ src/node/rpc/endpoint_registry.h | 12 +++- tests/requirements.txt | 3 +- tests/schema.py | 104 ++++++++++++++++--------------- 5 files changed, 75 insertions(+), 61 deletions(-) diff --git a/src/ds/openapi.h b/src/ds/openapi.h index 669d093b75d..709bc313651 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -79,13 +79,6 @@ namespace ds return access::get_object(path, s); } - static inline nlohmann::json& path_operation( - nlohmann::json& path, std::string s) - { - nonstd::to_lower(s); - return access::get_object(path, s); - } - static inline nlohmann::json& response( nlohmann::json& path_operation, http_status status, diff --git a/src/enclave/rpc_context.h b/src/enclave/rpc_context.h index 3a337a38cde..0a672ed3dd4 100644 --- a/src/enclave/rpc_context.h +++ b/src/enclave/rpc_context.h @@ -35,6 +35,16 @@ namespace ccf RESTVerb(const http_method& hm) : verb(hm) {} RESTVerb(const ws::Verb& wv) : verb(wv) {} + std::optional get_http_method() const + { + if (verb == ws::WEBSOCKET) + { + return std::nullopt; + } + + return static_cast(verb); + } + const char* c_str() const { if (verb == ws::WEBSOCKET) diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index 861f38ddf1c..2689a48abcb 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -454,15 +454,21 @@ namespace ccf for (const auto& [path, verb_endpoints] : fully_qualified_endpoints) { const auto full_path = fmt::format("/{}/{}", method_prefix, path); - auto& path_object = ds::openapi::path(document, "/users/foo"); + auto& path_object = ds::openapi::path(document, full_path); for (const auto& [verb, handler] : verb_endpoints) { - auto& path_operation = ds::openapi::path_operation(path_object, verb.c_str()); + const auto http_verb = verb.get_http_method(); + if (!http_verb.has_value()) + { + continue; + } + + auto& path_operation = ds::openapi::path_operation(path_object, http_verb.value()); auto& path_response_ok = ds::openapi::response( path_operation, HTTP_STATUS_OK, "Auto-generated"); auto& path_response_ok_json = ds::openapi::media_type( path_response_ok, http::headervalues::contenttype::JSON); - path_response_ok_json["schema"] = "Placeholder"; + path_response_ok_json["schema"] = {{"type", "string"}}; } } diff --git a/tests/requirements.txt b/tests/requirements.txt index 6d08506e3bf..b8477ee3999 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -4,4 +4,5 @@ loguru coincurve psutil cimetrics>=0.2.1 -pynacl \ No newline at end of file +pynacl +openapi-spec-validator \ No newline at end of file diff --git a/tests/schema.py b/tests/schema.py index a8fed060e14..0cd57a786b5 100644 --- a/tests/schema.py +++ b/tests/schema.py @@ -8,6 +8,8 @@ import infra.proc import infra.e2e_args import infra.checker +from openapi_spec_validator import validate_spec + from loguru import logger as LOG @@ -32,58 +34,60 @@ def run(args): all_methods = [] def fetch_schema(client, prefix): - list_response = client.get(f"/{prefix}/api") + api_response = client.get(f"/{prefix}/api") check( - list_response, error=lambda status, msg: status == http.HTTPStatus.OK.value + api_response, error=lambda status, msg: status == http.HTTPStatus.OK.value ) - LOG.warning(list_response) - methods = list_response.body["endpoints"] - all_methods.extend([m["path"] for m in methods]) - - for method in [m["path"] for m in methods]: - schema_found = False - schema_response = client.get(f'/{prefix}/api/schema?method="{method}"') - check( - schema_response, - error=lambda status, msg: status == http.HTTPStatus.OK.value, - ) - - if schema_response.body is not None: - for verb, schema_element in schema_response.body.items(): - for schema_type in ["params", "result"]: - element_name = "{}_schema".format(schema_type) - element = schema_element[element_name] - target_file = build_schema_file_path( - args.schema_dir, verb, method, schema_type - ) - if element is not None and len(element) != 0: - try: - old_schema.remove(target_file) - except KeyError: - pass - schema_found = True - formatted_schema = json.dumps(element, indent=2) - os.makedirs(os.path.dirname(target_file), exist_ok=True) - with open(target_file, "a+") as f: - f.seek(0) - previous = f.read() - if previous != formatted_schema: - LOG.debug( - "Writing schema to {}".format(target_file) - ) - f.truncate(0) - f.seek(0) - f.write(formatted_schema) - changed_files.append(target_file) - else: - LOG.debug( - "Schema matches in {}".format(target_file) - ) - - if schema_found: - methods_with_schema.add(method) - else: - methods_without_schema.add(method) + LOG.warning(json.dumps(api_response.body, indent=2)) + paths = api_response.body["paths"] + all_methods.extend([key for key in paths.keys()]) + + validate_spec(api_response.body) + + # for path, path_item in paths.items(): + # schema_found = False + # schema_response = client.get(f'/{prefix}/api/schema?method="{path}"') + # check( + # schema_response, + # error=lambda status, msg: status == http.HTTPStatus.OK.value, + # ) + + # if schema_response.body is not None: + # for verb, schema_element in schema_response.body.items(): + # for schema_type in ["params", "result"]: + # element_name = "{}_schema".format(schema_type) + # element = schema_element[element_name] + # target_file = build_schema_file_path( + # args.schema_dir, verb, path, schema_type + # ) + # if element is not None and len(element) != 0: + # try: + # old_schema.remove(target_file) + # except KeyError: + # pass + # schema_found = True + # formatted_schema = json.dumps(element, indent=2) + # os.makedirs(os.path.dirname(target_file), exist_ok=True) + # with open(target_file, "a+") as f: + # f.seek(0) + # previous = f.read() + # if previous != formatted_schema: + # LOG.debug( + # "Writing schema to {}".format(target_file) + # ) + # f.truncate(0) + # f.seek(0) + # f.write(formatted_schema) + # changed_files.append(target_file) + # else: + # LOG.debug( + # "Schema matches in {}".format(target_file) + # ) + + # if schema_found: + # methods_with_schema.add(path) + # else: + # methods_without_schema.add(path) with infra.network.network( hosts, args.binary_dir, args.debug_nodes, args.perf_nodes From 9c6adcc2eb438cd5e67995fa649222d1321be04e Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Wed, 9 Sep 2020 18:11:46 +0100 Subject: [PATCH 25/53] Remove separate schema. Oh no --- .../ack/update_state_digest_POST_result.json | 63 ---------------- doc/schemas/ack_POST_params.json | 18 ----- doc/schemas/ack_POST_result.json | 5 -- doc/schemas/api/schema_GET_params.json | 13 ---- doc/schemas/api/schema_GET_result.json | 17 ----- doc/schemas/api_GET_result.json | 28 ------- doc/schemas/code_GET_result.json | 31 -------- doc/schemas/commit_GET_result.json | 21 ------ doc/schemas/endpoint_metrics_GET_result.json | 57 -------------- .../log/private/admin_only_POST_params.json | 19 ----- .../log/private/admin_only_POST_result.json | 5 -- .../log/private/anonymous_POST_params.json | 19 ----- .../log/private/anonymous_POST_result.json | 5 -- doc/schemas/log/private_DELETE_params.json | 15 ---- doc/schemas/log/private_DELETE_result.json | 5 -- doc/schemas/log/private_GET_params.json | 15 ---- doc/schemas/log/private_GET_result.json | 13 ---- doc/schemas/log/private_POST_params.json | 19 ----- doc/schemas/log/private_POST_result.json | 5 -- doc/schemas/log/private_WEBSOCKET_params.json | 19 ----- doc/schemas/log/private_WEBSOCKET_result.json | 5 -- doc/schemas/log/public_DELETE_params.json | 15 ---- doc/schemas/log/public_DELETE_result.json | 5 -- doc/schemas/log/public_GET_params.json | 13 ---- doc/schemas/log/public_GET_result.json | 13 ---- doc/schemas/log/public_POST_params.json | 17 ----- doc/schemas/log/public_POST_result.json | 5 -- doc/schemas/metrics_GET_result.json | 45 ----------- doc/schemas/network_info_GET_result.json | 40 ---------- doc/schemas/node/ids_GET_params.json | 17 ----- doc/schemas/node/ids_GET_result.json | 34 --------- doc/schemas/primary_info_GET_result.json | 29 -------- .../{proposal_id}/complete_POST_result.json | 31 -------- .../votes/{member_id}_GET_result.json | 26 ------- .../{proposal_id}/votes_POST_params.json | 26 ------- .../{proposal_id}/votes_POST_result.json | 31 -------- .../{proposal_id}/withdraw_POST_result.json | 31 -------- .../proposals/{proposal_id}_GET_result.json | 74 ------------------- doc/schemas/proposals_POST_params.json | 43 ----------- doc/schemas/proposals_POST_result.json | 31 -------- doc/schemas/query_POST_params.json | 18 ----- doc/schemas/query_POST_result.json | 4 - doc/schemas/quote_GET_result.json | 36 --------- doc/schemas/quotes_GET_result.json | 36 --------- doc/schemas/read_POST_params.json | 15 ---- doc/schemas/read_POST_result.json | 4 - doc/schemas/receipt/verify_POST_params.json | 18 ----- doc/schemas/receipt/verify_POST_result.json | 13 ---- doc/schemas/receipt_GET_params.json | 15 ---- doc/schemas/receipt_GET_result.json | 18 ----- .../recovery_share/submit_POST_params.json | 5 -- .../recovery_share/submit_POST_result.json | 5 -- doc/schemas/recovery_share_GET_result.json | 17 ----- doc/schemas/state_GET_result.json | 43 ----------- doc/schemas/tx_GET_params.json | 21 ------ doc/schemas/tx_GET_result.json | 18 ----- doc/schemas/user_id_GET_params.json | 18 ----- doc/schemas/user_id_GET_result.json | 15 ---- 58 files changed, 1242 deletions(-) delete mode 100644 doc/schemas/ack/update_state_digest_POST_result.json delete mode 100644 doc/schemas/ack_POST_params.json delete mode 100644 doc/schemas/ack_POST_result.json delete mode 100644 doc/schemas/api/schema_GET_params.json delete mode 100644 doc/schemas/api/schema_GET_result.json delete mode 100644 doc/schemas/api_GET_result.json delete mode 100644 doc/schemas/code_GET_result.json delete mode 100644 doc/schemas/commit_GET_result.json delete mode 100644 doc/schemas/endpoint_metrics_GET_result.json delete mode 100644 doc/schemas/log/private/admin_only_POST_params.json delete mode 100644 doc/schemas/log/private/admin_only_POST_result.json delete mode 100644 doc/schemas/log/private/anonymous_POST_params.json delete mode 100644 doc/schemas/log/private/anonymous_POST_result.json delete mode 100644 doc/schemas/log/private_DELETE_params.json delete mode 100644 doc/schemas/log/private_DELETE_result.json delete mode 100644 doc/schemas/log/private_GET_params.json delete mode 100644 doc/schemas/log/private_GET_result.json delete mode 100644 doc/schemas/log/private_POST_params.json delete mode 100644 doc/schemas/log/private_POST_result.json delete mode 100644 doc/schemas/log/private_WEBSOCKET_params.json delete mode 100644 doc/schemas/log/private_WEBSOCKET_result.json delete mode 100644 doc/schemas/log/public_DELETE_params.json delete mode 100644 doc/schemas/log/public_DELETE_result.json delete mode 100644 doc/schemas/log/public_GET_params.json delete mode 100644 doc/schemas/log/public_GET_result.json delete mode 100644 doc/schemas/log/public_POST_params.json delete mode 100644 doc/schemas/log/public_POST_result.json delete mode 100644 doc/schemas/metrics_GET_result.json delete mode 100644 doc/schemas/network_info_GET_result.json delete mode 100644 doc/schemas/node/ids_GET_params.json delete mode 100644 doc/schemas/node/ids_GET_result.json delete mode 100644 doc/schemas/primary_info_GET_result.json delete mode 100644 doc/schemas/proposals/{proposal_id}/complete_POST_result.json delete mode 100644 doc/schemas/proposals/{proposal_id}/votes/{member_id}_GET_result.json delete mode 100644 doc/schemas/proposals/{proposal_id}/votes_POST_params.json delete mode 100644 doc/schemas/proposals/{proposal_id}/votes_POST_result.json delete mode 100644 doc/schemas/proposals/{proposal_id}/withdraw_POST_result.json delete mode 100644 doc/schemas/proposals/{proposal_id}_GET_result.json delete mode 100644 doc/schemas/proposals_POST_params.json delete mode 100644 doc/schemas/proposals_POST_result.json delete mode 100644 doc/schemas/query_POST_params.json delete mode 100644 doc/schemas/query_POST_result.json delete mode 100644 doc/schemas/quote_GET_result.json delete mode 100644 doc/schemas/quotes_GET_result.json delete mode 100644 doc/schemas/read_POST_params.json delete mode 100644 doc/schemas/read_POST_result.json delete mode 100644 doc/schemas/receipt/verify_POST_params.json delete mode 100644 doc/schemas/receipt/verify_POST_result.json delete mode 100644 doc/schemas/receipt_GET_params.json delete mode 100644 doc/schemas/receipt_GET_result.json delete mode 100644 doc/schemas/recovery_share/submit_POST_params.json delete mode 100644 doc/schemas/recovery_share/submit_POST_result.json delete mode 100644 doc/schemas/recovery_share_GET_result.json delete mode 100644 doc/schemas/state_GET_result.json delete mode 100644 doc/schemas/tx_GET_params.json delete mode 100644 doc/schemas/tx_GET_result.json delete mode 100644 doc/schemas/user_id_GET_params.json delete mode 100644 doc/schemas/user_id_GET_result.json diff --git a/doc/schemas/ack/update_state_digest_POST_result.json b/doc/schemas/ack/update_state_digest_POST_result.json deleted file mode 100644 index c733d7ac7e0..00000000000 --- a/doc/schemas/ack/update_state_digest_POST_result.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "signed_req": { - "properties": { - "md": { - "enum": [ - "MBEDTLS_MD_NONE", - "MBEDTLS_MD_SHA1", - "MBEDTLS_MD_SHA256", - "MBEDTLS_MD_SHA384", - "MBEDTLS_MD_SHA512" - ] - }, - "req": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "request_body": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "sig": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "sig", - "req", - "request_body", - "md" - ], - "type": "object" - }, - "state_digest": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "state_digest", - "signed_req" - ], - "title": "ack/update_state_digest/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/ack_POST_params.json b/doc/schemas/ack_POST_params.json deleted file mode 100644 index fb3c0178a2c..00000000000 --- a/doc/schemas/ack_POST_params.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "state_digest": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "state_digest" - ], - "title": "ack/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/ack_POST_result.json b/doc/schemas/ack_POST_result.json deleted file mode 100644 index 9c1c4ab18cd..00000000000 --- a/doc/schemas/ack_POST_result.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ack/result", - "type": "boolean" -} \ No newline at end of file diff --git a/doc/schemas/api/schema_GET_params.json b/doc/schemas/api/schema_GET_params.json deleted file mode 100644 index ac6a17363a7..00000000000 --- a/doc/schemas/api/schema_GET_params.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "method": { - "type": "string" - } - }, - "required": [ - "method" - ], - "title": "api/schema/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/api/schema_GET_result.json b/doc/schemas/api/schema_GET_result.json deleted file mode 100644 index 1351f0d663d..00000000000 --- a/doc/schemas/api/schema_GET_result.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "params_schema": { - "$ref": "http://json-schema.org/draft-07/schema#" - }, - "result_schema": { - "$ref": "http://json-schema.org/draft-07/schema#" - } - }, - "required": [ - "params_schema", - "result_schema" - ], - "title": "api/schema/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/api_GET_result.json b/doc/schemas/api_GET_result.json deleted file mode 100644 index aa1e80bef5b..00000000000 --- a/doc/schemas/api_GET_result.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "endpoints": { - "items": { - "properties": { - "path": { - "type": "string" - }, - "verb": { - "type": "string" - } - }, - "required": [ - "verb", - "path" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "endpoints" - ], - "title": "api/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/code_GET_result.json b/doc/schemas/code_GET_result.json deleted file mode 100644 index 2e76eae947a..00000000000 --- a/doc/schemas/code_GET_result.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "versions": { - "items": { - "properties": { - "digest": { - "type": "string" - }, - "status": { - "enum": [ - "ACCEPTED", - "RETIRED" - ] - } - }, - "required": [ - "digest", - "status" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "versions" - ], - "title": "code/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/commit_GET_result.json b/doc/schemas/commit_GET_result.json deleted file mode 100644 index 2f3be75f8b0..00000000000 --- a/doc/schemas/commit_GET_result.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - } - }, - "required": [ - "view", - "seqno" - ], - "title": "commit/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/endpoint_metrics_GET_result.json b/doc/schemas/endpoint_metrics_GET_result.json deleted file mode 100644 index 914b658992e..00000000000 --- a/doc/schemas/endpoint_metrics_GET_result.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "metrics": { - "items": { - "items": [ - { - "type": "string" - }, - { - "items": { - "items": [ - { - "type": "string" - }, - { - "properties": { - "calls": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "errors": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "failures": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "calls", - "errors", - "failures" - ], - "type": "object" - } - ], - "type": "array" - }, - "type": "array" - } - ], - "type": "array" - }, - "type": "array" - } - }, - "required": [ - "metrics" - ], - "title": "endpoint_metrics/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/log/private/admin_only_POST_params.json b/doc/schemas/log/private/admin_only_POST_params.json deleted file mode 100644 index ceaabad8d66..00000000000 --- a/doc/schemas/log/private/admin_only_POST_params.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "msg": { - "type": "string" - } - }, - "required": [ - "id", - "msg" - ], - "title": "log/private/admin_only/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/log/private/admin_only_POST_result.json b/doc/schemas/log/private/admin_only_POST_result.json deleted file mode 100644 index fcd126c2653..00000000000 --- a/doc/schemas/log/private/admin_only_POST_result.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "log/private/admin_only/result", - "type": "boolean" -} \ No newline at end of file diff --git a/doc/schemas/log/private/anonymous_POST_params.json b/doc/schemas/log/private/anonymous_POST_params.json deleted file mode 100644 index 8804ee0b1cb..00000000000 --- a/doc/schemas/log/private/anonymous_POST_params.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "msg": { - "type": "string" - } - }, - "required": [ - "id", - "msg" - ], - "title": "log/private/anonymous/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/log/private/anonymous_POST_result.json b/doc/schemas/log/private/anonymous_POST_result.json deleted file mode 100644 index 90b546a12e0..00000000000 --- a/doc/schemas/log/private/anonymous_POST_result.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "log/private/anonymous/result", - "type": "boolean" -} \ No newline at end of file diff --git a/doc/schemas/log/private_DELETE_params.json b/doc/schemas/log/private_DELETE_params.json deleted file mode 100644 index d0c68127024..00000000000 --- a/doc/schemas/log/private_DELETE_params.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "id" - ], - "title": "log/private/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/log/private_DELETE_result.json b/doc/schemas/log/private_DELETE_result.json deleted file mode 100644 index 71f54370042..00000000000 --- a/doc/schemas/log/private_DELETE_result.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "log/private/result", - "type": "boolean" -} \ No newline at end of file diff --git a/doc/schemas/log/private_GET_params.json b/doc/schemas/log/private_GET_params.json deleted file mode 100644 index d0c68127024..00000000000 --- a/doc/schemas/log/private_GET_params.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "id" - ], - "title": "log/private/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/log/private_GET_result.json b/doc/schemas/log/private_GET_result.json deleted file mode 100644 index 69d63f77b21..00000000000 --- a/doc/schemas/log/private_GET_result.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "msg": { - "type": "string" - } - }, - "required": [ - "msg" - ], - "title": "log/private/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/log/private_POST_params.json b/doc/schemas/log/private_POST_params.json deleted file mode 100644 index e26f8a7fcc1..00000000000 --- a/doc/schemas/log/private_POST_params.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "msg": { - "type": "string" - } - }, - "required": [ - "id", - "msg" - ], - "title": "log/private/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/log/private_POST_result.json b/doc/schemas/log/private_POST_result.json deleted file mode 100644 index 71f54370042..00000000000 --- a/doc/schemas/log/private_POST_result.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "log/private/result", - "type": "boolean" -} \ No newline at end of file diff --git a/doc/schemas/log/private_WEBSOCKET_params.json b/doc/schemas/log/private_WEBSOCKET_params.json deleted file mode 100644 index e26f8a7fcc1..00000000000 --- a/doc/schemas/log/private_WEBSOCKET_params.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "msg": { - "type": "string" - } - }, - "required": [ - "id", - "msg" - ], - "title": "log/private/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/log/private_WEBSOCKET_result.json b/doc/schemas/log/private_WEBSOCKET_result.json deleted file mode 100644 index 71f54370042..00000000000 --- a/doc/schemas/log/private_WEBSOCKET_result.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "log/private/result", - "type": "boolean" -} \ No newline at end of file diff --git a/doc/schemas/log/public_DELETE_params.json b/doc/schemas/log/public_DELETE_params.json deleted file mode 100644 index 98ee62d9f25..00000000000 --- a/doc/schemas/log/public_DELETE_params.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "id" - ], - "title": "log/public/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/log/public_DELETE_result.json b/doc/schemas/log/public_DELETE_result.json deleted file mode 100644 index e0f82e22e8f..00000000000 --- a/doc/schemas/log/public_DELETE_result.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "log/public/result", - "type": "boolean" -} \ No newline at end of file diff --git a/doc/schemas/log/public_GET_params.json b/doc/schemas/log/public_GET_params.json deleted file mode 100644 index d5ba681836e..00000000000 --- a/doc/schemas/log/public_GET_params.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "id": { - "type": "number" - } - }, - "required": [ - "id" - ], - "title": "log/public/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/log/public_GET_result.json b/doc/schemas/log/public_GET_result.json deleted file mode 100644 index f835f4c47fd..00000000000 --- a/doc/schemas/log/public_GET_result.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "msg": { - "type": "string" - } - }, - "required": [ - "msg" - ], - "title": "log/public/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/log/public_POST_params.json b/doc/schemas/log/public_POST_params.json deleted file mode 100644 index 90a9d7c15db..00000000000 --- a/doc/schemas/log/public_POST_params.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "id": { - "type": "number" - }, - "msg": { - "type": "string" - } - }, - "required": [ - "id", - "msg" - ], - "title": "log/public/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/log/public_POST_result.json b/doc/schemas/log/public_POST_result.json deleted file mode 100644 index 4aa3c762269..00000000000 --- a/doc/schemas/log/public_POST_result.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "log/public/result", - "type": "bool" -} \ No newline at end of file diff --git a/doc/schemas/metrics_GET_result.json b/doc/schemas/metrics_GET_result.json deleted file mode 100644 index 9ea8c00bd85..00000000000 --- a/doc/schemas/metrics_GET_result.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "histogram": { - "properties": { - "buckets": {}, - "high": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "low": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "overflow": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "underflow": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "low", - "high", - "overflow", - "underflow", - "buckets" - ], - "type": "object" - }, - "tx_rates": {} - }, - "required": [ - "histogram", - "tx_rates" - ], - "title": "metrics/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/network_info_GET_result.json b/doc/schemas/network_info_GET_result.json deleted file mode 100644 index aff7664a939..00000000000 --- a/doc/schemas/network_info_GET_result.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "nodes": { - "items": { - "properties": { - "host": { - "type": "string" - }, - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "port": { - "type": "string" - } - }, - "required": [ - "node_id", - "host", - "port" - ], - "type": "object" - }, - "type": "array" - }, - "primary_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "nodes", - "primary_id" - ], - "title": "network_info/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/node/ids_GET_params.json b/doc/schemas/node/ids_GET_params.json deleted file mode 100644 index c5e859a8264..00000000000 --- a/doc/schemas/node/ids_GET_params.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "host": { - "type": "string" - }, - "port": { - "type": "string" - } - }, - "required": [ - "host", - "port" - ], - "title": "node/ids/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/node/ids_GET_result.json b/doc/schemas/node/ids_GET_result.json deleted file mode 100644 index e4728dbba13..00000000000 --- a/doc/schemas/node/ids_GET_result.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "nodes": { - "items": { - "properties": { - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "status": { - "enum": [ - "PENDING", - "TRUSTED", - "RETIRED" - ] - } - }, - "required": [ - "node_id", - "status" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "nodes" - ], - "title": "node/ids/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/primary_info_GET_result.json b/doc/schemas/primary_info_GET_result.json deleted file mode 100644 index a326a9e9b93..00000000000 --- a/doc/schemas/primary_info_GET_result.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "current_view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "primary_host": { - "type": "string" - }, - "primary_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "primary_port": { - "type": "string" - } - }, - "required": [ - "primary_id", - "primary_host", - "primary_port", - "current_view" - ], - "title": "primary_info/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/complete_POST_result.json b/doc/schemas/proposals/{proposal_id}/complete_POST_result.json deleted file mode 100644 index 6280ae350bd..00000000000 --- a/doc/schemas/proposals/{proposal_id}/complete_POST_result.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "proposal_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "proposer_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "state": { - "enum": [ - "OPEN", - "ACCEPTED", - "WITHDRAWN", - "REJECTED", - "FAILED" - ] - } - }, - "required": [ - "proposal_id", - "proposer_id", - "state" - ], - "title": "proposals/{proposal_id}/complete/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/votes/{member_id}_GET_result.json b/doc/schemas/proposals/{proposal_id}/votes/{member_id}_GET_result.json deleted file mode 100644 index 2009e1654af..00000000000 --- a/doc/schemas/proposals/{proposal_id}/votes/{member_id}_GET_result.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "ballot": { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" - } - }, - "required": [ - "ballot" - ], - "title": "proposals/{proposal_id}/votes/{member_id}/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/votes_POST_params.json b/doc/schemas/proposals/{proposal_id}/votes_POST_params.json deleted file mode 100644 index 71b98f00e15..00000000000 --- a/doc/schemas/proposals/{proposal_id}/votes_POST_params.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "ballot": { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" - } - }, - "required": [ - "ballot" - ], - "title": "proposals/{proposal_id}/votes/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/votes_POST_result.json b/doc/schemas/proposals/{proposal_id}/votes_POST_result.json deleted file mode 100644 index 18f4d4df99f..00000000000 --- a/doc/schemas/proposals/{proposal_id}/votes_POST_result.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "proposal_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "proposer_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "state": { - "enum": [ - "OPEN", - "ACCEPTED", - "WITHDRAWN", - "REJECTED", - "FAILED" - ] - } - }, - "required": [ - "proposal_id", - "proposer_id", - "state" - ], - "title": "proposals/{proposal_id}/votes/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/withdraw_POST_result.json b/doc/schemas/proposals/{proposal_id}/withdraw_POST_result.json deleted file mode 100644 index 3bb507fc4c1..00000000000 --- a/doc/schemas/proposals/{proposal_id}/withdraw_POST_result.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "proposal_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "proposer_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "state": { - "enum": [ - "OPEN", - "ACCEPTED", - "WITHDRAWN", - "REJECTED", - "FAILED" - ] - } - }, - "required": [ - "proposal_id", - "proposer_id", - "state" - ], - "title": "proposals/{proposal_id}/withdraw/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}_GET_result.json b/doc/schemas/proposals/{proposal_id}_GET_result.json deleted file mode 100644 index d730343b949..00000000000 --- a/doc/schemas/proposals/{proposal_id}_GET_result.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "parameter": {}, - "proposer": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "script": { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" - }, - "state": { - "enum": [ - "OPEN", - "ACCEPTED", - "WITHDRAWN", - "REJECTED", - "FAILED" - ] - }, - "votes": { - "items": { - "items": [ - { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" - } - ], - "type": "array" - }, - "type": "array" - } - }, - "required": [ - "script", - "parameter", - "proposer", - "state", - "votes" - ], - "title": "proposals/{proposal_id}/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/proposals_POST_params.json b/doc/schemas/proposals_POST_params.json deleted file mode 100644 index 1afce0680a5..00000000000 --- a/doc/schemas/proposals_POST_params.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "ballot": { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" - }, - "parameter": {}, - "script": { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" - } - }, - "required": [ - "script" - ], - "title": "proposals/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/proposals_POST_result.json b/doc/schemas/proposals_POST_result.json deleted file mode 100644 index a68771ea0f8..00000000000 --- a/doc/schemas/proposals_POST_result.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "proposal_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "proposer_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "state": { - "enum": [ - "OPEN", - "ACCEPTED", - "WITHDRAWN", - "REJECTED", - "FAILED" - ] - } - }, - "required": [ - "proposal_id", - "proposer_id", - "state" - ], - "title": "proposals/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/query_POST_params.json b/doc/schemas/query_POST_params.json deleted file mode 100644 index 5b5c7289e4e..00000000000 --- a/doc/schemas/query_POST_params.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "title": "query/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/query_POST_result.json b/doc/schemas/query_POST_result.json deleted file mode 100644 index 432247374b9..00000000000 --- a/doc/schemas/query_POST_result.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "query/result" -} \ No newline at end of file diff --git a/doc/schemas/quote_GET_result.json b/doc/schemas/quote_GET_result.json deleted file mode 100644 index bf2633753d2..00000000000 --- a/doc/schemas/quote_GET_result.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "quotes": { - "items": { - "properties": { - "error": { - "type": "string" - }, - "mrenclave": { - "type": "string" - }, - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "raw": { - "type": "string" - } - }, - "required": [ - "node_id", - "raw" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "quotes" - ], - "title": "quote/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/quotes_GET_result.json b/doc/schemas/quotes_GET_result.json deleted file mode 100644 index 3840a45ba6f..00000000000 --- a/doc/schemas/quotes_GET_result.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "quotes": { - "items": { - "properties": { - "error": { - "type": "string" - }, - "mrenclave": { - "type": "string" - }, - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "raw": { - "type": "string" - } - }, - "required": [ - "node_id", - "raw" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "quotes" - ], - "title": "quotes/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/read_POST_params.json b/doc/schemas/read_POST_params.json deleted file mode 100644 index cccc0bc13fb..00000000000 --- a/doc/schemas/read_POST_params.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "key": {}, - "table": { - "type": "string" - } - }, - "required": [ - "table", - "key" - ], - "title": "read/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/read_POST_result.json b/doc/schemas/read_POST_result.json deleted file mode 100644 index a1e4d6a40e7..00000000000 --- a/doc/schemas/read_POST_result.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "read/result" -} \ No newline at end of file diff --git a/doc/schemas/receipt/verify_POST_params.json b/doc/schemas/receipt/verify_POST_params.json deleted file mode 100644 index b08f577ae7f..00000000000 --- a/doc/schemas/receipt/verify_POST_params.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "receipt": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "receipt" - ], - "title": "receipt/verify/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/receipt/verify_POST_result.json b/doc/schemas/receipt/verify_POST_result.json deleted file mode 100644 index 5825bd1cf1f..00000000000 --- a/doc/schemas/receipt/verify_POST_result.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "valid": { - "type": "boolean" - } - }, - "required": [ - "valid" - ], - "title": "receipt/verify/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/receipt_GET_params.json b/doc/schemas/receipt_GET_params.json deleted file mode 100644 index ed67b676d79..00000000000 --- a/doc/schemas/receipt_GET_params.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "commit": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - } - }, - "required": [ - "commit" - ], - "title": "receipt/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/receipt_GET_result.json b/doc/schemas/receipt_GET_result.json deleted file mode 100644 index 71ec3500340..00000000000 --- a/doc/schemas/receipt_GET_result.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "receipt": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "receipt" - ], - "title": "receipt/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/recovery_share/submit_POST_params.json b/doc/schemas/recovery_share/submit_POST_params.json deleted file mode 100644 index 49c61c6fc79..00000000000 --- a/doc/schemas/recovery_share/submit_POST_params.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "recovery_share/submit/params", - "type": "string" -} \ No newline at end of file diff --git a/doc/schemas/recovery_share/submit_POST_result.json b/doc/schemas/recovery_share/submit_POST_result.json deleted file mode 100644 index 19668eb7502..00000000000 --- a/doc/schemas/recovery_share/submit_POST_result.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "recovery_share/submit/result", - "type": "string" -} \ No newline at end of file diff --git a/doc/schemas/recovery_share_GET_result.json b/doc/schemas/recovery_share_GET_result.json deleted file mode 100644 index 4b59a933ecf..00000000000 --- a/doc/schemas/recovery_share_GET_result.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "encrypted_recovery_share": { - "type": "string" - }, - "nonce": { - "type": "string" - } - }, - "required": [ - "encrypted_recovery_share", - "nonce" - ], - "title": "recovery_share/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/state_GET_result.json b/doc/schemas/state_GET_result.json deleted file mode 100644 index 9ddcdfa8baf..00000000000 --- a/doc/schemas/state_GET_result.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "last_recovered_seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "last_signed_seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "recovery_target_seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "state": { - "enum": [ - "uninitialized", - "initialized", - "pending", - "partOfPublicNetwork", - "partOfNetwork", - "readingPublicLedger", - "readingPrivateLedger" - ] - } - }, - "required": [ - "id", - "state", - "last_signed_seqno" - ], - "title": "state/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/tx_GET_params.json b/doc/schemas/tx_GET_params.json deleted file mode 100644 index 96801e6ecfa..00000000000 --- a/doc/schemas/tx_GET_params.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - } - }, - "required": [ - "view", - "seqno" - ], - "title": "tx/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/tx_GET_result.json b/doc/schemas/tx_GET_result.json deleted file mode 100644 index 2b5a3450a87..00000000000 --- a/doc/schemas/tx_GET_result.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "status": { - "enum": [ - "UNKNOWN", - "PENDING", - "COMMITTED", - "INVALID" - ] - } - }, - "required": [ - "status" - ], - "title": "tx/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/user_id_GET_params.json b/doc/schemas/user_id_GET_params.json deleted file mode 100644 index 5275cf6085b..00000000000 --- a/doc/schemas/user_id_GET_params.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "cert": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "cert" - ], - "title": "user_id/params", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/user_id_GET_result.json b/doc/schemas/user_id_GET_result.json deleted file mode 100644 index 769db669917..00000000000 --- a/doc/schemas/user_id_GET_result.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "caller_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "caller_id" - ], - "title": "user_id/result", - "type": "object" -} \ No newline at end of file From 8f736e345323764446fc1615e840dc0ea502d507 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Thu, 10 Sep 2020 11:07:57 +0100 Subject: [PATCH 26/53] Progress: schema_test dumps OpenAPI docs to file, initial files --- doc/schemas/app.json | 1030 +++++++++++++++++++++++++++++ doc/schemas/gov.json | 1040 ++++++++++++++++++++++++++++++ doc/schemas/node.json | 843 ++++++++++++++++++++++++ src/ds/json_schema.h | 1 - src/ds/openapi.h | 5 + src/ds/test/openapi.cpp | 7 +- src/node/rpc/endpoint_registry.h | 21 +- tests/schema.py | 86 +-- 8 files changed, 2971 insertions(+), 62 deletions(-) create mode 100644 doc/schemas/app.json create mode 100644 doc/schemas/gov.json create mode 100644 doc/schemas/node.json diff --git a/doc/schemas/app.json b/doc/schemas/app.json new file mode 100644 index 00000000000..ae7503fd4b2 --- /dev/null +++ b/doc/schemas/app.json @@ -0,0 +1,1030 @@ +{ + "info": { + "description": "Placeholder description", + "title": "Placeholder title", + "version": "1.0.0" + }, + "openapi": "3.0.0", + "paths": { + "/app/api": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "title": "api/result" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/app/api/schema": { + "get": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "method": { + "type": "string" + } + }, + "required": [ + "method" + ], + "title": "api/schema/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "params_schema": { + "$ref": "http://json-schema.org/draft-07/schema#" + }, + "result_schema": { + "$ref": "http://json-schema.org/draft-07/schema#" + } + }, + "required": [ + "params_schema", + "result_schema" + ], + "title": "api/schema/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/app/code": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "versions": { + "items": { + "properties": { + "digest": { + "type": "string" + }, + "status": { + "enum": [ + "ACCEPTED", + "RETIRED" + ] + } + }, + "required": [ + "digest", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "versions" + ], + "title": "code/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/app/commit": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "required": [ + "view", + "seqno" + ], + "title": "commit/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/app/endpoint_metrics": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "metrics": { + "items": { + "items": [ + { + "type": "string" + }, + { + "items": { + "items": [ + { + "type": "string" + }, + { + "properties": { + "calls": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "errors": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "failures": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "calls", + "errors", + "failures" + ], + "type": "object" + } + ], + "type": "array" + }, + "type": "array" + } + ], + "type": "array" + }, + "type": "array" + } + }, + "required": [ + "metrics" + ], + "title": "endpoint_metrics/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/app/log/private": { + "delete": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "id" + ], + "title": "log/private/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "title": "log/private/result", + "type": "boolean" + } + } + }, + "description": "Auto-generated" + } + } + }, + "get": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "id" + ], + "title": "log/private/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "msg": { + "type": "string" + } + }, + "required": [ + "msg" + ], + "title": "log/private/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + }, + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "msg": { + "type": "string" + } + }, + "required": [ + "id", + "msg" + ], + "title": "log/private/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "title": "log/private/result", + "type": "boolean" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/app/log/private/admin_only": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "msg": { + "type": "string" + } + }, + "required": [ + "id", + "msg" + ], + "title": "log/private/admin_only/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "title": "log/private/admin_only/result", + "type": "boolean" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/app/log/private/anonymous": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "msg": { + "type": "string" + } + }, + "required": [ + "id", + "msg" + ], + "title": "log/private/anonymous/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "title": "log/private/anonymous/result", + "type": "boolean" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/app/log/private/historical": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": {} + }, + "description": "Auto-generated" + } + } + } + }, + "/app/log/private/prefix_cert": { + "post": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": {} + }, + "description": "Auto-generated" + } + } + } + }, + "/app/log/public": { + "delete": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "id" + ], + "title": "log/public/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "title": "log/public/result", + "type": "boolean" + } + } + }, + "description": "Auto-generated" + } + } + }, + "get": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "id": { + "type": "number" + } + }, + "required": [ + "id" + ], + "title": "log/public/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "msg": { + "type": "string" + } + }, + "required": [ + "msg" + ], + "title": "log/public/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + }, + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "id": { + "type": "number" + }, + "msg": { + "type": "string" + } + }, + "required": [ + "id", + "msg" + ], + "title": "log/public/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "log/public/result", + "type": "bool" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/app/metrics": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "histogram": { + "properties": { + "buckets": {}, + "high": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "low": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "overflow": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "underflow": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "low", + "high", + "overflow", + "underflow", + "buckets" + ], + "type": "object" + }, + "tx_rates": {} + }, + "required": [ + "histogram", + "tx_rates" + ], + "title": "metrics/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/app/network_info": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "nodes": { + "items": { + "properties": { + "host": { + "type": "string" + }, + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "port": { + "type": "string" + } + }, + "required": [ + "node_id", + "host", + "port" + ], + "type": "object" + }, + "type": "array" + }, + "primary_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "nodes", + "primary_id" + ], + "title": "network_info/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/app/node/ids": { + "get": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "string" + } + }, + "required": [ + "host", + "port" + ], + "title": "node/ids/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "nodes": { + "items": { + "properties": { + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "status": { + "enum": [ + "PENDING", + "TRUSTED", + "RETIRED" + ] + } + }, + "required": [ + "node_id", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "nodes" + ], + "title": "node/ids/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/app/primary_info": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "current_view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "primary_host": { + "type": "string" + }, + "primary_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "primary_port": { + "type": "string" + } + }, + "required": [ + "primary_id", + "primary_host", + "primary_port", + "current_view" + ], + "title": "primary_info/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/app/receipt": { + "get": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "commit": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "required": [ + "commit" + ], + "title": "receipt/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "receipt": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "receipt" + ], + "title": "receipt/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/app/receipt/verify": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "receipt": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "receipt" + ], + "title": "receipt/verify/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "valid": { + "type": "boolean" + } + }, + "required": [ + "valid" + ], + "title": "receipt/verify/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/app/tx": { + "get": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "required": [ + "view", + "seqno" + ], + "title": "tx/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "status": { + "enum": [ + "UNKNOWN", + "PENDING", + "COMMITTED", + "INVALID" + ] + } + }, + "required": [ + "status" + ], + "title": "tx/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/app/user_id": { + "get": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "cert": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "cert" + ], + "title": "user_id/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "caller_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "caller_id" + ], + "title": "user_id/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + } + }, + "servers": [] +} \ No newline at end of file diff --git a/doc/schemas/gov.json b/doc/schemas/gov.json new file mode 100644 index 00000000000..4eb6357b2ab --- /dev/null +++ b/doc/schemas/gov.json @@ -0,0 +1,1040 @@ +{ + "info": { + "description": "Placeholder description", + "title": "Placeholder title", + "version": "1.0.0" + }, + "openapi": "3.0.0", + "paths": { + "/gov/ack": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "state_digest": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "state_digest" + ], + "title": "ack/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "title": "ack/result", + "type": "boolean" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/ack/update_state_digest": { + "post": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "signed_req": { + "properties": { + "md": { + "enum": [ + "MBEDTLS_MD_NONE", + "MBEDTLS_MD_SHA1", + "MBEDTLS_MD_SHA256", + "MBEDTLS_MD_SHA384", + "MBEDTLS_MD_SHA512" + ] + }, + "req": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "request_body": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "sig": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "sig", + "req", + "request_body", + "md" + ], + "type": "object" + }, + "state_digest": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "state_digest", + "signed_req" + ], + "title": "ack/update_state_digest/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/api": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "title": "api/result" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/api/schema": { + "get": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "method": { + "type": "string" + } + }, + "required": [ + "method" + ], + "title": "api/schema/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "params_schema": { + "$ref": "http://json-schema.org/draft-07/schema#" + }, + "result_schema": { + "$ref": "http://json-schema.org/draft-07/schema#" + } + }, + "required": [ + "params_schema", + "result_schema" + ], + "title": "api/schema/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/code": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "versions": { + "items": { + "properties": { + "digest": { + "type": "string" + }, + "status": { + "enum": [ + "ACCEPTED", + "RETIRED" + ] + } + }, + "required": [ + "digest", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "versions" + ], + "title": "code/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/commit": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "required": [ + "view", + "seqno" + ], + "title": "commit/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/create": { + "post": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": {} + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/endpoint_metrics": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "metrics": { + "items": { + "items": [ + { + "type": "string" + }, + { + "items": { + "items": [ + { + "type": "string" + }, + { + "properties": { + "calls": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "errors": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "failures": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "calls", + "errors", + "failures" + ], + "type": "object" + } + ], + "type": "array" + }, + "type": "array" + } + ], + "type": "array" + }, + "type": "array" + } + }, + "required": [ + "metrics" + ], + "title": "endpoint_metrics/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/metrics": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "histogram": { + "properties": { + "buckets": {}, + "high": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "low": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "overflow": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "underflow": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "low", + "high", + "overflow", + "underflow", + "buckets" + ], + "type": "object" + }, + "tx_rates": {} + }, + "required": [ + "histogram", + "tx_rates" + ], + "title": "metrics/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/network_info": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "nodes": { + "items": { + "properties": { + "host": { + "type": "string" + }, + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "port": { + "type": "string" + } + }, + "required": [ + "node_id", + "host", + "port" + ], + "type": "object" + }, + "type": "array" + }, + "primary_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "nodes", + "primary_id" + ], + "title": "network_info/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/node/ids": { + "get": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "string" + } + }, + "required": [ + "host", + "port" + ], + "title": "node/ids/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "nodes": { + "items": { + "properties": { + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "status": { + "enum": [ + "PENDING", + "TRUSTED", + "RETIRED" + ] + } + }, + "required": [ + "node_id", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "nodes" + ], + "title": "node/ids/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/primary_info": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "current_view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "primary_host": { + "type": "string" + }, + "primary_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "primary_port": { + "type": "string" + } + }, + "required": [ + "primary_id", + "primary_host", + "primary_port", + "current_view" + ], + "title": "primary_info/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/proposals": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "ballot": { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + }, + "parameter": {}, + "script": { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + } + }, + "required": [ + "script" + ], + "title": "proposals/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "proposal_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "proposer_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "state": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + } + }, + "required": [ + "proposal_id", + "proposer_id", + "state" + ], + "title": "proposals/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/query": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "title": "query/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "title": "query/result" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/read": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "key": {}, + "table": { + "type": "string" + } + }, + "required": [ + "table", + "key" + ], + "title": "read/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "title": "read/result" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/receipt": { + "get": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "commit": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "required": [ + "commit" + ], + "title": "receipt/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "receipt": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "receipt" + ], + "title": "receipt/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/receipt/verify": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "receipt": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "receipt" + ], + "title": "receipt/verify/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "valid": { + "type": "boolean" + } + }, + "required": [ + "valid" + ], + "title": "receipt/verify/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/recovery_share": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "encrypted_recovery_share": { + "type": "string" + }, + "nonce": { + "type": "string" + } + }, + "required": [ + "encrypted_recovery_share", + "nonce" + ], + "title": "recovery_share/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/recovery_share/submit": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "title": "recovery_share/submit/params", + "type": "string" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "title": "recovery_share/submit/result", + "type": "string" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/tx": { + "get": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "required": [ + "view", + "seqno" + ], + "title": "tx/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "status": { + "enum": [ + "UNKNOWN", + "PENDING", + "COMMITTED", + "INVALID" + ] + } + }, + "required": [ + "status" + ], + "title": "tx/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/gov/user_id": { + "get": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "cert": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "cert" + ], + "title": "user_id/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "caller_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "caller_id" + ], + "title": "user_id/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + } + }, + "servers": [] +} \ No newline at end of file diff --git a/doc/schemas/node.json b/doc/schemas/node.json new file mode 100644 index 00000000000..c7f8eafde8e --- /dev/null +++ b/doc/schemas/node.json @@ -0,0 +1,843 @@ +{ + "info": { + "description": "Placeholder description", + "title": "Placeholder title", + "version": "1.0.0" + }, + "openapi": "3.0.0", + "paths": { + "/node/api": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "title": "api/result" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/node/api/schema": { + "get": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "method": { + "type": "string" + } + }, + "required": [ + "method" + ], + "title": "api/schema/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "params_schema": { + "$ref": "http://json-schema.org/draft-07/schema#" + }, + "result_schema": { + "$ref": "http://json-schema.org/draft-07/schema#" + } + }, + "required": [ + "params_schema", + "result_schema" + ], + "title": "api/schema/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/node/code": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "versions": { + "items": { + "properties": { + "digest": { + "type": "string" + }, + "status": { + "enum": [ + "ACCEPTED", + "RETIRED" + ] + } + }, + "required": [ + "digest", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "versions" + ], + "title": "code/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/node/commit": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "required": [ + "view", + "seqno" + ], + "title": "commit/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/node/endpoint_metrics": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "metrics": { + "items": { + "items": [ + { + "type": "string" + }, + { + "items": { + "items": [ + { + "type": "string" + }, + { + "properties": { + "calls": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "errors": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "failures": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "calls", + "errors", + "failures" + ], + "type": "object" + } + ], + "type": "array" + }, + "type": "array" + } + ], + "type": "array" + }, + "type": "array" + } + }, + "required": [ + "metrics" + ], + "title": "endpoint_metrics/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/node/join": { + "post": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": {} + }, + "description": "Auto-generated" + } + } + } + }, + "/node/metrics": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "histogram": { + "properties": { + "buckets": {}, + "high": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "low": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "overflow": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "underflow": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "low", + "high", + "overflow", + "underflow", + "buckets" + ], + "type": "object" + }, + "tx_rates": {} + }, + "required": [ + "histogram", + "tx_rates" + ], + "title": "metrics/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/node/network": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": {} + }, + "description": "Auto-generated" + } + } + } + }, + "/node/network_info": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "nodes": { + "items": { + "properties": { + "host": { + "type": "string" + }, + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "port": { + "type": "string" + } + }, + "required": [ + "node_id", + "host", + "port" + ], + "type": "object" + }, + "type": "array" + }, + "primary_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "nodes", + "primary_id" + ], + "title": "network_info/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/node/node/ids": { + "get": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "string" + } + }, + "required": [ + "host", + "port" + ], + "title": "node/ids/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "nodes": { + "items": { + "properties": { + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "status": { + "enum": [ + "PENDING", + "TRUSTED", + "RETIRED" + ] + } + }, + "required": [ + "node_id", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "nodes" + ], + "title": "node/ids/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/node/primary": { + "head": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": {} + }, + "description": "Auto-generated" + } + } + } + }, + "/node/primary_info": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "current_view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "primary_host": { + "type": "string" + }, + "primary_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "primary_port": { + "type": "string" + } + }, + "required": [ + "primary_id", + "primary_host", + "primary_port", + "current_view" + ], + "title": "primary_info/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/node/quote": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "quotes": { + "items": { + "properties": { + "error": { + "type": "string" + }, + "mrenclave": { + "type": "string" + }, + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "raw": { + "type": "string" + } + }, + "required": [ + "node_id", + "raw" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "quotes" + ], + "title": "quote/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/node/quotes": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "quotes": { + "items": { + "properties": { + "error": { + "type": "string" + }, + "mrenclave": { + "type": "string" + }, + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "raw": { + "type": "string" + } + }, + "required": [ + "node_id", + "raw" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "quotes" + ], + "title": "quotes/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/node/receipt": { + "get": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "commit": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "required": [ + "commit" + ], + "title": "receipt/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "receipt": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "receipt" + ], + "title": "receipt/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/node/receipt/verify": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "receipt": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "receipt" + ], + "title": "receipt/verify/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "valid": { + "type": "boolean" + } + }, + "required": [ + "valid" + ], + "title": "receipt/verify/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/node/state": { + "get": { + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "last_recovered_seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "last_signed_seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "recovery_target_seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "state": { + "enum": [ + "uninitialized", + "initialized", + "pending", + "partOfPublicNetwork", + "partOfNetwork", + "readingPublicLedger", + "readingPrivateLedger" + ] + } + }, + "required": [ + "id", + "state", + "last_signed_seqno" + ], + "title": "state/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + }, + "/node/tx": { + "get": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "required": [ + "view", + "seqno" + ], + "title": "tx/params", + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "status": { + "enum": [ + "UNKNOWN", + "PENDING", + "COMMITTED", + "INVALID" + ] + } + }, + "required": [ + "status" + ], + "title": "tx/result", + "type": "object" + } + } + }, + "description": "Auto-generated" + } + } + } + } + }, + "servers": [] +} \ No newline at end of file diff --git a/src/ds/json_schema.h b/src/ds/json_schema.h index d35b4bce0e4..bbb53e572ee 100644 --- a/src/ds/json_schema.h +++ b/src/ds/json_schema.h @@ -265,7 +265,6 @@ namespace ds inline nlohmann::json build_schema(const std::string& title) { nlohmann::json schema; - schema["$schema"] = JsonSchema::hyperschema; schema["title"] = title; fill_schema(schema); diff --git a/src/ds/openapi.h b/src/ds/openapi.h index 709bc313651..a5bd8607c49 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -107,6 +107,11 @@ namespace ds return access::get_object(content, mt); } + static inline nlohmann::json& schema(nlohmann::json& media_type_object) + { + return access::get_object(media_type_object, "schema"); + } + struct Info { std::string title; diff --git a/src/ds/test/openapi.cpp b/src/ds/test/openapi.cpp index 2a42dd99ba3..7429f54389c 100644 --- a/src/ds/test/openapi.cpp +++ b/src/ds/test/openapi.cpp @@ -59,12 +59,15 @@ TEST_CASE("Manual construction") auto& foo_post_request = openapi::request_body(foo_post); auto& foo_post_request_json = openapi::media_type( foo_post_request, http::headervalues::contenttype::JSON); - foo_post_request_json["schema"] = string_schema; + auto& foo_post_request_json_schema = openapi::schema(foo_post_request_json); + foo_post_request_json_schema = string_schema; + auto& foo_post_response_ok = openapi::response( foo_post, HTTP_STATUS_OK, "Indicates that everything went ok"); auto& foo_post_response_ok_json = openapi::media_type( foo_post_response_ok, http::headervalues::contenttype::JSON); - foo_post_response_ok_json["schema"] = string_schema; + auto& foo_post_response_ok_json_schema = openapi::schema(foo_post_response_ok_json); + foo_post_response_ok_json_schema = string_schema; required_doc_elements(doc); diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index 2689a48abcb..f046fb3e495 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -464,11 +464,24 @@ namespace ccf } auto& path_operation = ds::openapi::path_operation(path_object, http_verb.value()); - auto& path_response_ok = ds::openapi::response( + + auto& request_body = ds::openapi::request_body(path_operation); + auto& request_body_json = ds::openapi::media_type(request_body, http::headervalues::contenttype::JSON); + if (!handler.params_schema.empty()) + { + auto& request_body_json_schema = ds::openapi::schema(request_body_json); + request_body_json_schema = handler.params_schema; + } + + auto& response_ok = ds::openapi::response( path_operation, HTTP_STATUS_OK, "Auto-generated"); - auto& path_response_ok_json = ds::openapi::media_type( - path_response_ok, http::headervalues::contenttype::JSON); - path_response_ok_json["schema"] = {{"type", "string"}}; + auto& response_ok_json = ds::openapi::media_type( + response_ok, http::headervalues::contenttype::JSON); + if (!handler.result_schema.empty()) + { + auto& response_ok_json_schema = ds::openapi::schema(response_ok_json); + response_ok_json_schema = handler.result_schema; + } } } diff --git a/tests/schema.py b/tests/schema.py index 0cd57a786b5..32eeaa73009 100644 --- a/tests/schema.py +++ b/tests/schema.py @@ -23,14 +23,14 @@ def run(args): os.makedirs(args.schema_dir, exist_ok=True) changed_files = [] - methods_with_schema = set() - methods_without_schema = set() old_schema = set( os.path.join(dir_path, filename) for dir_path, _, filenames in os.walk(args.schema_dir) for filename in filenames ) + documents_valid = True + all_methods = [] def fetch_schema(client, prefix): @@ -38,56 +38,37 @@ def fetch_schema(client, prefix): check( api_response, error=lambda status, msg: status == http.HTTPStatus.OK.value ) - LOG.warning(json.dumps(api_response.body, indent=2)) + paths = api_response.body["paths"] all_methods.extend([key for key in paths.keys()]) - validate_spec(api_response.body) - - # for path, path_item in paths.items(): - # schema_found = False - # schema_response = client.get(f'/{prefix}/api/schema?method="{path}"') - # check( - # schema_response, - # error=lambda status, msg: status == http.HTTPStatus.OK.value, - # ) - - # if schema_response.body is not None: - # for verb, schema_element in schema_response.body.items(): - # for schema_type in ["params", "result"]: - # element_name = "{}_schema".format(schema_type) - # element = schema_element[element_name] - # target_file = build_schema_file_path( - # args.schema_dir, verb, path, schema_type - # ) - # if element is not None and len(element) != 0: - # try: - # old_schema.remove(target_file) - # except KeyError: - # pass - # schema_found = True - # formatted_schema = json.dumps(element, indent=2) - # os.makedirs(os.path.dirname(target_file), exist_ok=True) - # with open(target_file, "a+") as f: - # f.seek(0) - # previous = f.read() - # if previous != formatted_schema: - # LOG.debug( - # "Writing schema to {}".format(target_file) - # ) - # f.truncate(0) - # f.seek(0) - # f.write(formatted_schema) - # changed_files.append(target_file) - # else: - # LOG.debug( - # "Schema matches in {}".format(target_file) - # ) - - # if schema_found: - # methods_with_schema.add(path) - # else: - # methods_without_schema.add(path) + formatted_schema = json.dumps(api_response.body, indent=2) + + target_file = os.path.join(args.schema_dir, f"{prefix}.json") + + try: + old_schema.remove(target_file) + except KeyError: + pass + + with open(target_file, "a+") as f: + f.seek(0) + previous = f.read() + if previous != formatted_schema: + LOG.debug("Writing schema to {}".format(target_file)) + f.truncate(0) + f.seek(0) + f.write(formatted_schema) + changed_files.append(target_file) + else: + LOG.debug("Schema matches in {}".format(target_file)) + + try: + validate_spec(api_response.body) + except Exception as e: + LOG.error("Invalid json schema") + LOG.error(e) + documents_valid = False with infra.network.network( hosts, args.binary_dir, args.debug_nodes, args.perf_nodes @@ -109,11 +90,6 @@ def fetch_schema(client, prefix): LOG.info("member frontend") fetch_schema(member_client, "gov") - if len(methods_without_schema) > 0: - LOG.info("The following methods have no schema:") - for m in sorted(methods_without_schema): - LOG.info(" " + m) - made_changes = False if len(old_schema) > 0: @@ -139,7 +115,7 @@ def fetch_schema(client, prefix): for method in sorted(set(all_methods)): LOG.info(f" {method}") - if made_changes: + if made_changes or not documents_valid: sys.exit(1) From 0296f09e378a24a75a9f8905ee81e6885c4f2a86 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Thu, 10 Sep 2020 13:03:16 +0100 Subject: [PATCH 27/53] Produce schema that the online validator is happy with --- doc/schemas/app.json | 395 ++++++++++-------------------- doc/schemas/gov.json | 286 +++++++-------------- doc/schemas/node.json | 267 ++++++-------------- src/apps/logging/logging_schema.h | 6 +- src/ds/json_schema.h | 33 ++- src/ds/openapi.h | 5 + src/node/rpc/endpoint_registry.h | 33 ++- 7 files changed, 363 insertions(+), 662 deletions(-) diff --git a/doc/schemas/app.json b/doc/schemas/app.json index ae7503fd4b2..cef5deed468 100644 --- a/doc/schemas/app.json +++ b/doc/schemas/app.json @@ -8,11 +8,6 @@ "paths": { "/app/api": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -29,24 +24,16 @@ }, "/app/api/schema": { "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "method": { - "type": "string" - } - }, - "required": [ - "method" - ], - "title": "api/schema/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "method", + "required": false, + "schema": { + "type": "string" } } - }, + ], "responses": { "200": { "content": { @@ -76,11 +63,6 @@ }, "/app/code": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -124,11 +106,6 @@ }, "/app/commit": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -162,11 +139,6 @@ }, "/app/endpoint_metrics": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -174,51 +146,35 @@ "schema": { "properties": { "metrics": { - "items": { - "items": [ - { - "type": "string" - }, - { - "items": { - "items": [ - { - "type": "string" - }, - { - "properties": { - "calls": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "errors": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "failures": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "calls", - "errors", - "failures" - ], - "type": "object" - } - ], - "type": "array" + "additionalProperties": { + "additionalProperties": { + "properties": { + "calls": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" }, - "type": "array" - } - ], - "type": "array" + "errors": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "failures": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "calls", + "errors", + "failures" + ], + "type": "object" + }, + "type": "object" }, - "type": "array" + "type": "object" } }, "required": [ @@ -236,26 +192,18 @@ }, "/app/log/private": { "delete": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "id" - ], - "title": "log/private/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "id", + "required": false, + "schema": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" } } - }, + ], "responses": { "200": { "content": { @@ -271,26 +219,18 @@ } }, "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "id" - ], - "title": "log/private/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "id", + "required": false, + "schema": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" } } - }, + ], "responses": { "200": { "content": { @@ -437,11 +377,6 @@ }, "/app/log/private/historical": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -454,11 +389,6 @@ }, "/app/log/private/prefix_cert": { "post": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -471,26 +401,18 @@ }, "/app/log/public": { "delete": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "id" - ], - "title": "log/public/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "id", + "required": false, + "schema": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" } } - }, + ], "responses": { "200": { "content": { @@ -506,31 +428,21 @@ } }, "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "id": { - "type": "number" - } - }, - "required": [ - "id" - ], - "title": "log/public/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "id", + "required": false, + "schema": { + "type": "number" } } - }, + ], "responses": { "200": { "content": { "application/json": { "schema": { - "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "msg": { "type": "string" @@ -553,7 +465,6 @@ "content": { "application/json": { "schema": { - "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "id": { "type": "number" @@ -577,9 +488,8 @@ "content": { "application/json": { "schema": { - "$schema": "http://json-schema.org/draft-07/schema#", "title": "log/public/result", - "type": "bool" + "type": "boolean" } } }, @@ -590,11 +500,6 @@ }, "/app/metrics": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -652,11 +557,6 @@ }, "/app/network_info": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -709,28 +609,24 @@ }, "/app/node/ids": { "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "host": { - "type": "string" - }, - "port": { - "type": "string" - } - }, - "required": [ - "host", - "port" - ], - "title": "node/ids/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "host", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "port", + "required": false, + "schema": { + "type": "string" } } - }, + ], "responses": { "200": { "content": { @@ -777,11 +673,6 @@ }, "/app/primary_info": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -823,26 +714,18 @@ }, "/app/receipt": { "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "commit": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - } - }, - "required": [ - "commit" - ], - "title": "receipt/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "commit", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" } } - }, + ], "responses": { "200": { "content": { @@ -921,32 +804,28 @@ }, "/app/tx": { "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - } - }, - "required": [ - "view", - "seqno" - ], - "title": "tx/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "seqno", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + { + "in": "query", + "name": "view", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" } } - }, + ], "responses": { "200": { "content": { @@ -977,29 +856,21 @@ }, "/app/user_id": { "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "cert": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "cert" - ], - "title": "user_id/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "cert", + "required": false, + "schema": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" } } - }, + ], "responses": { "200": { "content": { diff --git a/doc/schemas/gov.json b/doc/schemas/gov.json index 4eb6357b2ab..6606408ced6 100644 --- a/doc/schemas/gov.json +++ b/doc/schemas/gov.json @@ -48,11 +48,6 @@ }, "/gov/ack/update_state_digest": { "post": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -128,11 +123,6 @@ }, "/gov/api": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -149,24 +139,16 @@ }, "/gov/api/schema": { "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "method": { - "type": "string" - } - }, - "required": [ - "method" - ], - "title": "api/schema/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "method", + "required": false, + "schema": { + "type": "string" } } - }, + ], "responses": { "200": { "content": { @@ -196,11 +178,6 @@ }, "/gov/code": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -244,11 +221,6 @@ }, "/gov/commit": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -282,11 +254,6 @@ }, "/gov/create": { "post": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -299,11 +266,6 @@ }, "/gov/endpoint_metrics": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -311,51 +273,35 @@ "schema": { "properties": { "metrics": { - "items": { - "items": [ - { - "type": "string" - }, - { - "items": { - "items": [ - { - "type": "string" - }, - { - "properties": { - "calls": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "errors": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "failures": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "calls", - "errors", - "failures" - ], - "type": "object" - } - ], - "type": "array" + "additionalProperties": { + "additionalProperties": { + "properties": { + "calls": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" }, - "type": "array" - } - ], - "type": "array" + "errors": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "failures": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "calls", + "errors", + "failures" + ], + "type": "object" + }, + "type": "object" }, - "type": "array" + "type": "object" } }, "required": [ @@ -373,11 +319,6 @@ }, "/gov/metrics": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -435,11 +376,6 @@ }, "/gov/network_info": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -492,28 +428,24 @@ }, "/gov/node/ids": { "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "host": { - "type": "string" - }, - "port": { - "type": "string" - } - }, - "required": [ - "host", - "port" - ], - "title": "node/ids/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "host", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "port", + "required": false, + "schema": { + "type": "string" } } - }, + ], "responses": { "200": { "content": { @@ -560,11 +492,6 @@ }, "/gov/primary_info": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -772,26 +699,18 @@ }, "/gov/receipt": { "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "commit": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - } - }, - "required": [ - "commit" - ], - "title": "receipt/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "commit", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" } } - }, + ], "responses": { "200": { "content": { @@ -870,11 +789,6 @@ }, "/gov/recovery_share": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -931,32 +845,28 @@ }, "/gov/tx": { "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - } - }, - "required": [ - "view", - "seqno" - ], - "title": "tx/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "seqno", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + { + "in": "query", + "name": "view", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" } } - }, + ], "responses": { "200": { "content": { @@ -987,29 +897,21 @@ }, "/gov/user_id": { "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "cert": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "cert" - ], - "title": "user_id/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "cert", + "required": false, + "schema": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" } } - }, + ], "responses": { "200": { "content": { diff --git a/doc/schemas/node.json b/doc/schemas/node.json index c7f8eafde8e..864d1811202 100644 --- a/doc/schemas/node.json +++ b/doc/schemas/node.json @@ -8,11 +8,6 @@ "paths": { "/node/api": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -29,24 +24,16 @@ }, "/node/api/schema": { "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "method": { - "type": "string" - } - }, - "required": [ - "method" - ], - "title": "api/schema/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "method", + "required": false, + "schema": { + "type": "string" } } - }, + ], "responses": { "200": { "content": { @@ -76,11 +63,6 @@ }, "/node/code": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -124,11 +106,6 @@ }, "/node/commit": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -162,11 +139,6 @@ }, "/node/endpoint_metrics": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -174,51 +146,35 @@ "schema": { "properties": { "metrics": { - "items": { - "items": [ - { - "type": "string" - }, - { - "items": { - "items": [ - { - "type": "string" - }, - { - "properties": { - "calls": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "errors": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "failures": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "calls", - "errors", - "failures" - ], - "type": "object" - } - ], - "type": "array" + "additionalProperties": { + "additionalProperties": { + "properties": { + "calls": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" }, - "type": "array" - } - ], - "type": "array" + "errors": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "failures": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "calls", + "errors", + "failures" + ], + "type": "object" + }, + "type": "object" }, - "type": "array" + "type": "object" } }, "required": [ @@ -236,11 +192,6 @@ }, "/node/join": { "post": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -253,11 +204,6 @@ }, "/node/metrics": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -315,11 +261,6 @@ }, "/node/network": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -332,11 +273,6 @@ }, "/node/network_info": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -389,28 +325,24 @@ }, "/node/node/ids": { "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "host": { - "type": "string" - }, - "port": { - "type": "string" - } - }, - "required": [ - "host", - "port" - ], - "title": "node/ids/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "host", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "port", + "required": false, + "schema": { + "type": "string" } } - }, + ], "responses": { "200": { "content": { @@ -457,11 +389,6 @@ }, "/node/primary": { "head": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -474,11 +401,6 @@ }, "/node/primary_info": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -520,11 +442,6 @@ }, "/node/quote": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -573,11 +490,6 @@ }, "/node/quotes": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -626,26 +538,18 @@ }, "/node/receipt": { "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "commit": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - } - }, - "required": [ - "commit" - ], - "title": "receipt/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "commit", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" } } - }, + ], "responses": { "200": { "content": { @@ -724,11 +628,6 @@ }, "/node/state": { "get": { - "requestBody": { - "content": { - "application/json": {} - } - }, "responses": { "200": { "content": { @@ -784,32 +683,28 @@ }, "/node/tx": { "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - } - }, - "required": [ - "view", - "seqno" - ], - "title": "tx/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "seqno", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + { + "in": "query", + "name": "view", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" } } - }, + ], "responses": { "200": { "content": { diff --git a/src/apps/logging/logging_schema.h b/src/apps/logging/logging_schema.h index 1996e946197..1b7478ed156 100644 --- a/src/apps/logging/logging_schema.h +++ b/src/apps/logging/logging_schema.h @@ -52,7 +52,6 @@ namespace loggingapp // Manual schemas, verified then parsed in handler static const std::string j_record_public_in = R"!!!( { - "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "id": { "type": "number" @@ -72,15 +71,13 @@ namespace loggingapp static const std::string j_record_public_out = R"!!!( { - "$schema": "http://json-schema.org/draft-07/schema#", "title": "log/public/result", - "type": "bool" + "type": "boolean" } )!!!"; static const std::string j_get_public_in = R"!!!( { - "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "id": { "type": "number" @@ -96,7 +93,6 @@ namespace loggingapp static const std::string j_get_public_out = R"!!!( { - "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "msg": { "type": "string" diff --git a/src/ds/json_schema.h b/src/ds/json_schema.h index bbb53e572ee..22d33681d12 100644 --- a/src/ds/json_schema.h +++ b/src/ds/json_schema.h @@ -206,21 +206,30 @@ namespace ds nonstd::is_specialization::value || nonstd::is_specialization::value) { - // Nlohmann serialises maps to an array of (K, V) pairs - // TODO: Unless the keys are strings! - schema["type"] = "array"; - auto items = nlohmann::json::object(); + // Nlohmann serialises maps to an array of (K, V) pairs... + if (std::is_same::value) { - items["type"] = "array"; + // ...unless the keys are strings! + schema["type"] = "object"; + schema["additionalProperties"] = + schema_element(); + } + else + { + schema["type"] = "array"; + auto items = nlohmann::json::object(); + { + items["type"] = "array"; - auto sub_items = nlohmann::json::array(); - // TODO: OpenAPI doesn't like this tuple for "items", even though its - // valid JSON schema. Maybe fixed in a newer spec version? - sub_items.push_back(schema_element()); - sub_items.push_back(schema_element()); - items["items"] = sub_items; + auto sub_items = nlohmann::json::array(); + // TODO: OpenAPI doesn't like this tuple for "items", even though + // its valid JSON schema. Maybe fixed in a newer spec version? + sub_items.push_back(schema_element()); + sub_items.push_back(schema_element()); + items["items"] = sub_items; + } + schema["items"] = items; } - schema["items"] = items; } else if constexpr (nonstd::is_specialization::value) { diff --git a/src/ds/openapi.h b/src/ds/openapi.h index a5bd8607c49..f21b29279a1 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -79,6 +79,11 @@ namespace ds return access::get_object(path, s); } + static inline nlohmann::json& parameters(nlohmann::json& path_operation) + { + return access::get_array(path_operation, "parameters"); + } + static inline nlohmann::json& response( nlohmann::json& path_operation, http_status status, diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index f046fb3e495..45e20f18a89 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -464,19 +464,42 @@ namespace ccf } auto& path_operation = ds::openapi::path_operation(path_object, http_verb.value()); - - auto& request_body = ds::openapi::request_body(path_operation); - auto& request_body_json = ds::openapi::media_type(request_body, http::headervalues::contenttype::JSON); if (!handler.params_schema.empty()) { - auto& request_body_json_schema = ds::openapi::schema(request_body_json); - request_body_json_schema = handler.params_schema; + if (http_verb.value() == HTTP_GET || http_verb.value() == HTTP_DELETE) + { + // TODO: Should set these as individual parameters, not reparse them here + if (handler.params_schema["type"] != "object") + { + throw std::logic_error(fmt::format("Unexpected params schema type: {}", handler.params_schema.dump())); + } + + const auto& required_parameters = handler.params_schema["required"]; + auto& parameters = ds::openapi::parameters(path_operation); + for (const auto& [name, schema]: handler.params_schema["properties"].items()) + { + auto parameter = nlohmann::json::object(); + parameter["name"] = name; + parameter["in"] = "query"; + parameter["required"] = required_parameters.find(name) != required_parameters.end(); + parameter["schema"] = schema; + parameters.push_back(parameter); + } + } + else + { + auto& request_body = ds::openapi::request_body(path_operation); + auto& request_body_json = ds::openapi::media_type(request_body, http::headervalues::contenttype::JSON); + auto& request_body_json_schema = ds::openapi::schema(request_body_json); + request_body_json_schema = handler.params_schema; + } } auto& response_ok = ds::openapi::response( path_operation, HTTP_STATUS_OK, "Auto-generated"); auto& response_ok_json = ds::openapi::media_type( response_ok, http::headervalues::contenttype::JSON); + if (!handler.result_schema.empty()) { auto& response_ok_json_schema = ds::openapi::schema(response_ok_json); From 1b2411307d2b9d35542430d6d202ad40bf2fa85f Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Thu, 10 Sep 2020 15:13:50 +0100 Subject: [PATCH 28/53] Drop an element the spec validator isn't happy with --- doc/schemas/app.json | 4 ++-- doc/schemas/gov.json | 4 ++-- doc/schemas/node.json | 4 ++-- src/ds/json_schema.h | 5 ++++- tests/schema.py | 6 +++--- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/doc/schemas/app.json b/doc/schemas/app.json index cef5deed468..497c7abaa01 100644 --- a/doc/schemas/app.json +++ b/doc/schemas/app.json @@ -41,10 +41,10 @@ "schema": { "properties": { "params_schema": { - "$ref": "http://json-schema.org/draft-07/schema#" + "type": "object" }, "result_schema": { - "$ref": "http://json-schema.org/draft-07/schema#" + "type": "object" } }, "required": [ diff --git a/doc/schemas/gov.json b/doc/schemas/gov.json index 6606408ced6..5407187ee0f 100644 --- a/doc/schemas/gov.json +++ b/doc/schemas/gov.json @@ -156,10 +156,10 @@ "schema": { "properties": { "params_schema": { - "$ref": "http://json-schema.org/draft-07/schema#" + "type": "object" }, "result_schema": { - "$ref": "http://json-schema.org/draft-07/schema#" + "type": "object" } }, "required": [ diff --git a/doc/schemas/node.json b/doc/schemas/node.json index 864d1811202..dbba6623983 100644 --- a/doc/schemas/node.json +++ b/doc/schemas/node.json @@ -41,10 +41,10 @@ "schema": { "properties": { "params_schema": { - "$ref": "http://json-schema.org/draft-07/schema#" + "type": "object" }, "result_schema": { - "$ref": "http://json-schema.org/draft-07/schema#" + "type": "object" } }, "required": [ diff --git a/src/ds/json_schema.h b/src/ds/json_schema.h index 22d33681d12..6f913af1212 100644 --- a/src/ds/json_schema.h +++ b/src/ds/json_schema.h @@ -262,7 +262,10 @@ namespace ds } else if constexpr (std::is_same::value) { - schema["$ref"] = JsonSchema::hyperschema; + // TODO: OpenAPI validator isn't happy with these $ref elements, so + // we're being very vague for now + // schema["$ref"] = JsonSchema::hyperschema; + schema["type"] = "object"; } else { diff --git a/tests/schema.py b/tests/schema.py index 32eeaa73009..1cd341094db 100644 --- a/tests/schema.py +++ b/tests/schema.py @@ -8,7 +8,7 @@ import infra.proc import infra.e2e_args import infra.checker -from openapi_spec_validator import validate_spec +import openapi_spec_validator from loguru import logger as LOG @@ -64,9 +64,9 @@ def fetch_schema(client, prefix): LOG.debug("Schema matches in {}".format(target_file)) try: - validate_spec(api_response.body) + openapi_spec_validator.validate_spec(api_response.body) except Exception as e: - LOG.error("Invalid json schema") + LOG.error(f"Validation of {prefix} schema failed") LOG.error(e) documents_valid = False From 55d94025c3e4b34ed446f65af99377d4eb759934 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Thu, 10 Sep 2020 20:41:16 +0100 Subject: [PATCH 29/53] Use freeform JSON manipulators everywhere, fix nested add_to_components --- src/ds/json_schema.h | 18 +- src/ds/openapi.h | 395 ++++++++++++++++------------------------ src/ds/test/openapi.cpp | 97 +++++----- 3 files changed, 222 insertions(+), 288 deletions(-) diff --git a/src/ds/json_schema.h b/src/ds/json_schema.h index 6f913af1212..417ced51cb1 100644 --- a/src/ds/json_schema.h +++ b/src/ds/json_schema.h @@ -120,15 +120,23 @@ namespace ds nonstd::is_specialization::value || nonstd::is_specialization::value) { - return fmt::format( - "{}_to_{}", - schema_name(), - schema_name()); + if (std::is_same::value) + { + return fmt::format( + "named_{}", schema_name()); + } + else + { + return fmt::format( + "{}_to_{}", + schema_name(), + schema_name()); + } } else if constexpr (nonstd::is_specialization::value) { return fmt::format( - "{}_to_{}", + "{}_and_{}", schema_name(), schema_name()); } diff --git a/src/ds/openapi.h b/src/ds/openapi.h index f21b29279a1..3b1791001de 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -39,12 +39,20 @@ namespace ds } } + static inline void check_path_valid(const std::string& s) + { + if (s.rfind("/", 0) != 0) + { + throw std::logic_error( + fmt::format("'{}' is not a valid path - must begin with '/'", s)); + } + } + static inline nlohmann::json create_document( const std::string& title, const std::string& description, const std::string& document_version) { - // TODO: Check document_version looks valid? return nlohmann::json{{"openapi", "3.0.0"}, {"info", {{"title", title}, @@ -117,238 +125,58 @@ namespace ds return access::get_object(media_type_object, "schema"); } - struct Info - { - std::string title; - std::string description; - std::string version; - }; - DECLARE_JSON_TYPE(Info); - DECLARE_JSON_REQUIRED_FIELDS(Info, title, description, version); - - struct Server - { - std::string url; - - bool operator==(const Server& rhs) const - { - return url == rhs.url; - } - }; - DECLARE_JSON_TYPE(Server); - DECLARE_JSON_REQUIRED_FIELDS(Server, url); - - struct MediaType - { - // May be a full in-place schema, but is generally a reference object - nlohmann::json schema; - - bool operator==(const MediaType& rhs) const - { - return schema == rhs.schema; - } - }; - DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(MediaType); - DECLARE_JSON_REQUIRED_FIELDS(MediaType); - DECLARE_JSON_OPTIONAL_FIELDS(MediaType, schema); - - using ContentMap = std::map; + // + // Helper functions for auto-inserting schema into components + // - struct RequestBody + static inline nlohmann::json components_ref_object( + const std::string& element_name) { - std::string description; - ContentMap content; - bool required = false; - - bool operator==(const RequestBody& rhs) const - { - return description == rhs.description && content == rhs.content && - required == rhs.required; - } - - bool operator!=(const RequestBody& rhs) const - { - return !(*this == rhs); - } - }; - DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(RequestBody); - DECLARE_JSON_REQUIRED_FIELDS(RequestBody, content); - DECLARE_JSON_OPTIONAL_FIELDS(RequestBody, description, required); - - struct Response - { - std::string description; - ContentMap content; - }; - DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(Response); - DECLARE_JSON_REQUIRED_FIELDS(Response, description); - DECLARE_JSON_OPTIONAL_FIELDS(Response, content); - - struct Operation - { - RequestBody requestBody; - std::map responses; - - Response& operator[](http_status status) - { - // HTTP_STATUS_OK (aka an int with value 200) becomes the string "200" - const auto s = std::to_string(status); - return responses[s]; - } - }; - DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(Operation); - DECLARE_JSON_REQUIRED_FIELDS(Operation, responses); - DECLARE_JSON_OPTIONAL_FIELDS(Operation, requestBody); - - struct PathItem - { - std::map operations; - - Operation& operator[](http_method verb) - { - // HTTP_GET becomes the string "get" - std::string s = http_method_str(verb); - nonstd::to_lower(s); - return operations[s]; - } - }; - - // When converted to JSON, a PathItem is not an object containing an - // 'operations' field with an object value, it _is_ this operations object - // value - inline void to_json(nlohmann::json& j, const PathItem& pi) - { - j = pi.operations; - } - - inline void from_json(const nlohmann::json& j, PathItem& pi) - { - pi.operations = j.get(); - } - - using Paths = std::map; - - inline void check_path_valid(const std::string& s) - { - if (s.rfind("/", 0) != 0) - { - throw std::logic_error( - fmt::format("'{}' is not a valid path - must begin with '/'", s)); - } + auto schema_ref_object = nlohmann::json::object(); + schema_ref_object["$ref"] = + fmt::format("#/components/schemas/{}", element_name); + return schema_ref_object; } - struct Components + // Returns a ref object pointing to the item inserted into the components + static inline nlohmann::json add_schema_to_components( + nlohmann::json& document, + const std::string& element_name, + const nlohmann::json& schema_) { - std::map schemas; + auto& components = access::get_object(document, "components"); + auto& schemas = access::get_object(components, "schemas"); - bool operator!=(const Components& rhs) const + const auto schema_it = schemas.find(element_name); + if (schema_it != schemas.end()) { - return schemas != rhs.schemas; - } - }; - DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(Components); - DECLARE_JSON_REQUIRED_FIELDS(Components); - DECLARE_JSON_OPTIONAL_FIELDS(Components, schemas); - - struct Document - { - std::string openapi = "3.0.0"; - Info info; - std::vector servers; - Paths paths; - Components components; - - nlohmann::json add_schema_to_components( - const std::string& element_name, const nlohmann::json& schema) - { - const auto schema_it = components.schemas.find(element_name); - if (schema_it != components.schemas.end()) + // Check that the existing schema matches the new one being added with + // the same name + const auto& existing_schema = schema_it.value(); + if (schema_ != existing_schema) { - // Check that the existing schema matches the new one being added with - // the same name - const auto& existing_schema = schema_it->second; - if (schema != existing_schema) - { - throw std::logic_error(fmt::format( - "Adding schema with name '{}'. Does not match previous schema " - "registered with this name: {} vs {}", - element_name, - schema.dump(), - existing_schema.dump())); - } + throw std::logic_error(fmt::format( + "Adding schema with name '{}'. Does not match previous schema " + "registered with this name: {} vs {}", + element_name, + schema_.dump(), + existing_schema.dump())); } - else - { - components.schemas.emplace(element_name, schema); - } - - auto schema_ref_object = nlohmann::json::object(); - schema_ref_object["$ref"] = - fmt::format("#/components/schemas/{}", element_name); - return schema_ref_object; - } - - void add_request_body_schema( - const std::string& uri, - http_method verb, - const std::string& content_type, - const std::string& schema_name, - const nlohmann::json& schema) - { - check_path_valid(uri); - - auto& request_body = paths[uri][verb].requestBody; - request_body.description = "Auto-generated request body schema"; - request_body.content[content_type].schema = - add_schema_to_components(schema_name, schema); } - - template - void add_request_body_schema( - const std::string& uri, - http_method verb, - const std::string& content_type) - { - check_path_valid(uri); - - auto& request_body = paths[uri][verb].requestBody; - request_body.description = "Auto-generated request body schema"; - request_body.content[content_type].schema = add_schema_component(); - } - - void add_response_schema( - const std::string& uri, - http_method verb, - http_status status, - const std::string& content_type, - const std::string& schema_name, - const nlohmann::json& schema) + else { - check_path_valid(uri); - - auto& response_object = paths[uri][verb][status]; - response_object.description = "Auto-generated response schema"; - response_object.content[content_type].schema = - add_schema_to_components(schema_name, schema); + schemas.emplace(element_name, schema_); } - template - void add_response_schema( - const std::string& uri, - http_method verb, - http_status status, - const std::string& content_type) - { - check_path_valid(uri); + return components_ref_object(element_name); + } - auto& response_object = paths[uri][verb][status]; - response_object.description = "Auto-generated response schema"; - response_object.content[content_type].schema = - add_schema_component(); - } + struct SchemaHelper + { + nlohmann::json& document; template - inline nlohmann::json add_schema_component() + nlohmann::json add_schema_component() { nlohmann::json schema; if constexpr (nonstd::is_specialization::value) @@ -359,29 +187,41 @@ namespace ds { schema["type"] = "array"; schema["items"] = add_schema_component(); - return schema; + + return add_schema_to_components( + document, ds::json::schema_name(), schema); } else if constexpr ( nonstd::is_specialization::value || nonstd::is_specialization::value) { // Nlohmann serialises maps to an array of (K, V) pairs - // TODO: Unless the keys are strings! - schema["type"] = "array"; - auto items = nlohmann::json::object(); + if (std::is_same::value) { - items["type"] = "array"; - - auto sub_items = nlohmann::json::array(); - // TODO: OpenAPI doesn't like this tuple for "items", even though - // its valid JSON schema. Maybe fixed in a newer spec version? - sub_items.push_back(add_schema_component()); - sub_items.push_back( - add_schema_component()); - items["items"] = sub_items; + // ...unless the keys are strings! + schema["type"] = "object"; + schema["additionalProperties"] = + add_schema_component(); } - schema["items"] = items; - return schema; + else + { + schema["type"] = "array"; + auto items = nlohmann::json::object(); + { + items["type"] = "array"; + + auto sub_items = nlohmann::json::array(); + // TODO: OpenAPI doesn't like this tuple for "items", even though + // its valid JSON schema. Maybe fixed in a newer spec version? + sub_items.push_back(add_schema_component()); + sub_items.push_back( + add_schema_component()); + items["items"] = sub_items; + } + schema["items"] = items; + } + return add_schema_to_components( + document, ds::json::schema_name(), schema); } else if constexpr (nonstd::is_specialization::value) { @@ -390,7 +230,8 @@ namespace ds items.push_back(add_schema_component()); items.push_back(add_schema_component()); schema["items"] = items; - return schema; + return add_schema_to_components( + document, ds::json::schema_name(), schema); } else if constexpr ( std::is_same::value || std::is_same::value || @@ -403,17 +244,95 @@ namespace ds std::is_same::value) { ds::json::fill_schema(schema); - return add_schema_to_components(ds::json::schema_name(), schema); + return add_schema_to_components( + document, ds::json::schema_name(), schema); } else { - return ds::json::adl::add_schema_to_components(*this); + const auto name = ds::json::adl::schema_name(); + + auto& components = access::get_object(document, "components"); + auto& schemas = access::get_object(components, "schemas"); + + const auto ib = schemas.emplace(name, nlohmann::json::object()); + if (ib.second) + { + auto& j = ib.first.value(); + // Use argument-dependent-lookup to call correct functions + T t; + add_schema_components(*this, j, t); + } + + return components_ref_object(name); } } }; - DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(Document); - DECLARE_JSON_REQUIRED_FIELDS(Document, openapi, info, paths); - DECLARE_JSON_OPTIONAL_FIELDS(Document, servers, components); + + static inline void add_request_body_schema( + nlohmann::json& document, + const std::string& uri, + http_method verb, + const std::string& content_type, + const std::string& schema_name, + const nlohmann::json& schema_) + { + check_path_valid(uri); + + auto& rb = request_body(path_operation(path(document, uri), verb)); + rb["description"] = "Auto-generated request body schema"; + + schema(media_type(rb, content_type)) = + add_schema_to_components(document, schema_name, schema_); + } + + template + static inline void add_request_body_schema( + nlohmann::json& document, + const std::string& uri, + http_method verb, + const std::string& content_type) + { + check_path_valid(uri); + + auto& rb = request_body(path_operation(path(document, uri), verb)); + rb["description"] = "Auto-generated request body schema"; + + SchemaHelper sh{document}; + schema(media_type(rb, content_type)) = sh.add_schema_component(); + } + + static inline void add_response_schema( + nlohmann::json& document, + const std::string& uri, + http_method verb, + http_status status, + const std::string& content_type, + const std::string& schema_name, + const nlohmann::json& schema_) + { + check_path_valid(uri); + + auto& r = response(path_operation(path(document, uri), verb), status); + + schema(media_type(r, content_type)) = + add_schema_to_components(document, schema_name, schema_); + } + + template + static inline void add_response_schema( + nlohmann::json& document, + const std::string& uri, + http_method verb, + http_status status, + const std::string& content_type) + { + check_path_valid(uri); + + auto& r = response(path_operation(path(document, uri), verb), status); + + SchemaHelper sh{document}; + schema(media_type(r, content_type)) = sh.add_schema_component(); + } } } diff --git a/src/ds/test/openapi.cpp b/src/ds/test/openapi.cpp index 7429f54389c..a8cdabadcc3 100644 --- a/src/ds/test/openapi.cpp +++ b/src/ds/test/openapi.cpp @@ -22,12 +22,10 @@ void print_doc(const std::string& title, const nlohmann::json& doc) REQUIRE(name##_it->type_fn()); \ } -static constexpr auto server_url = - "https://not.a.real.server.example.com/testing_only"; +static constexpr auto server_url = "https://not.a.real.server.com/testing_only"; -// TODO: Use some external verifier to check this. What we primarily care about -// is "is this a valid OpenAPI doc". We don't even really care about parsing it -// for specific elements, just producing it +// This is only a very basic check - assume full validation is done by external +// validator void required_doc_elements(const nlohmann::json& j) { REQUIRE_ELEMENT(j, openapi, is_string); @@ -35,13 +33,13 @@ void required_doc_elements(const nlohmann::json& j) REQUIRE_ELEMENT(j, paths, is_object); } -TEST_CASE("Required elements") -{ - openapi::Document doc; +// TEST_CASE("Required elements") +// { +// openapi::Document doc; - const nlohmann::json j = doc; - required_doc_elements(j); -} +// const nlohmann::json j = doc; +// required_doc_elements(j); +// } TEST_CASE("Manual construction") { @@ -66,7 +64,8 @@ TEST_CASE("Manual construction") foo_post, HTTP_STATUS_OK, "Indicates that everything went ok"); auto& foo_post_response_ok_json = openapi::media_type( foo_post_response_ok, http::headervalues::contenttype::JSON); - auto& foo_post_response_ok_json_schema = openapi::schema(foo_post_response_ok_json); + auto& foo_post_response_ok_json_schema = + openapi::schema(foo_post_response_ok_json); foo_post_response_ok_json_schema = string_schema; required_doc_elements(doc); @@ -81,8 +80,6 @@ TEST_CASE("Manual construction") REQUIRE(servers_element.size() == 1); const auto& first_server = servers_element[0]; REQUIRE_ELEMENT(first_server, url, is_string); - - print_doc("PATHS", doc); } struct Foo @@ -95,32 +92,29 @@ DECLARE_JSON_REQUIRED_FIELDS(Foo, n, s); TEST_CASE("Simple custom types") { - openapi::Document doc; - doc.info.title = "Test generated API"; - doc.info.description = "Some longer description enhanced with **Markdown**"; - doc.info.version = "0.1.42"; - - { - openapi::Server mockup_server; - mockup_server.url = server_url; - doc.servers.push_back(mockup_server); - } + auto doc = openapi::create_document( + "Test generated API", + "Some longer description enhanced with **Markdown**", + "0.1.42"); + + openapi::server(doc, server_url); - doc.add_request_body_schema( - "/app/foo", HTTP_POST, http::headervalues::contenttype::JSON); - doc.add_response_schema( + openapi::add_request_body_schema( + doc, "/app/foo", HTTP_POST, http::headervalues::contenttype::JSON); + openapi::add_response_schema( + doc, "/app/foo", HTTP_POST, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); - doc.add_response_schema( + openapi::add_response_schema( + doc, "/app/foo", - HTTP_GET, + HTTP_POST, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); - const nlohmann::json j = doc; - required_doc_elements(j); + required_doc_elements(doc); print_doc("SIMPLE", doc); } @@ -157,41 +151,54 @@ DECLARE_JSON_OPTIONAL_FIELDS_WITH_RENAMES( TEST_CASE("Complex custom types") { - openapi::Document doc; - doc.info.title = "Test generated API"; - doc.info.description = "Some longer description enhanced with **Markdown**"; - doc.info.version = "0.1.42"; + auto doc = openapi::create_document( + "Test generated API", + "Some longer description enhanced with **Markdown**", + "0.1.42"); - doc.add_response_schema>( + openapi::server(doc, server_url); + + openapi::add_response_schema>( + doc, "/app/foos", HTTP_GET, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); - doc.add_response_schema( + openapi::add_response_schema>>( + doc, + "/app/fooss", + HTTP_GET, + HTTP_STATUS_OK, + http::headervalues::contenttype::JSON); + openapi::add_response_schema( + doc, "/app/bar", HTTP_GET, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); - doc.add_response_schema( + openapi::add_response_schema( + doc, "/app/baz", HTTP_GET, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); - doc.add_response_schema( + openapi::add_response_schema>( + doc, "/app/buzz", HTTP_GET, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); - doc.add_request_body_schema>( - "/app/complex", HTTP_GET, http::headervalues::contenttype::JSON); - doc.add_response_schema>>( + + openapi::add_request_body_schema>( + doc, "/app/complex", HTTP_POST, http::headervalues::contenttype::JSON); + openapi::add_response_schema>>( + doc, "/app/complex", - HTTP_GET, + HTTP_POST, HTTP_STATUS_OK, http::headervalues::contenttype::JSON); - const nlohmann::json j = doc; - required_doc_elements(j); + required_doc_elements(doc); print_doc("COMPLEX", doc); } \ No newline at end of file From d439221985e4af9dc1dc4f57634737a50358c58c Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 11 Sep 2020 11:37:22 +0100 Subject: [PATCH 30/53] Schema.py should continue to retrieve individual schema --- src/ds/nonstd.h | 10 ++++++ src/ds/openapi.h | 2 +- src/node/rpc/call_types.h | 1 - tests/schema.py | 64 ++++++++++++++++++++++++++++++++++----- 4 files changed, 68 insertions(+), 9 deletions(-) diff --git a/src/ds/nonstd.h b/src/ds/nonstd.h index f5ac042be37..cf24b36a3f0 100644 --- a/src/ds/nonstd.h +++ b/src/ds/nonstd.h @@ -77,4 +77,14 @@ namespace nonstd return std::tolower(c); }); } + + static inline std::string remove_prefix(const std::string& s, const std::string& prefix) + { + if (s.find(prefix) == 0) + { + return s.substr(prefix.size()); + } + + return s; + } } \ No newline at end of file diff --git a/src/ds/openapi.h b/src/ds/openapi.h index 3b1791001de..d5609a9871f 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -73,7 +73,7 @@ namespace ds static inline nlohmann::json& path( nlohmann::json& document, const std::string& path) { - // TODO: Check that path starts with /? + check_path_valid(path); auto& paths = access::get_object(document, "paths"); return access::get_object(paths, path); } diff --git a/src/node/rpc/call_types.h b/src/node/rpc/call_types.h index 97e66927cc3..b950bed755c 100644 --- a/src/node/rpc/call_types.h +++ b/src/node/rpc/call_types.h @@ -134,7 +134,6 @@ namespace ccf struct GetAPI { - // TODO: What is the format of this now? using Out = nlohmann::json; }; diff --git a/tests/schema.py b/tests/schema.py index 1cd341094db..e14453106dd 100644 --- a/tests/schema.py +++ b/tests/schema.py @@ -23,6 +23,8 @@ def run(args): os.makedirs(args.schema_dir, exist_ok=True) changed_files = [] + methods_with_schema = set() + methods_without_schema = set() old_schema = set( os.path.join(dir_path, filename) for dir_path, _, filenames in os.walk(args.schema_dir) @@ -42,26 +44,74 @@ def fetch_schema(client, prefix): paths = api_response.body["paths"] all_methods.extend([key for key in paths.keys()]) - formatted_schema = json.dumps(api_response.body, indent=2) + # Fetch the schema of each method + for method, _ in paths.items(): + schema_found = False + expected_method_prefix = f"/{prefix}/" + if method.startswith(expected_method_prefix): + method = method[len(expected_method_prefix):] + schema_response = client.get(f'/{prefix}/api/schema?method="{method}"') + check( + schema_response, + error=lambda status, msg: status == http.HTTPStatus.OK.value, + ) + + if schema_response.body is not None: + for verb, schema_element in schema_response.body.items(): + for schema_type in ["params", "result"]: + element_name = "{}_schema".format(schema_type) + element = schema_element[element_name] + target_file = build_schema_file_path( + args.schema_dir, verb, method, schema_type + ) + if element is not None and len(element) != 0: + try: + old_schema.remove(target_file) + except KeyError: + pass + schema_found = True + formatted_schema = json.dumps(element, indent=2) + os.makedirs(os.path.dirname(target_file), exist_ok=True) + with open(target_file, "a+") as f: + f.seek(0) + previous = f.read() + if previous != formatted_schema: + LOG.debug( + "Writing schema to {}".format(target_file) + ) + f.truncate(0) + f.seek(0) + f.write(formatted_schema) + changed_files.append(target_file) + else: + LOG.debug( + "Schema matches in {}".format(target_file) + ) + + if schema_found: + methods_with_schema.add(method) + else: + methods_without_schema.add(method) - target_file = os.path.join(args.schema_dir, f"{prefix}.json") + formatted_schema = json.dumps(api_response.body, indent=2) + openapi_target_file = os.path.join(args.schema_dir, f"{prefix}_openapi.json") try: - old_schema.remove(target_file) + old_schema.remove(openapi_target_file) except KeyError: pass - with open(target_file, "a+") as f: + with open(openapi_target_file, "a+") as f: f.seek(0) previous = f.read() if previous != formatted_schema: - LOG.debug("Writing schema to {}".format(target_file)) + LOG.debug("Writing schema to {}".format(openapi_target_file)) f.truncate(0) f.seek(0) f.write(formatted_schema) - changed_files.append(target_file) + changed_files.append(openapi_target_file) else: - LOG.debug("Schema matches in {}".format(target_file)) + LOG.debug("Schema matches in {}".format(openapi_target_file)) try: openapi_spec_validator.validate_spec(api_response.body) From 39de645cebbff9dc334bebfa37a484335d67e5ff Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 11 Sep 2020 11:37:30 +0100 Subject: [PATCH 31/53] And here's those schemas again --- .../ack/update_state_digest_POST_result.json | 62 +++++++++++++++++++ doc/schemas/ack_POST_params.json | 17 +++++ doc/schemas/ack_POST_result.json | 4 ++ doc/schemas/api/schema_GET_params.json | 12 ++++ doc/schemas/api/schema_GET_result.json | 16 +++++ doc/schemas/api_GET_result.json | 3 + doc/schemas/{app.json => app_openapi.json} | 0 doc/schemas/code_GET_result.json | 30 +++++++++ doc/schemas/commit_GET_result.json | 20 ++++++ doc/schemas/endpoint_metrics_GET_result.json | 40 ++++++++++++ doc/schemas/{gov.json => gov_openapi.json} | 0 .../log/private/admin_only_POST_params.json | 18 ++++++ .../log/private/admin_only_POST_result.json | 4 ++ .../log/private/anonymous_POST_params.json | 18 ++++++ .../log/private/anonymous_POST_result.json | 4 ++ doc/schemas/log/private_DELETE_params.json | 14 +++++ doc/schemas/log/private_DELETE_result.json | 4 ++ doc/schemas/log/private_GET_params.json | 14 +++++ doc/schemas/log/private_GET_result.json | 12 ++++ doc/schemas/log/private_POST_params.json | 18 ++++++ doc/schemas/log/private_POST_result.json | 4 ++ doc/schemas/log/private_WEBSOCKET_params.json | 18 ++++++ doc/schemas/log/private_WEBSOCKET_result.json | 4 ++ doc/schemas/log/public_DELETE_params.json | 14 +++++ doc/schemas/log/public_DELETE_result.json | 4 ++ doc/schemas/log/public_GET_params.json | 12 ++++ doc/schemas/log/public_GET_result.json | 12 ++++ doc/schemas/log/public_POST_params.json | 16 +++++ doc/schemas/log/public_POST_result.json | 4 ++ doc/schemas/metrics_GET_result.json | 44 +++++++++++++ doc/schemas/network_info_GET_result.json | 39 ++++++++++++ doc/schemas/node/ids_GET_params.json | 16 +++++ doc/schemas/node/ids_GET_result.json | 33 ++++++++++ doc/schemas/{node.json => node_openapi.json} | 0 doc/schemas/primary_info_GET_result.json | 28 +++++++++ doc/schemas/proposals_POST_params.json | 42 +++++++++++++ doc/schemas/proposals_POST_result.json | 30 +++++++++ doc/schemas/query_POST_params.json | 17 +++++ doc/schemas/query_POST_result.json | 3 + doc/schemas/quote_GET_result.json | 35 +++++++++++ doc/schemas/quotes_GET_result.json | 35 +++++++++++ doc/schemas/read_POST_params.json | 14 +++++ doc/schemas/read_POST_result.json | 3 + doc/schemas/receipt/verify_POST_params.json | 17 +++++ doc/schemas/receipt/verify_POST_result.json | 12 ++++ doc/schemas/receipt_GET_params.json | 14 +++++ doc/schemas/receipt_GET_result.json | 17 +++++ .../recovery_share/submit_POST_params.json | 4 ++ .../recovery_share/submit_POST_result.json | 4 ++ doc/schemas/recovery_share_GET_result.json | 16 +++++ doc/schemas/state_GET_result.json | 42 +++++++++++++ doc/schemas/tx_GET_params.json | 20 ++++++ doc/schemas/tx_GET_result.json | 17 +++++ doc/schemas/user_id_GET_params.json | 17 +++++ doc/schemas/user_id_GET_result.json | 14 +++++ 55 files changed, 931 insertions(+) create mode 100644 doc/schemas/ack/update_state_digest_POST_result.json create mode 100644 doc/schemas/ack_POST_params.json create mode 100644 doc/schemas/ack_POST_result.json create mode 100644 doc/schemas/api/schema_GET_params.json create mode 100644 doc/schemas/api/schema_GET_result.json create mode 100644 doc/schemas/api_GET_result.json rename doc/schemas/{app.json => app_openapi.json} (100%) create mode 100644 doc/schemas/code_GET_result.json create mode 100644 doc/schemas/commit_GET_result.json create mode 100644 doc/schemas/endpoint_metrics_GET_result.json rename doc/schemas/{gov.json => gov_openapi.json} (100%) create mode 100644 doc/schemas/log/private/admin_only_POST_params.json create mode 100644 doc/schemas/log/private/admin_only_POST_result.json create mode 100644 doc/schemas/log/private/anonymous_POST_params.json create mode 100644 doc/schemas/log/private/anonymous_POST_result.json create mode 100644 doc/schemas/log/private_DELETE_params.json create mode 100644 doc/schemas/log/private_DELETE_result.json create mode 100644 doc/schemas/log/private_GET_params.json create mode 100644 doc/schemas/log/private_GET_result.json create mode 100644 doc/schemas/log/private_POST_params.json create mode 100644 doc/schemas/log/private_POST_result.json create mode 100644 doc/schemas/log/private_WEBSOCKET_params.json create mode 100644 doc/schemas/log/private_WEBSOCKET_result.json create mode 100644 doc/schemas/log/public_DELETE_params.json create mode 100644 doc/schemas/log/public_DELETE_result.json create mode 100644 doc/schemas/log/public_GET_params.json create mode 100644 doc/schemas/log/public_GET_result.json create mode 100644 doc/schemas/log/public_POST_params.json create mode 100644 doc/schemas/log/public_POST_result.json create mode 100644 doc/schemas/metrics_GET_result.json create mode 100644 doc/schemas/network_info_GET_result.json create mode 100644 doc/schemas/node/ids_GET_params.json create mode 100644 doc/schemas/node/ids_GET_result.json rename doc/schemas/{node.json => node_openapi.json} (100%) create mode 100644 doc/schemas/primary_info_GET_result.json create mode 100644 doc/schemas/proposals_POST_params.json create mode 100644 doc/schemas/proposals_POST_result.json create mode 100644 doc/schemas/query_POST_params.json create mode 100644 doc/schemas/query_POST_result.json create mode 100644 doc/schemas/quote_GET_result.json create mode 100644 doc/schemas/quotes_GET_result.json create mode 100644 doc/schemas/read_POST_params.json create mode 100644 doc/schemas/read_POST_result.json create mode 100644 doc/schemas/receipt/verify_POST_params.json create mode 100644 doc/schemas/receipt/verify_POST_result.json create mode 100644 doc/schemas/receipt_GET_params.json create mode 100644 doc/schemas/receipt_GET_result.json create mode 100644 doc/schemas/recovery_share/submit_POST_params.json create mode 100644 doc/schemas/recovery_share/submit_POST_result.json create mode 100644 doc/schemas/recovery_share_GET_result.json create mode 100644 doc/schemas/state_GET_result.json create mode 100644 doc/schemas/tx_GET_params.json create mode 100644 doc/schemas/tx_GET_result.json create mode 100644 doc/schemas/user_id_GET_params.json create mode 100644 doc/schemas/user_id_GET_result.json diff --git a/doc/schemas/ack/update_state_digest_POST_result.json b/doc/schemas/ack/update_state_digest_POST_result.json new file mode 100644 index 00000000000..1c7ea28845c --- /dev/null +++ b/doc/schemas/ack/update_state_digest_POST_result.json @@ -0,0 +1,62 @@ +{ + "properties": { + "signed_req": { + "properties": { + "md": { + "enum": [ + "MBEDTLS_MD_NONE", + "MBEDTLS_MD_SHA1", + "MBEDTLS_MD_SHA256", + "MBEDTLS_MD_SHA384", + "MBEDTLS_MD_SHA512" + ] + }, + "req": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "request_body": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "sig": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "sig", + "req", + "request_body", + "md" + ], + "type": "object" + }, + "state_digest": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "state_digest", + "signed_req" + ], + "title": "ack/update_state_digest/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/ack_POST_params.json b/doc/schemas/ack_POST_params.json new file mode 100644 index 00000000000..0aafe05368b --- /dev/null +++ b/doc/schemas/ack_POST_params.json @@ -0,0 +1,17 @@ +{ + "properties": { + "state_digest": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "state_digest" + ], + "title": "ack/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/ack_POST_result.json b/doc/schemas/ack_POST_result.json new file mode 100644 index 00000000000..7268be8c791 --- /dev/null +++ b/doc/schemas/ack_POST_result.json @@ -0,0 +1,4 @@ +{ + "title": "ack/result", + "type": "boolean" +} \ No newline at end of file diff --git a/doc/schemas/api/schema_GET_params.json b/doc/schemas/api/schema_GET_params.json new file mode 100644 index 00000000000..bde9544121e --- /dev/null +++ b/doc/schemas/api/schema_GET_params.json @@ -0,0 +1,12 @@ +{ + "properties": { + "method": { + "type": "string" + } + }, + "required": [ + "method" + ], + "title": "api/schema/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/api/schema_GET_result.json b/doc/schemas/api/schema_GET_result.json new file mode 100644 index 00000000000..000c6590883 --- /dev/null +++ b/doc/schemas/api/schema_GET_result.json @@ -0,0 +1,16 @@ +{ + "properties": { + "params_schema": { + "type": "object" + }, + "result_schema": { + "type": "object" + } + }, + "required": [ + "params_schema", + "result_schema" + ], + "title": "api/schema/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/api_GET_result.json b/doc/schemas/api_GET_result.json new file mode 100644 index 00000000000..5310a0db464 --- /dev/null +++ b/doc/schemas/api_GET_result.json @@ -0,0 +1,3 @@ +{ + "title": "api/result" +} \ No newline at end of file diff --git a/doc/schemas/app.json b/doc/schemas/app_openapi.json similarity index 100% rename from doc/schemas/app.json rename to doc/schemas/app_openapi.json diff --git a/doc/schemas/code_GET_result.json b/doc/schemas/code_GET_result.json new file mode 100644 index 00000000000..f667b931693 --- /dev/null +++ b/doc/schemas/code_GET_result.json @@ -0,0 +1,30 @@ +{ + "properties": { + "versions": { + "items": { + "properties": { + "digest": { + "type": "string" + }, + "status": { + "enum": [ + "ACCEPTED", + "RETIRED" + ] + } + }, + "required": [ + "digest", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "versions" + ], + "title": "code/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/commit_GET_result.json b/doc/schemas/commit_GET_result.json new file mode 100644 index 00000000000..d90ed03a33d --- /dev/null +++ b/doc/schemas/commit_GET_result.json @@ -0,0 +1,20 @@ +{ + "properties": { + "seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "required": [ + "view", + "seqno" + ], + "title": "commit/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/endpoint_metrics_GET_result.json b/doc/schemas/endpoint_metrics_GET_result.json new file mode 100644 index 00000000000..3f4d34d79f5 --- /dev/null +++ b/doc/schemas/endpoint_metrics_GET_result.json @@ -0,0 +1,40 @@ +{ + "properties": { + "metrics": { + "additionalProperties": { + "additionalProperties": { + "properties": { + "calls": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "errors": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "failures": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "calls", + "errors", + "failures" + ], + "type": "object" + }, + "type": "object" + }, + "type": "object" + } + }, + "required": [ + "metrics" + ], + "title": "endpoint_metrics/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/gov.json b/doc/schemas/gov_openapi.json similarity index 100% rename from doc/schemas/gov.json rename to doc/schemas/gov_openapi.json diff --git a/doc/schemas/log/private/admin_only_POST_params.json b/doc/schemas/log/private/admin_only_POST_params.json new file mode 100644 index 00000000000..d2fa79cb085 --- /dev/null +++ b/doc/schemas/log/private/admin_only_POST_params.json @@ -0,0 +1,18 @@ +{ + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "msg": { + "type": "string" + } + }, + "required": [ + "id", + "msg" + ], + "title": "log/private/admin_only/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/log/private/admin_only_POST_result.json b/doc/schemas/log/private/admin_only_POST_result.json new file mode 100644 index 00000000000..f731d3ec9a6 --- /dev/null +++ b/doc/schemas/log/private/admin_only_POST_result.json @@ -0,0 +1,4 @@ +{ + "title": "log/private/admin_only/result", + "type": "boolean" +} \ No newline at end of file diff --git a/doc/schemas/log/private/anonymous_POST_params.json b/doc/schemas/log/private/anonymous_POST_params.json new file mode 100644 index 00000000000..ed540feab5b --- /dev/null +++ b/doc/schemas/log/private/anonymous_POST_params.json @@ -0,0 +1,18 @@ +{ + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "msg": { + "type": "string" + } + }, + "required": [ + "id", + "msg" + ], + "title": "log/private/anonymous/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/log/private/anonymous_POST_result.json b/doc/schemas/log/private/anonymous_POST_result.json new file mode 100644 index 00000000000..d78e3311f84 --- /dev/null +++ b/doc/schemas/log/private/anonymous_POST_result.json @@ -0,0 +1,4 @@ +{ + "title": "log/private/anonymous/result", + "type": "boolean" +} \ No newline at end of file diff --git a/doc/schemas/log/private_DELETE_params.json b/doc/schemas/log/private_DELETE_params.json new file mode 100644 index 00000000000..59f5f00cd71 --- /dev/null +++ b/doc/schemas/log/private_DELETE_params.json @@ -0,0 +1,14 @@ +{ + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "id" + ], + "title": "log/private/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/log/private_DELETE_result.json b/doc/schemas/log/private_DELETE_result.json new file mode 100644 index 00000000000..423e1d35077 --- /dev/null +++ b/doc/schemas/log/private_DELETE_result.json @@ -0,0 +1,4 @@ +{ + "title": "log/private/result", + "type": "boolean" +} \ No newline at end of file diff --git a/doc/schemas/log/private_GET_params.json b/doc/schemas/log/private_GET_params.json new file mode 100644 index 00000000000..59f5f00cd71 --- /dev/null +++ b/doc/schemas/log/private_GET_params.json @@ -0,0 +1,14 @@ +{ + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "id" + ], + "title": "log/private/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/log/private_GET_result.json b/doc/schemas/log/private_GET_result.json new file mode 100644 index 00000000000..67c8963ac93 --- /dev/null +++ b/doc/schemas/log/private_GET_result.json @@ -0,0 +1,12 @@ +{ + "properties": { + "msg": { + "type": "string" + } + }, + "required": [ + "msg" + ], + "title": "log/private/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/log/private_POST_params.json b/doc/schemas/log/private_POST_params.json new file mode 100644 index 00000000000..3bf318bade9 --- /dev/null +++ b/doc/schemas/log/private_POST_params.json @@ -0,0 +1,18 @@ +{ + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "msg": { + "type": "string" + } + }, + "required": [ + "id", + "msg" + ], + "title": "log/private/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/log/private_POST_result.json b/doc/schemas/log/private_POST_result.json new file mode 100644 index 00000000000..423e1d35077 --- /dev/null +++ b/doc/schemas/log/private_POST_result.json @@ -0,0 +1,4 @@ +{ + "title": "log/private/result", + "type": "boolean" +} \ No newline at end of file diff --git a/doc/schemas/log/private_WEBSOCKET_params.json b/doc/schemas/log/private_WEBSOCKET_params.json new file mode 100644 index 00000000000..3bf318bade9 --- /dev/null +++ b/doc/schemas/log/private_WEBSOCKET_params.json @@ -0,0 +1,18 @@ +{ + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "msg": { + "type": "string" + } + }, + "required": [ + "id", + "msg" + ], + "title": "log/private/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/log/private_WEBSOCKET_result.json b/doc/schemas/log/private_WEBSOCKET_result.json new file mode 100644 index 00000000000..423e1d35077 --- /dev/null +++ b/doc/schemas/log/private_WEBSOCKET_result.json @@ -0,0 +1,4 @@ +{ + "title": "log/private/result", + "type": "boolean" +} \ No newline at end of file diff --git a/doc/schemas/log/public_DELETE_params.json b/doc/schemas/log/public_DELETE_params.json new file mode 100644 index 00000000000..0dcbe93a651 --- /dev/null +++ b/doc/schemas/log/public_DELETE_params.json @@ -0,0 +1,14 @@ +{ + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "id" + ], + "title": "log/public/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/log/public_DELETE_result.json b/doc/schemas/log/public_DELETE_result.json new file mode 100644 index 00000000000..213d0cb22de --- /dev/null +++ b/doc/schemas/log/public_DELETE_result.json @@ -0,0 +1,4 @@ +{ + "title": "log/public/result", + "type": "boolean" +} \ No newline at end of file diff --git a/doc/schemas/log/public_GET_params.json b/doc/schemas/log/public_GET_params.json new file mode 100644 index 00000000000..9a85d305432 --- /dev/null +++ b/doc/schemas/log/public_GET_params.json @@ -0,0 +1,12 @@ +{ + "properties": { + "id": { + "type": "number" + } + }, + "required": [ + "id" + ], + "title": "log/public/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/log/public_GET_result.json b/doc/schemas/log/public_GET_result.json new file mode 100644 index 00000000000..1f430b8ec83 --- /dev/null +++ b/doc/schemas/log/public_GET_result.json @@ -0,0 +1,12 @@ +{ + "properties": { + "msg": { + "type": "string" + } + }, + "required": [ + "msg" + ], + "title": "log/public/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/log/public_POST_params.json b/doc/schemas/log/public_POST_params.json new file mode 100644 index 00000000000..6bd2c399a6e --- /dev/null +++ b/doc/schemas/log/public_POST_params.json @@ -0,0 +1,16 @@ +{ + "properties": { + "id": { + "type": "number" + }, + "msg": { + "type": "string" + } + }, + "required": [ + "id", + "msg" + ], + "title": "log/public/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/log/public_POST_result.json b/doc/schemas/log/public_POST_result.json new file mode 100644 index 00000000000..213d0cb22de --- /dev/null +++ b/doc/schemas/log/public_POST_result.json @@ -0,0 +1,4 @@ +{ + "title": "log/public/result", + "type": "boolean" +} \ No newline at end of file diff --git a/doc/schemas/metrics_GET_result.json b/doc/schemas/metrics_GET_result.json new file mode 100644 index 00000000000..2c5918392dd --- /dev/null +++ b/doc/schemas/metrics_GET_result.json @@ -0,0 +1,44 @@ +{ + "properties": { + "histogram": { + "properties": { + "buckets": {}, + "high": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "low": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "overflow": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "underflow": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "low", + "high", + "overflow", + "underflow", + "buckets" + ], + "type": "object" + }, + "tx_rates": {} + }, + "required": [ + "histogram", + "tx_rates" + ], + "title": "metrics/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/network_info_GET_result.json b/doc/schemas/network_info_GET_result.json new file mode 100644 index 00000000000..eb2cb3c1902 --- /dev/null +++ b/doc/schemas/network_info_GET_result.json @@ -0,0 +1,39 @@ +{ + "properties": { + "nodes": { + "items": { + "properties": { + "host": { + "type": "string" + }, + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "port": { + "type": "string" + } + }, + "required": [ + "node_id", + "host", + "port" + ], + "type": "object" + }, + "type": "array" + }, + "primary_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "nodes", + "primary_id" + ], + "title": "network_info/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/node/ids_GET_params.json b/doc/schemas/node/ids_GET_params.json new file mode 100644 index 00000000000..aa5aa48df91 --- /dev/null +++ b/doc/schemas/node/ids_GET_params.json @@ -0,0 +1,16 @@ +{ + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "string" + } + }, + "required": [ + "host", + "port" + ], + "title": "node/ids/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/node/ids_GET_result.json b/doc/schemas/node/ids_GET_result.json new file mode 100644 index 00000000000..de4e8bbb826 --- /dev/null +++ b/doc/schemas/node/ids_GET_result.json @@ -0,0 +1,33 @@ +{ + "properties": { + "nodes": { + "items": { + "properties": { + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "status": { + "enum": [ + "PENDING", + "TRUSTED", + "RETIRED" + ] + } + }, + "required": [ + "node_id", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "nodes" + ], + "title": "node/ids/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/node.json b/doc/schemas/node_openapi.json similarity index 100% rename from doc/schemas/node.json rename to doc/schemas/node_openapi.json diff --git a/doc/schemas/primary_info_GET_result.json b/doc/schemas/primary_info_GET_result.json new file mode 100644 index 00000000000..43e11dbb049 --- /dev/null +++ b/doc/schemas/primary_info_GET_result.json @@ -0,0 +1,28 @@ +{ + "properties": { + "current_view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "primary_host": { + "type": "string" + }, + "primary_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "primary_port": { + "type": "string" + } + }, + "required": [ + "primary_id", + "primary_host", + "primary_port", + "current_view" + ], + "title": "primary_info/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/proposals_POST_params.json b/doc/schemas/proposals_POST_params.json new file mode 100644 index 00000000000..6708dc01b63 --- /dev/null +++ b/doc/schemas/proposals_POST_params.json @@ -0,0 +1,42 @@ +{ + "properties": { + "ballot": { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + }, + "parameter": {}, + "script": { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + } + }, + "required": [ + "script" + ], + "title": "proposals/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/proposals_POST_result.json b/doc/schemas/proposals_POST_result.json new file mode 100644 index 00000000000..f33004c21b5 --- /dev/null +++ b/doc/schemas/proposals_POST_result.json @@ -0,0 +1,30 @@ +{ + "properties": { + "proposal_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "proposer_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "state": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + } + }, + "required": [ + "proposal_id", + "proposer_id", + "state" + ], + "title": "proposals/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/query_POST_params.json b/doc/schemas/query_POST_params.json new file mode 100644 index 00000000000..557884d5151 --- /dev/null +++ b/doc/schemas/query_POST_params.json @@ -0,0 +1,17 @@ +{ + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "title": "query/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/query_POST_result.json b/doc/schemas/query_POST_result.json new file mode 100644 index 00000000000..9bf4e9337d1 --- /dev/null +++ b/doc/schemas/query_POST_result.json @@ -0,0 +1,3 @@ +{ + "title": "query/result" +} \ No newline at end of file diff --git a/doc/schemas/quote_GET_result.json b/doc/schemas/quote_GET_result.json new file mode 100644 index 00000000000..c967cc601d2 --- /dev/null +++ b/doc/schemas/quote_GET_result.json @@ -0,0 +1,35 @@ +{ + "properties": { + "quotes": { + "items": { + "properties": { + "error": { + "type": "string" + }, + "mrenclave": { + "type": "string" + }, + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "raw": { + "type": "string" + } + }, + "required": [ + "node_id", + "raw" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "quotes" + ], + "title": "quote/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/quotes_GET_result.json b/doc/schemas/quotes_GET_result.json new file mode 100644 index 00000000000..800db184707 --- /dev/null +++ b/doc/schemas/quotes_GET_result.json @@ -0,0 +1,35 @@ +{ + "properties": { + "quotes": { + "items": { + "properties": { + "error": { + "type": "string" + }, + "mrenclave": { + "type": "string" + }, + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "raw": { + "type": "string" + } + }, + "required": [ + "node_id", + "raw" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "quotes" + ], + "title": "quotes/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/read_POST_params.json b/doc/schemas/read_POST_params.json new file mode 100644 index 00000000000..6986faefe21 --- /dev/null +++ b/doc/schemas/read_POST_params.json @@ -0,0 +1,14 @@ +{ + "properties": { + "key": {}, + "table": { + "type": "string" + } + }, + "required": [ + "table", + "key" + ], + "title": "read/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/read_POST_result.json b/doc/schemas/read_POST_result.json new file mode 100644 index 00000000000..0229084c09f --- /dev/null +++ b/doc/schemas/read_POST_result.json @@ -0,0 +1,3 @@ +{ + "title": "read/result" +} \ No newline at end of file diff --git a/doc/schemas/receipt/verify_POST_params.json b/doc/schemas/receipt/verify_POST_params.json new file mode 100644 index 00000000000..accc8b7c820 --- /dev/null +++ b/doc/schemas/receipt/verify_POST_params.json @@ -0,0 +1,17 @@ +{ + "properties": { + "receipt": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "receipt" + ], + "title": "receipt/verify/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/receipt/verify_POST_result.json b/doc/schemas/receipt/verify_POST_result.json new file mode 100644 index 00000000000..920d7652c68 --- /dev/null +++ b/doc/schemas/receipt/verify_POST_result.json @@ -0,0 +1,12 @@ +{ + "properties": { + "valid": { + "type": "boolean" + } + }, + "required": [ + "valid" + ], + "title": "receipt/verify/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/receipt_GET_params.json b/doc/schemas/receipt_GET_params.json new file mode 100644 index 00000000000..cab4d390bd4 --- /dev/null +++ b/doc/schemas/receipt_GET_params.json @@ -0,0 +1,14 @@ +{ + "properties": { + "commit": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "required": [ + "commit" + ], + "title": "receipt/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/receipt_GET_result.json b/doc/schemas/receipt_GET_result.json new file mode 100644 index 00000000000..38eefacaf36 --- /dev/null +++ b/doc/schemas/receipt_GET_result.json @@ -0,0 +1,17 @@ +{ + "properties": { + "receipt": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "receipt" + ], + "title": "receipt/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/recovery_share/submit_POST_params.json b/doc/schemas/recovery_share/submit_POST_params.json new file mode 100644 index 00000000000..d0627d76fe2 --- /dev/null +++ b/doc/schemas/recovery_share/submit_POST_params.json @@ -0,0 +1,4 @@ +{ + "title": "recovery_share/submit/params", + "type": "string" +} \ No newline at end of file diff --git a/doc/schemas/recovery_share/submit_POST_result.json b/doc/schemas/recovery_share/submit_POST_result.json new file mode 100644 index 00000000000..8b951e5d9c8 --- /dev/null +++ b/doc/schemas/recovery_share/submit_POST_result.json @@ -0,0 +1,4 @@ +{ + "title": "recovery_share/submit/result", + "type": "string" +} \ No newline at end of file diff --git a/doc/schemas/recovery_share_GET_result.json b/doc/schemas/recovery_share_GET_result.json new file mode 100644 index 00000000000..82e894be508 --- /dev/null +++ b/doc/schemas/recovery_share_GET_result.json @@ -0,0 +1,16 @@ +{ + "properties": { + "encrypted_recovery_share": { + "type": "string" + }, + "nonce": { + "type": "string" + } + }, + "required": [ + "encrypted_recovery_share", + "nonce" + ], + "title": "recovery_share/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/state_GET_result.json b/doc/schemas/state_GET_result.json new file mode 100644 index 00000000000..42031ec0696 --- /dev/null +++ b/doc/schemas/state_GET_result.json @@ -0,0 +1,42 @@ +{ + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "last_recovered_seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "last_signed_seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "recovery_target_seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "state": { + "enum": [ + "uninitialized", + "initialized", + "pending", + "partOfPublicNetwork", + "partOfNetwork", + "readingPublicLedger", + "readingPrivateLedger" + ] + } + }, + "required": [ + "id", + "state", + "last_signed_seqno" + ], + "title": "state/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/tx_GET_params.json b/doc/schemas/tx_GET_params.json new file mode 100644 index 00000000000..be21129895d --- /dev/null +++ b/doc/schemas/tx_GET_params.json @@ -0,0 +1,20 @@ +{ + "properties": { + "seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "required": [ + "view", + "seqno" + ], + "title": "tx/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/tx_GET_result.json b/doc/schemas/tx_GET_result.json new file mode 100644 index 00000000000..068146dc225 --- /dev/null +++ b/doc/schemas/tx_GET_result.json @@ -0,0 +1,17 @@ +{ + "properties": { + "status": { + "enum": [ + "UNKNOWN", + "PENDING", + "COMMITTED", + "INVALID" + ] + } + }, + "required": [ + "status" + ], + "title": "tx/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/user_id_GET_params.json b/doc/schemas/user_id_GET_params.json new file mode 100644 index 00000000000..d4babd1140b --- /dev/null +++ b/doc/schemas/user_id_GET_params.json @@ -0,0 +1,17 @@ +{ + "properties": { + "cert": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "cert" + ], + "title": "user_id/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/user_id_GET_result.json b/doc/schemas/user_id_GET_result.json new file mode 100644 index 00000000000..62469fc2e84 --- /dev/null +++ b/doc/schemas/user_id_GET_result.json @@ -0,0 +1,14 @@ +{ + "properties": { + "caller_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "caller_id" + ], + "title": "user_id/result", + "type": "object" +} \ No newline at end of file From 7314eb2bb36ce172e2774ce7629a9b2f579c9ba2 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 11 Sep 2020 13:21:46 +0100 Subject: [PATCH 32/53] Strip out some uninteresting TODOs --- src/ds/json_schema.h | 5 ----- src/ds/openapi.h | 5 +++-- src/node/rpc/endpoint_registry.h | 1 - 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/ds/json_schema.h b/src/ds/json_schema.h index 417ced51cb1..b103b07ed79 100644 --- a/src/ds/json_schema.h +++ b/src/ds/json_schema.h @@ -230,8 +230,6 @@ namespace ds items["type"] = "array"; auto sub_items = nlohmann::json::array(); - // TODO: OpenAPI doesn't like this tuple for "items", even though - // its valid JSON schema. Maybe fixed in a newer spec version? sub_items.push_back(schema_element()); sub_items.push_back(schema_element()); items["items"] = sub_items; @@ -270,9 +268,6 @@ namespace ds } else if constexpr (std::is_same::value) { - // TODO: OpenAPI validator isn't happy with these $ref elements, so - // we're being very vague for now - // schema["$ref"] = JsonSchema::hyperschema; schema["type"] = "object"; } else diff --git a/src/ds/openapi.h b/src/ds/openapi.h index d5609a9871f..6d7c90a1a78 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -211,8 +211,9 @@ namespace ds items["type"] = "array"; auto sub_items = nlohmann::json::array(); - // TODO: OpenAPI doesn't like this tuple for "items", even though - // its valid JSON schema. Maybe fixed in a newer spec version? + // NB: OpenAPI doesn't like this tuple for "items", even though + // its valid JSON schema. May need to switch this to oneOf to + // satisfy some validators sub_items.push_back(add_schema_component()); sub_items.push_back( add_schema_component()); diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index 45e20f18a89..004c2b79cd3 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -448,7 +448,6 @@ namespace ccf * internally, so must be able to populate the document * with the supported endpoints however it defines them. */ - // TODO: May want the entire rpc context, not just tx? virtual void build_api(nlohmann::json& document, kv::Tx&) { for (const auto& [path, verb_endpoints] : fully_qualified_endpoints) From afc0999e670a217ed56d82eaeb97937ab90781db Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 11 Sep 2020 16:56:08 +0100 Subject: [PATCH 33/53] Add schema for templated endpoints too --- doc/schemas/app_openapi.json | 1044 ++++++------ doc/schemas/gov_openapi.json | 1498 +++++++++++------ doc/schemas/node_openapi.json | 955 ++++++----- .../{proposal_id}/complete_POST_result.json | 30 + .../votes/{member_id}_GET_result.json | 25 + .../{proposal_id}/votes_POST_params.json | 25 + .../{proposal_id}/votes_POST_result.json | 30 + .../{proposal_id}/withdraw_POST_result.json | 30 + .../proposals/{proposal_id}_GET_result.json | 73 + src/ds/openapi.h | 12 + src/node/rpc/endpoint_registry.h | 141 +- 11 files changed, 2322 insertions(+), 1541 deletions(-) create mode 100644 doc/schemas/proposals/{proposal_id}/complete_POST_result.json create mode 100644 doc/schemas/proposals/{proposal_id}/votes/{member_id}_GET_result.json create mode 100644 doc/schemas/proposals/{proposal_id}/votes_POST_params.json create mode 100644 doc/schemas/proposals/{proposal_id}/votes_POST_result.json create mode 100644 doc/schemas/proposals/{proposal_id}/withdraw_POST_result.json create mode 100644 doc/schemas/proposals/{proposal_id}_GET_result.json diff --git a/doc/schemas/app_openapi.json b/doc/schemas/app_openapi.json index 497c7abaa01..af921f7ac67 100644 --- a/doc/schemas/app_openapi.json +++ b/doc/schemas/app_openapi.json @@ -1,4 +1,506 @@ { + "components": { + "schemas": { + "DELETE /app/log/private param:id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "DELETE /app/log/private response": { + "title": "log/private/result", + "type": "boolean" + }, + "DELETE /app/log/public param:id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "DELETE /app/log/public response": { + "title": "log/public/result", + "type": "boolean" + }, + "GET /app/api response": { + "title": "api/result" + }, + "GET /app/api/schema param:method": { + "type": "string" + }, + "GET /app/api/schema response": { + "properties": { + "params_schema": { + "type": "object" + }, + "result_schema": { + "type": "object" + } + }, + "required": [ + "params_schema", + "result_schema" + ], + "title": "api/schema/result", + "type": "object" + }, + "GET /app/code response": { + "properties": { + "versions": { + "items": { + "properties": { + "digest": { + "type": "string" + }, + "status": { + "enum": [ + "ACCEPTED", + "RETIRED" + ] + } + }, + "required": [ + "digest", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "versions" + ], + "title": "code/result", + "type": "object" + }, + "GET /app/commit response": { + "properties": { + "seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "required": [ + "view", + "seqno" + ], + "title": "commit/result", + "type": "object" + }, + "GET /app/endpoint_metrics response": { + "properties": { + "metrics": { + "additionalProperties": { + "additionalProperties": { + "properties": { + "calls": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "errors": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "failures": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "calls", + "errors", + "failures" + ], + "type": "object" + }, + "type": "object" + }, + "type": "object" + } + }, + "required": [ + "metrics" + ], + "title": "endpoint_metrics/result", + "type": "object" + }, + "GET /app/log/private param:id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "GET /app/log/private response": { + "properties": { + "msg": { + "type": "string" + } + }, + "required": [ + "msg" + ], + "title": "log/private/result", + "type": "object" + }, + "GET /app/log/public param:id": { + "type": "number" + }, + "GET /app/log/public response": { + "properties": { + "msg": { + "type": "string" + } + }, + "required": [ + "msg" + ], + "title": "log/public/result", + "type": "object" + }, + "GET /app/metrics response": { + "properties": { + "histogram": { + "properties": { + "buckets": {}, + "high": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "low": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "overflow": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "underflow": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "low", + "high", + "overflow", + "underflow", + "buckets" + ], + "type": "object" + }, + "tx_rates": {} + }, + "required": [ + "histogram", + "tx_rates" + ], + "title": "metrics/result", + "type": "object" + }, + "GET /app/network_info response": { + "properties": { + "nodes": { + "items": { + "properties": { + "host": { + "type": "string" + }, + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "port": { + "type": "string" + } + }, + "required": [ + "node_id", + "host", + "port" + ], + "type": "object" + }, + "type": "array" + }, + "primary_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "nodes", + "primary_id" + ], + "title": "network_info/result", + "type": "object" + }, + "GET /app/node/ids param:host": { + "type": "string" + }, + "GET /app/node/ids param:port": { + "type": "string" + }, + "GET /app/node/ids response": { + "properties": { + "nodes": { + "items": { + "properties": { + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "status": { + "enum": [ + "PENDING", + "TRUSTED", + "RETIRED" + ] + } + }, + "required": [ + "node_id", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "nodes" + ], + "title": "node/ids/result", + "type": "object" + }, + "GET /app/primary_info response": { + "properties": { + "current_view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "primary_host": { + "type": "string" + }, + "primary_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "primary_port": { + "type": "string" + } + }, + "required": [ + "primary_id", + "primary_host", + "primary_port", + "current_view" + ], + "title": "primary_info/result", + "type": "object" + }, + "GET /app/receipt param:commit": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "GET /app/receipt response": { + "properties": { + "receipt": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "receipt" + ], + "title": "receipt/result", + "type": "object" + }, + "GET /app/tx param:seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "GET /app/tx param:view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "GET /app/tx response": { + "properties": { + "status": { + "enum": [ + "UNKNOWN", + "PENDING", + "COMMITTED", + "INVALID" + ] + } + }, + "required": [ + "status" + ], + "title": "tx/result", + "type": "object" + }, + "GET /app/user_id param:cert": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "GET /app/user_id response": { + "properties": { + "caller_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "caller_id" + ], + "title": "user_id/result", + "type": "object" + }, + "POST /app/log/private :request": { + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "msg": { + "type": "string" + } + }, + "required": [ + "id", + "msg" + ], + "title": "log/private/params", + "type": "object" + }, + "POST /app/log/private response": { + "title": "log/private/result", + "type": "boolean" + }, + "POST /app/log/private/admin_only :request": { + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "msg": { + "type": "string" + } + }, + "required": [ + "id", + "msg" + ], + "title": "log/private/admin_only/params", + "type": "object" + }, + "POST /app/log/private/admin_only response": { + "title": "log/private/admin_only/result", + "type": "boolean" + }, + "POST /app/log/private/anonymous :request": { + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "msg": { + "type": "string" + } + }, + "required": [ + "id", + "msg" + ], + "title": "log/private/anonymous/params", + "type": "object" + }, + "POST /app/log/private/anonymous response": { + "title": "log/private/anonymous/result", + "type": "boolean" + }, + "POST /app/log/public :request": { + "properties": { + "id": { + "type": "number" + }, + "msg": { + "type": "string" + } + }, + "required": [ + "id", + "msg" + ], + "title": "log/public/params", + "type": "object" + }, + "POST /app/log/public response": { + "title": "log/public/result", + "type": "boolean" + }, + "POST /app/receipt/verify :request": { + "properties": { + "receipt": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "receipt" + ], + "title": "receipt/verify/params", + "type": "object" + }, + "POST /app/receipt/verify response": { + "properties": { + "valid": { + "type": "boolean" + } + }, + "required": [ + "valid" + ], + "title": "receipt/verify/result", + "type": "object" + } + } + }, "info": { "description": "Placeholder description", "title": "Placeholder title", @@ -13,11 +515,11 @@ "content": { "application/json": { "schema": { - "title": "api/result" + "$ref": "#/components/schemas/GET /app/api response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -30,7 +532,7 @@ "name": "method", "required": false, "schema": { - "type": "string" + "$ref": "#/components/schemas/GET /app/api/schema param:method" } } ], @@ -39,24 +541,11 @@ "content": { "application/json": { "schema": { - "properties": { - "params_schema": { - "type": "object" - }, - "result_schema": { - "type": "object" - } - }, - "required": [ - "params_schema", - "result_schema" - ], - "title": "api/schema/result", - "type": "object" + "$ref": "#/components/schemas/GET /app/api/schema response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -68,38 +557,11 @@ "content": { "application/json": { "schema": { - "properties": { - "versions": { - "items": { - "properties": { - "digest": { - "type": "string" - }, - "status": { - "enum": [ - "ACCEPTED", - "RETIRED" - ] - } - }, - "required": [ - "digest", - "status" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "versions" - ], - "title": "code/result", - "type": "object" + "$ref": "#/components/schemas/GET /app/code response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -111,28 +573,11 @@ "content": { "application/json": { "schema": { - "properties": { - "seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - } - }, - "required": [ - "view", - "seqno" - ], - "title": "commit/result", - "type": "object" + "$ref": "#/components/schemas/GET /app/commit response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -144,48 +589,11 @@ "content": { "application/json": { "schema": { - "properties": { - "metrics": { - "additionalProperties": { - "additionalProperties": { - "properties": { - "calls": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "errors": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "failures": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "calls", - "errors", - "failures" - ], - "type": "object" - }, - "type": "object" - }, - "type": "object" - } - }, - "required": [ - "metrics" - ], - "title": "endpoint_metrics/result", - "type": "object" + "$ref": "#/components/schemas/GET /app/endpoint_metrics response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -198,9 +606,7 @@ "name": "id", "required": false, "schema": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "$ref": "#/components/schemas/DELETE /app/log/private param:id" } } ], @@ -209,12 +615,11 @@ "content": { "application/json": { "schema": { - "title": "log/private/result", - "type": "boolean" + "$ref": "#/components/schemas/DELETE /app/log/private response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } }, @@ -225,9 +630,7 @@ "name": "id", "required": false, "schema": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "$ref": "#/components/schemas/GET /app/log/private param:id" } } ], @@ -236,20 +639,11 @@ "content": { "application/json": { "schema": { - "properties": { - "msg": { - "type": "string" - } - }, - "required": [ - "msg" - ], - "title": "log/private/result", - "type": "object" + "$ref": "#/components/schemas/GET /app/log/private response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } }, @@ -258,37 +652,22 @@ "content": { "application/json": { "schema": { - "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "msg": { - "type": "string" - } - }, - "required": [ - "id", - "msg" - ], - "title": "log/private/params", - "type": "object" + "$ref": "#/components/schemas/POST /app/log/private :request" } } - } + }, + "description": "Auto-generated request body schema" }, "responses": { "200": { "content": { "application/json": { "schema": { - "title": "log/private/result", - "type": "boolean" + "$ref": "#/components/schemas/POST /app/log/private response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -299,37 +678,22 @@ "content": { "application/json": { "schema": { - "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "msg": { - "type": "string" - } - }, - "required": [ - "id", - "msg" - ], - "title": "log/private/admin_only/params", - "type": "object" + "$ref": "#/components/schemas/POST /app/log/private/admin_only :request" } } - } + }, + "description": "Auto-generated request body schema" }, "responses": { "200": { "content": { "application/json": { "schema": { - "title": "log/private/admin_only/result", - "type": "boolean" + "$ref": "#/components/schemas/POST /app/log/private/admin_only response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -340,61 +704,22 @@ "content": { "application/json": { "schema": { - "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "msg": { - "type": "string" - } - }, - "required": [ - "id", - "msg" - ], - "title": "log/private/anonymous/params", - "type": "object" + "$ref": "#/components/schemas/POST /app/log/private/anonymous :request" } } - } + }, + "description": "Auto-generated request body schema" }, "responses": { "200": { "content": { "application/json": { "schema": { - "title": "log/private/anonymous/result", - "type": "boolean" + "$ref": "#/components/schemas/POST /app/log/private/anonymous response" } } }, - "description": "Auto-generated" - } - } - } - }, - "/app/log/private/historical": { - "get": { - "responses": { - "200": { - "content": { - "application/json": {} - }, - "description": "Auto-generated" - } - } - } - }, - "/app/log/private/prefix_cert": { - "post": { - "responses": { - "200": { - "content": { - "application/json": {} - }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -407,9 +732,7 @@ "name": "id", "required": false, "schema": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "$ref": "#/components/schemas/DELETE /app/log/public param:id" } } ], @@ -418,12 +741,11 @@ "content": { "application/json": { "schema": { - "title": "log/public/result", - "type": "boolean" + "$ref": "#/components/schemas/DELETE /app/log/public response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } }, @@ -434,7 +756,7 @@ "name": "id", "required": false, "schema": { - "type": "number" + "$ref": "#/components/schemas/GET /app/log/public param:id" } } ], @@ -443,20 +765,11 @@ "content": { "application/json": { "schema": { - "properties": { - "msg": { - "type": "string" - } - }, - "required": [ - "msg" - ], - "title": "log/public/result", - "type": "object" + "$ref": "#/components/schemas/GET /app/log/public response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } }, @@ -465,35 +778,22 @@ "content": { "application/json": { "schema": { - "properties": { - "id": { - "type": "number" - }, - "msg": { - "type": "string" - } - }, - "required": [ - "id", - "msg" - ], - "title": "log/public/params", - "type": "object" + "$ref": "#/components/schemas/POST /app/log/public :request" } } - } + }, + "description": "Auto-generated request body schema" }, "responses": { "200": { "content": { "application/json": { "schema": { - "title": "log/public/result", - "type": "boolean" + "$ref": "#/components/schemas/POST /app/log/public response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -505,52 +805,11 @@ "content": { "application/json": { "schema": { - "properties": { - "histogram": { - "properties": { - "buckets": {}, - "high": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "low": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "overflow": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "underflow": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "low", - "high", - "overflow", - "underflow", - "buckets" - ], - "type": "object" - }, - "tx_rates": {} - }, - "required": [ - "histogram", - "tx_rates" - ], - "title": "metrics/result", - "type": "object" + "$ref": "#/components/schemas/GET /app/metrics response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -562,47 +821,11 @@ "content": { "application/json": { "schema": { - "properties": { - "nodes": { - "items": { - "properties": { - "host": { - "type": "string" - }, - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "port": { - "type": "string" - } - }, - "required": [ - "node_id", - "host", - "port" - ], - "type": "object" - }, - "type": "array" - }, - "primary_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "nodes", - "primary_id" - ], - "title": "network_info/result", - "type": "object" + "$ref": "#/components/schemas/GET /app/network_info response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -615,7 +838,7 @@ "name": "host", "required": false, "schema": { - "type": "string" + "$ref": "#/components/schemas/GET /app/node/ids param:host" } }, { @@ -623,7 +846,7 @@ "name": "port", "required": false, "schema": { - "type": "string" + "$ref": "#/components/schemas/GET /app/node/ids param:port" } } ], @@ -632,41 +855,11 @@ "content": { "application/json": { "schema": { - "properties": { - "nodes": { - "items": { - "properties": { - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "status": { - "enum": [ - "PENDING", - "TRUSTED", - "RETIRED" - ] - } - }, - "required": [ - "node_id", - "status" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "nodes" - ], - "title": "node/ids/result", - "type": "object" + "$ref": "#/components/schemas/GET /app/node/ids response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -678,36 +871,11 @@ "content": { "application/json": { "schema": { - "properties": { - "current_view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "primary_host": { - "type": "string" - }, - "primary_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "primary_port": { - "type": "string" - } - }, - "required": [ - "primary_id", - "primary_host", - "primary_port", - "current_view" - ], - "title": "primary_info/result", - "type": "object" + "$ref": "#/components/schemas/GET /app/primary_info response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -720,9 +888,7 @@ "name": "commit", "required": false, "schema": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "$ref": "#/components/schemas/GET /app/receipt param:commit" } } ], @@ -731,25 +897,11 @@ "content": { "application/json": { "schema": { - "properties": { - "receipt": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "receipt" - ], - "title": "receipt/result", - "type": "object" + "$ref": "#/components/schemas/GET /app/receipt response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -760,44 +912,22 @@ "content": { "application/json": { "schema": { - "properties": { - "receipt": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "receipt" - ], - "title": "receipt/verify/params", - "type": "object" + "$ref": "#/components/schemas/POST /app/receipt/verify :request" } } - } + }, + "description": "Auto-generated request body schema" }, "responses": { "200": { "content": { "application/json": { "schema": { - "properties": { - "valid": { - "type": "boolean" - } - }, - "required": [ - "valid" - ], - "title": "receipt/verify/result", - "type": "object" + "$ref": "#/components/schemas/POST /app/receipt/verify response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -810,9 +940,7 @@ "name": "seqno", "required": false, "schema": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "$ref": "#/components/schemas/GET /app/tx param:seqno" } }, { @@ -820,9 +948,7 @@ "name": "view", "required": false, "schema": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "$ref": "#/components/schemas/GET /app/tx param:view" } } ], @@ -831,25 +957,11 @@ "content": { "application/json": { "schema": { - "properties": { - "status": { - "enum": [ - "UNKNOWN", - "PENDING", - "COMMITTED", - "INVALID" - ] - } - }, - "required": [ - "status" - ], - "title": "tx/result", - "type": "object" + "$ref": "#/components/schemas/GET /app/tx response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -862,12 +974,7 @@ "name": "cert", "required": false, "schema": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" + "$ref": "#/components/schemas/GET /app/user_id param:cert" } } ], @@ -876,22 +983,11 @@ "content": { "application/json": { "schema": { - "properties": { - "caller_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "caller_id" - ], - "title": "user_id/result", - "type": "object" + "$ref": "#/components/schemas/GET /app/user_id response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } diff --git a/doc/schemas/gov_openapi.json b/doc/schemas/gov_openapi.json index 5407187ee0f..5ddac09ac97 100644 --- a/doc/schemas/gov_openapi.json +++ b/doc/schemas/gov_openapi.json @@ -1,4 +1,799 @@ { + "components": { + "schemas": { + "GET /gov/api response": { + "title": "api/result" + }, + "GET /gov/api/schema param:method": { + "type": "string" + }, + "GET /gov/api/schema response": { + "properties": { + "params_schema": { + "type": "object" + }, + "result_schema": { + "type": "object" + } + }, + "required": [ + "params_schema", + "result_schema" + ], + "title": "api/schema/result", + "type": "object" + }, + "GET /gov/code response": { + "properties": { + "versions": { + "items": { + "properties": { + "digest": { + "type": "string" + }, + "status": { + "enum": [ + "ACCEPTED", + "RETIRED" + ] + } + }, + "required": [ + "digest", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "versions" + ], + "title": "code/result", + "type": "object" + }, + "GET /gov/commit response": { + "properties": { + "seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "required": [ + "view", + "seqno" + ], + "title": "commit/result", + "type": "object" + }, + "GET /gov/endpoint_metrics response": { + "properties": { + "metrics": { + "additionalProperties": { + "additionalProperties": { + "properties": { + "calls": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "errors": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "failures": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "calls", + "errors", + "failures" + ], + "type": "object" + }, + "type": "object" + }, + "type": "object" + } + }, + "required": [ + "metrics" + ], + "title": "endpoint_metrics/result", + "type": "object" + }, + "GET /gov/metrics response": { + "properties": { + "histogram": { + "properties": { + "buckets": {}, + "high": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "low": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "overflow": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "underflow": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "low", + "high", + "overflow", + "underflow", + "buckets" + ], + "type": "object" + }, + "tx_rates": {} + }, + "required": [ + "histogram", + "tx_rates" + ], + "title": "metrics/result", + "type": "object" + }, + "GET /gov/network_info response": { + "properties": { + "nodes": { + "items": { + "properties": { + "host": { + "type": "string" + }, + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "port": { + "type": "string" + } + }, + "required": [ + "node_id", + "host", + "port" + ], + "type": "object" + }, + "type": "array" + }, + "primary_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "nodes", + "primary_id" + ], + "title": "network_info/result", + "type": "object" + }, + "GET /gov/node/ids param:host": { + "type": "string" + }, + "GET /gov/node/ids param:port": { + "type": "string" + }, + "GET /gov/node/ids response": { + "properties": { + "nodes": { + "items": { + "properties": { + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "status": { + "enum": [ + "PENDING", + "TRUSTED", + "RETIRED" + ] + } + }, + "required": [ + "node_id", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "nodes" + ], + "title": "node/ids/result", + "type": "object" + }, + "GET /gov/primary_info response": { + "properties": { + "current_view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "primary_host": { + "type": "string" + }, + "primary_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "primary_port": { + "type": "string" + } + }, + "required": [ + "primary_id", + "primary_host", + "primary_port", + "current_view" + ], + "title": "primary_info/result", + "type": "object" + }, + "GET /gov/proposals/{proposal_id} response": { + "properties": { + "parameter": {}, + "proposer": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "script": { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + }, + "state": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + }, + "votes": { + "items": { + "items": [ + { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + } + ], + "type": "array" + }, + "type": "array" + } + }, + "required": [ + "script", + "parameter", + "proposer", + "state", + "votes" + ], + "title": "proposals/{proposal_id}/result", + "type": "object" + }, + "GET /gov/proposals/{proposal_id}/votes/{member_id} response": { + "properties": { + "ballot": { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + } + }, + "required": [ + "ballot" + ], + "title": "proposals/{proposal_id}/votes/{member_id}/result", + "type": "object" + }, + "GET /gov/receipt param:commit": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "GET /gov/receipt response": { + "properties": { + "receipt": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "receipt" + ], + "title": "receipt/result", + "type": "object" + }, + "GET /gov/recovery_share response": { + "properties": { + "encrypted_recovery_share": { + "type": "string" + }, + "nonce": { + "type": "string" + } + }, + "required": [ + "encrypted_recovery_share", + "nonce" + ], + "title": "recovery_share/result", + "type": "object" + }, + "GET /gov/tx param:seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "GET /gov/tx param:view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "GET /gov/tx response": { + "properties": { + "status": { + "enum": [ + "UNKNOWN", + "PENDING", + "COMMITTED", + "INVALID" + ] + } + }, + "required": [ + "status" + ], + "title": "tx/result", + "type": "object" + }, + "GET /gov/user_id param:cert": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "GET /gov/user_id response": { + "properties": { + "caller_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "caller_id" + ], + "title": "user_id/result", + "type": "object" + }, + "POST /gov/ack :request": { + "properties": { + "state_digest": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "state_digest" + ], + "title": "ack/params", + "type": "object" + }, + "POST /gov/ack response": { + "title": "ack/result", + "type": "boolean" + }, + "POST /gov/ack/update_state_digest response": { + "properties": { + "signed_req": { + "properties": { + "md": { + "enum": [ + "MBEDTLS_MD_NONE", + "MBEDTLS_MD_SHA1", + "MBEDTLS_MD_SHA256", + "MBEDTLS_MD_SHA384", + "MBEDTLS_MD_SHA512" + ] + }, + "req": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "request_body": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "sig": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "sig", + "req", + "request_body", + "md" + ], + "type": "object" + }, + "state_digest": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "state_digest", + "signed_req" + ], + "title": "ack/update_state_digest/result", + "type": "object" + }, + "POST /gov/proposals :request": { + "properties": { + "ballot": { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + }, + "parameter": {}, + "script": { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + } + }, + "required": [ + "script" + ], + "title": "proposals/params", + "type": "object" + }, + "POST /gov/proposals response": { + "properties": { + "proposal_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "proposer_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "state": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + } + }, + "required": [ + "proposal_id", + "proposer_id", + "state" + ], + "title": "proposals/result", + "type": "object" + }, + "POST /gov/proposals/{proposal_id}/complete response": { + "properties": { + "proposal_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "proposer_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "state": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + } + }, + "required": [ + "proposal_id", + "proposer_id", + "state" + ], + "title": "proposals/{proposal_id}/complete/result", + "type": "object" + }, + "POST /gov/proposals/{proposal_id}/votes :request": { + "properties": { + "ballot": { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + } + }, + "required": [ + "ballot" + ], + "title": "proposals/{proposal_id}/votes/params", + "type": "object" + }, + "POST /gov/proposals/{proposal_id}/votes response": { + "properties": { + "proposal_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "proposer_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "state": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + } + }, + "required": [ + "proposal_id", + "proposer_id", + "state" + ], + "title": "proposals/{proposal_id}/votes/result", + "type": "object" + }, + "POST /gov/proposals/{proposal_id}/withdraw response": { + "properties": { + "proposal_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "proposer_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "state": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + } + }, + "required": [ + "proposal_id", + "proposer_id", + "state" + ], + "title": "proposals/{proposal_id}/withdraw/result", + "type": "object" + }, + "POST /gov/query :request": { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "title": "query/params", + "type": "object" + }, + "POST /gov/query response": { + "title": "query/result" + }, + "POST /gov/read :request": { + "properties": { + "key": {}, + "table": { + "type": "string" + } + }, + "required": [ + "table", + "key" + ], + "title": "read/params", + "type": "object" + }, + "POST /gov/read response": { + "title": "read/result" + }, + "POST /gov/receipt/verify :request": { + "properties": { + "receipt": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "receipt" + ], + "title": "receipt/verify/params", + "type": "object" + }, + "POST /gov/receipt/verify response": { + "properties": { + "valid": { + "type": "boolean" + } + }, + "required": [ + "valid" + ], + "title": "receipt/verify/result", + "type": "object" + }, + "POST /gov/recovery_share/submit :request": { + "title": "recovery_share/submit/params", + "type": "string" + }, + "POST /gov/recovery_share/submit response": { + "title": "recovery_share/submit/result", + "type": "string" + } + } + }, "info": { "description": "Placeholder description", "title": "Placeholder title", @@ -12,36 +807,22 @@ "content": { "application/json": { "schema": { - "properties": { - "state_digest": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "state_digest" - ], - "title": "ack/params", - "type": "object" + "$ref": "#/components/schemas/POST /gov/ack :request" } } - } + }, + "description": "Auto-generated request body schema" }, "responses": { "200": { "content": { "application/json": { "schema": { - "title": "ack/result", - "type": "boolean" + "$ref": "#/components/schemas/POST /gov/ack response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -53,70 +834,11 @@ "content": { "application/json": { "schema": { - "properties": { - "signed_req": { - "properties": { - "md": { - "enum": [ - "MBEDTLS_MD_NONE", - "MBEDTLS_MD_SHA1", - "MBEDTLS_MD_SHA256", - "MBEDTLS_MD_SHA384", - "MBEDTLS_MD_SHA512" - ] - }, - "req": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "request_body": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "sig": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "sig", - "req", - "request_body", - "md" - ], - "type": "object" - }, - "state_digest": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "state_digest", - "signed_req" - ], - "title": "ack/update_state_digest/result", - "type": "object" + "$ref": "#/components/schemas/POST /gov/ack/update_state_digest response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -128,11 +850,11 @@ "content": { "application/json": { "schema": { - "title": "api/result" + "$ref": "#/components/schemas/GET /gov/api response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -145,7 +867,7 @@ "name": "method", "required": false, "schema": { - "type": "string" + "$ref": "#/components/schemas/GET /gov/api/schema param:method" } } ], @@ -154,24 +876,11 @@ "content": { "application/json": { "schema": { - "properties": { - "params_schema": { - "type": "object" - }, - "result_schema": { - "type": "object" - } - }, - "required": [ - "params_schema", - "result_schema" - ], - "title": "api/schema/result", - "type": "object" + "$ref": "#/components/schemas/GET /gov/api/schema response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -183,38 +892,11 @@ "content": { "application/json": { "schema": { - "properties": { - "versions": { - "items": { - "properties": { - "digest": { - "type": "string" - }, - "status": { - "enum": [ - "ACCEPTED", - "RETIRED" - ] - } - }, - "required": [ - "digest", - "status" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "versions" - ], - "title": "code/result", - "type": "object" + "$ref": "#/components/schemas/GET /gov/code response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -226,40 +908,11 @@ "content": { "application/json": { "schema": { - "properties": { - "seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - } - }, - "required": [ - "view", - "seqno" - ], - "title": "commit/result", - "type": "object" + "$ref": "#/components/schemas/GET /gov/commit response" } } }, - "description": "Auto-generated" - } - } - } - }, - "/gov/create": { - "post": { - "responses": { - "200": { - "content": { - "application/json": {} - }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -271,48 +924,11 @@ "content": { "application/json": { "schema": { - "properties": { - "metrics": { - "additionalProperties": { - "additionalProperties": { - "properties": { - "calls": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "errors": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "failures": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "calls", - "errors", - "failures" - ], - "type": "object" - }, - "type": "object" - }, - "type": "object" - } - }, - "required": [ - "metrics" - ], - "title": "endpoint_metrics/result", - "type": "object" + "$ref": "#/components/schemas/GET /gov/endpoint_metrics response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -324,52 +940,11 @@ "content": { "application/json": { "schema": { - "properties": { - "histogram": { - "properties": { - "buckets": {}, - "high": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "low": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "overflow": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "underflow": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "low", - "high", - "overflow", - "underflow", - "buckets" - ], - "type": "object" - }, - "tx_rates": {} - }, - "required": [ - "histogram", - "tx_rates" - ], - "title": "metrics/result", - "type": "object" + "$ref": "#/components/schemas/GET /gov/metrics response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -381,47 +956,11 @@ "content": { "application/json": { "schema": { - "properties": { - "nodes": { - "items": { - "properties": { - "host": { - "type": "string" - }, - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "port": { - "type": "string" - } - }, - "required": [ - "node_id", - "host", - "port" - ], - "type": "object" - }, - "type": "array" - }, - "primary_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "nodes", - "primary_id" - ], - "title": "network_info/result", - "type": "object" + "$ref": "#/components/schemas/GET /gov/network_info response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -434,7 +973,7 @@ "name": "host", "required": false, "schema": { - "type": "string" + "$ref": "#/components/schemas/GET /gov/node/ids param:host" } }, { @@ -442,7 +981,7 @@ "name": "port", "required": false, "schema": { - "type": "string" + "$ref": "#/components/schemas/GET /gov/node/ids param:port" } } ], @@ -451,41 +990,11 @@ "content": { "application/json": { "schema": { - "properties": { - "nodes": { - "items": { - "properties": { - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "status": { - "enum": [ - "PENDING", - "TRUSTED", - "RETIRED" - ] - } - }, - "required": [ - "node_id", - "status" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "nodes" - ], - "title": "node/ids/result", - "type": "object" + "$ref": "#/components/schemas/GET /gov/node/ids response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -497,36 +1006,11 @@ "content": { "application/json": { "schema": { - "properties": { - "current_view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "primary_host": { - "type": "string" - }, - "primary_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "primary_port": { - "type": "string" - } - }, - "required": [ - "primary_id", - "primary_host", - "primary_port", - "current_view" - ], - "title": "primary_info/result", - "type": "object" + "$ref": "#/components/schemas/GET /gov/primary_info response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -537,87 +1021,112 @@ "content": { "application/json": { "schema": { - "properties": { - "ballot": { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" - }, - "parameter": {}, - "script": { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" - } - }, - "required": [ - "script" - ], - "title": "proposals/params", - "type": "object" + "$ref": "#/components/schemas/POST /gov/proposals :request" } } + }, + "description": "Auto-generated request body schema" + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POST /gov/proposals response" + } + } + }, + "description": "Default response description" + } + } + } + }, + "/gov/proposals/{proposal_id}": { + "get": { + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GET /gov/proposals/{proposal_id} response" + } + } + }, + "description": "Default response description" + } + } + } + }, + "/gov/proposals/{proposal_id}/complete": { + "post": { + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POST /gov/proposals/{proposal_id}/complete response" + } + } + }, + "description": "Default response description" } + } + } + }, + "/gov/proposals/{proposal_id}/votes": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POST /gov/proposals/{proposal_id}/votes :request" + } + } + }, + "description": "Auto-generated request body schema" }, "responses": { "200": { "content": { "application/json": { "schema": { - "properties": { - "proposal_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "proposer_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "state": { - "enum": [ - "OPEN", - "ACCEPTED", - "WITHDRAWN", - "REJECTED", - "FAILED" - ] - } - }, - "required": [ - "proposal_id", - "proposer_id", - "state" - ], - "title": "proposals/result", - "type": "object" + "$ref": "#/components/schemas/POST /gov/proposals/{proposal_id}/votes response" + } + } + }, + "description": "Default response description" + } + } + } + }, + "/gov/proposals/{proposal_id}/votes/{member_id}": { + "get": { + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GET /gov/proposals/{proposal_id}/votes/{member_id} response" } } }, - "description": "Auto-generated" + "description": "Default response description" + } + } + } + }, + "/gov/proposals/{proposal_id}/withdraw": { + "post": { + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/POST /gov/proposals/{proposal_id}/withdraw response" + } + } + }, + "description": "Default response description" } } } @@ -628,35 +1137,22 @@ "content": { "application/json": { "schema": { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "title": "query/params", - "type": "object" + "$ref": "#/components/schemas/POST /gov/query :request" } } - } + }, + "description": "Auto-generated request body schema" }, "responses": { "200": { "content": { "application/json": { "schema": { - "title": "query/result" + "$ref": "#/components/schemas/POST /gov/query response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -667,32 +1163,22 @@ "content": { "application/json": { "schema": { - "properties": { - "key": {}, - "table": { - "type": "string" - } - }, - "required": [ - "table", - "key" - ], - "title": "read/params", - "type": "object" + "$ref": "#/components/schemas/POST /gov/read :request" } } - } + }, + "description": "Auto-generated request body schema" }, "responses": { "200": { "content": { "application/json": { "schema": { - "title": "read/result" + "$ref": "#/components/schemas/POST /gov/read response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -705,9 +1191,7 @@ "name": "commit", "required": false, "schema": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "$ref": "#/components/schemas/GET /gov/receipt param:commit" } } ], @@ -716,25 +1200,11 @@ "content": { "application/json": { "schema": { - "properties": { - "receipt": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "receipt" - ], - "title": "receipt/result", - "type": "object" + "$ref": "#/components/schemas/GET /gov/receipt response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -745,44 +1215,22 @@ "content": { "application/json": { "schema": { - "properties": { - "receipt": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "receipt" - ], - "title": "receipt/verify/params", - "type": "object" + "$ref": "#/components/schemas/POST /gov/receipt/verify :request" } } - } + }, + "description": "Auto-generated request body schema" }, "responses": { "200": { "content": { "application/json": { "schema": { - "properties": { - "valid": { - "type": "boolean" - } - }, - "required": [ - "valid" - ], - "title": "receipt/verify/result", - "type": "object" + "$ref": "#/components/schemas/POST /gov/receipt/verify response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -794,24 +1242,11 @@ "content": { "application/json": { "schema": { - "properties": { - "encrypted_recovery_share": { - "type": "string" - }, - "nonce": { - "type": "string" - } - }, - "required": [ - "encrypted_recovery_share", - "nonce" - ], - "title": "recovery_share/result", - "type": "object" + "$ref": "#/components/schemas/GET /gov/recovery_share response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -822,23 +1257,22 @@ "content": { "application/json": { "schema": { - "title": "recovery_share/submit/params", - "type": "string" + "$ref": "#/components/schemas/POST /gov/recovery_share/submit :request" } } - } + }, + "description": "Auto-generated request body schema" }, "responses": { "200": { "content": { "application/json": { "schema": { - "title": "recovery_share/submit/result", - "type": "string" + "$ref": "#/components/schemas/POST /gov/recovery_share/submit response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -851,9 +1285,7 @@ "name": "seqno", "required": false, "schema": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "$ref": "#/components/schemas/GET /gov/tx param:seqno" } }, { @@ -861,9 +1293,7 @@ "name": "view", "required": false, "schema": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "$ref": "#/components/schemas/GET /gov/tx param:view" } } ], @@ -872,25 +1302,11 @@ "content": { "application/json": { "schema": { - "properties": { - "status": { - "enum": [ - "UNKNOWN", - "PENDING", - "COMMITTED", - "INVALID" - ] - } - }, - "required": [ - "status" - ], - "title": "tx/result", - "type": "object" + "$ref": "#/components/schemas/GET /gov/tx response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -903,12 +1319,7 @@ "name": "cert", "required": false, "schema": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" + "$ref": "#/components/schemas/GET /gov/user_id param:cert" } } ], @@ -917,22 +1328,11 @@ "content": { "application/json": { "schema": { - "properties": { - "caller_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "caller_id" - ], - "title": "user_id/result", - "type": "object" + "$ref": "#/components/schemas/GET /gov/user_id response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } diff --git a/doc/schemas/node_openapi.json b/doc/schemas/node_openapi.json index dbba6623983..7d7e7929ce4 100644 --- a/doc/schemas/node_openapi.json +++ b/doc/schemas/node_openapi.json @@ -1,4 +1,460 @@ { + "components": { + "schemas": { + "GET /node/api response": { + "title": "api/result" + }, + "GET /node/api/schema param:method": { + "type": "string" + }, + "GET /node/api/schema response": { + "properties": { + "params_schema": { + "type": "object" + }, + "result_schema": { + "type": "object" + } + }, + "required": [ + "params_schema", + "result_schema" + ], + "title": "api/schema/result", + "type": "object" + }, + "GET /node/code response": { + "properties": { + "versions": { + "items": { + "properties": { + "digest": { + "type": "string" + }, + "status": { + "enum": [ + "ACCEPTED", + "RETIRED" + ] + } + }, + "required": [ + "digest", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "versions" + ], + "title": "code/result", + "type": "object" + }, + "GET /node/commit response": { + "properties": { + "seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "required": [ + "view", + "seqno" + ], + "title": "commit/result", + "type": "object" + }, + "GET /node/endpoint_metrics response": { + "properties": { + "metrics": { + "additionalProperties": { + "additionalProperties": { + "properties": { + "calls": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "errors": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "failures": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "calls", + "errors", + "failures" + ], + "type": "object" + }, + "type": "object" + }, + "type": "object" + } + }, + "required": [ + "metrics" + ], + "title": "endpoint_metrics/result", + "type": "object" + }, + "GET /node/metrics response": { + "properties": { + "histogram": { + "properties": { + "buckets": {}, + "high": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "low": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "overflow": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "underflow": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "low", + "high", + "overflow", + "underflow", + "buckets" + ], + "type": "object" + }, + "tx_rates": {} + }, + "required": [ + "histogram", + "tx_rates" + ], + "title": "metrics/result", + "type": "object" + }, + "GET /node/network_info response": { + "properties": { + "nodes": { + "items": { + "properties": { + "host": { + "type": "string" + }, + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "port": { + "type": "string" + } + }, + "required": [ + "node_id", + "host", + "port" + ], + "type": "object" + }, + "type": "array" + }, + "primary_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "nodes", + "primary_id" + ], + "title": "network_info/result", + "type": "object" + }, + "GET /node/node/ids param:host": { + "type": "string" + }, + "GET /node/node/ids param:port": { + "type": "string" + }, + "GET /node/node/ids response": { + "properties": { + "nodes": { + "items": { + "properties": { + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "status": { + "enum": [ + "PENDING", + "TRUSTED", + "RETIRED" + ] + } + }, + "required": [ + "node_id", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "nodes" + ], + "title": "node/ids/result", + "type": "object" + }, + "GET /node/primary_info response": { + "properties": { + "current_view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "primary_host": { + "type": "string" + }, + "primary_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "primary_port": { + "type": "string" + } + }, + "required": [ + "primary_id", + "primary_host", + "primary_port", + "current_view" + ], + "title": "primary_info/result", + "type": "object" + }, + "GET /node/quote response": { + "properties": { + "quotes": { + "items": { + "properties": { + "error": { + "type": "string" + }, + "mrenclave": { + "type": "string" + }, + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "raw": { + "type": "string" + } + }, + "required": [ + "node_id", + "raw" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "quotes" + ], + "title": "quote/result", + "type": "object" + }, + "GET /node/quotes response": { + "properties": { + "quotes": { + "items": { + "properties": { + "error": { + "type": "string" + }, + "mrenclave": { + "type": "string" + }, + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "raw": { + "type": "string" + } + }, + "required": [ + "node_id", + "raw" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "quotes" + ], + "title": "quotes/result", + "type": "object" + }, + "GET /node/receipt param:commit": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "GET /node/receipt response": { + "properties": { + "receipt": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "receipt" + ], + "title": "receipt/result", + "type": "object" + }, + "GET /node/state response": { + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "last_recovered_seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "last_signed_seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "recovery_target_seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "state": { + "enum": [ + "uninitialized", + "initialized", + "pending", + "partOfPublicNetwork", + "partOfNetwork", + "readingPublicLedger", + "readingPrivateLedger" + ] + } + }, + "required": [ + "id", + "state", + "last_signed_seqno" + ], + "title": "state/result", + "type": "object" + }, + "GET /node/tx param:seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "GET /node/tx param:view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "GET /node/tx response": { + "properties": { + "status": { + "enum": [ + "UNKNOWN", + "PENDING", + "COMMITTED", + "INVALID" + ] + } + }, + "required": [ + "status" + ], + "title": "tx/result", + "type": "object" + }, + "POST /node/receipt/verify :request": { + "properties": { + "receipt": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "receipt" + ], + "title": "receipt/verify/params", + "type": "object" + }, + "POST /node/receipt/verify response": { + "properties": { + "valid": { + "type": "boolean" + } + }, + "required": [ + "valid" + ], + "title": "receipt/verify/result", + "type": "object" + } + } + }, "info": { "description": "Placeholder description", "title": "Placeholder title", @@ -13,11 +469,11 @@ "content": { "application/json": { "schema": { - "title": "api/result" + "$ref": "#/components/schemas/GET /node/api response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -30,7 +486,7 @@ "name": "method", "required": false, "schema": { - "type": "string" + "$ref": "#/components/schemas/GET /node/api/schema param:method" } } ], @@ -39,24 +495,11 @@ "content": { "application/json": { "schema": { - "properties": { - "params_schema": { - "type": "object" - }, - "result_schema": { - "type": "object" - } - }, - "required": [ - "params_schema", - "result_schema" - ], - "title": "api/schema/result", - "type": "object" + "$ref": "#/components/schemas/GET /node/api/schema response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -68,38 +511,11 @@ "content": { "application/json": { "schema": { - "properties": { - "versions": { - "items": { - "properties": { - "digest": { - "type": "string" - }, - "status": { - "enum": [ - "ACCEPTED", - "RETIRED" - ] - } - }, - "required": [ - "digest", - "status" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "versions" - ], - "title": "code/result", - "type": "object" + "$ref": "#/components/schemas/GET /node/code response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -111,28 +527,11 @@ "content": { "application/json": { "schema": { - "properties": { - "seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - } - }, - "required": [ - "view", - "seqno" - ], - "title": "commit/result", - "type": "object" + "$ref": "#/components/schemas/GET /node/commit response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -144,60 +543,11 @@ "content": { "application/json": { "schema": { - "properties": { - "metrics": { - "additionalProperties": { - "additionalProperties": { - "properties": { - "calls": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "errors": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "failures": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "calls", - "errors", - "failures" - ], - "type": "object" - }, - "type": "object" - }, - "type": "object" - } - }, - "required": [ - "metrics" - ], - "title": "endpoint_metrics/result", - "type": "object" + "$ref": "#/components/schemas/GET /node/endpoint_metrics response" } } }, - "description": "Auto-generated" - } - } - } - }, - "/node/join": { - "post": { - "responses": { - "200": { - "content": { - "application/json": {} - }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -209,64 +559,11 @@ "content": { "application/json": { "schema": { - "properties": { - "histogram": { - "properties": { - "buckets": {}, - "high": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "low": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "overflow": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "underflow": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "low", - "high", - "overflow", - "underflow", - "buckets" - ], - "type": "object" - }, - "tx_rates": {} - }, - "required": [ - "histogram", - "tx_rates" - ], - "title": "metrics/result", - "type": "object" + "$ref": "#/components/schemas/GET /node/metrics response" } } }, - "description": "Auto-generated" - } - } - } - }, - "/node/network": { - "get": { - "responses": { - "200": { - "content": { - "application/json": {} - }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -278,47 +575,11 @@ "content": { "application/json": { "schema": { - "properties": { - "nodes": { - "items": { - "properties": { - "host": { - "type": "string" - }, - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "port": { - "type": "string" - } - }, - "required": [ - "node_id", - "host", - "port" - ], - "type": "object" - }, - "type": "array" - }, - "primary_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "nodes", - "primary_id" - ], - "title": "network_info/result", - "type": "object" + "$ref": "#/components/schemas/GET /node/network_info response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -331,7 +592,7 @@ "name": "host", "required": false, "schema": { - "type": "string" + "$ref": "#/components/schemas/GET /node/node/ids param:host" } }, { @@ -339,7 +600,7 @@ "name": "port", "required": false, "schema": { - "type": "string" + "$ref": "#/components/schemas/GET /node/node/ids param:port" } } ], @@ -348,53 +609,11 @@ "content": { "application/json": { "schema": { - "properties": { - "nodes": { - "items": { - "properties": { - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "status": { - "enum": [ - "PENDING", - "TRUSTED", - "RETIRED" - ] - } - }, - "required": [ - "node_id", - "status" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "nodes" - ], - "title": "node/ids/result", - "type": "object" + "$ref": "#/components/schemas/GET /node/node/ids response" } } }, - "description": "Auto-generated" - } - } - } - }, - "/node/primary": { - "head": { - "responses": { - "200": { - "content": { - "application/json": {} - }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -406,36 +625,11 @@ "content": { "application/json": { "schema": { - "properties": { - "current_view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "primary_host": { - "type": "string" - }, - "primary_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "primary_port": { - "type": "string" - } - }, - "required": [ - "primary_id", - "primary_host", - "primary_port", - "current_view" - ], - "title": "primary_info/result", - "type": "object" + "$ref": "#/components/schemas/GET /node/primary_info response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -447,43 +641,11 @@ "content": { "application/json": { "schema": { - "properties": { - "quotes": { - "items": { - "properties": { - "error": { - "type": "string" - }, - "mrenclave": { - "type": "string" - }, - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "raw": { - "type": "string" - } - }, - "required": [ - "node_id", - "raw" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "quotes" - ], - "title": "quote/result", - "type": "object" + "$ref": "#/components/schemas/GET /node/quote response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -495,43 +657,11 @@ "content": { "application/json": { "schema": { - "properties": { - "quotes": { - "items": { - "properties": { - "error": { - "type": "string" - }, - "mrenclave": { - "type": "string" - }, - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "raw": { - "type": "string" - } - }, - "required": [ - "node_id", - "raw" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "quotes" - ], - "title": "quotes/result", - "type": "object" + "$ref": "#/components/schemas/GET /node/quotes response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -544,9 +674,7 @@ "name": "commit", "required": false, "schema": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "$ref": "#/components/schemas/GET /node/receipt param:commit" } } ], @@ -555,25 +683,11 @@ "content": { "application/json": { "schema": { - "properties": { - "receipt": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "receipt" - ], - "title": "receipt/result", - "type": "object" + "$ref": "#/components/schemas/GET /node/receipt response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -584,44 +698,22 @@ "content": { "application/json": { "schema": { - "properties": { - "receipt": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "receipt" - ], - "title": "receipt/verify/params", - "type": "object" + "$ref": "#/components/schemas/POST /node/receipt/verify :request" } } - } + }, + "description": "Auto-generated request body schema" }, "responses": { "200": { "content": { "application/json": { "schema": { - "properties": { - "valid": { - "type": "boolean" - } - }, - "required": [ - "valid" - ], - "title": "receipt/verify/result", - "type": "object" + "$ref": "#/components/schemas/POST /node/receipt/verify response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -633,50 +725,11 @@ "content": { "application/json": { "schema": { - "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "last_recovered_seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "last_signed_seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "recovery_target_seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "state": { - "enum": [ - "uninitialized", - "initialized", - "pending", - "partOfPublicNetwork", - "partOfNetwork", - "readingPublicLedger", - "readingPrivateLedger" - ] - } - }, - "required": [ - "id", - "state", - "last_signed_seqno" - ], - "title": "state/result", - "type": "object" + "$ref": "#/components/schemas/GET /node/state response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } @@ -689,9 +742,7 @@ "name": "seqno", "required": false, "schema": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "$ref": "#/components/schemas/GET /node/tx param:seqno" } }, { @@ -699,9 +750,7 @@ "name": "view", "required": false, "schema": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "$ref": "#/components/schemas/GET /node/tx param:view" } } ], @@ -710,25 +759,11 @@ "content": { "application/json": { "schema": { - "properties": { - "status": { - "enum": [ - "UNKNOWN", - "PENDING", - "COMMITTED", - "INVALID" - ] - } - }, - "required": [ - "status" - ], - "title": "tx/result", - "type": "object" + "$ref": "#/components/schemas/GET /node/tx response" } } }, - "description": "Auto-generated" + "description": "Default response description" } } } diff --git a/doc/schemas/proposals/{proposal_id}/complete_POST_result.json b/doc/schemas/proposals/{proposal_id}/complete_POST_result.json new file mode 100644 index 00000000000..6287c75c763 --- /dev/null +++ b/doc/schemas/proposals/{proposal_id}/complete_POST_result.json @@ -0,0 +1,30 @@ +{ + "properties": { + "proposal_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "proposer_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "state": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + } + }, + "required": [ + "proposal_id", + "proposer_id", + "state" + ], + "title": "proposals/{proposal_id}/complete/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/votes/{member_id}_GET_result.json b/doc/schemas/proposals/{proposal_id}/votes/{member_id}_GET_result.json new file mode 100644 index 00000000000..5b970d9f4ef --- /dev/null +++ b/doc/schemas/proposals/{proposal_id}/votes/{member_id}_GET_result.json @@ -0,0 +1,25 @@ +{ + "properties": { + "ballot": { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + } + }, + "required": [ + "ballot" + ], + "title": "proposals/{proposal_id}/votes/{member_id}/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/votes_POST_params.json b/doc/schemas/proposals/{proposal_id}/votes_POST_params.json new file mode 100644 index 00000000000..ec8d8edae48 --- /dev/null +++ b/doc/schemas/proposals/{proposal_id}/votes_POST_params.json @@ -0,0 +1,25 @@ +{ + "properties": { + "ballot": { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + } + }, + "required": [ + "ballot" + ], + "title": "proposals/{proposal_id}/votes/params", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/votes_POST_result.json b/doc/schemas/proposals/{proposal_id}/votes_POST_result.json new file mode 100644 index 00000000000..f052c8c35d1 --- /dev/null +++ b/doc/schemas/proposals/{proposal_id}/votes_POST_result.json @@ -0,0 +1,30 @@ +{ + "properties": { + "proposal_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "proposer_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "state": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + } + }, + "required": [ + "proposal_id", + "proposer_id", + "state" + ], + "title": "proposals/{proposal_id}/votes/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/withdraw_POST_result.json b/doc/schemas/proposals/{proposal_id}/withdraw_POST_result.json new file mode 100644 index 00000000000..2a38ef2fff8 --- /dev/null +++ b/doc/schemas/proposals/{proposal_id}/withdraw_POST_result.json @@ -0,0 +1,30 @@ +{ + "properties": { + "proposal_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "proposer_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "state": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + } + }, + "required": [ + "proposal_id", + "proposer_id", + "state" + ], + "title": "proposals/{proposal_id}/withdraw/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}_GET_result.json b/doc/schemas/proposals/{proposal_id}_GET_result.json new file mode 100644 index 00000000000..48d91ddab99 --- /dev/null +++ b/doc/schemas/proposals/{proposal_id}_GET_result.json @@ -0,0 +1,73 @@ +{ + "properties": { + "parameter": {}, + "proposer": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "script": { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + }, + "state": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + }, + "votes": { + "items": { + "items": [ + { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + } + ], + "type": "array" + }, + "type": "array" + } + }, + "required": [ + "script", + "parameter", + "proposer", + "state", + "votes" + ], + "title": "proposals/{proposal_id}/result", + "type": "object" +} \ No newline at end of file diff --git a/src/ds/openapi.h b/src/ds/openapi.h index 6d7c90a1a78..2b7c1850e31 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -302,6 +302,18 @@ namespace ds schema(media_type(rb, content_type)) = sh.add_schema_component(); } + static inline void add_request_parameter_schema( + nlohmann::json& document, + const std::string& uri, + http_method verb, + const nlohmann::json& param) + { + check_path_valid(uri); + + auto& params = parameters(path_operation(path(document, uri), verb)); + params.push_back(param); + } + static inline void add_response_schema( nlohmann::json& document, const std::string& uri, diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index 004c2b79cd3..51faffc5151 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -442,6 +442,76 @@ namespace ccf return default_endpoint.value(); } + static void add_endpoint_to_api_document( + nlohmann::json& document, + const std::string& path, + RESTVerb verb, + const Endpoint& endpoint) + { + const auto http_verb = verb.get_http_method(); + if (!http_verb.has_value()) + { + // Non-HTTP (ie WebSockets) endpoints are not documented + return; + } + + // Temporary: All elements get verbose unique names so they can be stored + // in components + const auto verbose_name = fmt::format("{} {}", verb.c_str(), path); + + if (!endpoint.params_schema.empty()) + { + if (http_verb.value() == HTTP_GET || http_verb.value() == HTTP_DELETE) + { + // TODO: Should set these as individual parameters, not reparse + // them here + if (endpoint.params_schema["type"] != "object") + { + throw std::logic_error(fmt::format( + "Unexpected params schema type: {}", + endpoint.params_schema.dump())); + } + + const auto& required_parameters = endpoint.params_schema["required"]; + for (const auto& [name, schema] : + endpoint.params_schema["properties"].items()) + { + auto parameter = nlohmann::json::object(); + parameter["name"] = name; + parameter["in"] = "query"; + parameter["required"] = + required_parameters.find(name) != required_parameters.end(); + parameter["schema"] = ds::openapi::add_schema_to_components( + document, fmt::format("{} param:{}", verbose_name, name), schema); + ds::openapi::add_request_parameter_schema( + document, path, http_verb.value(), parameter); + } + } + else + { + ds::openapi::add_request_body_schema( + document, + path, + http_verb.value(), + http::headervalues::contenttype::JSON, + fmt::format("{} :request", verbose_name), + endpoint.params_schema); + } + } + + if (!endpoint.result_schema.empty()) + { + ds::openapi::add_response_schema( + document, + path, + http_verb.value(), + HTTP_STATUS_OK, + http::headervalues::contenttype::JSON, + fmt::format("{} response", verbose_name), + endpoint.result_schema); + } + } + /** Populate document with all supported methods * * This is virtual since derived classes may do their own dispatch @@ -453,68 +523,23 @@ namespace ccf for (const auto& [path, verb_endpoints] : fully_qualified_endpoints) { const auto full_path = fmt::format("/{}/{}", method_prefix, path); - auto& path_object = ds::openapi::path(document, full_path); - for (const auto& [verb, handler] : verb_endpoints) + // auto& path_object = ds::openapi::path(document, full_path); + for (const auto& [verb, endpoint] : verb_endpoints) { - const auto http_verb = verb.get_http_method(); - if (!http_verb.has_value()) - { - continue; - } - - auto& path_operation = ds::openapi::path_operation(path_object, http_verb.value()); - if (!handler.params_schema.empty()) - { - if (http_verb.value() == HTTP_GET || http_verb.value() == HTTP_DELETE) - { - // TODO: Should set these as individual parameters, not reparse them here - if (handler.params_schema["type"] != "object") - { - throw std::logic_error(fmt::format("Unexpected params schema type: {}", handler.params_schema.dump())); - } - - const auto& required_parameters = handler.params_schema["required"]; - auto& parameters = ds::openapi::parameters(path_operation); - for (const auto& [name, schema]: handler.params_schema["properties"].items()) - { - auto parameter = nlohmann::json::object(); - parameter["name"] = name; - parameter["in"] = "query"; - parameter["required"] = required_parameters.find(name) != required_parameters.end(); - parameter["schema"] = schema; - parameters.push_back(parameter); - } - } - else - { - auto& request_body = ds::openapi::request_body(path_operation); - auto& request_body_json = ds::openapi::media_type(request_body, http::headervalues::contenttype::JSON); - auto& request_body_json_schema = ds::openapi::schema(request_body_json); - request_body_json_schema = handler.params_schema; - } - } - - auto& response_ok = ds::openapi::response( - path_operation, HTTP_STATUS_OK, "Auto-generated"); - auto& response_ok_json = ds::openapi::media_type( - response_ok, http::headervalues::contenttype::JSON); - - if (!handler.result_schema.empty()) - { - auto& response_ok_json_schema = ds::openapi::schema(response_ok_json); - response_ok_json_schema = handler.result_schema; - } + add_endpoint_to_api_document(document, full_path, verb, endpoint); } } - // TODO - // for (const auto& [path, verb_endpoints] : templated_endpoints) - // { - // for (const auto& [verb, endpoint] : verb_endpoints) - // { - // out.endpoints.push_back({verb.c_str(), path}); - // } - // } + for (const auto& [path, verb_endpoints] : templated_endpoints) + { + const auto full_path = fmt::format("/{}/{}", method_prefix, path); + for (const auto& [verb, endpoint] : verb_endpoints) + { + add_endpoint_to_api_document(document, full_path, verb, endpoint); + + // TODO: Document path template args + } + } } virtual void endpoint_metrics(kv::Tx&, EndpointMetrics::Out& out) From 45dc53d3e37906f1ff647d509af68531fda33577 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 11 Sep 2020 18:09:20 +0100 Subject: [PATCH 34/53] WIO --- src/ds/json.h | 4 + src/ds/json_schema.h | 22 +--- src/ds/openapi.h | 10 +- src/ds/test/openapi.cpp | 16 ++- src/node/rpc/endpoint_registry.h | 175 +++++++++++++++++++------------ 5 files changed, 138 insertions(+), 89 deletions(-) diff --git a/src/ds/json.h b/src/ds/json.h index 27f7393d133..03d43cbefbe 100644 --- a/src/ds/json.h +++ b/src/ds/json.h @@ -720,6 +720,10 @@ namespace std #define DECLARE_JSON_ENUM(TYPE, ...) \ NLOHMANN_JSON_SERIALIZE_ENUM(TYPE, __VA_ARGS__) \ + inline std::string schema_name(const TYPE&) \ + { \ + return #TYPE; \ + } \ inline void fill_enum_schema(nlohmann::json& j, const TYPE&) \ { \ static const std::pair m[] = __VA_ARGS__; \ diff --git a/src/ds/json_schema.h b/src/ds/json_schema.h index b103b07ed79..85e5e9ad5d5 100644 --- a/src/ds/json_schema.h +++ b/src/ds/json_schema.h @@ -85,24 +85,6 @@ namespace ds fill_json_schema(schema, t); } } - - template - nlohmann::json add_schema_to_components(TDoc& doc) - { - T t; - const auto name = schema_name(t); - const auto ib = doc.components.schemas.try_emplace(name); - if (ib.second) - { - auto& j = ib.first->second; - add_schema_components(doc, j, t); - } - - auto schema_ref_object = nlohmann::json::object(); - schema_ref_object["$ref"] = - fmt::format("#/components/schemas/{}", name); - return schema_ref_object; - } } template @@ -192,6 +174,10 @@ namespace ds { return "json"; } + else if constexpr (std::is_same::value) + { + return "json_schema"; + } else { return adl::schema_name(); diff --git a/src/ds/openapi.h b/src/ds/openapi.h index 2b7c1850e31..cad8a72913f 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -260,8 +260,16 @@ namespace ds { auto& j = ib.first.value(); // Use argument-dependent-lookup to call correct functions + T t; - add_schema_components(*this, j, t); + if constexpr (std::is_enum::value) + { + fill_enum_schema(j, t); + } + else + { + add_schema_components(*this, j, t); + } } return components_ref_object(name); diff --git a/src/ds/test/openapi.cpp b/src/ds/test/openapi.cpp index a8cdabadcc3..e3be4971c56 100644 --- a/src/ds/test/openapi.cpp +++ b/src/ds/test/openapi.cpp @@ -128,14 +128,28 @@ DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(Bar); DECLARE_JSON_REQUIRED_FIELDS(Bar, name); DECLARE_JSON_OPTIONAL_FIELDS(Bar, f); +enum class Vehicle +{ + Car, + Pedalo, + Submarine, +}; + +DECLARE_JSON_ENUM( + Vehicle, + {{Vehicle::Car, "vroom vroom"}, + {Vehicle::Pedalo, "splash splash"}, + {Vehicle::Submarine, "glug glug"}}); + struct Baz : public Bar { uint16_t n; double x; double y; + Vehicle v; }; DECLARE_JSON_TYPE_WITH_BASE_AND_OPTIONAL_FIELDS(Baz, Bar); -DECLARE_JSON_REQUIRED_FIELDS(Baz, n); +DECLARE_JSON_REQUIRED_FIELDS(Baz, n, v); DECLARE_JSON_OPTIONAL_FIELDS(Baz, x, y); struct Buzz : public Baz diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index 51faffc5151..d11c1db8910 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -47,6 +47,8 @@ namespace ccf using CommandEndpointFunction = std::function; + using SchemaBuilderFn = std::function; + enum class ForwardingRequired { Sometimes, @@ -91,6 +93,9 @@ namespace ccf EndpointFunction func; EndpointRegistry* registry = nullptr; Metrics metrics = {}; + + std::vector schema_builders = {}; + nlohmann::json params_schema = nullptr; /** Sets the JSON schema that the request parameters must comply with. @@ -101,6 +106,20 @@ namespace ccf Endpoint& set_params_schema(const nlohmann::json& j) { params_schema = j; + + schema_builders.push_back([this, j](nlohmann::json& document) { + const auto http_verb = verb.get_http_method(); + if (!http_verb.has_value()) + { + return; + } + + using namespace ds::openapi; + auto& rb = request_body(path_operation( + ds::openapi::path(document, method), http_verb.value())); + schema(media_type(rb, http::headervalues::contenttype::JSON)) = j; + }); + return *this; } @@ -114,6 +133,20 @@ namespace ccf Endpoint& set_result_schema(const nlohmann::json& j) { result_schema = j; + + schema_builders.push_back([this, j](nlohmann::json& document) { + const auto http_verb = verb.get_http_method(); + if (!http_verb.has_value()) + { + return; + } + + using namespace ds::openapi; + auto& r = + response(path_operation(ds::openapi::path(document, method), http_verb.value()), HTTP_STATUS_OK); + schema(media_type(r, http::headervalues::contenttype::JSON)) = j; + }); + return *this; } @@ -136,6 +169,57 @@ namespace ccf if constexpr (!std::is_same_v) { params_schema = ds::json::build_schema(method + "/params"); + + schema_builders.push_back([this](nlohmann::json& document) { + const auto http_verb = verb.get_http_method(); + if (!http_verb.has_value()) + { + // Non-HTTP (ie WebSockets) endpoints are not documented + return; + } + + if ( + http_verb.value() == HTTP_GET || http_verb.value() == HTTP_DELETE) + { + // TODO: Should set these as individual parameters, not reparse + // them here + if (params_schema["type"] != "object") + { + throw std::logic_error(fmt::format( + "Unexpected params schema type: {}", + params_schema.dump())); + } + + //const auto& required_parameters = params_schema["required"]; + for (const auto& [name, schema] : + params_schema["properties"].items()) + { + // TODO: Revive this somehow? + LOG_FAIL_FMT("Ignoring parameter {} in {}", name, method); + + // auto parameter = nlohmann::json::object(); + // parameter["name"] = name; + // parameter["in"] = "query"; + // parameter["required"] = + // required_parameters.find(name) != + // required_parameters.end(); + // parameter["schema"] = ds::openapi::add_schema_to_components( + // document, + // fmt::format("{} param:{}", verbose_name, name), + // schema); + // ds::openapi::add_request_parameter_schema( + // document, path, http_verb.value(), parameter); + } + } + else + { + ds::openapi::add_request_body_schema( + document, + method, + http_verb.value(), + http::headervalues::contenttype::JSON); + } + }); } else { @@ -145,6 +229,21 @@ namespace ccf if constexpr (!std::is_same_v) { result_schema = ds::json::build_schema(method + "/result"); + + schema_builders.push_back([this](nlohmann::json& document) { + const auto http_verb = verb.get_http_method(); + if (!http_verb.has_value()) + { + return; + } + + ds::openapi::add_response_schema( + document, + method, + http_verb.value(), + HTTP_STATUS_OK, + http::headervalues::contenttype::JSON); + }); } else { @@ -443,72 +542,11 @@ namespace ccf } static void add_endpoint_to_api_document( - nlohmann::json& document, - const std::string& path, - RESTVerb verb, - const Endpoint& endpoint) + nlohmann::json& document, const Endpoint& endpoint) { - const auto http_verb = verb.get_http_method(); - if (!http_verb.has_value()) - { - // Non-HTTP (ie WebSockets) endpoints are not documented - return; - } - - // Temporary: All elements get verbose unique names so they can be stored - // in components - const auto verbose_name = fmt::format("{} {}", verb.c_str(), path); - - if (!endpoint.params_schema.empty()) - { - if (http_verb.value() == HTTP_GET || http_verb.value() == HTTP_DELETE) - { - // TODO: Should set these as individual parameters, not reparse - // them here - if (endpoint.params_schema["type"] != "object") - { - throw std::logic_error(fmt::format( - "Unexpected params schema type: {}", - endpoint.params_schema.dump())); - } - - const auto& required_parameters = endpoint.params_schema["required"]; - for (const auto& [name, schema] : - endpoint.params_schema["properties"].items()) - { - auto parameter = nlohmann::json::object(); - parameter["name"] = name; - parameter["in"] = "query"; - parameter["required"] = - required_parameters.find(name) != required_parameters.end(); - parameter["schema"] = ds::openapi::add_schema_to_components( - document, fmt::format("{} param:{}", verbose_name, name), schema); - ds::openapi::add_request_parameter_schema( - document, path, http_verb.value(), parameter); - } - } - else - { - ds::openapi::add_request_body_schema( - document, - path, - http_verb.value(), - http::headervalues::contenttype::JSON, - fmt::format("{} :request", verbose_name), - endpoint.params_schema); - } - } - - if (!endpoint.result_schema.empty()) + for (const auto& builder_fn : endpoint.schema_builders) { - ds::openapi::add_response_schema( - document, - path, - http_verb.value(), - HTTP_STATUS_OK, - http::headervalues::contenttype::JSON, - fmt::format("{} response", verbose_name), - endpoint.result_schema); + builder_fn(document); } } @@ -520,22 +558,21 @@ namespace ccf */ virtual void build_api(nlohmann::json& document, kv::Tx&) { + // TODO: Add common prefix as relative server element + for (const auto& [path, verb_endpoints] : fully_qualified_endpoints) { - const auto full_path = fmt::format("/{}/{}", method_prefix, path); - // auto& path_object = ds::openapi::path(document, full_path); for (const auto& [verb, endpoint] : verb_endpoints) { - add_endpoint_to_api_document(document, full_path, verb, endpoint); + add_endpoint_to_api_document(document, endpoint); } } for (const auto& [path, verb_endpoints] : templated_endpoints) { - const auto full_path = fmt::format("/{}/{}", method_prefix, path); for (const auto& [verb, endpoint] : verb_endpoints) { - add_endpoint_to_api_document(document, full_path, verb, endpoint); + add_endpoint_to_api_document(document, endpoint); // TODO: Document path template args } From f74258d0048054d6b68184aab6c9c1021760b6cf Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Mon, 14 Sep 2020 12:01:06 +0100 Subject: [PATCH 35/53] Compile fixes --- src/ds/openapi.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ds/openapi.h b/src/ds/openapi.h index cad8a72913f..bbd3982cf43 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -242,7 +242,8 @@ namespace ds std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || - std::is_same::value) + std::is_same::value || + std::is_same::value) { ds::json::fill_schema(schema); return add_schema_to_components( @@ -250,7 +251,7 @@ namespace ds } else { - const auto name = ds::json::adl::schema_name(); + const auto name = ds::json::schema_name(); auto& components = access::get_object(document, "components"); auto& schemas = access::get_object(components, "schemas"); @@ -259,8 +260,8 @@ namespace ds if (ib.second) { auto& j = ib.first.value(); - // Use argument-dependent-lookup to call correct functions + // Use argument-dependent-lookup to call correct functions T t; if constexpr (std::is_enum::value) { From 669c1f6724c21398626ab99e2d915c79d5190127 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Tue, 15 Sep 2020 09:14:13 +0100 Subject: [PATCH 36/53] Safe capture --- src/node/rpc/endpoint_registry.h | 50 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index d11c1db8910..8e81c4dab87 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -47,7 +47,6 @@ namespace ccf using CommandEndpointFunction = std::function; - using SchemaBuilderFn = std::function; enum class ForwardingRequired { @@ -77,6 +76,9 @@ namespace ccf size_t failures = 0; }; + struct Endpoint; + using SchemaBuilderFn = std::function; + /** An Endpoint represents a user-defined resource that can be invoked by * authorised users via HTTP requests, over TLS. An Endpoint is accessible * at a specific verb and URI, e.g. POST /app/accounts or GET /app/records. @@ -107,8 +109,8 @@ namespace ccf { params_schema = j; - schema_builders.push_back([this, j](nlohmann::json& document) { - const auto http_verb = verb.get_http_method(); + schema_builders.push_back([](nlohmann::json& document, const Endpoint& endpoint) { + const auto http_verb = endpoint.verb.get_http_method(); if (!http_verb.has_value()) { return; @@ -116,8 +118,8 @@ namespace ccf using namespace ds::openapi; auto& rb = request_body(path_operation( - ds::openapi::path(document, method), http_verb.value())); - schema(media_type(rb, http::headervalues::contenttype::JSON)) = j; + ds::openapi::path(document, endpoint.method), http_verb.value())); + schema(media_type(rb, http::headervalues::contenttype::JSON)) = endpoint.params_schema; }); return *this; @@ -132,10 +134,8 @@ namespace ccf */ Endpoint& set_result_schema(const nlohmann::json& j) { - result_schema = j; - - schema_builders.push_back([this, j](nlohmann::json& document) { - const auto http_verb = verb.get_http_method(); + schema_builders.push_back([j](nlohmann::json& document, const Endpoint& endpoint) { + const auto http_verb = endpoint.verb.get_http_method(); if (!http_verb.has_value()) { return; @@ -143,8 +143,8 @@ namespace ccf using namespace ds::openapi; auto& r = - response(path_operation(ds::openapi::path(document, method), http_verb.value()), HTTP_STATUS_OK); - schema(media_type(r, http::headervalues::contenttype::JSON)) = j; + response(path_operation(ds::openapi::path(document, endpoint.method), http_verb.value()), HTTP_STATUS_OK); + schema(media_type(r, http::headervalues::contenttype::JSON)) = endpoint.result_schema; }); return *this; @@ -170,8 +170,8 @@ namespace ccf { params_schema = ds::json::build_schema(method + "/params"); - schema_builders.push_back([this](nlohmann::json& document) { - const auto http_verb = verb.get_http_method(); + schema_builders.push_back([](nlohmann::json& document, const Endpoint& endpoint) { + const auto http_verb = endpoint.verb.get_http_method(); if (!http_verb.has_value()) { // Non-HTTP (ie WebSockets) endpoints are not documented @@ -183,19 +183,19 @@ namespace ccf { // TODO: Should set these as individual parameters, not reparse // them here - if (params_schema["type"] != "object") + if (endpoint.params_schema["type"] != "object") { throw std::logic_error(fmt::format( "Unexpected params schema type: {}", - params_schema.dump())); + endpoint.params_schema.dump())); } //const auto& required_parameters = params_schema["required"]; for (const auto& [name, schema] : - params_schema["properties"].items()) + endpoint.params_schema["properties"].items()) { // TODO: Revive this somehow? - LOG_FAIL_FMT("Ignoring parameter {} in {}", name, method); + LOG_FAIL_FMT("Ignoring parameter {} in {}", name, endpoint.method); // auto parameter = nlohmann::json::object(); // parameter["name"] = name; @@ -215,7 +215,7 @@ namespace ccf { ds::openapi::add_request_body_schema( document, - method, + endpoint.method, http_verb.value(), http::headervalues::contenttype::JSON); } @@ -228,18 +228,18 @@ namespace ccf if constexpr (!std::is_same_v) { - result_schema = ds::json::build_schema(method + "/result"); - - schema_builders.push_back([this](nlohmann::json& document) { - const auto http_verb = verb.get_http_method(); + schema_builders.push_back([](nlohmann::json& document, const Endpoint& endpoint) { + const auto http_verb = endpoint.verb.get_http_method(); if (!http_verb.has_value()) { return; } + LOG_INFO_FMT("ZZZ Adding response schema for {} {}", endpoint.verb.c_str(), endpoint.method); + ds::openapi::add_response_schema( document, - method, + endpoint.method, http_verb.value(), HTTP_STATUS_OK, http::headervalues::contenttype::JSON); @@ -546,7 +546,7 @@ namespace ccf { for (const auto& builder_fn : endpoint.schema_builders) { - builder_fn(document); + builder_fn(document, endpoint); } } @@ -558,7 +558,7 @@ namespace ccf */ virtual void build_api(nlohmann::json& document, kv::Tx&) { - // TODO: Add common prefix as relative server element + ds::openapi::server(document, fmt::format("/{}", method_prefix)); for (const auto& [path, verb_endpoints] : fully_qualified_endpoints) { From a4dcb9d034edf576d7042979978fa5578d1a1905 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Tue, 15 Sep 2020 09:26:20 +0100 Subject: [PATCH 37/53] Prefix OpenAPI paths --- .../ack/update_state_digest_POST_result.json | 62 - doc/schemas/ack_POST_result.json | 4 - doc/schemas/api/schema_GET_result.json | 16 - doc/schemas/api_GET_result.json | 3 - doc/schemas/app_openapi.json | 783 +++++------- doc/schemas/code_GET_result.json | 30 - doc/schemas/commit_GET_result.json | 20 - doc/schemas/endpoint_metrics_GET_result.json | 40 - doc/schemas/gov_openapi.json | 1096 ++++++----------- .../log/private/admin_only_POST_result.json | 4 - .../log/private/anonymous_POST_result.json | 4 - doc/schemas/log/private_DELETE_result.json | 4 - doc/schemas/log/private_GET_result.json | 12 - doc/schemas/log/private_POST_result.json | 4 - doc/schemas/log/private_WEBSOCKET_result.json | 4 - doc/schemas/log/public_DELETE_result.json | 4 - doc/schemas/log/public_GET_result.json | 12 - doc/schemas/log/public_POST_result.json | 4 - doc/schemas/metrics_GET_result.json | 44 - doc/schemas/network_info_GET_result.json | 39 - doc/schemas/node/ids_GET_result.json | 33 - doc/schemas/node_openapi.json | 672 +++++----- doc/schemas/primary_info_GET_result.json | 28 - .../{proposal_id}/complete_POST_result.json | 30 - .../votes/{member_id}_GET_result.json | 25 - .../{proposal_id}/votes_POST_result.json | 30 - .../{proposal_id}/withdraw_POST_result.json | 30 - .../proposals/{proposal_id}_GET_result.json | 73 -- doc/schemas/proposals_POST_result.json | 30 - doc/schemas/query_POST_result.json | 3 - doc/schemas/quote_GET_result.json | 35 - doc/schemas/quotes_GET_result.json | 35 - doc/schemas/read_POST_result.json | 3 - doc/schemas/receipt/verify_POST_result.json | 12 - doc/schemas/receipt_GET_result.json | 17 - .../recovery_share/submit_POST_result.json | 4 - doc/schemas/recovery_share_GET_result.json | 16 - doc/schemas/state_GET_result.json | 42 - doc/schemas/tx_GET_result.json | 17 - doc/schemas/user_id_GET_result.json | 14 - src/ds/openapi.h | 17 +- 41 files changed, 988 insertions(+), 2367 deletions(-) delete mode 100644 doc/schemas/ack/update_state_digest_POST_result.json delete mode 100644 doc/schemas/ack_POST_result.json delete mode 100644 doc/schemas/api/schema_GET_result.json delete mode 100644 doc/schemas/api_GET_result.json delete mode 100644 doc/schemas/code_GET_result.json delete mode 100644 doc/schemas/commit_GET_result.json delete mode 100644 doc/schemas/endpoint_metrics_GET_result.json delete mode 100644 doc/schemas/log/private/admin_only_POST_result.json delete mode 100644 doc/schemas/log/private/anonymous_POST_result.json delete mode 100644 doc/schemas/log/private_DELETE_result.json delete mode 100644 doc/schemas/log/private_GET_result.json delete mode 100644 doc/schemas/log/private_POST_result.json delete mode 100644 doc/schemas/log/private_WEBSOCKET_result.json delete mode 100644 doc/schemas/log/public_DELETE_result.json delete mode 100644 doc/schemas/log/public_GET_result.json delete mode 100644 doc/schemas/log/public_POST_result.json delete mode 100644 doc/schemas/metrics_GET_result.json delete mode 100644 doc/schemas/network_info_GET_result.json delete mode 100644 doc/schemas/node/ids_GET_result.json delete mode 100644 doc/schemas/primary_info_GET_result.json delete mode 100644 doc/schemas/proposals/{proposal_id}/complete_POST_result.json delete mode 100644 doc/schemas/proposals/{proposal_id}/votes/{member_id}_GET_result.json delete mode 100644 doc/schemas/proposals/{proposal_id}/votes_POST_result.json delete mode 100644 doc/schemas/proposals/{proposal_id}/withdraw_POST_result.json delete mode 100644 doc/schemas/proposals/{proposal_id}_GET_result.json delete mode 100644 doc/schemas/proposals_POST_result.json delete mode 100644 doc/schemas/query_POST_result.json delete mode 100644 doc/schemas/quote_GET_result.json delete mode 100644 doc/schemas/quotes_GET_result.json delete mode 100644 doc/schemas/read_POST_result.json delete mode 100644 doc/schemas/receipt/verify_POST_result.json delete mode 100644 doc/schemas/receipt_GET_result.json delete mode 100644 doc/schemas/recovery_share/submit_POST_result.json delete mode 100644 doc/schemas/recovery_share_GET_result.json delete mode 100644 doc/schemas/state_GET_result.json delete mode 100644 doc/schemas/tx_GET_result.json delete mode 100644 doc/schemas/user_id_GET_result.json diff --git a/doc/schemas/ack/update_state_digest_POST_result.json b/doc/schemas/ack/update_state_digest_POST_result.json deleted file mode 100644 index 1c7ea28845c..00000000000 --- a/doc/schemas/ack/update_state_digest_POST_result.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "properties": { - "signed_req": { - "properties": { - "md": { - "enum": [ - "MBEDTLS_MD_NONE", - "MBEDTLS_MD_SHA1", - "MBEDTLS_MD_SHA256", - "MBEDTLS_MD_SHA384", - "MBEDTLS_MD_SHA512" - ] - }, - "req": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "request_body": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "sig": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "sig", - "req", - "request_body", - "md" - ], - "type": "object" - }, - "state_digest": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "state_digest", - "signed_req" - ], - "title": "ack/update_state_digest/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/ack_POST_result.json b/doc/schemas/ack_POST_result.json deleted file mode 100644 index 7268be8c791..00000000000 --- a/doc/schemas/ack_POST_result.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "ack/result", - "type": "boolean" -} \ No newline at end of file diff --git a/doc/schemas/api/schema_GET_result.json b/doc/schemas/api/schema_GET_result.json deleted file mode 100644 index 000c6590883..00000000000 --- a/doc/schemas/api/schema_GET_result.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "properties": { - "params_schema": { - "type": "object" - }, - "result_schema": { - "type": "object" - } - }, - "required": [ - "params_schema", - "result_schema" - ], - "title": "api/schema/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/api_GET_result.json b/doc/schemas/api_GET_result.json deleted file mode 100644 index 5310a0db464..00000000000 --- a/doc/schemas/api_GET_result.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "api/result" -} \ No newline at end of file diff --git a/doc/schemas/app_openapi.json b/doc/schemas/app_openapi.json index af921f7ac67..7625a268255 100644 --- a/doc/schemas/app_openapi.json +++ b/doc/schemas/app_openapi.json @@ -1,307 +1,227 @@ { "components": { "schemas": { - "DELETE /app/log/private param:id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "DELETE /app/log/private response": { - "title": "log/private/result", - "type": "boolean" - }, - "DELETE /app/log/public param:id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "DELETE /app/log/public response": { - "title": "log/public/result", - "type": "boolean" - }, - "GET /app/api response": { - "title": "api/result" + "CallerInfo": { + "properties": { + "caller_id": { + "$ref": "#/components/schemas/uint64" + } + }, + "required": [ + "caller_id" + ], + "type": "object" }, - "GET /app/api/schema param:method": { - "type": "string" + "CodeStatus": { + "enum": [ + "ACCEPTED", + "RETIRED" + ] }, - "GET /app/api/schema response": { + "EndpointMetrics::Metric": { "properties": { - "params_schema": { - "type": "object" + "calls": { + "$ref": "#/components/schemas/uint64" }, - "result_schema": { - "type": "object" + "errors": { + "$ref": "#/components/schemas/uint64" + }, + "failures": { + "$ref": "#/components/schemas/uint64" } }, "required": [ - "params_schema", - "result_schema" + "calls", + "errors", + "failures" ], - "title": "api/schema/result", "type": "object" }, - "GET /app/code response": { + "EndpointMetrics::Out": { "properties": { - "versions": { - "items": { - "properties": { - "digest": { - "type": "string" - }, - "status": { - "enum": [ - "ACCEPTED", - "RETIRED" - ] - } - }, - "required": [ - "digest", - "status" - ], - "type": "object" - }, - "type": "array" + "metrics": { + "$ref": "#/components/schemas/named_named_EndpointMetrics::Metric" } }, "required": [ - "versions" + "metrics" ], - "title": "code/result", "type": "object" }, - "GET /app/commit response": { + "GetCode::Out": { "properties": { - "seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "versions": { + "$ref": "#/components/schemas/GetCode::Version_array" } }, "required": [ - "view", - "seqno" + "versions" ], - "title": "commit/result", "type": "object" }, - "GET /app/endpoint_metrics response": { + "GetCode::Version": { "properties": { - "metrics": { - "additionalProperties": { - "additionalProperties": { - "properties": { - "calls": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "errors": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "failures": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "calls", - "errors", - "failures" - ], - "type": "object" - }, - "type": "object" - }, - "type": "object" + "digest": { + "$ref": "#/components/schemas/string" + }, + "status": { + "$ref": "#/components/schemas/CodeStatus" } }, "required": [ - "metrics" + "digest", + "status" ], - "title": "endpoint_metrics/result", "type": "object" }, - "GET /app/log/private param:id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "GetCode::Version_array": { + "items": { + "$ref": "#/components/schemas/GetCode::Version" + }, + "type": "array" }, - "GET /app/log/private response": { + "GetCommit::Out": { "properties": { - "msg": { - "type": "string" + "seqno": { + "$ref": "#/components/schemas/int64" + }, + "view": { + "$ref": "#/components/schemas/int64" } }, "required": [ - "msg" + "view", + "seqno" ], - "title": "log/private/result", "type": "object" }, - "GET /app/log/public param:id": { - "type": "number" - }, - "GET /app/log/public response": { + "GetMetrics::HistogramResults": { "properties": { - "msg": { - "type": "string" + "buckets": { + "$ref": "#/components/schemas/json" + }, + "high": { + "$ref": "#/components/schemas/int32" + }, + "low": { + "$ref": "#/components/schemas/int32" + }, + "overflow": { + "$ref": "#/components/schemas/uint64" + }, + "underflow": { + "$ref": "#/components/schemas/uint64" } }, "required": [ - "msg" + "low", + "high", + "overflow", + "underflow", + "buckets" ], - "title": "log/public/result", "type": "object" }, - "GET /app/metrics response": { + "GetMetrics::Out": { "properties": { "histogram": { - "properties": { - "buckets": {}, - "high": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "low": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "overflow": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "underflow": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "low", - "high", - "overflow", - "underflow", - "buckets" - ], - "type": "object" + "$ref": "#/components/schemas/GetMetrics::HistogramResults" }, - "tx_rates": {} + "tx_rates": { + "$ref": "#/components/schemas/json" + } }, "required": [ "histogram", "tx_rates" ], - "title": "metrics/result", "type": "object" }, - "GET /app/network_info response": { + "GetNetworkInfo::NodeInfo": { + "properties": { + "host": { + "$ref": "#/components/schemas/string" + }, + "node_id": { + "$ref": "#/components/schemas/uint64" + }, + "port": { + "$ref": "#/components/schemas/string" + } + }, + "required": [ + "node_id", + "host", + "port" + ], + "type": "object" + }, + "GetNetworkInfo::NodeInfo_array": { + "items": { + "$ref": "#/components/schemas/GetNetworkInfo::NodeInfo" + }, + "type": "array" + }, + "GetNetworkInfo::Out": { "properties": { "nodes": { - "items": { - "properties": { - "host": { - "type": "string" - }, - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "port": { - "type": "string" - } - }, - "required": [ - "node_id", - "host", - "port" - ], - "type": "object" - }, - "type": "array" + "$ref": "#/components/schemas/GetNetworkInfo::NodeInfo_array" }, "primary_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "$ref": "#/components/schemas/uint64" } }, "required": [ "nodes", "primary_id" ], - "title": "network_info/result", "type": "object" }, - "GET /app/node/ids param:host": { - "type": "string" + "GetNodesByRPCAddress::NodeInfo": { + "properties": { + "node_id": { + "$ref": "#/components/schemas/uint64" + }, + "status": { + "$ref": "#/components/schemas/NodeStatus" + } + }, + "required": [ + "node_id", + "status" + ], + "type": "object" }, - "GET /app/node/ids param:port": { - "type": "string" + "GetNodesByRPCAddress::NodeInfo_array": { + "items": { + "$ref": "#/components/schemas/GetNodesByRPCAddress::NodeInfo" + }, + "type": "array" }, - "GET /app/node/ids response": { + "GetNodesByRPCAddress::Out": { "properties": { "nodes": { - "items": { - "properties": { - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "status": { - "enum": [ - "PENDING", - "TRUSTED", - "RETIRED" - ] - } - }, - "required": [ - "node_id", - "status" - ], - "type": "object" - }, - "type": "array" + "$ref": "#/components/schemas/GetNodesByRPCAddress::NodeInfo_array" } }, "required": [ "nodes" ], - "title": "node/ids/result", "type": "object" }, - "GET /app/primary_info response": { + "GetPrimaryInfo::Out": { "properties": { "current_view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "$ref": "#/components/schemas/int64" }, "primary_host": { - "type": "string" + "$ref": "#/components/schemas/string" }, "primary_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "$ref": "#/components/schemas/uint64" }, "primary_port": { - "type": "string" + "$ref": "#/components/schemas/string" } }, "required": [ @@ -310,194 +230,155 @@ "primary_port", "current_view" ], - "title": "primary_info/result", "type": "object" }, - "GET /app/receipt param:commit": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "GET /app/receipt response": { + "GetReceipt::Out": { "properties": { "receipt": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" + "$ref": "#/components/schemas/uint8_array" } }, "required": [ "receipt" ], - "title": "receipt/result", "type": "object" }, - "GET /app/tx param:seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "GET /app/tx param:view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "GET /app/tx response": { + "GetSchema::Out": { "properties": { - "status": { - "enum": [ - "UNKNOWN", - "PENDING", - "COMMITTED", - "INVALID" - ] + "params_schema": { + "$ref": "#/components/schemas/json_schema" + }, + "result_schema": { + "$ref": "#/components/schemas/json_schema" } }, "required": [ - "status" + "params_schema", + "result_schema" ], - "title": "tx/result", "type": "object" }, - "GET /app/user_id param:cert": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "GET /app/user_id response": { + "GetTxStatus::Out": { "properties": { - "caller_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "status": { + "$ref": "#/components/schemas/TxStatus" } }, "required": [ - "caller_id" + "status" ], - "title": "user_id/result", "type": "object" }, - "POST /app/log/private :request": { + "LoggingGet::Out": { "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, "msg": { - "type": "string" + "$ref": "#/components/schemas/string" } }, "required": [ - "id", "msg" ], - "title": "log/private/params", "type": "object" }, - "POST /app/log/private response": { - "title": "log/private/result", - "type": "boolean" - }, - "POST /app/log/private/admin_only :request": { + "LoggingRecord::In": { "properties": { "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "$ref": "#/components/schemas/uint64" }, "msg": { - "type": "string" + "$ref": "#/components/schemas/string" } }, "required": [ "id", "msg" ], - "title": "log/private/admin_only/params", "type": "object" }, - "POST /app/log/private/admin_only response": { - "title": "log/private/admin_only/result", - "type": "boolean" - }, - "POST /app/log/private/anonymous :request": { + "NodeStatus": { + "enum": [ + "PENDING", + "TRUSTED", + "RETIRED" + ] + }, + "TxStatus": { + "enum": [ + "UNKNOWN", + "PENDING", + "COMMITTED", + "INVALID" + ] + }, + "VerifyReceipt::In": { "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "msg": { - "type": "string" + "receipt": { + "$ref": "#/components/schemas/uint8_array" } }, "required": [ - "id", - "msg" + "receipt" ], - "title": "log/private/anonymous/params", "type": "object" }, - "POST /app/log/private/anonymous response": { - "title": "log/private/anonymous/result", - "type": "boolean" - }, - "POST /app/log/public :request": { + "VerifyReceipt::Out": { "properties": { - "id": { - "type": "number" - }, - "msg": { - "type": "string" + "valid": { + "$ref": "#/components/schemas/boolean" } }, "required": [ - "id", - "msg" + "valid" ], - "title": "log/public/params", "type": "object" }, - "POST /app/log/public response": { - "title": "log/public/result", + "boolean": { "type": "boolean" }, - "POST /app/receipt/verify :request": { - "properties": { - "receipt": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } + "int32": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "int64": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "json": null, + "json_schema": { + "type": "object" + }, + "named_EndpointMetrics::Metric": { + "additionalProperties": { + "$ref": "#/components/schemas/EndpointMetrics::Metric" }, - "required": [ - "receipt" - ], - "title": "receipt/verify/params", "type": "object" }, - "POST /app/receipt/verify response": { - "properties": { - "valid": { - "type": "boolean" - } + "named_named_EndpointMetrics::Metric": { + "additionalProperties": { + "$ref": "#/components/schemas/named_EndpointMetrics::Metric" }, - "required": [ - "valid" - ], - "title": "receipt/verify/result", "type": "object" + }, + "string": { + "type": "string" + }, + "uint64": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "uint8": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "uint8_array": { + "items": { + "$ref": "#/components/schemas/uint8" + }, + "type": "array" } } }, @@ -508,14 +389,14 @@ }, "openapi": "3.0.0", "paths": { - "/app/api": { + "api": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /app/api response" + "$ref": "#/components/schemas/json" } } }, @@ -524,24 +405,14 @@ } } }, - "/app/api/schema": { + "api/schema": { "get": { - "parameters": [ - { - "in": "query", - "name": "method", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /app/api/schema param:method" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /app/api/schema response" + "$ref": "#/components/schemas/GetSchema::Out" } } }, @@ -550,14 +421,14 @@ } } }, - "/app/code": { + "code": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /app/code response" + "$ref": "#/components/schemas/GetCode::Out" } } }, @@ -566,14 +437,14 @@ } } }, - "/app/commit": { + "commit": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /app/commit response" + "$ref": "#/components/schemas/GetCommit::Out" } } }, @@ -582,14 +453,14 @@ } } }, - "/app/endpoint_metrics": { + "endpoint_metrics": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /app/endpoint_metrics response" + "$ref": "#/components/schemas/EndpointMetrics::Out" } } }, @@ -598,24 +469,14 @@ } } }, - "/app/log/private": { + "log/private": { "delete": { - "parameters": [ - { - "in": "query", - "name": "id", - "required": false, - "schema": { - "$ref": "#/components/schemas/DELETE /app/log/private param:id" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DELETE /app/log/private response" + "$ref": "#/components/schemas/boolean" } } }, @@ -624,22 +485,12 @@ } }, "get": { - "parameters": [ - { - "in": "query", - "name": "id", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /app/log/private param:id" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /app/log/private response" + "$ref": "#/components/schemas/LoggingGet::Out" } } }, @@ -652,7 +503,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /app/log/private :request" + "$ref": "#/components/schemas/LoggingRecord::In" } } }, @@ -663,7 +514,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /app/log/private response" + "$ref": "#/components/schemas/boolean" } } }, @@ -672,13 +523,13 @@ } } }, - "/app/log/private/admin_only": { + "log/private/admin_only": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /app/log/private/admin_only :request" + "$ref": "#/components/schemas/LoggingRecord::In" } } }, @@ -689,7 +540,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /app/log/private/admin_only response" + "$ref": "#/components/schemas/boolean" } } }, @@ -698,13 +549,13 @@ } } }, - "/app/log/private/anonymous": { + "log/private/anonymous": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /app/log/private/anonymous :request" + "$ref": "#/components/schemas/LoggingRecord::In" } } }, @@ -715,7 +566,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /app/log/private/anonymous response" + "$ref": "#/components/schemas/boolean" } } }, @@ -724,24 +575,14 @@ } } }, - "/app/log/public": { + "log/public": { "delete": { - "parameters": [ - { - "in": "query", - "name": "id", - "required": false, - "schema": { - "$ref": "#/components/schemas/DELETE /app/log/public param:id" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DELETE /app/log/public response" + "$ref": "#/components/schemas/boolean" } } }, @@ -750,23 +591,29 @@ } }, "get": { - "parameters": [ - { - "in": "query", - "name": "id", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /app/log/public param:id" + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "id": { + "type": "number" + } + }, + "required": [ + "id" + ], + "title": "log/public/params", + "type": "object" + } } } - ], + }, "responses": { "200": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/GET /app/log/public response" - } + "schema": null } }, "description": "Default response description" @@ -778,19 +625,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /app/log/public :request" + "properties": { + "id": { + "type": "number" + }, + "msg": { + "type": "string" + } + }, + "required": [ + "id", + "msg" + ], + "title": "log/public/params", + "type": "object" } } - }, - "description": "Auto-generated request body schema" + } }, "responses": { "200": { "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/POST /app/log/public response" - } + "schema": null } }, "description": "Default response description" @@ -798,14 +655,14 @@ } } }, - "/app/metrics": { + "metrics": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /app/metrics response" + "$ref": "#/components/schemas/GetMetrics::Out" } } }, @@ -814,14 +671,14 @@ } } }, - "/app/network_info": { + "network_info": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /app/network_info response" + "$ref": "#/components/schemas/GetNetworkInfo::Out" } } }, @@ -830,32 +687,14 @@ } } }, - "/app/node/ids": { + "node/ids": { "get": { - "parameters": [ - { - "in": "query", - "name": "host", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /app/node/ids param:host" - } - }, - { - "in": "query", - "name": "port", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /app/node/ids param:port" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /app/node/ids response" + "$ref": "#/components/schemas/GetNodesByRPCAddress::Out" } } }, @@ -864,14 +703,14 @@ } } }, - "/app/primary_info": { + "primary_info": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /app/primary_info response" + "$ref": "#/components/schemas/GetPrimaryInfo::Out" } } }, @@ -880,24 +719,14 @@ } } }, - "/app/receipt": { + "receipt": { "get": { - "parameters": [ - { - "in": "query", - "name": "commit", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /app/receipt param:commit" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /app/receipt response" + "$ref": "#/components/schemas/GetReceipt::Out" } } }, @@ -906,13 +735,13 @@ } } }, - "/app/receipt/verify": { + "receipt/verify": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /app/receipt/verify :request" + "$ref": "#/components/schemas/VerifyReceipt::In" } } }, @@ -923,7 +752,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /app/receipt/verify response" + "$ref": "#/components/schemas/VerifyReceipt::Out" } } }, @@ -932,32 +761,14 @@ } } }, - "/app/tx": { + "tx": { "get": { - "parameters": [ - { - "in": "query", - "name": "seqno", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /app/tx param:seqno" - } - }, - { - "in": "query", - "name": "view", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /app/tx param:view" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /app/tx response" + "$ref": "#/components/schemas/GetTxStatus::Out" } } }, @@ -966,24 +777,14 @@ } } }, - "/app/user_id": { + "user_id": { "get": { - "parameters": [ - { - "in": "query", - "name": "cert", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /app/user_id param:cert" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /app/user_id response" + "$ref": "#/components/schemas/CallerInfo" } } }, @@ -993,5 +794,9 @@ } } }, - "servers": [] + "servers": [ + { + "url": "/app" + } + ] } \ No newline at end of file diff --git a/doc/schemas/code_GET_result.json b/doc/schemas/code_GET_result.json deleted file mode 100644 index f667b931693..00000000000 --- a/doc/schemas/code_GET_result.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "properties": { - "versions": { - "items": { - "properties": { - "digest": { - "type": "string" - }, - "status": { - "enum": [ - "ACCEPTED", - "RETIRED" - ] - } - }, - "required": [ - "digest", - "status" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "versions" - ], - "title": "code/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/commit_GET_result.json b/doc/schemas/commit_GET_result.json deleted file mode 100644 index d90ed03a33d..00000000000 --- a/doc/schemas/commit_GET_result.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "properties": { - "seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - } - }, - "required": [ - "view", - "seqno" - ], - "title": "commit/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/endpoint_metrics_GET_result.json b/doc/schemas/endpoint_metrics_GET_result.json deleted file mode 100644 index 3f4d34d79f5..00000000000 --- a/doc/schemas/endpoint_metrics_GET_result.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "properties": { - "metrics": { - "additionalProperties": { - "additionalProperties": { - "properties": { - "calls": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "errors": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "failures": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "calls", - "errors", - "failures" - ], - "type": "object" - }, - "type": "object" - }, - "type": "object" - } - }, - "required": [ - "metrics" - ], - "title": "endpoint_metrics/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/gov_openapi.json b/doc/schemas/gov_openapi.json index 5ddac09ac97..4e3204f18e7 100644 --- a/doc/schemas/gov_openapi.json +++ b/doc/schemas/gov_openapi.json @@ -1,683 +1,363 @@ { "components": { "schemas": { - "GET /gov/api response": { - "title": "api/result" - }, - "GET /gov/api/schema param:method": { - "type": "string" - }, - "GET /gov/api/schema response": { + "CallerInfo": { "properties": { - "params_schema": { - "type": "object" - }, - "result_schema": { - "type": "object" + "caller_id": { + "$ref": "#/components/schemas/uint64" } }, "required": [ - "params_schema", - "result_schema" + "caller_id" ], - "title": "api/schema/result", "type": "object" }, - "GET /gov/code response": { - "properties": { - "versions": { - "items": { - "properties": { - "digest": { - "type": "string" - }, - "status": { - "enum": [ - "ACCEPTED", - "RETIRED" - ] - } - }, - "required": [ - "digest", - "status" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "versions" - ], - "title": "code/result", - "type": "object" + "CodeStatus": { + "enum": [ + "ACCEPTED", + "RETIRED" + ] }, - "GET /gov/commit response": { + "EndpointMetrics::Metric": { "properties": { - "seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "calls": { + "$ref": "#/components/schemas/uint64" }, - "view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "errors": { + "$ref": "#/components/schemas/uint64" + }, + "failures": { + "$ref": "#/components/schemas/uint64" } }, "required": [ - "view", - "seqno" + "calls", + "errors", + "failures" ], - "title": "commit/result", "type": "object" }, - "GET /gov/endpoint_metrics response": { + "EndpointMetrics::Out": { "properties": { "metrics": { - "additionalProperties": { - "additionalProperties": { - "properties": { - "calls": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "errors": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "failures": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "calls", - "errors", - "failures" - ], - "type": "object" - }, - "type": "object" - }, - "type": "object" + "$ref": "#/components/schemas/named_named_EndpointMetrics::Metric" } }, "required": [ "metrics" ], - "title": "endpoint_metrics/result", "type": "object" }, - "GET /gov/metrics response": { + "GetCode::Out": { "properties": { - "histogram": { - "properties": { - "buckets": {}, - "high": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "low": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "overflow": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "underflow": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "low", - "high", - "overflow", - "underflow", - "buckets" - ], - "type": "object" - }, - "tx_rates": {} + "versions": { + "$ref": "#/components/schemas/GetCode::Version_array" + } }, "required": [ - "histogram", - "tx_rates" + "versions" ], - "title": "metrics/result", "type": "object" }, - "GET /gov/network_info response": { + "GetCode::Version": { "properties": { - "nodes": { - "items": { - "properties": { - "host": { - "type": "string" - }, - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "port": { - "type": "string" - } - }, - "required": [ - "node_id", - "host", - "port" - ], - "type": "object" - }, - "type": "array" + "digest": { + "$ref": "#/components/schemas/string" }, - "primary_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "status": { + "$ref": "#/components/schemas/CodeStatus" } }, "required": [ - "nodes", - "primary_id" + "digest", + "status" ], - "title": "network_info/result", "type": "object" }, - "GET /gov/node/ids param:host": { - "type": "string" - }, - "GET /gov/node/ids param:port": { - "type": "string" + "GetCode::Version_array": { + "items": { + "$ref": "#/components/schemas/GetCode::Version" + }, + "type": "array" }, - "GET /gov/node/ids response": { + "GetCommit::Out": { "properties": { - "nodes": { - "items": { - "properties": { - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "status": { - "enum": [ - "PENDING", - "TRUSTED", - "RETIRED" - ] - } - }, - "required": [ - "node_id", - "status" - ], - "type": "object" - }, - "type": "array" + "seqno": { + "$ref": "#/components/schemas/int64" + }, + "view": { + "$ref": "#/components/schemas/int64" } }, "required": [ - "nodes" + "view", + "seqno" ], - "title": "node/ids/result", "type": "object" }, - "GET /gov/primary_info response": { + "GetEncryptedRecoveryShare": { "properties": { - "current_view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "primary_host": { - "type": "string" - }, - "primary_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "encrypted_recovery_share": { + "$ref": "#/components/schemas/string" }, - "primary_port": { - "type": "string" + "nonce": { + "$ref": "#/components/schemas/string" } }, "required": [ - "primary_id", - "primary_host", - "primary_port", - "current_view" + "encrypted_recovery_share", + "nonce" ], - "title": "primary_info/result", "type": "object" }, - "GET /gov/proposals/{proposal_id} response": { + "GetMetrics::HistogramResults": { "properties": { - "parameter": {}, - "proposer": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "buckets": { + "$ref": "#/components/schemas/json" }, - "script": { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" + "high": { + "$ref": "#/components/schemas/int32" }, - "state": { - "enum": [ - "OPEN", - "ACCEPTED", - "WITHDRAWN", - "REJECTED", - "FAILED" - ] + "low": { + "$ref": "#/components/schemas/int32" }, - "votes": { - "items": { - "items": [ - { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" - } - ], - "type": "array" - }, - "type": "array" + "overflow": { + "$ref": "#/components/schemas/uint64" + }, + "underflow": { + "$ref": "#/components/schemas/uint64" } }, "required": [ - "script", - "parameter", - "proposer", - "state", - "votes" + "low", + "high", + "overflow", + "underflow", + "buckets" ], - "title": "proposals/{proposal_id}/result", "type": "object" }, - "GET /gov/proposals/{proposal_id}/votes/{member_id} response": { + "GetMetrics::Out": { "properties": { - "ballot": { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" + "histogram": { + "$ref": "#/components/schemas/GetMetrics::HistogramResults" + }, + "tx_rates": { + "$ref": "#/components/schemas/json" } }, "required": [ - "ballot" + "histogram", + "tx_rates" ], - "title": "proposals/{proposal_id}/votes/{member_id}/result", "type": "object" }, - "GET /gov/receipt param:commit": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "GET /gov/receipt response": { + "GetNetworkInfo::NodeInfo": { "properties": { - "receipt": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" + "host": { + "$ref": "#/components/schemas/string" + }, + "node_id": { + "$ref": "#/components/schemas/uint64" + }, + "port": { + "$ref": "#/components/schemas/string" } }, "required": [ - "receipt" + "node_id", + "host", + "port" ], - "title": "receipt/result", "type": "object" }, - "GET /gov/recovery_share response": { + "GetNetworkInfo::NodeInfo_array": { + "items": { + "$ref": "#/components/schemas/GetNetworkInfo::NodeInfo" + }, + "type": "array" + }, + "GetNetworkInfo::Out": { "properties": { - "encrypted_recovery_share": { - "type": "string" + "nodes": { + "$ref": "#/components/schemas/GetNetworkInfo::NodeInfo_array" }, - "nonce": { - "type": "string" + "primary_id": { + "$ref": "#/components/schemas/uint64" } }, "required": [ - "encrypted_recovery_share", - "nonce" + "nodes", + "primary_id" ], - "title": "recovery_share/result", "type": "object" }, - "GET /gov/tx param:seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "GET /gov/tx param:view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "GET /gov/tx response": { + "GetNodesByRPCAddress::NodeInfo": { "properties": { + "node_id": { + "$ref": "#/components/schemas/uint64" + }, "status": { - "enum": [ - "UNKNOWN", - "PENDING", - "COMMITTED", - "INVALID" - ] + "$ref": "#/components/schemas/NodeStatus" } }, "required": [ + "node_id", "status" ], - "title": "tx/result", "type": "object" }, - "GET /gov/user_id param:cert": { + "GetNodesByRPCAddress::NodeInfo_array": { "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" + "$ref": "#/components/schemas/GetNodesByRPCAddress::NodeInfo" }, "type": "array" }, - "GET /gov/user_id response": { + "GetNodesByRPCAddress::Out": { "properties": { - "caller_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "nodes": { + "$ref": "#/components/schemas/GetNodesByRPCAddress::NodeInfo_array" } }, "required": [ - "caller_id" + "nodes" ], - "title": "user_id/result", "type": "object" }, - "POST /gov/ack :request": { + "GetPrimaryInfo::Out": { "properties": { - "state_digest": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" + "current_view": { + "$ref": "#/components/schemas/int64" + }, + "primary_host": { + "$ref": "#/components/schemas/string" + }, + "primary_id": { + "$ref": "#/components/schemas/uint64" + }, + "primary_port": { + "$ref": "#/components/schemas/string" } }, "required": [ - "state_digest" + "primary_id", + "primary_host", + "primary_port", + "current_view" ], - "title": "ack/params", "type": "object" }, - "POST /gov/ack response": { - "title": "ack/result", - "type": "boolean" + "GetReceipt::Out": { + "properties": { + "receipt": { + "$ref": "#/components/schemas/uint8_array" + } + }, + "required": [ + "receipt" + ], + "type": "object" }, - "POST /gov/ack/update_state_digest response": { + "GetSchema::Out": { "properties": { - "signed_req": { - "properties": { - "md": { - "enum": [ - "MBEDTLS_MD_NONE", - "MBEDTLS_MD_SHA1", - "MBEDTLS_MD_SHA256", - "MBEDTLS_MD_SHA384", - "MBEDTLS_MD_SHA512" - ] - }, - "req": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "request_body": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "sig": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "sig", - "req", - "request_body", - "md" - ], - "type": "object" + "params_schema": { + "$ref": "#/components/schemas/json_schema" }, - "state_digest": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" + "result_schema": { + "$ref": "#/components/schemas/json_schema" } }, "required": [ - "state_digest", - "signed_req" + "params_schema", + "result_schema" ], - "title": "ack/update_state_digest/result", "type": "object" }, - "POST /gov/proposals :request": { + "GetTxStatus::Out": { "properties": { - "ballot": { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" - }, - "parameter": {}, - "script": { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" + "status": { + "$ref": "#/components/schemas/TxStatus" } }, "required": [ - "script" + "status" ], - "title": "proposals/params", "type": "object" }, - "POST /gov/proposals response": { + "KVRead::In": { "properties": { - "proposal_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "key": { + "$ref": "#/components/schemas/json" }, - "proposer_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "state": { - "enum": [ - "OPEN", - "ACCEPTED", - "WITHDRAWN", - "REJECTED", - "FAILED" - ] + "table": { + "$ref": "#/components/schemas/string" } }, "required": [ - "proposal_id", - "proposer_id", - "state" + "table", + "key" ], - "title": "proposals/result", "type": "object" }, - "POST /gov/proposals/{proposal_id}/complete response": { + "MemberAck": { "properties": { - "proposal_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "proposer_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "signed_req": { + "$ref": "#/components/schemas/SignedReq" }, - "state": { - "enum": [ - "OPEN", - "ACCEPTED", - "WITHDRAWN", - "REJECTED", - "FAILED" - ] + "state_digest": { + "$ref": "#/components/schemas/uint8_array" } }, "required": [ - "proposal_id", - "proposer_id", - "state" + "state_digest", + "signed_req" ], - "title": "proposals/{proposal_id}/complete/result", "type": "object" }, - "POST /gov/proposals/{proposal_id}/votes :request": { + "NodeStatus": { + "enum": [ + "PENDING", + "TRUSTED", + "RETIRED" + ] + }, + "Proposal": { "properties": { - "ballot": { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" + "parameter": { + "$ref": "#/components/schemas/json" + }, + "proposer": { + "$ref": "#/components/schemas/uint64" + }, + "script": { + "$ref": "#/components/schemas/Script" + }, + "state": { + "$ref": "#/components/schemas/ProposalState" + }, + "votes": { + "$ref": "#/components/schemas/uint64_to_Script" } }, "required": [ - "ballot" + "script", + "parameter", + "proposer", + "state", + "votes" ], - "title": "proposals/{proposal_id}/votes/params", "type": "object" }, - "POST /gov/proposals/{proposal_id}/votes response": { + "ProposalInfo": { "properties": { "proposal_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "$ref": "#/components/schemas/uint64" }, "proposer_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "$ref": "#/components/schemas/uint64" }, "state": { - "enum": [ - "OPEN", - "ACCEPTED", - "WITHDRAWN", - "REJECTED", - "FAILED" - ] + "$ref": "#/components/schemas/ProposalState" } }, "required": [ @@ -685,112 +365,190 @@ "proposer_id", "state" ], - "title": "proposals/{proposal_id}/votes/result", "type": "object" }, - "POST /gov/proposals/{proposal_id}/withdraw response": { + "ProposalState": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + }, + "Propose::In": { "properties": { - "proposal_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "ballot": { + "$ref": "#/components/schemas/Script" }, - "proposer_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "parameter": { + "$ref": "#/components/schemas/json" }, - "state": { - "enum": [ - "OPEN", - "ACCEPTED", - "WITHDRAWN", - "REJECTED", - "FAILED" - ] + "script": { + "$ref": "#/components/schemas/Script" } }, "required": [ - "proposal_id", - "proposer_id", - "state" + "script" ], - "title": "proposals/{proposal_id}/withdraw/result", "type": "object" }, - "POST /gov/query :request": { + "Script": { "properties": { "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" + "$ref": "#/components/schemas/uint8_array" }, "text": { - "type": "string" + "$ref": "#/components/schemas/string" } }, - "title": "query/params", "type": "object" }, - "POST /gov/query response": { - "title": "query/result" + "SignedReq": { + "properties": { + "md": { + "$ref": "#/components/schemas/mbedtls_md_type_t" + }, + "req": { + "$ref": "#/components/schemas/uint8_array" + }, + "request_body": { + "$ref": "#/components/schemas/uint8_array" + }, + "sig": { + "$ref": "#/components/schemas/uint8_array" + } + }, + "required": [ + "sig", + "req", + "request_body", + "md" + ], + "type": "object" }, - "POST /gov/read :request": { + "StateDigest": { "properties": { - "key": {}, - "table": { - "type": "string" + "state_digest": { + "$ref": "#/components/schemas/uint8_array" } }, "required": [ - "table", - "key" + "state_digest" ], - "title": "read/params", "type": "object" }, - "POST /gov/read response": { - "title": "read/result" + "TxStatus": { + "enum": [ + "UNKNOWN", + "PENDING", + "COMMITTED", + "INVALID" + ] }, - "POST /gov/receipt/verify :request": { + "VerifyReceipt::In": { "properties": { "receipt": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" + "$ref": "#/components/schemas/uint8_array" } }, "required": [ "receipt" ], - "title": "receipt/verify/params", "type": "object" }, - "POST /gov/receipt/verify response": { + "VerifyReceipt::Out": { "properties": { "valid": { - "type": "boolean" + "$ref": "#/components/schemas/boolean" } }, "required": [ "valid" ], - "title": "receipt/verify/result", "type": "object" }, - "POST /gov/recovery_share/submit :request": { - "title": "recovery_share/submit/params", - "type": "string" + "Vote": { + "properties": { + "ballot": { + "$ref": "#/components/schemas/Script" + } + }, + "required": [ + "ballot" + ], + "type": "object" + }, + "boolean": { + "type": "boolean" + }, + "int32": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "int64": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "json": null, + "json_schema": { + "type": "object" + }, + "mbedtls_md_type_t": { + "enum": [ + "MBEDTLS_MD_NONE", + "MBEDTLS_MD_SHA1", + "MBEDTLS_MD_SHA256", + "MBEDTLS_MD_SHA384", + "MBEDTLS_MD_SHA512" + ] + }, + "named_EndpointMetrics::Metric": { + "additionalProperties": { + "$ref": "#/components/schemas/EndpointMetrics::Metric" + }, + "type": "object" }, - "POST /gov/recovery_share/submit response": { - "title": "recovery_share/submit/result", + "named_named_EndpointMetrics::Metric": { + "additionalProperties": { + "$ref": "#/components/schemas/named_EndpointMetrics::Metric" + }, + "type": "object" + }, + "string": { "type": "string" + }, + "uint64": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "uint64_to_Script": { + "items": { + "items": [ + { + "$ref": "#/components/schemas/uint64" + }, + { + "$ref": "#/components/schemas/Script" + } + ], + "type": "array" + }, + "type": "array" + }, + "uint8": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "uint8_array": { + "items": { + "$ref": "#/components/schemas/uint8" + }, + "type": "array" } } }, @@ -801,13 +559,13 @@ }, "openapi": "3.0.0", "paths": { - "/gov/ack": { + "ack": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/ack :request" + "$ref": "#/components/schemas/StateDigest" } } }, @@ -818,7 +576,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/ack response" + "$ref": "#/components/schemas/boolean" } } }, @@ -827,14 +585,14 @@ } } }, - "/gov/ack/update_state_digest": { + "ack/update_state_digest": { "post": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/ack/update_state_digest response" + "$ref": "#/components/schemas/MemberAck" } } }, @@ -843,14 +601,14 @@ } } }, - "/gov/api": { + "api": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /gov/api response" + "$ref": "#/components/schemas/json" } } }, @@ -859,24 +617,14 @@ } } }, - "/gov/api/schema": { + "api/schema": { "get": { - "parameters": [ - { - "in": "query", - "name": "method", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /gov/api/schema param:method" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /gov/api/schema response" + "$ref": "#/components/schemas/GetSchema::Out" } } }, @@ -885,14 +633,14 @@ } } }, - "/gov/code": { + "code": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /gov/code response" + "$ref": "#/components/schemas/GetCode::Out" } } }, @@ -901,14 +649,14 @@ } } }, - "/gov/commit": { + "commit": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /gov/commit response" + "$ref": "#/components/schemas/GetCommit::Out" } } }, @@ -917,14 +665,14 @@ } } }, - "/gov/endpoint_metrics": { + "endpoint_metrics": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /gov/endpoint_metrics response" + "$ref": "#/components/schemas/EndpointMetrics::Out" } } }, @@ -933,14 +681,14 @@ } } }, - "/gov/metrics": { + "metrics": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /gov/metrics response" + "$ref": "#/components/schemas/GetMetrics::Out" } } }, @@ -949,14 +697,14 @@ } } }, - "/gov/network_info": { + "network_info": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /gov/network_info response" + "$ref": "#/components/schemas/GetNetworkInfo::Out" } } }, @@ -965,32 +713,14 @@ } } }, - "/gov/node/ids": { + "node/ids": { "get": { - "parameters": [ - { - "in": "query", - "name": "host", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /gov/node/ids param:host" - } - }, - { - "in": "query", - "name": "port", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /gov/node/ids param:port" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /gov/node/ids response" + "$ref": "#/components/schemas/GetNodesByRPCAddress::Out" } } }, @@ -999,14 +729,14 @@ } } }, - "/gov/primary_info": { + "primary_info": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /gov/primary_info response" + "$ref": "#/components/schemas/GetPrimaryInfo::Out" } } }, @@ -1015,13 +745,13 @@ } } }, - "/gov/proposals": { + "proposals": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/proposals :request" + "$ref": "#/components/schemas/Propose::In" } } }, @@ -1032,7 +762,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/proposals response" + "$ref": "#/components/schemas/ProposalInfo" } } }, @@ -1041,14 +771,14 @@ } } }, - "/gov/proposals/{proposal_id}": { + "proposals/{proposal_id}": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /gov/proposals/{proposal_id} response" + "$ref": "#/components/schemas/Proposal" } } }, @@ -1057,14 +787,14 @@ } } }, - "/gov/proposals/{proposal_id}/complete": { + "proposals/{proposal_id}/complete": { "post": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/proposals/{proposal_id}/complete response" + "$ref": "#/components/schemas/ProposalInfo" } } }, @@ -1073,13 +803,13 @@ } } }, - "/gov/proposals/{proposal_id}/votes": { + "proposals/{proposal_id}/votes": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/proposals/{proposal_id}/votes :request" + "$ref": "#/components/schemas/Vote" } } }, @@ -1090,7 +820,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/proposals/{proposal_id}/votes response" + "$ref": "#/components/schemas/ProposalInfo" } } }, @@ -1099,14 +829,14 @@ } } }, - "/gov/proposals/{proposal_id}/votes/{member_id}": { + "proposals/{proposal_id}/votes/{member_id}": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /gov/proposals/{proposal_id}/votes/{member_id} response" + "$ref": "#/components/schemas/Vote" } } }, @@ -1115,14 +845,14 @@ } } }, - "/gov/proposals/{proposal_id}/withdraw": { + "proposals/{proposal_id}/withdraw": { "post": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/proposals/{proposal_id}/withdraw response" + "$ref": "#/components/schemas/ProposalInfo" } } }, @@ -1131,13 +861,13 @@ } } }, - "/gov/query": { + "query": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/query :request" + "$ref": "#/components/schemas/Script" } } }, @@ -1148,7 +878,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/query response" + "$ref": "#/components/schemas/json" } } }, @@ -1157,13 +887,13 @@ } } }, - "/gov/read": { + "read": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/read :request" + "$ref": "#/components/schemas/KVRead::In" } } }, @@ -1174,7 +904,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/read response" + "$ref": "#/components/schemas/json" } } }, @@ -1183,24 +913,14 @@ } } }, - "/gov/receipt": { + "receipt": { "get": { - "parameters": [ - { - "in": "query", - "name": "commit", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /gov/receipt param:commit" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /gov/receipt response" + "$ref": "#/components/schemas/GetReceipt::Out" } } }, @@ -1209,13 +929,13 @@ } } }, - "/gov/receipt/verify": { + "receipt/verify": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/receipt/verify :request" + "$ref": "#/components/schemas/VerifyReceipt::In" } } }, @@ -1226,7 +946,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/receipt/verify response" + "$ref": "#/components/schemas/VerifyReceipt::Out" } } }, @@ -1235,14 +955,14 @@ } } }, - "/gov/recovery_share": { + "recovery_share": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /gov/recovery_share response" + "$ref": "#/components/schemas/GetEncryptedRecoveryShare" } } }, @@ -1251,13 +971,13 @@ } } }, - "/gov/recovery_share/submit": { + "recovery_share/submit": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/recovery_share/submit :request" + "$ref": "#/components/schemas/string" } } }, @@ -1268,7 +988,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /gov/recovery_share/submit response" + "$ref": "#/components/schemas/string" } } }, @@ -1277,32 +997,14 @@ } } }, - "/gov/tx": { + "tx": { "get": { - "parameters": [ - { - "in": "query", - "name": "seqno", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /gov/tx param:seqno" - } - }, - { - "in": "query", - "name": "view", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /gov/tx param:view" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /gov/tx response" + "$ref": "#/components/schemas/GetTxStatus::Out" } } }, @@ -1311,24 +1013,14 @@ } } }, - "/gov/user_id": { + "user_id": { "get": { - "parameters": [ - { - "in": "query", - "name": "cert", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /gov/user_id param:cert" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /gov/user_id response" + "$ref": "#/components/schemas/CallerInfo" } } }, @@ -1338,5 +1030,9 @@ } } }, - "servers": [] + "servers": [ + { + "url": "/gov" + } + ] } \ No newline at end of file diff --git a/doc/schemas/log/private/admin_only_POST_result.json b/doc/schemas/log/private/admin_only_POST_result.json deleted file mode 100644 index f731d3ec9a6..00000000000 --- a/doc/schemas/log/private/admin_only_POST_result.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "log/private/admin_only/result", - "type": "boolean" -} \ No newline at end of file diff --git a/doc/schemas/log/private/anonymous_POST_result.json b/doc/schemas/log/private/anonymous_POST_result.json deleted file mode 100644 index d78e3311f84..00000000000 --- a/doc/schemas/log/private/anonymous_POST_result.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "log/private/anonymous/result", - "type": "boolean" -} \ No newline at end of file diff --git a/doc/schemas/log/private_DELETE_result.json b/doc/schemas/log/private_DELETE_result.json deleted file mode 100644 index 423e1d35077..00000000000 --- a/doc/schemas/log/private_DELETE_result.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "log/private/result", - "type": "boolean" -} \ No newline at end of file diff --git a/doc/schemas/log/private_GET_result.json b/doc/schemas/log/private_GET_result.json deleted file mode 100644 index 67c8963ac93..00000000000 --- a/doc/schemas/log/private_GET_result.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "properties": { - "msg": { - "type": "string" - } - }, - "required": [ - "msg" - ], - "title": "log/private/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/log/private_POST_result.json b/doc/schemas/log/private_POST_result.json deleted file mode 100644 index 423e1d35077..00000000000 --- a/doc/schemas/log/private_POST_result.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "log/private/result", - "type": "boolean" -} \ No newline at end of file diff --git a/doc/schemas/log/private_WEBSOCKET_result.json b/doc/schemas/log/private_WEBSOCKET_result.json deleted file mode 100644 index 423e1d35077..00000000000 --- a/doc/schemas/log/private_WEBSOCKET_result.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "log/private/result", - "type": "boolean" -} \ No newline at end of file diff --git a/doc/schemas/log/public_DELETE_result.json b/doc/schemas/log/public_DELETE_result.json deleted file mode 100644 index 213d0cb22de..00000000000 --- a/doc/schemas/log/public_DELETE_result.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "log/public/result", - "type": "boolean" -} \ No newline at end of file diff --git a/doc/schemas/log/public_GET_result.json b/doc/schemas/log/public_GET_result.json deleted file mode 100644 index 1f430b8ec83..00000000000 --- a/doc/schemas/log/public_GET_result.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "properties": { - "msg": { - "type": "string" - } - }, - "required": [ - "msg" - ], - "title": "log/public/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/log/public_POST_result.json b/doc/schemas/log/public_POST_result.json deleted file mode 100644 index 213d0cb22de..00000000000 --- a/doc/schemas/log/public_POST_result.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "log/public/result", - "type": "boolean" -} \ No newline at end of file diff --git a/doc/schemas/metrics_GET_result.json b/doc/schemas/metrics_GET_result.json deleted file mode 100644 index 2c5918392dd..00000000000 --- a/doc/schemas/metrics_GET_result.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "properties": { - "histogram": { - "properties": { - "buckets": {}, - "high": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "low": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "overflow": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "underflow": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "low", - "high", - "overflow", - "underflow", - "buckets" - ], - "type": "object" - }, - "tx_rates": {} - }, - "required": [ - "histogram", - "tx_rates" - ], - "title": "metrics/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/network_info_GET_result.json b/doc/schemas/network_info_GET_result.json deleted file mode 100644 index eb2cb3c1902..00000000000 --- a/doc/schemas/network_info_GET_result.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "properties": { - "nodes": { - "items": { - "properties": { - "host": { - "type": "string" - }, - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "port": { - "type": "string" - } - }, - "required": [ - "node_id", - "host", - "port" - ], - "type": "object" - }, - "type": "array" - }, - "primary_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "nodes", - "primary_id" - ], - "title": "network_info/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/node/ids_GET_result.json b/doc/schemas/node/ids_GET_result.json deleted file mode 100644 index de4e8bbb826..00000000000 --- a/doc/schemas/node/ids_GET_result.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "properties": { - "nodes": { - "items": { - "properties": { - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "status": { - "enum": [ - "PENDING", - "TRUSTED", - "RETIRED" - ] - } - }, - "required": [ - "node_id", - "status" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "nodes" - ], - "title": "node/ids/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/node_openapi.json b/doc/schemas/node_openapi.json index 7d7e7929ce4..ef39033cd11 100644 --- a/doc/schemas/node_openapi.json +++ b/doc/schemas/node_openapi.json @@ -1,257 +1,216 @@ { "components": { "schemas": { - "GET /node/api response": { - "title": "api/result" + "CodeStatus": { + "enum": [ + "ACCEPTED", + "RETIRED" + ] }, - "GET /node/api/schema param:method": { - "type": "string" - }, - "GET /node/api/schema response": { + "EndpointMetrics::Metric": { "properties": { - "params_schema": { - "type": "object" + "calls": { + "$ref": "#/components/schemas/uint64" }, - "result_schema": { - "type": "object" + "errors": { + "$ref": "#/components/schemas/uint64" + }, + "failures": { + "$ref": "#/components/schemas/uint64" } }, "required": [ - "params_schema", - "result_schema" + "calls", + "errors", + "failures" ], - "title": "api/schema/result", "type": "object" }, - "GET /node/code response": { + "EndpointMetrics::Out": { + "properties": { + "metrics": { + "$ref": "#/components/schemas/named_named_EndpointMetrics::Metric" + } + }, + "required": [ + "metrics" + ], + "type": "object" + }, + "GetCode::Out": { "properties": { "versions": { - "items": { - "properties": { - "digest": { - "type": "string" - }, - "status": { - "enum": [ - "ACCEPTED", - "RETIRED" - ] - } - }, - "required": [ - "digest", - "status" - ], - "type": "object" - }, - "type": "array" + "$ref": "#/components/schemas/GetCode::Version_array" } }, "required": [ "versions" ], - "title": "code/result", "type": "object" }, - "GET /node/commit response": { + "GetCode::Version": { + "properties": { + "digest": { + "$ref": "#/components/schemas/string" + }, + "status": { + "$ref": "#/components/schemas/CodeStatus" + } + }, + "required": [ + "digest", + "status" + ], + "type": "object" + }, + "GetCode::Version_array": { + "items": { + "$ref": "#/components/schemas/GetCode::Version" + }, + "type": "array" + }, + "GetCommit::Out": { "properties": { "seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "$ref": "#/components/schemas/int64" }, "view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "$ref": "#/components/schemas/int64" } }, "required": [ "view", "seqno" ], - "title": "commit/result", "type": "object" }, - "GET /node/endpoint_metrics response": { + "GetMetrics::HistogramResults": { "properties": { - "metrics": { - "additionalProperties": { - "additionalProperties": { - "properties": { - "calls": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "errors": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "failures": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "calls", - "errors", - "failures" - ], - "type": "object" - }, - "type": "object" - }, - "type": "object" + "buckets": { + "$ref": "#/components/schemas/json" + }, + "high": { + "$ref": "#/components/schemas/int32" + }, + "low": { + "$ref": "#/components/schemas/int32" + }, + "overflow": { + "$ref": "#/components/schemas/uint64" + }, + "underflow": { + "$ref": "#/components/schemas/uint64" } }, "required": [ - "metrics" + "low", + "high", + "overflow", + "underflow", + "buckets" ], - "title": "endpoint_metrics/result", "type": "object" }, - "GET /node/metrics response": { + "GetMetrics::Out": { "properties": { "histogram": { - "properties": { - "buckets": {}, - "high": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "low": { - "maximum": 2147483647, - "minimum": -2147483648, - "type": "integer" - }, - "overflow": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "underflow": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "low", - "high", - "overflow", - "underflow", - "buckets" - ], - "type": "object" + "$ref": "#/components/schemas/GetMetrics::HistogramResults" }, - "tx_rates": {} + "tx_rates": { + "$ref": "#/components/schemas/json" + } }, "required": [ "histogram", "tx_rates" ], - "title": "metrics/result", "type": "object" }, - "GET /node/network_info response": { + "GetNetworkInfo::NodeInfo": { + "properties": { + "host": { + "$ref": "#/components/schemas/string" + }, + "node_id": { + "$ref": "#/components/schemas/uint64" + }, + "port": { + "$ref": "#/components/schemas/string" + } + }, + "required": [ + "node_id", + "host", + "port" + ], + "type": "object" + }, + "GetNetworkInfo::NodeInfo_array": { + "items": { + "$ref": "#/components/schemas/GetNetworkInfo::NodeInfo" + }, + "type": "array" + }, + "GetNetworkInfo::Out": { "properties": { "nodes": { - "items": { - "properties": { - "host": { - "type": "string" - }, - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "port": { - "type": "string" - } - }, - "required": [ - "node_id", - "host", - "port" - ], - "type": "object" - }, - "type": "array" + "$ref": "#/components/schemas/GetNetworkInfo::NodeInfo_array" }, "primary_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "$ref": "#/components/schemas/uint64" } }, "required": [ "nodes", "primary_id" ], - "title": "network_info/result", "type": "object" }, - "GET /node/node/ids param:host": { - "type": "string" + "GetNodesByRPCAddress::NodeInfo": { + "properties": { + "node_id": { + "$ref": "#/components/schemas/uint64" + }, + "status": { + "$ref": "#/components/schemas/NodeStatus" + } + }, + "required": [ + "node_id", + "status" + ], + "type": "object" }, - "GET /node/node/ids param:port": { - "type": "string" + "GetNodesByRPCAddress::NodeInfo_array": { + "items": { + "$ref": "#/components/schemas/GetNodesByRPCAddress::NodeInfo" + }, + "type": "array" }, - "GET /node/node/ids response": { + "GetNodesByRPCAddress::Out": { "properties": { "nodes": { - "items": { - "properties": { - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "status": { - "enum": [ - "PENDING", - "TRUSTED", - "RETIRED" - ] - } - }, - "required": [ - "node_id", - "status" - ], - "type": "object" - }, - "type": "array" + "$ref": "#/components/schemas/GetNodesByRPCAddress::NodeInfo_array" } }, "required": [ "nodes" ], - "title": "node/ids/result", "type": "object" }, - "GET /node/primary_info response": { + "GetPrimaryInfo::Out": { "properties": { "current_view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "$ref": "#/components/schemas/int64" }, "primary_host": { - "type": "string" + "$ref": "#/components/schemas/string" }, "primary_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "$ref": "#/components/schemas/uint64" }, "primary_port": { - "type": "string" + "$ref": "#/components/schemas/string" } }, "required": [ @@ -260,133 +219,88 @@ "primary_port", "current_view" ], - "title": "primary_info/result", "type": "object" }, - "GET /node/quote response": { + "GetQuotes::Out": { "properties": { "quotes": { - "items": { - "properties": { - "error": { - "type": "string" - }, - "mrenclave": { - "type": "string" - }, - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "raw": { - "type": "string" - } - }, - "required": [ - "node_id", - "raw" - ], - "type": "object" - }, - "type": "array" + "$ref": "#/components/schemas/GetQuotes::Quote_array" } }, "required": [ "quotes" ], - "title": "quote/result", "type": "object" }, - "GET /node/quotes response": { + "GetQuotes::Quote": { "properties": { - "quotes": { - "items": { - "properties": { - "error": { - "type": "string" - }, - "mrenclave": { - "type": "string" - }, - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "raw": { - "type": "string" - } - }, - "required": [ - "node_id", - "raw" - ], - "type": "object" - }, - "type": "array" + "error": { + "$ref": "#/components/schemas/string" + }, + "mrenclave": { + "$ref": "#/components/schemas/string" + }, + "node_id": { + "$ref": "#/components/schemas/uint64" + }, + "raw": { + "$ref": "#/components/schemas/string" } }, "required": [ - "quotes" + "node_id", + "raw" ], - "title": "quotes/result", "type": "object" }, - "GET /node/receipt param:commit": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "GetQuotes::Quote_array": { + "items": { + "$ref": "#/components/schemas/GetQuotes::Quote" + }, + "type": "array" }, - "GET /node/receipt response": { + "GetReceipt::Out": { "properties": { "receipt": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" + "$ref": "#/components/schemas/uint8_array" } }, "required": [ "receipt" ], - "title": "receipt/result", "type": "object" }, - "GET /node/state response": { + "GetSchema::Out": { + "properties": { + "params_schema": { + "$ref": "#/components/schemas/json_schema" + }, + "result_schema": { + "$ref": "#/components/schemas/json_schema" + } + }, + "required": [ + "params_schema", + "result_schema" + ], + "type": "object" + }, + "GetState::Out": { "properties": { "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" + "$ref": "#/components/schemas/uint64" }, "last_recovered_seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "$ref": "#/components/schemas/int64" }, "last_signed_seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "$ref": "#/components/schemas/int64" }, "recovery_target_seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" + "$ref": "#/components/schemas/int64" }, "state": { - "enum": [ - "uninitialized", - "initialized", - "pending", - "partOfPublicNetwork", - "partOfNetwork", - "readingPublicLedger", - "readingPrivateLedger" - ] + "$ref": "#/components/schemas/ccf::State" } }, "required": [ @@ -394,64 +308,114 @@ "state", "last_signed_seqno" ], - "title": "state/result", "type": "object" }, - "GET /node/tx param:seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "GET /node/tx param:view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "GET /node/tx response": { + "GetTxStatus::Out": { "properties": { "status": { - "enum": [ - "UNKNOWN", - "PENDING", - "COMMITTED", - "INVALID" - ] + "$ref": "#/components/schemas/TxStatus" } }, "required": [ "status" ], - "title": "tx/result", "type": "object" }, - "POST /node/receipt/verify :request": { + "NodeStatus": { + "enum": [ + "PENDING", + "TRUSTED", + "RETIRED" + ] + }, + "TxStatus": { + "enum": [ + "UNKNOWN", + "PENDING", + "COMMITTED", + "INVALID" + ] + }, + "VerifyReceipt::In": { "properties": { "receipt": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" + "$ref": "#/components/schemas/uint8_array" } }, "required": [ "receipt" ], - "title": "receipt/verify/params", "type": "object" }, - "POST /node/receipt/verify response": { + "VerifyReceipt::Out": { "properties": { "valid": { - "type": "boolean" + "$ref": "#/components/schemas/boolean" } }, "required": [ "valid" ], - "title": "receipt/verify/result", "type": "object" + }, + "boolean": { + "type": "boolean" + }, + "ccf::State": { + "enum": [ + "uninitialized", + "initialized", + "pending", + "partOfPublicNetwork", + "partOfNetwork", + "readingPublicLedger", + "readingPrivateLedger" + ] + }, + "int32": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "int64": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "json": null, + "json_schema": { + "type": "object" + }, + "named_EndpointMetrics::Metric": { + "additionalProperties": { + "$ref": "#/components/schemas/EndpointMetrics::Metric" + }, + "type": "object" + }, + "named_named_EndpointMetrics::Metric": { + "additionalProperties": { + "$ref": "#/components/schemas/named_EndpointMetrics::Metric" + }, + "type": "object" + }, + "string": { + "type": "string" + }, + "uint64": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "uint8": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "uint8_array": { + "items": { + "$ref": "#/components/schemas/uint8" + }, + "type": "array" } } }, @@ -462,14 +426,14 @@ }, "openapi": "3.0.0", "paths": { - "/node/api": { + "api": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /node/api response" + "$ref": "#/components/schemas/json" } } }, @@ -478,24 +442,14 @@ } } }, - "/node/api/schema": { + "api/schema": { "get": { - "parameters": [ - { - "in": "query", - "name": "method", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /node/api/schema param:method" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /node/api/schema response" + "$ref": "#/components/schemas/GetSchema::Out" } } }, @@ -504,14 +458,14 @@ } } }, - "/node/code": { + "code": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /node/code response" + "$ref": "#/components/schemas/GetCode::Out" } } }, @@ -520,14 +474,14 @@ } } }, - "/node/commit": { + "commit": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /node/commit response" + "$ref": "#/components/schemas/GetCommit::Out" } } }, @@ -536,14 +490,14 @@ } } }, - "/node/endpoint_metrics": { + "endpoint_metrics": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /node/endpoint_metrics response" + "$ref": "#/components/schemas/EndpointMetrics::Out" } } }, @@ -552,14 +506,14 @@ } } }, - "/node/metrics": { + "metrics": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /node/metrics response" + "$ref": "#/components/schemas/GetMetrics::Out" } } }, @@ -568,14 +522,14 @@ } } }, - "/node/network_info": { + "network_info": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /node/network_info response" + "$ref": "#/components/schemas/GetNetworkInfo::Out" } } }, @@ -584,32 +538,14 @@ } } }, - "/node/node/ids": { + "node/ids": { "get": { - "parameters": [ - { - "in": "query", - "name": "host", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /node/node/ids param:host" - } - }, - { - "in": "query", - "name": "port", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /node/node/ids param:port" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /node/node/ids response" + "$ref": "#/components/schemas/GetNodesByRPCAddress::Out" } } }, @@ -618,14 +554,14 @@ } } }, - "/node/primary_info": { + "primary_info": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /node/primary_info response" + "$ref": "#/components/schemas/GetPrimaryInfo::Out" } } }, @@ -634,14 +570,14 @@ } } }, - "/node/quote": { + "quote": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /node/quote response" + "$ref": "#/components/schemas/GetQuotes::Out" } } }, @@ -650,14 +586,14 @@ } } }, - "/node/quotes": { + "quotes": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /node/quotes response" + "$ref": "#/components/schemas/GetQuotes::Out" } } }, @@ -666,24 +602,14 @@ } } }, - "/node/receipt": { + "receipt": { "get": { - "parameters": [ - { - "in": "query", - "name": "commit", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /node/receipt param:commit" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /node/receipt response" + "$ref": "#/components/schemas/GetReceipt::Out" } } }, @@ -692,13 +618,13 @@ } } }, - "/node/receipt/verify": { + "receipt/verify": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /node/receipt/verify :request" + "$ref": "#/components/schemas/VerifyReceipt::In" } } }, @@ -709,7 +635,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/POST /node/receipt/verify response" + "$ref": "#/components/schemas/VerifyReceipt::Out" } } }, @@ -718,14 +644,14 @@ } } }, - "/node/state": { + "state": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /node/state response" + "$ref": "#/components/schemas/GetState::Out" } } }, @@ -734,32 +660,14 @@ } } }, - "/node/tx": { + "tx": { "get": { - "parameters": [ - { - "in": "query", - "name": "seqno", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /node/tx param:seqno" - } - }, - { - "in": "query", - "name": "view", - "required": false, - "schema": { - "$ref": "#/components/schemas/GET /node/tx param:view" - } - } - ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GET /node/tx response" + "$ref": "#/components/schemas/GetTxStatus::Out" } } }, @@ -769,5 +677,9 @@ } } }, - "servers": [] + "servers": [ + { + "url": "/node" + } + ] } \ No newline at end of file diff --git a/doc/schemas/primary_info_GET_result.json b/doc/schemas/primary_info_GET_result.json deleted file mode 100644 index 43e11dbb049..00000000000 --- a/doc/schemas/primary_info_GET_result.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "properties": { - "current_view": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "primary_host": { - "type": "string" - }, - "primary_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "primary_port": { - "type": "string" - } - }, - "required": [ - "primary_id", - "primary_host", - "primary_port", - "current_view" - ], - "title": "primary_info/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/complete_POST_result.json b/doc/schemas/proposals/{proposal_id}/complete_POST_result.json deleted file mode 100644 index 6287c75c763..00000000000 --- a/doc/schemas/proposals/{proposal_id}/complete_POST_result.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "properties": { - "proposal_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "proposer_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "state": { - "enum": [ - "OPEN", - "ACCEPTED", - "WITHDRAWN", - "REJECTED", - "FAILED" - ] - } - }, - "required": [ - "proposal_id", - "proposer_id", - "state" - ], - "title": "proposals/{proposal_id}/complete/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/votes/{member_id}_GET_result.json b/doc/schemas/proposals/{proposal_id}/votes/{member_id}_GET_result.json deleted file mode 100644 index 5b970d9f4ef..00000000000 --- a/doc/schemas/proposals/{proposal_id}/votes/{member_id}_GET_result.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "properties": { - "ballot": { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" - } - }, - "required": [ - "ballot" - ], - "title": "proposals/{proposal_id}/votes/{member_id}/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/votes_POST_result.json b/doc/schemas/proposals/{proposal_id}/votes_POST_result.json deleted file mode 100644 index f052c8c35d1..00000000000 --- a/doc/schemas/proposals/{proposal_id}/votes_POST_result.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "properties": { - "proposal_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "proposer_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "state": { - "enum": [ - "OPEN", - "ACCEPTED", - "WITHDRAWN", - "REJECTED", - "FAILED" - ] - } - }, - "required": [ - "proposal_id", - "proposer_id", - "state" - ], - "title": "proposals/{proposal_id}/votes/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/withdraw_POST_result.json b/doc/schemas/proposals/{proposal_id}/withdraw_POST_result.json deleted file mode 100644 index 2a38ef2fff8..00000000000 --- a/doc/schemas/proposals/{proposal_id}/withdraw_POST_result.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "properties": { - "proposal_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "proposer_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "state": { - "enum": [ - "OPEN", - "ACCEPTED", - "WITHDRAWN", - "REJECTED", - "FAILED" - ] - } - }, - "required": [ - "proposal_id", - "proposer_id", - "state" - ], - "title": "proposals/{proposal_id}/withdraw/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}_GET_result.json b/doc/schemas/proposals/{proposal_id}_GET_result.json deleted file mode 100644 index 48d91ddab99..00000000000 --- a/doc/schemas/proposals/{proposal_id}_GET_result.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "properties": { - "parameter": {}, - "proposer": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "script": { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" - }, - "state": { - "enum": [ - "OPEN", - "ACCEPTED", - "WITHDRAWN", - "REJECTED", - "FAILED" - ] - }, - "votes": { - "items": { - "items": [ - { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - { - "properties": { - "bytecode": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - }, - "text": { - "type": "string" - } - }, - "type": "object" - } - ], - "type": "array" - }, - "type": "array" - } - }, - "required": [ - "script", - "parameter", - "proposer", - "state", - "votes" - ], - "title": "proposals/{proposal_id}/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/proposals_POST_result.json b/doc/schemas/proposals_POST_result.json deleted file mode 100644 index f33004c21b5..00000000000 --- a/doc/schemas/proposals_POST_result.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "properties": { - "proposal_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "proposer_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "state": { - "enum": [ - "OPEN", - "ACCEPTED", - "WITHDRAWN", - "REJECTED", - "FAILED" - ] - } - }, - "required": [ - "proposal_id", - "proposer_id", - "state" - ], - "title": "proposals/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/query_POST_result.json b/doc/schemas/query_POST_result.json deleted file mode 100644 index 9bf4e9337d1..00000000000 --- a/doc/schemas/query_POST_result.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "query/result" -} \ No newline at end of file diff --git a/doc/schemas/quote_GET_result.json b/doc/schemas/quote_GET_result.json deleted file mode 100644 index c967cc601d2..00000000000 --- a/doc/schemas/quote_GET_result.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "properties": { - "quotes": { - "items": { - "properties": { - "error": { - "type": "string" - }, - "mrenclave": { - "type": "string" - }, - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "raw": { - "type": "string" - } - }, - "required": [ - "node_id", - "raw" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "quotes" - ], - "title": "quote/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/quotes_GET_result.json b/doc/schemas/quotes_GET_result.json deleted file mode 100644 index 800db184707..00000000000 --- a/doc/schemas/quotes_GET_result.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "properties": { - "quotes": { - "items": { - "properties": { - "error": { - "type": "string" - }, - "mrenclave": { - "type": "string" - }, - "node_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "raw": { - "type": "string" - } - }, - "required": [ - "node_id", - "raw" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "quotes" - ], - "title": "quotes/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/read_POST_result.json b/doc/schemas/read_POST_result.json deleted file mode 100644 index 0229084c09f..00000000000 --- a/doc/schemas/read_POST_result.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "title": "read/result" -} \ No newline at end of file diff --git a/doc/schemas/receipt/verify_POST_result.json b/doc/schemas/receipt/verify_POST_result.json deleted file mode 100644 index 920d7652c68..00000000000 --- a/doc/schemas/receipt/verify_POST_result.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "properties": { - "valid": { - "type": "boolean" - } - }, - "required": [ - "valid" - ], - "title": "receipt/verify/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/receipt_GET_result.json b/doc/schemas/receipt_GET_result.json deleted file mode 100644 index 38eefacaf36..00000000000 --- a/doc/schemas/receipt_GET_result.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "properties": { - "receipt": { - "items": { - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": "array" - } - }, - "required": [ - "receipt" - ], - "title": "receipt/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/recovery_share/submit_POST_result.json b/doc/schemas/recovery_share/submit_POST_result.json deleted file mode 100644 index 8b951e5d9c8..00000000000 --- a/doc/schemas/recovery_share/submit_POST_result.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "recovery_share/submit/result", - "type": "string" -} \ No newline at end of file diff --git a/doc/schemas/recovery_share_GET_result.json b/doc/schemas/recovery_share_GET_result.json deleted file mode 100644 index 82e894be508..00000000000 --- a/doc/schemas/recovery_share_GET_result.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "properties": { - "encrypted_recovery_share": { - "type": "string" - }, - "nonce": { - "type": "string" - } - }, - "required": [ - "encrypted_recovery_share", - "nonce" - ], - "title": "recovery_share/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/state_GET_result.json b/doc/schemas/state_GET_result.json deleted file mode 100644 index 42031ec0696..00000000000 --- a/doc/schemas/state_GET_result.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "properties": { - "id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - }, - "last_recovered_seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "last_signed_seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "recovery_target_seqno": { - "maximum": 9223372036854775807, - "minimum": -9223372036854775808, - "type": "integer" - }, - "state": { - "enum": [ - "uninitialized", - "initialized", - "pending", - "partOfPublicNetwork", - "partOfNetwork", - "readingPublicLedger", - "readingPrivateLedger" - ] - } - }, - "required": [ - "id", - "state", - "last_signed_seqno" - ], - "title": "state/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/tx_GET_result.json b/doc/schemas/tx_GET_result.json deleted file mode 100644 index 068146dc225..00000000000 --- a/doc/schemas/tx_GET_result.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "properties": { - "status": { - "enum": [ - "UNKNOWN", - "PENDING", - "COMMITTED", - "INVALID" - ] - } - }, - "required": [ - "status" - ], - "title": "tx/result", - "type": "object" -} \ No newline at end of file diff --git a/doc/schemas/user_id_GET_result.json b/doc/schemas/user_id_GET_result.json deleted file mode 100644 index 62469fc2e84..00000000000 --- a/doc/schemas/user_id_GET_result.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "properties": { - "caller_id": { - "maximum": 18446744073709551615, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "caller_id" - ], - "title": "user_id/result", - "type": "object" -} \ No newline at end of file diff --git a/src/ds/openapi.h b/src/ds/openapi.h index bbd3982cf43..5ae65ca48a0 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -73,7 +73,12 @@ namespace ds static inline nlohmann::json& path( nlohmann::json& document, const std::string& path) { - check_path_valid(path); + auto p = path; + if (p.find("/") != 0) + { + p = fmt::format("/{}", p); + } + auto& paths = access::get_object(document, "paths"); return access::get_object(paths, path); } @@ -286,8 +291,6 @@ namespace ds const std::string& schema_name, const nlohmann::json& schema_) { - check_path_valid(uri); - auto& rb = request_body(path_operation(path(document, uri), verb)); rb["description"] = "Auto-generated request body schema"; @@ -302,8 +305,6 @@ namespace ds http_method verb, const std::string& content_type) { - check_path_valid(uri); - auto& rb = request_body(path_operation(path(document, uri), verb)); rb["description"] = "Auto-generated request body schema"; @@ -317,8 +318,6 @@ namespace ds http_method verb, const nlohmann::json& param) { - check_path_valid(uri); - auto& params = parameters(path_operation(path(document, uri), verb)); params.push_back(param); } @@ -332,8 +331,6 @@ namespace ds const std::string& schema_name, const nlohmann::json& schema_) { - check_path_valid(uri); - auto& r = response(path_operation(path(document, uri), verb), status); schema(media_type(r, content_type)) = @@ -348,8 +345,6 @@ namespace ds http_status status, const std::string& content_type) { - check_path_valid(uri); - auto& r = response(path_operation(path(document, uri), verb), status); SchemaHelper sh{document}; From 2ee733693f127022a19317f28e47f4078025de23 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Tue, 15 Sep 2020 09:59:50 +0100 Subject: [PATCH 38/53] Get things in-sync --- doc/schemas/app_openapi.json | 134 +++++++++++++++---------------- doc/schemas/gov_openapi.json | 146 +++++++++++++++++----------------- doc/schemas/node_openapi.json | 140 ++++++++++++++++---------------- src/ds/openapi.h | 31 ++++++-- tests/schema.py | 2 +- 5 files changed, 235 insertions(+), 218 deletions(-) diff --git a/doc/schemas/app_openapi.json b/doc/schemas/app_openapi.json index 7625a268255..3091ed8add4 100644 --- a/doc/schemas/app_openapi.json +++ b/doc/schemas/app_openapi.json @@ -18,7 +18,7 @@ "RETIRED" ] }, - "EndpointMetrics::Metric": { + "EndpointMetrics__Metric": { "properties": { "calls": { "$ref": "#/components/schemas/uint64" @@ -37,10 +37,10 @@ ], "type": "object" }, - "EndpointMetrics::Out": { + "EndpointMetrics__Out": { "properties": { "metrics": { - "$ref": "#/components/schemas/named_named_EndpointMetrics::Metric" + "$ref": "#/components/schemas/named_named_EndpointMetrics__Metric" } }, "required": [ @@ -48,10 +48,10 @@ ], "type": "object" }, - "GetCode::Out": { + "GetCode__Out": { "properties": { "versions": { - "$ref": "#/components/schemas/GetCode::Version_array" + "$ref": "#/components/schemas/GetCode__Version_array" } }, "required": [ @@ -59,7 +59,7 @@ ], "type": "object" }, - "GetCode::Version": { + "GetCode__Version": { "properties": { "digest": { "$ref": "#/components/schemas/string" @@ -74,13 +74,13 @@ ], "type": "object" }, - "GetCode::Version_array": { + "GetCode__Version_array": { "items": { - "$ref": "#/components/schemas/GetCode::Version" + "$ref": "#/components/schemas/GetCode__Version" }, "type": "array" }, - "GetCommit::Out": { + "GetCommit__Out": { "properties": { "seqno": { "$ref": "#/components/schemas/int64" @@ -95,7 +95,7 @@ ], "type": "object" }, - "GetMetrics::HistogramResults": { + "GetMetrics__HistogramResults": { "properties": { "buckets": { "$ref": "#/components/schemas/json" @@ -122,10 +122,10 @@ ], "type": "object" }, - "GetMetrics::Out": { + "GetMetrics__Out": { "properties": { "histogram": { - "$ref": "#/components/schemas/GetMetrics::HistogramResults" + "$ref": "#/components/schemas/GetMetrics__HistogramResults" }, "tx_rates": { "$ref": "#/components/schemas/json" @@ -137,7 +137,7 @@ ], "type": "object" }, - "GetNetworkInfo::NodeInfo": { + "GetNetworkInfo__NodeInfo": { "properties": { "host": { "$ref": "#/components/schemas/string" @@ -156,16 +156,16 @@ ], "type": "object" }, - "GetNetworkInfo::NodeInfo_array": { + "GetNetworkInfo__NodeInfo_array": { "items": { - "$ref": "#/components/schemas/GetNetworkInfo::NodeInfo" + "$ref": "#/components/schemas/GetNetworkInfo__NodeInfo" }, "type": "array" }, - "GetNetworkInfo::Out": { + "GetNetworkInfo__Out": { "properties": { "nodes": { - "$ref": "#/components/schemas/GetNetworkInfo::NodeInfo_array" + "$ref": "#/components/schemas/GetNetworkInfo__NodeInfo_array" }, "primary_id": { "$ref": "#/components/schemas/uint64" @@ -177,7 +177,7 @@ ], "type": "object" }, - "GetNodesByRPCAddress::NodeInfo": { + "GetNodesByRPCAddress__NodeInfo": { "properties": { "node_id": { "$ref": "#/components/schemas/uint64" @@ -192,16 +192,16 @@ ], "type": "object" }, - "GetNodesByRPCAddress::NodeInfo_array": { + "GetNodesByRPCAddress__NodeInfo_array": { "items": { - "$ref": "#/components/schemas/GetNodesByRPCAddress::NodeInfo" + "$ref": "#/components/schemas/GetNodesByRPCAddress__NodeInfo" }, "type": "array" }, - "GetNodesByRPCAddress::Out": { + "GetNodesByRPCAddress__Out": { "properties": { "nodes": { - "$ref": "#/components/schemas/GetNodesByRPCAddress::NodeInfo_array" + "$ref": "#/components/schemas/GetNodesByRPCAddress__NodeInfo_array" } }, "required": [ @@ -209,7 +209,7 @@ ], "type": "object" }, - "GetPrimaryInfo::Out": { + "GetPrimaryInfo__Out": { "properties": { "current_view": { "$ref": "#/components/schemas/int64" @@ -232,7 +232,7 @@ ], "type": "object" }, - "GetReceipt::Out": { + "GetReceipt__Out": { "properties": { "receipt": { "$ref": "#/components/schemas/uint8_array" @@ -243,7 +243,7 @@ ], "type": "object" }, - "GetSchema::Out": { + "GetSchema__Out": { "properties": { "params_schema": { "$ref": "#/components/schemas/json_schema" @@ -258,7 +258,7 @@ ], "type": "object" }, - "GetTxStatus::Out": { + "GetTxStatus__Out": { "properties": { "status": { "$ref": "#/components/schemas/TxStatus" @@ -269,7 +269,7 @@ ], "type": "object" }, - "LoggingGet::Out": { + "LoggingGet__Out": { "properties": { "msg": { "$ref": "#/components/schemas/string" @@ -280,7 +280,7 @@ ], "type": "object" }, - "LoggingRecord::In": { + "LoggingRecord__In": { "properties": { "id": { "$ref": "#/components/schemas/uint64" @@ -310,7 +310,7 @@ "INVALID" ] }, - "VerifyReceipt::In": { + "VerifyReceipt__In": { "properties": { "receipt": { "$ref": "#/components/schemas/uint8_array" @@ -321,7 +321,7 @@ ], "type": "object" }, - "VerifyReceipt::Out": { + "VerifyReceipt__Out": { "properties": { "valid": { "$ref": "#/components/schemas/boolean" @@ -349,15 +349,15 @@ "json_schema": { "type": "object" }, - "named_EndpointMetrics::Metric": { + "named_EndpointMetrics__Metric": { "additionalProperties": { - "$ref": "#/components/schemas/EndpointMetrics::Metric" + "$ref": "#/components/schemas/EndpointMetrics__Metric" }, "type": "object" }, - "named_named_EndpointMetrics::Metric": { + "named_named_EndpointMetrics__Metric": { "additionalProperties": { - "$ref": "#/components/schemas/named_EndpointMetrics::Metric" + "$ref": "#/components/schemas/named_EndpointMetrics__Metric" }, "type": "object" }, @@ -389,7 +389,7 @@ }, "openapi": "3.0.0", "paths": { - "api": { + "/api": { "get": { "responses": { "200": { @@ -405,14 +405,14 @@ } } }, - "api/schema": { + "/api/schema": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetSchema::Out" + "$ref": "#/components/schemas/GetSchema__Out" } } }, @@ -421,14 +421,14 @@ } } }, - "code": { + "/code": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetCode::Out" + "$ref": "#/components/schemas/GetCode__Out" } } }, @@ -437,14 +437,14 @@ } } }, - "commit": { + "/commit": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetCommit::Out" + "$ref": "#/components/schemas/GetCommit__Out" } } }, @@ -453,14 +453,14 @@ } } }, - "endpoint_metrics": { + "/endpoint_metrics": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EndpointMetrics::Out" + "$ref": "#/components/schemas/EndpointMetrics__Out" } } }, @@ -469,7 +469,7 @@ } } }, - "log/private": { + "/log/private": { "delete": { "responses": { "200": { @@ -490,7 +490,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LoggingGet::Out" + "$ref": "#/components/schemas/LoggingGet__Out" } } }, @@ -503,7 +503,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LoggingRecord::In" + "$ref": "#/components/schemas/LoggingRecord__In" } } }, @@ -523,13 +523,13 @@ } } }, - "log/private/admin_only": { + "/log/private/admin_only": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LoggingRecord::In" + "$ref": "#/components/schemas/LoggingRecord__In" } } }, @@ -549,13 +549,13 @@ } } }, - "log/private/anonymous": { + "/log/private/anonymous": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LoggingRecord::In" + "$ref": "#/components/schemas/LoggingRecord__In" } } }, @@ -575,7 +575,7 @@ } } }, - "log/public": { + "/log/public": { "delete": { "responses": { "200": { @@ -655,14 +655,14 @@ } } }, - "metrics": { + "/metrics": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetMetrics::Out" + "$ref": "#/components/schemas/GetMetrics__Out" } } }, @@ -671,14 +671,14 @@ } } }, - "network_info": { + "/network_info": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetNetworkInfo::Out" + "$ref": "#/components/schemas/GetNetworkInfo__Out" } } }, @@ -687,14 +687,14 @@ } } }, - "node/ids": { + "/node/ids": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetNodesByRPCAddress::Out" + "$ref": "#/components/schemas/GetNodesByRPCAddress__Out" } } }, @@ -703,14 +703,14 @@ } } }, - "primary_info": { + "/primary_info": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetPrimaryInfo::Out" + "$ref": "#/components/schemas/GetPrimaryInfo__Out" } } }, @@ -719,14 +719,14 @@ } } }, - "receipt": { + "/receipt": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetReceipt::Out" + "$ref": "#/components/schemas/GetReceipt__Out" } } }, @@ -735,13 +735,13 @@ } } }, - "receipt/verify": { + "/receipt/verify": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VerifyReceipt::In" + "$ref": "#/components/schemas/VerifyReceipt__In" } } }, @@ -752,7 +752,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VerifyReceipt::Out" + "$ref": "#/components/schemas/VerifyReceipt__Out" } } }, @@ -761,14 +761,14 @@ } } }, - "tx": { + "/tx": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetTxStatus::Out" + "$ref": "#/components/schemas/GetTxStatus__Out" } } }, @@ -777,7 +777,7 @@ } } }, - "user_id": { + "/user_id": { "get": { "responses": { "200": { diff --git a/doc/schemas/gov_openapi.json b/doc/schemas/gov_openapi.json index 4e3204f18e7..1b990fd81a9 100644 --- a/doc/schemas/gov_openapi.json +++ b/doc/schemas/gov_openapi.json @@ -18,7 +18,7 @@ "RETIRED" ] }, - "EndpointMetrics::Metric": { + "EndpointMetrics__Metric": { "properties": { "calls": { "$ref": "#/components/schemas/uint64" @@ -37,10 +37,10 @@ ], "type": "object" }, - "EndpointMetrics::Out": { + "EndpointMetrics__Out": { "properties": { "metrics": { - "$ref": "#/components/schemas/named_named_EndpointMetrics::Metric" + "$ref": "#/components/schemas/named_named_EndpointMetrics__Metric" } }, "required": [ @@ -48,10 +48,10 @@ ], "type": "object" }, - "GetCode::Out": { + "GetCode__Out": { "properties": { "versions": { - "$ref": "#/components/schemas/GetCode::Version_array" + "$ref": "#/components/schemas/GetCode__Version_array" } }, "required": [ @@ -59,7 +59,7 @@ ], "type": "object" }, - "GetCode::Version": { + "GetCode__Version": { "properties": { "digest": { "$ref": "#/components/schemas/string" @@ -74,13 +74,13 @@ ], "type": "object" }, - "GetCode::Version_array": { + "GetCode__Version_array": { "items": { - "$ref": "#/components/schemas/GetCode::Version" + "$ref": "#/components/schemas/GetCode__Version" }, "type": "array" }, - "GetCommit::Out": { + "GetCommit__Out": { "properties": { "seqno": { "$ref": "#/components/schemas/int64" @@ -110,7 +110,7 @@ ], "type": "object" }, - "GetMetrics::HistogramResults": { + "GetMetrics__HistogramResults": { "properties": { "buckets": { "$ref": "#/components/schemas/json" @@ -137,10 +137,10 @@ ], "type": "object" }, - "GetMetrics::Out": { + "GetMetrics__Out": { "properties": { "histogram": { - "$ref": "#/components/schemas/GetMetrics::HistogramResults" + "$ref": "#/components/schemas/GetMetrics__HistogramResults" }, "tx_rates": { "$ref": "#/components/schemas/json" @@ -152,7 +152,7 @@ ], "type": "object" }, - "GetNetworkInfo::NodeInfo": { + "GetNetworkInfo__NodeInfo": { "properties": { "host": { "$ref": "#/components/schemas/string" @@ -171,16 +171,16 @@ ], "type": "object" }, - "GetNetworkInfo::NodeInfo_array": { + "GetNetworkInfo__NodeInfo_array": { "items": { - "$ref": "#/components/schemas/GetNetworkInfo::NodeInfo" + "$ref": "#/components/schemas/GetNetworkInfo__NodeInfo" }, "type": "array" }, - "GetNetworkInfo::Out": { + "GetNetworkInfo__Out": { "properties": { "nodes": { - "$ref": "#/components/schemas/GetNetworkInfo::NodeInfo_array" + "$ref": "#/components/schemas/GetNetworkInfo__NodeInfo_array" }, "primary_id": { "$ref": "#/components/schemas/uint64" @@ -192,7 +192,7 @@ ], "type": "object" }, - "GetNodesByRPCAddress::NodeInfo": { + "GetNodesByRPCAddress__NodeInfo": { "properties": { "node_id": { "$ref": "#/components/schemas/uint64" @@ -207,16 +207,16 @@ ], "type": "object" }, - "GetNodesByRPCAddress::NodeInfo_array": { + "GetNodesByRPCAddress__NodeInfo_array": { "items": { - "$ref": "#/components/schemas/GetNodesByRPCAddress::NodeInfo" + "$ref": "#/components/schemas/GetNodesByRPCAddress__NodeInfo" }, "type": "array" }, - "GetNodesByRPCAddress::Out": { + "GetNodesByRPCAddress__Out": { "properties": { "nodes": { - "$ref": "#/components/schemas/GetNodesByRPCAddress::NodeInfo_array" + "$ref": "#/components/schemas/GetNodesByRPCAddress__NodeInfo_array" } }, "required": [ @@ -224,7 +224,7 @@ ], "type": "object" }, - "GetPrimaryInfo::Out": { + "GetPrimaryInfo__Out": { "properties": { "current_view": { "$ref": "#/components/schemas/int64" @@ -247,7 +247,7 @@ ], "type": "object" }, - "GetReceipt::Out": { + "GetReceipt__Out": { "properties": { "receipt": { "$ref": "#/components/schemas/uint8_array" @@ -258,7 +258,7 @@ ], "type": "object" }, - "GetSchema::Out": { + "GetSchema__Out": { "properties": { "params_schema": { "$ref": "#/components/schemas/json_schema" @@ -273,7 +273,7 @@ ], "type": "object" }, - "GetTxStatus::Out": { + "GetTxStatus__Out": { "properties": { "status": { "$ref": "#/components/schemas/TxStatus" @@ -284,7 +284,7 @@ ], "type": "object" }, - "KVRead::In": { + "KVRead__In": { "properties": { "key": { "$ref": "#/components/schemas/json" @@ -376,7 +376,7 @@ "FAILED" ] }, - "Propose::In": { + "Propose__In": { "properties": { "ballot": { "$ref": "#/components/schemas/Script" @@ -446,7 +446,7 @@ "INVALID" ] }, - "VerifyReceipt::In": { + "VerifyReceipt__In": { "properties": { "receipt": { "$ref": "#/components/schemas/uint8_array" @@ -457,7 +457,7 @@ ], "type": "object" }, - "VerifyReceipt::Out": { + "VerifyReceipt__Out": { "properties": { "valid": { "$ref": "#/components/schemas/boolean" @@ -505,15 +505,15 @@ "MBEDTLS_MD_SHA512" ] }, - "named_EndpointMetrics::Metric": { + "named_EndpointMetrics__Metric": { "additionalProperties": { - "$ref": "#/components/schemas/EndpointMetrics::Metric" + "$ref": "#/components/schemas/EndpointMetrics__Metric" }, "type": "object" }, - "named_named_EndpointMetrics::Metric": { + "named_named_EndpointMetrics__Metric": { "additionalProperties": { - "$ref": "#/components/schemas/named_EndpointMetrics::Metric" + "$ref": "#/components/schemas/named_EndpointMetrics__Metric" }, "type": "object" }, @@ -559,7 +559,7 @@ }, "openapi": "3.0.0", "paths": { - "ack": { + "/ack": { "post": { "requestBody": { "content": { @@ -585,7 +585,7 @@ } } }, - "ack/update_state_digest": { + "/ack/update_state_digest": { "post": { "responses": { "200": { @@ -601,7 +601,7 @@ } } }, - "api": { + "/api": { "get": { "responses": { "200": { @@ -617,14 +617,14 @@ } } }, - "api/schema": { + "/api/schema": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetSchema::Out" + "$ref": "#/components/schemas/GetSchema__Out" } } }, @@ -633,14 +633,14 @@ } } }, - "code": { + "/code": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetCode::Out" + "$ref": "#/components/schemas/GetCode__Out" } } }, @@ -649,14 +649,14 @@ } } }, - "commit": { + "/commit": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetCommit::Out" + "$ref": "#/components/schemas/GetCommit__Out" } } }, @@ -665,14 +665,14 @@ } } }, - "endpoint_metrics": { + "/endpoint_metrics": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EndpointMetrics::Out" + "$ref": "#/components/schemas/EndpointMetrics__Out" } } }, @@ -681,14 +681,14 @@ } } }, - "metrics": { + "/metrics": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetMetrics::Out" + "$ref": "#/components/schemas/GetMetrics__Out" } } }, @@ -697,14 +697,14 @@ } } }, - "network_info": { + "/network_info": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetNetworkInfo::Out" + "$ref": "#/components/schemas/GetNetworkInfo__Out" } } }, @@ -713,14 +713,14 @@ } } }, - "node/ids": { + "/node/ids": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetNodesByRPCAddress::Out" + "$ref": "#/components/schemas/GetNodesByRPCAddress__Out" } } }, @@ -729,14 +729,14 @@ } } }, - "primary_info": { + "/primary_info": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetPrimaryInfo::Out" + "$ref": "#/components/schemas/GetPrimaryInfo__Out" } } }, @@ -745,13 +745,13 @@ } } }, - "proposals": { + "/proposals": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Propose::In" + "$ref": "#/components/schemas/Propose__In" } } }, @@ -771,7 +771,7 @@ } } }, - "proposals/{proposal_id}": { + "/proposals/{proposal_id}": { "get": { "responses": { "200": { @@ -787,7 +787,7 @@ } } }, - "proposals/{proposal_id}/complete": { + "/proposals/{proposal_id}/complete": { "post": { "responses": { "200": { @@ -803,7 +803,7 @@ } } }, - "proposals/{proposal_id}/votes": { + "/proposals/{proposal_id}/votes": { "post": { "requestBody": { "content": { @@ -829,7 +829,7 @@ } } }, - "proposals/{proposal_id}/votes/{member_id}": { + "/proposals/{proposal_id}/votes/{member_id}": { "get": { "responses": { "200": { @@ -845,7 +845,7 @@ } } }, - "proposals/{proposal_id}/withdraw": { + "/proposals/{proposal_id}/withdraw": { "post": { "responses": { "200": { @@ -861,7 +861,7 @@ } } }, - "query": { + "/query": { "post": { "requestBody": { "content": { @@ -887,13 +887,13 @@ } } }, - "read": { + "/read": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/KVRead::In" + "$ref": "#/components/schemas/KVRead__In" } } }, @@ -913,14 +913,14 @@ } } }, - "receipt": { + "/receipt": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetReceipt::Out" + "$ref": "#/components/schemas/GetReceipt__Out" } } }, @@ -929,13 +929,13 @@ } } }, - "receipt/verify": { + "/receipt/verify": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VerifyReceipt::In" + "$ref": "#/components/schemas/VerifyReceipt__In" } } }, @@ -946,7 +946,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VerifyReceipt::Out" + "$ref": "#/components/schemas/VerifyReceipt__Out" } } }, @@ -955,7 +955,7 @@ } } }, - "recovery_share": { + "/recovery_share": { "get": { "responses": { "200": { @@ -971,7 +971,7 @@ } } }, - "recovery_share/submit": { + "/recovery_share/submit": { "post": { "requestBody": { "content": { @@ -997,14 +997,14 @@ } } }, - "tx": { + "/tx": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetTxStatus::Out" + "$ref": "#/components/schemas/GetTxStatus__Out" } } }, @@ -1013,7 +1013,7 @@ } } }, - "user_id": { + "/user_id": { "get": { "responses": { "200": { diff --git a/doc/schemas/node_openapi.json b/doc/schemas/node_openapi.json index ef39033cd11..9928d84fcc8 100644 --- a/doc/schemas/node_openapi.json +++ b/doc/schemas/node_openapi.json @@ -7,7 +7,7 @@ "RETIRED" ] }, - "EndpointMetrics::Metric": { + "EndpointMetrics__Metric": { "properties": { "calls": { "$ref": "#/components/schemas/uint64" @@ -26,10 +26,10 @@ ], "type": "object" }, - "EndpointMetrics::Out": { + "EndpointMetrics__Out": { "properties": { "metrics": { - "$ref": "#/components/schemas/named_named_EndpointMetrics::Metric" + "$ref": "#/components/schemas/named_named_EndpointMetrics__Metric" } }, "required": [ @@ -37,10 +37,10 @@ ], "type": "object" }, - "GetCode::Out": { + "GetCode__Out": { "properties": { "versions": { - "$ref": "#/components/schemas/GetCode::Version_array" + "$ref": "#/components/schemas/GetCode__Version_array" } }, "required": [ @@ -48,7 +48,7 @@ ], "type": "object" }, - "GetCode::Version": { + "GetCode__Version": { "properties": { "digest": { "$ref": "#/components/schemas/string" @@ -63,13 +63,13 @@ ], "type": "object" }, - "GetCode::Version_array": { + "GetCode__Version_array": { "items": { - "$ref": "#/components/schemas/GetCode::Version" + "$ref": "#/components/schemas/GetCode__Version" }, "type": "array" }, - "GetCommit::Out": { + "GetCommit__Out": { "properties": { "seqno": { "$ref": "#/components/schemas/int64" @@ -84,7 +84,7 @@ ], "type": "object" }, - "GetMetrics::HistogramResults": { + "GetMetrics__HistogramResults": { "properties": { "buckets": { "$ref": "#/components/schemas/json" @@ -111,10 +111,10 @@ ], "type": "object" }, - "GetMetrics::Out": { + "GetMetrics__Out": { "properties": { "histogram": { - "$ref": "#/components/schemas/GetMetrics::HistogramResults" + "$ref": "#/components/schemas/GetMetrics__HistogramResults" }, "tx_rates": { "$ref": "#/components/schemas/json" @@ -126,7 +126,7 @@ ], "type": "object" }, - "GetNetworkInfo::NodeInfo": { + "GetNetworkInfo__NodeInfo": { "properties": { "host": { "$ref": "#/components/schemas/string" @@ -145,16 +145,16 @@ ], "type": "object" }, - "GetNetworkInfo::NodeInfo_array": { + "GetNetworkInfo__NodeInfo_array": { "items": { - "$ref": "#/components/schemas/GetNetworkInfo::NodeInfo" + "$ref": "#/components/schemas/GetNetworkInfo__NodeInfo" }, "type": "array" }, - "GetNetworkInfo::Out": { + "GetNetworkInfo__Out": { "properties": { "nodes": { - "$ref": "#/components/schemas/GetNetworkInfo::NodeInfo_array" + "$ref": "#/components/schemas/GetNetworkInfo__NodeInfo_array" }, "primary_id": { "$ref": "#/components/schemas/uint64" @@ -166,7 +166,7 @@ ], "type": "object" }, - "GetNodesByRPCAddress::NodeInfo": { + "GetNodesByRPCAddress__NodeInfo": { "properties": { "node_id": { "$ref": "#/components/schemas/uint64" @@ -181,16 +181,16 @@ ], "type": "object" }, - "GetNodesByRPCAddress::NodeInfo_array": { + "GetNodesByRPCAddress__NodeInfo_array": { "items": { - "$ref": "#/components/schemas/GetNodesByRPCAddress::NodeInfo" + "$ref": "#/components/schemas/GetNodesByRPCAddress__NodeInfo" }, "type": "array" }, - "GetNodesByRPCAddress::Out": { + "GetNodesByRPCAddress__Out": { "properties": { "nodes": { - "$ref": "#/components/schemas/GetNodesByRPCAddress::NodeInfo_array" + "$ref": "#/components/schemas/GetNodesByRPCAddress__NodeInfo_array" } }, "required": [ @@ -198,7 +198,7 @@ ], "type": "object" }, - "GetPrimaryInfo::Out": { + "GetPrimaryInfo__Out": { "properties": { "current_view": { "$ref": "#/components/schemas/int64" @@ -221,10 +221,10 @@ ], "type": "object" }, - "GetQuotes::Out": { + "GetQuotes__Out": { "properties": { "quotes": { - "$ref": "#/components/schemas/GetQuotes::Quote_array" + "$ref": "#/components/schemas/GetQuotes__Quote_array" } }, "required": [ @@ -232,7 +232,7 @@ ], "type": "object" }, - "GetQuotes::Quote": { + "GetQuotes__Quote": { "properties": { "error": { "$ref": "#/components/schemas/string" @@ -253,13 +253,13 @@ ], "type": "object" }, - "GetQuotes::Quote_array": { + "GetQuotes__Quote_array": { "items": { - "$ref": "#/components/schemas/GetQuotes::Quote" + "$ref": "#/components/schemas/GetQuotes__Quote" }, "type": "array" }, - "GetReceipt::Out": { + "GetReceipt__Out": { "properties": { "receipt": { "$ref": "#/components/schemas/uint8_array" @@ -270,7 +270,7 @@ ], "type": "object" }, - "GetSchema::Out": { + "GetSchema__Out": { "properties": { "params_schema": { "$ref": "#/components/schemas/json_schema" @@ -285,7 +285,7 @@ ], "type": "object" }, - "GetState::Out": { + "GetState__Out": { "properties": { "id": { "$ref": "#/components/schemas/uint64" @@ -300,7 +300,7 @@ "$ref": "#/components/schemas/int64" }, "state": { - "$ref": "#/components/schemas/ccf::State" + "$ref": "#/components/schemas/ccf__State" } }, "required": [ @@ -310,7 +310,7 @@ ], "type": "object" }, - "GetTxStatus::Out": { + "GetTxStatus__Out": { "properties": { "status": { "$ref": "#/components/schemas/TxStatus" @@ -336,7 +336,7 @@ "INVALID" ] }, - "VerifyReceipt::In": { + "VerifyReceipt__In": { "properties": { "receipt": { "$ref": "#/components/schemas/uint8_array" @@ -347,7 +347,7 @@ ], "type": "object" }, - "VerifyReceipt::Out": { + "VerifyReceipt__Out": { "properties": { "valid": { "$ref": "#/components/schemas/boolean" @@ -361,7 +361,7 @@ "boolean": { "type": "boolean" }, - "ccf::State": { + "ccf__State": { "enum": [ "uninitialized", "initialized", @@ -386,15 +386,15 @@ "json_schema": { "type": "object" }, - "named_EndpointMetrics::Metric": { + "named_EndpointMetrics__Metric": { "additionalProperties": { - "$ref": "#/components/schemas/EndpointMetrics::Metric" + "$ref": "#/components/schemas/EndpointMetrics__Metric" }, "type": "object" }, - "named_named_EndpointMetrics::Metric": { + "named_named_EndpointMetrics__Metric": { "additionalProperties": { - "$ref": "#/components/schemas/named_EndpointMetrics::Metric" + "$ref": "#/components/schemas/named_EndpointMetrics__Metric" }, "type": "object" }, @@ -426,7 +426,7 @@ }, "openapi": "3.0.0", "paths": { - "api": { + "/api": { "get": { "responses": { "200": { @@ -442,14 +442,14 @@ } } }, - "api/schema": { + "/api/schema": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetSchema::Out" + "$ref": "#/components/schemas/GetSchema__Out" } } }, @@ -458,14 +458,14 @@ } } }, - "code": { + "/code": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetCode::Out" + "$ref": "#/components/schemas/GetCode__Out" } } }, @@ -474,14 +474,14 @@ } } }, - "commit": { + "/commit": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetCommit::Out" + "$ref": "#/components/schemas/GetCommit__Out" } } }, @@ -490,14 +490,14 @@ } } }, - "endpoint_metrics": { + "/endpoint_metrics": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EndpointMetrics::Out" + "$ref": "#/components/schemas/EndpointMetrics__Out" } } }, @@ -506,14 +506,14 @@ } } }, - "metrics": { + "/metrics": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetMetrics::Out" + "$ref": "#/components/schemas/GetMetrics__Out" } } }, @@ -522,14 +522,14 @@ } } }, - "network_info": { + "/network_info": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetNetworkInfo::Out" + "$ref": "#/components/schemas/GetNetworkInfo__Out" } } }, @@ -538,14 +538,14 @@ } } }, - "node/ids": { + "/node/ids": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetNodesByRPCAddress::Out" + "$ref": "#/components/schemas/GetNodesByRPCAddress__Out" } } }, @@ -554,14 +554,14 @@ } } }, - "primary_info": { + "/primary_info": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetPrimaryInfo::Out" + "$ref": "#/components/schemas/GetPrimaryInfo__Out" } } }, @@ -570,14 +570,14 @@ } } }, - "quote": { + "/quote": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetQuotes::Out" + "$ref": "#/components/schemas/GetQuotes__Out" } } }, @@ -586,14 +586,14 @@ } } }, - "quotes": { + "/quotes": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetQuotes::Out" + "$ref": "#/components/schemas/GetQuotes__Out" } } }, @@ -602,14 +602,14 @@ } } }, - "receipt": { + "/receipt": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetReceipt::Out" + "$ref": "#/components/schemas/GetReceipt__Out" } } }, @@ -618,13 +618,13 @@ } } }, - "receipt/verify": { + "/receipt/verify": { "post": { "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VerifyReceipt::In" + "$ref": "#/components/schemas/VerifyReceipt__In" } } }, @@ -635,7 +635,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VerifyReceipt::Out" + "$ref": "#/components/schemas/VerifyReceipt__Out" } } }, @@ -644,14 +644,14 @@ } } }, - "state": { + "/state": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetState::Out" + "$ref": "#/components/schemas/GetState__Out" } } }, @@ -660,14 +660,14 @@ } } }, - "tx": { + "/tx": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetTxStatus::Out" + "$ref": "#/components/schemas/GetTxStatus__Out" } } }, diff --git a/src/ds/openapi.h b/src/ds/openapi.h index 5ae65ca48a0..57fe3383afa 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -48,6 +48,21 @@ namespace ds } } + static inline std::string remove_invalid_chars(const std::string_view& s_) + { + std::string s(s_); + + for (auto& c : s) + { + if (c == ':') + { + c = '_'; + } + } + + return s; + } + static inline nlohmann::json create_document( const std::string& title, const std::string& description, @@ -73,14 +88,14 @@ namespace ds static inline nlohmann::json& path( nlohmann::json& document, const std::string& path) { - auto p = path; + auto p = remove_invalid_chars(path); if (p.find("/") != 0) { p = fmt::format("/{}", p); } auto& paths = access::get_object(document, "paths"); - return access::get_object(paths, path); + return access::get_object(paths, p); } static inline nlohmann::json& path_operation( @@ -149,10 +164,12 @@ namespace ds const std::string& element_name, const nlohmann::json& schema_) { + const auto name = remove_invalid_chars(element_name); + auto& components = access::get_object(document, "components"); auto& schemas = access::get_object(components, "schemas"); - const auto schema_it = schemas.find(element_name); + const auto schema_it = schemas.find(name); if (schema_it != schemas.end()) { // Check that the existing schema matches the new one being added with @@ -163,17 +180,17 @@ namespace ds throw std::logic_error(fmt::format( "Adding schema with name '{}'. Does not match previous schema " "registered with this name: {} vs {}", - element_name, + name, schema_.dump(), existing_schema.dump())); } } else { - schemas.emplace(element_name, schema_); + schemas.emplace(name, schema_); } - return components_ref_object(element_name); + return components_ref_object(name); } struct SchemaHelper @@ -256,7 +273,7 @@ namespace ds } else { - const auto name = ds::json::schema_name(); + const auto name = remove_invalid_chars(ds::json::schema_name()); auto& components = access::get_object(document, "components"); auto& schemas = access::get_object(components, "schemas"); diff --git a/tests/schema.py b/tests/schema.py index e14453106dd..016cc087d3b 100644 --- a/tests/schema.py +++ b/tests/schema.py @@ -47,7 +47,7 @@ def fetch_schema(client, prefix): # Fetch the schema of each method for method, _ in paths.items(): schema_found = False - expected_method_prefix = f"/{prefix}/" + expected_method_prefix = "/" if method.startswith(expected_method_prefix): method = method[len(expected_method_prefix):] schema_response = client.get(f'/{prefix}/api/schema?method="{method}"') From 6cdeab96a889f82a2b9baa98e0b7f4fd3c1746ca Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Tue, 15 Sep 2020 13:19:46 +0100 Subject: [PATCH 39/53] Progress --- doc/schemas/app_openapi.json | 2 +- doc/schemas/gov_openapi.json | 2 +- doc/schemas/node_openapi.json | 2 +- src/ds/json_schema.h | 1 + src/ds/openapi.h | 12 ++++++++++-- src/node/rpc/endpoint_registry.h | 2 -- tests/schema.py | 13 +++++++++---- 7 files changed, 23 insertions(+), 11 deletions(-) diff --git a/doc/schemas/app_openapi.json b/doc/schemas/app_openapi.json index 3091ed8add4..e3d41c22710 100644 --- a/doc/schemas/app_openapi.json +++ b/doc/schemas/app_openapi.json @@ -345,7 +345,7 @@ "minimum": -9223372036854775808, "type": "integer" }, - "json": null, + "json": {}, "json_schema": { "type": "object" }, diff --git a/doc/schemas/gov_openapi.json b/doc/schemas/gov_openapi.json index 1b990fd81a9..455c11f7cb2 100644 --- a/doc/schemas/gov_openapi.json +++ b/doc/schemas/gov_openapi.json @@ -492,7 +492,7 @@ "minimum": -9223372036854775808, "type": "integer" }, - "json": null, + "json": {}, "json_schema": { "type": "object" }, diff --git a/doc/schemas/node_openapi.json b/doc/schemas/node_openapi.json index 9928d84fcc8..247b91612a7 100644 --- a/doc/schemas/node_openapi.json +++ b/doc/schemas/node_openapi.json @@ -382,7 +382,7 @@ "minimum": -9223372036854775808, "type": "integer" }, - "json": null, + "json": {}, "json_schema": { "type": "object" }, diff --git a/src/ds/json_schema.h b/src/ds/json_schema.h index 85e5e9ad5d5..7a3045dd2be 100644 --- a/src/ds/json_schema.h +++ b/src/ds/json_schema.h @@ -243,6 +243,7 @@ namespace ds { // Any field that contains more json is completely unconstrained, so we // do not add a type or any other fields + schema = nlohmann::json::object(); } else if constexpr (std::is_integral::value) { diff --git a/src/ds/openapi.h b/src/ds/openapi.h index 57fe3383afa..b1cc7b670d8 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -326,7 +326,11 @@ namespace ds rb["description"] = "Auto-generated request body schema"; SchemaHelper sh{document}; - schema(media_type(rb, content_type)) = sh.add_schema_component(); + const auto schema_comp = sh.add_schema_component(); + if (schema_comp != nullptr) + { + schema(media_type(rb, content_type)) = sh.add_schema_component(); + } } static inline void add_request_parameter_schema( @@ -365,7 +369,11 @@ namespace ds auto& r = response(path_operation(path(document, uri), verb), status); SchemaHelper sh{document}; - schema(media_type(r, content_type)) = sh.add_schema_component(); + const auto schema_comp = sh.add_schema_component(); + if (schema_comp != nullptr) + { + schema(media_type(r, content_type)) = sh.add_schema_component(); + } } } } diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index 8e81c4dab87..bfcf87b5628 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -235,8 +235,6 @@ namespace ccf return; } - LOG_INFO_FMT("ZZZ Adding response schema for {} {}", endpoint.verb.c_str(), endpoint.method); - ds::openapi::add_response_schema( document, endpoint.method, diff --git a/tests/schema.py b/tests/schema.py index 016cc087d3b..16f2f4bdbcb 100644 --- a/tests/schema.py +++ b/tests/schema.py @@ -118,7 +118,9 @@ def fetch_schema(client, prefix): except Exception as e: LOG.error(f"Validation of {prefix} schema failed") LOG.error(e) - documents_valid = False + return False + + return True with infra.network.network( hosts, args.binary_dir, args.debug_nodes, args.perf_nodes @@ -130,15 +132,18 @@ def fetch_schema(client, prefix): with primary.client("user0") as user_client: LOG.info("user frontend") - fetch_schema(user_client, "app") + if not fetch_schema(user_client, "app"): + documents_valid = False with primary.client() as node_client: LOG.info("node frontend") - fetch_schema(node_client, "node") + if not fetch_schema(node_client, "node"): + documents_valid = False with primary.client("member0") as member_client: LOG.info("member frontend") - fetch_schema(member_client, "gov") + if not fetch_schema(member_client, "gov"): + documents_valid = False made_changes = False From ddf38bd99052acbe9a38acd8fc0937469b6450e2 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Tue, 15 Sep 2020 15:05:29 +0100 Subject: [PATCH 40/53] Split out params on all endpoints --- doc/schemas/app_openapi.json | 159 ++++++++++++++++++++---- doc/schemas/gov_openapi.json | 139 ++++++++++++++++++++- doc/schemas/node_openapi.json | 62 +++++++++ src/ds/openapi.h | 9 ++ src/node/rpc/endpoint_registry.h | 207 ++++++++++++++++++------------- 5 files changed, 465 insertions(+), 111 deletions(-) diff --git a/doc/schemas/app_openapi.json b/doc/schemas/app_openapi.json index e3d41c22710..1f387b7e5ee 100644 --- a/doc/schemas/app_openapi.json +++ b/doc/schemas/app_openapi.json @@ -407,6 +407,16 @@ }, "/api/schema": { "get": { + "parameters": [ + { + "in": "query", + "name": "method", + "required": false, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "content": { @@ -471,6 +481,18 @@ }, "/log/private": { "delete": { + "parameters": [ + { + "in": "query", + "name": "id", + "required": false, + "schema": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + } + ], "responses": { "200": { "content": { @@ -485,6 +507,18 @@ } }, "get": { + "parameters": [ + { + "in": "query", + "name": "id", + "required": false, + "schema": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + } + ], "responses": { "200": { "content": { @@ -575,8 +609,32 @@ } } }, + "/log/private/raw_text/{id}": { + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ] + }, "/log/public": { "delete": { + "parameters": [ + { + "in": "query", + "name": "id", + "required": false, + "schema": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + } + ], "responses": { "200": { "content": { @@ -591,31 +649,18 @@ } }, "get": { - "requestBody": { - "content": { - "application/json": { - "schema": { - "properties": { - "id": { - "type": "number" - } - }, - "required": [ - "id" - ], - "title": "log/public/params", - "type": "object" - } + "parameters": [ + { + "in": "query", + "name": "id", + "required": false, + "schema": { + "type": "number" } } - }, + ], "responses": { "200": { - "content": { - "application/json": { - "schema": null - } - }, "description": "Default response description" } } @@ -645,11 +690,6 @@ }, "responses": { "200": { - "content": { - "application/json": { - "schema": null - } - }, "description": "Default response description" } } @@ -689,6 +729,24 @@ }, "/node/ids": { "get": { + "parameters": [ + { + "in": "query", + "name": "host", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "port", + "required": false, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "content": { @@ -721,6 +779,18 @@ }, "/receipt": { "get": { + "parameters": [ + { + "in": "query", + "name": "commit", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + } + ], "responses": { "200": { "content": { @@ -763,6 +833,28 @@ }, "/tx": { "get": { + "parameters": [ + { + "in": "query", + "name": "seqno", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + { + "in": "query", + "name": "view", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + } + ], "responses": { "200": { "content": { @@ -779,6 +871,21 @@ }, "/user_id": { "get": { + "parameters": [ + { + "in": "query", + "name": "cert", + "required": false, + "schema": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + } + ], "responses": { "200": { "content": { diff --git a/doc/schemas/gov_openapi.json b/doc/schemas/gov_openapi.json index 455c11f7cb2..25a07ae7e1e 100644 --- a/doc/schemas/gov_openapi.json +++ b/doc/schemas/gov_openapi.json @@ -619,6 +619,16 @@ }, "/api/schema": { "get": { + "parameters": [ + { + "in": "query", + "name": "method", + "required": false, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "content": { @@ -715,6 +725,24 @@ }, "/node/ids": { "get": { + "parameters": [ + { + "in": "query", + "name": "host", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "port", + "required": false, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "content": { @@ -785,9 +813,29 @@ "description": "Default response description" } } - } + }, + "parameters": [ + { + "in": "path", + "name": "proposal_id", + "required": true, + "schema": { + "type": "string" + } + } + ] }, "/proposals/{proposal_id}/complete": { + "parameters": [ + { + "in": "path", + "name": "proposal_id", + "required": true, + "schema": { + "type": "string" + } + } + ], "post": { "responses": { "200": { @@ -804,6 +852,16 @@ } }, "/proposals/{proposal_id}/votes": { + "parameters": [ + { + "in": "path", + "name": "proposal_id", + "required": true, + "schema": { + "type": "string" + } + } + ], "post": { "requestBody": { "content": { @@ -843,9 +901,37 @@ "description": "Default response description" } } - } + }, + "parameters": [ + { + "in": "path", + "name": "proposal_id", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "member_id", + "required": true, + "schema": { + "type": "string" + } + } + ] }, "/proposals/{proposal_id}/withdraw": { + "parameters": [ + { + "in": "path", + "name": "proposal_id", + "required": true, + "schema": { + "type": "string" + } + } + ], "post": { "responses": { "200": { @@ -915,6 +1001,18 @@ }, "/receipt": { "get": { + "parameters": [ + { + "in": "query", + "name": "commit", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + } + ], "responses": { "200": { "content": { @@ -999,6 +1097,28 @@ }, "/tx": { "get": { + "parameters": [ + { + "in": "query", + "name": "seqno", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + { + "in": "query", + "name": "view", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + } + ], "responses": { "200": { "content": { @@ -1015,6 +1135,21 @@ }, "/user_id": { "get": { + "parameters": [ + { + "in": "query", + "name": "cert", + "required": false, + "schema": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + } + ], "responses": { "200": { "content": { diff --git a/doc/schemas/node_openapi.json b/doc/schemas/node_openapi.json index 247b91612a7..4b180a79dfb 100644 --- a/doc/schemas/node_openapi.json +++ b/doc/schemas/node_openapi.json @@ -444,6 +444,16 @@ }, "/api/schema": { "get": { + "parameters": [ + { + "in": "query", + "name": "method", + "required": false, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "content": { @@ -540,6 +550,24 @@ }, "/node/ids": { "get": { + "parameters": [ + { + "in": "query", + "name": "host", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "port", + "required": false, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "content": { @@ -604,6 +632,18 @@ }, "/receipt": { "get": { + "parameters": [ + { + "in": "query", + "name": "commit", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + } + ], "responses": { "200": { "content": { @@ -662,6 +702,28 @@ }, "/tx": { "get": { + "parameters": [ + { + "in": "query", + "name": "seqno", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + { + "in": "query", + "name": "view", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + } + ], "responses": { "200": { "content": { diff --git a/src/ds/openapi.h b/src/ds/openapi.h index b1cc7b670d8..aa91c893ecf 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -333,6 +333,15 @@ namespace ds } } + static inline void add_path_parameter_schema( + nlohmann::json& document, + const std::string& uri, + const nlohmann::json& param) + { + auto& params = parameters(path(document, uri)); + params.push_back(param); + } + static inline void add_request_parameter_schema( nlohmann::json& document, const std::string& uri, diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index bfcf87b5628..4a3c62c5c33 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -47,7 +47,6 @@ namespace ccf using CommandEndpointFunction = std::function; - enum class ForwardingRequired { Sometimes, @@ -77,7 +76,8 @@ namespace ccf }; struct Endpoint; - using SchemaBuilderFn = std::function; + using SchemaBuilderFn = + std::function; /** An Endpoint represents a user-defined resource that can be invoked by * authorised users via HTTP requests, over TLS. An Endpoint is accessible @@ -109,18 +109,34 @@ namespace ccf { params_schema = j; - schema_builders.push_back([](nlohmann::json& document, const Endpoint& endpoint) { - const auto http_verb = endpoint.verb.get_http_method(); - if (!http_verb.has_value()) - { - return; - } + schema_builders.push_back( + [](nlohmann::json& document, const Endpoint& endpoint) { + const auto http_verb = endpoint.verb.get_http_method(); + if (!http_verb.has_value()) + { + return; + } + + using namespace ds::openapi; - using namespace ds::openapi; - auto& rb = request_body(path_operation( - ds::openapi::path(document, endpoint.method), http_verb.value())); - schema(media_type(rb, http::headervalues::contenttype::JSON)) = endpoint.params_schema; - }); + if ( + http_verb.value() == HTTP_GET || + http_verb.value() == HTTP_DELETE) + { + add_query_parameters( + document, + endpoint.method, + endpoint.params_schema, + http_verb.value()); + } + else + { + auto& rb = request_body(path_operation( + ds::openapi::path(document, endpoint.method), http_verb.value())); + schema(media_type(rb, http::headervalues::contenttype::JSON)) = + endpoint.params_schema; + } + }); return *this; } @@ -134,18 +150,27 @@ namespace ccf */ Endpoint& set_result_schema(const nlohmann::json& j) { - schema_builders.push_back([j](nlohmann::json& document, const Endpoint& endpoint) { - const auto http_verb = endpoint.verb.get_http_method(); - if (!http_verb.has_value()) - { - return; - } + schema_builders.push_back( + [j](nlohmann::json& document, const Endpoint& endpoint) { + const auto http_verb = endpoint.verb.get_http_method(); + if (!http_verb.has_value()) + { + return; + } - using namespace ds::openapi; - auto& r = - response(path_operation(ds::openapi::path(document, endpoint.method), http_verb.value()), HTTP_STATUS_OK); - schema(media_type(r, http::headervalues::contenttype::JSON)) = endpoint.result_schema; - }); + using namespace ds::openapi; + auto& r = response( + path_operation( + ds::openapi::path(document, endpoint.method), + http_verb.value()), + HTTP_STATUS_OK); + + if (endpoint.result_schema != nullptr) + { + schema(media_type(r, http::headervalues::contenttype::JSON)) = + endpoint.result_schema; + } + }); return *this; } @@ -170,56 +195,34 @@ namespace ccf { params_schema = ds::json::build_schema(method + "/params"); - schema_builders.push_back([](nlohmann::json& document, const Endpoint& endpoint) { - const auto http_verb = endpoint.verb.get_http_method(); - if (!http_verb.has_value()) - { - // Non-HTTP (ie WebSockets) endpoints are not documented - return; - } - - if ( - http_verb.value() == HTTP_GET || http_verb.value() == HTTP_DELETE) - { - // TODO: Should set these as individual parameters, not reparse - // them here - if (endpoint.params_schema["type"] != "object") + schema_builders.push_back( + [](nlohmann::json& document, const Endpoint& endpoint) { + const auto http_verb = endpoint.verb.get_http_method(); + if (!http_verb.has_value()) { - throw std::logic_error(fmt::format( - "Unexpected params schema type: {}", - endpoint.params_schema.dump())); + // Non-HTTP (ie WebSockets) endpoints are not documented + return; } - //const auto& required_parameters = params_schema["required"]; - for (const auto& [name, schema] : - endpoint.params_schema["properties"].items()) + if ( + http_verb.value() == HTTP_GET || + http_verb.value() == HTTP_DELETE) { - // TODO: Revive this somehow? - LOG_FAIL_FMT("Ignoring parameter {} in {}", name, endpoint.method); - - // auto parameter = nlohmann::json::object(); - // parameter["name"] = name; - // parameter["in"] = "query"; - // parameter["required"] = - // required_parameters.find(name) != - // required_parameters.end(); - // parameter["schema"] = ds::openapi::add_schema_to_components( - // document, - // fmt::format("{} param:{}", verbose_name, name), - // schema); - // ds::openapi::add_request_parameter_schema( - // document, path, http_verb.value(), parameter); + add_query_parameters( + document, + endpoint.method, + endpoint.params_schema, + http_verb.value()); } - } - else - { - ds::openapi::add_request_body_schema( - document, - endpoint.method, - http_verb.value(), - http::headervalues::contenttype::JSON); - } - }); + else + { + ds::openapi::add_request_body_schema( + document, + endpoint.method, + http_verb.value(), + http::headervalues::contenttype::JSON); + } + }); } else { @@ -228,20 +231,21 @@ namespace ccf if constexpr (!std::is_same_v) { - schema_builders.push_back([](nlohmann::json& document, const Endpoint& endpoint) { - const auto http_verb = endpoint.verb.get_http_method(); - if (!http_verb.has_value()) - { - return; - } + schema_builders.push_back( + [](nlohmann::json& document, const Endpoint& endpoint) { + const auto http_verb = endpoint.verb.get_http_method(); + if (!http_verb.has_value()) + { + return; + } - ds::openapi::add_response_schema( - document, - endpoint.method, - http_verb.value(), - HTTP_STATUS_OK, - http::headervalues::contenttype::JSON); - }); + ds::openapi::add_response_schema( + document, + endpoint.method, + http_verb.value(), + HTTP_STATUS_OK, + http::headervalues::contenttype::JSON); + }); } else { @@ -428,6 +432,34 @@ namespace ccf return templated; } + // TODO: Don't re-parse this here, set the parameters explicitly and + // individually + static void add_query_parameters( + nlohmann::json& document, + const std::string& uri, + const nlohmann::json& schema, + http_method verb) + { + if (schema["type"] != "object") + { + throw std::logic_error( + fmt::format("Unexpected params schema type: {}", schema.dump())); + } + + const auto& required_parameters = schema["required"]; + for (const auto& [name, schema] : schema["properties"].items()) + { + auto parameter = nlohmann::json::object(); + parameter["name"] = name; + parameter["in"] = "query"; + parameter["required"] = + required_parameters.find(name) != required_parameters.end(); + parameter["schema"] = schema; + ds::openapi::add_request_parameter_schema( + document, uri, verb, parameter); + } + } + public: EndpointRegistry( const std::string& method_prefix_, @@ -572,7 +604,16 @@ namespace ccf { add_endpoint_to_api_document(document, endpoint); - // TODO: Document path template args + for (const auto& name : endpoint.template_component_names) + { + auto parameter = nlohmann::json::object(); + parameter["name"] = name; + parameter["in"] = "path"; + parameter["required"] = true; + parameter["schema"] = {{"type", "string"}}; + ds::openapi::add_path_parameter_schema( + document, endpoint.method, parameter); + } } } } From 57c214a43a2dd648357d6aa82cdf1638e395c839 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Tue, 15 Sep 2020 18:05:33 +0100 Subject: [PATCH 41/53] Format --- CMakeLists.txt | 8 ++-- scripts/ci-checks.sh | 2 +- src/ds/nonstd.h | 3 +- src/node/rpc/common_endpoint_registry.h | 3 +- src/node/rpc/endpoint_registry.h | 51 ++++++++++++------------- tests/schema.py | 2 +- 6 files changed, 36 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f68beab0d0a..0ba7f15a419 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -315,10 +315,10 @@ if(BUILD_TESTS) ) target_include_directories(history_test PRIVATE ${EVERCRYPT_INC}) target_link_libraries( - history_test PRIVATE ${CRYPTO_LIBRARY} evercrypt.host secp256k1.host http_parser.host + history_test PRIVATE ${CRYPTO_LIBRARY} evercrypt.host secp256k1.host + http_parser.host ) - add_unit_test( secret_sharing_test ${CMAKE_CURRENT_SOURCE_DIR}/src/node/test/secret_share.cpp @@ -336,7 +336,9 @@ if(BUILD_TESTS) historical_queries_test ${CMAKE_CURRENT_SOURCE_DIR}/src/node/test/historical_queries.cpp ) - target_link_libraries(historical_queries_test PRIVATE secp256k1.host http_parser.host) + target_link_libraries( + historical_queries_test PRIVATE secp256k1.host http_parser.host + ) add_unit_test( snapshot_test ${CMAKE_CURRENT_SOURCE_DIR}/src/node/test/snapshot.cpp diff --git a/scripts/ci-checks.sh b/scripts/ci-checks.sh index 12f4ae8a438..0b1bd328708 100755 --- a/scripts/ci-checks.sh +++ b/scripts/ci-checks.sh @@ -16,7 +16,7 @@ echo "Shell scripts" find . -type f -regex ".*\.sh$" | grep -E -v "^./3rdparty/" | xargs shellcheck -s bash -e SC2044,SC2002,SC1091,SC2181 echo "TODOs" -"$SCRIPT_DIR"/check-todo.sh src +#"$SCRIPT_DIR"/check-todo.sh src echo "C/C++ format" if [ $FIX -ne 0 ]; then diff --git a/src/ds/nonstd.h b/src/ds/nonstd.h index cf24b36a3f0..ae8d1c97bda 100644 --- a/src/ds/nonstd.h +++ b/src/ds/nonstd.h @@ -78,7 +78,8 @@ namespace nonstd }); } - static inline std::string remove_prefix(const std::string& s, const std::string& prefix) + static inline std::string remove_prefix( + const std::string& s, const std::string& prefix) { if (s.find(prefix) == 0) { diff --git a/src/node/rpc/common_endpoint_registry.h b/src/node/rpc/common_endpoint_registry.h index fa1c7544266..4752ce83ed1 100644 --- a/src/node/rpc/common_endpoint_registry.h +++ b/src/node/rpc/common_endpoint_registry.h @@ -225,7 +225,8 @@ namespace ccf auto openapi = [this](kv::Tx& tx, nlohmann::json&&) { // TODO: Update these - auto document = ds::openapi::create_document("Placeholder title", "Placeholder description", "1.0.0"); + auto document = ds::openapi::create_document( + "Placeholder title", "Placeholder description", "1.0.0"); build_api(document, tx); return make_success(document); }; diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index 4a3c62c5c33..616267228b4 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -109,34 +109,33 @@ namespace ccf { params_schema = j; - schema_builders.push_back( - [](nlohmann::json& document, const Endpoint& endpoint) { - const auto http_verb = endpoint.verb.get_http_method(); - if (!http_verb.has_value()) - { - return; - } + schema_builders.push_back([]( + nlohmann::json& document, + const Endpoint& endpoint) { + const auto http_verb = endpoint.verb.get_http_method(); + if (!http_verb.has_value()) + { + return; + } - using namespace ds::openapi; + using namespace ds::openapi; - if ( - http_verb.value() == HTTP_GET || - http_verb.value() == HTTP_DELETE) - { - add_query_parameters( - document, - endpoint.method, - endpoint.params_schema, - http_verb.value()); - } - else - { - auto& rb = request_body(path_operation( - ds::openapi::path(document, endpoint.method), http_verb.value())); - schema(media_type(rb, http::headervalues::contenttype::JSON)) = - endpoint.params_schema; - } - }); + if (http_verb.value() == HTTP_GET || http_verb.value() == HTTP_DELETE) + { + add_query_parameters( + document, + endpoint.method, + endpoint.params_schema, + http_verb.value()); + } + else + { + auto& rb = request_body(path_operation( + ds::openapi::path(document, endpoint.method), http_verb.value())); + schema(media_type(rb, http::headervalues::contenttype::JSON)) = + endpoint.params_schema; + } + }); return *this; } diff --git a/tests/schema.py b/tests/schema.py index 16f2f4bdbcb..0c0fd39d381 100644 --- a/tests/schema.py +++ b/tests/schema.py @@ -49,7 +49,7 @@ def fetch_schema(client, prefix): schema_found = False expected_method_prefix = "/" if method.startswith(expected_method_prefix): - method = method[len(expected_method_prefix):] + method = method[len(expected_method_prefix) :] schema_response = client.get(f'/{prefix}/api/schema?method="{method}"') check( schema_response, From c28ace55af81dc59687b4f47ae7b7c2dbfcf5d03 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Wed, 16 Sep 2020 14:02:42 +0100 Subject: [PATCH 42/53] Delete --- python/setup.py | 42 ------------------------------------------ 1 file changed, 42 deletions(-) delete mode 100644 python/setup.py diff --git a/python/setup.py b/python/setup.py deleted file mode 100644 index b32f73f1f1c..00000000000 --- a/python/setup.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the Apache 2.0 License. - -from setuptools import setup # type: ignore -from os import path - -PACKAGE_NAME = "ccf" -UTILITIES_PATH = "utils" - -path_here = path.abspath(path.dirname(__file__)) - -with open(path.join(path_here, "README.md"), encoding="utf-8") as f: - long_description = f.read() - -with open('requirements.txt') as f: - requirements = f.read().splitlines() - -setup( - name=PACKAGE_NAME, - version="0.13.2", - description="Set of tools and utilities for the Confidential Consortium Framework (CCF)", - long_description=long_description, - long_description_content_type="text/markdown", - url="https://github.com/microsoft/CCF/tree/master/python", - license="Apache License 2.0", - author="CCF Team", - classifiers=[ - "Development Status :: 3 - Alpha", - "Intended Audience :: Developers", - "Programming Language :: Python :: 3", - ], - packages=[PACKAGE_NAME], - python_requires=">=3.7", - install_requires=requirements, - scripts=[ - path.join(PACKAGE_NAME, "proposal_generator.py"), - path.join(UTILITIES_PATH, "keygenerator.sh"), - path.join(UTILITIES_PATH, "scurl.sh"), - path.join(UTILITIES_PATH, "submit_recovery_share.sh"), - ], - include_package_data=True, -) From 75962416d449629958fc45fc0961fddcc7bf0325 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Wed, 16 Sep 2020 16:52:17 +0100 Subject: [PATCH 43/53] Oops - these lines restore result schema --- src/node/rpc/endpoint_registry.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index 616267228b4..ec29a6fe323 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -149,6 +149,8 @@ namespace ccf */ Endpoint& set_result_schema(const nlohmann::json& j) { + result_schema = j; + schema_builders.push_back( [j](nlohmann::json& document, const Endpoint& endpoint) { const auto http_verb = endpoint.verb.get_http_method(); @@ -230,6 +232,8 @@ namespace ccf if constexpr (!std::is_same_v) { + result_schema = ds::json::build_schema(method + "/result"); + schema_builders.push_back( [](nlohmann::json& document, const Endpoint& endpoint) { const auto http_verb = endpoint.verb.get_http_method(); From 8d5a1b8cfaa6e3da2e381eff7a283dd8c7d631ad Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Wed, 16 Sep 2020 16:52:55 +0100 Subject: [PATCH 44/53] Add restored result schema --- .../ack/update_state_digest_POST_result.json | 62 ++++++++++++++++ doc/schemas/ack_POST_result.json | 4 + doc/schemas/api/schema_GET_result.json | 16 ++++ doc/schemas/app_openapi.json | 62 ++++++++++++++++ doc/schemas/code_GET_result.json | 30 ++++++++ doc/schemas/commit_GET_result.json | 20 +++++ doc/schemas/endpoint_metrics_GET_result.json | 40 ++++++++++ doc/schemas/gov_openapi.json | 38 ++++++++++ doc/schemas/local_tx_GET_params.json | 1 - doc/schemas/local_tx_GET_result.json | 1 - .../log/private/admin_only_POST_result.json | 4 + .../log/private/anonymous_POST_result.json | 4 + doc/schemas/log/private_DELETE_result.json | 4 + doc/schemas/log/private_GET_result.json | 12 +++ doc/schemas/log/private_POST_result.json | 4 + doc/schemas/log/private_WEBSOCKET_result.json | 4 + doc/schemas/log/public_DELETE_result.json | 4 + doc/schemas/log/public_GET_result.json | 12 +++ doc/schemas/log/public_POST_result.json | 4 + doc/schemas/metrics_GET_result.json | 44 +++++++++++ doc/schemas/network_info_GET_result.json | 39 ++++++++++ doc/schemas/node/ids_GET_result.json | 33 +++++++++ doc/schemas/node_openapi.json | 38 ++++++++++ doc/schemas/primary_info_GET_result.json | 28 +++++++ .../{proposal_id}/complete_POST_result.json | 30 ++++++++ .../votes/{member_id}_GET_result.json | 25 +++++++ .../{proposal_id}/votes_POST_result.json | 30 ++++++++ .../{proposal_id}/withdraw_POST_result.json | 30 ++++++++ .../proposals/{proposal_id}_GET_result.json | 73 +++++++++++++++++++ doc/schemas/proposals_POST_result.json | 30 ++++++++ doc/schemas/quote_GET_result.json | 35 +++++++++ doc/schemas/quotes_GET_result.json | 35 +++++++++ doc/schemas/receipt/verify_POST_result.json | 12 +++ doc/schemas/receipt_GET_result.json | 17 +++++ .../recovery_share/submit_POST_result.json | 4 + doc/schemas/recovery_share_GET_result.json | 16 ++++ doc/schemas/state_GET_result.json | 42 +++++++++++ doc/schemas/tx_GET_result.json | 17 +++++ doc/schemas/user_id_GET_result.json | 14 ++++ 39 files changed, 916 insertions(+), 2 deletions(-) create mode 100644 doc/schemas/ack/update_state_digest_POST_result.json create mode 100644 doc/schemas/ack_POST_result.json create mode 100644 doc/schemas/api/schema_GET_result.json create mode 100644 doc/schemas/code_GET_result.json create mode 100644 doc/schemas/commit_GET_result.json create mode 100644 doc/schemas/endpoint_metrics_GET_result.json create mode 100644 doc/schemas/log/private/admin_only_POST_result.json create mode 100644 doc/schemas/log/private/anonymous_POST_result.json create mode 100644 doc/schemas/log/private_DELETE_result.json create mode 100644 doc/schemas/log/private_GET_result.json create mode 100644 doc/schemas/log/private_POST_result.json create mode 100644 doc/schemas/log/private_WEBSOCKET_result.json create mode 100644 doc/schemas/log/public_DELETE_result.json create mode 100644 doc/schemas/log/public_GET_result.json create mode 100644 doc/schemas/log/public_POST_result.json create mode 100644 doc/schemas/metrics_GET_result.json create mode 100644 doc/schemas/network_info_GET_result.json create mode 100644 doc/schemas/node/ids_GET_result.json create mode 100644 doc/schemas/primary_info_GET_result.json create mode 100644 doc/schemas/proposals/{proposal_id}/complete_POST_result.json create mode 100644 doc/schemas/proposals/{proposal_id}/votes/{member_id}_GET_result.json create mode 100644 doc/schemas/proposals/{proposal_id}/votes_POST_result.json create mode 100644 doc/schemas/proposals/{proposal_id}/withdraw_POST_result.json create mode 100644 doc/schemas/proposals/{proposal_id}_GET_result.json create mode 100644 doc/schemas/proposals_POST_result.json create mode 100644 doc/schemas/quote_GET_result.json create mode 100644 doc/schemas/quotes_GET_result.json create mode 100644 doc/schemas/receipt/verify_POST_result.json create mode 100644 doc/schemas/receipt_GET_result.json create mode 100644 doc/schemas/recovery_share/submit_POST_result.json create mode 100644 doc/schemas/recovery_share_GET_result.json create mode 100644 doc/schemas/state_GET_result.json create mode 100644 doc/schemas/tx_GET_result.json create mode 100644 doc/schemas/user_id_GET_result.json diff --git a/doc/schemas/ack/update_state_digest_POST_result.json b/doc/schemas/ack/update_state_digest_POST_result.json new file mode 100644 index 00000000000..1c7ea28845c --- /dev/null +++ b/doc/schemas/ack/update_state_digest_POST_result.json @@ -0,0 +1,62 @@ +{ + "properties": { + "signed_req": { + "properties": { + "md": { + "enum": [ + "MBEDTLS_MD_NONE", + "MBEDTLS_MD_SHA1", + "MBEDTLS_MD_SHA256", + "MBEDTLS_MD_SHA384", + "MBEDTLS_MD_SHA512" + ] + }, + "req": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "request_body": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "sig": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "sig", + "req", + "request_body", + "md" + ], + "type": "object" + }, + "state_digest": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "state_digest", + "signed_req" + ], + "title": "ack/update_state_digest/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/ack_POST_result.json b/doc/schemas/ack_POST_result.json new file mode 100644 index 00000000000..7268be8c791 --- /dev/null +++ b/doc/schemas/ack_POST_result.json @@ -0,0 +1,4 @@ +{ + "title": "ack/result", + "type": "boolean" +} \ No newline at end of file diff --git a/doc/schemas/api/schema_GET_result.json b/doc/schemas/api/schema_GET_result.json new file mode 100644 index 00000000000..000c6590883 --- /dev/null +++ b/doc/schemas/api/schema_GET_result.json @@ -0,0 +1,16 @@ +{ + "properties": { + "params_schema": { + "type": "object" + }, + "result_schema": { + "type": "object" + } + }, + "required": [ + "params_schema", + "result_schema" + ], + "title": "api/schema/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/app_openapi.json b/doc/schemas/app_openapi.json index 1f387b7e5ee..6e41bbc0073 100644 --- a/doc/schemas/app_openapi.json +++ b/doc/schemas/app_openapi.json @@ -479,6 +479,44 @@ } } }, + "/local_tx": { + "get": { + "parameters": [ + { + "in": "query", + "name": "seqno", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + { + "in": "query", + "name": "view", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetTxStatus__Out" + } + } + }, + "description": "Default response description" + } + } + } + }, "/log/private": { "delete": { "parameters": [ @@ -661,6 +699,22 @@ ], "responses": { "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "msg": { + "type": "string" + } + }, + "required": [ + "msg" + ], + "title": "log/public/result", + "type": "object" + } + } + }, "description": "Default response description" } } @@ -690,6 +744,14 @@ }, "responses": { "200": { + "content": { + "application/json": { + "schema": { + "title": "log/public/result", + "type": "boolean" + } + } + }, "description": "Default response description" } } diff --git a/doc/schemas/code_GET_result.json b/doc/schemas/code_GET_result.json new file mode 100644 index 00000000000..f667b931693 --- /dev/null +++ b/doc/schemas/code_GET_result.json @@ -0,0 +1,30 @@ +{ + "properties": { + "versions": { + "items": { + "properties": { + "digest": { + "type": "string" + }, + "status": { + "enum": [ + "ACCEPTED", + "RETIRED" + ] + } + }, + "required": [ + "digest", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "versions" + ], + "title": "code/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/commit_GET_result.json b/doc/schemas/commit_GET_result.json new file mode 100644 index 00000000000..d90ed03a33d --- /dev/null +++ b/doc/schemas/commit_GET_result.json @@ -0,0 +1,20 @@ +{ + "properties": { + "seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + "required": [ + "view", + "seqno" + ], + "title": "commit/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/endpoint_metrics_GET_result.json b/doc/schemas/endpoint_metrics_GET_result.json new file mode 100644 index 00000000000..3f4d34d79f5 --- /dev/null +++ b/doc/schemas/endpoint_metrics_GET_result.json @@ -0,0 +1,40 @@ +{ + "properties": { + "metrics": { + "additionalProperties": { + "additionalProperties": { + "properties": { + "calls": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "errors": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "failures": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "calls", + "errors", + "failures" + ], + "type": "object" + }, + "type": "object" + }, + "type": "object" + } + }, + "required": [ + "metrics" + ], + "title": "endpoint_metrics/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/gov_openapi.json b/doc/schemas/gov_openapi.json index 25a07ae7e1e..4c618023bfd 100644 --- a/doc/schemas/gov_openapi.json +++ b/doc/schemas/gov_openapi.json @@ -691,6 +691,44 @@ } } }, + "/local_tx": { + "get": { + "parameters": [ + { + "in": "query", + "name": "seqno", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + { + "in": "query", + "name": "view", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetTxStatus__Out" + } + } + }, + "description": "Default response description" + } + } + } + }, "/metrics": { "get": { "responses": { diff --git a/doc/schemas/local_tx_GET_params.json b/doc/schemas/local_tx_GET_params.json index 2f5c752fc70..1d62fc03e13 100644 --- a/doc/schemas/local_tx_GET_params.json +++ b/doc/schemas/local_tx_GET_params.json @@ -1,5 +1,4 @@ { - "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "seqno": { "maximum": 9223372036854775807, diff --git a/doc/schemas/local_tx_GET_result.json b/doc/schemas/local_tx_GET_result.json index 70f76814f8e..beec85746a5 100644 --- a/doc/schemas/local_tx_GET_result.json +++ b/doc/schemas/local_tx_GET_result.json @@ -1,5 +1,4 @@ { - "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "status": { "enum": [ diff --git a/doc/schemas/log/private/admin_only_POST_result.json b/doc/schemas/log/private/admin_only_POST_result.json new file mode 100644 index 00000000000..f731d3ec9a6 --- /dev/null +++ b/doc/schemas/log/private/admin_only_POST_result.json @@ -0,0 +1,4 @@ +{ + "title": "log/private/admin_only/result", + "type": "boolean" +} \ No newline at end of file diff --git a/doc/schemas/log/private/anonymous_POST_result.json b/doc/schemas/log/private/anonymous_POST_result.json new file mode 100644 index 00000000000..d78e3311f84 --- /dev/null +++ b/doc/schemas/log/private/anonymous_POST_result.json @@ -0,0 +1,4 @@ +{ + "title": "log/private/anonymous/result", + "type": "boolean" +} \ No newline at end of file diff --git a/doc/schemas/log/private_DELETE_result.json b/doc/schemas/log/private_DELETE_result.json new file mode 100644 index 00000000000..423e1d35077 --- /dev/null +++ b/doc/schemas/log/private_DELETE_result.json @@ -0,0 +1,4 @@ +{ + "title": "log/private/result", + "type": "boolean" +} \ No newline at end of file diff --git a/doc/schemas/log/private_GET_result.json b/doc/schemas/log/private_GET_result.json new file mode 100644 index 00000000000..67c8963ac93 --- /dev/null +++ b/doc/schemas/log/private_GET_result.json @@ -0,0 +1,12 @@ +{ + "properties": { + "msg": { + "type": "string" + } + }, + "required": [ + "msg" + ], + "title": "log/private/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/log/private_POST_result.json b/doc/schemas/log/private_POST_result.json new file mode 100644 index 00000000000..423e1d35077 --- /dev/null +++ b/doc/schemas/log/private_POST_result.json @@ -0,0 +1,4 @@ +{ + "title": "log/private/result", + "type": "boolean" +} \ No newline at end of file diff --git a/doc/schemas/log/private_WEBSOCKET_result.json b/doc/schemas/log/private_WEBSOCKET_result.json new file mode 100644 index 00000000000..423e1d35077 --- /dev/null +++ b/doc/schemas/log/private_WEBSOCKET_result.json @@ -0,0 +1,4 @@ +{ + "title": "log/private/result", + "type": "boolean" +} \ No newline at end of file diff --git a/doc/schemas/log/public_DELETE_result.json b/doc/schemas/log/public_DELETE_result.json new file mode 100644 index 00000000000..213d0cb22de --- /dev/null +++ b/doc/schemas/log/public_DELETE_result.json @@ -0,0 +1,4 @@ +{ + "title": "log/public/result", + "type": "boolean" +} \ No newline at end of file diff --git a/doc/schemas/log/public_GET_result.json b/doc/schemas/log/public_GET_result.json new file mode 100644 index 00000000000..1f430b8ec83 --- /dev/null +++ b/doc/schemas/log/public_GET_result.json @@ -0,0 +1,12 @@ +{ + "properties": { + "msg": { + "type": "string" + } + }, + "required": [ + "msg" + ], + "title": "log/public/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/log/public_POST_result.json b/doc/schemas/log/public_POST_result.json new file mode 100644 index 00000000000..213d0cb22de --- /dev/null +++ b/doc/schemas/log/public_POST_result.json @@ -0,0 +1,4 @@ +{ + "title": "log/public/result", + "type": "boolean" +} \ No newline at end of file diff --git a/doc/schemas/metrics_GET_result.json b/doc/schemas/metrics_GET_result.json new file mode 100644 index 00000000000..2c5918392dd --- /dev/null +++ b/doc/schemas/metrics_GET_result.json @@ -0,0 +1,44 @@ +{ + "properties": { + "histogram": { + "properties": { + "buckets": {}, + "high": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "low": { + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "overflow": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "underflow": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "low", + "high", + "overflow", + "underflow", + "buckets" + ], + "type": "object" + }, + "tx_rates": {} + }, + "required": [ + "histogram", + "tx_rates" + ], + "title": "metrics/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/network_info_GET_result.json b/doc/schemas/network_info_GET_result.json new file mode 100644 index 00000000000..eb2cb3c1902 --- /dev/null +++ b/doc/schemas/network_info_GET_result.json @@ -0,0 +1,39 @@ +{ + "properties": { + "nodes": { + "items": { + "properties": { + "host": { + "type": "string" + }, + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "port": { + "type": "string" + } + }, + "required": [ + "node_id", + "host", + "port" + ], + "type": "object" + }, + "type": "array" + }, + "primary_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "nodes", + "primary_id" + ], + "title": "network_info/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/node/ids_GET_result.json b/doc/schemas/node/ids_GET_result.json new file mode 100644 index 00000000000..de4e8bbb826 --- /dev/null +++ b/doc/schemas/node/ids_GET_result.json @@ -0,0 +1,33 @@ +{ + "properties": { + "nodes": { + "items": { + "properties": { + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "status": { + "enum": [ + "PENDING", + "TRUSTED", + "RETIRED" + ] + } + }, + "required": [ + "node_id", + "status" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "nodes" + ], + "title": "node/ids/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/node_openapi.json b/doc/schemas/node_openapi.json index 4b180a79dfb..d63ab2f8ca8 100644 --- a/doc/schemas/node_openapi.json +++ b/doc/schemas/node_openapi.json @@ -516,6 +516,44 @@ } } }, + "/local_tx": { + "get": { + "parameters": [ + { + "in": "query", + "name": "seqno", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + }, + { + "in": "query", + "name": "view", + "required": false, + "schema": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetTxStatus__Out" + } + } + }, + "description": "Default response description" + } + } + } + }, "/metrics": { "get": { "responses": { diff --git a/doc/schemas/primary_info_GET_result.json b/doc/schemas/primary_info_GET_result.json new file mode 100644 index 00000000000..43e11dbb049 --- /dev/null +++ b/doc/schemas/primary_info_GET_result.json @@ -0,0 +1,28 @@ +{ + "properties": { + "current_view": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "primary_host": { + "type": "string" + }, + "primary_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "primary_port": { + "type": "string" + } + }, + "required": [ + "primary_id", + "primary_host", + "primary_port", + "current_view" + ], + "title": "primary_info/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/complete_POST_result.json b/doc/schemas/proposals/{proposal_id}/complete_POST_result.json new file mode 100644 index 00000000000..6287c75c763 --- /dev/null +++ b/doc/schemas/proposals/{proposal_id}/complete_POST_result.json @@ -0,0 +1,30 @@ +{ + "properties": { + "proposal_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "proposer_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "state": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + } + }, + "required": [ + "proposal_id", + "proposer_id", + "state" + ], + "title": "proposals/{proposal_id}/complete/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/votes/{member_id}_GET_result.json b/doc/schemas/proposals/{proposal_id}/votes/{member_id}_GET_result.json new file mode 100644 index 00000000000..5b970d9f4ef --- /dev/null +++ b/doc/schemas/proposals/{proposal_id}/votes/{member_id}_GET_result.json @@ -0,0 +1,25 @@ +{ + "properties": { + "ballot": { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + } + }, + "required": [ + "ballot" + ], + "title": "proposals/{proposal_id}/votes/{member_id}/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/votes_POST_result.json b/doc/schemas/proposals/{proposal_id}/votes_POST_result.json new file mode 100644 index 00000000000..f052c8c35d1 --- /dev/null +++ b/doc/schemas/proposals/{proposal_id}/votes_POST_result.json @@ -0,0 +1,30 @@ +{ + "properties": { + "proposal_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "proposer_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "state": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + } + }, + "required": [ + "proposal_id", + "proposer_id", + "state" + ], + "title": "proposals/{proposal_id}/votes/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}/withdraw_POST_result.json b/doc/schemas/proposals/{proposal_id}/withdraw_POST_result.json new file mode 100644 index 00000000000..2a38ef2fff8 --- /dev/null +++ b/doc/schemas/proposals/{proposal_id}/withdraw_POST_result.json @@ -0,0 +1,30 @@ +{ + "properties": { + "proposal_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "proposer_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "state": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + } + }, + "required": [ + "proposal_id", + "proposer_id", + "state" + ], + "title": "proposals/{proposal_id}/withdraw/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/proposals/{proposal_id}_GET_result.json b/doc/schemas/proposals/{proposal_id}_GET_result.json new file mode 100644 index 00000000000..48d91ddab99 --- /dev/null +++ b/doc/schemas/proposals/{proposal_id}_GET_result.json @@ -0,0 +1,73 @@ +{ + "properties": { + "parameter": {}, + "proposer": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "script": { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + }, + "state": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + }, + "votes": { + "items": { + "items": [ + { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + { + "properties": { + "bytecode": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + }, + "text": { + "type": "string" + } + }, + "type": "object" + } + ], + "type": "array" + }, + "type": "array" + } + }, + "required": [ + "script", + "parameter", + "proposer", + "state", + "votes" + ], + "title": "proposals/{proposal_id}/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/proposals_POST_result.json b/doc/schemas/proposals_POST_result.json new file mode 100644 index 00000000000..f33004c21b5 --- /dev/null +++ b/doc/schemas/proposals_POST_result.json @@ -0,0 +1,30 @@ +{ + "properties": { + "proposal_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "proposer_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "state": { + "enum": [ + "OPEN", + "ACCEPTED", + "WITHDRAWN", + "REJECTED", + "FAILED" + ] + } + }, + "required": [ + "proposal_id", + "proposer_id", + "state" + ], + "title": "proposals/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/quote_GET_result.json b/doc/schemas/quote_GET_result.json new file mode 100644 index 00000000000..c967cc601d2 --- /dev/null +++ b/doc/schemas/quote_GET_result.json @@ -0,0 +1,35 @@ +{ + "properties": { + "quotes": { + "items": { + "properties": { + "error": { + "type": "string" + }, + "mrenclave": { + "type": "string" + }, + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "raw": { + "type": "string" + } + }, + "required": [ + "node_id", + "raw" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "quotes" + ], + "title": "quote/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/quotes_GET_result.json b/doc/schemas/quotes_GET_result.json new file mode 100644 index 00000000000..800db184707 --- /dev/null +++ b/doc/schemas/quotes_GET_result.json @@ -0,0 +1,35 @@ +{ + "properties": { + "quotes": { + "items": { + "properties": { + "error": { + "type": "string" + }, + "mrenclave": { + "type": "string" + }, + "node_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "raw": { + "type": "string" + } + }, + "required": [ + "node_id", + "raw" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "quotes" + ], + "title": "quotes/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/receipt/verify_POST_result.json b/doc/schemas/receipt/verify_POST_result.json new file mode 100644 index 00000000000..920d7652c68 --- /dev/null +++ b/doc/schemas/receipt/verify_POST_result.json @@ -0,0 +1,12 @@ +{ + "properties": { + "valid": { + "type": "boolean" + } + }, + "required": [ + "valid" + ], + "title": "receipt/verify/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/receipt_GET_result.json b/doc/schemas/receipt_GET_result.json new file mode 100644 index 00000000000..38eefacaf36 --- /dev/null +++ b/doc/schemas/receipt_GET_result.json @@ -0,0 +1,17 @@ +{ + "properties": { + "receipt": { + "items": { + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": "array" + } + }, + "required": [ + "receipt" + ], + "title": "receipt/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/recovery_share/submit_POST_result.json b/doc/schemas/recovery_share/submit_POST_result.json new file mode 100644 index 00000000000..8b951e5d9c8 --- /dev/null +++ b/doc/schemas/recovery_share/submit_POST_result.json @@ -0,0 +1,4 @@ +{ + "title": "recovery_share/submit/result", + "type": "string" +} \ No newline at end of file diff --git a/doc/schemas/recovery_share_GET_result.json b/doc/schemas/recovery_share_GET_result.json new file mode 100644 index 00000000000..82e894be508 --- /dev/null +++ b/doc/schemas/recovery_share_GET_result.json @@ -0,0 +1,16 @@ +{ + "properties": { + "encrypted_recovery_share": { + "type": "string" + }, + "nonce": { + "type": "string" + } + }, + "required": [ + "encrypted_recovery_share", + "nonce" + ], + "title": "recovery_share/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/state_GET_result.json b/doc/schemas/state_GET_result.json new file mode 100644 index 00000000000..42031ec0696 --- /dev/null +++ b/doc/schemas/state_GET_result.json @@ -0,0 +1,42 @@ +{ + "properties": { + "id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + }, + "last_recovered_seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "last_signed_seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "recovery_target_seqno": { + "maximum": 9223372036854775807, + "minimum": -9223372036854775808, + "type": "integer" + }, + "state": { + "enum": [ + "uninitialized", + "initialized", + "pending", + "partOfPublicNetwork", + "partOfNetwork", + "readingPublicLedger", + "readingPrivateLedger" + ] + } + }, + "required": [ + "id", + "state", + "last_signed_seqno" + ], + "title": "state/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/tx_GET_result.json b/doc/schemas/tx_GET_result.json new file mode 100644 index 00000000000..068146dc225 --- /dev/null +++ b/doc/schemas/tx_GET_result.json @@ -0,0 +1,17 @@ +{ + "properties": { + "status": { + "enum": [ + "UNKNOWN", + "PENDING", + "COMMITTED", + "INVALID" + ] + } + }, + "required": [ + "status" + ], + "title": "tx/result", + "type": "object" +} \ No newline at end of file diff --git a/doc/schemas/user_id_GET_result.json b/doc/schemas/user_id_GET_result.json new file mode 100644 index 00000000000..62469fc2e84 --- /dev/null +++ b/doc/schemas/user_id_GET_result.json @@ -0,0 +1,14 @@ +{ + "properties": { + "caller_id": { + "maximum": 18446744073709551615, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "caller_id" + ], + "title": "user_id/result", + "type": "object" +} \ No newline at end of file From 78905b53f8df0ce3de759d35b8f9ffe6b3457356 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Thu, 17 Sep 2020 17:16:13 +0100 Subject: [PATCH 45/53] Document (minimum) JS endpoints --- src/apps/js_generic/js_generic.cpp | 70 +++++++++++++++++-------- src/ds/openapi.h | 5 +- src/node/rpc/common_endpoint_registry.h | 41 ++------------- src/node/rpc/endpoint_registry.h | 31 +++++++++++ 4 files changed, 88 insertions(+), 59 deletions(-) diff --git a/src/apps/js_generic/js_generic.cpp b/src/apps/js_generic/js_generic.cpp index 64b270965ae..c572c0272df 100644 --- a/src/apps/js_generic/js_generic.cpp +++ b/src/apps/js_generic/js_generic.cpp @@ -655,33 +655,61 @@ namespace ccfapp set_default(default_handler); } + static std::pair split_script_key(const std::string& key) + { + size_t s = key.find(' '); + if (s != std::string::npos) + { + return std::make_pair( + http::http_method_from_str(key.substr(0, s).c_str()), + key.substr(s + 1, key.size() - (s + 1))); + } + else + { + return std::make_pair(HTTP_POST, key); + } + } + // Since we do our own dispatch within the default handler, report the // supported methods here void build_api(nlohmann::json& document, kv::Tx& tx) override { UserEndpointRegistry::build_api(document, tx); - // TODO - // auto scripts = tx.get_view(this->network.app_scripts); - // scripts->foreach([&out](const auto& key, const auto&) { - // out.methods.push_back(key); - // return true; - // }); - - // auto scripts = tx.get_view(this->network.app_scripts); - // scripts->foreach([&out](const auto& key, const auto&) { - // size_t s = key.find(' '); - // if (s != std::string::npos) - // { - // out.endpoints.push_back( - // {key.substr(0, s), key.substr(s + 1, key.size() - (s + 1))}); - // } - // else - // { - // out.endpoints.push_back({"POST", key}); - // } - // return true; - // }); + auto scripts = tx.get_view(this->network.app_scripts); + scripts->foreach([&document](const auto& key, const auto&) { + const auto [verb, method] = split_script_key(key); + + ds::openapi::path_operation(ds::openapi::path(document, method), verb); + return true; + }); + } + + nlohmann::json get_endpoint_schema( + kv::Tx& tx, const GetSchema::In& in) override + { + auto j = UserEndpointRegistry::get_endpoint_schema(tx, in); + + auto scripts = tx.get_view(this->network.app_scripts); + scripts->foreach([&j, &in](const auto& key, const auto&) { + const auto [verb, method] = split_script_key(key); + + if (in.method == method) + { + std::string verb_name = http_method_str(verb); + nonstd::to_lower(verb_name); + // We have no schema for JS endpoints, but populate the object if we + // know about them + GetSchema::Out out; + out.params_schema.schema = nullptr; + out.result_schema.schema = nullptr; + j[verb_name] = out; + } + + return true; + }); + + return j; } }; diff --git a/src/ds/openapi.h b/src/ds/openapi.h index aa91c893ecf..e74a8b131a5 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -104,7 +104,10 @@ namespace ds // HTTP_GET becomes the string "get" std::string s = http_method_str(verb); nonstd::to_lower(s); - return access::get_object(path, s); + auto& po = access::get_object(path, s); + // responses is required field in a path_operation + access::get_object(po, "responses"); + return po; } static inline nlohmann::json& parameters(nlohmann::json& path_operation) diff --git a/src/node/rpc/common_endpoint_registry.h b/src/node/rpc/common_endpoint_registry.h index 4752ce83ed1..526df88ee1c 100644 --- a/src/node/rpc/common_endpoint_registry.h +++ b/src/node/rpc/common_endpoint_registry.h @@ -245,43 +245,10 @@ namespace ccf .set_auto_schema() .install(); - auto get_schema = [this](auto&, nlohmann::json&& params) { + auto get_schema = [this](kv::Tx& tx, nlohmann::json&& params) { const auto in = params.get(); - auto j = nlohmann::json::object(); - - const auto it = fully_qualified_endpoints.find(in.method); - if (it != fully_qualified_endpoints.end()) - { - for (const auto& [verb, endpoint] : it->second) - { - std::string verb_name = verb.c_str(); - std::transform( - verb_name.begin(), - verb_name.end(), - verb_name.begin(), - [](unsigned char c) { return std::tolower(c); }); - j[verb_name] = - GetSchema::Out{endpoint.params_schema, endpoint.result_schema}; - } - } - - const auto templated_it = templated_endpoints.find(in.method); - if (templated_it != templated_endpoints.end()) - { - for (const auto& [verb, endpoint] : templated_it->second) - { - std::string verb_name = verb.c_str(); - std::transform( - verb_name.begin(), - verb_name.end(), - verb_name.begin(), - [](unsigned char c) { return std::tolower(c); }); - j[verb_name] = - GetSchema::Out{endpoint.params_schema, endpoint.result_schema}; - } - } - + auto j = get_endpoint_schema(tx, in); if (j.empty()) { return make_error( @@ -291,8 +258,8 @@ namespace ccf return make_success(j); }; - make_command_endpoint( - "api/schema", HTTP_GET, json_command_adapter(get_schema)) + make_endpoint( + "api/schema", HTTP_GET, json_adapter(get_schema)) .set_auto_schema() .install(); diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index ec29a6fe323..9d5b547be5e 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -621,6 +621,37 @@ namespace ccf } } + virtual nlohmann::json get_endpoint_schema(kv::Tx&, const GetSchema::In& in) + { + auto j = nlohmann::json::object(); + + const auto it = fully_qualified_endpoints.find(in.method); + if (it != fully_qualified_endpoints.end()) + { + for (const auto& [verb, endpoint] : it->second) + { + std::string verb_name = verb.c_str(); + nonstd::to_lower(verb_name); + j[verb_name] = + GetSchema::Out{endpoint.params_schema, endpoint.result_schema}; + } + } + + const auto templated_it = templated_endpoints.find(in.method); + if (templated_it != templated_endpoints.end()) + { + for (const auto& [verb, endpoint] : templated_it->second) + { + std::string verb_name = verb.c_str(); + nonstd::to_lower(verb_name); + j[verb_name] = + GetSchema::Out{endpoint.params_schema, endpoint.result_schema}; + } + } + + return j; + } + virtual void endpoint_metrics(kv::Tx&, EndpointMetrics::Out& out) { for (const auto& [path, verb_endpoints] : fully_qualified_endpoints) From 08fe5a6a4e00108ddd730649779f8259962d44b2 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Thu, 17 Sep 2020 17:21:25 +0100 Subject: [PATCH 46/53] Hey we can do that in lua too --- src/apps/lua_generic/lua_generic.cpp | 64 +++++++++++++++++++++------- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/src/apps/lua_generic/lua_generic.cpp b/src/apps/lua_generic/lua_generic.cpp index 0263d9d2ebf..ab8f19dd767 100644 --- a/src/apps/lua_generic/lua_generic.cpp +++ b/src/apps/lua_generic/lua_generic.cpp @@ -185,27 +185,61 @@ namespace ccfapp set_default(json_adapter(default_handler)); } + static std::pair split_script_key(const std::string& key) + { + size_t s = key.find(' '); + if (s != std::string::npos) + { + return std::make_pair( + http::http_method_from_str(key.substr(0, s).c_str()), + key.substr(s + 1, key.size() - (s + 1))); + } + else + { + return std::make_pair(HTTP_POST, key); + } + } + // Since we do our own dispatch within the default handler, report the // supported methods here void build_api(nlohmann::json& document, kv::Tx& tx) override { UserEndpointRegistry::build_api(document, tx); - // TODO - // auto scripts = tx.get_view(this->network.app_scripts); - // scripts->foreach([&out](const auto& key, const auto&) { - // if (key != UserScriptIds::ENV_HANDLER) - // { - // out.methods.push_back(key); - // } - // return true; - // }); - - // auto scripts = tx.get_view(this->network.app_scripts); - // scripts->foreach([&out](const auto& key, const auto&) { - // out.endpoints.push_back({"POST", key}); - // return true; - // }); + auto scripts = tx.get_view(this->network.app_scripts); + scripts->foreach([&document](const auto& key, const auto&) { + const auto [verb, method] = split_script_key(key); + + ds::openapi::path_operation(ds::openapi::path(document, method), verb); + return true; + }); + } + + nlohmann::json get_endpoint_schema( + kv::Tx& tx, const GetSchema::In& in) override + { + auto j = UserEndpointRegistry::get_endpoint_schema(tx, in); + + auto scripts = tx.get_view(this->network.app_scripts); + scripts->foreach([&j, &in](const auto& key, const auto&) { + const auto [verb, method] = split_script_key(key); + + if (in.method == method) + { + std::string verb_name = http_method_str(verb); + nonstd::to_lower(verb_name); + // We have no schema for JS endpoints, but populate the object if we + // know about them + GetSchema::Out out; + out.params_schema.schema = nullptr; + out.result_schema.schema = nullptr; + j[verb_name] = out; + } + + return true; + }); + + return j; } }; From 890c9d7b696ecfc2227459cb23c32ff080247431 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Thu, 17 Sep 2020 17:21:52 +0100 Subject: [PATCH 47/53] Shout about TODOs again --- scripts/ci-checks.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci-checks.sh b/scripts/ci-checks.sh index 0b1bd328708..12f4ae8a438 100755 --- a/scripts/ci-checks.sh +++ b/scripts/ci-checks.sh @@ -16,7 +16,7 @@ echo "Shell scripts" find . -type f -regex ".*\.sh$" | grep -E -v "^./3rdparty/" | xargs shellcheck -s bash -e SC2044,SC2002,SC1091,SC2181 echo "TODOs" -#"$SCRIPT_DIR"/check-todo.sh src +"$SCRIPT_DIR"/check-todo.sh src echo "C/C++ format" if [ $FIX -ne 0 ]; then From c31c300d87529e7a27f0b52ee46c4fe9617c2790 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Mon, 21 Sep 2020 16:44:56 +0100 Subject: [PATCH 48/53] Fixups --- tests/schema.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/schema.py b/tests/schema.py index 90f17549c98..455dda19470 100644 --- a/tests/schema.py +++ b/tests/schema.py @@ -41,7 +41,8 @@ def fetch_schema(client, prefix): api_response, error=lambda status, msg: status == http.HTTPStatus.OK.value ) - paths = api_response.body["paths"] + response_body = api_response.body.json() + paths = response_body["paths"] all_methods.extend(paths.keys()) # Fetch the schema of each method @@ -93,7 +94,7 @@ def fetch_schema(client, prefix): else: methods_without_schema.add(method) - formatted_schema = json.dumps(api_response.body, indent=2) + formatted_schema = json.dumps(response_body, indent=2) openapi_target_file = os.path.join(args.schema_dir, f"{prefix}_openapi.json") try: @@ -114,7 +115,7 @@ def fetch_schema(client, prefix): LOG.debug("Schema matches in {}".format(openapi_target_file)) try: - openapi_spec_validator.validate_spec(api_response.body) + openapi_spec_validator.validate_spec(response_body) except Exception as e: LOG.error(f"Validation of {prefix} schema failed") LOG.error(e) From 7e63db4f8f1d4de98095454915db7353e6cc4efd Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Wed, 23 Sep 2020 11:44:18 +0100 Subject: [PATCH 49/53] Make OpenAPI info customisable --- doc/schemas/app_openapi.json | 6 +++--- doc/schemas/gov_openapi.json | 6 +++--- doc/schemas/node_openapi.json | 6 +++--- src/apps/logging/logging.cpp | 6 ++++++ src/node/rpc/common_endpoint_registry.h | 8 ++++---- src/node/rpc/endpoint_registry.h | 9 +++++++-- src/node/rpc/member_frontend.h | 7 ++++++- src/node/rpc/node_frontend.h | 7 ++++++- src/node/rpc/user_frontend.h | 4 +++- 9 files changed, 41 insertions(+), 18 deletions(-) diff --git a/doc/schemas/app_openapi.json b/doc/schemas/app_openapi.json index 6e41bbc0073..8358403b8de 100644 --- a/doc/schemas/app_openapi.json +++ b/doc/schemas/app_openapi.json @@ -383,9 +383,9 @@ } }, "info": { - "description": "Placeholder description", - "title": "Placeholder title", - "version": "1.0.0" + "description": "This CCF sample app implements a simple logging application, securely recording messages at client-specified IDs. It demonstrates most of the features available to CCF apps.", + "title": "CCF Sample Logging App", + "version": "0.0.1" }, "openapi": "3.0.0", "paths": { diff --git a/doc/schemas/gov_openapi.json b/doc/schemas/gov_openapi.json index 4c618023bfd..99c42226427 100644 --- a/doc/schemas/gov_openapi.json +++ b/doc/schemas/gov_openapi.json @@ -553,9 +553,9 @@ } }, "info": { - "description": "Placeholder description", - "title": "Placeholder title", - "version": "1.0.0" + "description": "This API is used to submit and query proposals which affect CCF's public governance tables.", + "title": "CCF Governance API", + "version": "0.0.1" }, "openapi": "3.0.0", "paths": { diff --git a/doc/schemas/node_openapi.json b/doc/schemas/node_openapi.json index d63ab2f8ca8..84625b1723b 100644 --- a/doc/schemas/node_openapi.json +++ b/doc/schemas/node_openapi.json @@ -420,9 +420,9 @@ } }, "info": { - "description": "Placeholder description", - "title": "Placeholder title", - "version": "1.0.0" + "description": "This API provides public, uncredentialed access to service and node state.", + "title": "CCF Public Node API", + "version": "0.0.1" }, "openapi": "3.0.0", "paths": { diff --git a/src/apps/logging/logging.cpp b/src/apps/logging/logging.cpp index f617091ac91..b7b1beab2fb 100644 --- a/src/apps/logging/logging.cpp +++ b/src/apps/logging/logging.cpp @@ -69,6 +69,12 @@ namespace loggingapp get_public_params_schema(nlohmann::json::parse(j_get_public_in)), get_public_result_schema(nlohmann::json::parse(j_get_public_out)) { + openapi_info.title = "CCF Sample Logging App"; + openapi_info.description = + "This CCF sample app implements a simple logging application, securely " + "recording messages at client-specified IDs. It demonstrates most of " + "the features available to CCF apps."; + // SNIPPET_START: record auto record = [this](kv::Tx& tx, nlohmann::json&& params) { // SNIPPET_START: macro_validation_record diff --git a/src/node/rpc/common_endpoint_registry.h b/src/node/rpc/common_endpoint_registry.h index 526df88ee1c..fb85fbee2a4 100644 --- a/src/node/rpc/common_endpoint_registry.h +++ b/src/node/rpc/common_endpoint_registry.h @@ -224,9 +224,10 @@ namespace ccf .install(); auto openapi = [this](kv::Tx& tx, nlohmann::json&&) { - // TODO: Update these auto document = ds::openapi::create_document( - "Placeholder title", "Placeholder description", "1.0.0"); + openapi_info.title, + openapi_info.description, + openapi_info.document_version); build_api(document, tx); return make_success(document); }; @@ -258,8 +259,7 @@ namespace ccf return make_success(j); }; - make_endpoint( - "api/schema", HTTP_GET, json_adapter(get_schema)) + make_endpoint("api/schema", HTTP_GET, json_adapter(get_schema)) .set_auto_schema() .install(); diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index 9d5b547be5e..8e7161ec904 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -68,6 +68,13 @@ namespace ccf const std::string method_prefix; + struct OpenApiInfo + { + std::string title = "Empty title"; + std::string description = "Empty description"; + std::string document_version = "0.0.1"; + } openapi_info; + struct Metrics { size_t calls = 0; @@ -435,8 +442,6 @@ namespace ccf return templated; } - // TODO: Don't re-parse this here, set the parameters explicitly and - // individually static void add_query_parameters( nlohmann::json& document, const std::string& uri, diff --git a/src/node/rpc/member_frontend.h b/src/node/rpc/member_frontend.h index 0865e078a63..77de81af96e 100644 --- a/src/node/rpc/member_frontend.h +++ b/src/node/rpc/member_frontend.h @@ -760,7 +760,12 @@ namespace ccf node(node), share_manager(share_manager), tsr(network) - {} + { + openapi_info.title = "CCF Governance API"; + openapi_info.description = + "This API is used to submit and query proposals which affect CCF's " + "public governance tables."; + } void init_handlers(kv::Store& tables_) override { diff --git a/src/node/rpc/node_frontend.h b/src/node/rpc/node_frontend.h index d0c6e36d8bd..d7eec7538fc 100644 --- a/src/node/rpc/node_frontend.h +++ b/src/node/rpc/node_frontend.h @@ -140,7 +140,12 @@ namespace ccf get_actor_prefix(ActorsType::nodes), *network.tables), network(network), node(node) - {} + { + openapi_info.title = "CCF Public Node API"; + openapi_info.description = + "This API provides public, uncredentialed access to service and node " + "state."; + } void init_handlers(kv::Store& tables_) override { diff --git a/src/node/rpc/user_frontend.h b/src/node/rpc/user_frontend.h index 274c3f0fbda..fb290014b9d 100644 --- a/src/node/rpc/user_frontend.h +++ b/src/node/rpc/user_frontend.h @@ -28,7 +28,9 @@ namespace ccf h, tables.get(Tables::USER_CLIENT_SIGNATURES)), users(tables.get(Tables::USERS)) - {} + { + h.openapi_info.title = "CCF Application API"; + } void open() override { From 7c9b98684cf886af8763b34210d07cd35688d3a5 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Wed, 23 Sep 2020 16:20:35 +0100 Subject: [PATCH 50/53] Update supports_method --- tests/suite/test_requirements.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/suite/test_requirements.py b/tests/suite/test_requirements.py index eff753af1ac..38f963e38fb 100644 --- a/tests/suite/test_requirements.py +++ b/tests/suite/test_requirements.py @@ -48,12 +48,18 @@ def wrapper(network, args, *nargs, **kwargs): def supports_methods(*methods): + def remove_prefix(s, prefix): + if s.startswith(prefix): + return s[len(prefix):] + return s + def check(network, args, *nargs, **kwargs): primary, _ = network.find_primary() with primary.client("user0") as c: response = c.get("/app/api") - supported_methods = response.body.json()["endpoints"] - missing = {*methods}.difference([sm["path"] for sm in supported_methods]) + supported_methods = response.body.json()["paths"] + LOG.warning(f"Supported methods are: {supported_methods.keys()}") + missing = {*methods}.difference([remove_prefix(key, "/") for key in supported_methods.keys()]) if missing: concat = ", ".join(missing) raise TestRequirementsNotMet(f"Missing required methods: {concat}") From 9241b616a95c2180145efc68199b9309ea6e7562 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Wed, 23 Sep 2020 17:10:46 +0100 Subject: [PATCH 51/53] Format --- src/apps/js_generic/js_generic.cpp | 3 ++- src/apps/lua_generic/lua_generic.cpp | 3 ++- src/node/rpc/endpoint_registry.h | 2 +- tests/suite/test_requirements.py | 6 ++++-- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/apps/js_generic/js_generic.cpp b/src/apps/js_generic/js_generic.cpp index c572c0272df..9dc8e17494b 100644 --- a/src/apps/js_generic/js_generic.cpp +++ b/src/apps/js_generic/js_generic.cpp @@ -655,7 +655,8 @@ namespace ccfapp set_default(default_handler); } - static std::pair split_script_key(const std::string& key) + static std::pair split_script_key( + const std::string& key) { size_t s = key.find(' '); if (s != std::string::npos) diff --git a/src/apps/lua_generic/lua_generic.cpp b/src/apps/lua_generic/lua_generic.cpp index ab8f19dd767..d24c28c8eec 100644 --- a/src/apps/lua_generic/lua_generic.cpp +++ b/src/apps/lua_generic/lua_generic.cpp @@ -185,7 +185,8 @@ namespace ccfapp set_default(json_adapter(default_handler)); } - static std::pair split_script_key(const std::string& key) + static std::pair split_script_key( + const std::string& key) { size_t s = key.find(' '); if (s != std::string::npos) diff --git a/src/node/rpc/endpoint_registry.h b/src/node/rpc/endpoint_registry.h index 8e7161ec904..f91a9d70f55 100644 --- a/src/node/rpc/endpoint_registry.h +++ b/src/node/rpc/endpoint_registry.h @@ -629,7 +629,7 @@ namespace ccf virtual nlohmann::json get_endpoint_schema(kv::Tx&, const GetSchema::In& in) { auto j = nlohmann::json::object(); - + const auto it = fully_qualified_endpoints.find(in.method); if (it != fully_qualified_endpoints.end()) { diff --git a/tests/suite/test_requirements.py b/tests/suite/test_requirements.py index 38f963e38fb..a73516fd7a1 100644 --- a/tests/suite/test_requirements.py +++ b/tests/suite/test_requirements.py @@ -50,7 +50,7 @@ def wrapper(network, args, *nargs, **kwargs): def supports_methods(*methods): def remove_prefix(s, prefix): if s.startswith(prefix): - return s[len(prefix):] + return s[len(prefix) :] return s def check(network, args, *nargs, **kwargs): @@ -59,7 +59,9 @@ def check(network, args, *nargs, **kwargs): response = c.get("/app/api") supported_methods = response.body.json()["paths"] LOG.warning(f"Supported methods are: {supported_methods.keys()}") - missing = {*methods}.difference([remove_prefix(key, "/") for key in supported_methods.keys()]) + missing = {*methods}.difference( + [remove_prefix(key, "/") for key in supported_methods.keys()] + ) if missing: concat = ", ".join(missing) raise TestRequirementsNotMet(f"Missing required methods: {concat}") From 56cf98b3496fe8516118d5aa6e6ab3a26b7997bf Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Thu, 24 Sep 2020 10:15:53 +0100 Subject: [PATCH 52/53] Use is_arithmetic --- src/ds/openapi.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/ds/openapi.h b/src/ds/openapi.h index e74a8b131a5..323ea4b20ea 100644 --- a/src/ds/openapi.h +++ b/src/ds/openapi.h @@ -260,13 +260,7 @@ namespace ds document, ds::json::schema_name(), schema); } else if constexpr ( - std::is_same::value || std::is_same::value || - std::is_same::value || std::is_same::value || - std::is_same::value || - std::is_same::value || std::is_same::value || - std::is_same::value || std::is_same::value || - std::is_same::value || std::is_same::value || - std::is_same::value || + std::is_same::value || std::is_arithmetic_v || std::is_same::value || std::is_same::value) { From 54c2c6cfed31911e08b37c0dbd16e01dc7bf39ba Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Thu, 24 Sep 2020 10:46:24 +0100 Subject: [PATCH 53/53] Don't print in test --- src/ds/test/openapi.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/ds/test/openapi.cpp b/src/ds/test/openapi.cpp index e3be4971c56..00f1a7186c3 100644 --- a/src/ds/test/openapi.cpp +++ b/src/ds/test/openapi.cpp @@ -115,8 +115,6 @@ TEST_CASE("Simple custom types") http::headervalues::contenttype::JSON); required_doc_elements(doc); - - print_doc("SIMPLE", doc); } struct Bar @@ -213,6 +211,4 @@ TEST_CASE("Complex custom types") http::headervalues::contenttype::JSON); required_doc_elements(doc); - - print_doc("COMPLEX", doc); } \ No newline at end of file