1e5aaf047SAppaRao Puli /* 26be832e2SEd Tanous Copyright (c) 2020 Intel Corporation 36be832e2SEd Tanous 46be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License"); 56be832e2SEd Tanous you may not use this file except in compliance with the License. 66be832e2SEd Tanous You may obtain a copy of the License at 76be832e2SEd Tanous 86be832e2SEd Tanous http://www.apache.org/licenses/LICENSE-2.0 96be832e2SEd Tanous 106be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software 116be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS, 126be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136be832e2SEd Tanous See the License for the specific language governing permissions and 146be832e2SEd Tanous limitations under the License. 15e5aaf047SAppaRao Puli */ 16e5aaf047SAppaRao Puli #pragma once 173ccb3adbSEd Tanous #include "app.hpp" 18b52664e2SAppaRao Puli #include "event_service_manager.hpp" 19539d8c6bSEd Tanous #include "generated/enums/event_service.hpp" 203ccb3adbSEd Tanous #include "http/utility.hpp" 213ccb3adbSEd Tanous #include "logging.hpp" 223ccb3adbSEd Tanous #include "query.hpp" 233ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 243d30708fSChicago Duan #include "snmp_trap_event_clients.hpp" 25e5aaf047SAppaRao Puli 26601c71aeSEd Tanous #include <boost/beast/http/fields.hpp> 273d30708fSChicago Duan #include <boost/system/error_code.hpp> 28a716aa74SEd Tanous #include <boost/url/parse.hpp> 293d30708fSChicago Duan #include <sdbusplus/unpack_properties.hpp> 303d30708fSChicago Duan #include <utils/dbus_utils.hpp> 31ed398213SEd Tanous 323d30708fSChicago Duan #include <charconv> 333d30708fSChicago Duan #include <memory> 343544d2a7SEd Tanous #include <ranges> 351e270c5fSPatrick Williams #include <span> 363d30708fSChicago Duan #include <string> 37a14c9113SEd Tanous #include <vector> 381e270c5fSPatrick Williams 39e5aaf047SAppaRao Puli namespace redfish 40e5aaf047SAppaRao Puli { 41e5aaf047SAppaRao Puli 42156d6b00SAppaRao Puli static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = { 43156d6b00SAppaRao Puli eventFormatType, metricReportFormatType}; 44e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRegPrefixes = { 45b304bd79SP Dheeraj Srujan Kumar "Base", "OpenBMC", "TaskEvent"}; 46e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRetryPolicies = { 47e5aaf047SAppaRao Puli "TerminateAfterRetries", "SuspendRetries", "RetryForever"}; 48e5aaf047SAppaRao Puli 49e56f254cSSunitha Harish static constexpr const std::array<const char*, 1> supportedResourceTypes = { 50e56f254cSSunitha Harish "Task"}; 51e56f254cSSunitha Harish 527e860f15SJohn Edward Broadbent inline void requestRoutesEventService(App& app) 53e5aaf047SAppaRao Puli { 547e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/") 55ed398213SEd Tanous .privileges(redfish::privileges::getEventService) 56bd79bce8SPatrick Williams .methods( 57bd79bce8SPatrick Williams boost::beast::http::verb:: 58bd79bce8SPatrick Williams get)([&app]( 59bd79bce8SPatrick Williams const crow::Request& req, 60002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 613ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 6245ca1b86SEd Tanous { 6345ca1b86SEd Tanous return; 6445ca1b86SEd Tanous } 651476687dSEd Tanous 661476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/EventService"; 671476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 681476687dSEd Tanous "#EventService.v1_5_0.EventService"; 691476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "EventService"; 701476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Event Service"; 715e44e3d8SAppaRao Puli asyncResp->res.jsonValue["ServerSentEventUri"] = 725e44e3d8SAppaRao Puli "/redfish/v1/EventService/SSE"; 735e44e3d8SAppaRao Puli 741476687dSEd Tanous asyncResp->res.jsonValue["Subscriptions"]["@odata.id"] = 751476687dSEd Tanous "/redfish/v1/EventService/Subscriptions"; 76bd79bce8SPatrick Williams asyncResp->res.jsonValue["Actions"]["#EventService.SubmitTestEvent"] 77bd79bce8SPatrick Williams ["target"] = 781476687dSEd Tanous "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent"; 79e5aaf047SAppaRao Puli 8028afb49cSJunLin Chen const persistent_data::EventServiceConfig eventServiceConfig = 8128afb49cSJunLin Chen persistent_data::EventServiceStore::getInstance() 8228afb49cSJunLin Chen .getEventServiceConfig(); 837d1cc387SAppaRao Puli 847d1cc387SAppaRao Puli asyncResp->res.jsonValue["Status"]["State"] = 8528afb49cSJunLin Chen (eventServiceConfig.enabled ? "Enabled" : "Disabled"); 86bd79bce8SPatrick Williams asyncResp->res.jsonValue["ServiceEnabled"] = 87bd79bce8SPatrick Williams eventServiceConfig.enabled; 887e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["DeliveryRetryAttempts"] = 8928afb49cSJunLin Chen eventServiceConfig.retryAttempts; 90e5aaf047SAppaRao Puli asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] = 9128afb49cSJunLin Chen eventServiceConfig.retryTimeoutInterval; 92bd79bce8SPatrick Williams asyncResp->res.jsonValue["EventFormatTypes"] = 93bd79bce8SPatrick Williams supportedEvtFormatTypes; 940fda0f12SGeorge Liu asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes; 950fda0f12SGeorge Liu asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes; 9607941a88SAyushi Smriti 97613dabeaSEd Tanous nlohmann::json::object_t supportedSSEFilters; 98613dabeaSEd Tanous supportedSSEFilters["EventFormatType"] = true; 99613dabeaSEd Tanous supportedSSEFilters["MessageId"] = true; 100613dabeaSEd Tanous supportedSSEFilters["MetricReportDefinition"] = true; 101613dabeaSEd Tanous supportedSSEFilters["RegistryPrefix"] = true; 102613dabeaSEd Tanous supportedSSEFilters["OriginResource"] = false; 103613dabeaSEd Tanous supportedSSEFilters["ResourceType"] = false; 10407941a88SAyushi Smriti 10507941a88SAyushi Smriti asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] = 106613dabeaSEd Tanous std::move(supportedSSEFilters); 1077e860f15SJohn Edward Broadbent }); 108e5aaf047SAppaRao Puli 1097e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/") 110ed398213SEd Tanous .privileges(redfish::privileges::patchEventService) 1117e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 11245ca1b86SEd Tanous [&app](const crow::Request& req, 11345ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1143ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 115e5aaf047SAppaRao Puli { 11645ca1b86SEd Tanous return; 11745ca1b86SEd Tanous } 118e5aaf047SAppaRao Puli std::optional<bool> serviceEnabled; 119e5aaf047SAppaRao Puli std::optional<uint32_t> retryAttemps; 120e5aaf047SAppaRao Puli std::optional<uint32_t> retryInterval; 121afc474aeSMyung Bae if (!json_util::readJsonPatch( // 122afc474aeSMyung Bae req, asyncResp->res, // 123afc474aeSMyung Bae "DeliveryRetryAttempts", retryAttemps, // 124afc474aeSMyung Bae "DeliveryRetryIntervalSeconds", retryInterval, // 125afc474aeSMyung Bae "ServiceEnabled", serviceEnabled // 126afc474aeSMyung Bae )) 127e5aaf047SAppaRao Puli { 128e5aaf047SAppaRao Puli return; 129e5aaf047SAppaRao Puli } 130e5aaf047SAppaRao Puli 13128afb49cSJunLin Chen persistent_data::EventServiceConfig eventServiceConfig = 13228afb49cSJunLin Chen persistent_data::EventServiceStore::getInstance() 13328afb49cSJunLin Chen .getEventServiceConfig(); 1347d1cc387SAppaRao Puli 135e5aaf047SAppaRao Puli if (serviceEnabled) 136e5aaf047SAppaRao Puli { 13728afb49cSJunLin Chen eventServiceConfig.enabled = *serviceEnabled; 138e5aaf047SAppaRao Puli } 139e5aaf047SAppaRao Puli 140e5aaf047SAppaRao Puli if (retryAttemps) 141e5aaf047SAppaRao Puli { 142e5aaf047SAppaRao Puli // Supported range [1-3] 143e5aaf047SAppaRao Puli if ((*retryAttemps < 1) || (*retryAttemps > 3)) 144e5aaf047SAppaRao Puli { 145e5aaf047SAppaRao Puli messages::queryParameterOutOfRange( 146e5aaf047SAppaRao Puli asyncResp->res, std::to_string(*retryAttemps), 147e5aaf047SAppaRao Puli "DeliveryRetryAttempts", "[1-3]"); 148e5aaf047SAppaRao Puli } 149e5aaf047SAppaRao Puli else 150e5aaf047SAppaRao Puli { 15128afb49cSJunLin Chen eventServiceConfig.retryAttempts = *retryAttemps; 152e5aaf047SAppaRao Puli } 153e5aaf047SAppaRao Puli } 154e5aaf047SAppaRao Puli 155e5aaf047SAppaRao Puli if (retryInterval) 156e5aaf047SAppaRao Puli { 15733a32b34SGunnar Mills // Supported range [5 - 180] 15833a32b34SGunnar Mills if ((*retryInterval < 5) || (*retryInterval > 180)) 159e5aaf047SAppaRao Puli { 160e5aaf047SAppaRao Puli messages::queryParameterOutOfRange( 161e5aaf047SAppaRao Puli asyncResp->res, std::to_string(*retryInterval), 16233a32b34SGunnar Mills "DeliveryRetryIntervalSeconds", "[5-180]"); 163e5aaf047SAppaRao Puli } 164e5aaf047SAppaRao Puli else 165e5aaf047SAppaRao Puli { 166bd79bce8SPatrick Williams eventServiceConfig.retryTimeoutInterval = 167bd79bce8SPatrick Williams *retryInterval; 168e5aaf047SAppaRao Puli } 169e5aaf047SAppaRao Puli } 170e5aaf047SAppaRao Puli 1717d1cc387SAppaRao Puli EventServiceManager::getInstance().setEventServiceConfig( 17228afb49cSJunLin Chen eventServiceConfig); 1737e860f15SJohn Edward Broadbent }); 1740b4bdd93SAppaRao Puli } 1750b4bdd93SAppaRao Puli 1767e860f15SJohn Edward Broadbent inline void requestRoutesSubmitTestEvent(App& app) 1770b4bdd93SAppaRao Puli { 1787e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 1797e860f15SJohn Edward Broadbent app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/") 180ed398213SEd Tanous .privileges(redfish::privileges::postEventService) 1817e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 18245ca1b86SEd Tanous [&app](const crow::Request& req, 1837e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1843ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 18545ca1b86SEd Tanous { 18645ca1b86SEd Tanous return; 18745ca1b86SEd Tanous } 1886ba8c82eSsunharis_in if (!EventServiceManager::getInstance().sendTestEventLog()) 1896ba8c82eSsunharis_in { 1906ba8c82eSsunharis_in messages::serviceDisabled(asyncResp->res, 1916ba8c82eSsunharis_in "/redfish/v1/EventService/"); 1926ba8c82eSsunharis_in return; 1936ba8c82eSsunharis_in } 1948d1b46d7Szhanghch05 asyncResp->res.result(boost::beast::http::status::no_content); 1957e860f15SJohn Edward Broadbent }); 196e5aaf047SAppaRao Puli } 197e5aaf047SAppaRao Puli 1983d30708fSChicago Duan inline void doSubscriptionCollection( 199e81de512SEd Tanous const boost::system::error_code& ec, 2003d30708fSChicago Duan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2013d30708fSChicago Duan const dbus::utility::ManagedObjectType& resp) 2023d30708fSChicago Duan { 2033d30708fSChicago Duan if (ec) 2043d30708fSChicago Duan { 2051306101eSEd Tanous if (ec.value() == EBADR || ec.value() == EHOSTUNREACH) 2063d30708fSChicago Duan { 2073d30708fSChicago Duan // This is an optional process so just return if it isn't there 2083d30708fSChicago Duan return; 2093d30708fSChicago Duan } 2103d30708fSChicago Duan 21162598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus response error on GetManagedObjects {}", ec); 2123d30708fSChicago Duan messages::internalError(asyncResp->res); 2133d30708fSChicago Duan return; 2143d30708fSChicago Duan } 2153d30708fSChicago Duan nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"]; 2163d30708fSChicago Duan for (const auto& objpath : resp) 2173d30708fSChicago Duan { 2183d30708fSChicago Duan sdbusplus::message::object_path path(objpath.first); 2193d30708fSChicago Duan const std::string snmpId = path.filename(); 2203d30708fSChicago Duan if (snmpId.empty()) 2213d30708fSChicago Duan { 22262598e31SEd Tanous BMCWEB_LOG_ERROR("The SNMP client ID is wrong"); 2233d30708fSChicago Duan messages::internalError(asyncResp->res); 2243d30708fSChicago Duan return; 2253d30708fSChicago Duan } 2263d30708fSChicago Duan 2273d30708fSChicago Duan getSnmpSubscriptionList(asyncResp, snmpId, memberArray); 2283d30708fSChicago Duan } 2293d30708fSChicago Duan } 2303d30708fSChicago Duan 2317e860f15SJohn Edward Broadbent inline void requestRoutesEventDestinationCollection(App& app) 232e5aaf047SAppaRao Puli { 2331ebe3e41SGayathri Leburu BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/") 234ed398213SEd Tanous .privileges(redfish::privileges::getEventDestinationCollection) 2357e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 23645ca1b86SEd Tanous [&app](const crow::Request& req, 2377e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2383ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 23945ca1b86SEd Tanous { 24045ca1b86SEd Tanous return; 24145ca1b86SEd Tanous } 2421476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2431476687dSEd Tanous "#EventDestinationCollection.EventDestinationCollection"; 2441476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2451476687dSEd Tanous "/redfish/v1/EventService/Subscriptions"; 246bd79bce8SPatrick Williams asyncResp->res.jsonValue["Name"] = 247bd79bce8SPatrick Williams "Event Destination Collections"; 248e5aaf047SAppaRao Puli 249bd79bce8SPatrick Williams nlohmann::json& memberArray = 250bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"]; 251e5aaf047SAppaRao Puli 252b52664e2SAppaRao Puli std::vector<std::string> subscripIds = 253b52664e2SAppaRao Puli EventServiceManager::getInstance().getAllIDs(); 254b52664e2SAppaRao Puli memberArray = nlohmann::json::array(); 255bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members@odata.count"] = 256bd79bce8SPatrick Williams subscripIds.size(); 257b52664e2SAppaRao Puli 258b52664e2SAppaRao Puli for (const std::string& id : subscripIds) 259e5aaf047SAppaRao Puli { 2601476687dSEd Tanous nlohmann::json::object_t member; 2613d30708fSChicago Duan member["@odata.id"] = boost::urls::format( 2623d30708fSChicago Duan "/redfish/v1/EventService/Subscriptions/{}" + id); 263b2ba3072SPatrick Williams memberArray.emplace_back(std::move(member)); 264e5aaf047SAppaRao Puli } 2653d30708fSChicago Duan crow::connections::systemBus->async_method_call( 266e81de512SEd Tanous [asyncResp](const boost::system::error_code& ec, 2673d30708fSChicago Duan const dbus::utility::ManagedObjectType& resp) { 2683d30708fSChicago Duan doSubscriptionCollection(ec, asyncResp, resp); 2693d30708fSChicago Duan }, 2703d30708fSChicago Duan "xyz.openbmc_project.Network.SNMP", 2713d30708fSChicago Duan "/xyz/openbmc_project/network/snmp/manager", 2723d30708fSChicago Duan "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 2737e860f15SJohn Edward Broadbent }); 2743d30708fSChicago Duan 2757e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/") 2767eeafa76SAbhishek Patel .privileges(redfish::privileges::postEventDestinationCollection) 277bd79bce8SPatrick Williams .methods( 278bd79bce8SPatrick Williams boost::beast::http::verb:: 279bd79bce8SPatrick Williams post)([&app]( 280bd79bce8SPatrick Williams const crow::Request& req, 2817e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2823ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 28345ca1b86SEd Tanous { 28445ca1b86SEd Tanous return; 28545ca1b86SEd Tanous } 286fffb8c1fSEd Tanous if (EventServiceManager::getInstance().getNumberOfSubscriptions() >= 287fffb8c1fSEd Tanous maxNoOfSubscriptions) 288e5aaf047SAppaRao Puli { 289e5aaf047SAppaRao Puli messages::eventSubscriptionLimitExceeded(asyncResp->res); 290e5aaf047SAppaRao Puli return; 291e5aaf047SAppaRao Puli } 292e5aaf047SAppaRao Puli std::string destUrl; 293e5aaf047SAppaRao Puli std::string protocol; 29419bb362bSEd Tanous std::optional<bool> verifyCertificate; 295e5aaf047SAppaRao Puli std::optional<std::string> context; 296e5aaf047SAppaRao Puli std::optional<std::string> subscriptionType; 29723a21a1cSEd Tanous std::optional<std::string> eventFormatType2; 298e5aaf047SAppaRao Puli std::optional<std::string> retryPolicy; 299e5aaf047SAppaRao Puli std::optional<std::vector<std::string>> msgIds; 300e5aaf047SAppaRao Puli std::optional<std::vector<std::string>> regPrefixes; 301a14c9113SEd Tanous std::optional<std::vector<std::string>> originResources; 302e56f254cSSunitha Harish std::optional<std::vector<std::string>> resTypes; 30378d4ec4fSEd Tanous std::optional<std::vector<nlohmann::json::object_t>> headers; 30478d4ec4fSEd Tanous std::optional<std::vector<nlohmann::json::object_t>> mrdJsonArray; 305e5aaf047SAppaRao Puli 306afc474aeSMyung Bae if (!json_util::readJsonPatch( // 307afc474aeSMyung Bae req, asyncResp->res, // 308afc474aeSMyung Bae "Context", context, // 309afc474aeSMyung Bae "DeliveryRetryPolicy", retryPolicy, // 310afc474aeSMyung Bae "Destination", destUrl, // 311afc474aeSMyung Bae "EventFormatType", eventFormatType2, // 312afc474aeSMyung Bae "HttpHeaders", headers, // 313afc474aeSMyung Bae "MessageIds", msgIds, // 314afc474aeSMyung Bae "MetricReportDefinitions", mrdJsonArray, // 315afc474aeSMyung Bae "OriginResources", originResources, // 316afc474aeSMyung Bae "Protocol", protocol, // 317afc474aeSMyung Bae "RegistryPrefixes", regPrefixes, // 318afc474aeSMyung Bae "ResourceTypes", resTypes, // 319afc474aeSMyung Bae "SubscriptionType", subscriptionType, // 320afc474aeSMyung Bae "VerifyCertificate", verifyCertificate // 3214b712a29SEd Tanous )) 322e5aaf047SAppaRao Puli { 323e5aaf047SAppaRao Puli return; 324e5aaf047SAppaRao Puli } 3254b712a29SEd Tanous // clang-format on 326e5aaf047SAppaRao Puli 327600af5f1SAppaRao Puli // https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers 328600af5f1SAppaRao Puli static constexpr const uint16_t maxDestinationSize = 2000; 329600af5f1SAppaRao Puli if (destUrl.size() > maxDestinationSize) 330600af5f1SAppaRao Puli { 331600af5f1SAppaRao Puli messages::stringValueTooLong(asyncResp->res, "Destination", 332600af5f1SAppaRao Puli maxDestinationSize); 333600af5f1SAppaRao Puli return; 334600af5f1SAppaRao Puli } 335600af5f1SAppaRao Puli 336dd28ba82SAppaRao Puli if (regPrefixes && msgIds) 337dd28ba82SAppaRao Puli { 33826f6976fSEd Tanous if (!regPrefixes->empty() && !msgIds->empty()) 339dd28ba82SAppaRao Puli { 340bd79bce8SPatrick Williams messages::propertyValueConflict( 341bd79bce8SPatrick Williams asyncResp->res, "MessageIds", "RegistryPrefixes"); 342dd28ba82SAppaRao Puli return; 343dd28ba82SAppaRao Puli } 344dd28ba82SAppaRao Puli } 345dd28ba82SAppaRao Puli 3466fd29553SEd Tanous boost::system::result<boost::urls::url> url = 347a716aa74SEd Tanous boost::urls::parse_absolute_uri(destUrl); 348a716aa74SEd Tanous if (!url) 349e5aaf047SAppaRao Puli { 350bd79bce8SPatrick Williams BMCWEB_LOG_WARNING( 351bd79bce8SPatrick Williams "Failed to validate and split destination url"); 352e5aaf047SAppaRao Puli messages::propertyValueFormatError(asyncResp->res, destUrl, 353e5aaf047SAppaRao Puli "Destination"); 354e5aaf047SAppaRao Puli return; 355e5aaf047SAppaRao Puli } 356a716aa74SEd Tanous url->normalize(); 357*b07942e3SGeorge Liu 358*b07942e3SGeorge Liu // port_number returns zero if it is not a valid representable port 359*b07942e3SGeorge Liu if (url->has_port() && url->port_number() == 0) 360*b07942e3SGeorge Liu { 361*b07942e3SGeorge Liu BMCWEB_LOG_WARNING("{} is an invalid port in destination url", 362*b07942e3SGeorge Liu url->port()); 363*b07942e3SGeorge Liu messages::propertyValueFormatError(asyncResp->res, destUrl, 364*b07942e3SGeorge Liu "Destination"); 365*b07942e3SGeorge Liu return; 366*b07942e3SGeorge Liu } 367*b07942e3SGeorge Liu 368a716aa74SEd Tanous crow::utility::setProtocolDefaults(*url, protocol); 369a716aa74SEd Tanous crow::utility::setPortDefaults(*url); 370a716aa74SEd Tanous 371a716aa74SEd Tanous if (url->path().empty()) 372a716aa74SEd Tanous { 373a716aa74SEd Tanous url->set_path("/"); 374a716aa74SEd Tanous } 375a716aa74SEd Tanous 376a716aa74SEd Tanous if (url->has_userinfo()) 377a716aa74SEd Tanous { 378a716aa74SEd Tanous messages::propertyValueFormatError(asyncResp->res, destUrl, 379a716aa74SEd Tanous "Destination"); 380a716aa74SEd Tanous return; 381a716aa74SEd Tanous } 382b52664e2SAppaRao Puli 3833d30708fSChicago Duan if (protocol == "SNMPv2c") 3843d30708fSChicago Duan { 3853d30708fSChicago Duan if (context) 3863d30708fSChicago Duan { 3873d30708fSChicago Duan messages::propertyValueConflict(asyncResp->res, "Context", 3883d30708fSChicago Duan "Protocol"); 3893d30708fSChicago Duan return; 3903d30708fSChicago Duan } 3913d30708fSChicago Duan if (eventFormatType2) 3923d30708fSChicago Duan { 393bd79bce8SPatrick Williams messages::propertyValueConflict( 394bd79bce8SPatrick Williams asyncResp->res, "EventFormatType", "Protocol"); 3953d30708fSChicago Duan return; 3963d30708fSChicago Duan } 3973d30708fSChicago Duan if (retryPolicy) 3983d30708fSChicago Duan { 399bd79bce8SPatrick Williams messages::propertyValueConflict(asyncResp->res, 400bd79bce8SPatrick Williams "RetryPolicy", "Protocol"); 4013d30708fSChicago Duan return; 4023d30708fSChicago Duan } 4033d30708fSChicago Duan if (msgIds) 4043d30708fSChicago Duan { 405bd79bce8SPatrick Williams messages::propertyValueConflict(asyncResp->res, 406bd79bce8SPatrick Williams "MessageIds", "Protocol"); 4073d30708fSChicago Duan return; 4083d30708fSChicago Duan } 4093d30708fSChicago Duan if (regPrefixes) 4103d30708fSChicago Duan { 411bd79bce8SPatrick Williams messages::propertyValueConflict( 412bd79bce8SPatrick Williams asyncResp->res, "RegistryPrefixes", "Protocol"); 4133d30708fSChicago Duan return; 4143d30708fSChicago Duan } 4153d30708fSChicago Duan if (resTypes) 4163d30708fSChicago Duan { 417bd79bce8SPatrick Williams messages::propertyValueConflict( 418bd79bce8SPatrick Williams asyncResp->res, "ResourceTypes", "Protocol"); 4193d30708fSChicago Duan return; 4203d30708fSChicago Duan } 4213d30708fSChicago Duan if (headers) 4223d30708fSChicago Duan { 423bd79bce8SPatrick Williams messages::propertyValueConflict(asyncResp->res, 424bd79bce8SPatrick Williams "HttpHeaders", "Protocol"); 4253d30708fSChicago Duan return; 4263d30708fSChicago Duan } 4273d30708fSChicago Duan if (mrdJsonArray) 4283d30708fSChicago Duan { 4293d30708fSChicago Duan messages::propertyValueConflict( 4303d30708fSChicago Duan asyncResp->res, "MetricReportDefinitions", "Protocol"); 4313d30708fSChicago Duan return; 4323d30708fSChicago Duan } 433a716aa74SEd Tanous if (url->scheme() != "snmp") 434a716aa74SEd Tanous { 435bd79bce8SPatrick Williams messages::propertyValueConflict(asyncResp->res, 436bd79bce8SPatrick Williams "Destination", "Protocol"); 4373d30708fSChicago Duan return; 4383d30708fSChicago Duan } 4393d30708fSChicago Duan 440a716aa74SEd Tanous addSnmpTrapClient(asyncResp, url->host_address(), 441a716aa74SEd Tanous url->port_number()); 442a716aa74SEd Tanous return; 443b52664e2SAppaRao Puli } 4443d30708fSChicago Duan 445a716aa74SEd Tanous std::shared_ptr<Subscription> subValue = 44621a94d5cSMyung Bae std::make_shared<Subscription>( 44721a94d5cSMyung Bae persistent_data::UserSubscription{}, *url, app.ioContext()); 448b52664e2SAppaRao Puli 4494b712a29SEd Tanous subValue->userSub.destinationUrl = std::move(*url); 450e5aaf047SAppaRao Puli 451e5aaf047SAppaRao Puli if (subscriptionType) 452e5aaf047SAppaRao Puli { 453e5aaf047SAppaRao Puli if (*subscriptionType != "RedfishEvent") 454e5aaf047SAppaRao Puli { 455fffb8c1fSEd Tanous messages::propertyValueNotInList( 456fffb8c1fSEd Tanous asyncResp->res, *subscriptionType, "SubscriptionType"); 457e5aaf047SAppaRao Puli return; 458e5aaf047SAppaRao Puli } 4594b712a29SEd Tanous subValue->userSub.subscriptionType = *subscriptionType; 460e5aaf047SAppaRao Puli } 461e5aaf047SAppaRao Puli else 462e5aaf047SAppaRao Puli { 4634b712a29SEd Tanous // Default 4644b712a29SEd Tanous subValue->userSub.subscriptionType = "RedfishEvent"; 465e5aaf047SAppaRao Puli } 466e5aaf047SAppaRao Puli 467e5aaf047SAppaRao Puli if (protocol != "Redfish") 468e5aaf047SAppaRao Puli { 469e5aaf047SAppaRao Puli messages::propertyValueNotInList(asyncResp->res, protocol, 470e5aaf047SAppaRao Puli "Protocol"); 471e5aaf047SAppaRao Puli return; 472e5aaf047SAppaRao Puli } 4734b712a29SEd Tanous subValue->userSub.protocol = protocol; 474e5aaf047SAppaRao Puli 47519bb362bSEd Tanous if (verifyCertificate) 47619bb362bSEd Tanous { 4774b712a29SEd Tanous subValue->userSub.verifyCertificate = *verifyCertificate; 47819bb362bSEd Tanous } 47919bb362bSEd Tanous 48023a21a1cSEd Tanous if (eventFormatType2) 481e5aaf047SAppaRao Puli { 482bd79bce8SPatrick Williams if (std::ranges::find(supportedEvtFormatTypes, 483bd79bce8SPatrick Williams *eventFormatType2) == 4843544d2a7SEd Tanous supportedEvtFormatTypes.end()) 485e5aaf047SAppaRao Puli { 486fffb8c1fSEd Tanous messages::propertyValueNotInList( 487fffb8c1fSEd Tanous asyncResp->res, *eventFormatType2, "EventFormatType"); 488e5aaf047SAppaRao Puli return; 489e5aaf047SAppaRao Puli } 4904b712a29SEd Tanous subValue->userSub.eventFormatType = *eventFormatType2; 491e5aaf047SAppaRao Puli } 492e5aaf047SAppaRao Puli else 493e5aaf047SAppaRao Puli { 494e5aaf047SAppaRao Puli // If not specified, use default "Event" 4954b712a29SEd Tanous subValue->userSub.eventFormatType = "Event"; 496e5aaf047SAppaRao Puli } 497e5aaf047SAppaRao Puli 498e5aaf047SAppaRao Puli if (context) 499e5aaf047SAppaRao Puli { 5008ece0e45SEd Tanous // This value is selected arbitrarily. 501600af5f1SAppaRao Puli constexpr const size_t maxContextSize = 256; 502600af5f1SAppaRao Puli if (context->size() > maxContextSize) 503600af5f1SAppaRao Puli { 504600af5f1SAppaRao Puli messages::stringValueTooLong(asyncResp->res, "Context", 505600af5f1SAppaRao Puli maxContextSize); 506600af5f1SAppaRao Puli return; 507600af5f1SAppaRao Puli } 5084b712a29SEd Tanous subValue->userSub.customText = *context; 509e5aaf047SAppaRao Puli } 510e5aaf047SAppaRao Puli 511e5aaf047SAppaRao Puli if (headers) 512e5aaf047SAppaRao Puli { 513600af5f1SAppaRao Puli size_t cumulativeLen = 0; 514600af5f1SAppaRao Puli 51578d4ec4fSEd Tanous for (const nlohmann::json::object_t& headerChunk : *headers) 516601c71aeSEd Tanous { 51778d4ec4fSEd Tanous for (const auto& item : headerChunk) 51878d4ec4fSEd Tanous { 51978d4ec4fSEd Tanous const std::string* value = 52078d4ec4fSEd Tanous item.second.get_ptr<const std::string*>(); 52178d4ec4fSEd Tanous if (value == nullptr) 52278d4ec4fSEd Tanous { 52378d4ec4fSEd Tanous messages::propertyValueFormatError( 52478d4ec4fSEd Tanous asyncResp->res, item.second, 52578d4ec4fSEd Tanous "HttpHeaders/" + item.first); 52678d4ec4fSEd Tanous return; 52778d4ec4fSEd Tanous } 52878d4ec4fSEd Tanous // Adding a new json value is the size of the key, + 52978d4ec4fSEd Tanous // the size of the value + 2 * 2 quotes for each, + 53078d4ec4fSEd Tanous // the colon and space between. example: 53178d4ec4fSEd Tanous // "key": "value" 53278d4ec4fSEd Tanous cumulativeLen += item.first.size() + value->size() + 6; 533600af5f1SAppaRao Puli // This value is selected to mirror http_connection.hpp 534600af5f1SAppaRao Puli constexpr const uint16_t maxHeaderSizeED = 8096; 535600af5f1SAppaRao Puli if (cumulativeLen > maxHeaderSizeED) 536600af5f1SAppaRao Puli { 53778d4ec4fSEd Tanous messages::arraySizeTooLong( 53878d4ec4fSEd Tanous asyncResp->res, "HttpHeaders", maxHeaderSizeED); 539600af5f1SAppaRao Puli return; 540600af5f1SAppaRao Puli } 5414b712a29SEd Tanous subValue->userSub.httpHeaders.set(item.first, *value); 542601c71aeSEd Tanous } 543601c71aeSEd Tanous } 544e5aaf047SAppaRao Puli } 545e5aaf047SAppaRao Puli 546e5aaf047SAppaRao Puli if (regPrefixes) 547e5aaf047SAppaRao Puli { 548e5aaf047SAppaRao Puli for (const std::string& it : *regPrefixes) 549e5aaf047SAppaRao Puli { 5503544d2a7SEd Tanous if (std::ranges::find(supportedRegPrefixes, it) == 5513544d2a7SEd Tanous supportedRegPrefixes.end()) 552e5aaf047SAppaRao Puli { 553fffb8c1fSEd Tanous messages::propertyValueNotInList(asyncResp->res, it, 554fffb8c1fSEd Tanous "RegistryPrefixes"); 555e5aaf047SAppaRao Puli return; 556e5aaf047SAppaRao Puli } 557e5aaf047SAppaRao Puli } 5584b712a29SEd Tanous subValue->userSub.registryPrefixes = *regPrefixes; 559e5aaf047SAppaRao Puli } 560e5aaf047SAppaRao Puli 561a14c9113SEd Tanous if (originResources) 562a14c9113SEd Tanous { 5634b712a29SEd Tanous subValue->userSub.originResources = *originResources; 564a14c9113SEd Tanous } 565a14c9113SEd Tanous 566e56f254cSSunitha Harish if (resTypes) 567e56f254cSSunitha Harish { 568e56f254cSSunitha Harish for (const std::string& it : *resTypes) 569e56f254cSSunitha Harish { 5703544d2a7SEd Tanous if (std::ranges::find(supportedResourceTypes, it) == 5713544d2a7SEd Tanous supportedResourceTypes.end()) 572e56f254cSSunitha Harish { 573e56f254cSSunitha Harish messages::propertyValueNotInList(asyncResp->res, it, 574e56f254cSSunitha Harish "ResourceTypes"); 575e56f254cSSunitha Harish return; 576e56f254cSSunitha Harish } 577e56f254cSSunitha Harish } 5784b712a29SEd Tanous subValue->userSub.resourceTypes = *resTypes; 579e56f254cSSunitha Harish } 580e56f254cSSunitha Harish 581e5aaf047SAppaRao Puli if (msgIds) 582e5aaf047SAppaRao Puli { 583b304bd79SP Dheeraj Srujan Kumar std::vector<std::string> registryPrefix; 584b304bd79SP Dheeraj Srujan Kumar 5857e860f15SJohn Edward Broadbent // If no registry prefixes are mentioned, consider all 5867e860f15SJohn Edward Broadbent // supported prefixes 5874b712a29SEd Tanous if (subValue->userSub.registryPrefixes.empty()) 588b304bd79SP Dheeraj Srujan Kumar { 589b304bd79SP Dheeraj Srujan Kumar registryPrefix.assign(supportedRegPrefixes.begin(), 590b304bd79SP Dheeraj Srujan Kumar supportedRegPrefixes.end()); 591b304bd79SP Dheeraj Srujan Kumar } 592b304bd79SP Dheeraj Srujan Kumar else 593b304bd79SP Dheeraj Srujan Kumar { 5944b712a29SEd Tanous registryPrefix = subValue->userSub.registryPrefixes; 595b304bd79SP Dheeraj Srujan Kumar } 596b304bd79SP Dheeraj Srujan Kumar 597b304bd79SP Dheeraj Srujan Kumar for (const std::string& id : *msgIds) 598b304bd79SP Dheeraj Srujan Kumar { 599b304bd79SP Dheeraj Srujan Kumar bool validId = false; 600b304bd79SP Dheeraj Srujan Kumar 601b304bd79SP Dheeraj Srujan Kumar // Check for Message ID in each of the selected Registry 602b304bd79SP Dheeraj Srujan Kumar for (const std::string& it : registryPrefix) 603b304bd79SP Dheeraj Srujan Kumar { 604fffb8c1fSEd Tanous const std::span<const redfish::registries::MessageEntry> 605fffb8c1fSEd Tanous registry = 606fffb8c1fSEd Tanous redfish::registries::getRegistryFromPrefix(it); 607b304bd79SP Dheeraj Srujan Kumar 6083544d2a7SEd Tanous if (std::ranges::any_of( 6093544d2a7SEd Tanous registry, 610fffb8c1fSEd Tanous [&id](const redfish::registries::MessageEntry& 611fffb8c1fSEd Tanous messageEntry) { 61255f79e6fSEd Tanous return id == messageEntry.first; 613b304bd79SP Dheeraj Srujan Kumar })) 614b304bd79SP Dheeraj Srujan Kumar { 615b304bd79SP Dheeraj Srujan Kumar validId = true; 616b304bd79SP Dheeraj Srujan Kumar break; 617b304bd79SP Dheeraj Srujan Kumar } 618b304bd79SP Dheeraj Srujan Kumar } 619b304bd79SP Dheeraj Srujan Kumar 620b304bd79SP Dheeraj Srujan Kumar if (!validId) 621b304bd79SP Dheeraj Srujan Kumar { 622b304bd79SP Dheeraj Srujan Kumar messages::propertyValueNotInList(asyncResp->res, id, 623b304bd79SP Dheeraj Srujan Kumar "MessageIds"); 624b304bd79SP Dheeraj Srujan Kumar return; 625b304bd79SP Dheeraj Srujan Kumar } 626b304bd79SP Dheeraj Srujan Kumar } 627b304bd79SP Dheeraj Srujan Kumar 6284b712a29SEd Tanous subValue->userSub.registryMsgIds = *msgIds; 629e5aaf047SAppaRao Puli } 630e5aaf047SAppaRao Puli 631e5aaf047SAppaRao Puli if (retryPolicy) 632e5aaf047SAppaRao Puli { 6333544d2a7SEd Tanous if (std::ranges::find(supportedRetryPolicies, *retryPolicy) == 6343544d2a7SEd Tanous supportedRetryPolicies.end()) 635e5aaf047SAppaRao Puli { 636bd79bce8SPatrick Williams messages::propertyValueNotInList( 637bd79bce8SPatrick Williams asyncResp->res, *retryPolicy, "DeliveryRetryPolicy"); 638e5aaf047SAppaRao Puli return; 639e5aaf047SAppaRao Puli } 6404b712a29SEd Tanous subValue->userSub.retryPolicy = *retryPolicy; 641e5aaf047SAppaRao Puli } 642e5aaf047SAppaRao Puli else 643e5aaf047SAppaRao Puli { 644e5aaf047SAppaRao Puli // Default "TerminateAfterRetries" 6454b712a29SEd Tanous subValue->userSub.retryPolicy = "TerminateAfterRetries"; 646e5aaf047SAppaRao Puli } 647e5aaf047SAppaRao Puli 648144b6318SAppaRao Puli if (mrdJsonArray) 649156d6b00SAppaRao Puli { 65078d4ec4fSEd Tanous for (nlohmann::json::object_t& mrdObj : *mrdJsonArray) 651144b6318SAppaRao Puli { 652144b6318SAppaRao Puli std::string mrdUri; 653ea2e6eecSWilly Tu 65478d4ec4fSEd Tanous if (!json_util::readJsonObject(mrdObj, asyncResp->res, 65578d4ec4fSEd Tanous "@odata.id", mrdUri)) 656ea2e6eecSWilly Tu 657144b6318SAppaRao Puli { 658144b6318SAppaRao Puli return; 659144b6318SAppaRao Puli } 6604b712a29SEd Tanous subValue->userSub.metricReportDefinitions.emplace_back( 6614b712a29SEd Tanous mrdUri); 662144b6318SAppaRao Puli } 663156d6b00SAppaRao Puli } 664156d6b00SAppaRao Puli 665b52664e2SAppaRao Puli std::string id = 666bd79bce8SPatrick Williams EventServiceManager::getInstance().addPushSubscription( 667bd79bce8SPatrick Williams subValue); 668b52664e2SAppaRao Puli if (id.empty()) 669e5aaf047SAppaRao Puli { 670e5aaf047SAppaRao Puli messages::internalError(asyncResp->res); 671e5aaf047SAppaRao Puli return; 672e5aaf047SAppaRao Puli } 673e5aaf047SAppaRao Puli 674e5aaf047SAppaRao Puli messages::created(asyncResp->res); 675e5aaf047SAppaRao Puli asyncResp->res.addHeader( 676e5aaf047SAppaRao Puli "Location", "/redfish/v1/EventService/Subscriptions/" + id); 6777e860f15SJohn Edward Broadbent }); 678e5aaf047SAppaRao Puli } 679e5aaf047SAppaRao Puli 6807e860f15SJohn Edward Broadbent inline void requestRoutesEventDestination(App& app) 681e5aaf047SAppaRao Puli { 6829d41aec6SRavi Teja BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 683ed398213SEd Tanous .privileges(redfish::privileges::getEventDestination) 6847e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 68545ca1b86SEd Tanous [&app](const crow::Request& req, 6867e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6877e860f15SJohn Edward Broadbent const std::string& param) { 6883ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 68945ca1b86SEd Tanous { 69045ca1b86SEd Tanous return; 69145ca1b86SEd Tanous } 6923d30708fSChicago Duan 6933d30708fSChicago Duan if (param.starts_with("snmp")) 6943d30708fSChicago Duan { 6953d30708fSChicago Duan getSnmpTrapClient(asyncResp, param); 6963d30708fSChicago Duan return; 6973d30708fSChicago Duan } 6983d30708fSChicago Duan 699b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 7007e860f15SJohn Edward Broadbent EventServiceManager::getInstance().getSubscription(param); 701b52664e2SAppaRao Puli if (subValue == nullptr) 702e5aaf047SAppaRao Puli { 703bd79bce8SPatrick Williams asyncResp->res.result( 704bd79bce8SPatrick Williams boost::beast::http::status::not_found); 705e5aaf047SAppaRao Puli return; 706e5aaf047SAppaRao Puli } 7077e860f15SJohn Edward Broadbent const std::string& id = param; 708e5aaf047SAppaRao Puli 7094b712a29SEd Tanous const persistent_data::UserSubscription& userSub = 7104b712a29SEd Tanous subValue->userSub; 711e56f254cSSunitha Harish 7124b712a29SEd Tanous nlohmann::json& jVal = asyncResp->res.jsonValue; 7134b712a29SEd Tanous jVal["@odata.type"] = 7144b712a29SEd Tanous "#EventDestination.v1_14_1.EventDestination"; 7154b712a29SEd Tanous jVal["Protocol"] = 7164b712a29SEd Tanous event_destination::EventDestinationProtocol::Redfish; 7174b712a29SEd Tanous jVal["@odata.id"] = boost::urls::format( 7184b712a29SEd Tanous "/redfish/v1/EventService/Subscriptions/{}", id); 7194b712a29SEd Tanous jVal["Id"] = id; 7204b712a29SEd Tanous jVal["Name"] = "Event Destination " + id; 7214b712a29SEd Tanous jVal["Destination"] = userSub.destinationUrl; 7224b712a29SEd Tanous jVal["Context"] = userSub.customText; 7234b712a29SEd Tanous jVal["SubscriptionType"] = userSub.subscriptionType; 7244b712a29SEd Tanous jVal["HttpHeaders"] = nlohmann::json::array(); 7254b712a29SEd Tanous jVal["EventFormatType"] = userSub.eventFormatType; 7264b712a29SEd Tanous jVal["RegistryPrefixes"] = userSub.registryPrefixes; 7274b712a29SEd Tanous jVal["ResourceTypes"] = userSub.resourceTypes; 7284b712a29SEd Tanous 7294b712a29SEd Tanous jVal["MessageIds"] = userSub.registryMsgIds; 7304b712a29SEd Tanous jVal["DeliveryRetryPolicy"] = userSub.retryPolicy; 7314b712a29SEd Tanous jVal["VerifyCertificate"] = userSub.verifyCertificate; 732144b6318SAppaRao Puli 7331476687dSEd Tanous nlohmann::json::array_t mrdJsonArray; 7344b712a29SEd Tanous for (const auto& mdrUri : userSub.metricReportDefinitions) 735144b6318SAppaRao Puli { 7361476687dSEd Tanous nlohmann::json::object_t mdr; 7371476687dSEd Tanous mdr["@odata.id"] = mdrUri; 7381476687dSEd Tanous mrdJsonArray.emplace_back(std::move(mdr)); 739144b6318SAppaRao Puli } 7404b712a29SEd Tanous jVal["MetricReportDefinitions"] = mrdJsonArray; 7417e860f15SJohn Edward Broadbent }); 7429d41aec6SRavi Teja BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 743ed398213SEd Tanous // The below privilege is wrong, it should be ConfigureManager OR 744ed398213SEd Tanous // ConfigureSelf 7457eeafa76SAbhishek Patel // https://github.com/openbmc/bmcweb/issues/220 746ed398213SEd Tanous //.privileges(redfish::privileges::patchEventDestination) 747432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 7487e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 74945ca1b86SEd Tanous [&app](const crow::Request& req, 7507e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 7517e860f15SJohn Edward Broadbent const std::string& param) { 7523ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 75345ca1b86SEd Tanous { 75445ca1b86SEd Tanous return; 75545ca1b86SEd Tanous } 756b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 7577e860f15SJohn Edward Broadbent EventServiceManager::getInstance().getSubscription(param); 758b52664e2SAppaRao Puli if (subValue == nullptr) 759e5aaf047SAppaRao Puli { 760bd79bce8SPatrick Williams asyncResp->res.result( 761bd79bce8SPatrick Williams boost::beast::http::status::not_found); 762e5aaf047SAppaRao Puli return; 763e5aaf047SAppaRao Puli } 764e5aaf047SAppaRao Puli 765e5aaf047SAppaRao Puli std::optional<std::string> context; 766e5aaf047SAppaRao Puli std::optional<std::string> retryPolicy; 76719bb362bSEd Tanous std::optional<bool> verifyCertificate; 76878d4ec4fSEd Tanous std::optional<std::vector<nlohmann::json::object_t>> headers; 769e5aaf047SAppaRao Puli 770afc474aeSMyung Bae if (!json_util::readJsonPatch( // 771afc474aeSMyung Bae req, asyncResp->res, // 772afc474aeSMyung Bae "Context", context, // 773afc474aeSMyung Bae "DeliveryRetryPolicy", retryPolicy, // 774afc474aeSMyung Bae "HttpHeaders", headers, // 775afc474aeSMyung Bae "VerifyCertificate", verifyCertificate // 776afc474aeSMyung Bae )) 777e5aaf047SAppaRao Puli { 778e5aaf047SAppaRao Puli return; 779e5aaf047SAppaRao Puli } 780e5aaf047SAppaRao Puli 781e5aaf047SAppaRao Puli if (context) 782e5aaf047SAppaRao Puli { 7834b712a29SEd Tanous subValue->userSub.customText = *context; 784e5aaf047SAppaRao Puli } 785e5aaf047SAppaRao Puli 786e5aaf047SAppaRao Puli if (headers) 787e5aaf047SAppaRao Puli { 788601c71aeSEd Tanous boost::beast::http::fields fields; 78978d4ec4fSEd Tanous for (const nlohmann::json::object_t& headerChunk : *headers) 790601c71aeSEd Tanous { 79178d4ec4fSEd Tanous for (const auto& it : headerChunk) 792601c71aeSEd Tanous { 793601c71aeSEd Tanous const std::string* value = 79478d4ec4fSEd Tanous it.second.get_ptr<const std::string*>(); 795601c71aeSEd Tanous if (value == nullptr) 796601c71aeSEd Tanous { 797601c71aeSEd Tanous messages::propertyValueFormatError( 79878d4ec4fSEd Tanous asyncResp->res, it.second, 79978d4ec4fSEd Tanous "HttpHeaders/" + it.first); 800601c71aeSEd Tanous return; 801601c71aeSEd Tanous } 80278d4ec4fSEd Tanous fields.set(it.first, *value); 803601c71aeSEd Tanous } 804601c71aeSEd Tanous } 8054b712a29SEd Tanous subValue->userSub.httpHeaders = std::move(fields); 806e5aaf047SAppaRao Puli } 807e5aaf047SAppaRao Puli 808e5aaf047SAppaRao Puli if (retryPolicy) 809e5aaf047SAppaRao Puli { 810bd79bce8SPatrick Williams if (std::ranges::find(supportedRetryPolicies, 811bd79bce8SPatrick Williams *retryPolicy) == 8123544d2a7SEd Tanous supportedRetryPolicies.end()) 813e5aaf047SAppaRao Puli { 814bd79bce8SPatrick Williams messages::propertyValueNotInList(asyncResp->res, 815bd79bce8SPatrick Williams *retryPolicy, 816e5aaf047SAppaRao Puli "DeliveryRetryPolicy"); 817e5aaf047SAppaRao Puli return; 818e5aaf047SAppaRao Puli } 8194b712a29SEd Tanous subValue->userSub.retryPolicy = *retryPolicy; 820e5aaf047SAppaRao Puli } 821e5aaf047SAppaRao Puli 82219bb362bSEd Tanous if (verifyCertificate) 82319bb362bSEd Tanous { 8244b712a29SEd Tanous subValue->userSub.verifyCertificate = *verifyCertificate; 82519bb362bSEd Tanous } 82619bb362bSEd Tanous 82756ba386dSMyung Bae // Sync Subscription to UserSubscriptionConfig 82856ba386dSMyung Bae persistent_data::EventServiceStore::getInstance() 82956ba386dSMyung Bae .updateUserSubscriptionConfig(subValue->userSub); 83056ba386dSMyung Bae 831b52664e2SAppaRao Puli EventServiceManager::getInstance().updateSubscriptionData(); 8327e860f15SJohn Edward Broadbent }); 8339d41aec6SRavi Teja BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 834ed398213SEd Tanous // The below privilege is wrong, it should be ConfigureManager OR 835ed398213SEd Tanous // ConfigureSelf 8367eeafa76SAbhishek Patel // https://github.com/openbmc/bmcweb/issues/220 837ed398213SEd Tanous //.privileges(redfish::privileges::deleteEventDestination) 838432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 8397e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 84045ca1b86SEd Tanous [&app](const crow::Request& req, 8417e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8427e860f15SJohn Edward Broadbent const std::string& param) { 8433ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 84445ca1b86SEd Tanous { 84545ca1b86SEd Tanous return; 84645ca1b86SEd Tanous } 8474b712a29SEd Tanous EventServiceManager& event = EventServiceManager::getInstance(); 8483d30708fSChicago Duan if (param.starts_with("snmp")) 8493d30708fSChicago Duan { 8503d30708fSChicago Duan deleteSnmpTrapClient(asyncResp, param); 8514b712a29SEd Tanous event.deleteSubscription(param); 8523d30708fSChicago Duan return; 8533d30708fSChicago Duan } 8543d30708fSChicago Duan 8554b712a29SEd Tanous if (!event.deleteSubscription(param)) 856e5aaf047SAppaRao Puli { 8574b712a29SEd Tanous messages::resourceNotFound(asyncResp->res, 8584b712a29SEd Tanous "EventDestination", param); 859e5aaf047SAppaRao Puli return; 860e5aaf047SAppaRao Puli } 8614b712a29SEd Tanous messages::success(asyncResp->res); 8627e860f15SJohn Edward Broadbent }); 863e5aaf047SAppaRao Puli } 864e5aaf047SAppaRao Puli 865e5aaf047SAppaRao Puli } // namespace redfish 866