blob: f03bd7908f68b090499a6978ae942eda6fa70828 [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
10namespace persistent_data
11{
12
13struct UserSubscription
14{
15 std::string id;
Ed Tanousa716aa72023-08-01 11:35:53 -070016 boost::urls::url destinationUrl;
JunLin Chen28afb492021-02-24 17:13:29 +080017 std::string protocol;
18 std::string retryPolicy;
19 std::string customText;
20 std::string eventFormatType;
21 std::string subscriptionType;
22 std::vector<std::string> registryMsgIds;
23 std::vector<std::string> registryPrefixes;
24 std::vector<std::string> resourceTypes;
Ed Tanous601c71a2021-09-08 16:40:12 -070025 boost::beast::http::fields httpHeaders;
JunLin Chen28afb492021-02-24 17:13:29 +080026 std::vector<std::string> metricReportDefinitions;
27
28 static std::shared_ptr<UserSubscription>
29 fromJson(const nlohmann::json& j, const bool loadFromOldConfig = false)
30 {
31 std::shared_ptr<UserSubscription> subvalue =
32 std::make_shared<UserSubscription>();
33 for (const auto& element : j.items())
34 {
35 if (element.key() == "Id")
36 {
37 const std::string* value =
38 element.value().get_ptr<const std::string*>();
39 if (value == nullptr)
40 {
41 continue;
42 }
43 subvalue->id = *value;
44 }
45 else if (element.key() == "Destination")
46 {
47 const std::string* value =
48 element.value().get_ptr<const std::string*>();
49 if (value == nullptr)
50 {
51 continue;
52 }
Ed Tanous6fd29552023-10-04 09:40:14 -070053 boost::system::result<boost::urls::url> url =
Ed Tanousa716aa72023-08-01 11:35:53 -070054 boost::urls::parse_absolute_uri(*value);
55 if (!url)
56 {
57 continue;
58 }
59 subvalue->destinationUrl = std::move(*url);
JunLin Chen28afb492021-02-24 17:13:29 +080060 }
61 else if (element.key() == "Protocol")
62 {
63 const std::string* value =
64 element.value().get_ptr<const std::string*>();
65 if (value == nullptr)
66 {
67 continue;
68 }
69 subvalue->protocol = *value;
70 }
71 else if (element.key() == "DeliveryRetryPolicy")
72 {
73 const std::string* value =
74 element.value().get_ptr<const std::string*>();
75 if (value == nullptr)
76 {
77 continue;
78 }
79 subvalue->retryPolicy = *value;
80 }
81 else if (element.key() == "Context")
82 {
83 const std::string* value =
84 element.value().get_ptr<const std::string*>();
85 if (value == nullptr)
86 {
87 continue;
88 }
89 subvalue->customText = *value;
90 }
91 else if (element.key() == "EventFormatType")
92 {
93 const std::string* value =
94 element.value().get_ptr<const std::string*>();
95 if (value == nullptr)
96 {
97 continue;
98 }
99 subvalue->eventFormatType = *value;
100 }
101 else if (element.key() == "SubscriptionType")
102 {
103 const std::string* value =
104 element.value().get_ptr<const std::string*>();
105 if (value == nullptr)
106 {
107 continue;
108 }
109 subvalue->subscriptionType = *value;
110 }
111 else if (element.key() == "MessageIds")
112 {
113 const auto& obj = element.value();
114 for (const auto& val : obj.items())
115 {
116 const std::string* value =
117 val.value().get_ptr<const std::string*>();
118 if (value == nullptr)
119 {
120 continue;
121 }
122 subvalue->registryMsgIds.emplace_back(*value);
123 }
124 }
125 else if (element.key() == "RegistryPrefixes")
126 {
127 const auto& obj = element.value();
128 for (const auto& val : obj.items())
129 {
130 const std::string* value =
131 val.value().get_ptr<const std::string*>();
132 if (value == nullptr)
133 {
134 continue;
135 }
136 subvalue->registryPrefixes.emplace_back(*value);
137 }
138 }
139 else if (element.key() == "ResourceTypes")
140 {
141 const auto& obj = element.value();
142 for (const auto& val : obj.items())
143 {
144 const std::string* value =
145 val.value().get_ptr<const std::string*>();
146 if (value == nullptr)
147 {
148 continue;
149 }
150 subvalue->resourceTypes.emplace_back(*value);
151 }
152 }
153 else if (element.key() == "HttpHeaders")
154 {
155 const auto& obj = element.value();
156 for (const auto& val : obj.items())
157 {
Ed Tanous601c71a2021-09-08 16:40:12 -0700158 const std::string* value =
159 val.value().get_ptr<const std::string*>();
JunLin Chen28afb492021-02-24 17:13:29 +0800160 if (value == nullptr)
161 {
Ed Tanous62598e32023-07-17 17:06:25 -0700162 BMCWEB_LOG_ERROR("Failed to parse value for key{}",
163 val.key());
JunLin Chen28afb492021-02-24 17:13:29 +0800164 continue;
165 }
Ed Tanous601c71a2021-09-08 16:40:12 -0700166 subvalue->httpHeaders.set(val.key(), *value);
JunLin Chen28afb492021-02-24 17:13:29 +0800167 }
168 }
169 else if (element.key() == "MetricReportDefinitions")
170 {
171 const auto& obj = element.value();
172 for (const auto& val : obj.items())
173 {
174 const std::string* value =
175 val.value().get_ptr<const std::string*>();
176 if (value == nullptr)
177 {
178 continue;
179 }
180 subvalue->metricReportDefinitions.emplace_back(*value);
181 }
182 }
183 else
184 {
Ed Tanous62598e32023-07-17 17:06:25 -0700185 BMCWEB_LOG_ERROR(
186 "Got unexpected property reading persistent file: {}",
187 element.key());
JunLin Chen28afb492021-02-24 17:13:29 +0800188 continue;
189 }
190 }
191
192 if ((subvalue->id.empty() && !loadFromOldConfig) ||
193 subvalue->destinationUrl.empty() || subvalue->protocol.empty() ||
Sunitha Harishe6a71652021-08-06 03:15:59 -0500194 subvalue->retryPolicy.empty() ||
JunLin Chen28afb492021-02-24 17:13:29 +0800195 subvalue->eventFormatType.empty() ||
Sunitha Harishe6a71652021-08-06 03:15:59 -0500196 subvalue->subscriptionType.empty())
JunLin Chen28afb492021-02-24 17:13:29 +0800197 {
Ed Tanous62598e32023-07-17 17:06:25 -0700198 BMCWEB_LOG_ERROR("Subscription missing required field "
199 "information, refusing to restore");
JunLin Chen28afb492021-02-24 17:13:29 +0800200 return nullptr;
201 }
202
203 return subvalue;
204 }
205};
206
207struct EventServiceConfig
208{
209 bool enabled = true;
210 uint32_t retryAttempts = 3;
211 uint32_t retryTimeoutInterval = 30;
212
213 void fromJson(const nlohmann::json& j)
214 {
215 for (const auto& element : j.items())
216 {
217 if (element.key() == "ServiceEnabled")
218 {
219 const bool* value = element.value().get_ptr<const bool*>();
220 if (value == nullptr)
221 {
222 continue;
223 }
224 enabled = *value;
225 }
226 else if (element.key() == "DeliveryRetryAttempts")
227 {
228 const uint64_t* value =
229 element.value().get_ptr<const uint64_t*>();
230 if ((value == nullptr) ||
JunLin Chen28afb492021-02-24 17:13:29 +0800231 (*value > std::numeric_limits<uint32_t>::max()))
232 {
233 continue;
234 }
235 retryAttempts = static_cast<uint32_t>(*value);
236 }
237 else if (element.key() == "DeliveryRetryIntervalSeconds")
238 {
239 const uint64_t* value =
240 element.value().get_ptr<const uint64_t*>();
241 if ((value == nullptr) ||
JunLin Chen28afb492021-02-24 17:13:29 +0800242 (*value > std::numeric_limits<uint32_t>::max()))
243 {
244 continue;
245 }
246 retryTimeoutInterval = static_cast<uint32_t>(*value);
247 }
248 }
249 }
250};
251
252class EventServiceStore
253{
254 public:
255 boost::container::flat_map<std::string, std::shared_ptr<UserSubscription>>
256 subscriptionsConfigMap;
257 EventServiceConfig eventServiceConfig;
258
259 static EventServiceStore& getInstance()
260 {
261 static EventServiceStore eventServiceStore;
262 return eventServiceStore;
263 }
264
265 EventServiceConfig& getEventServiceConfig()
266 {
267 return eventServiceConfig;
268 }
269};
270
271} // namespace persistent_data