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