blob: b0a1d9703d1faae8e9cb80f5359d09cb5b5fcdfd [file] [log] [blame]
#pragma once
#include "logging.hpp"
#include <boost/beast/http/fields.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/url/parse.hpp>
#include <boost/url/url.hpp>
#include <nlohmann/json.hpp>
#include <memory>
#include <string>
#include <vector>
namespace persistent_data
{
struct UserSubscription
{
// Represents a Redfish EventDestination instance
std::string id;
boost::urls::url destinationUrl;
std::string protocol;
bool verifyCertificate = true;
std::string retryPolicy;
std::string customText;
std::string eventFormatType;
std::string subscriptionType;
std::vector<std::string> registryMsgIds;
std::vector<std::string> registryPrefixes;
std::vector<std::string> resourceTypes;
boost::beast::http::fields httpHeaders;
std::vector<std::string> metricReportDefinitions;
std::vector<std::string> originResources;
static std::optional<UserSubscription> fromJson(
const nlohmann::json::object_t& j, const bool loadFromOldConfig = false)
{
UserSubscription subvalue;
for (const auto& element : j)
{
if (element.first == "Id")
{
const std::string* value =
element.second.get_ptr<const std::string*>();
if (value == nullptr)
{
continue;
}
subvalue.id = *value;
}
else if (element.first == "Destination")
{
const std::string* value =
element.second.get_ptr<const std::string*>();
if (value == nullptr)
{
continue;
}
boost::system::result<boost::urls::url> url =
boost::urls::parse_absolute_uri(*value);
if (!url)
{
continue;
}
subvalue.destinationUrl = std::move(*url);
}
else if (element.first == "Protocol")
{
const std::string* value =
element.second.get_ptr<const std::string*>();
if (value == nullptr)
{
continue;
}
subvalue.protocol = *value;
}
else if (element.first == "VerifyCertificate")
{
const bool* value = element.second.get_ptr<const bool*>();
if (value == nullptr)
{
continue;
}
subvalue.verifyCertificate = *value;
}
else if (element.first == "DeliveryRetryPolicy")
{
const std::string* value =
element.second.get_ptr<const std::string*>();
if (value == nullptr)
{
continue;
}
subvalue.retryPolicy = *value;
}
else if (element.first == "Context")
{
const std::string* value =
element.second.get_ptr<const std::string*>();
if (value == nullptr)
{
continue;
}
subvalue.customText = *value;
}
else if (element.first == "EventFormatType")
{
const std::string* value =
element.second.get_ptr<const std::string*>();
if (value == nullptr)
{
continue;
}
subvalue.eventFormatType = *value;
}
else if (element.first == "SubscriptionType")
{
const std::string* value =
element.second.get_ptr<const std::string*>();
if (value == nullptr)
{
continue;
}
subvalue.subscriptionType = *value;
}
else if (element.first == "MessageIds")
{
const nlohmann::json::array_t* obj =
element.second.get_ptr<const nlohmann::json::array_t*>();
if (obj == nullptr)
{
continue;
}
for (const auto& val : *obj)
{
const std::string* value =
val.get_ptr<const std::string*>();
if (value == nullptr)
{
continue;
}
subvalue.registryMsgIds.emplace_back(*value);
}
}
else if (element.first == "RegistryPrefixes")
{
const nlohmann::json::array_t* obj =
element.second.get_ptr<const nlohmann::json::array_t*>();
if (obj == nullptr)
{
continue;
}
for (const auto& val : *obj)
{
const std::string* value =
val.get_ptr<const std::string*>();
if (value == nullptr)
{
continue;
}
subvalue.registryPrefixes.emplace_back(*value);
}
}
else if (element.first == "ResourceTypes")
{
const nlohmann::json::array_t* obj =
element.second.get_ptr<const nlohmann::json::array_t*>();
if (obj == nullptr)
{
continue;
}
for (const auto& val : *obj)
{
const std::string* value =
val.get_ptr<const std::string*>();
if (value == nullptr)
{
continue;
}
subvalue.resourceTypes.emplace_back(*value);
}
}
else if (element.first == "HttpHeaders")
{
const nlohmann::json::object_t* obj =
element.second.get_ptr<const nlohmann::json::object_t*>();
if (obj == nullptr)
{
continue;
}
for (const auto& val : *obj)
{
const std::string* value =
val.second.get_ptr<const std::string*>();
if (value == nullptr)
{
BMCWEB_LOG_ERROR("Failed to parse value for key{}",
val.first);
continue;
}
subvalue.httpHeaders.set(val.first, *value);
}
}
else if (element.first == "MetricReportDefinitions")
{
const nlohmann::json::array_t* obj =
element.second.get_ptr<const nlohmann::json::array_t*>();
if (obj == nullptr)
{
continue;
}
for (const auto& val : *obj)
{
const std::string* value =
val.get_ptr<const std::string*>();
if (value == nullptr)
{
continue;
}
subvalue.metricReportDefinitions.emplace_back(*value);
}
}
else if (element.first == "OriginResources")
{
const nlohmann::json::array_t* obj =
element.second.get_ptr<const nlohmann::json::array_t*>();
if (obj == nullptr)
{
continue;
}
for (const auto& val : *obj)
{
const std::string* value =
val.get_ptr<const std::string*>();
if (value == nullptr)
{
continue;
}
subvalue.originResources.emplace_back(*value);
}
}
else
{
BMCWEB_LOG_ERROR(
"Got unexpected property reading persistent file: {}",
element.first);
continue;
}
}
if ((subvalue.id.empty() && !loadFromOldConfig) ||
subvalue.destinationUrl.empty() || subvalue.protocol.empty() ||
subvalue.retryPolicy.empty() || subvalue.eventFormatType.empty() ||
subvalue.subscriptionType.empty())
{
BMCWEB_LOG_ERROR("Subscription missing required field "
"information, refusing to restore");
return std::nullopt;
}
return subvalue;
}
};
struct EventServiceConfig
{
bool enabled = true;
uint32_t retryAttempts = 3;
uint32_t retryTimeoutInterval = 30;
void fromJson(const nlohmann::json::object_t& j)
{
for (const auto& element : j)
{
if (element.first == "ServiceEnabled")
{
const bool* value = element.second.get_ptr<const bool*>();
if (value == nullptr)
{
continue;
}
enabled = *value;
}
else if (element.first == "DeliveryRetryAttempts")
{
const uint64_t* value =
element.second.get_ptr<const uint64_t*>();
if ((value == nullptr) ||
(*value > std::numeric_limits<uint32_t>::max()))
{
continue;
}
retryAttempts = static_cast<uint32_t>(*value);
}
else if (element.first == "DeliveryRetryIntervalSeconds")
{
const uint64_t* value =
element.second.get_ptr<const uint64_t*>();
if ((value == nullptr) ||
(*value > std::numeric_limits<uint32_t>::max()))
{
continue;
}
retryTimeoutInterval = static_cast<uint32_t>(*value);
}
}
}
};
class EventServiceStore
{
public:
boost::container::flat_map<std::string, std::shared_ptr<UserSubscription>>
subscriptionsConfigMap;
EventServiceConfig eventServiceConfig;
static EventServiceStore& getInstance()
{
static EventServiceStore eventServiceStore;
return eventServiceStore;
}
EventServiceConfig& getEventServiceConfig()
{
return eventServiceConfig;
}
};
} // namespace persistent_data