blob: 61f1ac7b0f3199aa71e5068bdb406110d43a758c [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>
6#include <nlohmann/json.hpp>
7
8namespace persistent_data
9{
10
11struct UserSubscription
12{
13 std::string id;
14 std::string destinationUrl;
15 std::string protocol;
16 std::string retryPolicy;
17 std::string customText;
18 std::string eventFormatType;
19 std::string subscriptionType;
20 std::vector<std::string> registryMsgIds;
21 std::vector<std::string> registryPrefixes;
22 std::vector<std::string> resourceTypes;
Ed Tanous601c71a2021-09-08 16:40:12 -070023 boost::beast::http::fields httpHeaders;
JunLin Chen28afb492021-02-24 17:13:29 +080024 std::vector<std::string> metricReportDefinitions;
25
26 static std::shared_ptr<UserSubscription>
27 fromJson(const nlohmann::json& j, const bool loadFromOldConfig = false)
28 {
29 std::shared_ptr<UserSubscription> subvalue =
30 std::make_shared<UserSubscription>();
31 for (const auto& element : j.items())
32 {
33 if (element.key() == "Id")
34 {
35 const std::string* value =
36 element.value().get_ptr<const std::string*>();
37 if (value == nullptr)
38 {
39 continue;
40 }
41 subvalue->id = *value;
42 }
43 else if (element.key() == "Destination")
44 {
45 const std::string* value =
46 element.value().get_ptr<const std::string*>();
47 if (value == nullptr)
48 {
49 continue;
50 }
51 subvalue->destinationUrl = *value;
52 }
53 else if (element.key() == "Protocol")
54 {
55 const std::string* value =
56 element.value().get_ptr<const std::string*>();
57 if (value == nullptr)
58 {
59 continue;
60 }
61 subvalue->protocol = *value;
62 }
63 else if (element.key() == "DeliveryRetryPolicy")
64 {
65 const std::string* value =
66 element.value().get_ptr<const std::string*>();
67 if (value == nullptr)
68 {
69 continue;
70 }
71 subvalue->retryPolicy = *value;
72 }
73 else if (element.key() == "Context")
74 {
75 const std::string* value =
76 element.value().get_ptr<const std::string*>();
77 if (value == nullptr)
78 {
79 continue;
80 }
81 subvalue->customText = *value;
82 }
83 else if (element.key() == "EventFormatType")
84 {
85 const std::string* value =
86 element.value().get_ptr<const std::string*>();
87 if (value == nullptr)
88 {
89 continue;
90 }
91 subvalue->eventFormatType = *value;
92 }
93 else if (element.key() == "SubscriptionType")
94 {
95 const std::string* value =
96 element.value().get_ptr<const std::string*>();
97 if (value == nullptr)
98 {
99 continue;
100 }
101 subvalue->subscriptionType = *value;
102 }
103 else if (element.key() == "MessageIds")
104 {
105 const auto& obj = element.value();
106 for (const auto& val : obj.items())
107 {
108 const std::string* value =
109 val.value().get_ptr<const std::string*>();
110 if (value == nullptr)
111 {
112 continue;
113 }
114 subvalue->registryMsgIds.emplace_back(*value);
115 }
116 }
117 else if (element.key() == "RegistryPrefixes")
118 {
119 const auto& obj = element.value();
120 for (const auto& val : obj.items())
121 {
122 const std::string* value =
123 val.value().get_ptr<const std::string*>();
124 if (value == nullptr)
125 {
126 continue;
127 }
128 subvalue->registryPrefixes.emplace_back(*value);
129 }
130 }
131 else if (element.key() == "ResourceTypes")
132 {
133 const auto& obj = element.value();
134 for (const auto& val : obj.items())
135 {
136 const std::string* value =
137 val.value().get_ptr<const std::string*>();
138 if (value == nullptr)
139 {
140 continue;
141 }
142 subvalue->resourceTypes.emplace_back(*value);
143 }
144 }
145 else if (element.key() == "HttpHeaders")
146 {
147 const auto& obj = element.value();
148 for (const auto& val : obj.items())
149 {
Ed Tanous601c71a2021-09-08 16:40:12 -0700150 const std::string* value =
151 val.value().get_ptr<const std::string*>();
JunLin Chen28afb492021-02-24 17:13:29 +0800152 if (value == nullptr)
153 {
Ed Tanous62598e32023-07-17 17:06:25 -0700154 BMCWEB_LOG_ERROR("Failed to parse value for key{}",
155 val.key());
JunLin Chen28afb492021-02-24 17:13:29 +0800156 continue;
157 }
Ed Tanous601c71a2021-09-08 16:40:12 -0700158 subvalue->httpHeaders.set(val.key(), *value);
JunLin Chen28afb492021-02-24 17:13:29 +0800159 }
160 }
161 else if (element.key() == "MetricReportDefinitions")
162 {
163 const auto& obj = element.value();
164 for (const auto& val : obj.items())
165 {
166 const std::string* value =
167 val.value().get_ptr<const std::string*>();
168 if (value == nullptr)
169 {
170 continue;
171 }
172 subvalue->metricReportDefinitions.emplace_back(*value);
173 }
174 }
175 else
176 {
Ed Tanous62598e32023-07-17 17:06:25 -0700177 BMCWEB_LOG_ERROR(
178 "Got unexpected property reading persistent file: {}",
179 element.key());
JunLin Chen28afb492021-02-24 17:13:29 +0800180 continue;
181 }
182 }
183
184 if ((subvalue->id.empty() && !loadFromOldConfig) ||
185 subvalue->destinationUrl.empty() || subvalue->protocol.empty() ||
Sunitha Harishe6a71652021-08-06 03:15:59 -0500186 subvalue->retryPolicy.empty() ||
JunLin Chen28afb492021-02-24 17:13:29 +0800187 subvalue->eventFormatType.empty() ||
Sunitha Harishe6a71652021-08-06 03:15:59 -0500188 subvalue->subscriptionType.empty())
JunLin Chen28afb492021-02-24 17:13:29 +0800189 {
Ed Tanous62598e32023-07-17 17:06:25 -0700190 BMCWEB_LOG_ERROR("Subscription missing required field "
191 "information, refusing to restore");
JunLin Chen28afb492021-02-24 17:13:29 +0800192 return nullptr;
193 }
194
195 return subvalue;
196 }
197};
198
199struct EventServiceConfig
200{
201 bool enabled = true;
202 uint32_t retryAttempts = 3;
203 uint32_t retryTimeoutInterval = 30;
204
205 void fromJson(const nlohmann::json& j)
206 {
207 for (const auto& element : j.items())
208 {
209 if (element.key() == "ServiceEnabled")
210 {
211 const bool* value = element.value().get_ptr<const bool*>();
212 if (value == nullptr)
213 {
214 continue;
215 }
216 enabled = *value;
217 }
218 else if (element.key() == "DeliveryRetryAttempts")
219 {
220 const uint64_t* value =
221 element.value().get_ptr<const uint64_t*>();
222 if ((value == nullptr) ||
JunLin Chen28afb492021-02-24 17:13:29 +0800223 (*value > std::numeric_limits<uint32_t>::max()))
224 {
225 continue;
226 }
227 retryAttempts = static_cast<uint32_t>(*value);
228 }
229 else if (element.key() == "DeliveryRetryIntervalSeconds")
230 {
231 const uint64_t* value =
232 element.value().get_ptr<const uint64_t*>();
233 if ((value == nullptr) ||
JunLin Chen28afb492021-02-24 17:13:29 +0800234 (*value > std::numeric_limits<uint32_t>::max()))
235 {
236 continue;
237 }
238 retryTimeoutInterval = static_cast<uint32_t>(*value);
239 }
240 }
241 }
242};
243
244class EventServiceStore
245{
246 public:
247 boost::container::flat_map<std::string, std::shared_ptr<UserSubscription>>
248 subscriptionsConfigMap;
249 EventServiceConfig eventServiceConfig;
250
251 static EventServiceStore& getInstance()
252 {
253 static EventServiceStore eventServiceStore;
254 return eventServiceStore;
255 }
256
257 EventServiceConfig& getEventServiceConfig()
258 {
259 return eventServiceConfig;
260 }
261};
262
263} // namespace persistent_data