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" 23*d109e2b6SAlexander Hansen #include "registries.hpp" 243ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 25*d109e2b6SAlexander Hansen #include "registries_selector.hpp" 263d30708fSChicago Duan #include "snmp_trap_event_clients.hpp" 27*d109e2b6SAlexander Hansen #include "utils/json_utils.hpp" 28e5aaf047SAppaRao Puli 29601c71aeSEd Tanous #include <boost/beast/http/fields.hpp> 303d30708fSChicago Duan #include <boost/system/error_code.hpp> 31a716aa74SEd Tanous #include <boost/url/parse.hpp> 323d30708fSChicago Duan #include <sdbusplus/unpack_properties.hpp> 333d30708fSChicago Duan #include <utils/dbus_utils.hpp> 34ed398213SEd Tanous 353d30708fSChicago Duan #include <charconv> 363d30708fSChicago Duan #include <memory> 373544d2a7SEd Tanous #include <ranges> 381e270c5fSPatrick Williams #include <span> 393d30708fSChicago Duan #include <string> 40a14c9113SEd Tanous #include <vector> 411e270c5fSPatrick Williams 42e5aaf047SAppaRao Puli namespace redfish 43e5aaf047SAppaRao Puli { 44e5aaf047SAppaRao Puli 45156d6b00SAppaRao Puli static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = { 46156d6b00SAppaRao Puli eventFormatType, metricReportFormatType}; 47e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRegPrefixes = { 48b304bd79SP Dheeraj Srujan Kumar "Base", "OpenBMC", "TaskEvent"}; 49e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRetryPolicies = { 50e5aaf047SAppaRao Puli "TerminateAfterRetries", "SuspendRetries", "RetryForever"}; 51e5aaf047SAppaRao Puli 52e56f254cSSunitha Harish static constexpr const std::array<const char*, 1> supportedResourceTypes = { 53e56f254cSSunitha Harish "Task"}; 54e56f254cSSunitha Harish 557e860f15SJohn Edward Broadbent inline void requestRoutesEventService(App& app) 56e5aaf047SAppaRao Puli { 577e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/") 58ed398213SEd Tanous .privileges(redfish::privileges::getEventService) 59bd79bce8SPatrick Williams .methods( 60bd79bce8SPatrick Williams boost::beast::http::verb:: 61bd79bce8SPatrick Williams get)([&app]( 62bd79bce8SPatrick Williams const crow::Request& req, 63002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 643ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 6545ca1b86SEd Tanous { 6645ca1b86SEd Tanous return; 6745ca1b86SEd Tanous } 681476687dSEd Tanous 691476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/EventService"; 701476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 711476687dSEd Tanous "#EventService.v1_5_0.EventService"; 721476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "EventService"; 731476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Event Service"; 745e44e3d8SAppaRao Puli asyncResp->res.jsonValue["ServerSentEventUri"] = 755e44e3d8SAppaRao Puli "/redfish/v1/EventService/SSE"; 765e44e3d8SAppaRao Puli 771476687dSEd Tanous asyncResp->res.jsonValue["Subscriptions"]["@odata.id"] = 781476687dSEd Tanous "/redfish/v1/EventService/Subscriptions"; 79bd79bce8SPatrick Williams asyncResp->res.jsonValue["Actions"]["#EventService.SubmitTestEvent"] 80bd79bce8SPatrick Williams ["target"] = 811476687dSEd Tanous "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent"; 82e5aaf047SAppaRao Puli 8328afb49cSJunLin Chen const persistent_data::EventServiceConfig eventServiceConfig = 8428afb49cSJunLin Chen persistent_data::EventServiceStore::getInstance() 8528afb49cSJunLin Chen .getEventServiceConfig(); 867d1cc387SAppaRao Puli 877d1cc387SAppaRao Puli asyncResp->res.jsonValue["Status"]["State"] = 8828afb49cSJunLin Chen (eventServiceConfig.enabled ? "Enabled" : "Disabled"); 89bd79bce8SPatrick Williams asyncResp->res.jsonValue["ServiceEnabled"] = 90bd79bce8SPatrick Williams eventServiceConfig.enabled; 917e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["DeliveryRetryAttempts"] = 9228afb49cSJunLin Chen eventServiceConfig.retryAttempts; 93e5aaf047SAppaRao Puli asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] = 9428afb49cSJunLin Chen eventServiceConfig.retryTimeoutInterval; 95bd79bce8SPatrick Williams asyncResp->res.jsonValue["EventFormatTypes"] = 96bd79bce8SPatrick Williams supportedEvtFormatTypes; 970fda0f12SGeorge Liu asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes; 980fda0f12SGeorge Liu asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes; 9907941a88SAyushi Smriti 100613dabeaSEd Tanous nlohmann::json::object_t supportedSSEFilters; 101613dabeaSEd Tanous supportedSSEFilters["EventFormatType"] = true; 102613dabeaSEd Tanous supportedSSEFilters["MessageId"] = true; 103613dabeaSEd Tanous supportedSSEFilters["MetricReportDefinition"] = true; 104613dabeaSEd Tanous supportedSSEFilters["RegistryPrefix"] = true; 105613dabeaSEd Tanous supportedSSEFilters["OriginResource"] = false; 106613dabeaSEd Tanous supportedSSEFilters["ResourceType"] = false; 10707941a88SAyushi Smriti 10807941a88SAyushi Smriti asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] = 109613dabeaSEd Tanous std::move(supportedSSEFilters); 1107e860f15SJohn Edward Broadbent }); 111e5aaf047SAppaRao Puli 1127e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/") 113ed398213SEd Tanous .privileges(redfish::privileges::patchEventService) 1147e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 11545ca1b86SEd Tanous [&app](const crow::Request& req, 11645ca1b86SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1173ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 118e5aaf047SAppaRao Puli { 11945ca1b86SEd Tanous return; 12045ca1b86SEd Tanous } 121e5aaf047SAppaRao Puli std::optional<bool> serviceEnabled; 122e5aaf047SAppaRao Puli std::optional<uint32_t> retryAttemps; 123e5aaf047SAppaRao Puli std::optional<uint32_t> retryInterval; 124afc474aeSMyung Bae if (!json_util::readJsonPatch( // 125afc474aeSMyung Bae req, asyncResp->res, // 126afc474aeSMyung Bae "DeliveryRetryAttempts", retryAttemps, // 127afc474aeSMyung Bae "DeliveryRetryIntervalSeconds", retryInterval, // 128afc474aeSMyung Bae "ServiceEnabled", serviceEnabled // 129afc474aeSMyung Bae )) 130e5aaf047SAppaRao Puli { 131e5aaf047SAppaRao Puli return; 132e5aaf047SAppaRao Puli } 133e5aaf047SAppaRao Puli 13428afb49cSJunLin Chen persistent_data::EventServiceConfig eventServiceConfig = 13528afb49cSJunLin Chen persistent_data::EventServiceStore::getInstance() 13628afb49cSJunLin Chen .getEventServiceConfig(); 1377d1cc387SAppaRao Puli 138e5aaf047SAppaRao Puli if (serviceEnabled) 139e5aaf047SAppaRao Puli { 14028afb49cSJunLin Chen eventServiceConfig.enabled = *serviceEnabled; 141e5aaf047SAppaRao Puli } 142e5aaf047SAppaRao Puli 143e5aaf047SAppaRao Puli if (retryAttemps) 144e5aaf047SAppaRao Puli { 145e5aaf047SAppaRao Puli // Supported range [1-3] 146e5aaf047SAppaRao Puli if ((*retryAttemps < 1) || (*retryAttemps > 3)) 147e5aaf047SAppaRao Puli { 148e5aaf047SAppaRao Puli messages::queryParameterOutOfRange( 149e5aaf047SAppaRao Puli asyncResp->res, std::to_string(*retryAttemps), 150e5aaf047SAppaRao Puli "DeliveryRetryAttempts", "[1-3]"); 151e5aaf047SAppaRao Puli } 152e5aaf047SAppaRao Puli else 153e5aaf047SAppaRao Puli { 15428afb49cSJunLin Chen eventServiceConfig.retryAttempts = *retryAttemps; 155e5aaf047SAppaRao Puli } 156e5aaf047SAppaRao Puli } 157e5aaf047SAppaRao Puli 158e5aaf047SAppaRao Puli if (retryInterval) 159e5aaf047SAppaRao Puli { 16033a32b34SGunnar Mills // Supported range [5 - 180] 16133a32b34SGunnar Mills if ((*retryInterval < 5) || (*retryInterval > 180)) 162e5aaf047SAppaRao Puli { 163e5aaf047SAppaRao Puli messages::queryParameterOutOfRange( 164e5aaf047SAppaRao Puli asyncResp->res, std::to_string(*retryInterval), 16533a32b34SGunnar Mills "DeliveryRetryIntervalSeconds", "[5-180]"); 166e5aaf047SAppaRao Puli } 167e5aaf047SAppaRao Puli else 168e5aaf047SAppaRao Puli { 169bd79bce8SPatrick Williams eventServiceConfig.retryTimeoutInterval = 170bd79bce8SPatrick Williams *retryInterval; 171e5aaf047SAppaRao Puli } 172e5aaf047SAppaRao Puli } 173e5aaf047SAppaRao Puli 1747d1cc387SAppaRao Puli EventServiceManager::getInstance().setEventServiceConfig( 17528afb49cSJunLin Chen eventServiceConfig); 1767e860f15SJohn Edward Broadbent }); 1770b4bdd93SAppaRao Puli } 1780b4bdd93SAppaRao Puli 1797e860f15SJohn Edward Broadbent inline void requestRoutesSubmitTestEvent(App& app) 1800b4bdd93SAppaRao Puli { 1817e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 1827e860f15SJohn Edward Broadbent app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/") 183ed398213SEd Tanous .privileges(redfish::privileges::postEventService) 1847e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 18545ca1b86SEd Tanous [&app](const crow::Request& req, 1867e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1873ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 18845ca1b86SEd Tanous { 18945ca1b86SEd Tanous return; 19045ca1b86SEd Tanous } 1916ba8c82eSsunharis_in if (!EventServiceManager::getInstance().sendTestEventLog()) 1926ba8c82eSsunharis_in { 1936ba8c82eSsunharis_in messages::serviceDisabled(asyncResp->res, 1946ba8c82eSsunharis_in "/redfish/v1/EventService/"); 1956ba8c82eSsunharis_in return; 1966ba8c82eSsunharis_in } 1978d1b46d7Szhanghch05 asyncResp->res.result(boost::beast::http::status::no_content); 1987e860f15SJohn Edward Broadbent }); 199e5aaf047SAppaRao Puli } 200e5aaf047SAppaRao Puli 2013d30708fSChicago Duan inline void doSubscriptionCollection( 202e81de512SEd Tanous const boost::system::error_code& ec, 2033d30708fSChicago Duan const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2043d30708fSChicago Duan const dbus::utility::ManagedObjectType& resp) 2053d30708fSChicago Duan { 2063d30708fSChicago Duan if (ec) 2073d30708fSChicago Duan { 2081306101eSEd Tanous if (ec.value() == EBADR || ec.value() == EHOSTUNREACH) 2093d30708fSChicago Duan { 2103d30708fSChicago Duan // This is an optional process so just return if it isn't there 2113d30708fSChicago Duan return; 2123d30708fSChicago Duan } 2133d30708fSChicago Duan 21462598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus response error on GetManagedObjects {}", ec); 2153d30708fSChicago Duan messages::internalError(asyncResp->res); 2163d30708fSChicago Duan return; 2173d30708fSChicago Duan } 2183d30708fSChicago Duan nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"]; 2193d30708fSChicago Duan for (const auto& objpath : resp) 2203d30708fSChicago Duan { 2213d30708fSChicago Duan sdbusplus::message::object_path path(objpath.first); 2223d30708fSChicago Duan const std::string snmpId = path.filename(); 2233d30708fSChicago Duan if (snmpId.empty()) 2243d30708fSChicago Duan { 22562598e31SEd Tanous BMCWEB_LOG_ERROR("The SNMP client ID is wrong"); 2263d30708fSChicago Duan messages::internalError(asyncResp->res); 2273d30708fSChicago Duan return; 2283d30708fSChicago Duan } 2293d30708fSChicago Duan 2303d30708fSChicago Duan getSnmpSubscriptionList(asyncResp, snmpId, memberArray); 2313d30708fSChicago Duan } 2323d30708fSChicago Duan } 2333d30708fSChicago Duan 2347e860f15SJohn Edward Broadbent inline void requestRoutesEventDestinationCollection(App& app) 235e5aaf047SAppaRao Puli { 2361ebe3e41SGayathri Leburu BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/") 237ed398213SEd Tanous .privileges(redfish::privileges::getEventDestinationCollection) 2387e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 23945ca1b86SEd Tanous [&app](const crow::Request& req, 2407e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2413ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 24245ca1b86SEd Tanous { 24345ca1b86SEd Tanous return; 24445ca1b86SEd Tanous } 2451476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2461476687dSEd Tanous "#EventDestinationCollection.EventDestinationCollection"; 2471476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2481476687dSEd Tanous "/redfish/v1/EventService/Subscriptions"; 249bd79bce8SPatrick Williams asyncResp->res.jsonValue["Name"] = 250bd79bce8SPatrick Williams "Event Destination Collections"; 251e5aaf047SAppaRao Puli 252bd79bce8SPatrick Williams nlohmann::json& memberArray = 253bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"]; 254e5aaf047SAppaRao Puli 255b52664e2SAppaRao Puli std::vector<std::string> subscripIds = 256b52664e2SAppaRao Puli EventServiceManager::getInstance().getAllIDs(); 257b52664e2SAppaRao Puli memberArray = nlohmann::json::array(); 258bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members@odata.count"] = 259bd79bce8SPatrick Williams subscripIds.size(); 260b52664e2SAppaRao Puli 261b52664e2SAppaRao Puli for (const std::string& id : subscripIds) 262e5aaf047SAppaRao Puli { 2631476687dSEd Tanous nlohmann::json::object_t member; 2643d30708fSChicago Duan member["@odata.id"] = boost::urls::format( 2653d30708fSChicago Duan "/redfish/v1/EventService/Subscriptions/{}" + id); 266b2ba3072SPatrick Williams memberArray.emplace_back(std::move(member)); 267e5aaf047SAppaRao Puli } 2683d30708fSChicago Duan crow::connections::systemBus->async_method_call( 269e81de512SEd Tanous [asyncResp](const boost::system::error_code& ec, 2703d30708fSChicago Duan const dbus::utility::ManagedObjectType& resp) { 2713d30708fSChicago Duan doSubscriptionCollection(ec, asyncResp, resp); 2723d30708fSChicago Duan }, 2733d30708fSChicago Duan "xyz.openbmc_project.Network.SNMP", 2743d30708fSChicago Duan "/xyz/openbmc_project/network/snmp/manager", 2753d30708fSChicago Duan "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 2767e860f15SJohn Edward Broadbent }); 2773d30708fSChicago Duan 2787e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/") 2797eeafa76SAbhishek Patel .privileges(redfish::privileges::postEventDestinationCollection) 280bd79bce8SPatrick Williams .methods( 281bd79bce8SPatrick Williams boost::beast::http::verb:: 282bd79bce8SPatrick Williams post)([&app]( 283bd79bce8SPatrick Williams const crow::Request& req, 2847e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2853ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 28645ca1b86SEd Tanous { 28745ca1b86SEd Tanous return; 28845ca1b86SEd Tanous } 289fffb8c1fSEd Tanous if (EventServiceManager::getInstance().getNumberOfSubscriptions() >= 290fffb8c1fSEd Tanous maxNoOfSubscriptions) 291e5aaf047SAppaRao Puli { 292e5aaf047SAppaRao Puli messages::eventSubscriptionLimitExceeded(asyncResp->res); 293e5aaf047SAppaRao Puli return; 294e5aaf047SAppaRao Puli } 295e5aaf047SAppaRao Puli std::string destUrl; 296e5aaf047SAppaRao Puli std::string protocol; 29719bb362bSEd Tanous std::optional<bool> verifyCertificate; 298e5aaf047SAppaRao Puli std::optional<std::string> context; 299e5aaf047SAppaRao Puli std::optional<std::string> subscriptionType; 30023a21a1cSEd Tanous std::optional<std::string> eventFormatType2; 301e5aaf047SAppaRao Puli std::optional<std::string> retryPolicy; 302e5aaf047SAppaRao Puli std::optional<std::vector<std::string>> msgIds; 303e5aaf047SAppaRao Puli std::optional<std::vector<std::string>> regPrefixes; 304a14c9113SEd Tanous std::optional<std::vector<std::string>> originResources; 305e56f254cSSunitha Harish std::optional<std::vector<std::string>> resTypes; 30678d4ec4fSEd Tanous std::optional<std::vector<nlohmann::json::object_t>> headers; 30778d4ec4fSEd Tanous std::optional<std::vector<nlohmann::json::object_t>> mrdJsonArray; 308e5aaf047SAppaRao Puli 309afc474aeSMyung Bae if (!json_util::readJsonPatch( // 310afc474aeSMyung Bae req, asyncResp->res, // 311afc474aeSMyung Bae "Context", context, // 312afc474aeSMyung Bae "DeliveryRetryPolicy", retryPolicy, // 313afc474aeSMyung Bae "Destination", destUrl, // 314afc474aeSMyung Bae "EventFormatType", eventFormatType2, // 315afc474aeSMyung Bae "HttpHeaders", headers, // 316afc474aeSMyung Bae "MessageIds", msgIds, // 317afc474aeSMyung Bae "MetricReportDefinitions", mrdJsonArray, // 318afc474aeSMyung Bae "OriginResources", originResources, // 319afc474aeSMyung Bae "Protocol", protocol, // 320afc474aeSMyung Bae "RegistryPrefixes", regPrefixes, // 321afc474aeSMyung Bae "ResourceTypes", resTypes, // 322afc474aeSMyung Bae "SubscriptionType", subscriptionType, // 323afc474aeSMyung Bae "VerifyCertificate", verifyCertificate // 3244b712a29SEd Tanous )) 325e5aaf047SAppaRao Puli { 326e5aaf047SAppaRao Puli return; 327e5aaf047SAppaRao Puli } 3284b712a29SEd Tanous // clang-format on 329e5aaf047SAppaRao Puli 330600af5f1SAppaRao Puli // https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers 331600af5f1SAppaRao Puli static constexpr const uint16_t maxDestinationSize = 2000; 332600af5f1SAppaRao Puli if (destUrl.size() > maxDestinationSize) 333600af5f1SAppaRao Puli { 334600af5f1SAppaRao Puli messages::stringValueTooLong(asyncResp->res, "Destination", 335600af5f1SAppaRao Puli maxDestinationSize); 336600af5f1SAppaRao Puli return; 337600af5f1SAppaRao Puli } 338600af5f1SAppaRao Puli 339dd28ba82SAppaRao Puli if (regPrefixes && msgIds) 340dd28ba82SAppaRao Puli { 34126f6976fSEd Tanous if (!regPrefixes->empty() && !msgIds->empty()) 342dd28ba82SAppaRao Puli { 343bd79bce8SPatrick Williams messages::propertyValueConflict( 344bd79bce8SPatrick Williams asyncResp->res, "MessageIds", "RegistryPrefixes"); 345dd28ba82SAppaRao Puli return; 346dd28ba82SAppaRao Puli } 347dd28ba82SAppaRao Puli } 348dd28ba82SAppaRao Puli 3496fd29553SEd Tanous boost::system::result<boost::urls::url> url = 350a716aa74SEd Tanous boost::urls::parse_absolute_uri(destUrl); 351a716aa74SEd Tanous if (!url) 352e5aaf047SAppaRao Puli { 353bd79bce8SPatrick Williams BMCWEB_LOG_WARNING( 354bd79bce8SPatrick Williams "Failed to validate and split destination url"); 355e5aaf047SAppaRao Puli messages::propertyValueFormatError(asyncResp->res, destUrl, 356e5aaf047SAppaRao Puli "Destination"); 357e5aaf047SAppaRao Puli return; 358e5aaf047SAppaRao Puli } 359a716aa74SEd Tanous url->normalize(); 360b07942e3SGeorge Liu 361b07942e3SGeorge Liu // port_number returns zero if it is not a valid representable port 362b07942e3SGeorge Liu if (url->has_port() && url->port_number() == 0) 363b07942e3SGeorge Liu { 364b07942e3SGeorge Liu BMCWEB_LOG_WARNING("{} is an invalid port in destination url", 365b07942e3SGeorge Liu url->port()); 366b07942e3SGeorge Liu messages::propertyValueFormatError(asyncResp->res, destUrl, 367b07942e3SGeorge Liu "Destination"); 368b07942e3SGeorge Liu return; 369b07942e3SGeorge Liu } 370b07942e3SGeorge Liu 371a716aa74SEd Tanous crow::utility::setProtocolDefaults(*url, protocol); 372a716aa74SEd Tanous crow::utility::setPortDefaults(*url); 373a716aa74SEd Tanous 374a716aa74SEd Tanous if (url->path().empty()) 375a716aa74SEd Tanous { 376a716aa74SEd Tanous url->set_path("/"); 377a716aa74SEd Tanous } 378a716aa74SEd Tanous 379a716aa74SEd Tanous if (url->has_userinfo()) 380a716aa74SEd Tanous { 381a716aa74SEd Tanous messages::propertyValueFormatError(asyncResp->res, destUrl, 382a716aa74SEd Tanous "Destination"); 383a716aa74SEd Tanous return; 384a716aa74SEd Tanous } 385b52664e2SAppaRao Puli 3863d30708fSChicago Duan if (protocol == "SNMPv2c") 3873d30708fSChicago Duan { 3883d30708fSChicago Duan if (context) 3893d30708fSChicago Duan { 3903d30708fSChicago Duan messages::propertyValueConflict(asyncResp->res, "Context", 3913d30708fSChicago Duan "Protocol"); 3923d30708fSChicago Duan return; 3933d30708fSChicago Duan } 3943d30708fSChicago Duan if (eventFormatType2) 3953d30708fSChicago Duan { 396bd79bce8SPatrick Williams messages::propertyValueConflict( 397bd79bce8SPatrick Williams asyncResp->res, "EventFormatType", "Protocol"); 3983d30708fSChicago Duan return; 3993d30708fSChicago Duan } 4003d30708fSChicago Duan if (retryPolicy) 4013d30708fSChicago Duan { 402bd79bce8SPatrick Williams messages::propertyValueConflict(asyncResp->res, 403bd79bce8SPatrick Williams "RetryPolicy", "Protocol"); 4043d30708fSChicago Duan return; 4053d30708fSChicago Duan } 4063d30708fSChicago Duan if (msgIds) 4073d30708fSChicago Duan { 408bd79bce8SPatrick Williams messages::propertyValueConflict(asyncResp->res, 409bd79bce8SPatrick Williams "MessageIds", "Protocol"); 4103d30708fSChicago Duan return; 4113d30708fSChicago Duan } 4123d30708fSChicago Duan if (regPrefixes) 4133d30708fSChicago Duan { 414bd79bce8SPatrick Williams messages::propertyValueConflict( 415bd79bce8SPatrick Williams asyncResp->res, "RegistryPrefixes", "Protocol"); 4163d30708fSChicago Duan return; 4173d30708fSChicago Duan } 4183d30708fSChicago Duan if (resTypes) 4193d30708fSChicago Duan { 420bd79bce8SPatrick Williams messages::propertyValueConflict( 421bd79bce8SPatrick Williams asyncResp->res, "ResourceTypes", "Protocol"); 4223d30708fSChicago Duan return; 4233d30708fSChicago Duan } 4243d30708fSChicago Duan if (headers) 4253d30708fSChicago Duan { 426bd79bce8SPatrick Williams messages::propertyValueConflict(asyncResp->res, 427bd79bce8SPatrick Williams "HttpHeaders", "Protocol"); 4283d30708fSChicago Duan return; 4293d30708fSChicago Duan } 4303d30708fSChicago Duan if (mrdJsonArray) 4313d30708fSChicago Duan { 4323d30708fSChicago Duan messages::propertyValueConflict( 4333d30708fSChicago Duan asyncResp->res, "MetricReportDefinitions", "Protocol"); 4343d30708fSChicago Duan return; 4353d30708fSChicago Duan } 436a716aa74SEd Tanous if (url->scheme() != "snmp") 437a716aa74SEd Tanous { 438bd79bce8SPatrick Williams messages::propertyValueConflict(asyncResp->res, 439bd79bce8SPatrick Williams "Destination", "Protocol"); 4403d30708fSChicago Duan return; 4413d30708fSChicago Duan } 4423d30708fSChicago Duan 443a716aa74SEd Tanous addSnmpTrapClient(asyncResp, url->host_address(), 444a716aa74SEd Tanous url->port_number()); 445a716aa74SEd Tanous return; 446b52664e2SAppaRao Puli } 4473d30708fSChicago Duan 448a716aa74SEd Tanous std::shared_ptr<Subscription> subValue = 44921a94d5cSMyung Bae std::make_shared<Subscription>( 4505fe4ef35SMyung Bae std::make_shared<persistent_data::UserSubscription>(), *url, 4515fe4ef35SMyung Bae app.ioContext()); 452e5aaf047SAppaRao Puli 453e5aaf047SAppaRao Puli if (subscriptionType) 454e5aaf047SAppaRao Puli { 455e5aaf047SAppaRao Puli if (*subscriptionType != "RedfishEvent") 456e5aaf047SAppaRao Puli { 457fffb8c1fSEd Tanous messages::propertyValueNotInList( 458fffb8c1fSEd Tanous asyncResp->res, *subscriptionType, "SubscriptionType"); 459e5aaf047SAppaRao Puli return; 460e5aaf047SAppaRao Puli } 4615fe4ef35SMyung Bae subValue->userSub->subscriptionType = *subscriptionType; 462e5aaf047SAppaRao Puli } 463e5aaf047SAppaRao Puli else 464e5aaf047SAppaRao Puli { 4654b712a29SEd Tanous // Default 4665fe4ef35SMyung Bae subValue->userSub->subscriptionType = "RedfishEvent"; 467e5aaf047SAppaRao Puli } 468e5aaf047SAppaRao Puli 469e5aaf047SAppaRao Puli if (protocol != "Redfish") 470e5aaf047SAppaRao Puli { 471e5aaf047SAppaRao Puli messages::propertyValueNotInList(asyncResp->res, protocol, 472e5aaf047SAppaRao Puli "Protocol"); 473e5aaf047SAppaRao Puli return; 474e5aaf047SAppaRao Puli } 4755fe4ef35SMyung Bae subValue->userSub->protocol = protocol; 476e5aaf047SAppaRao Puli 47719bb362bSEd Tanous if (verifyCertificate) 47819bb362bSEd Tanous { 4795fe4ef35SMyung Bae subValue->userSub->verifyCertificate = *verifyCertificate; 48019bb362bSEd Tanous } 48119bb362bSEd Tanous 48223a21a1cSEd Tanous if (eventFormatType2) 483e5aaf047SAppaRao Puli { 484bd79bce8SPatrick Williams if (std::ranges::find(supportedEvtFormatTypes, 485bd79bce8SPatrick Williams *eventFormatType2) == 4863544d2a7SEd Tanous supportedEvtFormatTypes.end()) 487e5aaf047SAppaRao Puli { 488fffb8c1fSEd Tanous messages::propertyValueNotInList( 489fffb8c1fSEd Tanous asyncResp->res, *eventFormatType2, "EventFormatType"); 490e5aaf047SAppaRao Puli return; 491e5aaf047SAppaRao Puli } 4925fe4ef35SMyung Bae subValue->userSub->eventFormatType = *eventFormatType2; 493e5aaf047SAppaRao Puli } 494e5aaf047SAppaRao Puli else 495e5aaf047SAppaRao Puli { 496e5aaf047SAppaRao Puli // If not specified, use default "Event" 4975fe4ef35SMyung Bae subValue->userSub->eventFormatType = "Event"; 498e5aaf047SAppaRao Puli } 499e5aaf047SAppaRao Puli 500e5aaf047SAppaRao Puli if (context) 501e5aaf047SAppaRao Puli { 5028ece0e45SEd Tanous // This value is selected arbitrarily. 503600af5f1SAppaRao Puli constexpr const size_t maxContextSize = 256; 504600af5f1SAppaRao Puli if (context->size() > maxContextSize) 505600af5f1SAppaRao Puli { 506600af5f1SAppaRao Puli messages::stringValueTooLong(asyncResp->res, "Context", 507600af5f1SAppaRao Puli maxContextSize); 508600af5f1SAppaRao Puli return; 509600af5f1SAppaRao Puli } 5105fe4ef35SMyung Bae subValue->userSub->customText = *context; 511e5aaf047SAppaRao Puli } 512e5aaf047SAppaRao Puli 513e5aaf047SAppaRao Puli if (headers) 514e5aaf047SAppaRao Puli { 515600af5f1SAppaRao Puli size_t cumulativeLen = 0; 516600af5f1SAppaRao Puli 51778d4ec4fSEd Tanous for (const nlohmann::json::object_t& headerChunk : *headers) 518601c71aeSEd Tanous { 51978d4ec4fSEd Tanous for (const auto& item : headerChunk) 52078d4ec4fSEd Tanous { 52178d4ec4fSEd Tanous const std::string* value = 52278d4ec4fSEd Tanous item.second.get_ptr<const std::string*>(); 52378d4ec4fSEd Tanous if (value == nullptr) 52478d4ec4fSEd Tanous { 52578d4ec4fSEd Tanous messages::propertyValueFormatError( 52678d4ec4fSEd Tanous asyncResp->res, item.second, 52778d4ec4fSEd Tanous "HttpHeaders/" + item.first); 52878d4ec4fSEd Tanous return; 52978d4ec4fSEd Tanous } 53078d4ec4fSEd Tanous // Adding a new json value is the size of the key, + 53178d4ec4fSEd Tanous // the size of the value + 2 * 2 quotes for each, + 53278d4ec4fSEd Tanous // the colon and space between. example: 53378d4ec4fSEd Tanous // "key": "value" 53478d4ec4fSEd Tanous cumulativeLen += item.first.size() + value->size() + 6; 535600af5f1SAppaRao Puli // This value is selected to mirror http_connection.hpp 536600af5f1SAppaRao Puli constexpr const uint16_t maxHeaderSizeED = 8096; 537600af5f1SAppaRao Puli if (cumulativeLen > maxHeaderSizeED) 538600af5f1SAppaRao Puli { 53978d4ec4fSEd Tanous messages::arraySizeTooLong( 54078d4ec4fSEd Tanous asyncResp->res, "HttpHeaders", maxHeaderSizeED); 541600af5f1SAppaRao Puli return; 542600af5f1SAppaRao Puli } 5435fe4ef35SMyung Bae subValue->userSub->httpHeaders.set(item.first, *value); 544601c71aeSEd Tanous } 545601c71aeSEd Tanous } 546e5aaf047SAppaRao Puli } 547e5aaf047SAppaRao Puli 548e5aaf047SAppaRao Puli if (regPrefixes) 549e5aaf047SAppaRao Puli { 550e5aaf047SAppaRao Puli for (const std::string& it : *regPrefixes) 551e5aaf047SAppaRao Puli { 5523544d2a7SEd Tanous if (std::ranges::find(supportedRegPrefixes, it) == 5533544d2a7SEd Tanous supportedRegPrefixes.end()) 554e5aaf047SAppaRao Puli { 555fffb8c1fSEd Tanous messages::propertyValueNotInList(asyncResp->res, it, 556fffb8c1fSEd Tanous "RegistryPrefixes"); 557e5aaf047SAppaRao Puli return; 558e5aaf047SAppaRao Puli } 559e5aaf047SAppaRao Puli } 5605fe4ef35SMyung Bae subValue->userSub->registryPrefixes = *regPrefixes; 561e5aaf047SAppaRao Puli } 562e5aaf047SAppaRao Puli 563a14c9113SEd Tanous if (originResources) 564a14c9113SEd Tanous { 5655fe4ef35SMyung Bae subValue->userSub->originResources = *originResources; 566a14c9113SEd Tanous } 567a14c9113SEd Tanous 568e56f254cSSunitha Harish if (resTypes) 569e56f254cSSunitha Harish { 570e56f254cSSunitha Harish for (const std::string& it : *resTypes) 571e56f254cSSunitha Harish { 5723544d2a7SEd Tanous if (std::ranges::find(supportedResourceTypes, it) == 5733544d2a7SEd Tanous supportedResourceTypes.end()) 574e56f254cSSunitha Harish { 575e56f254cSSunitha Harish messages::propertyValueNotInList(asyncResp->res, it, 576e56f254cSSunitha Harish "ResourceTypes"); 577e56f254cSSunitha Harish return; 578e56f254cSSunitha Harish } 579e56f254cSSunitha Harish } 5805fe4ef35SMyung Bae subValue->userSub->resourceTypes = *resTypes; 581e56f254cSSunitha Harish } 582e56f254cSSunitha Harish 583e5aaf047SAppaRao Puli if (msgIds) 584e5aaf047SAppaRao Puli { 585b304bd79SP Dheeraj Srujan Kumar std::vector<std::string> registryPrefix; 586b304bd79SP Dheeraj Srujan Kumar 5877e860f15SJohn Edward Broadbent // If no registry prefixes are mentioned, consider all 5887e860f15SJohn Edward Broadbent // supported prefixes 5895fe4ef35SMyung Bae if (subValue->userSub->registryPrefixes.empty()) 590b304bd79SP Dheeraj Srujan Kumar { 591b304bd79SP Dheeraj Srujan Kumar registryPrefix.assign(supportedRegPrefixes.begin(), 592b304bd79SP Dheeraj Srujan Kumar supportedRegPrefixes.end()); 593b304bd79SP Dheeraj Srujan Kumar } 594b304bd79SP Dheeraj Srujan Kumar else 595b304bd79SP Dheeraj Srujan Kumar { 5965fe4ef35SMyung Bae registryPrefix = subValue->userSub->registryPrefixes; 597b304bd79SP Dheeraj Srujan Kumar } 598b304bd79SP Dheeraj Srujan Kumar 599b304bd79SP Dheeraj Srujan Kumar for (const std::string& id : *msgIds) 600b304bd79SP Dheeraj Srujan Kumar { 601b304bd79SP Dheeraj Srujan Kumar bool validId = false; 602b304bd79SP Dheeraj Srujan Kumar 603b304bd79SP Dheeraj Srujan Kumar // Check for Message ID in each of the selected Registry 604b304bd79SP Dheeraj Srujan Kumar for (const std::string& it : registryPrefix) 605b304bd79SP Dheeraj Srujan Kumar { 606fffb8c1fSEd Tanous const std::span<const redfish::registries::MessageEntry> 607fffb8c1fSEd Tanous registry = 608fffb8c1fSEd Tanous redfish::registries::getRegistryFromPrefix(it); 609b304bd79SP Dheeraj Srujan Kumar 6103544d2a7SEd Tanous if (std::ranges::any_of( 6113544d2a7SEd Tanous registry, 612fffb8c1fSEd Tanous [&id](const redfish::registries::MessageEntry& 613fffb8c1fSEd Tanous messageEntry) { 61455f79e6fSEd Tanous return id == messageEntry.first; 615b304bd79SP Dheeraj Srujan Kumar })) 616b304bd79SP Dheeraj Srujan Kumar { 617b304bd79SP Dheeraj Srujan Kumar validId = true; 618b304bd79SP Dheeraj Srujan Kumar break; 619b304bd79SP Dheeraj Srujan Kumar } 620b304bd79SP Dheeraj Srujan Kumar } 621b304bd79SP Dheeraj Srujan Kumar 622b304bd79SP Dheeraj Srujan Kumar if (!validId) 623b304bd79SP Dheeraj Srujan Kumar { 624b304bd79SP Dheeraj Srujan Kumar messages::propertyValueNotInList(asyncResp->res, id, 625b304bd79SP Dheeraj Srujan Kumar "MessageIds"); 626b304bd79SP Dheeraj Srujan Kumar return; 627b304bd79SP Dheeraj Srujan Kumar } 628b304bd79SP Dheeraj Srujan Kumar } 629b304bd79SP Dheeraj Srujan Kumar 6305fe4ef35SMyung Bae subValue->userSub->registryMsgIds = *msgIds; 631e5aaf047SAppaRao Puli } 632e5aaf047SAppaRao Puli 633e5aaf047SAppaRao Puli if (retryPolicy) 634e5aaf047SAppaRao Puli { 6353544d2a7SEd Tanous if (std::ranges::find(supportedRetryPolicies, *retryPolicy) == 6363544d2a7SEd Tanous supportedRetryPolicies.end()) 637e5aaf047SAppaRao Puli { 638bd79bce8SPatrick Williams messages::propertyValueNotInList( 639bd79bce8SPatrick Williams asyncResp->res, *retryPolicy, "DeliveryRetryPolicy"); 640e5aaf047SAppaRao Puli return; 641e5aaf047SAppaRao Puli } 6425fe4ef35SMyung Bae subValue->userSub->retryPolicy = *retryPolicy; 643e5aaf047SAppaRao Puli } 644e5aaf047SAppaRao Puli else 645e5aaf047SAppaRao Puli { 646e5aaf047SAppaRao Puli // Default "TerminateAfterRetries" 6475fe4ef35SMyung Bae subValue->userSub->retryPolicy = "TerminateAfterRetries"; 648e5aaf047SAppaRao Puli } 649e5aaf047SAppaRao Puli 650144b6318SAppaRao Puli if (mrdJsonArray) 651156d6b00SAppaRao Puli { 65278d4ec4fSEd Tanous for (nlohmann::json::object_t& mrdObj : *mrdJsonArray) 653144b6318SAppaRao Puli { 654144b6318SAppaRao Puli std::string mrdUri; 655ea2e6eecSWilly Tu 65678d4ec4fSEd Tanous if (!json_util::readJsonObject(mrdObj, asyncResp->res, 65778d4ec4fSEd Tanous "@odata.id", mrdUri)) 658ea2e6eecSWilly Tu 659144b6318SAppaRao Puli { 660144b6318SAppaRao Puli return; 661144b6318SAppaRao Puli } 6625fe4ef35SMyung Bae subValue->userSub->metricReportDefinitions.emplace_back( 6634b712a29SEd Tanous mrdUri); 664144b6318SAppaRao Puli } 665156d6b00SAppaRao Puli } 666156d6b00SAppaRao Puli 667b52664e2SAppaRao Puli std::string id = 668bd79bce8SPatrick Williams EventServiceManager::getInstance().addPushSubscription( 669bd79bce8SPatrick Williams subValue); 670b52664e2SAppaRao Puli if (id.empty()) 671e5aaf047SAppaRao Puli { 672e5aaf047SAppaRao Puli messages::internalError(asyncResp->res); 673e5aaf047SAppaRao Puli return; 674e5aaf047SAppaRao Puli } 675e5aaf047SAppaRao Puli 676e5aaf047SAppaRao Puli messages::created(asyncResp->res); 677e5aaf047SAppaRao Puli asyncResp->res.addHeader( 678e5aaf047SAppaRao Puli "Location", "/redfish/v1/EventService/Subscriptions/" + id); 6797e860f15SJohn Edward Broadbent }); 680e5aaf047SAppaRao Puli } 681e5aaf047SAppaRao Puli 6827e860f15SJohn Edward Broadbent inline void requestRoutesEventDestination(App& app) 683e5aaf047SAppaRao Puli { 6849d41aec6SRavi Teja BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 685ed398213SEd Tanous .privileges(redfish::privileges::getEventDestination) 6867e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 68745ca1b86SEd Tanous [&app](const crow::Request& req, 6887e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6897e860f15SJohn Edward Broadbent const std::string& param) { 6903ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 69145ca1b86SEd Tanous { 69245ca1b86SEd Tanous return; 69345ca1b86SEd Tanous } 6943d30708fSChicago Duan 6953d30708fSChicago Duan if (param.starts_with("snmp")) 6963d30708fSChicago Duan { 6973d30708fSChicago Duan getSnmpTrapClient(asyncResp, param); 6983d30708fSChicago Duan return; 6993d30708fSChicago Duan } 7003d30708fSChicago Duan 701b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 7027e860f15SJohn Edward Broadbent EventServiceManager::getInstance().getSubscription(param); 703b52664e2SAppaRao Puli if (subValue == nullptr) 704e5aaf047SAppaRao Puli { 705bd79bce8SPatrick Williams asyncResp->res.result( 706bd79bce8SPatrick Williams boost::beast::http::status::not_found); 707e5aaf047SAppaRao Puli return; 708e5aaf047SAppaRao Puli } 7097e860f15SJohn Edward Broadbent const std::string& id = param; 710e5aaf047SAppaRao Puli 7114b712a29SEd Tanous const persistent_data::UserSubscription& userSub = 7125fe4ef35SMyung Bae *subValue->userSub; 713e56f254cSSunitha Harish 7144b712a29SEd Tanous nlohmann::json& jVal = asyncResp->res.jsonValue; 7154b712a29SEd Tanous jVal["@odata.type"] = 7164b712a29SEd Tanous "#EventDestination.v1_14_1.EventDestination"; 7174b712a29SEd Tanous jVal["Protocol"] = 7184b712a29SEd Tanous event_destination::EventDestinationProtocol::Redfish; 7194b712a29SEd Tanous jVal["@odata.id"] = boost::urls::format( 7204b712a29SEd Tanous "/redfish/v1/EventService/Subscriptions/{}", id); 7214b712a29SEd Tanous jVal["Id"] = id; 7224b712a29SEd Tanous jVal["Name"] = "Event Destination " + id; 7234b712a29SEd Tanous jVal["Destination"] = userSub.destinationUrl; 7244b712a29SEd Tanous jVal["Context"] = userSub.customText; 7254b712a29SEd Tanous jVal["SubscriptionType"] = userSub.subscriptionType; 7264b712a29SEd Tanous jVal["HttpHeaders"] = nlohmann::json::array(); 7274b712a29SEd Tanous jVal["EventFormatType"] = userSub.eventFormatType; 7284b712a29SEd Tanous jVal["RegistryPrefixes"] = userSub.registryPrefixes; 7294b712a29SEd Tanous jVal["ResourceTypes"] = userSub.resourceTypes; 7304b712a29SEd Tanous 7314b712a29SEd Tanous jVal["MessageIds"] = userSub.registryMsgIds; 7324b712a29SEd Tanous jVal["DeliveryRetryPolicy"] = userSub.retryPolicy; 7334b712a29SEd Tanous jVal["VerifyCertificate"] = userSub.verifyCertificate; 734144b6318SAppaRao Puli 7351476687dSEd Tanous nlohmann::json::array_t mrdJsonArray; 7364b712a29SEd Tanous for (const auto& mdrUri : userSub.metricReportDefinitions) 737144b6318SAppaRao Puli { 7381476687dSEd Tanous nlohmann::json::object_t mdr; 7391476687dSEd Tanous mdr["@odata.id"] = mdrUri; 7401476687dSEd Tanous mrdJsonArray.emplace_back(std::move(mdr)); 741144b6318SAppaRao Puli } 7424b712a29SEd Tanous jVal["MetricReportDefinitions"] = mrdJsonArray; 7437e860f15SJohn Edward Broadbent }); 7449d41aec6SRavi Teja BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 745ed398213SEd Tanous // The below privilege is wrong, it should be ConfigureManager OR 746ed398213SEd Tanous // ConfigureSelf 7477eeafa76SAbhishek Patel // https://github.com/openbmc/bmcweb/issues/220 748ed398213SEd Tanous //.privileges(redfish::privileges::patchEventDestination) 749432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 7507e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::patch)( 75145ca1b86SEd Tanous [&app](const crow::Request& req, 7527e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 7537e860f15SJohn Edward Broadbent const std::string& param) { 7543ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 75545ca1b86SEd Tanous { 75645ca1b86SEd Tanous return; 75745ca1b86SEd Tanous } 758b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 7597e860f15SJohn Edward Broadbent EventServiceManager::getInstance().getSubscription(param); 760b52664e2SAppaRao Puli if (subValue == nullptr) 761e5aaf047SAppaRao Puli { 762bd79bce8SPatrick Williams asyncResp->res.result( 763bd79bce8SPatrick Williams boost::beast::http::status::not_found); 764e5aaf047SAppaRao Puli return; 765e5aaf047SAppaRao Puli } 766e5aaf047SAppaRao Puli 767e5aaf047SAppaRao Puli std::optional<std::string> context; 768e5aaf047SAppaRao Puli std::optional<std::string> retryPolicy; 76919bb362bSEd Tanous std::optional<bool> verifyCertificate; 77078d4ec4fSEd Tanous std::optional<std::vector<nlohmann::json::object_t>> headers; 771e5aaf047SAppaRao Puli 772afc474aeSMyung Bae if (!json_util::readJsonPatch( // 773afc474aeSMyung Bae req, asyncResp->res, // 774afc474aeSMyung Bae "Context", context, // 775afc474aeSMyung Bae "DeliveryRetryPolicy", retryPolicy, // 776afc474aeSMyung Bae "HttpHeaders", headers, // 777afc474aeSMyung Bae "VerifyCertificate", verifyCertificate // 778afc474aeSMyung Bae )) 779e5aaf047SAppaRao Puli { 780e5aaf047SAppaRao Puli return; 781e5aaf047SAppaRao Puli } 782e5aaf047SAppaRao Puli 783e5aaf047SAppaRao Puli if (context) 784e5aaf047SAppaRao Puli { 7855fe4ef35SMyung Bae subValue->userSub->customText = *context; 786e5aaf047SAppaRao Puli } 787e5aaf047SAppaRao Puli 788e5aaf047SAppaRao Puli if (headers) 789e5aaf047SAppaRao Puli { 790601c71aeSEd Tanous boost::beast::http::fields fields; 79178d4ec4fSEd Tanous for (const nlohmann::json::object_t& headerChunk : *headers) 792601c71aeSEd Tanous { 79378d4ec4fSEd Tanous for (const auto& it : headerChunk) 794601c71aeSEd Tanous { 795601c71aeSEd Tanous const std::string* value = 79678d4ec4fSEd Tanous it.second.get_ptr<const std::string*>(); 797601c71aeSEd Tanous if (value == nullptr) 798601c71aeSEd Tanous { 799601c71aeSEd Tanous messages::propertyValueFormatError( 80078d4ec4fSEd Tanous asyncResp->res, it.second, 80178d4ec4fSEd Tanous "HttpHeaders/" + it.first); 802601c71aeSEd Tanous return; 803601c71aeSEd Tanous } 80478d4ec4fSEd Tanous fields.set(it.first, *value); 805601c71aeSEd Tanous } 806601c71aeSEd Tanous } 8075fe4ef35SMyung Bae subValue->userSub->httpHeaders = std::move(fields); 808e5aaf047SAppaRao Puli } 809e5aaf047SAppaRao Puli 810e5aaf047SAppaRao Puli if (retryPolicy) 811e5aaf047SAppaRao Puli { 812bd79bce8SPatrick Williams if (std::ranges::find(supportedRetryPolicies, 813bd79bce8SPatrick Williams *retryPolicy) == 8143544d2a7SEd Tanous supportedRetryPolicies.end()) 815e5aaf047SAppaRao Puli { 816bd79bce8SPatrick Williams messages::propertyValueNotInList(asyncResp->res, 817bd79bce8SPatrick Williams *retryPolicy, 818e5aaf047SAppaRao Puli "DeliveryRetryPolicy"); 819e5aaf047SAppaRao Puli return; 820e5aaf047SAppaRao Puli } 8215fe4ef35SMyung Bae subValue->userSub->retryPolicy = *retryPolicy; 822e5aaf047SAppaRao Puli } 823e5aaf047SAppaRao Puli 82419bb362bSEd Tanous if (verifyCertificate) 82519bb362bSEd Tanous { 8265fe4ef35SMyung Bae subValue->userSub->verifyCertificate = *verifyCertificate; 82719bb362bSEd Tanous } 82819bb362bSEd Tanous 829b52664e2SAppaRao Puli EventServiceManager::getInstance().updateSubscriptionData(); 8307e860f15SJohn Edward Broadbent }); 8319d41aec6SRavi Teja BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") 832ed398213SEd Tanous // The below privilege is wrong, it should be ConfigureManager OR 833ed398213SEd Tanous // ConfigureSelf 8347eeafa76SAbhishek Patel // https://github.com/openbmc/bmcweb/issues/220 835ed398213SEd Tanous //.privileges(redfish::privileges::deleteEventDestination) 836432a890cSEd Tanous .privileges({{"ConfigureManager"}}) 8377e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 83845ca1b86SEd Tanous [&app](const crow::Request& req, 8397e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8407e860f15SJohn Edward Broadbent const std::string& param) { 8413ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 84245ca1b86SEd Tanous { 84345ca1b86SEd Tanous return; 84445ca1b86SEd Tanous } 8454b712a29SEd Tanous EventServiceManager& event = EventServiceManager::getInstance(); 8463d30708fSChicago Duan if (param.starts_with("snmp")) 8473d30708fSChicago Duan { 8483d30708fSChicago Duan deleteSnmpTrapClient(asyncResp, param); 8494b712a29SEd Tanous event.deleteSubscription(param); 8503d30708fSChicago Duan return; 8513d30708fSChicago Duan } 8523d30708fSChicago Duan 8534b712a29SEd Tanous if (!event.deleteSubscription(param)) 854e5aaf047SAppaRao Puli { 8554b712a29SEd Tanous messages::resourceNotFound(asyncResp->res, 8564b712a29SEd Tanous "EventDestination", param); 857e5aaf047SAppaRao Puli return; 858e5aaf047SAppaRao Puli } 8594b712a29SEd Tanous messages::success(asyncResp->res); 8607e860f15SJohn Edward Broadbent }); 861e5aaf047SAppaRao Puli } 862e5aaf047SAppaRao Puli 863e5aaf047SAppaRao Puli } // namespace redfish 864