blob: ffbb3899a855af9d0198c133e4dd3eb6f39d5d5f [file] [log] [blame]
JunLin Chen28afb492021-02-24 17:13:29 +08001#pragma once
2#include "logging.hpp"
3
Ed Tanous601c71a2021-09-08 16:40:12 -07004#include <boost/beast/http/fields.hpp>
JunLin Chen28afb492021-02-24 17:13:29 +08005#include <boost/container/flat_map.hpp>
Ed Tanousa716aa72023-08-01 11:35:53 -07006#include <boost/url/parse.hpp>
Ed Tanous4a7fbef2024-04-06 16:03:49 -07007#include <boost/url/url.hpp>
JunLin Chen28afb492021-02-24 17:13:29 +08008#include <nlohmann/json.hpp>
9
Myung Bae5064a252024-10-04 09:34:25 -070010#include <limits>
Myung Bae56ba3862024-10-10 17:09:37 -070011#include <memory>
12#include <string>
13#include <vector>
14
JunLin Chen28afb492021-02-24 17:13:29 +080015namespace persistent_data
16{
17
18struct UserSubscription
19{
Ed Tanous4b712a22023-08-02 12:56:52 -070020 // Represents a Redfish EventDestination instance
JunLin Chen28afb492021-02-24 17:13:29 +080021 std::string id;
Ed Tanousa716aa72023-08-01 11:35:53 -070022 boost::urls::url destinationUrl;
JunLin Chen28afb492021-02-24 17:13:29 +080023 std::string protocol;
Ed Tanous19bb3622024-07-05 10:07:40 -050024 bool verifyCertificate = true;
JunLin Chen28afb492021-02-24 17:13:29 +080025 std::string retryPolicy;
Myung Bae5064a252024-10-04 09:34:25 -070026 bool sendHeartbeat = false;
27 // This value of hbIntervalMinutes is just a reasonable default value and
28 // most clients will update it if sendHeartbeat is turned on
29 uint64_t hbIntervalMinutes = 10;
JunLin Chen28afb492021-02-24 17:13:29 +080030 std::string customText;
31 std::string eventFormatType;
32 std::string subscriptionType;
33 std::vector<std::string> registryMsgIds;
34 std::vector<std::string> registryPrefixes;
35 std::vector<std::string> resourceTypes;
Ed Tanous601c71a2021-09-08 16:40:12 -070036 boost::beast::http::fields httpHeaders;
JunLin Chen28afb492021-02-24 17:13:29 +080037 std::vector<std::string> metricReportDefinitions;
Ed Tanousa14c9112024-09-04 10:46:47 -070038 std::vector<std::string> originResources;
JunLin Chen28afb492021-02-24 17:13:29 +080039
Ed Tanous4b712a22023-08-02 12:56:52 -070040 static std::optional<UserSubscription> fromJson(
Patrick Williamsbd79bce2024-08-16 15:22:20 -040041 const nlohmann::json::object_t& j, const bool loadFromOldConfig = false)
JunLin Chen28afb492021-02-24 17:13:29 +080042 {
Ed Tanous4b712a22023-08-02 12:56:52 -070043 UserSubscription subvalue;
Ed Tanous0bdda662023-08-03 17:27:34 -070044 for (const auto& element : j)
JunLin Chen28afb492021-02-24 17:13:29 +080045 {
Ed Tanous0bdda662023-08-03 17:27:34 -070046 if (element.first == "Id")
JunLin Chen28afb492021-02-24 17:13:29 +080047 {
48 const std::string* value =
Ed Tanous0bdda662023-08-03 17:27:34 -070049 element.second.get_ptr<const std::string*>();
JunLin Chen28afb492021-02-24 17:13:29 +080050 if (value == nullptr)
51 {
52 continue;
53 }
Ed Tanous4b712a22023-08-02 12:56:52 -070054 subvalue.id = *value;
JunLin Chen28afb492021-02-24 17:13:29 +080055 }
Ed Tanous0bdda662023-08-03 17:27:34 -070056 else if (element.first == "Destination")
JunLin Chen28afb492021-02-24 17:13:29 +080057 {
58 const std::string* value =
Ed Tanous0bdda662023-08-03 17:27:34 -070059 element.second.get_ptr<const std::string*>();
JunLin Chen28afb492021-02-24 17:13:29 +080060 if (value == nullptr)
61 {
62 continue;
63 }
Ed Tanous6fd29552023-10-04 09:40:14 -070064 boost::system::result<boost::urls::url> url =
Ed Tanousa716aa72023-08-01 11:35:53 -070065 boost::urls::parse_absolute_uri(*value);
66 if (!url)
67 {
68 continue;
69 }
Ed Tanous4b712a22023-08-02 12:56:52 -070070 subvalue.destinationUrl = std::move(*url);
JunLin Chen28afb492021-02-24 17:13:29 +080071 }
Ed Tanous0bdda662023-08-03 17:27:34 -070072 else if (element.first == "Protocol")
JunLin Chen28afb492021-02-24 17:13:29 +080073 {
74 const std::string* value =
Ed Tanous0bdda662023-08-03 17:27:34 -070075 element.second.get_ptr<const std::string*>();
JunLin Chen28afb492021-02-24 17:13:29 +080076 if (value == nullptr)
77 {
78 continue;
79 }
Ed Tanous4b712a22023-08-02 12:56:52 -070080 subvalue.protocol = *value;
JunLin Chen28afb492021-02-24 17:13:29 +080081 }
Ed Tanous19bb3622024-07-05 10:07:40 -050082 else if (element.first == "VerifyCertificate")
83 {
84 const bool* value = element.second.get_ptr<const bool*>();
85 if (value == nullptr)
86 {
87 continue;
88 }
Ed Tanous4b712a22023-08-02 12:56:52 -070089 subvalue.verifyCertificate = *value;
Ed Tanous19bb3622024-07-05 10:07:40 -050090 }
Ed Tanous0bdda662023-08-03 17:27:34 -070091 else if (element.first == "DeliveryRetryPolicy")
JunLin Chen28afb492021-02-24 17:13:29 +080092 {
93 const std::string* value =
Ed Tanous0bdda662023-08-03 17:27:34 -070094 element.second.get_ptr<const std::string*>();
JunLin Chen28afb492021-02-24 17:13:29 +080095 if (value == nullptr)
96 {
97 continue;
98 }
Ed Tanous4b712a22023-08-02 12:56:52 -070099 subvalue.retryPolicy = *value;
JunLin Chen28afb492021-02-24 17:13:29 +0800100 }
Myung Bae5064a252024-10-04 09:34:25 -0700101 else if (element.first == "SendHeartbeat")
102 {
103 const bool* value = element.second.get_ptr<const bool*>();
104 if (value == nullptr)
105 {
106 continue;
107 }
108 subvalue.sendHeartbeat = *value;
109 }
110 else if (element.first == "HeartbeatIntervalMinutes")
111 {
112 const uint64_t* value =
113 element.second.get_ptr<const uint64_t*>();
114 if (value == nullptr || *value < 1 || *value > 65535)
115 {
116 continue;
117 }
118 subvalue.hbIntervalMinutes = *value;
119 }
Ed Tanous0bdda662023-08-03 17:27:34 -0700120 else if (element.first == "Context")
JunLin Chen28afb492021-02-24 17:13:29 +0800121 {
122 const std::string* value =
Ed Tanous0bdda662023-08-03 17:27:34 -0700123 element.second.get_ptr<const std::string*>();
JunLin Chen28afb492021-02-24 17:13:29 +0800124 if (value == nullptr)
125 {
126 continue;
127 }
Ed Tanous4b712a22023-08-02 12:56:52 -0700128 subvalue.customText = *value;
JunLin Chen28afb492021-02-24 17:13:29 +0800129 }
Ed Tanous0bdda662023-08-03 17:27:34 -0700130 else if (element.first == "EventFormatType")
JunLin Chen28afb492021-02-24 17:13:29 +0800131 {
132 const std::string* value =
Ed Tanous0bdda662023-08-03 17:27:34 -0700133 element.second.get_ptr<const std::string*>();
JunLin Chen28afb492021-02-24 17:13:29 +0800134 if (value == nullptr)
135 {
136 continue;
137 }
Ed Tanous4b712a22023-08-02 12:56:52 -0700138 subvalue.eventFormatType = *value;
JunLin Chen28afb492021-02-24 17:13:29 +0800139 }
Ed Tanous0bdda662023-08-03 17:27:34 -0700140 else if (element.first == "SubscriptionType")
JunLin Chen28afb492021-02-24 17:13:29 +0800141 {
142 const std::string* value =
Ed Tanous0bdda662023-08-03 17:27:34 -0700143 element.second.get_ptr<const std::string*>();
JunLin Chen28afb492021-02-24 17:13:29 +0800144 if (value == nullptr)
145 {
146 continue;
147 }
Ed Tanous4b712a22023-08-02 12:56:52 -0700148 subvalue.subscriptionType = *value;
JunLin Chen28afb492021-02-24 17:13:29 +0800149 }
Ed Tanous0bdda662023-08-03 17:27:34 -0700150 else if (element.first == "MessageIds")
JunLin Chen28afb492021-02-24 17:13:29 +0800151 {
Ed Tanous0bdda662023-08-03 17:27:34 -0700152 const nlohmann::json::array_t* obj =
153 element.second.get_ptr<const nlohmann::json::array_t*>();
154 if (obj == nullptr)
155 {
156 continue;
157 }
158 for (const auto& val : *obj)
JunLin Chen28afb492021-02-24 17:13:29 +0800159 {
160 const std::string* value =
Ed Tanous0bdda662023-08-03 17:27:34 -0700161 val.get_ptr<const std::string*>();
JunLin Chen28afb492021-02-24 17:13:29 +0800162 if (value == nullptr)
163 {
164 continue;
165 }
Ed Tanous4b712a22023-08-02 12:56:52 -0700166 subvalue.registryMsgIds.emplace_back(*value);
JunLin Chen28afb492021-02-24 17:13:29 +0800167 }
168 }
Ed Tanous0bdda662023-08-03 17:27:34 -0700169 else if (element.first == "RegistryPrefixes")
JunLin Chen28afb492021-02-24 17:13:29 +0800170 {
Ed Tanous0bdda662023-08-03 17:27:34 -0700171 const nlohmann::json::array_t* obj =
172 element.second.get_ptr<const nlohmann::json::array_t*>();
173 if (obj == nullptr)
174 {
175 continue;
176 }
177 for (const auto& val : *obj)
JunLin Chen28afb492021-02-24 17:13:29 +0800178 {
179 const std::string* value =
Ed Tanous0bdda662023-08-03 17:27:34 -0700180 val.get_ptr<const std::string*>();
JunLin Chen28afb492021-02-24 17:13:29 +0800181 if (value == nullptr)
182 {
183 continue;
184 }
Ed Tanous4b712a22023-08-02 12:56:52 -0700185 subvalue.registryPrefixes.emplace_back(*value);
JunLin Chen28afb492021-02-24 17:13:29 +0800186 }
187 }
Ed Tanous0bdda662023-08-03 17:27:34 -0700188 else if (element.first == "ResourceTypes")
JunLin Chen28afb492021-02-24 17:13:29 +0800189 {
Ed Tanous0bdda662023-08-03 17:27:34 -0700190 const nlohmann::json::array_t* obj =
191 element.second.get_ptr<const nlohmann::json::array_t*>();
192 if (obj == nullptr)
193 {
194 continue;
195 }
196 for (const auto& val : *obj)
JunLin Chen28afb492021-02-24 17:13:29 +0800197 {
198 const std::string* value =
Ed Tanous0bdda662023-08-03 17:27:34 -0700199 val.get_ptr<const std::string*>();
JunLin Chen28afb492021-02-24 17:13:29 +0800200 if (value == nullptr)
201 {
202 continue;
203 }
Ed Tanous4b712a22023-08-02 12:56:52 -0700204 subvalue.resourceTypes.emplace_back(*value);
JunLin Chen28afb492021-02-24 17:13:29 +0800205 }
206 }
Ed Tanous0bdda662023-08-03 17:27:34 -0700207 else if (element.first == "HttpHeaders")
JunLin Chen28afb492021-02-24 17:13:29 +0800208 {
Ed Tanous0bdda662023-08-03 17:27:34 -0700209 const nlohmann::json::object_t* obj =
210 element.second.get_ptr<const nlohmann::json::object_t*>();
211 if (obj == nullptr)
212 {
213 continue;
214 }
215 for (const auto& val : *obj)
JunLin Chen28afb492021-02-24 17:13:29 +0800216 {
Ed Tanous601c71a2021-09-08 16:40:12 -0700217 const std::string* value =
Ed Tanous0bdda662023-08-03 17:27:34 -0700218 val.second.get_ptr<const std::string*>();
JunLin Chen28afb492021-02-24 17:13:29 +0800219 if (value == nullptr)
220 {
Ed Tanous62598e32023-07-17 17:06:25 -0700221 BMCWEB_LOG_ERROR("Failed to parse value for key{}",
Ed Tanous0bdda662023-08-03 17:27:34 -0700222 val.first);
JunLin Chen28afb492021-02-24 17:13:29 +0800223 continue;
224 }
Ed Tanous4b712a22023-08-02 12:56:52 -0700225 subvalue.httpHeaders.set(val.first, *value);
JunLin Chen28afb492021-02-24 17:13:29 +0800226 }
227 }
Ed Tanous0bdda662023-08-03 17:27:34 -0700228 else if (element.first == "MetricReportDefinitions")
JunLin Chen28afb492021-02-24 17:13:29 +0800229 {
Ed Tanous0bdda662023-08-03 17:27:34 -0700230 const nlohmann::json::array_t* obj =
231 element.second.get_ptr<const nlohmann::json::array_t*>();
232 if (obj == nullptr)
233 {
234 continue;
235 }
236 for (const auto& val : *obj)
JunLin Chen28afb492021-02-24 17:13:29 +0800237 {
238 const std::string* value =
Ed Tanous0bdda662023-08-03 17:27:34 -0700239 val.get_ptr<const std::string*>();
JunLin Chen28afb492021-02-24 17:13:29 +0800240 if (value == nullptr)
241 {
242 continue;
243 }
Ed Tanous4b712a22023-08-02 12:56:52 -0700244 subvalue.metricReportDefinitions.emplace_back(*value);
JunLin Chen28afb492021-02-24 17:13:29 +0800245 }
246 }
Ed Tanousa14c9112024-09-04 10:46:47 -0700247 else if (element.first == "OriginResources")
248 {
249 const nlohmann::json::array_t* obj =
250 element.second.get_ptr<const nlohmann::json::array_t*>();
251 if (obj == nullptr)
252 {
253 continue;
254 }
255 for (const auto& val : *obj)
256 {
257 const std::string* value =
258 val.get_ptr<const std::string*>();
259 if (value == nullptr)
260 {
261 continue;
262 }
Ed Tanous4b712a22023-08-02 12:56:52 -0700263 subvalue.originResources.emplace_back(*value);
Ed Tanousa14c9112024-09-04 10:46:47 -0700264 }
265 }
JunLin Chen28afb492021-02-24 17:13:29 +0800266 else
267 {
Ed Tanous62598e32023-07-17 17:06:25 -0700268 BMCWEB_LOG_ERROR(
269 "Got unexpected property reading persistent file: {}",
Ed Tanous0bdda662023-08-03 17:27:34 -0700270 element.first);
JunLin Chen28afb492021-02-24 17:13:29 +0800271 continue;
272 }
273 }
274
Ed Tanous4b712a22023-08-02 12:56:52 -0700275 if ((subvalue.id.empty() && !loadFromOldConfig) ||
276 subvalue.destinationUrl.empty() || subvalue.protocol.empty() ||
277 subvalue.retryPolicy.empty() || subvalue.eventFormatType.empty() ||
278 subvalue.subscriptionType.empty())
JunLin Chen28afb492021-02-24 17:13:29 +0800279 {
Ed Tanous62598e32023-07-17 17:06:25 -0700280 BMCWEB_LOG_ERROR("Subscription missing required field "
281 "information, refusing to restore");
Ed Tanous4b712a22023-08-02 12:56:52 -0700282 return std::nullopt;
JunLin Chen28afb492021-02-24 17:13:29 +0800283 }
284
285 return subvalue;
286 }
287};
288
289struct EventServiceConfig
290{
291 bool enabled = true;
292 uint32_t retryAttempts = 3;
293 uint32_t retryTimeoutInterval = 30;
294
Ed Tanous0bdda662023-08-03 17:27:34 -0700295 void fromJson(const nlohmann::json::object_t& j)
JunLin Chen28afb492021-02-24 17:13:29 +0800296 {
Ed Tanous0bdda662023-08-03 17:27:34 -0700297 for (const auto& element : j)
JunLin Chen28afb492021-02-24 17:13:29 +0800298 {
Ed Tanous0bdda662023-08-03 17:27:34 -0700299 if (element.first == "ServiceEnabled")
JunLin Chen28afb492021-02-24 17:13:29 +0800300 {
Ed Tanous0bdda662023-08-03 17:27:34 -0700301 const bool* value = element.second.get_ptr<const bool*>();
JunLin Chen28afb492021-02-24 17:13:29 +0800302 if (value == nullptr)
303 {
304 continue;
305 }
306 enabled = *value;
307 }
Ed Tanous0bdda662023-08-03 17:27:34 -0700308 else if (element.first == "DeliveryRetryAttempts")
JunLin Chen28afb492021-02-24 17:13:29 +0800309 {
310 const uint64_t* value =
Ed Tanous0bdda662023-08-03 17:27:34 -0700311 element.second.get_ptr<const uint64_t*>();
JunLin Chen28afb492021-02-24 17:13:29 +0800312 if ((value == nullptr) ||
JunLin Chen28afb492021-02-24 17:13:29 +0800313 (*value > std::numeric_limits<uint32_t>::max()))
314 {
315 continue;
316 }
317 retryAttempts = static_cast<uint32_t>(*value);
318 }
Ed Tanous0bdda662023-08-03 17:27:34 -0700319 else if (element.first == "DeliveryRetryIntervalSeconds")
JunLin Chen28afb492021-02-24 17:13:29 +0800320 {
321 const uint64_t* value =
Ed Tanous0bdda662023-08-03 17:27:34 -0700322 element.second.get_ptr<const uint64_t*>();
JunLin Chen28afb492021-02-24 17:13:29 +0800323 if ((value == nullptr) ||
JunLin Chen28afb492021-02-24 17:13:29 +0800324 (*value > std::numeric_limits<uint32_t>::max()))
325 {
326 continue;
327 }
328 retryTimeoutInterval = static_cast<uint32_t>(*value);
329 }
330 }
331 }
332};
333
334class EventServiceStore
335{
336 public:
Myung Bae5fe4ef32024-10-19 09:56:02 -0400337 boost::container::flat_map<std::string, std::shared_ptr<UserSubscription>>
JunLin Chen28afb492021-02-24 17:13:29 +0800338 subscriptionsConfigMap;
339 EventServiceConfig eventServiceConfig;
340
341 static EventServiceStore& getInstance()
342 {
343 static EventServiceStore eventServiceStore;
344 return eventServiceStore;
345 }
346
347 EventServiceConfig& getEventServiceConfig()
348 {
349 return eventServiceConfig;
350 }
JunLin Chen28afb492021-02-24 17:13:29 +0800351};
352
353} // namespace persistent_data