xref: /openbmc/bmcweb/features/redfish/lib/event_service.hpp (revision f80a87f2c458a4d8092aae91249aec1adcec6cd5)
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;
28119bb362bSEd 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",
29819bb362bSEd Tanous                 mrdJsonArray, "ResourceTypes", resTypes, "VerifyCertificate",
29919bb362bSEd 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 
43819bb362bSEd Tanous         if (verifyCertificate)
43919bb362bSEd Tanous         {
44019bb362bSEd Tanous             subValue->verifyCertificate = *verifyCertificate;
44119bb362bSEd Tanous         }
44219bb362bSEd 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 =
622*f80a87f2SEd Tanous             EventServiceManager::getInstance().addPushSubscription(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;
68219bb362bSEd Tanous         asyncResp->res.jsonValue["VerifyCertificate"] =
68319bb362bSEd 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;
71819bb362bSEd 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,
72219bb362bSEd 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 
76819bb362bSEd Tanous         if (verifyCertificate)
76919bb362bSEd Tanous         {
77019bb362bSEd Tanous             subValue->verifyCertificate = *verifyCertificate;
77119bb362bSEd Tanous         }
77219bb362bSEd 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