xref: /openbmc/bmcweb/features/redfish/lib/event_service.hpp (revision 539d8c6bc399e516d39bcaa18262cf206f4c1035)
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"
19*539d8c6bSEd Tanous #include "generated/enums/event_service.hpp"
203ccb3adbSEd Tanous #include "http/utility.hpp"
213ccb3adbSEd Tanous #include "logging.hpp"
223ccb3adbSEd Tanous #include "query.hpp"
233ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
243d30708fSChicago Duan #include "snmp_trap_event_clients.hpp"
25e5aaf047SAppaRao Puli 
26601c71aeSEd Tanous #include <boost/beast/http/fields.hpp>
273d30708fSChicago Duan #include <boost/system/error_code.hpp>
28a716aa74SEd Tanous #include <boost/url/parse.hpp>
293d30708fSChicago Duan #include <sdbusplus/unpack_properties.hpp>
303d30708fSChicago Duan #include <utils/dbus_utils.hpp>
31ed398213SEd Tanous 
323d30708fSChicago Duan #include <charconv>
333d30708fSChicago Duan #include <memory>
343544d2a7SEd Tanous #include <ranges>
351e270c5fSPatrick Williams #include <span>
363d30708fSChicago Duan #include <string>
371e270c5fSPatrick Williams 
38e5aaf047SAppaRao Puli namespace redfish
39e5aaf047SAppaRao Puli {
40e5aaf047SAppaRao Puli 
41156d6b00SAppaRao Puli static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
42156d6b00SAppaRao Puli     eventFormatType, metricReportFormatType};
43e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
44b304bd79SP Dheeraj Srujan Kumar     "Base", "OpenBMC", "TaskEvent"};
45e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
46e5aaf047SAppaRao Puli     "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
47e5aaf047SAppaRao Puli 
48e56f254cSSunitha Harish static constexpr const std::array<const char*, 1> supportedResourceTypes = {
49e56f254cSSunitha Harish     "Task"};
50e56f254cSSunitha Harish 
517e860f15SJohn Edward Broadbent inline void requestRoutesEventService(App& app)
52e5aaf047SAppaRao Puli {
537e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
54ed398213SEd Tanous         .privileges(redfish::privileges::getEventService)
55002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
56002d39b4SEd Tanous             [&app](const crow::Request& req,
57002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
583ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
5945ca1b86SEd Tanous         {
6045ca1b86SEd Tanous             return;
6145ca1b86SEd Tanous         }
621476687dSEd Tanous 
631476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/EventService";
641476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
651476687dSEd Tanous             "#EventService.v1_5_0.EventService";
661476687dSEd Tanous         asyncResp->res.jsonValue["Id"] = "EventService";
671476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "Event Service";
685e44e3d8SAppaRao Puli         asyncResp->res.jsonValue["ServerSentEventUri"] =
695e44e3d8SAppaRao Puli             "/redfish/v1/EventService/SSE";
705e44e3d8SAppaRao Puli 
711476687dSEd Tanous         asyncResp->res.jsonValue["Subscriptions"]["@odata.id"] =
721476687dSEd Tanous             "/redfish/v1/EventService/Subscriptions";
73002d39b4SEd Tanous         asyncResp->res
74002d39b4SEd Tanous             .jsonValue["Actions"]["#EventService.SubmitTestEvent"]["target"] =
751476687dSEd Tanous             "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent";
76e5aaf047SAppaRao Puli 
7728afb49cSJunLin Chen         const persistent_data::EventServiceConfig eventServiceConfig =
7828afb49cSJunLin Chen             persistent_data::EventServiceStore::getInstance()
7928afb49cSJunLin Chen                 .getEventServiceConfig();
807d1cc387SAppaRao Puli 
817d1cc387SAppaRao Puli         asyncResp->res.jsonValue["Status"]["State"] =
8228afb49cSJunLin Chen             (eventServiceConfig.enabled ? "Enabled" : "Disabled");
83002d39b4SEd Tanous         asyncResp->res.jsonValue["ServiceEnabled"] = eventServiceConfig.enabled;
847e860f15SJohn Edward Broadbent         asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
8528afb49cSJunLin Chen             eventServiceConfig.retryAttempts;
86e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
8728afb49cSJunLin Chen             eventServiceConfig.retryTimeoutInterval;
88002d39b4SEd Tanous         asyncResp->res.jsonValue["EventFormatTypes"] = supportedEvtFormatTypes;
890fda0f12SGeorge Liu         asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
900fda0f12SGeorge Liu         asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
9107941a88SAyushi Smriti 
92613dabeaSEd Tanous         nlohmann::json::object_t supportedSSEFilters;
93613dabeaSEd Tanous         supportedSSEFilters["EventFormatType"] = true;
94613dabeaSEd Tanous         supportedSSEFilters["MessageId"] = true;
95613dabeaSEd Tanous         supportedSSEFilters["MetricReportDefinition"] = true;
96613dabeaSEd Tanous         supportedSSEFilters["RegistryPrefix"] = true;
97613dabeaSEd Tanous         supportedSSEFilters["OriginResource"] = false;
98613dabeaSEd Tanous         supportedSSEFilters["ResourceType"] = false;
9907941a88SAyushi Smriti 
10007941a88SAyushi Smriti         asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
101613dabeaSEd Tanous             std::move(supportedSSEFilters);
1027e860f15SJohn Edward Broadbent     });
103e5aaf047SAppaRao Puli 
1047e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
105ed398213SEd Tanous         .privileges(redfish::privileges::patchEventService)
1067e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
10745ca1b86SEd Tanous             [&app](const crow::Request& req,
10845ca1b86SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1093ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
110e5aaf047SAppaRao Puli         {
11145ca1b86SEd Tanous             return;
11245ca1b86SEd Tanous         }
113e5aaf047SAppaRao Puli         std::optional<bool> serviceEnabled;
114e5aaf047SAppaRao Puli         std::optional<uint32_t> retryAttemps;
115e5aaf047SAppaRao Puli         std::optional<uint32_t> retryInterval;
116e5aaf047SAppaRao Puli 
11715ed6780SWilly Tu         if (!json_util::readJsonPatch(
1187e860f15SJohn Edward Broadbent                 req, asyncResp->res, "ServiceEnabled", serviceEnabled,
1197e860f15SJohn Edward Broadbent                 "DeliveryRetryAttempts", retryAttemps,
1207e860f15SJohn Edward Broadbent                 "DeliveryRetryIntervalSeconds", retryInterval))
121e5aaf047SAppaRao Puli         {
122e5aaf047SAppaRao Puli             return;
123e5aaf047SAppaRao Puli         }
124e5aaf047SAppaRao Puli 
12528afb49cSJunLin Chen         persistent_data::EventServiceConfig eventServiceConfig =
12628afb49cSJunLin Chen             persistent_data::EventServiceStore::getInstance()
12728afb49cSJunLin Chen                 .getEventServiceConfig();
1287d1cc387SAppaRao Puli 
129e5aaf047SAppaRao Puli         if (serviceEnabled)
130e5aaf047SAppaRao Puli         {
13128afb49cSJunLin Chen             eventServiceConfig.enabled = *serviceEnabled;
132e5aaf047SAppaRao Puli         }
133e5aaf047SAppaRao Puli 
134e5aaf047SAppaRao Puli         if (retryAttemps)
135e5aaf047SAppaRao Puli         {
136e5aaf047SAppaRao Puli             // Supported range [1-3]
137e5aaf047SAppaRao Puli             if ((*retryAttemps < 1) || (*retryAttemps > 3))
138e5aaf047SAppaRao Puli             {
139e5aaf047SAppaRao Puli                 messages::queryParameterOutOfRange(
140e5aaf047SAppaRao Puli                     asyncResp->res, std::to_string(*retryAttemps),
141e5aaf047SAppaRao Puli                     "DeliveryRetryAttempts", "[1-3]");
142e5aaf047SAppaRao Puli             }
143e5aaf047SAppaRao Puli             else
144e5aaf047SAppaRao Puli             {
14528afb49cSJunLin Chen                 eventServiceConfig.retryAttempts = *retryAttemps;
146e5aaf047SAppaRao Puli             }
147e5aaf047SAppaRao Puli         }
148e5aaf047SAppaRao Puli 
149e5aaf047SAppaRao Puli         if (retryInterval)
150e5aaf047SAppaRao Puli         {
15133a32b34SGunnar Mills             // Supported range [5 - 180]
15233a32b34SGunnar Mills             if ((*retryInterval < 5) || (*retryInterval > 180))
153e5aaf047SAppaRao Puli             {
154e5aaf047SAppaRao Puli                 messages::queryParameterOutOfRange(
155e5aaf047SAppaRao Puli                     asyncResp->res, std::to_string(*retryInterval),
15633a32b34SGunnar Mills                     "DeliveryRetryIntervalSeconds", "[5-180]");
157e5aaf047SAppaRao Puli             }
158e5aaf047SAppaRao Puli             else
159e5aaf047SAppaRao Puli             {
160002d39b4SEd Tanous                 eventServiceConfig.retryTimeoutInterval = *retryInterval;
161e5aaf047SAppaRao Puli             }
162e5aaf047SAppaRao Puli         }
163e5aaf047SAppaRao Puli 
1647d1cc387SAppaRao Puli         EventServiceManager::getInstance().setEventServiceConfig(
16528afb49cSJunLin Chen             eventServiceConfig);
1667e860f15SJohn Edward Broadbent     });
1670b4bdd93SAppaRao Puli }
1680b4bdd93SAppaRao Puli 
1697e860f15SJohn Edward Broadbent inline void requestRoutesSubmitTestEvent(App& app)
1700b4bdd93SAppaRao Puli {
1717e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
1727e860f15SJohn Edward Broadbent         app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
173ed398213SEd Tanous         .privileges(redfish::privileges::postEventService)
1747e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
17545ca1b86SEd Tanous             [&app](const crow::Request& req,
1767e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1773ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
17845ca1b86SEd Tanous         {
17945ca1b86SEd Tanous             return;
18045ca1b86SEd Tanous         }
1816ba8c82eSsunharis_in         if (!EventServiceManager::getInstance().sendTestEventLog())
1826ba8c82eSsunharis_in         {
1836ba8c82eSsunharis_in             messages::serviceDisabled(asyncResp->res,
1846ba8c82eSsunharis_in                                       "/redfish/v1/EventService/");
1856ba8c82eSsunharis_in             return;
1866ba8c82eSsunharis_in         }
1878d1b46d7Szhanghch05         asyncResp->res.result(boost::beast::http::status::no_content);
1887e860f15SJohn Edward Broadbent     });
189e5aaf047SAppaRao Puli }
190e5aaf047SAppaRao Puli 
1913d30708fSChicago Duan inline void doSubscriptionCollection(
192e81de512SEd Tanous     const boost::system::error_code& ec,
1933d30708fSChicago Duan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1943d30708fSChicago Duan     const dbus::utility::ManagedObjectType& resp)
1953d30708fSChicago Duan {
1963d30708fSChicago Duan     if (ec)
1973d30708fSChicago Duan     {
1981306101eSEd Tanous         if (ec.value() == EBADR || ec.value() == EHOSTUNREACH)
1993d30708fSChicago Duan         {
2003d30708fSChicago Duan             // This is an optional process so just return if it isn't there
2013d30708fSChicago Duan             return;
2023d30708fSChicago Duan         }
2033d30708fSChicago Duan 
20462598e31SEd Tanous         BMCWEB_LOG_ERROR("D-Bus response error on GetManagedObjects {}", ec);
2053d30708fSChicago Duan         messages::internalError(asyncResp->res);
2063d30708fSChicago Duan         return;
2073d30708fSChicago Duan     }
2083d30708fSChicago Duan     nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
2093d30708fSChicago Duan     for (const auto& objpath : resp)
2103d30708fSChicago Duan     {
2113d30708fSChicago Duan         sdbusplus::message::object_path path(objpath.first);
2123d30708fSChicago Duan         const std::string snmpId = path.filename();
2133d30708fSChicago Duan         if (snmpId.empty())
2143d30708fSChicago Duan         {
21562598e31SEd Tanous             BMCWEB_LOG_ERROR("The SNMP client ID is wrong");
2163d30708fSChicago Duan             messages::internalError(asyncResp->res);
2173d30708fSChicago Duan             return;
2183d30708fSChicago Duan         }
2193d30708fSChicago Duan 
2203d30708fSChicago Duan         getSnmpSubscriptionList(asyncResp, snmpId, memberArray);
2213d30708fSChicago Duan     }
2223d30708fSChicago Duan }
2233d30708fSChicago Duan 
2247e860f15SJohn Edward Broadbent inline void requestRoutesEventDestinationCollection(App& app)
225e5aaf047SAppaRao Puli {
2261ebe3e41SGayathri Leburu     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
227ed398213SEd Tanous         .privileges(redfish::privileges::getEventDestinationCollection)
2287e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
22945ca1b86SEd Tanous             [&app](const crow::Request& req,
2307e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2313ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
23245ca1b86SEd Tanous         {
23345ca1b86SEd Tanous             return;
23445ca1b86SEd Tanous         }
2351476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
2361476687dSEd Tanous             "#EventDestinationCollection.EventDestinationCollection";
2371476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
2381476687dSEd Tanous             "/redfish/v1/EventService/Subscriptions";
239002d39b4SEd Tanous         asyncResp->res.jsonValue["Name"] = "Event Destination Collections";
240e5aaf047SAppaRao Puli 
241002d39b4SEd Tanous         nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
242e5aaf047SAppaRao Puli 
243b52664e2SAppaRao Puli         std::vector<std::string> subscripIds =
244b52664e2SAppaRao Puli             EventServiceManager::getInstance().getAllIDs();
245b52664e2SAppaRao Puli         memberArray = nlohmann::json::array();
246002d39b4SEd Tanous         asyncResp->res.jsonValue["Members@odata.count"] = subscripIds.size();
247b52664e2SAppaRao Puli 
248b52664e2SAppaRao Puli         for (const std::string& id : subscripIds)
249e5aaf047SAppaRao Puli         {
2501476687dSEd Tanous             nlohmann::json::object_t member;
2513d30708fSChicago Duan             member["@odata.id"] = boost::urls::format(
2523d30708fSChicago Duan                 "/redfish/v1/EventService/Subscriptions/{}" + id);
253b2ba3072SPatrick Williams             memberArray.emplace_back(std::move(member));
254e5aaf047SAppaRao Puli         }
2553d30708fSChicago Duan         crow::connections::systemBus->async_method_call(
256e81de512SEd Tanous             [asyncResp](const boost::system::error_code& ec,
2573d30708fSChicago Duan                         const dbus::utility::ManagedObjectType& resp) {
2583d30708fSChicago Duan             doSubscriptionCollection(ec, asyncResp, resp);
2593d30708fSChicago Duan         },
2603d30708fSChicago Duan             "xyz.openbmc_project.Network.SNMP",
2613d30708fSChicago Duan             "/xyz/openbmc_project/network/snmp/manager",
2623d30708fSChicago Duan             "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
2637e860f15SJohn Edward Broadbent     });
2643d30708fSChicago Duan 
2657e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
2667eeafa76SAbhishek Patel         .privileges(redfish::privileges::postEventDestinationCollection)
267002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
268002d39b4SEd Tanous             [&app](const crow::Request& req,
2697e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2703ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
27145ca1b86SEd Tanous         {
27245ca1b86SEd Tanous             return;
27345ca1b86SEd Tanous         }
274fffb8c1fSEd Tanous         if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
275fffb8c1fSEd Tanous             maxNoOfSubscriptions)
276e5aaf047SAppaRao Puli         {
277e5aaf047SAppaRao Puli             messages::eventSubscriptionLimitExceeded(asyncResp->res);
278e5aaf047SAppaRao Puli             return;
279e5aaf047SAppaRao Puli         }
280e5aaf047SAppaRao Puli         std::string destUrl;
281e5aaf047SAppaRao Puli         std::string protocol;
28219bb362bSEd Tanous         std::optional<bool> verifyCertificate;
283e5aaf047SAppaRao Puli         std::optional<std::string> context;
284e5aaf047SAppaRao Puli         std::optional<std::string> subscriptionType;
28523a21a1cSEd Tanous         std::optional<std::string> eventFormatType2;
286e5aaf047SAppaRao Puli         std::optional<std::string> retryPolicy;
287e5aaf047SAppaRao Puli         std::optional<std::vector<std::string>> msgIds;
288e5aaf047SAppaRao Puli         std::optional<std::vector<std::string>> regPrefixes;
289e56f254cSSunitha Harish         std::optional<std::vector<std::string>> resTypes;
29078d4ec4fSEd Tanous         std::optional<std::vector<nlohmann::json::object_t>> headers;
29178d4ec4fSEd Tanous         std::optional<std::vector<nlohmann::json::object_t>> mrdJsonArray;
292e5aaf047SAppaRao Puli 
29315ed6780SWilly Tu         if (!json_util::readJsonPatch(
294002d39b4SEd Tanous                 req, asyncResp->res, "Destination", destUrl, "Context", context,
295002d39b4SEd Tanous                 "Protocol", protocol, "SubscriptionType", subscriptionType,
296002d39b4SEd Tanous                 "EventFormatType", eventFormatType2, "HttpHeaders", headers,
297002d39b4SEd Tanous                 "RegistryPrefixes", regPrefixes, "MessageIds", msgIds,
298002d39b4SEd Tanous                 "DeliveryRetryPolicy", retryPolicy, "MetricReportDefinitions",
29919bb362bSEd Tanous                 mrdJsonArray, "ResourceTypes", resTypes, "VerifyCertificate",
30019bb362bSEd Tanous                 verifyCertificate))
301e5aaf047SAppaRao Puli         {
302e5aaf047SAppaRao Puli             return;
303e5aaf047SAppaRao Puli         }
304e5aaf047SAppaRao Puli 
305600af5f1SAppaRao Puli         // https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
306600af5f1SAppaRao Puli         static constexpr const uint16_t maxDestinationSize = 2000;
307600af5f1SAppaRao Puli         if (destUrl.size() > maxDestinationSize)
308600af5f1SAppaRao Puli         {
309600af5f1SAppaRao Puli             messages::stringValueTooLong(asyncResp->res, "Destination",
310600af5f1SAppaRao Puli                                          maxDestinationSize);
311600af5f1SAppaRao Puli             return;
312600af5f1SAppaRao Puli         }
313600af5f1SAppaRao Puli 
314dd28ba82SAppaRao Puli         if (regPrefixes && msgIds)
315dd28ba82SAppaRao Puli         {
31626f6976fSEd Tanous             if (!regPrefixes->empty() && !msgIds->empty())
317dd28ba82SAppaRao Puli             {
318002d39b4SEd Tanous                 messages::propertyValueConflict(asyncResp->res, "MessageIds",
319002d39b4SEd Tanous                                                 "RegistryPrefixes");
320dd28ba82SAppaRao Puli                 return;
321dd28ba82SAppaRao Puli             }
322dd28ba82SAppaRao Puli         }
323dd28ba82SAppaRao Puli 
3246fd29553SEd Tanous         boost::system::result<boost::urls::url> url =
325a716aa74SEd Tanous             boost::urls::parse_absolute_uri(destUrl);
326a716aa74SEd Tanous         if (!url)
327e5aaf047SAppaRao Puli         {
32862598e31SEd Tanous             BMCWEB_LOG_WARNING("Failed to validate and split destination url");
329e5aaf047SAppaRao Puli             messages::propertyValueFormatError(asyncResp->res, destUrl,
330e5aaf047SAppaRao Puli                                                "Destination");
331e5aaf047SAppaRao Puli             return;
332e5aaf047SAppaRao Puli         }
333a716aa74SEd Tanous         url->normalize();
334a716aa74SEd Tanous         crow::utility::setProtocolDefaults(*url, protocol);
335a716aa74SEd Tanous         crow::utility::setPortDefaults(*url);
336a716aa74SEd Tanous 
337a716aa74SEd Tanous         if (url->path().empty())
338a716aa74SEd Tanous         {
339a716aa74SEd Tanous             url->set_path("/");
340a716aa74SEd Tanous         }
341a716aa74SEd Tanous 
342a716aa74SEd Tanous         if (url->has_userinfo())
343a716aa74SEd Tanous         {
344a716aa74SEd Tanous             messages::propertyValueFormatError(asyncResp->res, destUrl,
345a716aa74SEd Tanous                                                "Destination");
346a716aa74SEd Tanous             return;
347a716aa74SEd Tanous         }
348b52664e2SAppaRao Puli 
3493d30708fSChicago Duan         if (protocol == "SNMPv2c")
3503d30708fSChicago Duan         {
3513d30708fSChicago Duan             if (context)
3523d30708fSChicago Duan             {
3533d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "Context",
3543d30708fSChicago Duan                                                 "Protocol");
3553d30708fSChicago Duan                 return;
3563d30708fSChicago Duan             }
3573d30708fSChicago Duan             if (eventFormatType2)
3583d30708fSChicago Duan             {
3593d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res,
3603d30708fSChicago Duan                                                 "EventFormatType", "Protocol");
3613d30708fSChicago Duan                 return;
3623d30708fSChicago Duan             }
3633d30708fSChicago Duan             if (retryPolicy)
3643d30708fSChicago Duan             {
3653d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "RetryPolicy",
3663d30708fSChicago Duan                                                 "Protocol");
3673d30708fSChicago Duan                 return;
3683d30708fSChicago Duan             }
3693d30708fSChicago Duan             if (msgIds)
3703d30708fSChicago Duan             {
3713d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "MessageIds",
3723d30708fSChicago Duan                                                 "Protocol");
3733d30708fSChicago Duan                 return;
3743d30708fSChicago Duan             }
3753d30708fSChicago Duan             if (regPrefixes)
3763d30708fSChicago Duan             {
3773d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res,
3783d30708fSChicago Duan                                                 "RegistryPrefixes", "Protocol");
3793d30708fSChicago Duan                 return;
3803d30708fSChicago Duan             }
3813d30708fSChicago Duan             if (resTypes)
3823d30708fSChicago Duan             {
3833d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "ResourceTypes",
3843d30708fSChicago Duan                                                 "Protocol");
3853d30708fSChicago Duan                 return;
3863d30708fSChicago Duan             }
3873d30708fSChicago Duan             if (headers)
3883d30708fSChicago Duan             {
3893d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "HttpHeaders",
3903d30708fSChicago Duan                                                 "Protocol");
3913d30708fSChicago Duan                 return;
3923d30708fSChicago Duan             }
3933d30708fSChicago Duan             if (mrdJsonArray)
3943d30708fSChicago Duan             {
3953d30708fSChicago Duan                 messages::propertyValueConflict(
3963d30708fSChicago Duan                     asyncResp->res, "MetricReportDefinitions", "Protocol");
3973d30708fSChicago Duan                 return;
3983d30708fSChicago Duan             }
399a716aa74SEd Tanous             if (url->scheme() != "snmp")
400a716aa74SEd Tanous             {
401a716aa74SEd Tanous                 messages::propertyValueConflict(asyncResp->res, "Destination",
402a716aa74SEd Tanous                                                 "Protocol");
4033d30708fSChicago Duan                 return;
4043d30708fSChicago Duan             }
4053d30708fSChicago Duan 
406a716aa74SEd Tanous             addSnmpTrapClient(asyncResp, url->host_address(),
407a716aa74SEd Tanous                               url->port_number());
408a716aa74SEd Tanous             return;
409b52664e2SAppaRao Puli         }
4103d30708fSChicago Duan 
411a716aa74SEd Tanous         std::shared_ptr<Subscription> subValue =
412a716aa74SEd Tanous             std::make_shared<Subscription>(*url, app.ioContext());
413b52664e2SAppaRao Puli 
414a716aa74SEd Tanous         subValue->destinationUrl = std::move(*url);
415e5aaf047SAppaRao Puli 
416e5aaf047SAppaRao Puli         if (subscriptionType)
417e5aaf047SAppaRao Puli         {
418e5aaf047SAppaRao Puli             if (*subscriptionType != "RedfishEvent")
419e5aaf047SAppaRao Puli             {
420fffb8c1fSEd Tanous                 messages::propertyValueNotInList(
421fffb8c1fSEd Tanous                     asyncResp->res, *subscriptionType, "SubscriptionType");
422e5aaf047SAppaRao Puli                 return;
423e5aaf047SAppaRao Puli             }
424b52664e2SAppaRao Puli             subValue->subscriptionType = *subscriptionType;
425e5aaf047SAppaRao Puli         }
426e5aaf047SAppaRao Puli         else
427e5aaf047SAppaRao Puli         {
428b52664e2SAppaRao Puli             subValue->subscriptionType = "RedfishEvent"; // Default
429e5aaf047SAppaRao Puli         }
430e5aaf047SAppaRao Puli 
431e5aaf047SAppaRao Puli         if (protocol != "Redfish")
432e5aaf047SAppaRao Puli         {
433e5aaf047SAppaRao Puli             messages::propertyValueNotInList(asyncResp->res, protocol,
434e5aaf047SAppaRao Puli                                              "Protocol");
435e5aaf047SAppaRao Puli             return;
436e5aaf047SAppaRao Puli         }
437b52664e2SAppaRao Puli         subValue->protocol = protocol;
438e5aaf047SAppaRao Puli 
43919bb362bSEd Tanous         if (verifyCertificate)
44019bb362bSEd Tanous         {
44119bb362bSEd Tanous             subValue->verifyCertificate = *verifyCertificate;
44219bb362bSEd Tanous         }
44319bb362bSEd Tanous 
44423a21a1cSEd Tanous         if (eventFormatType2)
445e5aaf047SAppaRao Puli         {
4463544d2a7SEd Tanous             if (std::ranges::find(supportedEvtFormatTypes, *eventFormatType2) ==
4473544d2a7SEd Tanous                 supportedEvtFormatTypes.end())
448e5aaf047SAppaRao Puli             {
449fffb8c1fSEd Tanous                 messages::propertyValueNotInList(
450fffb8c1fSEd Tanous                     asyncResp->res, *eventFormatType2, "EventFormatType");
451e5aaf047SAppaRao Puli                 return;
452e5aaf047SAppaRao Puli             }
45323a21a1cSEd Tanous             subValue->eventFormatType = *eventFormatType2;
454e5aaf047SAppaRao Puli         }
455e5aaf047SAppaRao Puli         else
456e5aaf047SAppaRao Puli         {
457e5aaf047SAppaRao Puli             // If not specified, use default "Event"
45823a21a1cSEd Tanous             subValue->eventFormatType = "Event";
459e5aaf047SAppaRao Puli         }
460e5aaf047SAppaRao Puli 
461e5aaf047SAppaRao Puli         if (context)
462e5aaf047SAppaRao Puli         {
4638ece0e45SEd Tanous             // This value is selected arbitrarily.
464600af5f1SAppaRao Puli             constexpr const size_t maxContextSize = 256;
465600af5f1SAppaRao Puli             if (context->size() > maxContextSize)
466600af5f1SAppaRao Puli             {
467600af5f1SAppaRao Puli                 messages::stringValueTooLong(asyncResp->res, "Context",
468600af5f1SAppaRao Puli                                              maxContextSize);
469600af5f1SAppaRao Puli                 return;
470600af5f1SAppaRao Puli             }
471b52664e2SAppaRao Puli             subValue->customText = *context;
472e5aaf047SAppaRao Puli         }
473e5aaf047SAppaRao Puli 
474e5aaf047SAppaRao Puli         if (headers)
475e5aaf047SAppaRao Puli         {
476600af5f1SAppaRao Puli             size_t cumulativeLen = 0;
477600af5f1SAppaRao Puli 
47878d4ec4fSEd Tanous             for (const nlohmann::json::object_t& headerChunk : *headers)
479601c71aeSEd Tanous             {
48078d4ec4fSEd Tanous                 for (const auto& item : headerChunk)
48178d4ec4fSEd Tanous                 {
48278d4ec4fSEd Tanous                     const std::string* value =
48378d4ec4fSEd Tanous                         item.second.get_ptr<const std::string*>();
48478d4ec4fSEd Tanous                     if (value == nullptr)
48578d4ec4fSEd Tanous                     {
48678d4ec4fSEd Tanous                         messages::propertyValueFormatError(
48778d4ec4fSEd Tanous                             asyncResp->res, item.second,
48878d4ec4fSEd Tanous                             "HttpHeaders/" + item.first);
48978d4ec4fSEd Tanous                         return;
49078d4ec4fSEd Tanous                     }
49178d4ec4fSEd Tanous                     // Adding a new json value is the size of the key, +
49278d4ec4fSEd Tanous                     // the size of the value + 2 * 2 quotes for each, +
49378d4ec4fSEd Tanous                     // the colon and space between. example:
49478d4ec4fSEd Tanous                     // "key": "value"
49578d4ec4fSEd Tanous                     cumulativeLen += item.first.size() + value->size() + 6;
496600af5f1SAppaRao Puli                     // This value is selected to mirror http_connection.hpp
497600af5f1SAppaRao Puli                     constexpr const uint16_t maxHeaderSizeED = 8096;
498600af5f1SAppaRao Puli                     if (cumulativeLen > maxHeaderSizeED)
499600af5f1SAppaRao Puli                     {
50078d4ec4fSEd Tanous                         messages::arraySizeTooLong(
50178d4ec4fSEd Tanous                             asyncResp->res, "HttpHeaders", maxHeaderSizeED);
502600af5f1SAppaRao Puli                         return;
503600af5f1SAppaRao Puli                     }
50478d4ec4fSEd Tanous                     subValue->httpHeaders.set(item.first, *value);
505601c71aeSEd Tanous                 }
506601c71aeSEd Tanous             }
507e5aaf047SAppaRao Puli         }
508e5aaf047SAppaRao Puli 
509e5aaf047SAppaRao Puli         if (regPrefixes)
510e5aaf047SAppaRao Puli         {
511e5aaf047SAppaRao Puli             for (const std::string& it : *regPrefixes)
512e5aaf047SAppaRao Puli             {
5133544d2a7SEd Tanous                 if (std::ranges::find(supportedRegPrefixes, it) ==
5143544d2a7SEd Tanous                     supportedRegPrefixes.end())
515e5aaf047SAppaRao Puli                 {
516fffb8c1fSEd Tanous                     messages::propertyValueNotInList(asyncResp->res, it,
517fffb8c1fSEd Tanous                                                      "RegistryPrefixes");
518e5aaf047SAppaRao Puli                     return;
519e5aaf047SAppaRao Puli                 }
520e5aaf047SAppaRao Puli             }
521b52664e2SAppaRao Puli             subValue->registryPrefixes = *regPrefixes;
522e5aaf047SAppaRao Puli         }
523e5aaf047SAppaRao Puli 
524e56f254cSSunitha Harish         if (resTypes)
525e56f254cSSunitha Harish         {
526e56f254cSSunitha Harish             for (const std::string& it : *resTypes)
527e56f254cSSunitha Harish             {
5283544d2a7SEd Tanous                 if (std::ranges::find(supportedResourceTypes, it) ==
5293544d2a7SEd Tanous                     supportedResourceTypes.end())
530e56f254cSSunitha Harish                 {
531e56f254cSSunitha Harish                     messages::propertyValueNotInList(asyncResp->res, it,
532e56f254cSSunitha Harish                                                      "ResourceTypes");
533e56f254cSSunitha Harish                     return;
534e56f254cSSunitha Harish                 }
535e56f254cSSunitha Harish             }
536e56f254cSSunitha Harish             subValue->resourceTypes = *resTypes;
537e56f254cSSunitha Harish         }
538e56f254cSSunitha Harish 
539e5aaf047SAppaRao Puli         if (msgIds)
540e5aaf047SAppaRao Puli         {
541b304bd79SP Dheeraj Srujan Kumar             std::vector<std::string> registryPrefix;
542b304bd79SP Dheeraj Srujan Kumar 
5437e860f15SJohn Edward Broadbent             // If no registry prefixes are mentioned, consider all
5447e860f15SJohn Edward Broadbent             // supported prefixes
545b304bd79SP Dheeraj Srujan Kumar             if (subValue->registryPrefixes.empty())
546b304bd79SP Dheeraj Srujan Kumar             {
547b304bd79SP Dheeraj Srujan Kumar                 registryPrefix.assign(supportedRegPrefixes.begin(),
548b304bd79SP Dheeraj Srujan Kumar                                       supportedRegPrefixes.end());
549b304bd79SP Dheeraj Srujan Kumar             }
550b304bd79SP Dheeraj Srujan Kumar             else
551b304bd79SP Dheeraj Srujan Kumar             {
552b304bd79SP Dheeraj Srujan Kumar                 registryPrefix = subValue->registryPrefixes;
553b304bd79SP Dheeraj Srujan Kumar             }
554b304bd79SP Dheeraj Srujan Kumar 
555b304bd79SP Dheeraj Srujan Kumar             for (const std::string& id : *msgIds)
556b304bd79SP Dheeraj Srujan Kumar             {
557b304bd79SP Dheeraj Srujan Kumar                 bool validId = false;
558b304bd79SP Dheeraj Srujan Kumar 
559b304bd79SP Dheeraj Srujan Kumar                 // Check for Message ID in each of the selected Registry
560b304bd79SP Dheeraj Srujan Kumar                 for (const std::string& it : registryPrefix)
561b304bd79SP Dheeraj Srujan Kumar                 {
562fffb8c1fSEd Tanous                     const std::span<const redfish::registries::MessageEntry>
563fffb8c1fSEd Tanous                         registry =
564fffb8c1fSEd Tanous                             redfish::registries::getRegistryFromPrefix(it);
565b304bd79SP Dheeraj Srujan Kumar 
5663544d2a7SEd Tanous                     if (std::ranges::any_of(
5673544d2a7SEd Tanous                             registry,
568fffb8c1fSEd Tanous                             [&id](const redfish::registries::MessageEntry&
569fffb8c1fSEd Tanous                                       messageEntry) {
57055f79e6fSEd Tanous                         return id == messageEntry.first;
571b304bd79SP Dheeraj Srujan Kumar                     }))
572b304bd79SP Dheeraj Srujan Kumar                     {
573b304bd79SP Dheeraj Srujan Kumar                         validId = true;
574b304bd79SP Dheeraj Srujan Kumar                         break;
575b304bd79SP Dheeraj Srujan Kumar                     }
576b304bd79SP Dheeraj Srujan Kumar                 }
577b304bd79SP Dheeraj Srujan Kumar 
578b304bd79SP Dheeraj Srujan Kumar                 if (!validId)
579b304bd79SP Dheeraj Srujan Kumar                 {
580b304bd79SP Dheeraj Srujan Kumar                     messages::propertyValueNotInList(asyncResp->res, id,
581b304bd79SP Dheeraj Srujan Kumar                                                      "MessageIds");
582b304bd79SP Dheeraj Srujan Kumar                     return;
583b304bd79SP Dheeraj Srujan Kumar                 }
584b304bd79SP Dheeraj Srujan Kumar             }
585b304bd79SP Dheeraj Srujan Kumar 
586b52664e2SAppaRao Puli             subValue->registryMsgIds = *msgIds;
587e5aaf047SAppaRao Puli         }
588e5aaf047SAppaRao Puli 
589e5aaf047SAppaRao Puli         if (retryPolicy)
590e5aaf047SAppaRao Puli         {
5913544d2a7SEd Tanous             if (std::ranges::find(supportedRetryPolicies, *retryPolicy) ==
5923544d2a7SEd Tanous                 supportedRetryPolicies.end())
593e5aaf047SAppaRao Puli             {
594002d39b4SEd Tanous                 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
595002d39b4SEd Tanous                                                  "DeliveryRetryPolicy");
596e5aaf047SAppaRao Puli                 return;
597e5aaf047SAppaRao Puli             }
598b52664e2SAppaRao Puli             subValue->retryPolicy = *retryPolicy;
599e5aaf047SAppaRao Puli         }
600e5aaf047SAppaRao Puli         else
601e5aaf047SAppaRao Puli         {
602e5aaf047SAppaRao Puli             // Default "TerminateAfterRetries"
603b52664e2SAppaRao Puli             subValue->retryPolicy = "TerminateAfterRetries";
604e5aaf047SAppaRao Puli         }
605e5aaf047SAppaRao Puli 
606144b6318SAppaRao Puli         if (mrdJsonArray)
607156d6b00SAppaRao Puli         {
60878d4ec4fSEd Tanous             for (nlohmann::json::object_t& mrdObj : *mrdJsonArray)
609144b6318SAppaRao Puli             {
610144b6318SAppaRao Puli                 std::string mrdUri;
611ea2e6eecSWilly Tu 
61278d4ec4fSEd Tanous                 if (!json_util::readJsonObject(mrdObj, asyncResp->res,
61378d4ec4fSEd Tanous                                                "@odata.id", mrdUri))
614ea2e6eecSWilly Tu 
615144b6318SAppaRao Puli                 {
616144b6318SAppaRao Puli                     return;
617144b6318SAppaRao Puli                 }
618ea2e6eecSWilly Tu                 subValue->metricReportDefinitions.emplace_back(mrdUri);
619144b6318SAppaRao Puli             }
620156d6b00SAppaRao Puli         }
621156d6b00SAppaRao Puli 
622b52664e2SAppaRao Puli         std::string id =
623f80a87f2SEd Tanous             EventServiceManager::getInstance().addPushSubscription(subValue);
624b52664e2SAppaRao Puli         if (id.empty())
625e5aaf047SAppaRao Puli         {
626e5aaf047SAppaRao Puli             messages::internalError(asyncResp->res);
627e5aaf047SAppaRao Puli             return;
628e5aaf047SAppaRao Puli         }
629e5aaf047SAppaRao Puli 
630e5aaf047SAppaRao Puli         messages::created(asyncResp->res);
631e5aaf047SAppaRao Puli         asyncResp->res.addHeader(
632e5aaf047SAppaRao Puli             "Location", "/redfish/v1/EventService/Subscriptions/" + id);
6337e860f15SJohn Edward Broadbent     });
634e5aaf047SAppaRao Puli }
635e5aaf047SAppaRao Puli 
6367e860f15SJohn Edward Broadbent inline void requestRoutesEventDestination(App& app)
637e5aaf047SAppaRao Puli {
6389d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
639ed398213SEd Tanous         .privileges(redfish::privileges::getEventDestination)
6407e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
64145ca1b86SEd Tanous             [&app](const crow::Request& req,
6427e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
6437e860f15SJohn Edward Broadbent                    const std::string& param) {
6443ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
64545ca1b86SEd Tanous         {
64645ca1b86SEd Tanous             return;
64745ca1b86SEd Tanous         }
6483d30708fSChicago Duan 
6493d30708fSChicago Duan         if (param.starts_with("snmp"))
6503d30708fSChicago Duan         {
6513d30708fSChicago Duan             getSnmpTrapClient(asyncResp, param);
6523d30708fSChicago Duan             return;
6533d30708fSChicago Duan         }
6543d30708fSChicago Duan 
655b52664e2SAppaRao Puli         std::shared_ptr<Subscription> subValue =
6567e860f15SJohn Edward Broadbent             EventServiceManager::getInstance().getSubscription(param);
657b52664e2SAppaRao Puli         if (subValue == nullptr)
658e5aaf047SAppaRao Puli         {
659002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::not_found);
660e5aaf047SAppaRao Puli             return;
661e5aaf047SAppaRao Puli         }
6627e860f15SJohn Edward Broadbent         const std::string& id = param;
663e5aaf047SAppaRao Puli 
6641476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
6653d30708fSChicago Duan             "#EventDestination.v1_8_0.EventDestination";
666*539d8c6bSEd Tanous         asyncResp->res.jsonValue["Protocol"] =
667*539d8c6bSEd Tanous             event_destination::EventDestinationProtocol::Redfish;
6683b32780dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
6693b32780dSEd Tanous             "/redfish/v1/EventService/Subscriptions/{}", id);
670e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["Id"] = id;
671e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
672002d39b4SEd Tanous         asyncResp->res.jsonValue["Destination"] = subValue->destinationUrl;
673b52664e2SAppaRao Puli         asyncResp->res.jsonValue["Context"] = subValue->customText;
674e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["SubscriptionType"] =
675b52664e2SAppaRao Puli             subValue->subscriptionType;
676002d39b4SEd Tanous         asyncResp->res.jsonValue["HttpHeaders"] = nlohmann::json::array();
677002d39b4SEd Tanous         asyncResp->res.jsonValue["EventFormatType"] = subValue->eventFormatType;
678e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["RegistryPrefixes"] =
679b52664e2SAppaRao Puli             subValue->registryPrefixes;
680002d39b4SEd Tanous         asyncResp->res.jsonValue["ResourceTypes"] = subValue->resourceTypes;
681e56f254cSSunitha Harish 
682002d39b4SEd Tanous         asyncResp->res.jsonValue["MessageIds"] = subValue->registryMsgIds;
683002d39b4SEd Tanous         asyncResp->res.jsonValue["DeliveryRetryPolicy"] = subValue->retryPolicy;
68419bb362bSEd Tanous         asyncResp->res.jsonValue["VerifyCertificate"] =
68519bb362bSEd Tanous             subValue->verifyCertificate;
686144b6318SAppaRao Puli 
6871476687dSEd Tanous         nlohmann::json::array_t mrdJsonArray;
688144b6318SAppaRao Puli         for (const auto& mdrUri : subValue->metricReportDefinitions)
689144b6318SAppaRao Puli         {
6901476687dSEd Tanous             nlohmann::json::object_t mdr;
6911476687dSEd Tanous             mdr["@odata.id"] = mdrUri;
6921476687dSEd Tanous             mrdJsonArray.emplace_back(std::move(mdr));
693144b6318SAppaRao Puli         }
694002d39b4SEd Tanous         asyncResp->res.jsonValue["MetricReportDefinitions"] = mrdJsonArray;
6957e860f15SJohn Edward Broadbent     });
6969d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
697ed398213SEd Tanous         // The below privilege is wrong, it should be ConfigureManager OR
698ed398213SEd Tanous         // ConfigureSelf
6997eeafa76SAbhishek Patel         // https://github.com/openbmc/bmcweb/issues/220
700ed398213SEd Tanous         //.privileges(redfish::privileges::patchEventDestination)
701432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
7027e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
70345ca1b86SEd Tanous             [&app](const crow::Request& req,
7047e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7057e860f15SJohn Edward Broadbent                    const std::string& param) {
7063ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
70745ca1b86SEd Tanous         {
70845ca1b86SEd Tanous             return;
70945ca1b86SEd Tanous         }
710b52664e2SAppaRao Puli         std::shared_ptr<Subscription> subValue =
7117e860f15SJohn Edward Broadbent             EventServiceManager::getInstance().getSubscription(param);
712b52664e2SAppaRao Puli         if (subValue == nullptr)
713e5aaf047SAppaRao Puli         {
714002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::not_found);
715e5aaf047SAppaRao Puli             return;
716e5aaf047SAppaRao Puli         }
717e5aaf047SAppaRao Puli 
718e5aaf047SAppaRao Puli         std::optional<std::string> context;
719e5aaf047SAppaRao Puli         std::optional<std::string> retryPolicy;
72019bb362bSEd Tanous         std::optional<bool> verifyCertificate;
72178d4ec4fSEd Tanous         std::optional<std::vector<nlohmann::json::object_t>> headers;
722e5aaf047SAppaRao Puli 
723002d39b4SEd Tanous         if (!json_util::readJsonPatch(req, asyncResp->res, "Context", context,
72419bb362bSEd Tanous                                       "VerifyCertificate", verifyCertificate,
725002d39b4SEd Tanous                                       "DeliveryRetryPolicy", retryPolicy,
726002d39b4SEd Tanous                                       "HttpHeaders", headers))
727e5aaf047SAppaRao Puli         {
728e5aaf047SAppaRao Puli             return;
729e5aaf047SAppaRao Puli         }
730e5aaf047SAppaRao Puli 
731e5aaf047SAppaRao Puli         if (context)
732e5aaf047SAppaRao Puli         {
733b52664e2SAppaRao Puli             subValue->customText = *context;
734e5aaf047SAppaRao Puli         }
735e5aaf047SAppaRao Puli 
736e5aaf047SAppaRao Puli         if (headers)
737e5aaf047SAppaRao Puli         {
738601c71aeSEd Tanous             boost::beast::http::fields fields;
73978d4ec4fSEd Tanous             for (const nlohmann::json::object_t& headerChunk : *headers)
740601c71aeSEd Tanous             {
74178d4ec4fSEd Tanous                 for (const auto& it : headerChunk)
742601c71aeSEd Tanous                 {
743601c71aeSEd Tanous                     const std::string* value =
74478d4ec4fSEd Tanous                         it.second.get_ptr<const std::string*>();
745601c71aeSEd Tanous                     if (value == nullptr)
746601c71aeSEd Tanous                     {
747601c71aeSEd Tanous                         messages::propertyValueFormatError(
74878d4ec4fSEd Tanous                             asyncResp->res, it.second,
74978d4ec4fSEd Tanous                             "HttpHeaders/" + it.first);
750601c71aeSEd Tanous                         return;
751601c71aeSEd Tanous                     }
75278d4ec4fSEd Tanous                     fields.set(it.first, *value);
753601c71aeSEd Tanous                 }
754601c71aeSEd Tanous             }
75578d4ec4fSEd Tanous             subValue->httpHeaders = std::move(fields);
756e5aaf047SAppaRao Puli         }
757e5aaf047SAppaRao Puli 
758e5aaf047SAppaRao Puli         if (retryPolicy)
759e5aaf047SAppaRao Puli         {
7603544d2a7SEd Tanous             if (std::ranges::find(supportedRetryPolicies, *retryPolicy) ==
7613544d2a7SEd Tanous                 supportedRetryPolicies.end())
762e5aaf047SAppaRao Puli             {
763002d39b4SEd Tanous                 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
764e5aaf047SAppaRao Puli                                                  "DeliveryRetryPolicy");
765e5aaf047SAppaRao Puli                 return;
766e5aaf047SAppaRao Puli             }
767b52664e2SAppaRao Puli             subValue->retryPolicy = *retryPolicy;
768e5aaf047SAppaRao Puli         }
769e5aaf047SAppaRao Puli 
77019bb362bSEd Tanous         if (verifyCertificate)
77119bb362bSEd Tanous         {
77219bb362bSEd Tanous             subValue->verifyCertificate = *verifyCertificate;
77319bb362bSEd Tanous         }
77419bb362bSEd Tanous 
775b52664e2SAppaRao Puli         EventServiceManager::getInstance().updateSubscriptionData();
7767e860f15SJohn Edward Broadbent     });
7779d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
778ed398213SEd Tanous         // The below privilege is wrong, it should be ConfigureManager OR
779ed398213SEd Tanous         // ConfigureSelf
7807eeafa76SAbhishek Patel         // https://github.com/openbmc/bmcweb/issues/220
781ed398213SEd Tanous         //.privileges(redfish::privileges::deleteEventDestination)
782432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
7837e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
78445ca1b86SEd Tanous             [&app](const crow::Request& req,
7857e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7867e860f15SJohn Edward Broadbent                    const std::string& param) {
7873ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
78845ca1b86SEd Tanous         {
78945ca1b86SEd Tanous             return;
79045ca1b86SEd Tanous         }
7913d30708fSChicago Duan 
7923d30708fSChicago Duan         if (param.starts_with("snmp"))
7933d30708fSChicago Duan         {
7943d30708fSChicago Duan             deleteSnmpTrapClient(asyncResp, param);
7953d30708fSChicago Duan             EventServiceManager::getInstance().deleteSubscription(param);
7963d30708fSChicago Duan             return;
7973d30708fSChicago Duan         }
7983d30708fSChicago Duan 
799002d39b4SEd Tanous         if (!EventServiceManager::getInstance().isSubscriptionExist(param))
800e5aaf047SAppaRao Puli         {
801002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::not_found);
802e5aaf047SAppaRao Puli             return;
803e5aaf047SAppaRao Puli         }
8047e860f15SJohn Edward Broadbent         EventServiceManager::getInstance().deleteSubscription(param);
8057e860f15SJohn Edward Broadbent     });
806e5aaf047SAppaRao Puli }
807e5aaf047SAppaRao Puli 
808e5aaf047SAppaRao Puli } // namespace redfish
809