| #include "subscription_backend_impl.hpp" |
| |
| #include <memory> |
| #include <string> |
| #include <system_error> // NOLINT |
| #include <unordered_set> |
| #include <utility> |
| #include <vector> |
| |
| #include "absl/log/die_if_null.h" |
| #include "absl/memory/memory.h" |
| #include "absl/status/status.h" |
| #include "absl/status/statusor.h" |
| #include "absl/strings/string_view.h" |
| #include "boost/beast/http/message.hpp" //NOLINT |
| #include "boost/beast/http/string_body.hpp" //NOLINT |
| #include "boost/beast/http/verb.hpp" // NOLINT |
| #include "subscription.h" |
| #include "g3/macros.h" |
| #include "nlohmann/json.hpp" |
| #include "app.hpp" |
| |
| namespace milotic { |
| |
| namespace { |
| |
| // Create Internal Request to query given `url`. |
| absl::StatusOr<crow::Request> CreateInternalRedfishRequest( |
| absl::string_view url, boost::beast::http::verb method, |
| const std::unordered_set<std::string>& peer_privileges) { |
| boost::beast::http::request<boost::beast::http::string_body> boost_request; |
| boost_request.target(url); |
| boost_request.method(method); |
| std::error_code error; |
| crow::Request crow_request(boost_request, error); |
| if (error) { |
| return absl::InternalError("Error creating crow_request."); |
| } |
| |
| crow_request.fromGrpc = true; |
| // At this moment, peer is authenticated for sure and BMC must have trust |
| // bundle. These have been checked in the Subscription RPC handler. |
| crow_request.peer_authenticated = true; |
| crow_request.with_trust_bundle = true; |
| crow_request.peer_privileges = peer_privileges; |
| return crow_request; |
| } |
| |
| } // namespace |
| |
| std::unique_ptr<BmcWebBackend> BmcWebBackend::Create(App* app) { |
| return absl::WrapUnique(new BmcWebBackend(*ABSL_DIE_IF_NULL(app))); |
| } |
| |
| absl::Status BmcWebBackend::Query( |
| absl::string_view url, QueryCallback&& query_callback, |
| const std::unordered_set<std::string>& peer_privileges) { |
| // Strand is not needed for subscriptions. |
| auto async_resp = std::make_shared<bmcweb::AsyncResp>(nullptr); |
| async_resp->response_type = |
| bmcweb::AsyncResp::ResponseType::kOriginOfCondition; |
| ECCLESIA_ASSIGN_OR_RETURN( |
| crow::Request crow_request, |
| CreateInternalRedfishRequest(url, boost::beast::http::verb::get, |
| peer_privileges)); |
| async_resp->res.setCompleteRequestHandler( |
| [query_callback(std::move(query_callback))](crow::Response& res) { |
| if (!res.stringResponse) { |
| query_callback(absl::InternalError("HTTP response is empty!"), {}); |
| return; |
| } |
| query_callback(absl::OkStatus(), res.jsonValue); |
| }); |
| |
| app_.handle(crow_request, async_resp); |
| return absl::OkStatus(); |
| } |
| |
| absl::Status BmcWebBackend::Subscribe( |
| absl::string_view url, SubscribeCallback&& callback, |
| const std::unordered_set<std::string>& peer_privileges) { |
| // Strand is not needed for subscriptions. |
| auto async_resp = std::make_shared<bmcweb::AsyncResp>(nullptr); |
| async_resp->response_type = bmcweb::AsyncResp::ResponseType::kSubscription; |
| ECCLESIA_ASSIGN_OR_RETURN( |
| crow::Request crow_request, |
| CreateInternalRedfishRequest(url, boost::beast::http::verb::get, |
| peer_privileges)); |
| async_resp->res.setCompleteRequestHandler( |
| [subscribe_callback(std::move(callback))](crow::Response& res) { |
| if (res.eventSourceIds.empty()) { |
| subscribe_callback( |
| absl::InternalError("EventSourceIds are not populated!"), {}); |
| return; |
| } |
| subscribe_callback(absl::OkStatus(), res.eventSourceIds); |
| }); |
| app_.handle(crow_request, async_resp); |
| return absl::OkStatus(); |
| } |
| |
| } // namespace milotic |