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 197e860f15SJohn Edward Broadbent #include <app.hpp> 20ed398213SEd Tanous #include <registries/privilege_registry.hpp> 21ed398213SEd Tanous 22e5aaf047SAppaRao Puli namespace redfish 23e5aaf047SAppaRao Puli { 24e5aaf047SAppaRao Puli 25156d6b00SAppaRao Puli static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = { 26156d6b00SAppaRao Puli eventFormatType, metricReportFormatType}; 27e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRegPrefixes = { 28b304bd79SP Dheeraj Srujan Kumar "Base", "OpenBMC", "TaskEvent"}; 29e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRetryPolicies = { 30e5aaf047SAppaRao Puli "TerminateAfterRetries", "SuspendRetries", "RetryForever"}; 31e5aaf047SAppaRao Puli 32e56f254cSSunitha Harish #ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE 33e56f254cSSunitha Harish static constexpr const std::array<const char*, 2> supportedResourceTypes = { 34e56f254cSSunitha Harish "IBMConfigFile", "Task"}; 35e56f254cSSunitha Harish #else 36e56f254cSSunitha Harish static constexpr const std::array<const char*, 1> supportedResourceTypes = { 37e56f254cSSunitha Harish "Task"}; 38e56f254cSSunitha Harish #endif 39e56f254cSSunitha Harish 40e5aaf047SAppaRao Puli static constexpr const uint8_t maxNoOfSubscriptions = 20; 41e5aaf047SAppaRao Puli 427e860f15SJohn Edward Broadbent inline void requestRoutesEventService(App& app) 43e5aaf047SAppaRao Puli { 447e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/") 45ed398213SEd Tanous .privileges(redfish::privileges::getEventService) 467e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 477e860f15SJohn Edward Broadbent [](const crow::Request&, 487e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 498d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 50e5aaf047SAppaRao Puli {"@odata.type", "#EventService.v1_5_0.EventService"}, 51e5aaf047SAppaRao Puli {"Id", "EventService"}, 52e5aaf047SAppaRao Puli {"Name", "Event Service"}, 53e5aaf047SAppaRao Puli {"Subscriptions", 54e5aaf047SAppaRao Puli {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}}, 550b4bdd93SAppaRao Puli {"Actions", 560b4bdd93SAppaRao Puli {{"#EventService.SubmitTestEvent", 570b4bdd93SAppaRao Puli {{"target", "/redfish/v1/EventService/Actions/" 580b4bdd93SAppaRao Puli "EventService.SubmitTestEvent"}}}}}, 59e5aaf047SAppaRao Puli {"@odata.id", "/redfish/v1/EventService"}}; 60e5aaf047SAppaRao Puli 61*28afb49cSJunLin Chen const persistent_data::EventServiceConfig eventServiceConfig = 62*28afb49cSJunLin Chen persistent_data::EventServiceStore::getInstance() 63*28afb49cSJunLin Chen .getEventServiceConfig(); 647d1cc387SAppaRao Puli 657d1cc387SAppaRao Puli asyncResp->res.jsonValue["Status"]["State"] = 66*28afb49cSJunLin Chen (eventServiceConfig.enabled ? "Enabled" : "Disabled"); 67*28afb49cSJunLin Chen asyncResp->res.jsonValue["ServiceEnabled"] = 68*28afb49cSJunLin Chen eventServiceConfig.enabled; 697e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["DeliveryRetryAttempts"] = 70*28afb49cSJunLin Chen eventServiceConfig.retryAttempts; 71e5aaf047SAppaRao Puli asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] = 72*28afb49cSJunLin Chen eventServiceConfig.retryTimeoutInterval; 737e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["EventFormatTypes"] = 747e860f15SJohn Edward Broadbent supportedEvtFormatTypes; 757e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["RegistryPrefixes"] = 767e860f15SJohn Edward Broadbent supportedRegPrefixes; 777e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["ResourceTypes"] = 787e860f15SJohn Edward Broadbent supportedResourceTypes; 7907941a88SAyushi Smriti 8007941a88SAyushi Smriti nlohmann::json supportedSSEFilters = { 8107941a88SAyushi Smriti {"EventFormatType", true}, {"MessageId", true}, 8207941a88SAyushi Smriti {"MetricReportDefinition", true}, {"RegistryPrefix", true}, 8307941a88SAyushi Smriti {"OriginResource", false}, {"ResourceType", false}}; 8407941a88SAyushi Smriti 8507941a88SAyushi Smriti asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] = 8607941a88SAyushi Smriti supportedSSEFilters; 877e860f15SJohn Edward Broadbent }); 88e5aaf047SAppaRao Puli 897e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/") 90ed398213SEd Tanous .privileges(redfish::privileges::patchEventService) 917e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 927e860f15SJohn Edward Broadbent [](const crow::Request& req, 937e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 947e860f15SJohn Edward Broadbent 95e5aaf047SAppaRao Puli { 96e5aaf047SAppaRao Puli std::optional<bool> serviceEnabled; 97e5aaf047SAppaRao Puli std::optional<uint32_t> retryAttemps; 98e5aaf047SAppaRao Puli std::optional<uint32_t> retryInterval; 99e5aaf047SAppaRao Puli 1007e860f15SJohn Edward Broadbent if (!json_util::readJson( 1017e860f15SJohn Edward Broadbent req, asyncResp->res, "ServiceEnabled", serviceEnabled, 1027e860f15SJohn Edward Broadbent "DeliveryRetryAttempts", retryAttemps, 1037e860f15SJohn Edward Broadbent "DeliveryRetryIntervalSeconds", retryInterval)) 104e5aaf047SAppaRao Puli { 105e5aaf047SAppaRao Puli return; 106e5aaf047SAppaRao Puli } 107e5aaf047SAppaRao Puli 108*28afb49cSJunLin Chen persistent_data::EventServiceConfig eventServiceConfig = 109*28afb49cSJunLin Chen persistent_data::EventServiceStore::getInstance() 110*28afb49cSJunLin Chen .getEventServiceConfig(); 1117d1cc387SAppaRao Puli 112e5aaf047SAppaRao Puli if (serviceEnabled) 113e5aaf047SAppaRao Puli { 114*28afb49cSJunLin Chen eventServiceConfig.enabled = *serviceEnabled; 115e5aaf047SAppaRao Puli } 116e5aaf047SAppaRao Puli 117e5aaf047SAppaRao Puli if (retryAttemps) 118e5aaf047SAppaRao Puli { 119e5aaf047SAppaRao Puli // Supported range [1-3] 120e5aaf047SAppaRao Puli if ((*retryAttemps < 1) || (*retryAttemps > 3)) 121e5aaf047SAppaRao Puli { 122e5aaf047SAppaRao Puli messages::queryParameterOutOfRange( 123e5aaf047SAppaRao Puli asyncResp->res, std::to_string(*retryAttemps), 124e5aaf047SAppaRao Puli "DeliveryRetryAttempts", "[1-3]"); 125e5aaf047SAppaRao Puli } 126e5aaf047SAppaRao Puli else 127e5aaf047SAppaRao Puli { 128*28afb49cSJunLin Chen eventServiceConfig.retryAttempts = *retryAttemps; 129e5aaf047SAppaRao Puli } 130e5aaf047SAppaRao Puli } 131e5aaf047SAppaRao Puli 132e5aaf047SAppaRao Puli if (retryInterval) 133e5aaf047SAppaRao Puli { 134e5aaf047SAppaRao Puli // Supported range [30 - 180] 135e5aaf047SAppaRao Puli if ((*retryInterval < 30) || (*retryInterval > 180)) 136e5aaf047SAppaRao Puli { 137e5aaf047SAppaRao Puli messages::queryParameterOutOfRange( 138e5aaf047SAppaRao Puli asyncResp->res, std::to_string(*retryInterval), 139e5aaf047SAppaRao Puli "DeliveryRetryIntervalSeconds", "[30-180]"); 140e5aaf047SAppaRao Puli } 141e5aaf047SAppaRao Puli else 142e5aaf047SAppaRao Puli { 143*28afb49cSJunLin Chen eventServiceConfig.retryTimeoutInterval = 144*28afb49cSJunLin Chen *retryInterval; 145e5aaf047SAppaRao Puli } 146e5aaf047SAppaRao Puli } 147e5aaf047SAppaRao Puli 1487d1cc387SAppaRao Puli EventServiceManager::getInstance().setEventServiceConfig( 149*28afb49cSJunLin Chen eventServiceConfig); 1507e860f15SJohn Edward Broadbent }); 1510b4bdd93SAppaRao Puli } 1520b4bdd93SAppaRao Puli 1537e860f15SJohn Edward Broadbent inline void requestRoutesSubmitTestEvent(App& app) 1540b4bdd93SAppaRao Puli { 1557e860f15SJohn Edward Broadbent 1567e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 1577e860f15SJohn Edward Broadbent app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/") 158ed398213SEd Tanous .privileges(redfish::privileges::postEventService) 1597e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 1607e860f15SJohn Edward Broadbent [](const crow::Request&, 1617e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1620b4bdd93SAppaRao Puli EventServiceManager::getInstance().sendTestEventLog(); 1638d1b46d7Szhanghch05 asyncResp->res.result(boost::beast::http::status::no_content); 1647e860f15SJohn Edward Broadbent }); 165e5aaf047SAppaRao Puli } 166e5aaf047SAppaRao Puli 1677e860f15SJohn Edward Broadbent inline void requestRoutesEventDestinationCollection(App& app) 168e5aaf047SAppaRao Puli { 1697e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions") 170ed398213SEd Tanous .privileges(redfish::privileges::getEventDestinationCollection) 1717e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 1727e860f15SJohn Edward Broadbent [](const crow::Request&, 1737e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1748d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 175e5aaf047SAppaRao Puli {"@odata.type", 176e5aaf047SAppaRao Puli "#EventDestinationCollection.EventDestinationCollection"}, 177e5aaf047SAppaRao Puli {"@odata.id", "/redfish/v1/EventService/Subscriptions"}, 178e5aaf047SAppaRao Puli {"Name", "Event Destination Collections"}}; 179e5aaf047SAppaRao Puli 1807e860f15SJohn Edward Broadbent nlohmann::json& memberArray = 1817e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 182e5aaf047SAppaRao Puli 183b52664e2SAppaRao Puli std::vector<std::string> subscripIds = 184b52664e2SAppaRao Puli EventServiceManager::getInstance().getAllIDs(); 185b52664e2SAppaRao Puli memberArray = nlohmann::json::array(); 1867e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members@odata.count"] = 1877e860f15SJohn Edward Broadbent subscripIds.size(); 188b52664e2SAppaRao Puli 189b52664e2SAppaRao Puli for (const std::string& id : subscripIds) 190e5aaf047SAppaRao Puli { 191e5aaf047SAppaRao Puli memberArray.push_back( 192e5aaf047SAppaRao Puli {{"@odata.id", 193b52664e2SAppaRao Puli "/redfish/v1/EventService/Subscriptions/" + id}}); 194e5aaf047SAppaRao Puli } 1957e860f15SJohn Edward Broadbent }); 1967e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/") 197ed398213SEd Tanous // The below privilege is wrong, it should be ConfigureManager OR 198ed398213SEd Tanous // ConfigureComponents 199ed398213SEd Tanous //.privileges(redfish::privileges::postEventDestinationCollection) 200432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 2017e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 2027e860f15SJohn Edward Broadbent [](const crow::Request& req, 2037e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2047e860f15SJohn Edward Broadbent if (EventServiceManager::getInstance() 2057e860f15SJohn Edward Broadbent .getNumberOfSubscriptions() >= maxNoOfSubscriptions) 206e5aaf047SAppaRao Puli { 207e5aaf047SAppaRao Puli messages::eventSubscriptionLimitExceeded(asyncResp->res); 208e5aaf047SAppaRao Puli return; 209e5aaf047SAppaRao Puli } 210e5aaf047SAppaRao Puli std::string destUrl; 211e5aaf047SAppaRao Puli std::string protocol; 212e5aaf047SAppaRao Puli std::optional<std::string> context; 213e5aaf047SAppaRao Puli std::optional<std::string> subscriptionType; 21423a21a1cSEd Tanous std::optional<std::string> eventFormatType2; 215e5aaf047SAppaRao Puli std::optional<std::string> retryPolicy; 216e5aaf047SAppaRao Puli std::optional<std::vector<std::string>> msgIds; 217e5aaf047SAppaRao Puli std::optional<std::vector<std::string>> regPrefixes; 218e56f254cSSunitha Harish std::optional<std::vector<std::string>> resTypes; 219e5aaf047SAppaRao Puli std::optional<std::vector<nlohmann::json>> headers; 220144b6318SAppaRao Puli std::optional<std::vector<nlohmann::json>> mrdJsonArray; 221e5aaf047SAppaRao Puli 222e5aaf047SAppaRao Puli if (!json_util::readJson( 2237e860f15SJohn Edward Broadbent req, asyncResp->res, "Destination", destUrl, "Context", 2247e860f15SJohn Edward Broadbent context, "Protocol", protocol, "SubscriptionType", 2257e860f15SJohn Edward Broadbent subscriptionType, "EventFormatType", eventFormatType2, 2267e860f15SJohn Edward Broadbent "HttpHeaders", headers, "RegistryPrefixes", regPrefixes, 2277e860f15SJohn Edward Broadbent "MessageIds", msgIds, "DeliveryRetryPolicy", 2287e860f15SJohn Edward Broadbent retryPolicy, "MetricReportDefinitions", mrdJsonArray, 2297e860f15SJohn Edward Broadbent "ResourceTypes", resTypes)) 230e5aaf047SAppaRao Puli { 231e5aaf047SAppaRao Puli return; 232e5aaf047SAppaRao Puli } 233e5aaf047SAppaRao Puli 234dd28ba82SAppaRao Puli if (regPrefixes && msgIds) 235dd28ba82SAppaRao Puli { 236dd28ba82SAppaRao Puli if (regPrefixes->size() && msgIds->size()) 237dd28ba82SAppaRao Puli { 238dd28ba82SAppaRao Puli messages::mutualExclusiveProperties( 239dd28ba82SAppaRao Puli asyncResp->res, "RegistryPrefixes", "MessageIds"); 240dd28ba82SAppaRao Puli return; 241dd28ba82SAppaRao Puli } 242dd28ba82SAppaRao Puli } 243dd28ba82SAppaRao Puli 244e5aaf047SAppaRao Puli // Validate the URL using regex expression 245b52664e2SAppaRao Puli // Format: <protocol>://<host>:<port>/<uri> 246b52664e2SAppaRao Puli // protocol: http/https 247b52664e2SAppaRao Puli // host: Exclude ' ', ':', '#', '?' 2484e0453b1SGunnar Mills // port: Empty or numeric value with ':' separator. 249b52664e2SAppaRao Puli // uri: Start with '/' and Exclude '#', ' ' 250b52664e2SAppaRao Puli // Can include query params(ex: '/event?test=1') 251b52664e2SAppaRao Puli // TODO: Need to validate hostname extensively(as per rfc) 252b52664e2SAppaRao Puli const std::regex urlRegex( 253b52664e2SAppaRao Puli "(http|https)://([^/\\x20\\x3f\\x23\\x3a]+):?([0-9]*)(/" 254b52664e2SAppaRao Puli "([^\\x20\\x23\\x3f]*\\x3f?([^\\x20\\x23\\x3f])*)?)"); 255b52664e2SAppaRao Puli std::cmatch match; 256b52664e2SAppaRao Puli if (!std::regex_match(destUrl.c_str(), match, urlRegex)) 257e5aaf047SAppaRao Puli { 258e5aaf047SAppaRao Puli messages::propertyValueFormatError(asyncResp->res, destUrl, 259e5aaf047SAppaRao Puli "Destination"); 260e5aaf047SAppaRao Puli return; 261e5aaf047SAppaRao Puli } 262b52664e2SAppaRao Puli 2637e860f15SJohn Edward Broadbent std::string uriProto = 2647e860f15SJohn Edward Broadbent std::string(match[1].first, match[1].second); 265b52664e2SAppaRao Puli if (uriProto == "http") 266b52664e2SAppaRao Puli { 267b52664e2SAppaRao Puli #ifndef BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING 268b52664e2SAppaRao Puli messages::propertyValueFormatError(asyncResp->res, destUrl, 269b52664e2SAppaRao Puli "Destination"); 270b52664e2SAppaRao Puli return; 271b52664e2SAppaRao Puli #endif 272b52664e2SAppaRao Puli } 273b52664e2SAppaRao Puli 274b52664e2SAppaRao Puli std::string host = std::string(match[2].first, match[2].second); 275b52664e2SAppaRao Puli std::string port = std::string(match[3].first, match[3].second); 276b52664e2SAppaRao Puli std::string path = std::string(match[4].first, match[4].second); 277b52664e2SAppaRao Puli if (port.empty()) 278b52664e2SAppaRao Puli { 279b52664e2SAppaRao Puli if (uriProto == "http") 280b52664e2SAppaRao Puli { 281b52664e2SAppaRao Puli port = "80"; 282b52664e2SAppaRao Puli } 283b52664e2SAppaRao Puli else 284b52664e2SAppaRao Puli { 285b52664e2SAppaRao Puli port = "443"; 286b52664e2SAppaRao Puli } 287b52664e2SAppaRao Puli } 288b52664e2SAppaRao Puli if (path.empty()) 289b52664e2SAppaRao Puli { 290b52664e2SAppaRao Puli path = "/"; 291b52664e2SAppaRao Puli } 292b52664e2SAppaRao Puli 293b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 294b52664e2SAppaRao Puli std::make_shared<Subscription>(host, port, path, uriProto); 295b52664e2SAppaRao Puli 296b52664e2SAppaRao Puli subValue->destinationUrl = destUrl; 297e5aaf047SAppaRao Puli 298e5aaf047SAppaRao Puli if (subscriptionType) 299e5aaf047SAppaRao Puli { 300e5aaf047SAppaRao Puli if (*subscriptionType != "RedfishEvent") 301e5aaf047SAppaRao Puli { 3027e860f15SJohn Edward Broadbent messages::propertyValueNotInList(asyncResp->res, 3037e860f15SJohn Edward Broadbent *subscriptionType, 3047e860f15SJohn Edward Broadbent "SubscriptionType"); 305e5aaf047SAppaRao Puli return; 306e5aaf047SAppaRao Puli } 307b52664e2SAppaRao Puli subValue->subscriptionType = *subscriptionType; 308e5aaf047SAppaRao Puli } 309e5aaf047SAppaRao Puli else 310e5aaf047SAppaRao Puli { 311b52664e2SAppaRao Puli subValue->subscriptionType = "RedfishEvent"; // Default 312e5aaf047SAppaRao Puli } 313e5aaf047SAppaRao Puli 314e5aaf047SAppaRao Puli if (protocol != "Redfish") 315e5aaf047SAppaRao Puli { 316e5aaf047SAppaRao Puli messages::propertyValueNotInList(asyncResp->res, protocol, 317e5aaf047SAppaRao Puli "Protocol"); 318e5aaf047SAppaRao Puli return; 319e5aaf047SAppaRao Puli } 320b52664e2SAppaRao Puli subValue->protocol = protocol; 321e5aaf047SAppaRao Puli 32223a21a1cSEd Tanous if (eventFormatType2) 323e5aaf047SAppaRao Puli { 324e5aaf047SAppaRao Puli if (std::find(supportedEvtFormatTypes.begin(), 325e5aaf047SAppaRao Puli supportedEvtFormatTypes.end(), 3267e860f15SJohn Edward Broadbent *eventFormatType2) == 3277e860f15SJohn Edward Broadbent supportedEvtFormatTypes.end()) 328e5aaf047SAppaRao Puli { 3297e860f15SJohn Edward Broadbent messages::propertyValueNotInList(asyncResp->res, 3307e860f15SJohn Edward Broadbent *eventFormatType2, 3317e860f15SJohn Edward Broadbent "EventFormatType"); 332e5aaf047SAppaRao Puli return; 333e5aaf047SAppaRao Puli } 33423a21a1cSEd Tanous subValue->eventFormatType = *eventFormatType2; 335e5aaf047SAppaRao Puli } 336e5aaf047SAppaRao Puli else 337e5aaf047SAppaRao Puli { 338e5aaf047SAppaRao Puli // If not specified, use default "Event" 33923a21a1cSEd Tanous subValue->eventFormatType = "Event"; 340e5aaf047SAppaRao Puli } 341e5aaf047SAppaRao Puli 342e5aaf047SAppaRao Puli if (context) 343e5aaf047SAppaRao Puli { 344b52664e2SAppaRao Puli subValue->customText = *context; 345e5aaf047SAppaRao Puli } 346e5aaf047SAppaRao Puli 347e5aaf047SAppaRao Puli if (headers) 348e5aaf047SAppaRao Puli { 349b52664e2SAppaRao Puli subValue->httpHeaders = *headers; 350e5aaf047SAppaRao Puli } 351e5aaf047SAppaRao Puli 352e5aaf047SAppaRao Puli if (regPrefixes) 353e5aaf047SAppaRao Puli { 354e5aaf047SAppaRao Puli for (const std::string& it : *regPrefixes) 355e5aaf047SAppaRao Puli { 356e5aaf047SAppaRao Puli if (std::find(supportedRegPrefixes.begin(), 357e5aaf047SAppaRao Puli supportedRegPrefixes.end(), 358e5aaf047SAppaRao Puli it) == supportedRegPrefixes.end()) 359e5aaf047SAppaRao Puli { 3607e860f15SJohn Edward Broadbent messages::propertyValueNotInList( 3617e860f15SJohn Edward Broadbent asyncResp->res, it, "RegistryPrefixes"); 362e5aaf047SAppaRao Puli return; 363e5aaf047SAppaRao Puli } 364e5aaf047SAppaRao Puli } 365b52664e2SAppaRao Puli subValue->registryPrefixes = *regPrefixes; 366e5aaf047SAppaRao Puli } 367e5aaf047SAppaRao Puli 368e56f254cSSunitha Harish if (resTypes) 369e56f254cSSunitha Harish { 370e56f254cSSunitha Harish for (const std::string& it : *resTypes) 371e56f254cSSunitha Harish { 372e56f254cSSunitha Harish if (std::find(supportedResourceTypes.begin(), 373e56f254cSSunitha Harish supportedResourceTypes.end(), 374e56f254cSSunitha Harish it) == supportedResourceTypes.end()) 375e56f254cSSunitha Harish { 376e56f254cSSunitha Harish messages::propertyValueNotInList(asyncResp->res, it, 377e56f254cSSunitha Harish "ResourceTypes"); 378e56f254cSSunitha Harish return; 379e56f254cSSunitha Harish } 380e56f254cSSunitha Harish } 381e56f254cSSunitha Harish subValue->resourceTypes = *resTypes; 382e56f254cSSunitha Harish } 383e56f254cSSunitha Harish 384e5aaf047SAppaRao Puli if (msgIds) 385e5aaf047SAppaRao Puli { 386b304bd79SP Dheeraj Srujan Kumar std::vector<std::string> registryPrefix; 387b304bd79SP Dheeraj Srujan Kumar 3887e860f15SJohn Edward Broadbent // If no registry prefixes are mentioned, consider all 3897e860f15SJohn Edward Broadbent // supported prefixes 390b304bd79SP Dheeraj Srujan Kumar if (subValue->registryPrefixes.empty()) 391b304bd79SP Dheeraj Srujan Kumar { 392b304bd79SP Dheeraj Srujan Kumar registryPrefix.assign(supportedRegPrefixes.begin(), 393b304bd79SP Dheeraj Srujan Kumar supportedRegPrefixes.end()); 394b304bd79SP Dheeraj Srujan Kumar } 395b304bd79SP Dheeraj Srujan Kumar else 396b304bd79SP Dheeraj Srujan Kumar { 397b304bd79SP Dheeraj Srujan Kumar registryPrefix = subValue->registryPrefixes; 398b304bd79SP Dheeraj Srujan Kumar } 399b304bd79SP Dheeraj Srujan Kumar 400b304bd79SP Dheeraj Srujan Kumar for (const std::string& id : *msgIds) 401b304bd79SP Dheeraj Srujan Kumar { 402b304bd79SP Dheeraj Srujan Kumar bool validId = false; 403b304bd79SP Dheeraj Srujan Kumar 404b304bd79SP Dheeraj Srujan Kumar // Check for Message ID in each of the selected Registry 405b304bd79SP Dheeraj Srujan Kumar for (const std::string& it : registryPrefix) 406b304bd79SP Dheeraj Srujan Kumar { 407b304bd79SP Dheeraj Srujan Kumar const boost::beast::span< 408b304bd79SP Dheeraj Srujan Kumar const redfish::message_registries::MessageEntry> 4097e860f15SJohn Edward Broadbent registry = redfish::message_registries:: 4107e860f15SJohn Edward Broadbent getRegistryFromPrefix(it); 411b304bd79SP Dheeraj Srujan Kumar 412b304bd79SP Dheeraj Srujan Kumar if (std::any_of( 413b304bd79SP Dheeraj Srujan Kumar registry.cbegin(), registry.cend(), 4147e860f15SJohn Edward Broadbent [&id](const redfish::message_registries:: 4157e860f15SJohn Edward Broadbent MessageEntry& messageEntry) { 416b304bd79SP Dheeraj Srujan Kumar return !id.compare(messageEntry.first); 417b304bd79SP Dheeraj Srujan Kumar })) 418b304bd79SP Dheeraj Srujan Kumar { 419b304bd79SP Dheeraj Srujan Kumar validId = true; 420b304bd79SP Dheeraj Srujan Kumar break; 421b304bd79SP Dheeraj Srujan Kumar } 422b304bd79SP Dheeraj Srujan Kumar } 423b304bd79SP Dheeraj Srujan Kumar 424b304bd79SP Dheeraj Srujan Kumar if (!validId) 425b304bd79SP Dheeraj Srujan Kumar { 426b304bd79SP Dheeraj Srujan Kumar messages::propertyValueNotInList(asyncResp->res, id, 427b304bd79SP Dheeraj Srujan Kumar "MessageIds"); 428b304bd79SP Dheeraj Srujan Kumar return; 429b304bd79SP Dheeraj Srujan Kumar } 430b304bd79SP Dheeraj Srujan Kumar } 431b304bd79SP Dheeraj Srujan Kumar 432b52664e2SAppaRao Puli subValue->registryMsgIds = *msgIds; 433e5aaf047SAppaRao Puli } 434e5aaf047SAppaRao Puli 435e5aaf047SAppaRao Puli if (retryPolicy) 436e5aaf047SAppaRao Puli { 437e5aaf047SAppaRao Puli if (std::find(supportedRetryPolicies.begin(), 438e5aaf047SAppaRao Puli supportedRetryPolicies.end(), 439e5aaf047SAppaRao Puli *retryPolicy) == supportedRetryPolicies.end()) 440e5aaf047SAppaRao Puli { 4417e860f15SJohn Edward Broadbent messages::propertyValueNotInList(asyncResp->res, 4427e860f15SJohn Edward Broadbent *retryPolicy, 443e5aaf047SAppaRao Puli "DeliveryRetryPolicy"); 444e5aaf047SAppaRao Puli return; 445e5aaf047SAppaRao Puli } 446b52664e2SAppaRao Puli subValue->retryPolicy = *retryPolicy; 447e5aaf047SAppaRao Puli } 448e5aaf047SAppaRao Puli else 449e5aaf047SAppaRao Puli { 450e5aaf047SAppaRao Puli // Default "TerminateAfterRetries" 451b52664e2SAppaRao Puli subValue->retryPolicy = "TerminateAfterRetries"; 452e5aaf047SAppaRao Puli } 453e5aaf047SAppaRao Puli 454144b6318SAppaRao Puli if (mrdJsonArray) 455156d6b00SAppaRao Puli { 456144b6318SAppaRao Puli for (nlohmann::json& mrdObj : *mrdJsonArray) 457144b6318SAppaRao Puli { 458144b6318SAppaRao Puli std::string mrdUri; 4597e860f15SJohn Edward Broadbent if (json_util::getValueFromJsonObject( 4607e860f15SJohn Edward Broadbent mrdObj, "@odata.id", mrdUri)) 461144b6318SAppaRao Puli { 4627e860f15SJohn Edward Broadbent subValue->metricReportDefinitions.emplace_back( 4637e860f15SJohn Edward Broadbent mrdUri); 464144b6318SAppaRao Puli } 465144b6318SAppaRao Puli else 466144b6318SAppaRao Puli { 467144b6318SAppaRao Puli messages::propertyValueFormatError( 46871f52d96SEd Tanous asyncResp->res, 4697e860f15SJohn Edward Broadbent mrdObj.dump( 4707e860f15SJohn Edward Broadbent 2, ' ', true, 47171f52d96SEd Tanous nlohmann::json::error_handler_t::replace), 472144b6318SAppaRao Puli "MetricReportDefinitions"); 473144b6318SAppaRao Puli return; 474144b6318SAppaRao Puli } 475144b6318SAppaRao Puli } 476156d6b00SAppaRao Puli } 477156d6b00SAppaRao Puli 478b52664e2SAppaRao Puli std::string id = 4797e860f15SJohn Edward Broadbent EventServiceManager::getInstance().addSubscription( 4807e860f15SJohn Edward Broadbent subValue); 481b52664e2SAppaRao Puli if (id.empty()) 482e5aaf047SAppaRao Puli { 483e5aaf047SAppaRao Puli messages::internalError(asyncResp->res); 484e5aaf047SAppaRao Puli return; 485e5aaf047SAppaRao Puli } 486e5aaf047SAppaRao Puli 487e5aaf047SAppaRao Puli messages::created(asyncResp->res); 488e5aaf047SAppaRao Puli asyncResp->res.addHeader( 489e5aaf047SAppaRao Puli "Location", "/redfish/v1/EventService/Subscriptions/" + id); 4907e860f15SJohn Edward Broadbent }); 491e5aaf047SAppaRao Puli } 492e5aaf047SAppaRao Puli 4937e860f15SJohn Edward Broadbent inline void requestRoutesEventDestination(App& app) 494e5aaf047SAppaRao Puli { 4959d41aec6SRavi Teja BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 496ed398213SEd Tanous .privileges(redfish::privileges::getEventDestination) 4977e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 4987e860f15SJohn Edward Broadbent [](const crow::Request&, 4997e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5007e860f15SJohn Edward Broadbent const std::string& param) { 501b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 5027e860f15SJohn Edward Broadbent EventServiceManager::getInstance().getSubscription(param); 503b52664e2SAppaRao Puli if (subValue == nullptr) 504e5aaf047SAppaRao Puli { 5057e860f15SJohn Edward Broadbent asyncResp->res.result( 5067e860f15SJohn Edward Broadbent boost::beast::http::status::not_found); 507e5aaf047SAppaRao Puli return; 508e5aaf047SAppaRao Puli } 5097e860f15SJohn Edward Broadbent const std::string& id = param; 510e5aaf047SAppaRao Puli 5118d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 5127e860f15SJohn Edward Broadbent {"@odata.type", 5137e860f15SJohn Edward Broadbent "#EventDestination.v1_7_0.EventDestination"}, 514e5aaf047SAppaRao Puli {"Protocol", "Redfish"}}; 515e5aaf047SAppaRao Puli asyncResp->res.jsonValue["@odata.id"] = 516e5aaf047SAppaRao Puli "/redfish/v1/EventService/Subscriptions/" + id; 517e5aaf047SAppaRao Puli asyncResp->res.jsonValue["Id"] = id; 518e5aaf047SAppaRao Puli asyncResp->res.jsonValue["Name"] = "Event Destination " + id; 5197e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Destination"] = 5207e860f15SJohn Edward Broadbent subValue->destinationUrl; 521b52664e2SAppaRao Puli asyncResp->res.jsonValue["Context"] = subValue->customText; 522e5aaf047SAppaRao Puli asyncResp->res.jsonValue["SubscriptionType"] = 523b52664e2SAppaRao Puli subValue->subscriptionType; 524b52664e2SAppaRao Puli asyncResp->res.jsonValue["HttpHeaders"] = subValue->httpHeaders; 5257e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["EventFormatType"] = 5267e860f15SJohn Edward Broadbent subValue->eventFormatType; 527e5aaf047SAppaRao Puli asyncResp->res.jsonValue["RegistryPrefixes"] = 528b52664e2SAppaRao Puli subValue->registryPrefixes; 5297e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["ResourceTypes"] = 5307e860f15SJohn Edward Broadbent subValue->resourceTypes; 531e56f254cSSunitha Harish 5327e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["MessageIds"] = 5337e860f15SJohn Edward Broadbent subValue->registryMsgIds; 5347e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["DeliveryRetryPolicy"] = 5357e860f15SJohn Edward Broadbent subValue->retryPolicy; 536144b6318SAppaRao Puli 537144b6318SAppaRao Puli std::vector<nlohmann::json> mrdJsonArray; 538144b6318SAppaRao Puli for (const auto& mdrUri : subValue->metricReportDefinitions) 539144b6318SAppaRao Puli { 540144b6318SAppaRao Puli mrdJsonArray.push_back({{"@odata.id", mdrUri}}); 541144b6318SAppaRao Puli } 5427e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["MetricReportDefinitions"] = 5437e860f15SJohn Edward Broadbent mrdJsonArray; 5447e860f15SJohn Edward Broadbent }); 5457e860f15SJohn Edward Broadbent /////redfish/v1/EventService/Subscriptions/ 5467e860f15SJohn Edward Broadbent // ConfigureManager 5479d41aec6SRavi Teja BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 548ed398213SEd Tanous // The below privilege is wrong, it should be ConfigureManager OR 549ed398213SEd Tanous // ConfigureSelf 550ed398213SEd Tanous // TODO(ed) follow up with DMTF spec and understand ConfigureSelf 551ed398213SEd Tanous //.privileges(redfish::privileges::patchEventDestination) 552432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 5537e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 5547e860f15SJohn Edward Broadbent [](const crow::Request& req, 5557e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5567e860f15SJohn Edward Broadbent const std::string& param) { 557b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 5587e860f15SJohn Edward Broadbent EventServiceManager::getInstance().getSubscription(param); 559b52664e2SAppaRao Puli if (subValue == nullptr) 560e5aaf047SAppaRao Puli { 5617e860f15SJohn Edward Broadbent asyncResp->res.result( 5627e860f15SJohn Edward Broadbent boost::beast::http::status::not_found); 563e5aaf047SAppaRao Puli return; 564e5aaf047SAppaRao Puli } 565e5aaf047SAppaRao Puli 566e5aaf047SAppaRao Puli std::optional<std::string> context; 567e5aaf047SAppaRao Puli std::optional<std::string> retryPolicy; 568e5aaf047SAppaRao Puli std::optional<std::vector<nlohmann::json>> headers; 569e5aaf047SAppaRao Puli 5707e860f15SJohn Edward Broadbent if (!json_util::readJson(req, asyncResp->res, "Context", 5717e860f15SJohn Edward Broadbent context, "DeliveryRetryPolicy", 5727e860f15SJohn Edward Broadbent retryPolicy, "HttpHeaders", headers)) 573e5aaf047SAppaRao Puli { 574e5aaf047SAppaRao Puli return; 575e5aaf047SAppaRao Puli } 576e5aaf047SAppaRao Puli 577e5aaf047SAppaRao Puli if (context) 578e5aaf047SAppaRao Puli { 579b52664e2SAppaRao Puli subValue->customText = *context; 580e5aaf047SAppaRao Puli } 581e5aaf047SAppaRao Puli 582e5aaf047SAppaRao Puli if (headers) 583e5aaf047SAppaRao Puli { 584b52664e2SAppaRao Puli subValue->httpHeaders = *headers; 585e5aaf047SAppaRao Puli } 586e5aaf047SAppaRao Puli 587e5aaf047SAppaRao Puli if (retryPolicy) 588e5aaf047SAppaRao Puli { 589e5aaf047SAppaRao Puli if (std::find(supportedRetryPolicies.begin(), 590e5aaf047SAppaRao Puli supportedRetryPolicies.end(), 591e5aaf047SAppaRao Puli *retryPolicy) == supportedRetryPolicies.end()) 592e5aaf047SAppaRao Puli { 5937e860f15SJohn Edward Broadbent messages::propertyValueNotInList(asyncResp->res, 5947e860f15SJohn Edward Broadbent *retryPolicy, 595e5aaf047SAppaRao Puli "DeliveryRetryPolicy"); 596e5aaf047SAppaRao Puli return; 597e5aaf047SAppaRao Puli } 598b52664e2SAppaRao Puli subValue->retryPolicy = *retryPolicy; 599fe44eb0bSAyushi Smriti subValue->updateRetryPolicy(); 600e5aaf047SAppaRao Puli } 601e5aaf047SAppaRao Puli 602b52664e2SAppaRao Puli EventServiceManager::getInstance().updateSubscriptionData(); 6037e860f15SJohn Edward Broadbent }); 6049d41aec6SRavi Teja BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 605ed398213SEd Tanous // The below privilege is wrong, it should be ConfigureManager OR 606ed398213SEd Tanous // ConfigureSelf 607ed398213SEd Tanous //.privileges(redfish::privileges::deleteEventDestination) 608432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 6097e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 6107e860f15SJohn Edward Broadbent [](const crow::Request&, 6117e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6127e860f15SJohn Edward Broadbent const std::string& param) { 6137e860f15SJohn Edward Broadbent if (!EventServiceManager::getInstance().isSubscriptionExist( 6147e860f15SJohn Edward Broadbent param)) 615e5aaf047SAppaRao Puli { 6167e860f15SJohn Edward Broadbent asyncResp->res.result( 6177e860f15SJohn Edward Broadbent boost::beast::http::status::not_found); 618e5aaf047SAppaRao Puli return; 619e5aaf047SAppaRao Puli } 6207e860f15SJohn Edward Broadbent EventServiceManager::getInstance().deleteSubscription(param); 6217e860f15SJohn Edward Broadbent }); 622e5aaf047SAppaRao Puli } 623e5aaf047SAppaRao Puli 624e5aaf047SAppaRao Puli } // namespace redfish 625