blob: ab460b84af7cb21da793231c5985c2b1ff5ba97a [file] [log] [blame]
#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