xref: /openbmc/bmcweb/features/redfish/lib/event_service.hpp (revision 19bb362b5b45e36db3c4d2db2fafdf191259972b)
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>
27a716aa74SEd Tanous #include <boost/url/parse.hpp>
283d30708fSChicago Duan #include <sdbusplus/unpack_properties.hpp>
293d30708fSChicago Duan #include <utils/dbus_utils.hpp>
30ed398213SEd Tanous 
313d30708fSChicago Duan #include <charconv>
323d30708fSChicago Duan #include <memory>
333544d2a7SEd Tanous #include <ranges>
341e270c5fSPatrick Williams #include <span>
353d30708fSChicago Duan #include <string>
361e270c5fSPatrick Williams 
37e5aaf047SAppaRao Puli namespace redfish
38e5aaf047SAppaRao Puli {
39e5aaf047SAppaRao Puli 
40156d6b00SAppaRao Puli static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
41156d6b00SAppaRao Puli     eventFormatType, metricReportFormatType};
42e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
43b304bd79SP Dheeraj Srujan Kumar     "Base", "OpenBMC", "TaskEvent"};
44e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
45e5aaf047SAppaRao Puli     "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
46e5aaf047SAppaRao Puli 
47e56f254cSSunitha Harish static constexpr const std::array<const char*, 1> supportedResourceTypes = {
48e56f254cSSunitha Harish     "Task"};
49e56f254cSSunitha Harish 
507e860f15SJohn Edward Broadbent inline void requestRoutesEventService(App& app)
51e5aaf047SAppaRao Puli {
527e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
53ed398213SEd Tanous         .privileges(redfish::privileges::getEventService)
54002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
55002d39b4SEd Tanous             [&app](const crow::Request& req,
56002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
573ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
5845ca1b86SEd Tanous         {
5945ca1b86SEd Tanous             return;
6045ca1b86SEd Tanous         }
611476687dSEd Tanous 
621476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/EventService";
631476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
641476687dSEd Tanous             "#EventService.v1_5_0.EventService";
651476687dSEd Tanous         asyncResp->res.jsonValue["Id"] = "EventService";
661476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "Event Service";
675e44e3d8SAppaRao Puli         asyncResp->res.jsonValue["ServerSentEventUri"] =
685e44e3d8SAppaRao Puli             "/redfish/v1/EventService/SSE";
695e44e3d8SAppaRao Puli 
701476687dSEd Tanous         asyncResp->res.jsonValue["Subscriptions"]["@odata.id"] =
711476687dSEd Tanous             "/redfish/v1/EventService/Subscriptions";
72002d39b4SEd Tanous         asyncResp->res
73002d39b4SEd Tanous             .jsonValue["Actions"]["#EventService.SubmitTestEvent"]["target"] =
741476687dSEd Tanous             "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent";
75e5aaf047SAppaRao Puli 
7628afb49cSJunLin Chen         const persistent_data::EventServiceConfig eventServiceConfig =
7728afb49cSJunLin Chen             persistent_data::EventServiceStore::getInstance()
7828afb49cSJunLin Chen                 .getEventServiceConfig();
797d1cc387SAppaRao Puli 
807d1cc387SAppaRao Puli         asyncResp->res.jsonValue["Status"]["State"] =
8128afb49cSJunLin Chen             (eventServiceConfig.enabled ? "Enabled" : "Disabled");
82002d39b4SEd Tanous         asyncResp->res.jsonValue["ServiceEnabled"] = eventServiceConfig.enabled;
837e860f15SJohn Edward Broadbent         asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
8428afb49cSJunLin Chen             eventServiceConfig.retryAttempts;
85e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
8628afb49cSJunLin Chen             eventServiceConfig.retryTimeoutInterval;
87002d39b4SEd Tanous         asyncResp->res.jsonValue["EventFormatTypes"] = supportedEvtFormatTypes;
880fda0f12SGeorge Liu         asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
890fda0f12SGeorge Liu         asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
9007941a88SAyushi Smriti 
91613dabeaSEd Tanous         nlohmann::json::object_t supportedSSEFilters;
92613dabeaSEd Tanous         supportedSSEFilters["EventFormatType"] = true;
93613dabeaSEd Tanous         supportedSSEFilters["MessageId"] = true;
94613dabeaSEd Tanous         supportedSSEFilters["MetricReportDefinition"] = true;
95613dabeaSEd Tanous         supportedSSEFilters["RegistryPrefix"] = true;
96613dabeaSEd Tanous         supportedSSEFilters["OriginResource"] = false;
97613dabeaSEd Tanous         supportedSSEFilters["ResourceType"] = false;
9807941a88SAyushi Smriti 
9907941a88SAyushi Smriti         asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
100613dabeaSEd Tanous             std::move(supportedSSEFilters);
1017e860f15SJohn Edward Broadbent     });
102e5aaf047SAppaRao Puli 
1037e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
104ed398213SEd Tanous         .privileges(redfish::privileges::patchEventService)
1057e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
10645ca1b86SEd Tanous             [&app](const crow::Request& req,
10745ca1b86SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1083ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
109e5aaf047SAppaRao Puli         {
11045ca1b86SEd Tanous             return;
11145ca1b86SEd Tanous         }
112e5aaf047SAppaRao Puli         std::optional<bool> serviceEnabled;
113e5aaf047SAppaRao Puli         std::optional<uint32_t> retryAttemps;
114e5aaf047SAppaRao Puli         std::optional<uint32_t> retryInterval;
115e5aaf047SAppaRao Puli 
11615ed6780SWilly Tu         if (!json_util::readJsonPatch(
1177e860f15SJohn Edward Broadbent                 req, asyncResp->res, "ServiceEnabled", serviceEnabled,
1187e860f15SJohn Edward Broadbent                 "DeliveryRetryAttempts", retryAttemps,
1197e860f15SJohn Edward Broadbent                 "DeliveryRetryIntervalSeconds", retryInterval))
120e5aaf047SAppaRao Puli         {
121e5aaf047SAppaRao Puli             return;
122e5aaf047SAppaRao Puli         }
123e5aaf047SAppaRao Puli 
12428afb49cSJunLin Chen         persistent_data::EventServiceConfig eventServiceConfig =
12528afb49cSJunLin Chen             persistent_data::EventServiceStore::getInstance()
12628afb49cSJunLin Chen                 .getEventServiceConfig();
1277d1cc387SAppaRao Puli 
128e5aaf047SAppaRao Puli         if (serviceEnabled)
129e5aaf047SAppaRao Puli         {
13028afb49cSJunLin Chen             eventServiceConfig.enabled = *serviceEnabled;
131e5aaf047SAppaRao Puli         }
132e5aaf047SAppaRao Puli 
133e5aaf047SAppaRao Puli         if (retryAttemps)
134e5aaf047SAppaRao Puli         {
135e5aaf047SAppaRao Puli             // Supported range [1-3]
136e5aaf047SAppaRao Puli             if ((*retryAttemps < 1) || (*retryAttemps > 3))
137e5aaf047SAppaRao Puli             {
138e5aaf047SAppaRao Puli                 messages::queryParameterOutOfRange(
139e5aaf047SAppaRao Puli                     asyncResp->res, std::to_string(*retryAttemps),
140e5aaf047SAppaRao Puli                     "DeliveryRetryAttempts", "[1-3]");
141e5aaf047SAppaRao Puli             }
142e5aaf047SAppaRao Puli             else
143e5aaf047SAppaRao Puli             {
14428afb49cSJunLin Chen                 eventServiceConfig.retryAttempts = *retryAttemps;
145e5aaf047SAppaRao Puli             }
146e5aaf047SAppaRao Puli         }
147e5aaf047SAppaRao Puli 
148e5aaf047SAppaRao Puli         if (retryInterval)
149e5aaf047SAppaRao Puli         {
15033a32b34SGunnar Mills             // Supported range [5 - 180]
15133a32b34SGunnar Mills             if ((*retryInterval < 5) || (*retryInterval > 180))
152e5aaf047SAppaRao Puli             {
153e5aaf047SAppaRao Puli                 messages::queryParameterOutOfRange(
154e5aaf047SAppaRao Puli                     asyncResp->res, std::to_string(*retryInterval),
15533a32b34SGunnar Mills                     "DeliveryRetryIntervalSeconds", "[5-180]");
156e5aaf047SAppaRao Puli             }
157e5aaf047SAppaRao Puli             else
158e5aaf047SAppaRao Puli             {
159002d39b4SEd Tanous                 eventServiceConfig.retryTimeoutInterval = *retryInterval;
160e5aaf047SAppaRao Puli             }
161e5aaf047SAppaRao Puli         }
162e5aaf047SAppaRao Puli 
1637d1cc387SAppaRao Puli         EventServiceManager::getInstance().setEventServiceConfig(
16428afb49cSJunLin Chen             eventServiceConfig);
1657e860f15SJohn Edward Broadbent     });
1660b4bdd93SAppaRao Puli }
1670b4bdd93SAppaRao Puli 
1687e860f15SJohn Edward Broadbent inline void requestRoutesSubmitTestEvent(App& app)
1690b4bdd93SAppaRao Puli {
1707e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
1717e860f15SJohn Edward Broadbent         app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
172ed398213SEd Tanous         .privileges(redfish::privileges::postEventService)
1737e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
17445ca1b86SEd Tanous             [&app](const crow::Request& req,
1757e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1763ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
17745ca1b86SEd Tanous         {
17845ca1b86SEd Tanous             return;
17945ca1b86SEd Tanous         }
1806ba8c82eSsunharis_in         if (!EventServiceManager::getInstance().sendTestEventLog())
1816ba8c82eSsunharis_in         {
1826ba8c82eSsunharis_in             messages::serviceDisabled(asyncResp->res,
1836ba8c82eSsunharis_in                                       "/redfish/v1/EventService/");
1846ba8c82eSsunharis_in             return;
1856ba8c82eSsunharis_in         }
1868d1b46d7Szhanghch05         asyncResp->res.result(boost::beast::http::status::no_content);
1877e860f15SJohn Edward Broadbent     });
188e5aaf047SAppaRao Puli }
189e5aaf047SAppaRao Puli 
1903d30708fSChicago Duan inline void doSubscriptionCollection(
191e81de512SEd Tanous     const boost::system::error_code& ec,
1923d30708fSChicago Duan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1933d30708fSChicago Duan     const dbus::utility::ManagedObjectType& resp)
1943d30708fSChicago Duan {
1953d30708fSChicago Duan     if (ec)
1963d30708fSChicago Duan     {
1971306101eSEd Tanous         if (ec.value() == EBADR || ec.value() == EHOSTUNREACH)
1983d30708fSChicago Duan         {
1993d30708fSChicago Duan             // This is an optional process so just return if it isn't there
2003d30708fSChicago Duan             return;
2013d30708fSChicago Duan         }
2023d30708fSChicago Duan 
20362598e31SEd Tanous         BMCWEB_LOG_ERROR("D-Bus response error on GetManagedObjects {}", ec);
2043d30708fSChicago Duan         messages::internalError(asyncResp->res);
2053d30708fSChicago Duan         return;
2063d30708fSChicago Duan     }
2073d30708fSChicago Duan     nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
2083d30708fSChicago Duan     for (const auto& objpath : resp)
2093d30708fSChicago Duan     {
2103d30708fSChicago Duan         sdbusplus::message::object_path path(objpath.first);
2113d30708fSChicago Duan         const std::string snmpId = path.filename();
2123d30708fSChicago Duan         if (snmpId.empty())
2133d30708fSChicago Duan         {
21462598e31SEd Tanous             BMCWEB_LOG_ERROR("The SNMP client ID is wrong");
2153d30708fSChicago Duan             messages::internalError(asyncResp->res);
2163d30708fSChicago Duan             return;
2173d30708fSChicago Duan         }
2183d30708fSChicago Duan 
2193d30708fSChicago Duan         getSnmpSubscriptionList(asyncResp, snmpId, memberArray);
2203d30708fSChicago Duan     }
2213d30708fSChicago Duan }
2223d30708fSChicago Duan 
2237e860f15SJohn Edward Broadbent inline void requestRoutesEventDestinationCollection(App& app)
224e5aaf047SAppaRao Puli {
2251ebe3e41SGayathri Leburu     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
226ed398213SEd Tanous         .privileges(redfish::privileges::getEventDestinationCollection)
2277e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
22845ca1b86SEd Tanous             [&app](const crow::Request& req,
2297e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2303ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
23145ca1b86SEd Tanous         {
23245ca1b86SEd Tanous             return;
23345ca1b86SEd Tanous         }
2341476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
2351476687dSEd Tanous             "#EventDestinationCollection.EventDestinationCollection";
2361476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
2371476687dSEd Tanous             "/redfish/v1/EventService/Subscriptions";
238002d39b4SEd Tanous         asyncResp->res.jsonValue["Name"] = "Event Destination Collections";
239e5aaf047SAppaRao Puli 
240002d39b4SEd Tanous         nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
241e5aaf047SAppaRao Puli 
242b52664e2SAppaRao Puli         std::vector<std::string> subscripIds =
243b52664e2SAppaRao Puli             EventServiceManager::getInstance().getAllIDs();
244b52664e2SAppaRao Puli         memberArray = nlohmann::json::array();
245002d39b4SEd Tanous         asyncResp->res.jsonValue["Members@odata.count"] = subscripIds.size();
246b52664e2SAppaRao Puli 
247b52664e2SAppaRao Puli         for (const std::string& id : subscripIds)
248e5aaf047SAppaRao Puli         {
2491476687dSEd Tanous             nlohmann::json::object_t member;
2503d30708fSChicago Duan             member["@odata.id"] = boost::urls::format(
2513d30708fSChicago Duan                 "/redfish/v1/EventService/Subscriptions/{}" + id);
252b2ba3072SPatrick Williams             memberArray.emplace_back(std::move(member));
253e5aaf047SAppaRao Puli         }
2543d30708fSChicago Duan         crow::connections::systemBus->async_method_call(
255e81de512SEd Tanous             [asyncResp](const boost::system::error_code& ec,
2563d30708fSChicago Duan                         const dbus::utility::ManagedObjectType& resp) {
2573d30708fSChicago Duan             doSubscriptionCollection(ec, asyncResp, resp);
2583d30708fSChicago Duan         },
2593d30708fSChicago Duan             "xyz.openbmc_project.Network.SNMP",
2603d30708fSChicago Duan             "/xyz/openbmc_project/network/snmp/manager",
2613d30708fSChicago Duan             "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
2627e860f15SJohn Edward Broadbent     });
2633d30708fSChicago Duan 
2647e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
2657eeafa76SAbhishek Patel         .privileges(redfish::privileges::postEventDestinationCollection)
266002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
267002d39b4SEd Tanous             [&app](const crow::Request& req,
2687e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2693ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
27045ca1b86SEd Tanous         {
27145ca1b86SEd Tanous             return;
27245ca1b86SEd Tanous         }
273fffb8c1fSEd Tanous         if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
274fffb8c1fSEd Tanous             maxNoOfSubscriptions)
275e5aaf047SAppaRao Puli         {
276e5aaf047SAppaRao Puli             messages::eventSubscriptionLimitExceeded(asyncResp->res);
277e5aaf047SAppaRao Puli             return;
278e5aaf047SAppaRao Puli         }
279e5aaf047SAppaRao Puli         std::string destUrl;
280e5aaf047SAppaRao Puli         std::string protocol;
281*19bb362bSEd Tanous         std::optional<bool> verifyCertificate;
282e5aaf047SAppaRao Puli         std::optional<std::string> context;
283e5aaf047SAppaRao Puli         std::optional<std::string> subscriptionType;
28423a21a1cSEd Tanous         std::optional<std::string> eventFormatType2;
285e5aaf047SAppaRao Puli         std::optional<std::string> retryPolicy;
286e5aaf047SAppaRao Puli         std::optional<std::vector<std::string>> msgIds;
287e5aaf047SAppaRao Puli         std::optional<std::vector<std::string>> regPrefixes;
288e56f254cSSunitha Harish         std::optional<std::vector<std::string>> resTypes;
28978d4ec4fSEd Tanous         std::optional<std::vector<nlohmann::json::object_t>> headers;
29078d4ec4fSEd Tanous         std::optional<std::vector<nlohmann::json::object_t>> mrdJsonArray;
291e5aaf047SAppaRao Puli 
29215ed6780SWilly Tu         if (!json_util::readJsonPatch(
293002d39b4SEd Tanous                 req, asyncResp->res, "Destination", destUrl, "Context", context,
294002d39b4SEd Tanous                 "Protocol", protocol, "SubscriptionType", subscriptionType,
295002d39b4SEd Tanous                 "EventFormatType", eventFormatType2, "HttpHeaders", headers,
296002d39b4SEd Tanous                 "RegistryPrefixes", regPrefixes, "MessageIds", msgIds,
297002d39b4SEd Tanous                 "DeliveryRetryPolicy", retryPolicy, "MetricReportDefinitions",
298*19bb362bSEd Tanous                 mrdJsonArray, "ResourceTypes", resTypes, "VerifyCertificate",
299*19bb362bSEd Tanous                 verifyCertificate))
300e5aaf047SAppaRao Puli         {
301e5aaf047SAppaRao Puli             return;
302e5aaf047SAppaRao Puli         }
303e5aaf047SAppaRao Puli 
304600af5f1SAppaRao Puli         // https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
305600af5f1SAppaRao Puli         static constexpr const uint16_t maxDestinationSize = 2000;
306600af5f1SAppaRao Puli         if (destUrl.size() > maxDestinationSize)
307600af5f1SAppaRao Puli         {
308600af5f1SAppaRao Puli             messages::stringValueTooLong(asyncResp->res, "Destination",
309600af5f1SAppaRao Puli                                          maxDestinationSize);
310600af5f1SAppaRao Puli             return;
311600af5f1SAppaRao Puli         }
312600af5f1SAppaRao Puli 
313dd28ba82SAppaRao Puli         if (regPrefixes && msgIds)
314dd28ba82SAppaRao Puli         {
31526f6976fSEd Tanous             if (!regPrefixes->empty() && !msgIds->empty())
316dd28ba82SAppaRao Puli             {
317002d39b4SEd Tanous                 messages::propertyValueConflict(asyncResp->res, "MessageIds",
318002d39b4SEd Tanous                                                 "RegistryPrefixes");
319dd28ba82SAppaRao Puli                 return;
320dd28ba82SAppaRao Puli             }
321dd28ba82SAppaRao Puli         }
322dd28ba82SAppaRao Puli 
3236fd29553SEd Tanous         boost::system::result<boost::urls::url> url =
324a716aa74SEd Tanous             boost::urls::parse_absolute_uri(destUrl);
325a716aa74SEd Tanous         if (!url)
326e5aaf047SAppaRao Puli         {
32762598e31SEd Tanous             BMCWEB_LOG_WARNING("Failed to validate and split destination url");
328e5aaf047SAppaRao Puli             messages::propertyValueFormatError(asyncResp->res, destUrl,
329e5aaf047SAppaRao Puli                                                "Destination");
330e5aaf047SAppaRao Puli             return;
331e5aaf047SAppaRao Puli         }
332a716aa74SEd Tanous         url->normalize();
333a716aa74SEd Tanous         crow::utility::setProtocolDefaults(*url, protocol);
334a716aa74SEd Tanous         crow::utility::setPortDefaults(*url);
335a716aa74SEd Tanous 
336a716aa74SEd Tanous         if (url->path().empty())
337a716aa74SEd Tanous         {
338a716aa74SEd Tanous             url->set_path("/");
339a716aa74SEd Tanous         }
340a716aa74SEd Tanous 
341a716aa74SEd Tanous         if (url->has_userinfo())
342a716aa74SEd Tanous         {
343a716aa74SEd Tanous             messages::propertyValueFormatError(asyncResp->res, destUrl,
344a716aa74SEd Tanous                                                "Destination");
345a716aa74SEd Tanous             return;
346a716aa74SEd Tanous         }
347b52664e2SAppaRao Puli 
3483d30708fSChicago Duan         if (protocol == "SNMPv2c")
3493d30708fSChicago Duan         {
3503d30708fSChicago Duan             if (context)
3513d30708fSChicago Duan             {
3523d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "Context",
3533d30708fSChicago Duan                                                 "Protocol");
3543d30708fSChicago Duan                 return;
3553d30708fSChicago Duan             }
3563d30708fSChicago Duan             if (eventFormatType2)
3573d30708fSChicago Duan             {
3583d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res,
3593d30708fSChicago Duan                                                 "EventFormatType", "Protocol");
3603d30708fSChicago Duan                 return;
3613d30708fSChicago Duan             }
3623d30708fSChicago Duan             if (retryPolicy)
3633d30708fSChicago Duan             {
3643d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "RetryPolicy",
3653d30708fSChicago Duan                                                 "Protocol");
3663d30708fSChicago Duan                 return;
3673d30708fSChicago Duan             }
3683d30708fSChicago Duan             if (msgIds)
3693d30708fSChicago Duan             {
3703d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "MessageIds",
3713d30708fSChicago Duan                                                 "Protocol");
3723d30708fSChicago Duan                 return;
3733d30708fSChicago Duan             }
3743d30708fSChicago Duan             if (regPrefixes)
3753d30708fSChicago Duan             {
3763d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res,
3773d30708fSChicago Duan                                                 "RegistryPrefixes", "Protocol");
3783d30708fSChicago Duan                 return;
3793d30708fSChicago Duan             }
3803d30708fSChicago Duan             if (resTypes)
3813d30708fSChicago Duan             {
3823d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "ResourceTypes",
3833d30708fSChicago Duan                                                 "Protocol");
3843d30708fSChicago Duan                 return;
3853d30708fSChicago Duan             }
3863d30708fSChicago Duan             if (headers)
3873d30708fSChicago Duan             {
3883d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "HttpHeaders",
3893d30708fSChicago Duan                                                 "Protocol");
3903d30708fSChicago Duan                 return;
3913d30708fSChicago Duan             }
3923d30708fSChicago Duan             if (mrdJsonArray)
3933d30708fSChicago Duan             {
3943d30708fSChicago Duan                 messages::propertyValueConflict(
3953d30708fSChicago Duan                     asyncResp->res, "MetricReportDefinitions", "Protocol");
3963d30708fSChicago Duan                 return;
3973d30708fSChicago Duan             }
398a716aa74SEd Tanous             if (url->scheme() != "snmp")
399a716aa74SEd Tanous             {
400a716aa74SEd Tanous                 messages::propertyValueConflict(asyncResp->res, "Destination",
401a716aa74SEd Tanous                                                 "Protocol");
4023d30708fSChicago Duan                 return;
4033d30708fSChicago Duan             }
4043d30708fSChicago Duan 
405a716aa74SEd Tanous             addSnmpTrapClient(asyncResp, url->host_address(),
406a716aa74SEd Tanous                               url->port_number());
407a716aa74SEd Tanous             return;
408b52664e2SAppaRao Puli         }
4093d30708fSChicago Duan 
410a716aa74SEd Tanous         std::shared_ptr<Subscription> subValue =
411a716aa74SEd Tanous             std::make_shared<Subscription>(*url, app.ioContext());
412b52664e2SAppaRao Puli 
413a716aa74SEd Tanous         subValue->destinationUrl = std::move(*url);
414e5aaf047SAppaRao Puli 
415e5aaf047SAppaRao Puli         if (subscriptionType)
416e5aaf047SAppaRao Puli         {
417e5aaf047SAppaRao Puli             if (*subscriptionType != "RedfishEvent")
418e5aaf047SAppaRao Puli             {
419fffb8c1fSEd Tanous                 messages::propertyValueNotInList(
420fffb8c1fSEd Tanous                     asyncResp->res, *subscriptionType, "SubscriptionType");
421e5aaf047SAppaRao Puli                 return;
422e5aaf047SAppaRao Puli             }
423b52664e2SAppaRao Puli             subValue->subscriptionType = *subscriptionType;
424e5aaf047SAppaRao Puli         }
425e5aaf047SAppaRao Puli         else
426e5aaf047SAppaRao Puli         {
427b52664e2SAppaRao Puli             subValue->subscriptionType = "RedfishEvent"; // Default
428e5aaf047SAppaRao Puli         }
429e5aaf047SAppaRao Puli 
430e5aaf047SAppaRao Puli         if (protocol != "Redfish")
431e5aaf047SAppaRao Puli         {
432e5aaf047SAppaRao Puli             messages::propertyValueNotInList(asyncResp->res, protocol,
433e5aaf047SAppaRao Puli                                              "Protocol");
434e5aaf047SAppaRao Puli             return;
435e5aaf047SAppaRao Puli         }
436b52664e2SAppaRao Puli         subValue->protocol = protocol;
437e5aaf047SAppaRao Puli 
438*19bb362bSEd Tanous         if (verifyCertificate)
439*19bb362bSEd Tanous         {
440*19bb362bSEd Tanous             subValue->verifyCertificate = *verifyCertificate;
441*19bb362bSEd Tanous         }
442*19bb362bSEd Tanous 
44323a21a1cSEd Tanous         if (eventFormatType2)
444e5aaf047SAppaRao Puli         {
4453544d2a7SEd Tanous             if (std::ranges::find(supportedEvtFormatTypes, *eventFormatType2) ==
4463544d2a7SEd Tanous                 supportedEvtFormatTypes.end())
447e5aaf047SAppaRao Puli             {
448fffb8c1fSEd Tanous                 messages::propertyValueNotInList(
449fffb8c1fSEd Tanous                     asyncResp->res, *eventFormatType2, "EventFormatType");
450e5aaf047SAppaRao Puli                 return;
451e5aaf047SAppaRao Puli             }
45223a21a1cSEd Tanous             subValue->eventFormatType = *eventFormatType2;
453e5aaf047SAppaRao Puli         }
454e5aaf047SAppaRao Puli         else
455e5aaf047SAppaRao Puli         {
456e5aaf047SAppaRao Puli             // If not specified, use default "Event"
45723a21a1cSEd Tanous             subValue->eventFormatType = "Event";
458e5aaf047SAppaRao Puli         }
459e5aaf047SAppaRao Puli 
460e5aaf047SAppaRao Puli         if (context)
461e5aaf047SAppaRao Puli         {
4628ece0e45SEd Tanous             // This value is selected arbitrarily.
463600af5f1SAppaRao Puli             constexpr const size_t maxContextSize = 256;
464600af5f1SAppaRao Puli             if (context->size() > maxContextSize)
465600af5f1SAppaRao Puli             {
466600af5f1SAppaRao Puli                 messages::stringValueTooLong(asyncResp->res, "Context",
467600af5f1SAppaRao Puli                                              maxContextSize);
468600af5f1SAppaRao Puli                 return;
469600af5f1SAppaRao Puli             }
470b52664e2SAppaRao Puli             subValue->customText = *context;
471e5aaf047SAppaRao Puli         }
472e5aaf047SAppaRao Puli 
473e5aaf047SAppaRao Puli         if (headers)
474e5aaf047SAppaRao Puli         {
475600af5f1SAppaRao Puli             size_t cumulativeLen = 0;
476600af5f1SAppaRao Puli 
47778d4ec4fSEd Tanous             for (const nlohmann::json::object_t& headerChunk : *headers)
478601c71aeSEd Tanous             {
47978d4ec4fSEd Tanous                 for (const auto& item : headerChunk)
48078d4ec4fSEd Tanous                 {
48178d4ec4fSEd Tanous                     const std::string* value =
48278d4ec4fSEd Tanous                         item.second.get_ptr<const std::string*>();
48378d4ec4fSEd Tanous                     if (value == nullptr)
48478d4ec4fSEd Tanous                     {
48578d4ec4fSEd Tanous                         messages::propertyValueFormatError(
48678d4ec4fSEd Tanous                             asyncResp->res, item.second,
48778d4ec4fSEd Tanous                             "HttpHeaders/" + item.first);
48878d4ec4fSEd Tanous                         return;
48978d4ec4fSEd Tanous                     }
49078d4ec4fSEd Tanous                     // Adding a new json value is the size of the key, +
49178d4ec4fSEd Tanous                     // the size of the value + 2 * 2 quotes for each, +
49278d4ec4fSEd Tanous                     // the colon and space between. example:
49378d4ec4fSEd Tanous                     // "key": "value"
49478d4ec4fSEd Tanous                     cumulativeLen += item.first.size() + value->size() + 6;
495600af5f1SAppaRao Puli                     // This value is selected to mirror http_connection.hpp
496600af5f1SAppaRao Puli                     constexpr const uint16_t maxHeaderSizeED = 8096;
497600af5f1SAppaRao Puli                     if (cumulativeLen > maxHeaderSizeED)
498600af5f1SAppaRao Puli                     {
49978d4ec4fSEd Tanous                         messages::arraySizeTooLong(
50078d4ec4fSEd Tanous                             asyncResp->res, "HttpHeaders", maxHeaderSizeED);
501600af5f1SAppaRao Puli                         return;
502600af5f1SAppaRao Puli                     }
50378d4ec4fSEd Tanous                     subValue->httpHeaders.set(item.first, *value);
504601c71aeSEd Tanous                 }
505601c71aeSEd Tanous             }
506e5aaf047SAppaRao Puli         }
507e5aaf047SAppaRao Puli 
508e5aaf047SAppaRao Puli         if (regPrefixes)
509e5aaf047SAppaRao Puli         {
510e5aaf047SAppaRao Puli             for (const std::string& it : *regPrefixes)
511e5aaf047SAppaRao Puli             {
5123544d2a7SEd Tanous                 if (std::ranges::find(supportedRegPrefixes, it) ==
5133544d2a7SEd Tanous                     supportedRegPrefixes.end())
514e5aaf047SAppaRao Puli                 {
515fffb8c1fSEd Tanous                     messages::propertyValueNotInList(asyncResp->res, it,
516fffb8c1fSEd Tanous                                                      "RegistryPrefixes");
517e5aaf047SAppaRao Puli                     return;
518e5aaf047SAppaRao Puli                 }
519e5aaf047SAppaRao Puli             }
520b52664e2SAppaRao Puli             subValue->registryPrefixes = *regPrefixes;
521e5aaf047SAppaRao Puli         }
522e5aaf047SAppaRao Puli 
523e56f254cSSunitha Harish         if (resTypes)
524e56f254cSSunitha Harish         {
525e56f254cSSunitha Harish             for (const std::string& it : *resTypes)
526e56f254cSSunitha Harish             {
5273544d2a7SEd Tanous                 if (std::ranges::find(supportedResourceTypes, it) ==
5283544d2a7SEd Tanous                     supportedResourceTypes.end())
529e56f254cSSunitha Harish                 {
530e56f254cSSunitha Harish                     messages::propertyValueNotInList(asyncResp->res, it,
531e56f254cSSunitha Harish                                                      "ResourceTypes");
532e56f254cSSunitha Harish                     return;
533e56f254cSSunitha Harish                 }
534e56f254cSSunitha Harish             }
535e56f254cSSunitha Harish             subValue->resourceTypes = *resTypes;
536e56f254cSSunitha Harish         }
537e56f254cSSunitha Harish 
538e5aaf047SAppaRao Puli         if (msgIds)
539e5aaf047SAppaRao Puli         {
540b304bd79SP Dheeraj Srujan Kumar             std::vector<std::string> registryPrefix;
541b304bd79SP Dheeraj Srujan Kumar 
5427e860f15SJohn Edward Broadbent             // If no registry prefixes are mentioned, consider all
5437e860f15SJohn Edward Broadbent             // supported prefixes
544b304bd79SP Dheeraj Srujan Kumar             if (subValue->registryPrefixes.empty())
545b304bd79SP Dheeraj Srujan Kumar             {
546b304bd79SP Dheeraj Srujan Kumar                 registryPrefix.assign(supportedRegPrefixes.begin(),
547b304bd79SP Dheeraj Srujan Kumar                                       supportedRegPrefixes.end());
548b304bd79SP Dheeraj Srujan Kumar             }
549b304bd79SP Dheeraj Srujan Kumar             else
550b304bd79SP Dheeraj Srujan Kumar             {
551b304bd79SP Dheeraj Srujan Kumar                 registryPrefix = subValue->registryPrefixes;
552b304bd79SP Dheeraj Srujan Kumar             }
553b304bd79SP Dheeraj Srujan Kumar 
554b304bd79SP Dheeraj Srujan Kumar             for (const std::string& id : *msgIds)
555b304bd79SP Dheeraj Srujan Kumar             {
556b304bd79SP Dheeraj Srujan Kumar                 bool validId = false;
557b304bd79SP Dheeraj Srujan Kumar 
558b304bd79SP Dheeraj Srujan Kumar                 // Check for Message ID in each of the selected Registry
559b304bd79SP Dheeraj Srujan Kumar                 for (const std::string& it : registryPrefix)
560b304bd79SP Dheeraj Srujan Kumar                 {
561fffb8c1fSEd Tanous                     const std::span<const redfish::registries::MessageEntry>
562fffb8c1fSEd Tanous                         registry =
563fffb8c1fSEd Tanous                             redfish::registries::getRegistryFromPrefix(it);
564b304bd79SP Dheeraj Srujan Kumar 
5653544d2a7SEd Tanous                     if (std::ranges::any_of(
5663544d2a7SEd Tanous                             registry,
567fffb8c1fSEd Tanous                             [&id](const redfish::registries::MessageEntry&
568fffb8c1fSEd Tanous                                       messageEntry) {
56955f79e6fSEd Tanous                         return id == messageEntry.first;
570b304bd79SP Dheeraj Srujan Kumar                     }))
571b304bd79SP Dheeraj Srujan Kumar                     {
572b304bd79SP Dheeraj Srujan Kumar                         validId = true;
573b304bd79SP Dheeraj Srujan Kumar                         break;
574b304bd79SP Dheeraj Srujan Kumar                     }
575b304bd79SP Dheeraj Srujan Kumar                 }
576b304bd79SP Dheeraj Srujan Kumar 
577b304bd79SP Dheeraj Srujan Kumar                 if (!validId)
578b304bd79SP Dheeraj Srujan Kumar                 {
579b304bd79SP Dheeraj Srujan Kumar                     messages::propertyValueNotInList(asyncResp->res, id,
580b304bd79SP Dheeraj Srujan Kumar                                                      "MessageIds");
581b304bd79SP Dheeraj Srujan Kumar                     return;
582b304bd79SP Dheeraj Srujan Kumar                 }
583b304bd79SP Dheeraj Srujan Kumar             }
584b304bd79SP Dheeraj Srujan Kumar 
585b52664e2SAppaRao Puli             subValue->registryMsgIds = *msgIds;
586e5aaf047SAppaRao Puli         }
587e5aaf047SAppaRao Puli 
588e5aaf047SAppaRao Puli         if (retryPolicy)
589e5aaf047SAppaRao Puli         {
5903544d2a7SEd Tanous             if (std::ranges::find(supportedRetryPolicies, *retryPolicy) ==
5913544d2a7SEd Tanous                 supportedRetryPolicies.end())
592e5aaf047SAppaRao Puli             {
593002d39b4SEd Tanous                 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
594002d39b4SEd Tanous                                                  "DeliveryRetryPolicy");
595e5aaf047SAppaRao Puli                 return;
596e5aaf047SAppaRao Puli             }
597b52664e2SAppaRao Puli             subValue->retryPolicy = *retryPolicy;
598e5aaf047SAppaRao Puli         }
599e5aaf047SAppaRao Puli         else
600e5aaf047SAppaRao Puli         {
601e5aaf047SAppaRao Puli             // Default "TerminateAfterRetries"
602b52664e2SAppaRao Puli             subValue->retryPolicy = "TerminateAfterRetries";
603e5aaf047SAppaRao Puli         }
604e5aaf047SAppaRao Puli 
605144b6318SAppaRao Puli         if (mrdJsonArray)
606156d6b00SAppaRao Puli         {
60778d4ec4fSEd Tanous             for (nlohmann::json::object_t& mrdObj : *mrdJsonArray)
608144b6318SAppaRao Puli             {
609144b6318SAppaRao Puli                 std::string mrdUri;
610ea2e6eecSWilly Tu 
61178d4ec4fSEd Tanous                 if (!json_util::readJsonObject(mrdObj, asyncResp->res,
61278d4ec4fSEd Tanous                                                "@odata.id", mrdUri))
613ea2e6eecSWilly Tu 
614144b6318SAppaRao Puli                 {
615144b6318SAppaRao Puli                     return;
616144b6318SAppaRao Puli                 }
617ea2e6eecSWilly Tu                 subValue->metricReportDefinitions.emplace_back(mrdUri);
618144b6318SAppaRao Puli             }
619156d6b00SAppaRao Puli         }
620156d6b00SAppaRao Puli 
621b52664e2SAppaRao Puli         std::string id =
622fffb8c1fSEd Tanous             EventServiceManager::getInstance().addSubscription(subValue);
623b52664e2SAppaRao Puli         if (id.empty())
624e5aaf047SAppaRao Puli         {
625e5aaf047SAppaRao Puli             messages::internalError(asyncResp->res);
626e5aaf047SAppaRao Puli             return;
627e5aaf047SAppaRao Puli         }
628e5aaf047SAppaRao Puli 
629e5aaf047SAppaRao Puli         messages::created(asyncResp->res);
630e5aaf047SAppaRao Puli         asyncResp->res.addHeader(
631e5aaf047SAppaRao Puli             "Location", "/redfish/v1/EventService/Subscriptions/" + id);
6327e860f15SJohn Edward Broadbent     });
633e5aaf047SAppaRao Puli }
634e5aaf047SAppaRao Puli 
6357e860f15SJohn Edward Broadbent inline void requestRoutesEventDestination(App& app)
636e5aaf047SAppaRao Puli {
6379d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
638ed398213SEd Tanous         .privileges(redfish::privileges::getEventDestination)
6397e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
64045ca1b86SEd Tanous             [&app](const crow::Request& req,
6417e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
6427e860f15SJohn Edward Broadbent                    const std::string& param) {
6433ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
64445ca1b86SEd Tanous         {
64545ca1b86SEd Tanous             return;
64645ca1b86SEd Tanous         }
6473d30708fSChicago Duan 
6483d30708fSChicago Duan         if (param.starts_with("snmp"))
6493d30708fSChicago Duan         {
6503d30708fSChicago Duan             getSnmpTrapClient(asyncResp, param);
6513d30708fSChicago Duan             return;
6523d30708fSChicago Duan         }
6533d30708fSChicago Duan 
654b52664e2SAppaRao Puli         std::shared_ptr<Subscription> subValue =
6557e860f15SJohn Edward Broadbent             EventServiceManager::getInstance().getSubscription(param);
656b52664e2SAppaRao Puli         if (subValue == nullptr)
657e5aaf047SAppaRao Puli         {
658002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::not_found);
659e5aaf047SAppaRao Puli             return;
660e5aaf047SAppaRao Puli         }
6617e860f15SJohn Edward Broadbent         const std::string& id = param;
662e5aaf047SAppaRao Puli 
6631476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
6643d30708fSChicago Duan             "#EventDestination.v1_8_0.EventDestination";
6651476687dSEd Tanous         asyncResp->res.jsonValue["Protocol"] = "Redfish";
6663b32780dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
6673b32780dSEd Tanous             "/redfish/v1/EventService/Subscriptions/{}", id);
668e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["Id"] = id;
669e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
670002d39b4SEd Tanous         asyncResp->res.jsonValue["Destination"] = subValue->destinationUrl;
671b52664e2SAppaRao Puli         asyncResp->res.jsonValue["Context"] = subValue->customText;
672e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["SubscriptionType"] =
673b52664e2SAppaRao Puli             subValue->subscriptionType;
674002d39b4SEd Tanous         asyncResp->res.jsonValue["HttpHeaders"] = nlohmann::json::array();
675002d39b4SEd Tanous         asyncResp->res.jsonValue["EventFormatType"] = subValue->eventFormatType;
676e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["RegistryPrefixes"] =
677b52664e2SAppaRao Puli             subValue->registryPrefixes;
678002d39b4SEd Tanous         asyncResp->res.jsonValue["ResourceTypes"] = subValue->resourceTypes;
679e56f254cSSunitha Harish 
680002d39b4SEd Tanous         asyncResp->res.jsonValue["MessageIds"] = subValue->registryMsgIds;
681002d39b4SEd Tanous         asyncResp->res.jsonValue["DeliveryRetryPolicy"] = subValue->retryPolicy;
682*19bb362bSEd Tanous         asyncResp->res.jsonValue["VerifyCertificate"] =
683*19bb362bSEd Tanous             subValue->verifyCertificate;
684144b6318SAppaRao Puli 
6851476687dSEd Tanous         nlohmann::json::array_t mrdJsonArray;
686144b6318SAppaRao Puli         for (const auto& mdrUri : subValue->metricReportDefinitions)
687144b6318SAppaRao Puli         {
6881476687dSEd Tanous             nlohmann::json::object_t mdr;
6891476687dSEd Tanous             mdr["@odata.id"] = mdrUri;
6901476687dSEd Tanous             mrdJsonArray.emplace_back(std::move(mdr));
691144b6318SAppaRao Puli         }
692002d39b4SEd Tanous         asyncResp->res.jsonValue["MetricReportDefinitions"] = mrdJsonArray;
6937e860f15SJohn Edward Broadbent     });
6949d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
695ed398213SEd Tanous         // The below privilege is wrong, it should be ConfigureManager OR
696ed398213SEd Tanous         // ConfigureSelf
6977eeafa76SAbhishek Patel         // https://github.com/openbmc/bmcweb/issues/220
698ed398213SEd Tanous         //.privileges(redfish::privileges::patchEventDestination)
699432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
7007e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
70145ca1b86SEd Tanous             [&app](const crow::Request& req,
7027e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7037e860f15SJohn Edward Broadbent                    const std::string& param) {
7043ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
70545ca1b86SEd Tanous         {
70645ca1b86SEd Tanous             return;
70745ca1b86SEd Tanous         }
708b52664e2SAppaRao Puli         std::shared_ptr<Subscription> subValue =
7097e860f15SJohn Edward Broadbent             EventServiceManager::getInstance().getSubscription(param);
710b52664e2SAppaRao Puli         if (subValue == nullptr)
711e5aaf047SAppaRao Puli         {
712002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::not_found);
713e5aaf047SAppaRao Puli             return;
714e5aaf047SAppaRao Puli         }
715e5aaf047SAppaRao Puli 
716e5aaf047SAppaRao Puli         std::optional<std::string> context;
717e5aaf047SAppaRao Puli         std::optional<std::string> retryPolicy;
718*19bb362bSEd Tanous         std::optional<bool> verifyCertificate;
71978d4ec4fSEd Tanous         std::optional<std::vector<nlohmann::json::object_t>> headers;
720e5aaf047SAppaRao Puli 
721002d39b4SEd Tanous         if (!json_util::readJsonPatch(req, asyncResp->res, "Context", context,
722*19bb362bSEd Tanous                                       "VerifyCertificate", verifyCertificate,
723002d39b4SEd Tanous                                       "DeliveryRetryPolicy", retryPolicy,
724002d39b4SEd Tanous                                       "HttpHeaders", headers))
725e5aaf047SAppaRao Puli         {
726e5aaf047SAppaRao Puli             return;
727e5aaf047SAppaRao Puli         }
728e5aaf047SAppaRao Puli 
729e5aaf047SAppaRao Puli         if (context)
730e5aaf047SAppaRao Puli         {
731b52664e2SAppaRao Puli             subValue->customText = *context;
732e5aaf047SAppaRao Puli         }
733e5aaf047SAppaRao Puli 
734e5aaf047SAppaRao Puli         if (headers)
735e5aaf047SAppaRao Puli         {
736601c71aeSEd Tanous             boost::beast::http::fields fields;
73778d4ec4fSEd Tanous             for (const nlohmann::json::object_t& headerChunk : *headers)
738601c71aeSEd Tanous             {
73978d4ec4fSEd Tanous                 for (const auto& it : headerChunk)
740601c71aeSEd Tanous                 {
741601c71aeSEd Tanous                     const std::string* value =
74278d4ec4fSEd Tanous                         it.second.get_ptr<const std::string*>();
743601c71aeSEd Tanous                     if (value == nullptr)
744601c71aeSEd Tanous                     {
745601c71aeSEd Tanous                         messages::propertyValueFormatError(
74678d4ec4fSEd Tanous                             asyncResp->res, it.second,
74778d4ec4fSEd Tanous                             "HttpHeaders/" + it.first);
748601c71aeSEd Tanous                         return;
749601c71aeSEd Tanous                     }
75078d4ec4fSEd Tanous                     fields.set(it.first, *value);
751601c71aeSEd Tanous                 }
752601c71aeSEd Tanous             }
75378d4ec4fSEd Tanous             subValue->httpHeaders = std::move(fields);
754e5aaf047SAppaRao Puli         }
755e5aaf047SAppaRao Puli 
756e5aaf047SAppaRao Puli         if (retryPolicy)
757e5aaf047SAppaRao Puli         {
7583544d2a7SEd Tanous             if (std::ranges::find(supportedRetryPolicies, *retryPolicy) ==
7593544d2a7SEd Tanous                 supportedRetryPolicies.end())
760e5aaf047SAppaRao Puli             {
761002d39b4SEd Tanous                 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
762e5aaf047SAppaRao Puli                                                  "DeliveryRetryPolicy");
763e5aaf047SAppaRao Puli                 return;
764e5aaf047SAppaRao Puli             }
765b52664e2SAppaRao Puli             subValue->retryPolicy = *retryPolicy;
766e5aaf047SAppaRao Puli         }
767e5aaf047SAppaRao Puli 
768*19bb362bSEd Tanous         if (verifyCertificate)
769*19bb362bSEd Tanous         {
770*19bb362bSEd Tanous             subValue->verifyCertificate = *verifyCertificate;
771*19bb362bSEd Tanous         }
772*19bb362bSEd Tanous 
773b52664e2SAppaRao Puli         EventServiceManager::getInstance().updateSubscriptionData();
7747e860f15SJohn Edward Broadbent     });
7759d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
776ed398213SEd Tanous         // The below privilege is wrong, it should be ConfigureManager OR
777ed398213SEd Tanous         // ConfigureSelf
7787eeafa76SAbhishek Patel         // https://github.com/openbmc/bmcweb/issues/220
779ed398213SEd Tanous         //.privileges(redfish::privileges::deleteEventDestination)
780432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
7817e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
78245ca1b86SEd Tanous             [&app](const crow::Request& req,
7837e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7847e860f15SJohn Edward Broadbent                    const std::string& param) {
7853ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
78645ca1b86SEd Tanous         {
78745ca1b86SEd Tanous             return;
78845ca1b86SEd Tanous         }
7893d30708fSChicago Duan 
7903d30708fSChicago Duan         if (param.starts_with("snmp"))
7913d30708fSChicago Duan         {
7923d30708fSChicago Duan             deleteSnmpTrapClient(asyncResp, param);
7933d30708fSChicago Duan             EventServiceManager::getInstance().deleteSubscription(param);
7943d30708fSChicago Duan             return;
7953d30708fSChicago Duan         }
7963d30708fSChicago Duan 
797002d39b4SEd Tanous         if (!EventServiceManager::getInstance().isSubscriptionExist(param))
798e5aaf047SAppaRao Puli         {
799002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::not_found);
800e5aaf047SAppaRao Puli             return;
801e5aaf047SAppaRao Puli         }
8027e860f15SJohn Edward Broadbent         EventServiceManager::getInstance().deleteSubscription(param);
8037e860f15SJohn Edward Broadbent     });
804e5aaf047SAppaRao Puli }
805e5aaf047SAppaRao Puli 
806e5aaf047SAppaRao Puli } // namespace redfish
807