1e5aaf047SAppaRao Puli /* 2e5aaf047SAppaRao Puli // Copyright (c) 2020 Intel Corporation 3e5aaf047SAppaRao Puli // 4e5aaf047SAppaRao Puli // Licensed under the Apache License, Version 2.0 (the "License"); 5e5aaf047SAppaRao Puli // you may not use this file except in compliance with the License. 6e5aaf047SAppaRao Puli // You may obtain a copy of the License at 7e5aaf047SAppaRao Puli // 8e5aaf047SAppaRao Puli // http://www.apache.org/licenses/LICENSE-2.0 9e5aaf047SAppaRao Puli // 10e5aaf047SAppaRao Puli // Unless required by applicable law or agreed to in writing, software 11e5aaf047SAppaRao Puli // distributed under the License is distributed on an "AS IS" BASIS, 12e5aaf047SAppaRao Puli // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e5aaf047SAppaRao Puli // See the License for the specific language governing permissions and 14e5aaf047SAppaRao Puli // limitations under the License. 15e5aaf047SAppaRao Puli */ 16e5aaf047SAppaRao Puli #pragma once 17b52664e2SAppaRao Puli #include "event_service_manager.hpp" 18e5aaf047SAppaRao Puli 19e5aaf047SAppaRao Puli namespace redfish 20e5aaf047SAppaRao Puli { 21e5aaf047SAppaRao Puli 22*156d6b00SAppaRao Puli static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = { 23*156d6b00SAppaRao Puli eventFormatType, metricReportFormatType}; 24e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRegPrefixes = { 25e5aaf047SAppaRao Puli "Base", "OpenBMC", "Task"}; 26e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRetryPolicies = { 27e5aaf047SAppaRao Puli "TerminateAfterRetries", "SuspendRetries", "RetryForever"}; 28e5aaf047SAppaRao Puli 29e5aaf047SAppaRao Puli static constexpr const uint8_t maxNoOfSubscriptions = 20; 30e5aaf047SAppaRao Puli 31e5aaf047SAppaRao Puli class EventService : public Node 32e5aaf047SAppaRao Puli { 33e5aaf047SAppaRao Puli public: 34e5aaf047SAppaRao Puli EventService(CrowApp& app) : Node(app, "/redfish/v1/EventService/") 35e5aaf047SAppaRao Puli { 36e5aaf047SAppaRao Puli entityPrivileges = { 37e5aaf047SAppaRao Puli {boost::beast::http::verb::get, {{"Login"}}}, 38e5aaf047SAppaRao Puli {boost::beast::http::verb::head, {{"Login"}}}, 39e5aaf047SAppaRao Puli {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 40e5aaf047SAppaRao Puli {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 41e5aaf047SAppaRao Puli {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 42e5aaf047SAppaRao Puli {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 43e5aaf047SAppaRao Puli } 44e5aaf047SAppaRao Puli 45e5aaf047SAppaRao Puli private: 46e5aaf047SAppaRao Puli void doGet(crow::Response& res, const crow::Request& req, 47e5aaf047SAppaRao Puli const std::vector<std::string>& params) override 48e5aaf047SAppaRao Puli { 49e5aaf047SAppaRao Puli auto asyncResp = std::make_shared<AsyncResp>(res); 50e5aaf047SAppaRao Puli res.jsonValue = { 51e5aaf047SAppaRao Puli {"@odata.type", "#EventService.v1_5_0.EventService"}, 52e5aaf047SAppaRao Puli {"Id", "EventService"}, 53e5aaf047SAppaRao Puli {"Name", "Event Service"}, 54e5aaf047SAppaRao Puli {"ServerSentEventUri", 55e5aaf047SAppaRao Puli "/redfish/v1/EventService/Subscriptions/SSE"}, 56e5aaf047SAppaRao Puli {"Subscriptions", 57e5aaf047SAppaRao Puli {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}}, 580b4bdd93SAppaRao Puli {"Actions", 590b4bdd93SAppaRao Puli {{"#EventService.SubmitTestEvent", 600b4bdd93SAppaRao Puli {{"target", "/redfish/v1/EventService/Actions/" 610b4bdd93SAppaRao Puli "EventService.SubmitTestEvent"}}}}}, 62e5aaf047SAppaRao Puli {"@odata.id", "/redfish/v1/EventService"}}; 63e5aaf047SAppaRao Puli 64e5aaf047SAppaRao Puli asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 65b52664e2SAppaRao Puli asyncResp->res.jsonValue["ServiceEnabled"] = 66b52664e2SAppaRao Puli EventServiceManager::getInstance().enabled; 67e5aaf047SAppaRao Puli asyncResp->res.jsonValue["DeliveryRetryAttempts"] = 68b52664e2SAppaRao Puli EventServiceManager::getInstance().retryAttempts; 69e5aaf047SAppaRao Puli asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] = 70b52664e2SAppaRao Puli EventServiceManager::getInstance().retryTimeoutInterval; 71e5aaf047SAppaRao Puli asyncResp->res.jsonValue["EventFormatTypes"] = supportedEvtFormatTypes; 72e5aaf047SAppaRao Puli asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes; 73e5aaf047SAppaRao Puli } 74e5aaf047SAppaRao Puli 75e5aaf047SAppaRao Puli void doPatch(crow::Response& res, const crow::Request& req, 76e5aaf047SAppaRao Puli const std::vector<std::string>& params) override 77e5aaf047SAppaRao Puli { 78e5aaf047SAppaRao Puli auto asyncResp = std::make_shared<AsyncResp>(res); 79e5aaf047SAppaRao Puli 80e5aaf047SAppaRao Puli std::optional<bool> serviceEnabled; 81e5aaf047SAppaRao Puli std::optional<uint32_t> retryAttemps; 82e5aaf047SAppaRao Puli std::optional<uint32_t> retryInterval; 83e5aaf047SAppaRao Puli 84e5aaf047SAppaRao Puli if (!json_util::readJson(req, res, "ServiceEnabled", serviceEnabled, 85e5aaf047SAppaRao Puli "DeliveryRetryAttempts", retryAttemps, 86e5aaf047SAppaRao Puli "DeliveryRetryIntervalSeconds", retryInterval)) 87e5aaf047SAppaRao Puli { 88e5aaf047SAppaRao Puli return; 89e5aaf047SAppaRao Puli } 90e5aaf047SAppaRao Puli 91e5aaf047SAppaRao Puli if (serviceEnabled) 92e5aaf047SAppaRao Puli { 93b52664e2SAppaRao Puli EventServiceManager::getInstance().enabled = *serviceEnabled; 94e5aaf047SAppaRao Puli } 95e5aaf047SAppaRao Puli 96e5aaf047SAppaRao Puli if (retryAttemps) 97e5aaf047SAppaRao Puli { 98e5aaf047SAppaRao Puli // Supported range [1-3] 99e5aaf047SAppaRao Puli if ((*retryAttemps < 1) || (*retryAttemps > 3)) 100e5aaf047SAppaRao Puli { 101e5aaf047SAppaRao Puli messages::queryParameterOutOfRange( 102e5aaf047SAppaRao Puli asyncResp->res, std::to_string(*retryAttemps), 103e5aaf047SAppaRao Puli "DeliveryRetryAttempts", "[1-3]"); 104e5aaf047SAppaRao Puli } 105e5aaf047SAppaRao Puli else 106e5aaf047SAppaRao Puli { 107b52664e2SAppaRao Puli EventServiceManager::getInstance().retryAttempts = 108b52664e2SAppaRao Puli *retryAttemps; 109e5aaf047SAppaRao Puli } 110e5aaf047SAppaRao Puli } 111e5aaf047SAppaRao Puli 112e5aaf047SAppaRao Puli if (retryInterval) 113e5aaf047SAppaRao Puli { 114e5aaf047SAppaRao Puli // Supported range [30 - 180] 115e5aaf047SAppaRao Puli if ((*retryInterval < 30) || (*retryInterval > 180)) 116e5aaf047SAppaRao Puli { 117e5aaf047SAppaRao Puli messages::queryParameterOutOfRange( 118e5aaf047SAppaRao Puli asyncResp->res, std::to_string(*retryInterval), 119e5aaf047SAppaRao Puli "DeliveryRetryIntervalSeconds", "[30-180]"); 120e5aaf047SAppaRao Puli } 121e5aaf047SAppaRao Puli else 122e5aaf047SAppaRao Puli { 123b52664e2SAppaRao Puli EventServiceManager::getInstance().retryTimeoutInterval = 124b52664e2SAppaRao Puli *retryInterval; 125e5aaf047SAppaRao Puli } 126e5aaf047SAppaRao Puli } 127e5aaf047SAppaRao Puli 128b52664e2SAppaRao Puli EventServiceManager::getInstance().updateSubscriptionData(); 129e5aaf047SAppaRao Puli } 130e5aaf047SAppaRao Puli }; 131e5aaf047SAppaRao Puli 1320b4bdd93SAppaRao Puli class SubmitTestEvent : public Node 1330b4bdd93SAppaRao Puli { 1340b4bdd93SAppaRao Puli public: 1350b4bdd93SAppaRao Puli SubmitTestEvent(CrowApp& app) : 1360b4bdd93SAppaRao Puli Node(app, 1370b4bdd93SAppaRao Puli "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/") 1380b4bdd93SAppaRao Puli { 1390b4bdd93SAppaRao Puli entityPrivileges = { 1400b4bdd93SAppaRao Puli {boost::beast::http::verb::get, {{"Login"}}}, 1410b4bdd93SAppaRao Puli {boost::beast::http::verb::head, {{"Login"}}}, 1420b4bdd93SAppaRao Puli {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 1430b4bdd93SAppaRao Puli {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 1440b4bdd93SAppaRao Puli {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 1450b4bdd93SAppaRao Puli {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 1460b4bdd93SAppaRao Puli } 1470b4bdd93SAppaRao Puli 1480b4bdd93SAppaRao Puli private: 1490b4bdd93SAppaRao Puli void doPost(crow::Response& res, const crow::Request& req, 1500b4bdd93SAppaRao Puli const std::vector<std::string>& params) override 1510b4bdd93SAppaRao Puli { 1520b4bdd93SAppaRao Puli EventServiceManager::getInstance().sendTestEventLog(); 1530b4bdd93SAppaRao Puli res.result(boost::beast::http::status::no_content); 1540b4bdd93SAppaRao Puli res.end(); 1550b4bdd93SAppaRao Puli } 1560b4bdd93SAppaRao Puli }; 1570b4bdd93SAppaRao Puli 158e5aaf047SAppaRao Puli class EventDestinationCollection : public Node 159e5aaf047SAppaRao Puli { 160e5aaf047SAppaRao Puli public: 161e5aaf047SAppaRao Puli EventDestinationCollection(CrowApp& app) : 162e5aaf047SAppaRao Puli Node(app, "/redfish/v1/EventService/Subscriptions/") 163e5aaf047SAppaRao Puli { 164e5aaf047SAppaRao Puli entityPrivileges = { 165e5aaf047SAppaRao Puli {boost::beast::http::verb::get, {{"Login"}}}, 166e5aaf047SAppaRao Puli {boost::beast::http::verb::head, {{"Login"}}}, 167e5aaf047SAppaRao Puli {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 168e5aaf047SAppaRao Puli {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 169e5aaf047SAppaRao Puli {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 170e5aaf047SAppaRao Puli {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 171e5aaf047SAppaRao Puli } 172e5aaf047SAppaRao Puli 173e5aaf047SAppaRao Puli private: 174e5aaf047SAppaRao Puli void doGet(crow::Response& res, const crow::Request& req, 175e5aaf047SAppaRao Puli const std::vector<std::string>& params) override 176e5aaf047SAppaRao Puli { 177e5aaf047SAppaRao Puli auto asyncResp = std::make_shared<AsyncResp>(res); 178e5aaf047SAppaRao Puli 179e5aaf047SAppaRao Puli res.jsonValue = { 180e5aaf047SAppaRao Puli {"@odata.type", 181e5aaf047SAppaRao Puli "#EventDestinationCollection.EventDestinationCollection"}, 182e5aaf047SAppaRao Puli {"@odata.id", "/redfish/v1/EventService/Subscriptions"}, 183e5aaf047SAppaRao Puli {"Name", "Event Destination Collections"}}; 184e5aaf047SAppaRao Puli 185e5aaf047SAppaRao Puli nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"]; 186e5aaf047SAppaRao Puli 187b52664e2SAppaRao Puli std::vector<std::string> subscripIds = 188b52664e2SAppaRao Puli EventServiceManager::getInstance().getAllIDs(); 189b52664e2SAppaRao Puli memberArray = nlohmann::json::array(); 190b52664e2SAppaRao Puli asyncResp->res.jsonValue["Members@odata.count"] = subscripIds.size(); 191b52664e2SAppaRao Puli 192b52664e2SAppaRao Puli for (const std::string& id : subscripIds) 193e5aaf047SAppaRao Puli { 194e5aaf047SAppaRao Puli memberArray.push_back( 195e5aaf047SAppaRao Puli {{"@odata.id", 196b52664e2SAppaRao Puli "/redfish/v1/EventService/Subscriptions/" + id}}); 197e5aaf047SAppaRao Puli } 198e5aaf047SAppaRao Puli } 199e5aaf047SAppaRao Puli 200e5aaf047SAppaRao Puli void doPost(crow::Response& res, const crow::Request& req, 201e5aaf047SAppaRao Puli const std::vector<std::string>& params) override 202e5aaf047SAppaRao Puli { 203e5aaf047SAppaRao Puli auto asyncResp = std::make_shared<AsyncResp>(res); 204e5aaf047SAppaRao Puli 205b52664e2SAppaRao Puli if (EventServiceManager::getInstance().getNumberOfSubscriptions() >= 206b52664e2SAppaRao Puli maxNoOfSubscriptions) 207e5aaf047SAppaRao Puli { 208e5aaf047SAppaRao Puli messages::eventSubscriptionLimitExceeded(asyncResp->res); 209e5aaf047SAppaRao Puli return; 210e5aaf047SAppaRao Puli } 211e5aaf047SAppaRao Puli std::string destUrl; 212e5aaf047SAppaRao Puli std::string protocol; 213e5aaf047SAppaRao Puli std::optional<std::string> context; 214e5aaf047SAppaRao Puli std::optional<std::string> subscriptionType; 215e5aaf047SAppaRao Puli std::optional<std::string> eventFormatType; 216e5aaf047SAppaRao Puli std::optional<std::string> retryPolicy; 217e5aaf047SAppaRao Puli std::optional<std::vector<std::string>> msgIds; 218e5aaf047SAppaRao Puli std::optional<std::vector<std::string>> regPrefixes; 219e5aaf047SAppaRao Puli std::optional<std::vector<nlohmann::json>> headers; 220*156d6b00SAppaRao Puli std::optional<std::vector<nlohmann::json>> metricReportDefinitions; 221e5aaf047SAppaRao Puli 222e5aaf047SAppaRao Puli if (!json_util::readJson( 223e5aaf047SAppaRao Puli req, res, "Destination", destUrl, "Context", context, 224e5aaf047SAppaRao Puli "Protocol", protocol, "SubscriptionType", subscriptionType, 225e5aaf047SAppaRao Puli "EventFormatType", eventFormatType, "HttpHeaders", headers, 226e5aaf047SAppaRao Puli "RegistryPrefixes", regPrefixes, "MessageIds", msgIds, 227*156d6b00SAppaRao Puli "DeliveryRetryPolicy", retryPolicy, "MetricReportDefinitions", 228*156d6b00SAppaRao Puli metricReportDefinitions)) 229e5aaf047SAppaRao Puli { 230e5aaf047SAppaRao Puli return; 231e5aaf047SAppaRao Puli } 232e5aaf047SAppaRao Puli 233e5aaf047SAppaRao Puli // Validate the URL using regex expression 234b52664e2SAppaRao Puli // Format: <protocol>://<host>:<port>/<uri> 235b52664e2SAppaRao Puli // protocol: http/https 236b52664e2SAppaRao Puli // host: Exclude ' ', ':', '#', '?' 237b52664e2SAppaRao Puli // port: Empty or numeric value with ':' seperator. 238b52664e2SAppaRao Puli // uri: Start with '/' and Exclude '#', ' ' 239b52664e2SAppaRao Puli // Can include query params(ex: '/event?test=1') 240b52664e2SAppaRao Puli // TODO: Need to validate hostname extensively(as per rfc) 241b52664e2SAppaRao Puli const std::regex urlRegex( 242b52664e2SAppaRao Puli "(http|https)://([^/\\x20\\x3f\\x23\\x3a]+):?([0-9]*)(/" 243b52664e2SAppaRao Puli "([^\\x20\\x23\\x3f]*\\x3f?([^\\x20\\x23\\x3f])*)?)"); 244b52664e2SAppaRao Puli std::cmatch match; 245b52664e2SAppaRao Puli if (!std::regex_match(destUrl.c_str(), match, urlRegex)) 246e5aaf047SAppaRao Puli { 247e5aaf047SAppaRao Puli messages::propertyValueFormatError(asyncResp->res, destUrl, 248e5aaf047SAppaRao Puli "Destination"); 249e5aaf047SAppaRao Puli return; 250e5aaf047SAppaRao Puli } 251b52664e2SAppaRao Puli 252b52664e2SAppaRao Puli std::string uriProto = std::string(match[1].first, match[1].second); 253b52664e2SAppaRao Puli if (uriProto == "http") 254b52664e2SAppaRao Puli { 255b52664e2SAppaRao Puli #ifndef BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING 256b52664e2SAppaRao Puli messages::propertyValueFormatError(asyncResp->res, destUrl, 257b52664e2SAppaRao Puli "Destination"); 258b52664e2SAppaRao Puli return; 259b52664e2SAppaRao Puli #endif 260b52664e2SAppaRao Puli } 261b52664e2SAppaRao Puli 262b52664e2SAppaRao Puli std::string host = std::string(match[2].first, match[2].second); 263b52664e2SAppaRao Puli std::string port = std::string(match[3].first, match[3].second); 264b52664e2SAppaRao Puli std::string path = std::string(match[4].first, match[4].second); 265b52664e2SAppaRao Puli if (port.empty()) 266b52664e2SAppaRao Puli { 267b52664e2SAppaRao Puli if (uriProto == "http") 268b52664e2SAppaRao Puli { 269b52664e2SAppaRao Puli port = "80"; 270b52664e2SAppaRao Puli } 271b52664e2SAppaRao Puli else 272b52664e2SAppaRao Puli { 273b52664e2SAppaRao Puli port = "443"; 274b52664e2SAppaRao Puli } 275b52664e2SAppaRao Puli } 276b52664e2SAppaRao Puli if (path.empty()) 277b52664e2SAppaRao Puli { 278b52664e2SAppaRao Puli path = "/"; 279b52664e2SAppaRao Puli } 280b52664e2SAppaRao Puli 281b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 282b52664e2SAppaRao Puli std::make_shared<Subscription>(host, port, path, uriProto); 283b52664e2SAppaRao Puli 284b52664e2SAppaRao Puli subValue->destinationUrl = destUrl; 285e5aaf047SAppaRao Puli 286e5aaf047SAppaRao Puli if (subscriptionType) 287e5aaf047SAppaRao Puli { 288e5aaf047SAppaRao Puli if (*subscriptionType != "RedfishEvent") 289e5aaf047SAppaRao Puli { 290e5aaf047SAppaRao Puli messages::propertyValueNotInList( 291e5aaf047SAppaRao Puli asyncResp->res, *subscriptionType, "SubscriptionType"); 292e5aaf047SAppaRao Puli return; 293e5aaf047SAppaRao Puli } 294b52664e2SAppaRao Puli subValue->subscriptionType = *subscriptionType; 295e5aaf047SAppaRao Puli } 296e5aaf047SAppaRao Puli else 297e5aaf047SAppaRao Puli { 298b52664e2SAppaRao Puli subValue->subscriptionType = "RedfishEvent"; // Default 299e5aaf047SAppaRao Puli } 300e5aaf047SAppaRao Puli 301e5aaf047SAppaRao Puli if (protocol != "Redfish") 302e5aaf047SAppaRao Puli { 303e5aaf047SAppaRao Puli messages::propertyValueNotInList(asyncResp->res, protocol, 304e5aaf047SAppaRao Puli "Protocol"); 305e5aaf047SAppaRao Puli return; 306e5aaf047SAppaRao Puli } 307b52664e2SAppaRao Puli subValue->protocol = protocol; 308e5aaf047SAppaRao Puli 309e5aaf047SAppaRao Puli if (eventFormatType) 310e5aaf047SAppaRao Puli { 311e5aaf047SAppaRao Puli if (std::find(supportedEvtFormatTypes.begin(), 312e5aaf047SAppaRao Puli supportedEvtFormatTypes.end(), 313e5aaf047SAppaRao Puli *eventFormatType) == supportedEvtFormatTypes.end()) 314e5aaf047SAppaRao Puli { 315e5aaf047SAppaRao Puli messages::propertyValueNotInList( 316e5aaf047SAppaRao Puli asyncResp->res, *eventFormatType, "EventFormatType"); 317e5aaf047SAppaRao Puli return; 318e5aaf047SAppaRao Puli } 319b52664e2SAppaRao Puli subValue->eventFormatType = *eventFormatType; 320e5aaf047SAppaRao Puli } 321e5aaf047SAppaRao Puli else 322e5aaf047SAppaRao Puli { 323e5aaf047SAppaRao Puli // If not specified, use default "Event" 324b52664e2SAppaRao Puli subValue->eventFormatType.assign({"Event"}); 325e5aaf047SAppaRao Puli } 326e5aaf047SAppaRao Puli 327e5aaf047SAppaRao Puli if (context) 328e5aaf047SAppaRao Puli { 329b52664e2SAppaRao Puli subValue->customText = *context; 330e5aaf047SAppaRao Puli } 331e5aaf047SAppaRao Puli 332e5aaf047SAppaRao Puli if (headers) 333e5aaf047SAppaRao Puli { 334b52664e2SAppaRao Puli subValue->httpHeaders = *headers; 335e5aaf047SAppaRao Puli } 336e5aaf047SAppaRao Puli 337e5aaf047SAppaRao Puli if (regPrefixes) 338e5aaf047SAppaRao Puli { 339e5aaf047SAppaRao Puli for (const std::string& it : *regPrefixes) 340e5aaf047SAppaRao Puli { 341e5aaf047SAppaRao Puli if (std::find(supportedRegPrefixes.begin(), 342e5aaf047SAppaRao Puli supportedRegPrefixes.end(), 343e5aaf047SAppaRao Puli it) == supportedRegPrefixes.end()) 344e5aaf047SAppaRao Puli { 345e5aaf047SAppaRao Puli messages::propertyValueNotInList(asyncResp->res, it, 346e5aaf047SAppaRao Puli "RegistryPrefixes"); 347e5aaf047SAppaRao Puli return; 348e5aaf047SAppaRao Puli } 349e5aaf047SAppaRao Puli } 350b52664e2SAppaRao Puli subValue->registryPrefixes = *regPrefixes; 351e5aaf047SAppaRao Puli } 352e5aaf047SAppaRao Puli 353e5aaf047SAppaRao Puli if (msgIds) 354e5aaf047SAppaRao Puli { 355e5aaf047SAppaRao Puli // Do we need to loop-up MessageRegistry and validate 356e5aaf047SAppaRao Puli // data for authenticity??? Not mandate, i believe. 357b52664e2SAppaRao Puli subValue->registryMsgIds = *msgIds; 358e5aaf047SAppaRao Puli } 359e5aaf047SAppaRao Puli 360e5aaf047SAppaRao Puli if (retryPolicy) 361e5aaf047SAppaRao Puli { 362e5aaf047SAppaRao Puli if (std::find(supportedRetryPolicies.begin(), 363e5aaf047SAppaRao Puli supportedRetryPolicies.end(), 364e5aaf047SAppaRao Puli *retryPolicy) == supportedRetryPolicies.end()) 365e5aaf047SAppaRao Puli { 366e5aaf047SAppaRao Puli messages::propertyValueNotInList(asyncResp->res, *retryPolicy, 367e5aaf047SAppaRao Puli "DeliveryRetryPolicy"); 368e5aaf047SAppaRao Puli return; 369e5aaf047SAppaRao Puli } 370b52664e2SAppaRao Puli subValue->retryPolicy = *retryPolicy; 371e5aaf047SAppaRao Puli } 372e5aaf047SAppaRao Puli else 373e5aaf047SAppaRao Puli { 374e5aaf047SAppaRao Puli // Default "TerminateAfterRetries" 375b52664e2SAppaRao Puli subValue->retryPolicy = "TerminateAfterRetries"; 376e5aaf047SAppaRao Puli } 377e5aaf047SAppaRao Puli 378*156d6b00SAppaRao Puli if (metricReportDefinitions) 379*156d6b00SAppaRao Puli { 380*156d6b00SAppaRao Puli subValue->metricReportDefinitions = *metricReportDefinitions; 381*156d6b00SAppaRao Puli } 382*156d6b00SAppaRao Puli 383b52664e2SAppaRao Puli std::string id = 384b52664e2SAppaRao Puli EventServiceManager::getInstance().addSubscription(subValue); 385b52664e2SAppaRao Puli if (id.empty()) 386e5aaf047SAppaRao Puli { 387e5aaf047SAppaRao Puli messages::internalError(asyncResp->res); 388e5aaf047SAppaRao Puli return; 389e5aaf047SAppaRao Puli } 390e5aaf047SAppaRao Puli 391e5aaf047SAppaRao Puli messages::created(asyncResp->res); 392e5aaf047SAppaRao Puli asyncResp->res.addHeader( 393e5aaf047SAppaRao Puli "Location", "/redfish/v1/EventService/Subscriptions/" + id); 394e5aaf047SAppaRao Puli } 395e5aaf047SAppaRao Puli }; 396e5aaf047SAppaRao Puli 397e5aaf047SAppaRao Puli class EventDestination : public Node 398e5aaf047SAppaRao Puli { 399e5aaf047SAppaRao Puli public: 400e5aaf047SAppaRao Puli EventDestination(CrowApp& app) : 401e5aaf047SAppaRao Puli Node(app, "/redfish/v1/EventService/Subscriptions/<str>/", 402e5aaf047SAppaRao Puli std::string()) 403e5aaf047SAppaRao Puli { 404e5aaf047SAppaRao Puli entityPrivileges = { 405e5aaf047SAppaRao Puli {boost::beast::http::verb::get, {{"Login"}}}, 406e5aaf047SAppaRao Puli {boost::beast::http::verb::head, {{"Login"}}}, 407e5aaf047SAppaRao Puli {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 408e5aaf047SAppaRao Puli {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 409e5aaf047SAppaRao Puli {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 410e5aaf047SAppaRao Puli {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 411e5aaf047SAppaRao Puli } 412e5aaf047SAppaRao Puli 413e5aaf047SAppaRao Puli private: 414e5aaf047SAppaRao Puli void doGet(crow::Response& res, const crow::Request& req, 415e5aaf047SAppaRao Puli const std::vector<std::string>& params) override 416e5aaf047SAppaRao Puli { 417e5aaf047SAppaRao Puli auto asyncResp = std::make_shared<AsyncResp>(res); 418e5aaf047SAppaRao Puli if (params.size() != 1) 419e5aaf047SAppaRao Puli { 420e5aaf047SAppaRao Puli messages::internalError(asyncResp->res); 421e5aaf047SAppaRao Puli return; 422e5aaf047SAppaRao Puli } 423e5aaf047SAppaRao Puli 424b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 425b52664e2SAppaRao Puli EventServiceManager::getInstance().getSubscription(params[0]); 426b52664e2SAppaRao Puli if (subValue == nullptr) 427e5aaf047SAppaRao Puli { 428e5aaf047SAppaRao Puli res.result(boost::beast::http::status::not_found); 429e5aaf047SAppaRao Puli res.end(); 430e5aaf047SAppaRao Puli return; 431e5aaf047SAppaRao Puli } 432b52664e2SAppaRao Puli const std::string& id = params[0]; 433e5aaf047SAppaRao Puli 434e5aaf047SAppaRao Puli res.jsonValue = { 435e5aaf047SAppaRao Puli {"@odata.type", "#EventDestination.v1_7_0.EventDestination"}, 436e5aaf047SAppaRao Puli {"Protocol", "Redfish"}}; 437e5aaf047SAppaRao Puli asyncResp->res.jsonValue["@odata.id"] = 438e5aaf047SAppaRao Puli "/redfish/v1/EventService/Subscriptions/" + id; 439e5aaf047SAppaRao Puli asyncResp->res.jsonValue["Id"] = id; 440e5aaf047SAppaRao Puli asyncResp->res.jsonValue["Name"] = "Event Destination " + id; 441b52664e2SAppaRao Puli asyncResp->res.jsonValue["Destination"] = subValue->destinationUrl; 442b52664e2SAppaRao Puli asyncResp->res.jsonValue["Context"] = subValue->customText; 443e5aaf047SAppaRao Puli asyncResp->res.jsonValue["SubscriptionType"] = 444b52664e2SAppaRao Puli subValue->subscriptionType; 445b52664e2SAppaRao Puli asyncResp->res.jsonValue["HttpHeaders"] = subValue->httpHeaders; 446b52664e2SAppaRao Puli asyncResp->res.jsonValue["EventFormatType"] = subValue->eventFormatType; 447e5aaf047SAppaRao Puli asyncResp->res.jsonValue["RegistryPrefixes"] = 448b52664e2SAppaRao Puli subValue->registryPrefixes; 449b52664e2SAppaRao Puli asyncResp->res.jsonValue["MessageIds"] = subValue->registryMsgIds; 450b52664e2SAppaRao Puli asyncResp->res.jsonValue["DeliveryRetryPolicy"] = subValue->retryPolicy; 451*156d6b00SAppaRao Puli asyncResp->res.jsonValue["MetricReportDefinitions"] = 452*156d6b00SAppaRao Puli subValue->metricReportDefinitions; 453e5aaf047SAppaRao Puli } 454e5aaf047SAppaRao Puli 455e5aaf047SAppaRao Puli void doPatch(crow::Response& res, const crow::Request& req, 456e5aaf047SAppaRao Puli const std::vector<std::string>& params) override 457e5aaf047SAppaRao Puli { 458e5aaf047SAppaRao Puli auto asyncResp = std::make_shared<AsyncResp>(res); 459e5aaf047SAppaRao Puli if (params.size() != 1) 460e5aaf047SAppaRao Puli { 461e5aaf047SAppaRao Puli messages::internalError(asyncResp->res); 462e5aaf047SAppaRao Puli return; 463e5aaf047SAppaRao Puli } 464e5aaf047SAppaRao Puli 465b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 466b52664e2SAppaRao Puli EventServiceManager::getInstance().getSubscription(params[0]); 467b52664e2SAppaRao Puli if (subValue == nullptr) 468e5aaf047SAppaRao Puli { 469e5aaf047SAppaRao Puli res.result(boost::beast::http::status::not_found); 470e5aaf047SAppaRao Puli res.end(); 471e5aaf047SAppaRao Puli return; 472e5aaf047SAppaRao Puli } 473e5aaf047SAppaRao Puli 474e5aaf047SAppaRao Puli std::optional<std::string> context; 475e5aaf047SAppaRao Puli std::optional<std::string> retryPolicy; 476e5aaf047SAppaRao Puli std::optional<std::vector<nlohmann::json>> headers; 477e5aaf047SAppaRao Puli 478e5aaf047SAppaRao Puli if (!json_util::readJson(req, res, "Context", context, 479e5aaf047SAppaRao Puli "DeliveryRetryPolicy", retryPolicy, 480e5aaf047SAppaRao Puli "HttpHeaders", headers)) 481e5aaf047SAppaRao Puli { 482e5aaf047SAppaRao Puli return; 483e5aaf047SAppaRao Puli } 484e5aaf047SAppaRao Puli 485e5aaf047SAppaRao Puli if (context) 486e5aaf047SAppaRao Puli { 487b52664e2SAppaRao Puli subValue->customText = *context; 488e5aaf047SAppaRao Puli } 489e5aaf047SAppaRao Puli 490e5aaf047SAppaRao Puli if (headers) 491e5aaf047SAppaRao Puli { 492b52664e2SAppaRao Puli subValue->httpHeaders = *headers; 493e5aaf047SAppaRao Puli } 494e5aaf047SAppaRao Puli 495e5aaf047SAppaRao Puli if (retryPolicy) 496e5aaf047SAppaRao Puli { 497e5aaf047SAppaRao Puli if (std::find(supportedRetryPolicies.begin(), 498e5aaf047SAppaRao Puli supportedRetryPolicies.end(), 499e5aaf047SAppaRao Puli *retryPolicy) == supportedRetryPolicies.end()) 500e5aaf047SAppaRao Puli { 501e5aaf047SAppaRao Puli messages::propertyValueNotInList(asyncResp->res, *retryPolicy, 502e5aaf047SAppaRao Puli "DeliveryRetryPolicy"); 503e5aaf047SAppaRao Puli return; 504e5aaf047SAppaRao Puli } 505b52664e2SAppaRao Puli subValue->retryPolicy = *retryPolicy; 506e5aaf047SAppaRao Puli } 507e5aaf047SAppaRao Puli 508b52664e2SAppaRao Puli EventServiceManager::getInstance().updateSubscriptionData(); 509e5aaf047SAppaRao Puli } 510e5aaf047SAppaRao Puli 511e5aaf047SAppaRao Puli void doDelete(crow::Response& res, const crow::Request& req, 512e5aaf047SAppaRao Puli const std::vector<std::string>& params) override 513e5aaf047SAppaRao Puli { 514e5aaf047SAppaRao Puli auto asyncResp = std::make_shared<AsyncResp>(res); 515e5aaf047SAppaRao Puli 516e5aaf047SAppaRao Puli if (params.size() != 1) 517e5aaf047SAppaRao Puli { 518e5aaf047SAppaRao Puli messages::internalError(asyncResp->res); 519e5aaf047SAppaRao Puli return; 520e5aaf047SAppaRao Puli } 521e5aaf047SAppaRao Puli 522b52664e2SAppaRao Puli if (!EventServiceManager::getInstance().isSubscriptionExist(params[0])) 523e5aaf047SAppaRao Puli { 524e5aaf047SAppaRao Puli res.result(boost::beast::http::status::not_found); 525e5aaf047SAppaRao Puli res.end(); 526e5aaf047SAppaRao Puli return; 527e5aaf047SAppaRao Puli } 528b52664e2SAppaRao Puli EventServiceManager::getInstance().deleteSubscription(params[0]); 529e5aaf047SAppaRao Puli } 530e5aaf047SAppaRao Puli }; 531e5aaf047SAppaRao Puli 532e5aaf047SAppaRao Puli } // namespace redfish 533