xref: /openbmc/bmcweb/features/redfish/lib/event_service.hpp (revision 6be832e2963e9d720dd95543358eca380c5e52d2)
1e5aaf047SAppaRao Puli /*
2*6be832e2SEd Tanous Copyright (c) 2020 Intel Corporation
3*6be832e2SEd Tanous 
4*6be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License");
5*6be832e2SEd Tanous you may not use this file except in compliance with the License.
6*6be832e2SEd Tanous You may obtain a copy of the License at
7*6be832e2SEd Tanous 
8*6be832e2SEd Tanous       http://www.apache.org/licenses/LICENSE-2.0
9*6be832e2SEd Tanous 
10*6be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software
11*6be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS,
12*6be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6be832e2SEd Tanous See the License for the specific language governing permissions and
14*6be832e2SEd 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>
371e270c5fSPatrick Williams 
38e5aaf047SAppaRao Puli namespace redfish
39e5aaf047SAppaRao Puli {
40e5aaf047SAppaRao Puli 
41156d6b00SAppaRao Puli static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
42156d6b00SAppaRao Puli     eventFormatType, metricReportFormatType};
43e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
44b304bd79SP Dheeraj Srujan Kumar     "Base", "OpenBMC", "TaskEvent"};
45e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
46e5aaf047SAppaRao Puli     "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
47e5aaf047SAppaRao Puli 
48e56f254cSSunitha Harish static constexpr const std::array<const char*, 1> supportedResourceTypes = {
49e56f254cSSunitha Harish     "Task"};
50e56f254cSSunitha Harish 
517e860f15SJohn Edward Broadbent inline void requestRoutesEventService(App& app)
52e5aaf047SAppaRao Puli {
537e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
54ed398213SEd Tanous         .privileges(redfish::privileges::getEventService)
55bd79bce8SPatrick Williams         .methods(
56bd79bce8SPatrick Williams             boost::beast::http::verb::
57bd79bce8SPatrick Williams                 get)([&app](
58bd79bce8SPatrick Williams                          const crow::Request& req,
59002d39b4SEd Tanous                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
603ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
6145ca1b86SEd Tanous             {
6245ca1b86SEd Tanous                 return;
6345ca1b86SEd Tanous             }
641476687dSEd Tanous 
651476687dSEd Tanous             asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/EventService";
661476687dSEd Tanous             asyncResp->res.jsonValue["@odata.type"] =
671476687dSEd Tanous                 "#EventService.v1_5_0.EventService";
681476687dSEd Tanous             asyncResp->res.jsonValue["Id"] = "EventService";
691476687dSEd Tanous             asyncResp->res.jsonValue["Name"] = "Event Service";
705e44e3d8SAppaRao Puli             asyncResp->res.jsonValue["ServerSentEventUri"] =
715e44e3d8SAppaRao Puli                 "/redfish/v1/EventService/SSE";
725e44e3d8SAppaRao Puli 
731476687dSEd Tanous             asyncResp->res.jsonValue["Subscriptions"]["@odata.id"] =
741476687dSEd Tanous                 "/redfish/v1/EventService/Subscriptions";
75bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Actions"]["#EventService.SubmitTestEvent"]
76bd79bce8SPatrick Williams                                     ["target"] =
771476687dSEd Tanous                 "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent";
78e5aaf047SAppaRao Puli 
7928afb49cSJunLin Chen             const persistent_data::EventServiceConfig eventServiceConfig =
8028afb49cSJunLin Chen                 persistent_data::EventServiceStore::getInstance()
8128afb49cSJunLin Chen                     .getEventServiceConfig();
827d1cc387SAppaRao Puli 
837d1cc387SAppaRao Puli             asyncResp->res.jsonValue["Status"]["State"] =
8428afb49cSJunLin Chen                 (eventServiceConfig.enabled ? "Enabled" : "Disabled");
85bd79bce8SPatrick Williams             asyncResp->res.jsonValue["ServiceEnabled"] =
86bd79bce8SPatrick Williams                 eventServiceConfig.enabled;
877e860f15SJohn Edward Broadbent             asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
8828afb49cSJunLin Chen                 eventServiceConfig.retryAttempts;
89e5aaf047SAppaRao Puli             asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
9028afb49cSJunLin Chen                 eventServiceConfig.retryTimeoutInterval;
91bd79bce8SPatrick Williams             asyncResp->res.jsonValue["EventFormatTypes"] =
92bd79bce8SPatrick Williams                 supportedEvtFormatTypes;
930fda0f12SGeorge Liu             asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
940fda0f12SGeorge Liu             asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
9507941a88SAyushi Smriti 
96613dabeaSEd Tanous             nlohmann::json::object_t supportedSSEFilters;
97613dabeaSEd Tanous             supportedSSEFilters["EventFormatType"] = true;
98613dabeaSEd Tanous             supportedSSEFilters["MessageId"] = true;
99613dabeaSEd Tanous             supportedSSEFilters["MetricReportDefinition"] = true;
100613dabeaSEd Tanous             supportedSSEFilters["RegistryPrefix"] = true;
101613dabeaSEd Tanous             supportedSSEFilters["OriginResource"] = false;
102613dabeaSEd Tanous             supportedSSEFilters["ResourceType"] = false;
10307941a88SAyushi Smriti 
10407941a88SAyushi Smriti             asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
105613dabeaSEd Tanous                 std::move(supportedSSEFilters);
1067e860f15SJohn Edward Broadbent         });
107e5aaf047SAppaRao Puli 
1087e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
109ed398213SEd Tanous         .privileges(redfish::privileges::patchEventService)
1107e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
11145ca1b86SEd Tanous             [&app](const crow::Request& req,
11245ca1b86SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1133ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
114e5aaf047SAppaRao Puli                 {
11545ca1b86SEd Tanous                     return;
11645ca1b86SEd Tanous                 }
117e5aaf047SAppaRao Puli                 std::optional<bool> serviceEnabled;
118e5aaf047SAppaRao Puli                 std::optional<uint32_t> retryAttemps;
119e5aaf047SAppaRao Puli                 std::optional<uint32_t> retryInterval;
120e5aaf047SAppaRao Puli 
12115ed6780SWilly Tu                 if (!json_util::readJsonPatch(
1227e860f15SJohn Edward Broadbent                         req, asyncResp->res, "ServiceEnabled", serviceEnabled,
1237e860f15SJohn Edward Broadbent                         "DeliveryRetryAttempts", retryAttemps,
1247e860f15SJohn Edward Broadbent                         "DeliveryRetryIntervalSeconds", retryInterval))
125e5aaf047SAppaRao Puli                 {
126e5aaf047SAppaRao Puli                     return;
127e5aaf047SAppaRao Puli                 }
128e5aaf047SAppaRao Puli 
12928afb49cSJunLin Chen                 persistent_data::EventServiceConfig eventServiceConfig =
13028afb49cSJunLin Chen                     persistent_data::EventServiceStore::getInstance()
13128afb49cSJunLin Chen                         .getEventServiceConfig();
1327d1cc387SAppaRao Puli 
133e5aaf047SAppaRao Puli                 if (serviceEnabled)
134e5aaf047SAppaRao Puli                 {
13528afb49cSJunLin Chen                     eventServiceConfig.enabled = *serviceEnabled;
136e5aaf047SAppaRao Puli                 }
137e5aaf047SAppaRao Puli 
138e5aaf047SAppaRao Puli                 if (retryAttemps)
139e5aaf047SAppaRao Puli                 {
140e5aaf047SAppaRao Puli                     // Supported range [1-3]
141e5aaf047SAppaRao Puli                     if ((*retryAttemps < 1) || (*retryAttemps > 3))
142e5aaf047SAppaRao Puli                     {
143e5aaf047SAppaRao Puli                         messages::queryParameterOutOfRange(
144e5aaf047SAppaRao Puli                             asyncResp->res, std::to_string(*retryAttemps),
145e5aaf047SAppaRao Puli                             "DeliveryRetryAttempts", "[1-3]");
146e5aaf047SAppaRao Puli                     }
147e5aaf047SAppaRao Puli                     else
148e5aaf047SAppaRao Puli                     {
14928afb49cSJunLin Chen                         eventServiceConfig.retryAttempts = *retryAttemps;
150e5aaf047SAppaRao Puli                     }
151e5aaf047SAppaRao Puli                 }
152e5aaf047SAppaRao Puli 
153e5aaf047SAppaRao Puli                 if (retryInterval)
154e5aaf047SAppaRao Puli                 {
15533a32b34SGunnar Mills                     // Supported range [5 - 180]
15633a32b34SGunnar Mills                     if ((*retryInterval < 5) || (*retryInterval > 180))
157e5aaf047SAppaRao Puli                     {
158e5aaf047SAppaRao Puli                         messages::queryParameterOutOfRange(
159e5aaf047SAppaRao Puli                             asyncResp->res, std::to_string(*retryInterval),
16033a32b34SGunnar Mills                             "DeliveryRetryIntervalSeconds", "[5-180]");
161e5aaf047SAppaRao Puli                     }
162e5aaf047SAppaRao Puli                     else
163e5aaf047SAppaRao Puli                     {
164bd79bce8SPatrick Williams                         eventServiceConfig.retryTimeoutInterval =
165bd79bce8SPatrick Williams                             *retryInterval;
166e5aaf047SAppaRao Puli                     }
167e5aaf047SAppaRao Puli                 }
168e5aaf047SAppaRao Puli 
1697d1cc387SAppaRao Puli                 EventServiceManager::getInstance().setEventServiceConfig(
17028afb49cSJunLin Chen                     eventServiceConfig);
1717e860f15SJohn Edward Broadbent             });
1720b4bdd93SAppaRao Puli }
1730b4bdd93SAppaRao Puli 
1747e860f15SJohn Edward Broadbent inline void requestRoutesSubmitTestEvent(App& app)
1750b4bdd93SAppaRao Puli {
1767e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
1777e860f15SJohn Edward Broadbent         app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
178ed398213SEd Tanous         .privileges(redfish::privileges::postEventService)
1797e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
18045ca1b86SEd Tanous             [&app](const crow::Request& req,
1817e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1823ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
18345ca1b86SEd Tanous                 {
18445ca1b86SEd Tanous                     return;
18545ca1b86SEd Tanous                 }
1866ba8c82eSsunharis_in                 if (!EventServiceManager::getInstance().sendTestEventLog())
1876ba8c82eSsunharis_in                 {
1886ba8c82eSsunharis_in                     messages::serviceDisabled(asyncResp->res,
1896ba8c82eSsunharis_in                                               "/redfish/v1/EventService/");
1906ba8c82eSsunharis_in                     return;
1916ba8c82eSsunharis_in                 }
1928d1b46d7Szhanghch05                 asyncResp->res.result(boost::beast::http::status::no_content);
1937e860f15SJohn Edward Broadbent             });
194e5aaf047SAppaRao Puli }
195e5aaf047SAppaRao Puli 
1963d30708fSChicago Duan inline void doSubscriptionCollection(
197e81de512SEd Tanous     const boost::system::error_code& ec,
1983d30708fSChicago Duan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1993d30708fSChicago Duan     const dbus::utility::ManagedObjectType& resp)
2003d30708fSChicago Duan {
2013d30708fSChicago Duan     if (ec)
2023d30708fSChicago Duan     {
2031306101eSEd Tanous         if (ec.value() == EBADR || ec.value() == EHOSTUNREACH)
2043d30708fSChicago Duan         {
2053d30708fSChicago Duan             // This is an optional process so just return if it isn't there
2063d30708fSChicago Duan             return;
2073d30708fSChicago Duan         }
2083d30708fSChicago Duan 
20962598e31SEd Tanous         BMCWEB_LOG_ERROR("D-Bus response error on GetManagedObjects {}", ec);
2103d30708fSChicago Duan         messages::internalError(asyncResp->res);
2113d30708fSChicago Duan         return;
2123d30708fSChicago Duan     }
2133d30708fSChicago Duan     nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
2143d30708fSChicago Duan     for (const auto& objpath : resp)
2153d30708fSChicago Duan     {
2163d30708fSChicago Duan         sdbusplus::message::object_path path(objpath.first);
2173d30708fSChicago Duan         const std::string snmpId = path.filename();
2183d30708fSChicago Duan         if (snmpId.empty())
2193d30708fSChicago Duan         {
22062598e31SEd Tanous             BMCWEB_LOG_ERROR("The SNMP client ID is wrong");
2213d30708fSChicago Duan             messages::internalError(asyncResp->res);
2223d30708fSChicago Duan             return;
2233d30708fSChicago Duan         }
2243d30708fSChicago Duan 
2253d30708fSChicago Duan         getSnmpSubscriptionList(asyncResp, snmpId, memberArray);
2263d30708fSChicago Duan     }
2273d30708fSChicago Duan }
2283d30708fSChicago Duan 
2297e860f15SJohn Edward Broadbent inline void requestRoutesEventDestinationCollection(App& app)
230e5aaf047SAppaRao Puli {
2311ebe3e41SGayathri Leburu     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
232ed398213SEd Tanous         .privileges(redfish::privileges::getEventDestinationCollection)
2337e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
23445ca1b86SEd Tanous             [&app](const crow::Request& req,
2357e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2363ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
23745ca1b86SEd Tanous                 {
23845ca1b86SEd Tanous                     return;
23945ca1b86SEd Tanous                 }
2401476687dSEd Tanous                 asyncResp->res.jsonValue["@odata.type"] =
2411476687dSEd Tanous                     "#EventDestinationCollection.EventDestinationCollection";
2421476687dSEd Tanous                 asyncResp->res.jsonValue["@odata.id"] =
2431476687dSEd Tanous                     "/redfish/v1/EventService/Subscriptions";
244bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["Name"] =
245bd79bce8SPatrick Williams                     "Event Destination Collections";
246e5aaf047SAppaRao Puli 
247bd79bce8SPatrick Williams                 nlohmann::json& memberArray =
248bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Members"];
249e5aaf047SAppaRao Puli 
250b52664e2SAppaRao Puli                 std::vector<std::string> subscripIds =
251b52664e2SAppaRao Puli                     EventServiceManager::getInstance().getAllIDs();
252b52664e2SAppaRao Puli                 memberArray = nlohmann::json::array();
253bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["Members@odata.count"] =
254bd79bce8SPatrick Williams                     subscripIds.size();
255b52664e2SAppaRao Puli 
256b52664e2SAppaRao Puli                 for (const std::string& id : subscripIds)
257e5aaf047SAppaRao Puli                 {
2581476687dSEd Tanous                     nlohmann::json::object_t member;
2593d30708fSChicago Duan                     member["@odata.id"] = boost::urls::format(
2603d30708fSChicago Duan                         "/redfish/v1/EventService/Subscriptions/{}" + id);
261b2ba3072SPatrick Williams                     memberArray.emplace_back(std::move(member));
262e5aaf047SAppaRao Puli                 }
2633d30708fSChicago Duan                 crow::connections::systemBus->async_method_call(
264e81de512SEd Tanous                     [asyncResp](const boost::system::error_code& ec,
2653d30708fSChicago Duan                                 const dbus::utility::ManagedObjectType& resp) {
2663d30708fSChicago Duan                         doSubscriptionCollection(ec, asyncResp, resp);
2673d30708fSChicago Duan                     },
2683d30708fSChicago Duan                     "xyz.openbmc_project.Network.SNMP",
2693d30708fSChicago Duan                     "/xyz/openbmc_project/network/snmp/manager",
2703d30708fSChicago Duan                     "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
2717e860f15SJohn Edward Broadbent             });
2723d30708fSChicago Duan 
2737e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
2747eeafa76SAbhishek Patel         .privileges(redfish::privileges::postEventDestinationCollection)
275bd79bce8SPatrick Williams         .methods(
276bd79bce8SPatrick Williams             boost::beast::http::verb::
277bd79bce8SPatrick Williams                 post)([&app](
278bd79bce8SPatrick Williams                           const crow::Request& req,
2797e860f15SJohn Edward Broadbent                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2803ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
28145ca1b86SEd Tanous             {
28245ca1b86SEd Tanous                 return;
28345ca1b86SEd Tanous             }
284fffb8c1fSEd Tanous             if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
285fffb8c1fSEd Tanous                 maxNoOfSubscriptions)
286e5aaf047SAppaRao Puli             {
287e5aaf047SAppaRao Puli                 messages::eventSubscriptionLimitExceeded(asyncResp->res);
288e5aaf047SAppaRao Puli                 return;
289e5aaf047SAppaRao Puli             }
290e5aaf047SAppaRao Puli             std::string destUrl;
291e5aaf047SAppaRao Puli             std::string protocol;
29219bb362bSEd Tanous             std::optional<bool> verifyCertificate;
293e5aaf047SAppaRao Puli             std::optional<std::string> context;
294e5aaf047SAppaRao Puli             std::optional<std::string> subscriptionType;
29523a21a1cSEd Tanous             std::optional<std::string> eventFormatType2;
296e5aaf047SAppaRao Puli             std::optional<std::string> retryPolicy;
297e5aaf047SAppaRao Puli             std::optional<std::vector<std::string>> msgIds;
298e5aaf047SAppaRao Puli             std::optional<std::vector<std::string>> regPrefixes;
299e56f254cSSunitha Harish             std::optional<std::vector<std::string>> resTypes;
30078d4ec4fSEd Tanous             std::optional<std::vector<nlohmann::json::object_t>> headers;
30178d4ec4fSEd Tanous             std::optional<std::vector<nlohmann::json::object_t>> mrdJsonArray;
302e5aaf047SAppaRao Puli 
30315ed6780SWilly Tu             if (!json_util::readJsonPatch(
304bd79bce8SPatrick Williams                     req, asyncResp->res, "Destination", destUrl, "Context",
305bd79bce8SPatrick Williams                     context, "Protocol", protocol, "SubscriptionType",
306bd79bce8SPatrick Williams                     subscriptionType, "EventFormatType", eventFormatType2,
307bd79bce8SPatrick Williams                     "HttpHeaders", headers, "RegistryPrefixes", regPrefixes,
308bd79bce8SPatrick Williams                     "MessageIds", msgIds, "DeliveryRetryPolicy", retryPolicy,
309bd79bce8SPatrick Williams                     "MetricReportDefinitions", mrdJsonArray, "ResourceTypes",
310bd79bce8SPatrick Williams                     resTypes, "VerifyCertificate", verifyCertificate))
311e5aaf047SAppaRao Puli             {
312e5aaf047SAppaRao Puli                 return;
313e5aaf047SAppaRao Puli             }
314e5aaf047SAppaRao Puli 
315600af5f1SAppaRao Puli             // https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
316600af5f1SAppaRao Puli             static constexpr const uint16_t maxDestinationSize = 2000;
317600af5f1SAppaRao Puli             if (destUrl.size() > maxDestinationSize)
318600af5f1SAppaRao Puli             {
319600af5f1SAppaRao Puli                 messages::stringValueTooLong(asyncResp->res, "Destination",
320600af5f1SAppaRao Puli                                              maxDestinationSize);
321600af5f1SAppaRao Puli                 return;
322600af5f1SAppaRao Puli             }
323600af5f1SAppaRao Puli 
324dd28ba82SAppaRao Puli             if (regPrefixes && msgIds)
325dd28ba82SAppaRao Puli             {
32626f6976fSEd Tanous                 if (!regPrefixes->empty() && !msgIds->empty())
327dd28ba82SAppaRao Puli                 {
328bd79bce8SPatrick Williams                     messages::propertyValueConflict(
329bd79bce8SPatrick Williams                         asyncResp->res, "MessageIds", "RegistryPrefixes");
330dd28ba82SAppaRao Puli                     return;
331dd28ba82SAppaRao Puli                 }
332dd28ba82SAppaRao Puli             }
333dd28ba82SAppaRao Puli 
3346fd29553SEd Tanous             boost::system::result<boost::urls::url> url =
335a716aa74SEd Tanous                 boost::urls::parse_absolute_uri(destUrl);
336a716aa74SEd Tanous             if (!url)
337e5aaf047SAppaRao Puli             {
338bd79bce8SPatrick Williams                 BMCWEB_LOG_WARNING(
339bd79bce8SPatrick Williams                     "Failed to validate and split destination url");
340e5aaf047SAppaRao Puli                 messages::propertyValueFormatError(asyncResp->res, destUrl,
341e5aaf047SAppaRao Puli                                                    "Destination");
342e5aaf047SAppaRao Puli                 return;
343e5aaf047SAppaRao Puli             }
344a716aa74SEd Tanous             url->normalize();
345a716aa74SEd Tanous             crow::utility::setProtocolDefaults(*url, protocol);
346a716aa74SEd Tanous             crow::utility::setPortDefaults(*url);
347a716aa74SEd Tanous 
348a716aa74SEd Tanous             if (url->path().empty())
349a716aa74SEd Tanous             {
350a716aa74SEd Tanous                 url->set_path("/");
351a716aa74SEd Tanous             }
352a716aa74SEd Tanous 
353a716aa74SEd Tanous             if (url->has_userinfo())
354a716aa74SEd Tanous             {
355a716aa74SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, destUrl,
356a716aa74SEd Tanous                                                    "Destination");
357a716aa74SEd Tanous                 return;
358a716aa74SEd Tanous             }
359b52664e2SAppaRao Puli 
3603d30708fSChicago Duan             if (protocol == "SNMPv2c")
3613d30708fSChicago Duan             {
3623d30708fSChicago Duan                 if (context)
3633d30708fSChicago Duan                 {
3643d30708fSChicago Duan                     messages::propertyValueConflict(asyncResp->res, "Context",
3653d30708fSChicago Duan                                                     "Protocol");
3663d30708fSChicago Duan                     return;
3673d30708fSChicago Duan                 }
3683d30708fSChicago Duan                 if (eventFormatType2)
3693d30708fSChicago Duan                 {
370bd79bce8SPatrick Williams                     messages::propertyValueConflict(
371bd79bce8SPatrick Williams                         asyncResp->res, "EventFormatType", "Protocol");
3723d30708fSChicago Duan                     return;
3733d30708fSChicago Duan                 }
3743d30708fSChicago Duan                 if (retryPolicy)
3753d30708fSChicago Duan                 {
376bd79bce8SPatrick Williams                     messages::propertyValueConflict(asyncResp->res,
377bd79bce8SPatrick Williams                                                     "RetryPolicy", "Protocol");
3783d30708fSChicago Duan                     return;
3793d30708fSChicago Duan                 }
3803d30708fSChicago Duan                 if (msgIds)
3813d30708fSChicago Duan                 {
382bd79bce8SPatrick Williams                     messages::propertyValueConflict(asyncResp->res,
383bd79bce8SPatrick Williams                                                     "MessageIds", "Protocol");
3843d30708fSChicago Duan                     return;
3853d30708fSChicago Duan                 }
3863d30708fSChicago Duan                 if (regPrefixes)
3873d30708fSChicago Duan                 {
388bd79bce8SPatrick Williams                     messages::propertyValueConflict(
389bd79bce8SPatrick Williams                         asyncResp->res, "RegistryPrefixes", "Protocol");
3903d30708fSChicago Duan                     return;
3913d30708fSChicago Duan                 }
3923d30708fSChicago Duan                 if (resTypes)
3933d30708fSChicago Duan                 {
394bd79bce8SPatrick Williams                     messages::propertyValueConflict(
395bd79bce8SPatrick Williams                         asyncResp->res, "ResourceTypes", "Protocol");
3963d30708fSChicago Duan                     return;
3973d30708fSChicago Duan                 }
3983d30708fSChicago Duan                 if (headers)
3993d30708fSChicago Duan                 {
400bd79bce8SPatrick Williams                     messages::propertyValueConflict(asyncResp->res,
401bd79bce8SPatrick Williams                                                     "HttpHeaders", "Protocol");
4023d30708fSChicago Duan                     return;
4033d30708fSChicago Duan                 }
4043d30708fSChicago Duan                 if (mrdJsonArray)
4053d30708fSChicago Duan                 {
4063d30708fSChicago Duan                     messages::propertyValueConflict(
4073d30708fSChicago Duan                         asyncResp->res, "MetricReportDefinitions", "Protocol");
4083d30708fSChicago Duan                     return;
4093d30708fSChicago Duan                 }
410a716aa74SEd Tanous                 if (url->scheme() != "snmp")
411a716aa74SEd Tanous                 {
412bd79bce8SPatrick Williams                     messages::propertyValueConflict(asyncResp->res,
413bd79bce8SPatrick Williams                                                     "Destination", "Protocol");
4143d30708fSChicago Duan                     return;
4153d30708fSChicago Duan                 }
4163d30708fSChicago Duan 
417a716aa74SEd Tanous                 addSnmpTrapClient(asyncResp, url->host_address(),
418a716aa74SEd Tanous                                   url->port_number());
419a716aa74SEd Tanous                 return;
420b52664e2SAppaRao Puli             }
4213d30708fSChicago Duan 
422a716aa74SEd Tanous             std::shared_ptr<Subscription> subValue =
423a716aa74SEd Tanous                 std::make_shared<Subscription>(*url, app.ioContext());
424b52664e2SAppaRao Puli 
425a716aa74SEd Tanous             subValue->destinationUrl = std::move(*url);
426e5aaf047SAppaRao Puli 
427e5aaf047SAppaRao Puli             if (subscriptionType)
428e5aaf047SAppaRao Puli             {
429e5aaf047SAppaRao Puli                 if (*subscriptionType != "RedfishEvent")
430e5aaf047SAppaRao Puli                 {
431fffb8c1fSEd Tanous                     messages::propertyValueNotInList(
432fffb8c1fSEd Tanous                         asyncResp->res, *subscriptionType, "SubscriptionType");
433e5aaf047SAppaRao Puli                     return;
434e5aaf047SAppaRao Puli                 }
435b52664e2SAppaRao Puli                 subValue->subscriptionType = *subscriptionType;
436e5aaf047SAppaRao Puli             }
437e5aaf047SAppaRao Puli             else
438e5aaf047SAppaRao Puli             {
439b52664e2SAppaRao Puli                 subValue->subscriptionType = "RedfishEvent"; // Default
440e5aaf047SAppaRao Puli             }
441e5aaf047SAppaRao Puli 
442e5aaf047SAppaRao Puli             if (protocol != "Redfish")
443e5aaf047SAppaRao Puli             {
444e5aaf047SAppaRao Puli                 messages::propertyValueNotInList(asyncResp->res, protocol,
445e5aaf047SAppaRao Puli                                                  "Protocol");
446e5aaf047SAppaRao Puli                 return;
447e5aaf047SAppaRao Puli             }
448b52664e2SAppaRao Puli             subValue->protocol = protocol;
449e5aaf047SAppaRao Puli 
45019bb362bSEd Tanous             if (verifyCertificate)
45119bb362bSEd Tanous             {
45219bb362bSEd Tanous                 subValue->verifyCertificate = *verifyCertificate;
45319bb362bSEd Tanous             }
45419bb362bSEd Tanous 
45523a21a1cSEd Tanous             if (eventFormatType2)
456e5aaf047SAppaRao Puli             {
457bd79bce8SPatrick Williams                 if (std::ranges::find(supportedEvtFormatTypes,
458bd79bce8SPatrick Williams                                       *eventFormatType2) ==
4593544d2a7SEd Tanous                     supportedEvtFormatTypes.end())
460e5aaf047SAppaRao Puli                 {
461fffb8c1fSEd Tanous                     messages::propertyValueNotInList(
462fffb8c1fSEd Tanous                         asyncResp->res, *eventFormatType2, "EventFormatType");
463e5aaf047SAppaRao Puli                     return;
464e5aaf047SAppaRao Puli                 }
46523a21a1cSEd Tanous                 subValue->eventFormatType = *eventFormatType2;
466e5aaf047SAppaRao Puli             }
467e5aaf047SAppaRao Puli             else
468e5aaf047SAppaRao Puli             {
469e5aaf047SAppaRao Puli                 // If not specified, use default "Event"
47023a21a1cSEd Tanous                 subValue->eventFormatType = "Event";
471e5aaf047SAppaRao Puli             }
472e5aaf047SAppaRao Puli 
473e5aaf047SAppaRao Puli             if (context)
474e5aaf047SAppaRao Puli             {
4758ece0e45SEd Tanous                 // This value is selected arbitrarily.
476600af5f1SAppaRao Puli                 constexpr const size_t maxContextSize = 256;
477600af5f1SAppaRao Puli                 if (context->size() > maxContextSize)
478600af5f1SAppaRao Puli                 {
479600af5f1SAppaRao Puli                     messages::stringValueTooLong(asyncResp->res, "Context",
480600af5f1SAppaRao Puli                                                  maxContextSize);
481600af5f1SAppaRao Puli                     return;
482600af5f1SAppaRao Puli                 }
483b52664e2SAppaRao Puli                 subValue->customText = *context;
484e5aaf047SAppaRao Puli             }
485e5aaf047SAppaRao Puli 
486e5aaf047SAppaRao Puli             if (headers)
487e5aaf047SAppaRao Puli             {
488600af5f1SAppaRao Puli                 size_t cumulativeLen = 0;
489600af5f1SAppaRao Puli 
49078d4ec4fSEd Tanous                 for (const nlohmann::json::object_t& headerChunk : *headers)
491601c71aeSEd Tanous                 {
49278d4ec4fSEd Tanous                     for (const auto& item : headerChunk)
49378d4ec4fSEd Tanous                     {
49478d4ec4fSEd Tanous                         const std::string* value =
49578d4ec4fSEd Tanous                             item.second.get_ptr<const std::string*>();
49678d4ec4fSEd Tanous                         if (value == nullptr)
49778d4ec4fSEd Tanous                         {
49878d4ec4fSEd Tanous                             messages::propertyValueFormatError(
49978d4ec4fSEd Tanous                                 asyncResp->res, item.second,
50078d4ec4fSEd Tanous                                 "HttpHeaders/" + item.first);
50178d4ec4fSEd Tanous                             return;
50278d4ec4fSEd Tanous                         }
50378d4ec4fSEd Tanous                         // Adding a new json value is the size of the key, +
50478d4ec4fSEd Tanous                         // the size of the value + 2 * 2 quotes for each, +
50578d4ec4fSEd Tanous                         // the colon and space between. example:
50678d4ec4fSEd Tanous                         // "key": "value"
50778d4ec4fSEd Tanous                         cumulativeLen += item.first.size() + value->size() + 6;
508600af5f1SAppaRao Puli                         // This value is selected to mirror http_connection.hpp
509600af5f1SAppaRao Puli                         constexpr const uint16_t maxHeaderSizeED = 8096;
510600af5f1SAppaRao Puli                         if (cumulativeLen > maxHeaderSizeED)
511600af5f1SAppaRao Puli                         {
51278d4ec4fSEd Tanous                             messages::arraySizeTooLong(
51378d4ec4fSEd Tanous                                 asyncResp->res, "HttpHeaders", maxHeaderSizeED);
514600af5f1SAppaRao Puli                             return;
515600af5f1SAppaRao Puli                         }
51678d4ec4fSEd Tanous                         subValue->httpHeaders.set(item.first, *value);
517601c71aeSEd Tanous                     }
518601c71aeSEd Tanous                 }
519e5aaf047SAppaRao Puli             }
520e5aaf047SAppaRao Puli 
521e5aaf047SAppaRao Puli             if (regPrefixes)
522e5aaf047SAppaRao Puli             {
523e5aaf047SAppaRao Puli                 for (const std::string& it : *regPrefixes)
524e5aaf047SAppaRao Puli                 {
5253544d2a7SEd Tanous                     if (std::ranges::find(supportedRegPrefixes, it) ==
5263544d2a7SEd Tanous                         supportedRegPrefixes.end())
527e5aaf047SAppaRao Puli                     {
528fffb8c1fSEd Tanous                         messages::propertyValueNotInList(asyncResp->res, it,
529fffb8c1fSEd Tanous                                                          "RegistryPrefixes");
530e5aaf047SAppaRao Puli                         return;
531e5aaf047SAppaRao Puli                     }
532e5aaf047SAppaRao Puli                 }
533b52664e2SAppaRao Puli                 subValue->registryPrefixes = *regPrefixes;
534e5aaf047SAppaRao Puli             }
535e5aaf047SAppaRao Puli 
536e56f254cSSunitha Harish             if (resTypes)
537e56f254cSSunitha Harish             {
538e56f254cSSunitha Harish                 for (const std::string& it : *resTypes)
539e56f254cSSunitha Harish                 {
5403544d2a7SEd Tanous                     if (std::ranges::find(supportedResourceTypes, it) ==
5413544d2a7SEd Tanous                         supportedResourceTypes.end())
542e56f254cSSunitha Harish                     {
543e56f254cSSunitha Harish                         messages::propertyValueNotInList(asyncResp->res, it,
544e56f254cSSunitha Harish                                                          "ResourceTypes");
545e56f254cSSunitha Harish                         return;
546e56f254cSSunitha Harish                     }
547e56f254cSSunitha Harish                 }
548e56f254cSSunitha Harish                 subValue->resourceTypes = *resTypes;
549e56f254cSSunitha Harish             }
550e56f254cSSunitha Harish 
551e5aaf047SAppaRao Puli             if (msgIds)
552e5aaf047SAppaRao Puli             {
553b304bd79SP Dheeraj Srujan Kumar                 std::vector<std::string> registryPrefix;
554b304bd79SP Dheeraj Srujan Kumar 
5557e860f15SJohn Edward Broadbent                 // If no registry prefixes are mentioned, consider all
5567e860f15SJohn Edward Broadbent                 // supported prefixes
557b304bd79SP Dheeraj Srujan Kumar                 if (subValue->registryPrefixes.empty())
558b304bd79SP Dheeraj Srujan Kumar                 {
559b304bd79SP Dheeraj Srujan Kumar                     registryPrefix.assign(supportedRegPrefixes.begin(),
560b304bd79SP Dheeraj Srujan Kumar                                           supportedRegPrefixes.end());
561b304bd79SP Dheeraj Srujan Kumar                 }
562b304bd79SP Dheeraj Srujan Kumar                 else
563b304bd79SP Dheeraj Srujan Kumar                 {
564b304bd79SP Dheeraj Srujan Kumar                     registryPrefix = subValue->registryPrefixes;
565b304bd79SP Dheeraj Srujan Kumar                 }
566b304bd79SP Dheeraj Srujan Kumar 
567b304bd79SP Dheeraj Srujan Kumar                 for (const std::string& id : *msgIds)
568b304bd79SP Dheeraj Srujan Kumar                 {
569b304bd79SP Dheeraj Srujan Kumar                     bool validId = false;
570b304bd79SP Dheeraj Srujan Kumar 
571b304bd79SP Dheeraj Srujan Kumar                     // Check for Message ID in each of the selected Registry
572b304bd79SP Dheeraj Srujan Kumar                     for (const std::string& it : registryPrefix)
573b304bd79SP Dheeraj Srujan Kumar                     {
574fffb8c1fSEd Tanous                         const std::span<const redfish::registries::MessageEntry>
575fffb8c1fSEd Tanous                             registry =
576fffb8c1fSEd Tanous                                 redfish::registries::getRegistryFromPrefix(it);
577b304bd79SP Dheeraj Srujan Kumar 
5783544d2a7SEd Tanous                         if (std::ranges::any_of(
5793544d2a7SEd Tanous                                 registry,
580fffb8c1fSEd Tanous                                 [&id](const redfish::registries::MessageEntry&
581fffb8c1fSEd Tanous                                           messageEntry) {
58255f79e6fSEd Tanous                                     return id == messageEntry.first;
583b304bd79SP Dheeraj Srujan Kumar                                 }))
584b304bd79SP Dheeraj Srujan Kumar                         {
585b304bd79SP Dheeraj Srujan Kumar                             validId = true;
586b304bd79SP Dheeraj Srujan Kumar                             break;
587b304bd79SP Dheeraj Srujan Kumar                         }
588b304bd79SP Dheeraj Srujan Kumar                     }
589b304bd79SP Dheeraj Srujan Kumar 
590b304bd79SP Dheeraj Srujan Kumar                     if (!validId)
591b304bd79SP Dheeraj Srujan Kumar                     {
592b304bd79SP Dheeraj Srujan Kumar                         messages::propertyValueNotInList(asyncResp->res, id,
593b304bd79SP Dheeraj Srujan Kumar                                                          "MessageIds");
594b304bd79SP Dheeraj Srujan Kumar                         return;
595b304bd79SP Dheeraj Srujan Kumar                     }
596b304bd79SP Dheeraj Srujan Kumar                 }
597b304bd79SP Dheeraj Srujan Kumar 
598b52664e2SAppaRao Puli                 subValue->registryMsgIds = *msgIds;
599e5aaf047SAppaRao Puli             }
600e5aaf047SAppaRao Puli 
601e5aaf047SAppaRao Puli             if (retryPolicy)
602e5aaf047SAppaRao Puli             {
6033544d2a7SEd Tanous                 if (std::ranges::find(supportedRetryPolicies, *retryPolicy) ==
6043544d2a7SEd Tanous                     supportedRetryPolicies.end())
605e5aaf047SAppaRao Puli                 {
606bd79bce8SPatrick Williams                     messages::propertyValueNotInList(
607bd79bce8SPatrick Williams                         asyncResp->res, *retryPolicy, "DeliveryRetryPolicy");
608e5aaf047SAppaRao Puli                     return;
609e5aaf047SAppaRao Puli                 }
610b52664e2SAppaRao Puli                 subValue->retryPolicy = *retryPolicy;
611e5aaf047SAppaRao Puli             }
612e5aaf047SAppaRao Puli             else
613e5aaf047SAppaRao Puli             {
614e5aaf047SAppaRao Puli                 // Default "TerminateAfterRetries"
615b52664e2SAppaRao Puli                 subValue->retryPolicy = "TerminateAfterRetries";
616e5aaf047SAppaRao Puli             }
617e5aaf047SAppaRao Puli 
618144b6318SAppaRao Puli             if (mrdJsonArray)
619156d6b00SAppaRao Puli             {
62078d4ec4fSEd Tanous                 for (nlohmann::json::object_t& mrdObj : *mrdJsonArray)
621144b6318SAppaRao Puli                 {
622144b6318SAppaRao Puli                     std::string mrdUri;
623ea2e6eecSWilly Tu 
62478d4ec4fSEd Tanous                     if (!json_util::readJsonObject(mrdObj, asyncResp->res,
62578d4ec4fSEd Tanous                                                    "@odata.id", mrdUri))
626ea2e6eecSWilly Tu 
627144b6318SAppaRao Puli                     {
628144b6318SAppaRao Puli                         return;
629144b6318SAppaRao Puli                     }
630ea2e6eecSWilly Tu                     subValue->metricReportDefinitions.emplace_back(mrdUri);
631144b6318SAppaRao Puli                 }
632156d6b00SAppaRao Puli             }
633156d6b00SAppaRao Puli 
634b52664e2SAppaRao Puli             std::string id =
635bd79bce8SPatrick Williams                 EventServiceManager::getInstance().addPushSubscription(
636bd79bce8SPatrick Williams                     subValue);
637b52664e2SAppaRao Puli             if (id.empty())
638e5aaf047SAppaRao Puli             {
639e5aaf047SAppaRao Puli                 messages::internalError(asyncResp->res);
640e5aaf047SAppaRao Puli                 return;
641e5aaf047SAppaRao Puli             }
642e5aaf047SAppaRao Puli 
643e5aaf047SAppaRao Puli             messages::created(asyncResp->res);
644e5aaf047SAppaRao Puli             asyncResp->res.addHeader(
645e5aaf047SAppaRao Puli                 "Location", "/redfish/v1/EventService/Subscriptions/" + id);
6467e860f15SJohn Edward Broadbent         });
647e5aaf047SAppaRao Puli }
648e5aaf047SAppaRao Puli 
6497e860f15SJohn Edward Broadbent inline void requestRoutesEventDestination(App& app)
650e5aaf047SAppaRao Puli {
6519d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
652ed398213SEd Tanous         .privileges(redfish::privileges::getEventDestination)
6537e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
65445ca1b86SEd Tanous             [&app](const crow::Request& req,
6557e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
6567e860f15SJohn Edward Broadbent                    const std::string& param) {
6573ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
65845ca1b86SEd Tanous                 {
65945ca1b86SEd Tanous                     return;
66045ca1b86SEd Tanous                 }
6613d30708fSChicago Duan 
6623d30708fSChicago Duan                 if (param.starts_with("snmp"))
6633d30708fSChicago Duan                 {
6643d30708fSChicago Duan                     getSnmpTrapClient(asyncResp, param);
6653d30708fSChicago Duan                     return;
6663d30708fSChicago Duan                 }
6673d30708fSChicago Duan 
668b52664e2SAppaRao Puli                 std::shared_ptr<Subscription> subValue =
6697e860f15SJohn Edward Broadbent                     EventServiceManager::getInstance().getSubscription(param);
670b52664e2SAppaRao Puli                 if (subValue == nullptr)
671e5aaf047SAppaRao Puli                 {
672bd79bce8SPatrick Williams                     asyncResp->res.result(
673bd79bce8SPatrick Williams                         boost::beast::http::status::not_found);
674e5aaf047SAppaRao Puli                     return;
675e5aaf047SAppaRao Puli                 }
6767e860f15SJohn Edward Broadbent                 const std::string& id = param;
677e5aaf047SAppaRao Puli 
6781476687dSEd Tanous                 asyncResp->res.jsonValue["@odata.type"] =
6798759961cSMyung Bae                     "#EventDestination.v1_14_1.EventDestination";
680539d8c6bSEd Tanous                 asyncResp->res.jsonValue["Protocol"] =
681539d8c6bSEd Tanous                     event_destination::EventDestinationProtocol::Redfish;
6823b32780dSEd Tanous                 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
6833b32780dSEd Tanous                     "/redfish/v1/EventService/Subscriptions/{}", id);
684e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["Id"] = id;
685e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
686bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["Destination"] =
687bd79bce8SPatrick Williams                     subValue->destinationUrl;
688b52664e2SAppaRao Puli                 asyncResp->res.jsonValue["Context"] = subValue->customText;
689e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["SubscriptionType"] =
690b52664e2SAppaRao Puli                     subValue->subscriptionType;
691bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["HttpHeaders"] =
692bd79bce8SPatrick Williams                     nlohmann::json::array();
693bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["EventFormatType"] =
694bd79bce8SPatrick Williams                     subValue->eventFormatType;
695e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["RegistryPrefixes"] =
696b52664e2SAppaRao Puli                     subValue->registryPrefixes;
697bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["ResourceTypes"] =
698bd79bce8SPatrick Williams                     subValue->resourceTypes;
699e56f254cSSunitha Harish 
700bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["MessageIds"] =
701bd79bce8SPatrick Williams                     subValue->registryMsgIds;
702bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["DeliveryRetryPolicy"] =
703bd79bce8SPatrick Williams                     subValue->retryPolicy;
70419bb362bSEd Tanous                 asyncResp->res.jsonValue["VerifyCertificate"] =
70519bb362bSEd Tanous                     subValue->verifyCertificate;
706144b6318SAppaRao Puli 
7071476687dSEd Tanous                 nlohmann::json::array_t mrdJsonArray;
708144b6318SAppaRao Puli                 for (const auto& mdrUri : subValue->metricReportDefinitions)
709144b6318SAppaRao Puli                 {
7101476687dSEd Tanous                     nlohmann::json::object_t mdr;
7111476687dSEd Tanous                     mdr["@odata.id"] = mdrUri;
7121476687dSEd Tanous                     mrdJsonArray.emplace_back(std::move(mdr));
713144b6318SAppaRao Puli                 }
714bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["MetricReportDefinitions"] =
715bd79bce8SPatrick Williams                     mrdJsonArray;
7167e860f15SJohn Edward Broadbent             });
7179d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
718ed398213SEd Tanous         // The below privilege is wrong, it should be ConfigureManager OR
719ed398213SEd Tanous         // ConfigureSelf
7207eeafa76SAbhishek Patel         // https://github.com/openbmc/bmcweb/issues/220
721ed398213SEd Tanous         //.privileges(redfish::privileges::patchEventDestination)
722432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
7237e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
72445ca1b86SEd Tanous             [&app](const crow::Request& req,
7257e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7267e860f15SJohn Edward Broadbent                    const std::string& param) {
7273ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
72845ca1b86SEd Tanous                 {
72945ca1b86SEd Tanous                     return;
73045ca1b86SEd Tanous                 }
731b52664e2SAppaRao Puli                 std::shared_ptr<Subscription> subValue =
7327e860f15SJohn Edward Broadbent                     EventServiceManager::getInstance().getSubscription(param);
733b52664e2SAppaRao Puli                 if (subValue == nullptr)
734e5aaf047SAppaRao Puli                 {
735bd79bce8SPatrick Williams                     asyncResp->res.result(
736bd79bce8SPatrick Williams                         boost::beast::http::status::not_found);
737e5aaf047SAppaRao Puli                     return;
738e5aaf047SAppaRao Puli                 }
739e5aaf047SAppaRao Puli 
740e5aaf047SAppaRao Puli                 std::optional<std::string> context;
741e5aaf047SAppaRao Puli                 std::optional<std::string> retryPolicy;
74219bb362bSEd Tanous                 std::optional<bool> verifyCertificate;
74378d4ec4fSEd Tanous                 std::optional<std::vector<nlohmann::json::object_t>> headers;
744e5aaf047SAppaRao Puli 
745bd79bce8SPatrick Williams                 if (!json_util::readJsonPatch(
746bd79bce8SPatrick Williams                         req, asyncResp->res, "Context", context,
74719bb362bSEd Tanous                         "VerifyCertificate", verifyCertificate,
748bd79bce8SPatrick Williams                         "DeliveryRetryPolicy", retryPolicy, "HttpHeaders",
749bd79bce8SPatrick Williams                         headers))
750e5aaf047SAppaRao Puli                 {
751e5aaf047SAppaRao Puli                     return;
752e5aaf047SAppaRao Puli                 }
753e5aaf047SAppaRao Puli 
754e5aaf047SAppaRao Puli                 if (context)
755e5aaf047SAppaRao Puli                 {
756b52664e2SAppaRao Puli                     subValue->customText = *context;
757e5aaf047SAppaRao Puli                 }
758e5aaf047SAppaRao Puli 
759e5aaf047SAppaRao Puli                 if (headers)
760e5aaf047SAppaRao Puli                 {
761601c71aeSEd Tanous                     boost::beast::http::fields fields;
76278d4ec4fSEd Tanous                     for (const nlohmann::json::object_t& headerChunk : *headers)
763601c71aeSEd Tanous                     {
76478d4ec4fSEd Tanous                         for (const auto& it : headerChunk)
765601c71aeSEd Tanous                         {
766601c71aeSEd Tanous                             const std::string* value =
76778d4ec4fSEd Tanous                                 it.second.get_ptr<const std::string*>();
768601c71aeSEd Tanous                             if (value == nullptr)
769601c71aeSEd Tanous                             {
770601c71aeSEd Tanous                                 messages::propertyValueFormatError(
77178d4ec4fSEd Tanous                                     asyncResp->res, it.second,
77278d4ec4fSEd Tanous                                     "HttpHeaders/" + it.first);
773601c71aeSEd Tanous                                 return;
774601c71aeSEd Tanous                             }
77578d4ec4fSEd Tanous                             fields.set(it.first, *value);
776601c71aeSEd Tanous                         }
777601c71aeSEd Tanous                     }
77878d4ec4fSEd Tanous                     subValue->httpHeaders = std::move(fields);
779e5aaf047SAppaRao Puli                 }
780e5aaf047SAppaRao Puli 
781e5aaf047SAppaRao Puli                 if (retryPolicy)
782e5aaf047SAppaRao Puli                 {
783bd79bce8SPatrick Williams                     if (std::ranges::find(supportedRetryPolicies,
784bd79bce8SPatrick Williams                                           *retryPolicy) ==
7853544d2a7SEd Tanous                         supportedRetryPolicies.end())
786e5aaf047SAppaRao Puli                     {
787bd79bce8SPatrick Williams                         messages::propertyValueNotInList(asyncResp->res,
788bd79bce8SPatrick Williams                                                          *retryPolicy,
789e5aaf047SAppaRao Puli                                                          "DeliveryRetryPolicy");
790e5aaf047SAppaRao Puli                         return;
791e5aaf047SAppaRao Puli                     }
792b52664e2SAppaRao Puli                     subValue->retryPolicy = *retryPolicy;
793e5aaf047SAppaRao Puli                 }
794e5aaf047SAppaRao Puli 
79519bb362bSEd Tanous                 if (verifyCertificate)
79619bb362bSEd Tanous                 {
79719bb362bSEd Tanous                     subValue->verifyCertificate = *verifyCertificate;
79819bb362bSEd Tanous                 }
79919bb362bSEd Tanous 
800b52664e2SAppaRao Puli                 EventServiceManager::getInstance().updateSubscriptionData();
8017e860f15SJohn Edward Broadbent             });
8029d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
803ed398213SEd Tanous         // The below privilege is wrong, it should be ConfigureManager OR
804ed398213SEd Tanous         // ConfigureSelf
8057eeafa76SAbhishek Patel         // https://github.com/openbmc/bmcweb/issues/220
806ed398213SEd Tanous         //.privileges(redfish::privileges::deleteEventDestination)
807432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
8087e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
80945ca1b86SEd Tanous             [&app](const crow::Request& req,
8107e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
8117e860f15SJohn Edward Broadbent                    const std::string& param) {
8123ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
81345ca1b86SEd Tanous                 {
81445ca1b86SEd Tanous                     return;
81545ca1b86SEd Tanous                 }
8163d30708fSChicago Duan 
8173d30708fSChicago Duan                 if (param.starts_with("snmp"))
8183d30708fSChicago Duan                 {
8193d30708fSChicago Duan                     deleteSnmpTrapClient(asyncResp, param);
820bd79bce8SPatrick Williams                     EventServiceManager::getInstance().deleteSubscription(
821bd79bce8SPatrick Williams                         param);
8223d30708fSChicago Duan                     return;
8233d30708fSChicago Duan                 }
8243d30708fSChicago Duan 
825bd79bce8SPatrick Williams                 if (!EventServiceManager::getInstance().isSubscriptionExist(
826bd79bce8SPatrick Williams                         param))
827e5aaf047SAppaRao Puli                 {
828bd79bce8SPatrick Williams                     asyncResp->res.result(
829bd79bce8SPatrick Williams                         boost::beast::http::status::not_found);
830e5aaf047SAppaRao Puli                     return;
831e5aaf047SAppaRao Puli                 }
8327e860f15SJohn Edward Broadbent                 EventServiceManager::getInstance().deleteSubscription(param);
8337e860f15SJohn Edward Broadbent             });
834e5aaf047SAppaRao Puli }
835e5aaf047SAppaRao Puli 
836e5aaf047SAppaRao Puli } // namespace redfish
837