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 6128afb49cSJunLin Chen const persistent_data::EventServiceConfig eventServiceConfig = 6228afb49cSJunLin Chen persistent_data::EventServiceStore::getInstance() 6328afb49cSJunLin Chen .getEventServiceConfig(); 647d1cc387SAppaRao Puli 657d1cc387SAppaRao Puli asyncResp->res.jsonValue["Status"]["State"] = 6628afb49cSJunLin Chen (eventServiceConfig.enabled ? "Enabled" : "Disabled"); 6728afb49cSJunLin Chen asyncResp->res.jsonValue["ServiceEnabled"] = 6828afb49cSJunLin Chen eventServiceConfig.enabled; 697e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["DeliveryRetryAttempts"] = 7028afb49cSJunLin Chen eventServiceConfig.retryAttempts; 71e5aaf047SAppaRao Puli asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] = 7228afb49cSJunLin 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 10828afb49cSJunLin Chen persistent_data::EventServiceConfig eventServiceConfig = 10928afb49cSJunLin Chen persistent_data::EventServiceStore::getInstance() 11028afb49cSJunLin Chen .getEventServiceConfig(); 1117d1cc387SAppaRao Puli 112e5aaf047SAppaRao Puli if (serviceEnabled) 113e5aaf047SAppaRao Puli { 11428afb49cSJunLin 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 { 12828afb49cSJunLin 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 { 14328afb49cSJunLin Chen eventServiceConfig.retryTimeoutInterval = 14428afb49cSJunLin Chen *retryInterval; 145e5aaf047SAppaRao Puli } 146e5aaf047SAppaRao Puli } 147e5aaf047SAppaRao Puli 1487d1cc387SAppaRao Puli EventServiceManager::getInstance().setEventServiceConfig( 14928afb49cSJunLin 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/") 1977eeafa76SAbhishek Patel .privileges(redfish::privileges::postEventDestinationCollection) 1987e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 1997e860f15SJohn Edward Broadbent [](const crow::Request& req, 2007e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2017e860f15SJohn Edward Broadbent if (EventServiceManager::getInstance() 2027e860f15SJohn Edward Broadbent .getNumberOfSubscriptions() >= maxNoOfSubscriptions) 203e5aaf047SAppaRao Puli { 204e5aaf047SAppaRao Puli messages::eventSubscriptionLimitExceeded(asyncResp->res); 205e5aaf047SAppaRao Puli return; 206e5aaf047SAppaRao Puli } 207e5aaf047SAppaRao Puli std::string destUrl; 208e5aaf047SAppaRao Puli std::string protocol; 209e5aaf047SAppaRao Puli std::optional<std::string> context; 210e5aaf047SAppaRao Puli std::optional<std::string> subscriptionType; 21123a21a1cSEd Tanous std::optional<std::string> eventFormatType2; 212e5aaf047SAppaRao Puli std::optional<std::string> retryPolicy; 213e5aaf047SAppaRao Puli std::optional<std::vector<std::string>> msgIds; 214e5aaf047SAppaRao Puli std::optional<std::vector<std::string>> regPrefixes; 215e56f254cSSunitha Harish std::optional<std::vector<std::string>> resTypes; 216e5aaf047SAppaRao Puli std::optional<std::vector<nlohmann::json>> headers; 217144b6318SAppaRao Puli std::optional<std::vector<nlohmann::json>> mrdJsonArray; 218e5aaf047SAppaRao Puli 219e5aaf047SAppaRao Puli if (!json_util::readJson( 2207e860f15SJohn Edward Broadbent req, asyncResp->res, "Destination", destUrl, "Context", 2217e860f15SJohn Edward Broadbent context, "Protocol", protocol, "SubscriptionType", 2227e860f15SJohn Edward Broadbent subscriptionType, "EventFormatType", eventFormatType2, 2237e860f15SJohn Edward Broadbent "HttpHeaders", headers, "RegistryPrefixes", regPrefixes, 2247e860f15SJohn Edward Broadbent "MessageIds", msgIds, "DeliveryRetryPolicy", 2257e860f15SJohn Edward Broadbent retryPolicy, "MetricReportDefinitions", mrdJsonArray, 2267e860f15SJohn Edward Broadbent "ResourceTypes", resTypes)) 227e5aaf047SAppaRao Puli { 228e5aaf047SAppaRao Puli return; 229e5aaf047SAppaRao Puli } 230e5aaf047SAppaRao Puli 231dd28ba82SAppaRao Puli if (regPrefixes && msgIds) 232dd28ba82SAppaRao Puli { 233dd28ba82SAppaRao Puli if (regPrefixes->size() && msgIds->size()) 234dd28ba82SAppaRao Puli { 235dd28ba82SAppaRao Puli messages::mutualExclusiveProperties( 236dd28ba82SAppaRao Puli asyncResp->res, "RegistryPrefixes", "MessageIds"); 237dd28ba82SAppaRao Puli return; 238dd28ba82SAppaRao Puli } 239dd28ba82SAppaRao Puli } 240dd28ba82SAppaRao Puli 241e5aaf047SAppaRao Puli // Validate the URL using regex expression 242b52664e2SAppaRao Puli // Format: <protocol>://<host>:<port>/<uri> 243b52664e2SAppaRao Puli // protocol: http/https 244b52664e2SAppaRao Puli // host: Exclude ' ', ':', '#', '?' 2454e0453b1SGunnar Mills // port: Empty or numeric value with ':' separator. 246b52664e2SAppaRao Puli // uri: Start with '/' and Exclude '#', ' ' 247b52664e2SAppaRao Puli // Can include query params(ex: '/event?test=1') 248b52664e2SAppaRao Puli // TODO: Need to validate hostname extensively(as per rfc) 249b52664e2SAppaRao Puli const std::regex urlRegex( 250b52664e2SAppaRao Puli "(http|https)://([^/\\x20\\x3f\\x23\\x3a]+):?([0-9]*)(/" 251b52664e2SAppaRao Puli "([^\\x20\\x23\\x3f]*\\x3f?([^\\x20\\x23\\x3f])*)?)"); 252b52664e2SAppaRao Puli std::cmatch match; 253b52664e2SAppaRao Puli if (!std::regex_match(destUrl.c_str(), match, urlRegex)) 254e5aaf047SAppaRao Puli { 255e5aaf047SAppaRao Puli messages::propertyValueFormatError(asyncResp->res, destUrl, 256e5aaf047SAppaRao Puli "Destination"); 257e5aaf047SAppaRao Puli return; 258e5aaf047SAppaRao Puli } 259b52664e2SAppaRao Puli 2607e860f15SJohn Edward Broadbent std::string uriProto = 2617e860f15SJohn Edward Broadbent std::string(match[1].first, match[1].second); 262b52664e2SAppaRao Puli if (uriProto == "http") 263b52664e2SAppaRao Puli { 264b52664e2SAppaRao Puli #ifndef BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING 265b52664e2SAppaRao Puli messages::propertyValueFormatError(asyncResp->res, destUrl, 266b52664e2SAppaRao Puli "Destination"); 267b52664e2SAppaRao Puli return; 268b52664e2SAppaRao Puli #endif 269b52664e2SAppaRao Puli } 270b52664e2SAppaRao Puli 271b52664e2SAppaRao Puli std::string host = std::string(match[2].first, match[2].second); 272b52664e2SAppaRao Puli std::string port = std::string(match[3].first, match[3].second); 273b52664e2SAppaRao Puli std::string path = std::string(match[4].first, match[4].second); 274b52664e2SAppaRao Puli if (port.empty()) 275b52664e2SAppaRao Puli { 276b52664e2SAppaRao Puli if (uriProto == "http") 277b52664e2SAppaRao Puli { 278b52664e2SAppaRao Puli port = "80"; 279b52664e2SAppaRao Puli } 280b52664e2SAppaRao Puli else 281b52664e2SAppaRao Puli { 282b52664e2SAppaRao Puli port = "443"; 283b52664e2SAppaRao Puli } 284b52664e2SAppaRao Puli } 285b52664e2SAppaRao Puli if (path.empty()) 286b52664e2SAppaRao Puli { 287b52664e2SAppaRao Puli path = "/"; 288b52664e2SAppaRao Puli } 289b52664e2SAppaRao Puli 290b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 291b52664e2SAppaRao Puli std::make_shared<Subscription>(host, port, path, uriProto); 292b52664e2SAppaRao Puli 293b52664e2SAppaRao Puli subValue->destinationUrl = destUrl; 294e5aaf047SAppaRao Puli 295e5aaf047SAppaRao Puli if (subscriptionType) 296e5aaf047SAppaRao Puli { 297e5aaf047SAppaRao Puli if (*subscriptionType != "RedfishEvent") 298e5aaf047SAppaRao Puli { 2997e860f15SJohn Edward Broadbent messages::propertyValueNotInList(asyncResp->res, 3007e860f15SJohn Edward Broadbent *subscriptionType, 3017e860f15SJohn Edward Broadbent "SubscriptionType"); 302e5aaf047SAppaRao Puli return; 303e5aaf047SAppaRao Puli } 304b52664e2SAppaRao Puli subValue->subscriptionType = *subscriptionType; 305e5aaf047SAppaRao Puli } 306e5aaf047SAppaRao Puli else 307e5aaf047SAppaRao Puli { 308b52664e2SAppaRao Puli subValue->subscriptionType = "RedfishEvent"; // Default 309e5aaf047SAppaRao Puli } 310e5aaf047SAppaRao Puli 311e5aaf047SAppaRao Puli if (protocol != "Redfish") 312e5aaf047SAppaRao Puli { 313e5aaf047SAppaRao Puli messages::propertyValueNotInList(asyncResp->res, protocol, 314e5aaf047SAppaRao Puli "Protocol"); 315e5aaf047SAppaRao Puli return; 316e5aaf047SAppaRao Puli } 317b52664e2SAppaRao Puli subValue->protocol = protocol; 318e5aaf047SAppaRao Puli 31923a21a1cSEd Tanous if (eventFormatType2) 320e5aaf047SAppaRao Puli { 321e5aaf047SAppaRao Puli if (std::find(supportedEvtFormatTypes.begin(), 322e5aaf047SAppaRao Puli supportedEvtFormatTypes.end(), 3237e860f15SJohn Edward Broadbent *eventFormatType2) == 3247e860f15SJohn Edward Broadbent supportedEvtFormatTypes.end()) 325e5aaf047SAppaRao Puli { 3267e860f15SJohn Edward Broadbent messages::propertyValueNotInList(asyncResp->res, 3277e860f15SJohn Edward Broadbent *eventFormatType2, 3287e860f15SJohn Edward Broadbent "EventFormatType"); 329e5aaf047SAppaRao Puli return; 330e5aaf047SAppaRao Puli } 33123a21a1cSEd Tanous subValue->eventFormatType = *eventFormatType2; 332e5aaf047SAppaRao Puli } 333e5aaf047SAppaRao Puli else 334e5aaf047SAppaRao Puli { 335e5aaf047SAppaRao Puli // If not specified, use default "Event" 33623a21a1cSEd Tanous subValue->eventFormatType = "Event"; 337e5aaf047SAppaRao Puli } 338e5aaf047SAppaRao Puli 339e5aaf047SAppaRao Puli if (context) 340e5aaf047SAppaRao Puli { 341b52664e2SAppaRao Puli subValue->customText = *context; 342e5aaf047SAppaRao Puli } 343e5aaf047SAppaRao Puli 344e5aaf047SAppaRao Puli if (headers) 345e5aaf047SAppaRao Puli { 346b52664e2SAppaRao Puli subValue->httpHeaders = *headers; 347e5aaf047SAppaRao Puli } 348e5aaf047SAppaRao Puli 349e5aaf047SAppaRao Puli if (regPrefixes) 350e5aaf047SAppaRao Puli { 351e5aaf047SAppaRao Puli for (const std::string& it : *regPrefixes) 352e5aaf047SAppaRao Puli { 353e5aaf047SAppaRao Puli if (std::find(supportedRegPrefixes.begin(), 354e5aaf047SAppaRao Puli supportedRegPrefixes.end(), 355e5aaf047SAppaRao Puli it) == supportedRegPrefixes.end()) 356e5aaf047SAppaRao Puli { 3577e860f15SJohn Edward Broadbent messages::propertyValueNotInList( 3587e860f15SJohn Edward Broadbent asyncResp->res, it, "RegistryPrefixes"); 359e5aaf047SAppaRao Puli return; 360e5aaf047SAppaRao Puli } 361e5aaf047SAppaRao Puli } 362b52664e2SAppaRao Puli subValue->registryPrefixes = *regPrefixes; 363e5aaf047SAppaRao Puli } 364e5aaf047SAppaRao Puli 365e56f254cSSunitha Harish if (resTypes) 366e56f254cSSunitha Harish { 367e56f254cSSunitha Harish for (const std::string& it : *resTypes) 368e56f254cSSunitha Harish { 369e56f254cSSunitha Harish if (std::find(supportedResourceTypes.begin(), 370e56f254cSSunitha Harish supportedResourceTypes.end(), 371e56f254cSSunitha Harish it) == supportedResourceTypes.end()) 372e56f254cSSunitha Harish { 373e56f254cSSunitha Harish messages::propertyValueNotInList(asyncResp->res, it, 374e56f254cSSunitha Harish "ResourceTypes"); 375e56f254cSSunitha Harish return; 376e56f254cSSunitha Harish } 377e56f254cSSunitha Harish } 378e56f254cSSunitha Harish subValue->resourceTypes = *resTypes; 379e56f254cSSunitha Harish } 380e56f254cSSunitha Harish 381e5aaf047SAppaRao Puli if (msgIds) 382e5aaf047SAppaRao Puli { 383b304bd79SP Dheeraj Srujan Kumar std::vector<std::string> registryPrefix; 384b304bd79SP Dheeraj Srujan Kumar 3857e860f15SJohn Edward Broadbent // If no registry prefixes are mentioned, consider all 3867e860f15SJohn Edward Broadbent // supported prefixes 387b304bd79SP Dheeraj Srujan Kumar if (subValue->registryPrefixes.empty()) 388b304bd79SP Dheeraj Srujan Kumar { 389b304bd79SP Dheeraj Srujan Kumar registryPrefix.assign(supportedRegPrefixes.begin(), 390b304bd79SP Dheeraj Srujan Kumar supportedRegPrefixes.end()); 391b304bd79SP Dheeraj Srujan Kumar } 392b304bd79SP Dheeraj Srujan Kumar else 393b304bd79SP Dheeraj Srujan Kumar { 394b304bd79SP Dheeraj Srujan Kumar registryPrefix = subValue->registryPrefixes; 395b304bd79SP Dheeraj Srujan Kumar } 396b304bd79SP Dheeraj Srujan Kumar 397b304bd79SP Dheeraj Srujan Kumar for (const std::string& id : *msgIds) 398b304bd79SP Dheeraj Srujan Kumar { 399b304bd79SP Dheeraj Srujan Kumar bool validId = false; 400b304bd79SP Dheeraj Srujan Kumar 401b304bd79SP Dheeraj Srujan Kumar // Check for Message ID in each of the selected Registry 402b304bd79SP Dheeraj Srujan Kumar for (const std::string& it : registryPrefix) 403b304bd79SP Dheeraj Srujan Kumar { 404b304bd79SP Dheeraj Srujan Kumar const boost::beast::span< 405b304bd79SP Dheeraj Srujan Kumar const redfish::message_registries::MessageEntry> 4067e860f15SJohn Edward Broadbent registry = redfish::message_registries:: 4077e860f15SJohn Edward Broadbent getRegistryFromPrefix(it); 408b304bd79SP Dheeraj Srujan Kumar 409b304bd79SP Dheeraj Srujan Kumar if (std::any_of( 410b304bd79SP Dheeraj Srujan Kumar registry.cbegin(), registry.cend(), 4117e860f15SJohn Edward Broadbent [&id](const redfish::message_registries:: 4127e860f15SJohn Edward Broadbent MessageEntry& messageEntry) { 413b304bd79SP Dheeraj Srujan Kumar return !id.compare(messageEntry.first); 414b304bd79SP Dheeraj Srujan Kumar })) 415b304bd79SP Dheeraj Srujan Kumar { 416b304bd79SP Dheeraj Srujan Kumar validId = true; 417b304bd79SP Dheeraj Srujan Kumar break; 418b304bd79SP Dheeraj Srujan Kumar } 419b304bd79SP Dheeraj Srujan Kumar } 420b304bd79SP Dheeraj Srujan Kumar 421b304bd79SP Dheeraj Srujan Kumar if (!validId) 422b304bd79SP Dheeraj Srujan Kumar { 423b304bd79SP Dheeraj Srujan Kumar messages::propertyValueNotInList(asyncResp->res, id, 424b304bd79SP Dheeraj Srujan Kumar "MessageIds"); 425b304bd79SP Dheeraj Srujan Kumar return; 426b304bd79SP Dheeraj Srujan Kumar } 427b304bd79SP Dheeraj Srujan Kumar } 428b304bd79SP Dheeraj Srujan Kumar 429b52664e2SAppaRao Puli subValue->registryMsgIds = *msgIds; 430e5aaf047SAppaRao Puli } 431e5aaf047SAppaRao Puli 432e5aaf047SAppaRao Puli if (retryPolicy) 433e5aaf047SAppaRao Puli { 434e5aaf047SAppaRao Puli if (std::find(supportedRetryPolicies.begin(), 435e5aaf047SAppaRao Puli supportedRetryPolicies.end(), 436e5aaf047SAppaRao Puli *retryPolicy) == supportedRetryPolicies.end()) 437e5aaf047SAppaRao Puli { 4387e860f15SJohn Edward Broadbent messages::propertyValueNotInList(asyncResp->res, 4397e860f15SJohn Edward Broadbent *retryPolicy, 440e5aaf047SAppaRao Puli "DeliveryRetryPolicy"); 441e5aaf047SAppaRao Puli return; 442e5aaf047SAppaRao Puli } 443b52664e2SAppaRao Puli subValue->retryPolicy = *retryPolicy; 444e5aaf047SAppaRao Puli } 445e5aaf047SAppaRao Puli else 446e5aaf047SAppaRao Puli { 447e5aaf047SAppaRao Puli // Default "TerminateAfterRetries" 448b52664e2SAppaRao Puli subValue->retryPolicy = "TerminateAfterRetries"; 449e5aaf047SAppaRao Puli } 450e5aaf047SAppaRao Puli 451144b6318SAppaRao Puli if (mrdJsonArray) 452156d6b00SAppaRao Puli { 453144b6318SAppaRao Puli for (nlohmann::json& mrdObj : *mrdJsonArray) 454144b6318SAppaRao Puli { 455144b6318SAppaRao Puli std::string mrdUri; 4567e860f15SJohn Edward Broadbent if (json_util::getValueFromJsonObject( 4577e860f15SJohn Edward Broadbent mrdObj, "@odata.id", mrdUri)) 458144b6318SAppaRao Puli { 4597e860f15SJohn Edward Broadbent subValue->metricReportDefinitions.emplace_back( 4607e860f15SJohn Edward Broadbent mrdUri); 461144b6318SAppaRao Puli } 462144b6318SAppaRao Puli else 463144b6318SAppaRao Puli { 464144b6318SAppaRao Puli messages::propertyValueFormatError( 46571f52d96SEd Tanous asyncResp->res, 4667e860f15SJohn Edward Broadbent mrdObj.dump( 4677e860f15SJohn Edward Broadbent 2, ' ', true, 46871f52d96SEd Tanous nlohmann::json::error_handler_t::replace), 469144b6318SAppaRao Puli "MetricReportDefinitions"); 470144b6318SAppaRao Puli return; 471144b6318SAppaRao Puli } 472144b6318SAppaRao Puli } 473156d6b00SAppaRao Puli } 474156d6b00SAppaRao Puli 475b52664e2SAppaRao Puli std::string id = 4767e860f15SJohn Edward Broadbent EventServiceManager::getInstance().addSubscription( 4777e860f15SJohn Edward Broadbent subValue); 478b52664e2SAppaRao Puli if (id.empty()) 479e5aaf047SAppaRao Puli { 480e5aaf047SAppaRao Puli messages::internalError(asyncResp->res); 481e5aaf047SAppaRao Puli return; 482e5aaf047SAppaRao Puli } 483e5aaf047SAppaRao Puli 484e5aaf047SAppaRao Puli messages::created(asyncResp->res); 485e5aaf047SAppaRao Puli asyncResp->res.addHeader( 486e5aaf047SAppaRao Puli "Location", "/redfish/v1/EventService/Subscriptions/" + id); 4877e860f15SJohn Edward Broadbent }); 488e5aaf047SAppaRao Puli } 489e5aaf047SAppaRao Puli 4907e860f15SJohn Edward Broadbent inline void requestRoutesEventDestination(App& app) 491e5aaf047SAppaRao Puli { 4929d41aec6SRavi Teja BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 493ed398213SEd Tanous .privileges(redfish::privileges::getEventDestination) 4947e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 4957e860f15SJohn Edward Broadbent [](const crow::Request&, 4967e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 4977e860f15SJohn Edward Broadbent const std::string& param) { 498b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 4997e860f15SJohn Edward Broadbent EventServiceManager::getInstance().getSubscription(param); 500b52664e2SAppaRao Puli if (subValue == nullptr) 501e5aaf047SAppaRao Puli { 5027e860f15SJohn Edward Broadbent asyncResp->res.result( 5037e860f15SJohn Edward Broadbent boost::beast::http::status::not_found); 504e5aaf047SAppaRao Puli return; 505e5aaf047SAppaRao Puli } 5067e860f15SJohn Edward Broadbent const std::string& id = param; 507e5aaf047SAppaRao Puli 5088d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 5097e860f15SJohn Edward Broadbent {"@odata.type", 5107e860f15SJohn Edward Broadbent "#EventDestination.v1_7_0.EventDestination"}, 511e5aaf047SAppaRao Puli {"Protocol", "Redfish"}}; 512e5aaf047SAppaRao Puli asyncResp->res.jsonValue["@odata.id"] = 513e5aaf047SAppaRao Puli "/redfish/v1/EventService/Subscriptions/" + id; 514e5aaf047SAppaRao Puli asyncResp->res.jsonValue["Id"] = id; 515e5aaf047SAppaRao Puli asyncResp->res.jsonValue["Name"] = "Event Destination " + id; 5167e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Destination"] = 5177e860f15SJohn Edward Broadbent subValue->destinationUrl; 518b52664e2SAppaRao Puli asyncResp->res.jsonValue["Context"] = subValue->customText; 519e5aaf047SAppaRao Puli asyncResp->res.jsonValue["SubscriptionType"] = 520b52664e2SAppaRao Puli subValue->subscriptionType; 521*ad22fefeSEd Tanous asyncResp->res.jsonValue["HttpHeaders"] = 522*ad22fefeSEd Tanous nlohmann::json::array(); 5237e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["EventFormatType"] = 5247e860f15SJohn Edward Broadbent subValue->eventFormatType; 525e5aaf047SAppaRao Puli asyncResp->res.jsonValue["RegistryPrefixes"] = 526b52664e2SAppaRao Puli subValue->registryPrefixes; 5277e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["ResourceTypes"] = 5287e860f15SJohn Edward Broadbent subValue->resourceTypes; 529e56f254cSSunitha Harish 5307e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["MessageIds"] = 5317e860f15SJohn Edward Broadbent subValue->registryMsgIds; 5327e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["DeliveryRetryPolicy"] = 5337e860f15SJohn Edward Broadbent subValue->retryPolicy; 534144b6318SAppaRao Puli 535144b6318SAppaRao Puli std::vector<nlohmann::json> mrdJsonArray; 536144b6318SAppaRao Puli for (const auto& mdrUri : subValue->metricReportDefinitions) 537144b6318SAppaRao Puli { 538144b6318SAppaRao Puli mrdJsonArray.push_back({{"@odata.id", mdrUri}}); 539144b6318SAppaRao Puli } 5407e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["MetricReportDefinitions"] = 5417e860f15SJohn Edward Broadbent mrdJsonArray; 5427e860f15SJohn Edward Broadbent }); 5439d41aec6SRavi Teja BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 544ed398213SEd Tanous // The below privilege is wrong, it should be ConfigureManager OR 545ed398213SEd Tanous // ConfigureSelf 5467eeafa76SAbhishek Patel // https://github.com/openbmc/bmcweb/issues/220 547ed398213SEd Tanous //.privileges(redfish::privileges::patchEventDestination) 548432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 5497e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 5507e860f15SJohn Edward Broadbent [](const crow::Request& req, 5517e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5527e860f15SJohn Edward Broadbent const std::string& param) { 553b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 5547e860f15SJohn Edward Broadbent EventServiceManager::getInstance().getSubscription(param); 555b52664e2SAppaRao Puli if (subValue == nullptr) 556e5aaf047SAppaRao Puli { 5577e860f15SJohn Edward Broadbent asyncResp->res.result( 5587e860f15SJohn Edward Broadbent boost::beast::http::status::not_found); 559e5aaf047SAppaRao Puli return; 560e5aaf047SAppaRao Puli } 561e5aaf047SAppaRao Puli 562e5aaf047SAppaRao Puli std::optional<std::string> context; 563e5aaf047SAppaRao Puli std::optional<std::string> retryPolicy; 564e5aaf047SAppaRao Puli std::optional<std::vector<nlohmann::json>> headers; 565e5aaf047SAppaRao Puli 5667e860f15SJohn Edward Broadbent if (!json_util::readJson(req, asyncResp->res, "Context", 5677e860f15SJohn Edward Broadbent context, "DeliveryRetryPolicy", 5687e860f15SJohn Edward Broadbent retryPolicy, "HttpHeaders", headers)) 569e5aaf047SAppaRao Puli { 570e5aaf047SAppaRao Puli return; 571e5aaf047SAppaRao Puli } 572e5aaf047SAppaRao Puli 573e5aaf047SAppaRao Puli if (context) 574e5aaf047SAppaRao Puli { 575b52664e2SAppaRao Puli subValue->customText = *context; 576e5aaf047SAppaRao Puli } 577e5aaf047SAppaRao Puli 578e5aaf047SAppaRao Puli if (headers) 579e5aaf047SAppaRao Puli { 580b52664e2SAppaRao Puli subValue->httpHeaders = *headers; 581e5aaf047SAppaRao Puli } 582e5aaf047SAppaRao Puli 583e5aaf047SAppaRao Puli if (retryPolicy) 584e5aaf047SAppaRao Puli { 585e5aaf047SAppaRao Puli if (std::find(supportedRetryPolicies.begin(), 586e5aaf047SAppaRao Puli supportedRetryPolicies.end(), 587e5aaf047SAppaRao Puli *retryPolicy) == supportedRetryPolicies.end()) 588e5aaf047SAppaRao Puli { 5897e860f15SJohn Edward Broadbent messages::propertyValueNotInList(asyncResp->res, 5907e860f15SJohn Edward Broadbent *retryPolicy, 591e5aaf047SAppaRao Puli "DeliveryRetryPolicy"); 592e5aaf047SAppaRao Puli return; 593e5aaf047SAppaRao Puli } 594b52664e2SAppaRao Puli subValue->retryPolicy = *retryPolicy; 595fe44eb0bSAyushi Smriti subValue->updateRetryPolicy(); 596e5aaf047SAppaRao Puli } 597e5aaf047SAppaRao Puli 598b52664e2SAppaRao Puli EventServiceManager::getInstance().updateSubscriptionData(); 5997e860f15SJohn Edward Broadbent }); 6009d41aec6SRavi Teja BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 601ed398213SEd Tanous // The below privilege is wrong, it should be ConfigureManager OR 602ed398213SEd Tanous // ConfigureSelf 6037eeafa76SAbhishek Patel // https://github.com/openbmc/bmcweb/issues/220 604ed398213SEd Tanous //.privileges(redfish::privileges::deleteEventDestination) 605432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 6067e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 6077e860f15SJohn Edward Broadbent [](const crow::Request&, 6087e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6097e860f15SJohn Edward Broadbent const std::string& param) { 6107e860f15SJohn Edward Broadbent if (!EventServiceManager::getInstance().isSubscriptionExist( 6117e860f15SJohn Edward Broadbent param)) 612e5aaf047SAppaRao Puli { 6137e860f15SJohn Edward Broadbent asyncResp->res.result( 6147e860f15SJohn Edward Broadbent boost::beast::http::status::not_found); 615e5aaf047SAppaRao Puli return; 616e5aaf047SAppaRao Puli } 6177e860f15SJohn Edward Broadbent EventServiceManager::getInstance().deleteSubscription(param); 6187e860f15SJohn Edward Broadbent }); 619e5aaf047SAppaRao Puli } 620e5aaf047SAppaRao Puli 621e5aaf047SAppaRao Puli } // namespace redfish 622