1 #pragma once 2 #include "logging.hpp" 3 4 #include <boost/beast/http/fields.hpp> 5 #include <boost/container/flat_map.hpp> 6 #include <nlohmann/json.hpp> 7 8 namespace persistent_data 9 { 10 11 struct 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; 23 boost::beast::http::fields httpHeaders; 24 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 { 150 const std::string* value = 151 val.value().get_ptr<const std::string*>(); 152 if (value == nullptr) 153 { 154 BMCWEB_LOG_ERROR("Failed to parse value for key{}", 155 val.key()); 156 continue; 157 } 158 subvalue->httpHeaders.set(val.key(), *value); 159 } 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 { 177 BMCWEB_LOG_ERROR( 178 "Got unexpected property reading persistent file: {}", 179 element.key()); 180 continue; 181 } 182 } 183 184 if ((subvalue->id.empty() && !loadFromOldConfig) || 185 subvalue->destinationUrl.empty() || subvalue->protocol.empty() || 186 subvalue->retryPolicy.empty() || 187 subvalue->eventFormatType.empty() || 188 subvalue->subscriptionType.empty()) 189 { 190 BMCWEB_LOG_ERROR("Subscription missing required field " 191 "information, refusing to restore"); 192 return nullptr; 193 } 194 195 return subvalue; 196 } 197 }; 198 199 struct 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) || 223 (*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) || 234 (*value > std::numeric_limits<uint32_t>::max())) 235 { 236 continue; 237 } 238 retryTimeoutInterval = static_cast<uint32_t>(*value); 239 } 240 } 241 } 242 }; 243 244 class 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 264