xref: /openbmc/bmcweb/features/redfish/lib/event_service.hpp (revision 3544d2a719c8bb7b07f9a39f61a3770ec84b909f)
1e5aaf047SAppaRao Puli /*
2e5aaf047SAppaRao Puli // Copyright (c) 2020 Intel Corporation
3e5aaf047SAppaRao Puli //
4e5aaf047SAppaRao Puli // Licensed under the Apache License, Version 2.0 (the "License");
5e5aaf047SAppaRao Puli // you may not use this file except in compliance with the License.
6e5aaf047SAppaRao Puli // You may obtain a copy of the License at
7e5aaf047SAppaRao Puli //
8e5aaf047SAppaRao Puli //      http://www.apache.org/licenses/LICENSE-2.0
9e5aaf047SAppaRao Puli //
10e5aaf047SAppaRao Puli // Unless required by applicable law or agreed to in writing, software
11e5aaf047SAppaRao Puli // distributed under the License is distributed on an "AS IS" BASIS,
12e5aaf047SAppaRao Puli // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e5aaf047SAppaRao Puli // See the License for the specific language governing permissions and
14e5aaf047SAppaRao Puli // limitations under the License.
15e5aaf047SAppaRao Puli */
16e5aaf047SAppaRao Puli #pragma once
173ccb3adbSEd Tanous #include "app.hpp"
18b52664e2SAppaRao Puli #include "event_service_manager.hpp"
193ccb3adbSEd Tanous #include "http/utility.hpp"
203ccb3adbSEd Tanous #include "logging.hpp"
213ccb3adbSEd Tanous #include "query.hpp"
223ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
233d30708fSChicago Duan #include "snmp_trap_event_clients.hpp"
24e5aaf047SAppaRao Puli 
25601c71aeSEd Tanous #include <boost/beast/http/fields.hpp>
263d30708fSChicago Duan #include <boost/system/error_code.hpp>
273d30708fSChicago Duan #include <sdbusplus/unpack_properties.hpp>
283d30708fSChicago Duan #include <utils/dbus_utils.hpp>
29ed398213SEd Tanous 
303d30708fSChicago Duan #include <charconv>
313d30708fSChicago Duan #include <memory>
32*3544d2a7SEd Tanous #include <ranges>
331e270c5fSPatrick Williams #include <span>
343d30708fSChicago Duan #include <string>
351e270c5fSPatrick Williams 
36e5aaf047SAppaRao Puli namespace redfish
37e5aaf047SAppaRao Puli {
38e5aaf047SAppaRao Puli 
39156d6b00SAppaRao Puli static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
40156d6b00SAppaRao Puli     eventFormatType, metricReportFormatType};
41e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
42b304bd79SP Dheeraj Srujan Kumar     "Base", "OpenBMC", "TaskEvent"};
43e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
44e5aaf047SAppaRao Puli     "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
45e5aaf047SAppaRao Puli 
46e56f254cSSunitha Harish static constexpr const std::array<const char*, 1> supportedResourceTypes = {
47e56f254cSSunitha Harish     "Task"};
48e56f254cSSunitha Harish 
497e860f15SJohn Edward Broadbent inline void requestRoutesEventService(App& app)
50e5aaf047SAppaRao Puli {
517e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
52ed398213SEd Tanous         .privileges(redfish::privileges::getEventService)
53002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
54002d39b4SEd Tanous             [&app](const crow::Request& req,
55002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
563ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
5745ca1b86SEd Tanous         {
5845ca1b86SEd Tanous             return;
5945ca1b86SEd Tanous         }
601476687dSEd Tanous 
611476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/EventService";
621476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
631476687dSEd Tanous             "#EventService.v1_5_0.EventService";
641476687dSEd Tanous         asyncResp->res.jsonValue["Id"] = "EventService";
651476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "Event Service";
665e44e3d8SAppaRao Puli         asyncResp->res.jsonValue["ServerSentEventUri"] =
675e44e3d8SAppaRao Puli             "/redfish/v1/EventService/SSE";
685e44e3d8SAppaRao Puli 
691476687dSEd Tanous         asyncResp->res.jsonValue["Subscriptions"]["@odata.id"] =
701476687dSEd Tanous             "/redfish/v1/EventService/Subscriptions";
71002d39b4SEd Tanous         asyncResp->res
72002d39b4SEd Tanous             .jsonValue["Actions"]["#EventService.SubmitTestEvent"]["target"] =
731476687dSEd Tanous             "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent";
74e5aaf047SAppaRao Puli 
7528afb49cSJunLin Chen         const persistent_data::EventServiceConfig eventServiceConfig =
7628afb49cSJunLin Chen             persistent_data::EventServiceStore::getInstance()
7728afb49cSJunLin Chen                 .getEventServiceConfig();
787d1cc387SAppaRao Puli 
797d1cc387SAppaRao Puli         asyncResp->res.jsonValue["Status"]["State"] =
8028afb49cSJunLin Chen             (eventServiceConfig.enabled ? "Enabled" : "Disabled");
81002d39b4SEd Tanous         asyncResp->res.jsonValue["ServiceEnabled"] = eventServiceConfig.enabled;
827e860f15SJohn Edward Broadbent         asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
8328afb49cSJunLin Chen             eventServiceConfig.retryAttempts;
84e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
8528afb49cSJunLin Chen             eventServiceConfig.retryTimeoutInterval;
86002d39b4SEd Tanous         asyncResp->res.jsonValue["EventFormatTypes"] = supportedEvtFormatTypes;
870fda0f12SGeorge Liu         asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
880fda0f12SGeorge Liu         asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
8907941a88SAyushi Smriti 
90613dabeaSEd Tanous         nlohmann::json::object_t supportedSSEFilters;
91613dabeaSEd Tanous         supportedSSEFilters["EventFormatType"] = true;
92613dabeaSEd Tanous         supportedSSEFilters["MessageId"] = true;
93613dabeaSEd Tanous         supportedSSEFilters["MetricReportDefinition"] = true;
94613dabeaSEd Tanous         supportedSSEFilters["RegistryPrefix"] = true;
95613dabeaSEd Tanous         supportedSSEFilters["OriginResource"] = false;
96613dabeaSEd Tanous         supportedSSEFilters["ResourceType"] = false;
9707941a88SAyushi Smriti 
9807941a88SAyushi Smriti         asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
99613dabeaSEd Tanous             std::move(supportedSSEFilters);
1007e860f15SJohn Edward Broadbent         });
101e5aaf047SAppaRao Puli 
1027e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
103ed398213SEd Tanous         .privileges(redfish::privileges::patchEventService)
1047e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
10545ca1b86SEd Tanous             [&app](const crow::Request& req,
10645ca1b86SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1073ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
108e5aaf047SAppaRao Puli         {
10945ca1b86SEd Tanous             return;
11045ca1b86SEd Tanous         }
111e5aaf047SAppaRao Puli         std::optional<bool> serviceEnabled;
112e5aaf047SAppaRao Puli         std::optional<uint32_t> retryAttemps;
113e5aaf047SAppaRao Puli         std::optional<uint32_t> retryInterval;
114e5aaf047SAppaRao Puli 
11515ed6780SWilly Tu         if (!json_util::readJsonPatch(
1167e860f15SJohn Edward Broadbent                 req, asyncResp->res, "ServiceEnabled", serviceEnabled,
1177e860f15SJohn Edward Broadbent                 "DeliveryRetryAttempts", retryAttemps,
1187e860f15SJohn Edward Broadbent                 "DeliveryRetryIntervalSeconds", retryInterval))
119e5aaf047SAppaRao Puli         {
120e5aaf047SAppaRao Puli             return;
121e5aaf047SAppaRao Puli         }
122e5aaf047SAppaRao Puli 
12328afb49cSJunLin Chen         persistent_data::EventServiceConfig eventServiceConfig =
12428afb49cSJunLin Chen             persistent_data::EventServiceStore::getInstance()
12528afb49cSJunLin Chen                 .getEventServiceConfig();
1267d1cc387SAppaRao Puli 
127e5aaf047SAppaRao Puli         if (serviceEnabled)
128e5aaf047SAppaRao Puli         {
12928afb49cSJunLin Chen             eventServiceConfig.enabled = *serviceEnabled;
130e5aaf047SAppaRao Puli         }
131e5aaf047SAppaRao Puli 
132e5aaf047SAppaRao Puli         if (retryAttemps)
133e5aaf047SAppaRao Puli         {
134e5aaf047SAppaRao Puli             // Supported range [1-3]
135e5aaf047SAppaRao Puli             if ((*retryAttemps < 1) || (*retryAttemps > 3))
136e5aaf047SAppaRao Puli             {
137e5aaf047SAppaRao Puli                 messages::queryParameterOutOfRange(
138e5aaf047SAppaRao Puli                     asyncResp->res, std::to_string(*retryAttemps),
139e5aaf047SAppaRao Puli                     "DeliveryRetryAttempts", "[1-3]");
140e5aaf047SAppaRao Puli             }
141e5aaf047SAppaRao Puli             else
142e5aaf047SAppaRao Puli             {
14328afb49cSJunLin Chen                 eventServiceConfig.retryAttempts = *retryAttemps;
144e5aaf047SAppaRao Puli             }
145e5aaf047SAppaRao Puli         }
146e5aaf047SAppaRao Puli 
147e5aaf047SAppaRao Puli         if (retryInterval)
148e5aaf047SAppaRao Puli         {
14933a32b34SGunnar Mills             // Supported range [5 - 180]
15033a32b34SGunnar Mills             if ((*retryInterval < 5) || (*retryInterval > 180))
151e5aaf047SAppaRao Puli             {
152e5aaf047SAppaRao Puli                 messages::queryParameterOutOfRange(
153e5aaf047SAppaRao Puli                     asyncResp->res, std::to_string(*retryInterval),
15433a32b34SGunnar Mills                     "DeliveryRetryIntervalSeconds", "[5-180]");
155e5aaf047SAppaRao Puli             }
156e5aaf047SAppaRao Puli             else
157e5aaf047SAppaRao Puli             {
158002d39b4SEd Tanous                 eventServiceConfig.retryTimeoutInterval = *retryInterval;
159e5aaf047SAppaRao Puli             }
160e5aaf047SAppaRao Puli         }
161e5aaf047SAppaRao Puli 
1627d1cc387SAppaRao Puli         EventServiceManager::getInstance().setEventServiceConfig(
16328afb49cSJunLin Chen             eventServiceConfig);
1647e860f15SJohn Edward Broadbent         });
1650b4bdd93SAppaRao Puli }
1660b4bdd93SAppaRao Puli 
1677e860f15SJohn Edward Broadbent inline void requestRoutesSubmitTestEvent(App& app)
1680b4bdd93SAppaRao Puli {
1697e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
1707e860f15SJohn Edward Broadbent         app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
171ed398213SEd Tanous         .privileges(redfish::privileges::postEventService)
1727e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
17345ca1b86SEd Tanous             [&app](const crow::Request& req,
1747e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1753ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
17645ca1b86SEd Tanous         {
17745ca1b86SEd Tanous             return;
17845ca1b86SEd Tanous         }
1796ba8c82eSsunharis_in         if (!EventServiceManager::getInstance().sendTestEventLog())
1806ba8c82eSsunharis_in         {
1816ba8c82eSsunharis_in             messages::serviceDisabled(asyncResp->res,
1826ba8c82eSsunharis_in                                       "/redfish/v1/EventService/");
1836ba8c82eSsunharis_in             return;
1846ba8c82eSsunharis_in         }
1858d1b46d7Szhanghch05         asyncResp->res.result(boost::beast::http::status::no_content);
1867e860f15SJohn Edward Broadbent         });
187e5aaf047SAppaRao Puli }
188e5aaf047SAppaRao Puli 
1893d30708fSChicago Duan inline void doSubscriptionCollection(
190e81de512SEd Tanous     const boost::system::error_code& ec,
1913d30708fSChicago Duan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1923d30708fSChicago Duan     const dbus::utility::ManagedObjectType& resp)
1933d30708fSChicago Duan {
1943d30708fSChicago Duan     if (ec)
1953d30708fSChicago Duan     {
1961306101eSEd Tanous         if (ec.value() == EBADR || ec.value() == EHOSTUNREACH)
1973d30708fSChicago Duan         {
1983d30708fSChicago Duan             // This is an optional process so just return if it isn't there
1993d30708fSChicago Duan             return;
2003d30708fSChicago Duan         }
2013d30708fSChicago Duan 
20262598e31SEd Tanous         BMCWEB_LOG_ERROR("D-Bus response error on GetManagedObjects {}", ec);
2033d30708fSChicago Duan         messages::internalError(asyncResp->res);
2043d30708fSChicago Duan         return;
2053d30708fSChicago Duan     }
2063d30708fSChicago Duan     nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
2073d30708fSChicago Duan     for (const auto& objpath : resp)
2083d30708fSChicago Duan     {
2093d30708fSChicago Duan         sdbusplus::message::object_path path(objpath.first);
2103d30708fSChicago Duan         const std::string snmpId = path.filename();
2113d30708fSChicago Duan         if (snmpId.empty())
2123d30708fSChicago Duan         {
21362598e31SEd Tanous             BMCWEB_LOG_ERROR("The SNMP client ID is wrong");
2143d30708fSChicago Duan             messages::internalError(asyncResp->res);
2153d30708fSChicago Duan             return;
2163d30708fSChicago Duan         }
2173d30708fSChicago Duan 
2183d30708fSChicago Duan         getSnmpSubscriptionList(asyncResp, snmpId, memberArray);
2193d30708fSChicago Duan     }
2203d30708fSChicago Duan }
2213d30708fSChicago Duan 
2227e860f15SJohn Edward Broadbent inline void requestRoutesEventDestinationCollection(App& app)
223e5aaf047SAppaRao Puli {
2241ebe3e41SGayathri Leburu     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
225ed398213SEd Tanous         .privileges(redfish::privileges::getEventDestinationCollection)
2267e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
22745ca1b86SEd Tanous             [&app](const crow::Request& req,
2287e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2293ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
23045ca1b86SEd Tanous         {
23145ca1b86SEd Tanous             return;
23245ca1b86SEd Tanous         }
2331476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
2341476687dSEd Tanous             "#EventDestinationCollection.EventDestinationCollection";
2351476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
2361476687dSEd Tanous             "/redfish/v1/EventService/Subscriptions";
237002d39b4SEd Tanous         asyncResp->res.jsonValue["Name"] = "Event Destination Collections";
238e5aaf047SAppaRao Puli 
239002d39b4SEd Tanous         nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
240e5aaf047SAppaRao Puli 
241b52664e2SAppaRao Puli         std::vector<std::string> subscripIds =
242b52664e2SAppaRao Puli             EventServiceManager::getInstance().getAllIDs();
243b52664e2SAppaRao Puli         memberArray = nlohmann::json::array();
244002d39b4SEd Tanous         asyncResp->res.jsonValue["Members@odata.count"] = subscripIds.size();
245b52664e2SAppaRao Puli 
246b52664e2SAppaRao Puli         for (const std::string& id : subscripIds)
247e5aaf047SAppaRao Puli         {
2481476687dSEd Tanous             nlohmann::json::object_t member;
2493d30708fSChicago Duan             member["@odata.id"] = boost::urls::format(
2503d30708fSChicago Duan                 "/redfish/v1/EventService/Subscriptions/{}" + id);
251b2ba3072SPatrick Williams             memberArray.emplace_back(std::move(member));
252e5aaf047SAppaRao Puli         }
2533d30708fSChicago Duan         crow::connections::systemBus->async_method_call(
254e81de512SEd Tanous             [asyncResp](const boost::system::error_code& ec,
2553d30708fSChicago Duan                         const dbus::utility::ManagedObjectType& resp) {
2563d30708fSChicago Duan             doSubscriptionCollection(ec, asyncResp, resp);
2573d30708fSChicago Duan             },
2583d30708fSChicago Duan             "xyz.openbmc_project.Network.SNMP",
2593d30708fSChicago Duan             "/xyz/openbmc_project/network/snmp/manager",
2603d30708fSChicago Duan             "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
2617e860f15SJohn Edward Broadbent         });
2623d30708fSChicago Duan 
2637e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
2647eeafa76SAbhishek Patel         .privileges(redfish::privileges::postEventDestinationCollection)
265002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
266002d39b4SEd Tanous             [&app](const crow::Request& req,
2677e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2683ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
26945ca1b86SEd Tanous         {
27045ca1b86SEd Tanous             return;
27145ca1b86SEd Tanous         }
272fffb8c1fSEd Tanous         if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
273fffb8c1fSEd Tanous             maxNoOfSubscriptions)
274e5aaf047SAppaRao Puli         {
275e5aaf047SAppaRao Puli             messages::eventSubscriptionLimitExceeded(asyncResp->res);
276e5aaf047SAppaRao Puli             return;
277e5aaf047SAppaRao Puli         }
278e5aaf047SAppaRao Puli         std::string destUrl;
279e5aaf047SAppaRao Puli         std::string protocol;
280e5aaf047SAppaRao Puli         std::optional<std::string> context;
281e5aaf047SAppaRao Puli         std::optional<std::string> subscriptionType;
28223a21a1cSEd Tanous         std::optional<std::string> eventFormatType2;
283e5aaf047SAppaRao Puli         std::optional<std::string> retryPolicy;
284e5aaf047SAppaRao Puli         std::optional<std::vector<std::string>> msgIds;
285e5aaf047SAppaRao Puli         std::optional<std::vector<std::string>> regPrefixes;
286e56f254cSSunitha Harish         std::optional<std::vector<std::string>> resTypes;
287e5aaf047SAppaRao Puli         std::optional<std::vector<nlohmann::json>> headers;
288144b6318SAppaRao Puli         std::optional<std::vector<nlohmann::json>> mrdJsonArray;
289e5aaf047SAppaRao Puli 
29015ed6780SWilly Tu         if (!json_util::readJsonPatch(
291002d39b4SEd Tanous                 req, asyncResp->res, "Destination", destUrl, "Context", context,
292002d39b4SEd Tanous                 "Protocol", protocol, "SubscriptionType", subscriptionType,
293002d39b4SEd Tanous                 "EventFormatType", eventFormatType2, "HttpHeaders", headers,
294002d39b4SEd Tanous                 "RegistryPrefixes", regPrefixes, "MessageIds", msgIds,
295002d39b4SEd Tanous                 "DeliveryRetryPolicy", retryPolicy, "MetricReportDefinitions",
296002d39b4SEd Tanous                 mrdJsonArray, "ResourceTypes", resTypes))
297e5aaf047SAppaRao Puli         {
298e5aaf047SAppaRao Puli             return;
299e5aaf047SAppaRao Puli         }
300e5aaf047SAppaRao Puli 
301600af5f1SAppaRao Puli         // https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
302600af5f1SAppaRao Puli         static constexpr const uint16_t maxDestinationSize = 2000;
303600af5f1SAppaRao Puli         if (destUrl.size() > maxDestinationSize)
304600af5f1SAppaRao Puli         {
305600af5f1SAppaRao Puli             messages::stringValueTooLong(asyncResp->res, "Destination",
306600af5f1SAppaRao Puli                                          maxDestinationSize);
307600af5f1SAppaRao Puli             return;
308600af5f1SAppaRao Puli         }
309600af5f1SAppaRao Puli 
310dd28ba82SAppaRao Puli         if (regPrefixes && msgIds)
311dd28ba82SAppaRao Puli         {
31226f6976fSEd Tanous             if (!regPrefixes->empty() && !msgIds->empty())
313dd28ba82SAppaRao Puli             {
314002d39b4SEd Tanous                 messages::propertyValueConflict(asyncResp->res, "MessageIds",
315002d39b4SEd Tanous                                                 "RegistryPrefixes");
316dd28ba82SAppaRao Puli                 return;
317dd28ba82SAppaRao Puli             }
318dd28ba82SAppaRao Puli         }
319dd28ba82SAppaRao Puli 
320eb1c47d3SEd Tanous         std::string host;
321eb1c47d3SEd Tanous         std::string urlProto;
322eb1c47d3SEd Tanous         uint16_t port = 0;
323eb1c47d3SEd Tanous         std::string path;
324eb1c47d3SEd Tanous 
325002d39b4SEd Tanous         if (!crow::utility::validateAndSplitUrl(destUrl, urlProto, host, port,
326002d39b4SEd Tanous                                                 path))
327e5aaf047SAppaRao Puli         {
32862598e31SEd Tanous             BMCWEB_LOG_WARNING("Failed to validate and split destination url");
329e5aaf047SAppaRao Puli             messages::propertyValueFormatError(asyncResp->res, destUrl,
330e5aaf047SAppaRao Puli                                                "Destination");
331e5aaf047SAppaRao Puli             return;
332e5aaf047SAppaRao Puli         }
333b52664e2SAppaRao Puli 
3343d30708fSChicago Duan         if (protocol == "SNMPv2c")
3353d30708fSChicago Duan         {
3363d30708fSChicago Duan             if (context)
3373d30708fSChicago Duan             {
3383d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "Context",
3393d30708fSChicago Duan                                                 "Protocol");
3403d30708fSChicago Duan                 return;
3413d30708fSChicago Duan             }
3423d30708fSChicago Duan             if (eventFormatType2)
3433d30708fSChicago Duan             {
3443d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res,
3453d30708fSChicago Duan                                                 "EventFormatType", "Protocol");
3463d30708fSChicago Duan                 return;
3473d30708fSChicago Duan             }
3483d30708fSChicago Duan             if (retryPolicy)
3493d30708fSChicago Duan             {
3503d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "RetryPolicy",
3513d30708fSChicago Duan                                                 "Protocol");
3523d30708fSChicago Duan                 return;
3533d30708fSChicago Duan             }
3543d30708fSChicago Duan             if (msgIds)
3553d30708fSChicago Duan             {
3563d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "MessageIds",
3573d30708fSChicago Duan                                                 "Protocol");
3583d30708fSChicago Duan                 return;
3593d30708fSChicago Duan             }
3603d30708fSChicago Duan             if (regPrefixes)
3613d30708fSChicago Duan             {
3623d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res,
3633d30708fSChicago Duan                                                 "RegistryPrefixes", "Protocol");
3643d30708fSChicago Duan                 return;
3653d30708fSChicago Duan             }
3663d30708fSChicago Duan             if (resTypes)
3673d30708fSChicago Duan             {
3683d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "ResourceTypes",
3693d30708fSChicago Duan                                                 "Protocol");
3703d30708fSChicago Duan                 return;
3713d30708fSChicago Duan             }
3723d30708fSChicago Duan             if (headers)
3733d30708fSChicago Duan             {
3743d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "HttpHeaders",
3753d30708fSChicago Duan                                                 "Protocol");
3763d30708fSChicago Duan                 return;
3773d30708fSChicago Duan             }
3783d30708fSChicago Duan             if (mrdJsonArray)
3793d30708fSChicago Duan             {
3803d30708fSChicago Duan                 messages::propertyValueConflict(
3813d30708fSChicago Duan                     asyncResp->res, "MetricReportDefinitions", "Protocol");
3823d30708fSChicago Duan                 return;
3833d30708fSChicago Duan             }
3843d30708fSChicago Duan 
3853d30708fSChicago Duan             addSnmpTrapClient(asyncResp, host, port);
3863d30708fSChicago Duan             return;
3873d30708fSChicago Duan         }
3883d30708fSChicago Duan 
389b52664e2SAppaRao Puli         if (path.empty())
390b52664e2SAppaRao Puli         {
391b52664e2SAppaRao Puli             path = "/";
392b52664e2SAppaRao Puli         }
3933d30708fSChicago Duan 
394f8ca6d79SEd Tanous         std::shared_ptr<Subscription> subValue = std::make_shared<Subscription>(
395f8ca6d79SEd Tanous             host, port, path, urlProto, app.ioContext());
396b52664e2SAppaRao Puli 
397b52664e2SAppaRao Puli         subValue->destinationUrl = destUrl;
398e5aaf047SAppaRao Puli 
399e5aaf047SAppaRao Puli         if (subscriptionType)
400e5aaf047SAppaRao Puli         {
401e5aaf047SAppaRao Puli             if (*subscriptionType != "RedfishEvent")
402e5aaf047SAppaRao Puli             {
403fffb8c1fSEd Tanous                 messages::propertyValueNotInList(
404fffb8c1fSEd Tanous                     asyncResp->res, *subscriptionType, "SubscriptionType");
405e5aaf047SAppaRao Puli                 return;
406e5aaf047SAppaRao Puli             }
407b52664e2SAppaRao Puli             subValue->subscriptionType = *subscriptionType;
408e5aaf047SAppaRao Puli         }
409e5aaf047SAppaRao Puli         else
410e5aaf047SAppaRao Puli         {
411b52664e2SAppaRao Puli             subValue->subscriptionType = "RedfishEvent"; // Default
412e5aaf047SAppaRao Puli         }
413e5aaf047SAppaRao Puli 
414e5aaf047SAppaRao Puli         if (protocol != "Redfish")
415e5aaf047SAppaRao Puli         {
416e5aaf047SAppaRao Puli             messages::propertyValueNotInList(asyncResp->res, protocol,
417e5aaf047SAppaRao Puli                                              "Protocol");
418e5aaf047SAppaRao Puli             return;
419e5aaf047SAppaRao Puli         }
420b52664e2SAppaRao Puli         subValue->protocol = protocol;
421e5aaf047SAppaRao Puli 
42223a21a1cSEd Tanous         if (eventFormatType2)
423e5aaf047SAppaRao Puli         {
424*3544d2a7SEd Tanous             if (std::ranges::find(supportedEvtFormatTypes, *eventFormatType2) ==
425*3544d2a7SEd Tanous                 supportedEvtFormatTypes.end())
426e5aaf047SAppaRao Puli             {
427fffb8c1fSEd Tanous                 messages::propertyValueNotInList(
428fffb8c1fSEd Tanous                     asyncResp->res, *eventFormatType2, "EventFormatType");
429e5aaf047SAppaRao Puli                 return;
430e5aaf047SAppaRao Puli             }
43123a21a1cSEd Tanous             subValue->eventFormatType = *eventFormatType2;
432e5aaf047SAppaRao Puli         }
433e5aaf047SAppaRao Puli         else
434e5aaf047SAppaRao Puli         {
435e5aaf047SAppaRao Puli             // If not specified, use default "Event"
43623a21a1cSEd Tanous             subValue->eventFormatType = "Event";
437e5aaf047SAppaRao Puli         }
438e5aaf047SAppaRao Puli 
439e5aaf047SAppaRao Puli         if (context)
440e5aaf047SAppaRao Puli         {
441600af5f1SAppaRao Puli             // This value is selected aribitrarily.
442600af5f1SAppaRao Puli             constexpr const size_t maxContextSize = 256;
443600af5f1SAppaRao Puli             if (context->size() > maxContextSize)
444600af5f1SAppaRao Puli             {
445600af5f1SAppaRao Puli                 messages::stringValueTooLong(asyncResp->res, "Context",
446600af5f1SAppaRao Puli                                              maxContextSize);
447600af5f1SAppaRao Puli                 return;
448600af5f1SAppaRao Puli             }
449b52664e2SAppaRao Puli             subValue->customText = *context;
450e5aaf047SAppaRao Puli         }
451e5aaf047SAppaRao Puli 
452e5aaf047SAppaRao Puli         if (headers)
453e5aaf047SAppaRao Puli         {
454600af5f1SAppaRao Puli             size_t cumulativeLen = 0;
455600af5f1SAppaRao Puli 
456601c71aeSEd Tanous             for (const nlohmann::json& headerChunk : *headers)
457601c71aeSEd Tanous             {
458600af5f1SAppaRao Puli                 std::string hdr{headerChunk.dump(
459600af5f1SAppaRao Puli                     -1, ' ', true, nlohmann::json::error_handler_t::replace)};
460600af5f1SAppaRao Puli                 cumulativeLen += hdr.length();
461600af5f1SAppaRao Puli 
462600af5f1SAppaRao Puli                 // This value is selected to mirror http_connection.hpp
463600af5f1SAppaRao Puli                 constexpr const uint16_t maxHeaderSizeED = 8096;
464600af5f1SAppaRao Puli                 if (cumulativeLen > maxHeaderSizeED)
465600af5f1SAppaRao Puli                 {
466600af5f1SAppaRao Puli                     messages::arraySizeTooLong(asyncResp->res, "HttpHeaders",
467600af5f1SAppaRao Puli                                                maxHeaderSizeED);
468600af5f1SAppaRao Puli                     return;
469600af5f1SAppaRao Puli                 }
470601c71aeSEd Tanous                 for (const auto& item : headerChunk.items())
471601c71aeSEd Tanous                 {
472601c71aeSEd Tanous                     const std::string* value =
473601c71aeSEd Tanous                         item.value().get_ptr<const std::string*>();
474601c71aeSEd Tanous                     if (value == nullptr)
475601c71aeSEd Tanous                     {
476601c71aeSEd Tanous                         messages::propertyValueFormatError(
477f818b04dSEd Tanous                             asyncResp->res, item.value(),
478601c71aeSEd Tanous                             "HttpHeaders/" + item.key());
479601c71aeSEd Tanous                         return;
480601c71aeSEd Tanous                     }
481601c71aeSEd Tanous                     subValue->httpHeaders.set(item.key(), *value);
482601c71aeSEd Tanous                 }
483601c71aeSEd Tanous             }
484e5aaf047SAppaRao Puli         }
485e5aaf047SAppaRao Puli 
486e5aaf047SAppaRao Puli         if (regPrefixes)
487e5aaf047SAppaRao Puli         {
488e5aaf047SAppaRao Puli             for (const std::string& it : *regPrefixes)
489e5aaf047SAppaRao Puli             {
490*3544d2a7SEd Tanous                 if (std::ranges::find(supportedRegPrefixes, it) ==
491*3544d2a7SEd Tanous                     supportedRegPrefixes.end())
492e5aaf047SAppaRao Puli                 {
493fffb8c1fSEd Tanous                     messages::propertyValueNotInList(asyncResp->res, it,
494fffb8c1fSEd Tanous                                                      "RegistryPrefixes");
495e5aaf047SAppaRao Puli                     return;
496e5aaf047SAppaRao Puli                 }
497e5aaf047SAppaRao Puli             }
498b52664e2SAppaRao Puli             subValue->registryPrefixes = *regPrefixes;
499e5aaf047SAppaRao Puli         }
500e5aaf047SAppaRao Puli 
501e56f254cSSunitha Harish         if (resTypes)
502e56f254cSSunitha Harish         {
503e56f254cSSunitha Harish             for (const std::string& it : *resTypes)
504e56f254cSSunitha Harish             {
505*3544d2a7SEd Tanous                 if (std::ranges::find(supportedResourceTypes, it) ==
506*3544d2a7SEd Tanous                     supportedResourceTypes.end())
507e56f254cSSunitha Harish                 {
508e56f254cSSunitha Harish                     messages::propertyValueNotInList(asyncResp->res, it,
509e56f254cSSunitha Harish                                                      "ResourceTypes");
510e56f254cSSunitha Harish                     return;
511e56f254cSSunitha Harish                 }
512e56f254cSSunitha Harish             }
513e56f254cSSunitha Harish             subValue->resourceTypes = *resTypes;
514e56f254cSSunitha Harish         }
515e56f254cSSunitha Harish 
516e5aaf047SAppaRao Puli         if (msgIds)
517e5aaf047SAppaRao Puli         {
518b304bd79SP Dheeraj Srujan Kumar             std::vector<std::string> registryPrefix;
519b304bd79SP Dheeraj Srujan Kumar 
5207e860f15SJohn Edward Broadbent             // If no registry prefixes are mentioned, consider all
5217e860f15SJohn Edward Broadbent             // supported prefixes
522b304bd79SP Dheeraj Srujan Kumar             if (subValue->registryPrefixes.empty())
523b304bd79SP Dheeraj Srujan Kumar             {
524b304bd79SP Dheeraj Srujan Kumar                 registryPrefix.assign(supportedRegPrefixes.begin(),
525b304bd79SP Dheeraj Srujan Kumar                                       supportedRegPrefixes.end());
526b304bd79SP Dheeraj Srujan Kumar             }
527b304bd79SP Dheeraj Srujan Kumar             else
528b304bd79SP Dheeraj Srujan Kumar             {
529b304bd79SP Dheeraj Srujan Kumar                 registryPrefix = subValue->registryPrefixes;
530b304bd79SP Dheeraj Srujan Kumar             }
531b304bd79SP Dheeraj Srujan Kumar 
532b304bd79SP Dheeraj Srujan Kumar             for (const std::string& id : *msgIds)
533b304bd79SP Dheeraj Srujan Kumar             {
534b304bd79SP Dheeraj Srujan Kumar                 bool validId = false;
535b304bd79SP Dheeraj Srujan Kumar 
536b304bd79SP Dheeraj Srujan Kumar                 // Check for Message ID in each of the selected Registry
537b304bd79SP Dheeraj Srujan Kumar                 for (const std::string& it : registryPrefix)
538b304bd79SP Dheeraj Srujan Kumar                 {
539fffb8c1fSEd Tanous                     const std::span<const redfish::registries::MessageEntry>
540fffb8c1fSEd Tanous                         registry =
541fffb8c1fSEd Tanous                             redfish::registries::getRegistryFromPrefix(it);
542b304bd79SP Dheeraj Srujan Kumar 
543*3544d2a7SEd Tanous                     if (std::ranges::any_of(
544*3544d2a7SEd Tanous                             registry,
545fffb8c1fSEd Tanous                             [&id](const redfish::registries::MessageEntry&
546fffb8c1fSEd Tanous                                       messageEntry) {
54755f79e6fSEd Tanous                         return id == messageEntry.first;
548b304bd79SP Dheeraj Srujan Kumar                             }))
549b304bd79SP Dheeraj Srujan Kumar                     {
550b304bd79SP Dheeraj Srujan Kumar                         validId = true;
551b304bd79SP Dheeraj Srujan Kumar                         break;
552b304bd79SP Dheeraj Srujan Kumar                     }
553b304bd79SP Dheeraj Srujan Kumar                 }
554b304bd79SP Dheeraj Srujan Kumar 
555b304bd79SP Dheeraj Srujan Kumar                 if (!validId)
556b304bd79SP Dheeraj Srujan Kumar                 {
557b304bd79SP Dheeraj Srujan Kumar                     messages::propertyValueNotInList(asyncResp->res, id,
558b304bd79SP Dheeraj Srujan Kumar                                                      "MessageIds");
559b304bd79SP Dheeraj Srujan Kumar                     return;
560b304bd79SP Dheeraj Srujan Kumar                 }
561b304bd79SP Dheeraj Srujan Kumar             }
562b304bd79SP Dheeraj Srujan Kumar 
563b52664e2SAppaRao Puli             subValue->registryMsgIds = *msgIds;
564e5aaf047SAppaRao Puli         }
565e5aaf047SAppaRao Puli 
566e5aaf047SAppaRao Puli         if (retryPolicy)
567e5aaf047SAppaRao Puli         {
568*3544d2a7SEd Tanous             if (std::ranges::find(supportedRetryPolicies, *retryPolicy) ==
569*3544d2a7SEd Tanous                 supportedRetryPolicies.end())
570e5aaf047SAppaRao Puli             {
571002d39b4SEd Tanous                 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
572002d39b4SEd Tanous                                                  "DeliveryRetryPolicy");
573e5aaf047SAppaRao Puli                 return;
574e5aaf047SAppaRao Puli             }
575b52664e2SAppaRao Puli             subValue->retryPolicy = *retryPolicy;
576e5aaf047SAppaRao Puli         }
577e5aaf047SAppaRao Puli         else
578e5aaf047SAppaRao Puli         {
579e5aaf047SAppaRao Puli             // Default "TerminateAfterRetries"
580b52664e2SAppaRao Puli             subValue->retryPolicy = "TerminateAfterRetries";
581e5aaf047SAppaRao Puli         }
582e5aaf047SAppaRao Puli 
583144b6318SAppaRao Puli         if (mrdJsonArray)
584156d6b00SAppaRao Puli         {
585144b6318SAppaRao Puli             for (nlohmann::json& mrdObj : *mrdJsonArray)
586144b6318SAppaRao Puli             {
587144b6318SAppaRao Puli                 std::string mrdUri;
588ea2e6eecSWilly Tu 
589002d39b4SEd Tanous                 if (!json_util::readJson(mrdObj, asyncResp->res, "@odata.id",
590002d39b4SEd Tanous                                          mrdUri))
591ea2e6eecSWilly Tu 
592144b6318SAppaRao Puli                 {
593144b6318SAppaRao Puli                     return;
594144b6318SAppaRao Puli                 }
595ea2e6eecSWilly Tu                 subValue->metricReportDefinitions.emplace_back(mrdUri);
596144b6318SAppaRao Puli             }
597156d6b00SAppaRao Puli         }
598156d6b00SAppaRao Puli 
599b52664e2SAppaRao Puli         std::string id =
600fffb8c1fSEd Tanous             EventServiceManager::getInstance().addSubscription(subValue);
601b52664e2SAppaRao Puli         if (id.empty())
602e5aaf047SAppaRao Puli         {
603e5aaf047SAppaRao Puli             messages::internalError(asyncResp->res);
604e5aaf047SAppaRao Puli             return;
605e5aaf047SAppaRao Puli         }
606e5aaf047SAppaRao Puli 
607e5aaf047SAppaRao Puli         messages::created(asyncResp->res);
608e5aaf047SAppaRao Puli         asyncResp->res.addHeader(
609e5aaf047SAppaRao Puli             "Location", "/redfish/v1/EventService/Subscriptions/" + id);
6107e860f15SJohn Edward Broadbent         });
611e5aaf047SAppaRao Puli }
612e5aaf047SAppaRao Puli 
6137e860f15SJohn Edward Broadbent inline void requestRoutesEventDestination(App& app)
614e5aaf047SAppaRao Puli {
6159d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
616ed398213SEd Tanous         .privileges(redfish::privileges::getEventDestination)
6177e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
61845ca1b86SEd Tanous             [&app](const crow::Request& req,
6197e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
6207e860f15SJohn Edward Broadbent                    const std::string& param) {
6213ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
62245ca1b86SEd Tanous         {
62345ca1b86SEd Tanous             return;
62445ca1b86SEd Tanous         }
6253d30708fSChicago Duan 
6263d30708fSChicago Duan         if (param.starts_with("snmp"))
6273d30708fSChicago Duan         {
6283d30708fSChicago Duan             getSnmpTrapClient(asyncResp, param);
6293d30708fSChicago Duan             return;
6303d30708fSChicago Duan         }
6313d30708fSChicago Duan 
632b52664e2SAppaRao Puli         std::shared_ptr<Subscription> subValue =
6337e860f15SJohn Edward Broadbent             EventServiceManager::getInstance().getSubscription(param);
634b52664e2SAppaRao Puli         if (subValue == nullptr)
635e5aaf047SAppaRao Puli         {
636002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::not_found);
637e5aaf047SAppaRao Puli             return;
638e5aaf047SAppaRao Puli         }
6397e860f15SJohn Edward Broadbent         const std::string& id = param;
640e5aaf047SAppaRao Puli 
6411476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
6423d30708fSChicago Duan             "#EventDestination.v1_8_0.EventDestination";
6431476687dSEd Tanous         asyncResp->res.jsonValue["Protocol"] = "Redfish";
6443b32780dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
6453b32780dSEd Tanous             "/redfish/v1/EventService/Subscriptions/{}", id);
646e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["Id"] = id;
647e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
648002d39b4SEd Tanous         asyncResp->res.jsonValue["Destination"] = subValue->destinationUrl;
649b52664e2SAppaRao Puli         asyncResp->res.jsonValue["Context"] = subValue->customText;
650e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["SubscriptionType"] =
651b52664e2SAppaRao Puli             subValue->subscriptionType;
652002d39b4SEd Tanous         asyncResp->res.jsonValue["HttpHeaders"] = nlohmann::json::array();
653002d39b4SEd Tanous         asyncResp->res.jsonValue["EventFormatType"] = subValue->eventFormatType;
654e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["RegistryPrefixes"] =
655b52664e2SAppaRao Puli             subValue->registryPrefixes;
656002d39b4SEd Tanous         asyncResp->res.jsonValue["ResourceTypes"] = subValue->resourceTypes;
657e56f254cSSunitha Harish 
658002d39b4SEd Tanous         asyncResp->res.jsonValue["MessageIds"] = subValue->registryMsgIds;
659002d39b4SEd Tanous         asyncResp->res.jsonValue["DeliveryRetryPolicy"] = subValue->retryPolicy;
660144b6318SAppaRao Puli 
6611476687dSEd Tanous         nlohmann::json::array_t mrdJsonArray;
662144b6318SAppaRao Puli         for (const auto& mdrUri : subValue->metricReportDefinitions)
663144b6318SAppaRao Puli         {
6641476687dSEd Tanous             nlohmann::json::object_t mdr;
6651476687dSEd Tanous             mdr["@odata.id"] = mdrUri;
6661476687dSEd Tanous             mrdJsonArray.emplace_back(std::move(mdr));
667144b6318SAppaRao Puli         }
668002d39b4SEd Tanous         asyncResp->res.jsonValue["MetricReportDefinitions"] = mrdJsonArray;
6697e860f15SJohn Edward Broadbent         });
6709d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
671ed398213SEd Tanous         // The below privilege is wrong, it should be ConfigureManager OR
672ed398213SEd Tanous         // ConfigureSelf
6737eeafa76SAbhishek Patel         // https://github.com/openbmc/bmcweb/issues/220
674ed398213SEd Tanous         //.privileges(redfish::privileges::patchEventDestination)
675432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
6767e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
67745ca1b86SEd Tanous             [&app](const crow::Request& req,
6787e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
6797e860f15SJohn Edward Broadbent                    const std::string& param) {
6803ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
68145ca1b86SEd Tanous         {
68245ca1b86SEd Tanous             return;
68345ca1b86SEd Tanous         }
684b52664e2SAppaRao Puli         std::shared_ptr<Subscription> subValue =
6857e860f15SJohn Edward Broadbent             EventServiceManager::getInstance().getSubscription(param);
686b52664e2SAppaRao Puli         if (subValue == nullptr)
687e5aaf047SAppaRao Puli         {
688002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::not_found);
689e5aaf047SAppaRao Puli             return;
690e5aaf047SAppaRao Puli         }
691e5aaf047SAppaRao Puli 
692e5aaf047SAppaRao Puli         std::optional<std::string> context;
693e5aaf047SAppaRao Puli         std::optional<std::string> retryPolicy;
694e5aaf047SAppaRao Puli         std::optional<std::vector<nlohmann::json>> headers;
695e5aaf047SAppaRao Puli 
696002d39b4SEd Tanous         if (!json_util::readJsonPatch(req, asyncResp->res, "Context", context,
697002d39b4SEd Tanous                                       "DeliveryRetryPolicy", retryPolicy,
698002d39b4SEd Tanous                                       "HttpHeaders", headers))
699e5aaf047SAppaRao Puli         {
700e5aaf047SAppaRao Puli             return;
701e5aaf047SAppaRao Puli         }
702e5aaf047SAppaRao Puli 
703e5aaf047SAppaRao Puli         if (context)
704e5aaf047SAppaRao Puli         {
705b52664e2SAppaRao Puli             subValue->customText = *context;
706e5aaf047SAppaRao Puli         }
707e5aaf047SAppaRao Puli 
708e5aaf047SAppaRao Puli         if (headers)
709e5aaf047SAppaRao Puli         {
710601c71aeSEd Tanous             boost::beast::http::fields fields;
711601c71aeSEd Tanous             for (const nlohmann::json& headerChunk : *headers)
712601c71aeSEd Tanous             {
71362bafc01SPatrick Williams                 for (const auto& it : headerChunk.items())
714601c71aeSEd Tanous                 {
715601c71aeSEd Tanous                     const std::string* value =
716601c71aeSEd Tanous                         it.value().get_ptr<const std::string*>();
717601c71aeSEd Tanous                     if (value == nullptr)
718601c71aeSEd Tanous                     {
719601c71aeSEd Tanous                         messages::propertyValueFormatError(
720f818b04dSEd Tanous                             asyncResp->res, it.value(),
721601c71aeSEd Tanous                             "HttpHeaders/" + it.key());
722601c71aeSEd Tanous                         return;
723601c71aeSEd Tanous                     }
724601c71aeSEd Tanous                     fields.set(it.key(), *value);
725601c71aeSEd Tanous                 }
726601c71aeSEd Tanous             }
727601c71aeSEd Tanous             subValue->httpHeaders = fields;
728e5aaf047SAppaRao Puli         }
729e5aaf047SAppaRao Puli 
730e5aaf047SAppaRao Puli         if (retryPolicy)
731e5aaf047SAppaRao Puli         {
732*3544d2a7SEd Tanous             if (std::ranges::find(supportedRetryPolicies, *retryPolicy) ==
733*3544d2a7SEd Tanous                 supportedRetryPolicies.end())
734e5aaf047SAppaRao Puli             {
735002d39b4SEd Tanous                 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
736e5aaf047SAppaRao Puli                                                  "DeliveryRetryPolicy");
737e5aaf047SAppaRao Puli                 return;
738e5aaf047SAppaRao Puli             }
739b52664e2SAppaRao Puli             subValue->retryPolicy = *retryPolicy;
740e5aaf047SAppaRao Puli         }
741e5aaf047SAppaRao Puli 
742b52664e2SAppaRao Puli         EventServiceManager::getInstance().updateSubscriptionData();
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::deleteEventDestination)
749432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
7507e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
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         }
7583d30708fSChicago Duan 
7593d30708fSChicago Duan         if (param.starts_with("snmp"))
7603d30708fSChicago Duan         {
7613d30708fSChicago Duan             deleteSnmpTrapClient(asyncResp, param);
7623d30708fSChicago Duan             EventServiceManager::getInstance().deleteSubscription(param);
7633d30708fSChicago Duan             return;
7643d30708fSChicago Duan         }
7653d30708fSChicago Duan 
766002d39b4SEd Tanous         if (!EventServiceManager::getInstance().isSubscriptionExist(param))
767e5aaf047SAppaRao Puli         {
768002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::not_found);
769e5aaf047SAppaRao Puli             return;
770e5aaf047SAppaRao Puli         }
7717e860f15SJohn Edward Broadbent         EventServiceManager::getInstance().deleteSubscription(param);
7727e860f15SJohn Edward Broadbent         });
773e5aaf047SAppaRao Puli }
774e5aaf047SAppaRao Puli 
775e5aaf047SAppaRao Puli } // namespace redfish
776