141 auto get_constitution = [&](
auto& ctx,
ApiVersion api_version) {
148 auto constitution_handle =
149 ctx.tx.template ro<ccf::Constitution>(ccf::Tables::CONSTITUTION);
150 auto constitution = constitution_handle->get();
152 if (!constitution.has_value())
154 detail::set_gov_error(
156 HTTP_STATUS_NOT_FOUND,
157 ccf::errors::ResourceNotFound,
158 "Constitution not found");
163 ctx.rpc_ctx->set_response_status(HTTP_STATUS_OK);
164 ctx.rpc_ctx->set_response_body(std::move(constitution.value()));
165 ctx.rpc_ctx->set_response_header(
166 ccf::http::headers::CONTENT_TYPE,
167 http::headervalues::contenttype::JAVASCRIPT);
174 "/service/constitution",
181 auto get_service_info = [&](
auto& ctx,
ApiVersion api_version) {
188 auto response_body = nlohmann::json::object();
190 auto service_info_handle =
191 ctx.tx.template ro<ccf::Service>(ccf::Tables::SERVICE);
192 auto service_info = service_info_handle->get();
194 if (!service_info.has_value())
196 detail::set_gov_error(
198 HTTP_STATUS_NOT_FOUND,
199 ccf::errors::ResourceNotFound,
200 "Service info not yet available");
204 response_body[
"status"] = service_info->status;
205 response_body[
"certificate"] = service_info->cert.str();
206 response_body[
"recoveryCount"] =
207 service_info->recovery_count.value_or(0);
209 if (service_info->current_service_create_txid.has_value())
211 response_body[
"creationTransactionId"] =
212 service_info->current_service_create_txid.value();
216 GOV_INFO_FMT(
"No recorded current_service_create_txid");
219 if (service_info->previous_service_identity_version.has_value())
222 service_info->previous_service_identity_version.value();
227 response_body[
"previousServiceCreationTransactionId"] =
231 response_body[
"serviceData"] = service_info->service_data;
234 auto config_handle = ctx.tx.template ro<ccf::Configuration>(
235 ccf::Tables::CONFIGURATION);
237 auto config = config_handle->get();
238 if (config.has_value())
240 auto configuration = nlohmann::json::object();
241 configuration[
"recoveryThreshold"] = config->recovery_threshold;
242 configuration[
"maximumNodeCertificateValidityDays"] =
243 config->maximum_node_certificate_validity_days.value_or(
244 ccf::default_node_cert_validity_period_days);
245 configuration[
"maximumServiceCertificateValidityDays"] =
246 config->maximum_service_certificate_validity_days.value_or(
247 ccf::default_service_cert_validity_period_days);
248 configuration[
"recentCoseProposalsWindowSize"] =
249 config->recent_cose_proposals_window_size.value_or(
250 ccf::default_recent_cose_proposals_window_size);
251 response_body[
"configuration"] = configuration;
259 ctx.rpc_ctx->set_response_json(response_body, HTTP_STATUS_OK);
273 auto get_javascript_app = [&](
auto& ctx,
ApiVersion api_version) {
280 auto response_body = nlohmann::json::object();
284 auto endpoints = nlohmann::json::object();
286 auto js_endpoints_handle =
287 ctx.tx.template ro<ccf::endpoints::EndpointsMap>(
288 ccf::endpoints::Tables::ENDPOINTS);
289 js_endpoints_handle->foreach(
294 endpoints.emplace(key.uri_path, nlohmann::json::object());
295 auto& operations = *ib.first;
297 auto operation = nlohmann::json::object();
299 operation[
"jsModule"] = properties.
js_module;
301 operation[
"forwardingRequired"] =
304 auto policies = nlohmann::json::array();
307 policies.push_back(policy);
309 operation[
"authnPolicies"] = policies;
311 operation[
"mode"] = properties.
mode;
312 operation[
"openApi"] = properties.
openapi;
314 operations[key.verb.c_str()] = operation;
319 response_body[
"endpoints"] = endpoints;
322 ctx.rpc_ctx->set_response_json(response_body, HTTP_STATUS_OK);
329 "/service/javascript-app",
333 .set_openapi_hidden(
true)
336 auto get_javascript_modules = [&](
auto& ctx,
ApiVersion api_version) {
343 auto response_body = nlohmann::json::object();
346 auto module_list = nlohmann::json::array();
348 auto modules_handle =
349 ctx.tx.template ro<ccf::Modules>(ccf::Tables::MODULES);
351 modules_handle->foreach_key(
352 [&module_list](
const std::string& module_name) {
353 auto entry = nlohmann::json::object();
354 entry[
"moduleName"] = module_name;
355 module_list.push_back(entry);
359 response_body[
"value"] = module_list;
362 ctx.rpc_ctx->set_response_json(response_body, HTTP_STATUS_OK);
369 "/service/javascript-modules",
373 .set_openapi_hidden(
true)
376 auto get_javascript_module_by_name =
384 std::string module_name;
388 ctx.rpc_ctx->get_request_path_params(),
393 detail::set_gov_error(
395 HTTP_STATUS_BAD_REQUEST,
396 ccf::errors::InvalidResourceName,
402 module_name = ::http::url_decode(module_name);
404 auto modules_handle =
405 ctx.tx.template ro<ccf::Modules>(ccf::Tables::MODULES);
406 auto module = modules_handle->get(module_name);
408 if (!module.has_value())
410 detail::set_gov_error(
412 HTTP_STATUS_NOT_FOUND,
413 ccf::errors::ResourceNotFound,
414 fmt::format(
"Module {} does not exist.", module_name));
419 ctx.rpc_ctx->set_response_status(HTTP_STATUS_OK);
420 ctx.rpc_ctx->set_response_body(std::move(module.value()));
421 ctx.rpc_ctx->set_response_header(
422 ccf::http::headers::CONTENT_TYPE,
423 http::headervalues::contenttype::JAVASCRIPT);
430 "/service/javascript-modules/{moduleName}",
437 auto get_join_policy = [&](
auto& ctx,
ApiVersion api_version) {
444 auto response_body = nlohmann::json::object();
448 auto sgx_policy = nlohmann::json::object();
450 auto sgx_measurements = nlohmann::json::array();
451 auto code_ids_handle =
452 ctx.tx.template ro<ccf::CodeIDs>(ccf::Tables::NODE_CODE_IDS);
453 code_ids_handle->foreach(
459 sgx_measurements.push_back(measurement.hex_str());
463 sgx_policy[
"measurements"] = sgx_measurements;
465 response_body[
"sgx"] = sgx_policy;
470 auto snp_policy = nlohmann::json::object();
472 auto snp_measurements = nlohmann::json::array();
473 auto measurements_handle = ctx.tx.template ro<ccf::SnpMeasurements>(
474 ccf::Tables::NODE_SNP_MEASUREMENTS);
475 measurements_handle->foreach(
481 snp_measurements.push_back(measurement.hex_str());
485 snp_policy[
"measurements"] = snp_measurements;
487 auto snp_host_data = nlohmann::json::object();
488 auto host_data_handle =
489 ctx.tx.template ro<ccf::SnpHostDataMap>(ccf::Tables::HOST_DATA);
490 host_data_handle->foreach(
493 snp_host_data[host_data.
hex_str()] = metadata;
496 snp_policy[
"hostData"] = snp_host_data;
498 auto snp_endorsements = nlohmann::json::object();
499 auto endorsements_handle =
500 ctx.tx.template ro<ccf::SNPUVMEndorsements>(
501 ccf::Tables::NODE_SNP_UVM_ENDORSEMENTS);
502 endorsements_handle->foreach(
506 snp_endorsements[did] = feed_info;
509 snp_policy[
"uvmEndorsements"] = snp_endorsements;
511 response_body[
"snp"] = snp_policy;
514 ctx.rpc_ctx->set_response_json(response_body, HTTP_STATUS_OK);
521 "/service/join-policy",
528 auto get_jwk = [&](
auto& ctx,
ApiVersion api_version) {
535 auto response_body = nlohmann::json::object();
539 auto issuers = nlohmann::json::object();
541 auto jwt_issuers_handle =
542 ctx.tx.template ro<ccf::JwtIssuers>(ccf::Tables::JWT_ISSUERS);
543 jwt_issuers_handle->foreach(
547 auto jwt_issuer = nlohmann::json::object();
549 jwt_issuer[
"keyFilter"] = metadata.
key_filter;
554 jwt_issuer[
"keyPolicy"] = metadata.
key_policy.value();
559 jwt_issuer[
"caCertBundleName"] =
563 issuers[issuer_id] = jwt_issuer;
567 response_body[
"issuers"] = issuers;
572 auto keys = nlohmann::json::object();
574 auto jwt_keys_handle =
575 ctx.tx.template ro<ccf::JwtPublicSigningKeys>(
576 ccf::Tables::JWT_PUBLIC_SIGNING_KEYS_METADATA);
578 jwt_keys_handle->foreach(
581 const std::vector<OpenIDJWKMetadata>& v) {
582 auto keys_info = nlohmann::json::array();
583 for (
const auto& metadata : v)
585 auto info = nlohmann::json::object();
588 const auto cert_pem =
590 info[
"certificate"] = cert_pem.str();
592 info[
"issuer"] = metadata.issuer;
593 info[
"constraint"] = metadata.constraint;
595 keys_info.push_back(info);
602 response_body[
"keys"] = keys;
607 auto cert_bundles = nlohmann::json::object();
609 auto cert_bundles_handle =
610 ctx.tx.template ro<ccf::CACertBundlePEMs>(
611 ccf::Tables::CA_CERT_BUNDLE_PEMS);
612 cert_bundles_handle->foreach([&cert_bundles](
613 const std::string& bundle_name,
614 const std::string& bundle_value) {
615 cert_bundles[bundle_name] = bundle_value;
619 response_body[
"caCertBundles"] = cert_bundles;
622 ctx.rpc_ctx->set_response_json(response_body, HTTP_STATUS_OK);
636 auto get_members = [&](
auto& ctx,
ApiVersion api_version) {
643 auto response_body = nlohmann::json::object();
646 auto member_list = nlohmann::json::array();
648 auto member_info_handle =
649 ctx.tx.template ro<ccf::MemberInfo>(ccf::Tables::MEMBER_INFO);
650 auto member_certs_handle =
651 ctx.tx.template ro<ccf::MemberCerts>(ccf::Tables::MEMBER_CERTS);
652 auto member_enc_keys_handle =
653 ctx.tx.template ro<ccf::MemberPublicEncryptionKeys>(
654 ccf::Tables::MEMBER_ENCRYPTION_PUBLIC_KEYS);
656 member_info_handle->foreach(
657 [&member_list, member_certs_handle, member_enc_keys_handle](
664 member_enc_keys_handle));
668 response_body[
"value"] = member_list;
671 ctx.rpc_ctx->set_response_json(response_body, HTTP_STATUS_OK);
685 auto get_member_by_id = [&](
auto& ctx,
ApiVersion api_version) {
698 auto member_info_handle =
699 ctx.tx.template ro<ccf::MemberInfo>(ccf::Tables::MEMBER_INFO);
700 const auto member_info = member_info_handle->get(member_id);
701 if (!member_info.has_value())
703 detail::set_gov_error(
705 HTTP_STATUS_NOT_FOUND,
706 ccf::errors::ResourceNotFound,
707 fmt::format(
"Member {} does not exist.", member_id));
711 auto member_certs_handle =
712 ctx.tx.template ro<ccf::MemberCerts>(ccf::Tables::MEMBER_CERTS);
713 auto member_enc_keys_handle =
714 ctx.tx.template ro<ccf::MemberPublicEncryptionKeys>(
715 ccf::Tables::MEMBER_ENCRYPTION_PUBLIC_KEYS);
721 member_enc_keys_handle);
723 ctx.rpc_ctx->set_response_json(member, HTTP_STATUS_OK);
730 "/service/members/{memberId}",
737 auto get_users = [&](
auto& ctx,
ApiVersion api_version) {
744 auto response_body = nlohmann::json::object();
747 auto user_list = nlohmann::json::array();
749 auto user_certs_handle =
750 ctx.tx.template ro<ccf::UserCerts>(ccf::Tables::USER_CERTS);
751 auto user_info_handle =
752 ctx.tx.template ro<ccf::UserInfo>(ccf::Tables::USER_INFO);
754 user_certs_handle->foreach([&user_list, user_info_handle](
762 response_body[
"value"] = user_list;
765 ctx.rpc_ctx->set_response_json(response_body, HTTP_STATUS_OK);
779 auto get_user_by_id = [&](
auto& ctx,
ApiVersion api_version) {
792 auto user_certs_handle =
793 ctx.tx.template ro<ccf::UserCerts>(ccf::Tables::USER_CERTS);
795 const auto user_cert = user_certs_handle->get(user_id);
796 if (!user_cert.has_value())
798 detail::set_gov_error(
800 HTTP_STATUS_NOT_FOUND,
801 ccf::errors::ResourceNotFound,
802 fmt::format(
"User {} does not exist.", user_id));
806 auto user_info_handle =
807 ctx.tx.template ro<ccf::UserInfo>(ccf::Tables::USER_INFO);
810 user_id, user_cert.
value(), user_info_handle);
812 ctx.rpc_ctx->set_response_json(user, HTTP_STATUS_OK);
819 "/service/users/{userId}",
826 auto get_nodes = [&](
auto& ctx,
ApiVersion api_version) {
833 auto response_body = nlohmann::json::object();
836 auto node_list = nlohmann::json::array();
838 auto node_info_handle =
839 ctx.tx.template ro<ccf::Nodes>(ccf::Tables::NODES);
840 auto node_endorsed_certs_handle =
841 ctx.tx.template ro<ccf::NodeEndorsedCertificates>(
842 ccf::Tables::NODE_ENDORSED_CERTIFICATES);
844 node_info_handle->foreach(
845 [&node_list, node_endorsed_certs_handle](
848 node_id, node_info, node_endorsed_certs_handle));
852 response_body[
"value"] = node_list;
855 ctx.rpc_ctx->set_response_json(response_body, HTTP_STATUS_OK);
869 auto get_node_by_id = [&](
auto& ctx,
ApiVersion api_version) {
882 auto node_info_handle =
883 ctx.tx.template ro<ccf::Nodes>(ccf::Tables::NODES);
884 const auto node_info = node_info_handle->get(node_id);
885 if (!node_info.has_value())
887 detail::set_gov_error(
889 HTTP_STATUS_NOT_FOUND,
890 ccf::errors::ResourceNotFound,
891 fmt::format(
"Node {} does not exist.", node_id));
895 auto node_endorsed_certs_handle =
896 ctx.tx.template ro<ccf::NodeEndorsedCertificates>(
897 ccf::Tables::NODE_ENDORSED_CERTIFICATES);
899 node_id, node_info.
value(), node_endorsed_certs_handle);
901 ctx.rpc_ctx->set_response_json(node, HTTP_STATUS_OK);
908 "/service/nodes/{nodeId}",