blob: f7f03ab5c40cf173cf8c3079984b2fea6c3f115d [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>
namespace persistent_data
{
struct UserSubscription
{
std::string id;
boost::urls::url destinationUrl;
std::string protocol;
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;
static std::shared_ptr<UserSubscription>
fromJson(const nlohmann::json::object_t& j,
const bool loadFromOldConfig = false)
{
std::shared_ptr<UserSubscription> subvalue =
std::make_shared<UserSubscription>();
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 == "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
{
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 nullptr;
}
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