xref: /openbmc/bmcweb/features/redfish/lib/event_service.hpp (revision 3d30708fb65e40cd28da601b3e91a527a8862e15)
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"
23*3d30708fSChicago Duan #include "snmp_trap_event_clients.hpp"
24e5aaf047SAppaRao Puli 
25601c71aeSEd Tanous #include <boost/beast/http/fields.hpp>
26*3d30708fSChicago Duan #include <boost/system/error_code.hpp>
27*3d30708fSChicago Duan #include <sdbusplus/unpack_properties.hpp>
28*3d30708fSChicago Duan #include <utils/dbus_utils.hpp>
29ed398213SEd Tanous 
30*3d30708fSChicago Duan #include <charconv>
31*3d30708fSChicago Duan #include <memory>
321e270c5fSPatrick Williams #include <span>
33*3d30708fSChicago Duan #include <string>
341e270c5fSPatrick Williams 
35e5aaf047SAppaRao Puli namespace redfish
36e5aaf047SAppaRao Puli {
37e5aaf047SAppaRao Puli 
38156d6b00SAppaRao Puli static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
39156d6b00SAppaRao Puli     eventFormatType, metricReportFormatType};
40e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
41b304bd79SP Dheeraj Srujan Kumar     "Base", "OpenBMC", "TaskEvent"};
42e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
43e5aaf047SAppaRao Puli     "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
44e5aaf047SAppaRao Puli 
45e56f254cSSunitha Harish #ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
46e56f254cSSunitha Harish static constexpr const std::array<const char*, 2> supportedResourceTypes = {
47e56f254cSSunitha Harish     "IBMConfigFile", "Task"};
48e56f254cSSunitha Harish #else
49e56f254cSSunitha Harish static constexpr const std::array<const char*, 1> supportedResourceTypes = {
50e56f254cSSunitha Harish     "Task"};
51e56f254cSSunitha Harish #endif
52e56f254cSSunitha Harish 
537e860f15SJohn Edward Broadbent inline void requestRoutesEventService(App& app)
54e5aaf047SAppaRao Puli {
557e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
56ed398213SEd Tanous         .privileges(redfish::privileges::getEventService)
57002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
58002d39b4SEd Tanous             [&app](const crow::Request& req,
59002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
603ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
6145ca1b86SEd Tanous         {
6245ca1b86SEd Tanous             return;
6345ca1b86SEd Tanous         }
641476687dSEd Tanous 
651476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/EventService";
661476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
671476687dSEd Tanous             "#EventService.v1_5_0.EventService";
681476687dSEd Tanous         asyncResp->res.jsonValue["Id"] = "EventService";
691476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "Event Service";
705e44e3d8SAppaRao Puli         asyncResp->res.jsonValue["ServerSentEventUri"] =
715e44e3d8SAppaRao Puli             "/redfish/v1/EventService/SSE";
725e44e3d8SAppaRao Puli 
731476687dSEd Tanous         asyncResp->res.jsonValue["Subscriptions"]["@odata.id"] =
741476687dSEd Tanous             "/redfish/v1/EventService/Subscriptions";
75002d39b4SEd Tanous         asyncResp->res
76002d39b4SEd Tanous             .jsonValue["Actions"]["#EventService.SubmitTestEvent"]["target"] =
771476687dSEd Tanous             "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent";
78e5aaf047SAppaRao Puli 
7928afb49cSJunLin Chen         const persistent_data::EventServiceConfig eventServiceConfig =
8028afb49cSJunLin Chen             persistent_data::EventServiceStore::getInstance()
8128afb49cSJunLin Chen                 .getEventServiceConfig();
827d1cc387SAppaRao Puli 
837d1cc387SAppaRao Puli         asyncResp->res.jsonValue["Status"]["State"] =
8428afb49cSJunLin Chen             (eventServiceConfig.enabled ? "Enabled" : "Disabled");
85002d39b4SEd Tanous         asyncResp->res.jsonValue["ServiceEnabled"] = eventServiceConfig.enabled;
867e860f15SJohn Edward Broadbent         asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
8728afb49cSJunLin Chen             eventServiceConfig.retryAttempts;
88e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
8928afb49cSJunLin Chen             eventServiceConfig.retryTimeoutInterval;
90002d39b4SEd Tanous         asyncResp->res.jsonValue["EventFormatTypes"] = supportedEvtFormatTypes;
910fda0f12SGeorge Liu         asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
920fda0f12SGeorge Liu         asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
9307941a88SAyushi Smriti 
94613dabeaSEd Tanous         nlohmann::json::object_t supportedSSEFilters;
95613dabeaSEd Tanous         supportedSSEFilters["EventFormatType"] = true;
96613dabeaSEd Tanous         supportedSSEFilters["MessageId"] = true;
97613dabeaSEd Tanous         supportedSSEFilters["MetricReportDefinition"] = true;
98613dabeaSEd Tanous         supportedSSEFilters["RegistryPrefix"] = true;
99613dabeaSEd Tanous         supportedSSEFilters["OriginResource"] = false;
100613dabeaSEd Tanous         supportedSSEFilters["ResourceType"] = false;
10107941a88SAyushi Smriti 
10207941a88SAyushi Smriti         asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
103613dabeaSEd Tanous             std::move(supportedSSEFilters);
1047e860f15SJohn Edward Broadbent         });
105e5aaf047SAppaRao Puli 
1067e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
107ed398213SEd Tanous         .privileges(redfish::privileges::patchEventService)
1087e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
10945ca1b86SEd Tanous             [&app](const crow::Request& req,
11045ca1b86SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1113ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
112e5aaf047SAppaRao Puli         {
11345ca1b86SEd Tanous             return;
11445ca1b86SEd Tanous         }
115e5aaf047SAppaRao Puli         std::optional<bool> serviceEnabled;
116e5aaf047SAppaRao Puli         std::optional<uint32_t> retryAttemps;
117e5aaf047SAppaRao Puli         std::optional<uint32_t> retryInterval;
118e5aaf047SAppaRao Puli 
11915ed6780SWilly Tu         if (!json_util::readJsonPatch(
1207e860f15SJohn Edward Broadbent                 req, asyncResp->res, "ServiceEnabled", serviceEnabled,
1217e860f15SJohn Edward Broadbent                 "DeliveryRetryAttempts", retryAttemps,
1227e860f15SJohn Edward Broadbent                 "DeliveryRetryIntervalSeconds", retryInterval))
123e5aaf047SAppaRao Puli         {
124e5aaf047SAppaRao Puli             return;
125e5aaf047SAppaRao Puli         }
126e5aaf047SAppaRao Puli 
12728afb49cSJunLin Chen         persistent_data::EventServiceConfig eventServiceConfig =
12828afb49cSJunLin Chen             persistent_data::EventServiceStore::getInstance()
12928afb49cSJunLin Chen                 .getEventServiceConfig();
1307d1cc387SAppaRao Puli 
131e5aaf047SAppaRao Puli         if (serviceEnabled)
132e5aaf047SAppaRao Puli         {
13328afb49cSJunLin Chen             eventServiceConfig.enabled = *serviceEnabled;
134e5aaf047SAppaRao Puli         }
135e5aaf047SAppaRao Puli 
136e5aaf047SAppaRao Puli         if (retryAttemps)
137e5aaf047SAppaRao Puli         {
138e5aaf047SAppaRao Puli             // Supported range [1-3]
139e5aaf047SAppaRao Puli             if ((*retryAttemps < 1) || (*retryAttemps > 3))
140e5aaf047SAppaRao Puli             {
141e5aaf047SAppaRao Puli                 messages::queryParameterOutOfRange(
142e5aaf047SAppaRao Puli                     asyncResp->res, std::to_string(*retryAttemps),
143e5aaf047SAppaRao Puli                     "DeliveryRetryAttempts", "[1-3]");
144e5aaf047SAppaRao Puli             }
145e5aaf047SAppaRao Puli             else
146e5aaf047SAppaRao Puli             {
14728afb49cSJunLin Chen                 eventServiceConfig.retryAttempts = *retryAttemps;
148e5aaf047SAppaRao Puli             }
149e5aaf047SAppaRao Puli         }
150e5aaf047SAppaRao Puli 
151e5aaf047SAppaRao Puli         if (retryInterval)
152e5aaf047SAppaRao Puli         {
15333a32b34SGunnar Mills             // Supported range [5 - 180]
15433a32b34SGunnar Mills             if ((*retryInterval < 5) || (*retryInterval > 180))
155e5aaf047SAppaRao Puli             {
156e5aaf047SAppaRao Puli                 messages::queryParameterOutOfRange(
157e5aaf047SAppaRao Puli                     asyncResp->res, std::to_string(*retryInterval),
15833a32b34SGunnar Mills                     "DeliveryRetryIntervalSeconds", "[5-180]");
159e5aaf047SAppaRao Puli             }
160e5aaf047SAppaRao Puli             else
161e5aaf047SAppaRao Puli             {
162002d39b4SEd Tanous                 eventServiceConfig.retryTimeoutInterval = *retryInterval;
163e5aaf047SAppaRao Puli             }
164e5aaf047SAppaRao Puli         }
165e5aaf047SAppaRao Puli 
1667d1cc387SAppaRao Puli         EventServiceManager::getInstance().setEventServiceConfig(
16728afb49cSJunLin Chen             eventServiceConfig);
1687e860f15SJohn Edward Broadbent         });
1690b4bdd93SAppaRao Puli }
1700b4bdd93SAppaRao Puli 
1717e860f15SJohn Edward Broadbent inline void requestRoutesSubmitTestEvent(App& app)
1720b4bdd93SAppaRao Puli {
1737e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
1747e860f15SJohn Edward Broadbent         app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
175ed398213SEd Tanous         .privileges(redfish::privileges::postEventService)
1767e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
17745ca1b86SEd Tanous             [&app](const crow::Request& req,
1787e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1793ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
18045ca1b86SEd Tanous         {
18145ca1b86SEd Tanous             return;
18245ca1b86SEd Tanous         }
1836ba8c82eSsunharis_in         if (!EventServiceManager::getInstance().sendTestEventLog())
1846ba8c82eSsunharis_in         {
1856ba8c82eSsunharis_in             messages::serviceDisabled(asyncResp->res,
1866ba8c82eSsunharis_in                                       "/redfish/v1/EventService/");
1876ba8c82eSsunharis_in             return;
1886ba8c82eSsunharis_in         }
1898d1b46d7Szhanghch05         asyncResp->res.result(boost::beast::http::status::no_content);
1907e860f15SJohn Edward Broadbent         });
191e5aaf047SAppaRao Puli }
192e5aaf047SAppaRao Puli 
193*3d30708fSChicago Duan inline void doSubscriptionCollection(
194*3d30708fSChicago Duan     const boost::system::error_code ec,
195*3d30708fSChicago Duan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
196*3d30708fSChicago Duan     const dbus::utility::ManagedObjectType& resp)
197*3d30708fSChicago Duan {
198*3d30708fSChicago Duan     if (ec)
199*3d30708fSChicago Duan     {
200*3d30708fSChicago Duan         if (ec.value() == EBADR)
201*3d30708fSChicago Duan         {
202*3d30708fSChicago Duan             // This is an optional process so just return if it isn't there
203*3d30708fSChicago Duan             return;
204*3d30708fSChicago Duan         }
205*3d30708fSChicago Duan 
206*3d30708fSChicago Duan         BMCWEB_LOG_ERROR << "D-Bus response error on GetManagedObjects " << ec;
207*3d30708fSChicago Duan         messages::internalError(asyncResp->res);
208*3d30708fSChicago Duan         return;
209*3d30708fSChicago Duan     }
210*3d30708fSChicago Duan     nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
211*3d30708fSChicago Duan     for (const auto& objpath : resp)
212*3d30708fSChicago Duan     {
213*3d30708fSChicago Duan         sdbusplus::message::object_path path(objpath.first);
214*3d30708fSChicago Duan         const std::string snmpId = path.filename();
215*3d30708fSChicago Duan         if (snmpId.empty())
216*3d30708fSChicago Duan         {
217*3d30708fSChicago Duan             BMCWEB_LOG_ERROR << "The SNMP client ID is wrong";
218*3d30708fSChicago Duan             messages::internalError(asyncResp->res);
219*3d30708fSChicago Duan             return;
220*3d30708fSChicago Duan         }
221*3d30708fSChicago Duan 
222*3d30708fSChicago Duan         getSnmpSubscriptionList(asyncResp, snmpId, memberArray);
223*3d30708fSChicago Duan     }
224*3d30708fSChicago Duan }
225*3d30708fSChicago Duan 
2267e860f15SJohn Edward Broadbent inline void requestRoutesEventDestinationCollection(App& app)
227e5aaf047SAppaRao Puli {
2281ebe3e41SGayathri Leburu     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
229ed398213SEd Tanous         .privileges(redfish::privileges::getEventDestinationCollection)
2307e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
23145ca1b86SEd Tanous             [&app](const crow::Request& req,
2327e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2333ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
23445ca1b86SEd Tanous         {
23545ca1b86SEd Tanous             return;
23645ca1b86SEd Tanous         }
2371476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
2381476687dSEd Tanous             "#EventDestinationCollection.EventDestinationCollection";
2391476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
2401476687dSEd Tanous             "/redfish/v1/EventService/Subscriptions";
241002d39b4SEd Tanous         asyncResp->res.jsonValue["Name"] = "Event Destination Collections";
242e5aaf047SAppaRao Puli 
243002d39b4SEd Tanous         nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
244e5aaf047SAppaRao Puli 
245b52664e2SAppaRao Puli         std::vector<std::string> subscripIds =
246b52664e2SAppaRao Puli             EventServiceManager::getInstance().getAllIDs();
247b52664e2SAppaRao Puli         memberArray = nlohmann::json::array();
248002d39b4SEd Tanous         asyncResp->res.jsonValue["Members@odata.count"] = subscripIds.size();
249b52664e2SAppaRao Puli 
250b52664e2SAppaRao Puli         for (const std::string& id : subscripIds)
251e5aaf047SAppaRao Puli         {
2521476687dSEd Tanous             nlohmann::json::object_t member;
253*3d30708fSChicago Duan             member["@odata.id"] = boost::urls::format(
254*3d30708fSChicago Duan                 "/redfish/v1/EventService/Subscriptions/{}" + id);
255b2ba3072SPatrick Williams             memberArray.emplace_back(std::move(member));
256e5aaf047SAppaRao Puli         }
257*3d30708fSChicago Duan         crow::connections::systemBus->async_method_call(
258*3d30708fSChicago Duan             [asyncResp](const boost::system::error_code ec,
259*3d30708fSChicago Duan                         const dbus::utility::ManagedObjectType& resp) {
260*3d30708fSChicago Duan             doSubscriptionCollection(ec, asyncResp, resp);
261*3d30708fSChicago Duan             },
262*3d30708fSChicago Duan             "xyz.openbmc_project.Network.SNMP",
263*3d30708fSChicago Duan             "/xyz/openbmc_project/network/snmp/manager",
264*3d30708fSChicago Duan             "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
2657e860f15SJohn Edward Broadbent         });
266*3d30708fSChicago Duan 
2677e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
2687eeafa76SAbhishek Patel         .privileges(redfish::privileges::postEventDestinationCollection)
269002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
270002d39b4SEd Tanous             [&app](const crow::Request& req,
2717e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2723ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
27345ca1b86SEd Tanous         {
27445ca1b86SEd Tanous             return;
27545ca1b86SEd Tanous         }
276fffb8c1fSEd Tanous         if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
277fffb8c1fSEd Tanous             maxNoOfSubscriptions)
278e5aaf047SAppaRao Puli         {
279e5aaf047SAppaRao Puli             messages::eventSubscriptionLimitExceeded(asyncResp->res);
280e5aaf047SAppaRao Puli             return;
281e5aaf047SAppaRao Puli         }
282e5aaf047SAppaRao Puli         std::string destUrl;
283e5aaf047SAppaRao Puli         std::string protocol;
284e5aaf047SAppaRao Puli         std::optional<std::string> context;
285e5aaf047SAppaRao Puli         std::optional<std::string> subscriptionType;
28623a21a1cSEd Tanous         std::optional<std::string> eventFormatType2;
287e5aaf047SAppaRao Puli         std::optional<std::string> retryPolicy;
288e5aaf047SAppaRao Puli         std::optional<std::vector<std::string>> msgIds;
289e5aaf047SAppaRao Puli         std::optional<std::vector<std::string>> regPrefixes;
290e56f254cSSunitha Harish         std::optional<std::vector<std::string>> resTypes;
291e5aaf047SAppaRao Puli         std::optional<std::vector<nlohmann::json>> headers;
292144b6318SAppaRao Puli         std::optional<std::vector<nlohmann::json>> mrdJsonArray;
293e5aaf047SAppaRao Puli 
29415ed6780SWilly Tu         if (!json_util::readJsonPatch(
295002d39b4SEd Tanous                 req, asyncResp->res, "Destination", destUrl, "Context", context,
296002d39b4SEd Tanous                 "Protocol", protocol, "SubscriptionType", subscriptionType,
297002d39b4SEd Tanous                 "EventFormatType", eventFormatType2, "HttpHeaders", headers,
298002d39b4SEd Tanous                 "RegistryPrefixes", regPrefixes, "MessageIds", msgIds,
299002d39b4SEd Tanous                 "DeliveryRetryPolicy", retryPolicy, "MetricReportDefinitions",
300002d39b4SEd Tanous                 mrdJsonArray, "ResourceTypes", resTypes))
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 
324eb1c47d3SEd Tanous         std::string host;
325eb1c47d3SEd Tanous         std::string urlProto;
326eb1c47d3SEd Tanous         uint16_t port = 0;
327eb1c47d3SEd Tanous         std::string path;
328eb1c47d3SEd Tanous 
329002d39b4SEd Tanous         if (!crow::utility::validateAndSplitUrl(destUrl, urlProto, host, port,
330002d39b4SEd Tanous                                                 path))
331e5aaf047SAppaRao Puli         {
332eb1c47d3SEd Tanous             BMCWEB_LOG_WARNING
333eb1c47d3SEd Tanous                 << "Failed to validate and split destination url";
334e5aaf047SAppaRao Puli             messages::propertyValueFormatError(asyncResp->res, destUrl,
335e5aaf047SAppaRao Puli                                                "Destination");
336e5aaf047SAppaRao Puli             return;
337e5aaf047SAppaRao Puli         }
338b52664e2SAppaRao Puli 
339*3d30708fSChicago Duan         if (protocol == "SNMPv2c")
340*3d30708fSChicago Duan         {
341*3d30708fSChicago Duan             if (context)
342*3d30708fSChicago Duan             {
343*3d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "Context",
344*3d30708fSChicago Duan                                                 "Protocol");
345*3d30708fSChicago Duan                 return;
346*3d30708fSChicago Duan             }
347*3d30708fSChicago Duan             if (eventFormatType2)
348*3d30708fSChicago Duan             {
349*3d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res,
350*3d30708fSChicago Duan                                                 "EventFormatType", "Protocol");
351*3d30708fSChicago Duan                 return;
352*3d30708fSChicago Duan             }
353*3d30708fSChicago Duan             if (retryPolicy)
354*3d30708fSChicago Duan             {
355*3d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "RetryPolicy",
356*3d30708fSChicago Duan                                                 "Protocol");
357*3d30708fSChicago Duan                 return;
358*3d30708fSChicago Duan             }
359*3d30708fSChicago Duan             if (msgIds)
360*3d30708fSChicago Duan             {
361*3d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "MessageIds",
362*3d30708fSChicago Duan                                                 "Protocol");
363*3d30708fSChicago Duan                 return;
364*3d30708fSChicago Duan             }
365*3d30708fSChicago Duan             if (regPrefixes)
366*3d30708fSChicago Duan             {
367*3d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res,
368*3d30708fSChicago Duan                                                 "RegistryPrefixes", "Protocol");
369*3d30708fSChicago Duan                 return;
370*3d30708fSChicago Duan             }
371*3d30708fSChicago Duan             if (resTypes)
372*3d30708fSChicago Duan             {
373*3d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "ResourceTypes",
374*3d30708fSChicago Duan                                                 "Protocol");
375*3d30708fSChicago Duan                 return;
376*3d30708fSChicago Duan             }
377*3d30708fSChicago Duan             if (headers)
378*3d30708fSChicago Duan             {
379*3d30708fSChicago Duan                 messages::propertyValueConflict(asyncResp->res, "HttpHeaders",
380*3d30708fSChicago Duan                                                 "Protocol");
381*3d30708fSChicago Duan                 return;
382*3d30708fSChicago Duan             }
383*3d30708fSChicago Duan             if (mrdJsonArray)
384*3d30708fSChicago Duan             {
385*3d30708fSChicago Duan                 messages::propertyValueConflict(
386*3d30708fSChicago Duan                     asyncResp->res, "MetricReportDefinitions", "Protocol");
387*3d30708fSChicago Duan                 return;
388*3d30708fSChicago Duan             }
389*3d30708fSChicago Duan 
390*3d30708fSChicago Duan             addSnmpTrapClient(asyncResp, host, port);
391*3d30708fSChicago Duan             return;
392*3d30708fSChicago Duan         }
393*3d30708fSChicago Duan 
394b52664e2SAppaRao Puli         if (path.empty())
395b52664e2SAppaRao Puli         {
396b52664e2SAppaRao Puli             path = "/";
397b52664e2SAppaRao Puli         }
398*3d30708fSChicago Duan 
399f8ca6d79SEd Tanous         std::shared_ptr<Subscription> subValue = std::make_shared<Subscription>(
400f8ca6d79SEd Tanous             host, port, path, urlProto, app.ioContext());
401b52664e2SAppaRao Puli 
402b52664e2SAppaRao Puli         subValue->destinationUrl = destUrl;
403e5aaf047SAppaRao Puli 
404e5aaf047SAppaRao Puli         if (subscriptionType)
405e5aaf047SAppaRao Puli         {
406e5aaf047SAppaRao Puli             if (*subscriptionType != "RedfishEvent")
407e5aaf047SAppaRao Puli             {
408fffb8c1fSEd Tanous                 messages::propertyValueNotInList(
409fffb8c1fSEd Tanous                     asyncResp->res, *subscriptionType, "SubscriptionType");
410e5aaf047SAppaRao Puli                 return;
411e5aaf047SAppaRao Puli             }
412b52664e2SAppaRao Puli             subValue->subscriptionType = *subscriptionType;
413e5aaf047SAppaRao Puli         }
414e5aaf047SAppaRao Puli         else
415e5aaf047SAppaRao Puli         {
416b52664e2SAppaRao Puli             subValue->subscriptionType = "RedfishEvent"; // Default
417e5aaf047SAppaRao Puli         }
418e5aaf047SAppaRao Puli 
419e5aaf047SAppaRao Puli         if (protocol != "Redfish")
420e5aaf047SAppaRao Puli         {
421e5aaf047SAppaRao Puli             messages::propertyValueNotInList(asyncResp->res, protocol,
422e5aaf047SAppaRao Puli                                              "Protocol");
423e5aaf047SAppaRao Puli             return;
424e5aaf047SAppaRao Puli         }
425b52664e2SAppaRao Puli         subValue->protocol = protocol;
426e5aaf047SAppaRao Puli 
42723a21a1cSEd Tanous         if (eventFormatType2)
428e5aaf047SAppaRao Puli         {
429e5aaf047SAppaRao Puli             if (std::find(supportedEvtFormatTypes.begin(),
430e5aaf047SAppaRao Puli                           supportedEvtFormatTypes.end(),
431002d39b4SEd Tanous                           *eventFormatType2) == supportedEvtFormatTypes.end())
432e5aaf047SAppaRao Puli             {
433fffb8c1fSEd Tanous                 messages::propertyValueNotInList(
434fffb8c1fSEd Tanous                     asyncResp->res, *eventFormatType2, "EventFormatType");
435e5aaf047SAppaRao Puli                 return;
436e5aaf047SAppaRao Puli             }
43723a21a1cSEd Tanous             subValue->eventFormatType = *eventFormatType2;
438e5aaf047SAppaRao Puli         }
439e5aaf047SAppaRao Puli         else
440e5aaf047SAppaRao Puli         {
441e5aaf047SAppaRao Puli             // If not specified, use default "Event"
44223a21a1cSEd Tanous             subValue->eventFormatType = "Event";
443e5aaf047SAppaRao Puli         }
444e5aaf047SAppaRao Puli 
445e5aaf047SAppaRao Puli         if (context)
446e5aaf047SAppaRao Puli         {
447600af5f1SAppaRao Puli             // This value is selected aribitrarily.
448600af5f1SAppaRao Puli             constexpr const size_t maxContextSize = 256;
449600af5f1SAppaRao Puli             if (context->size() > maxContextSize)
450600af5f1SAppaRao Puli             {
451600af5f1SAppaRao Puli                 messages::stringValueTooLong(asyncResp->res, "Context",
452600af5f1SAppaRao Puli                                              maxContextSize);
453600af5f1SAppaRao Puli                 return;
454600af5f1SAppaRao Puli             }
455b52664e2SAppaRao Puli             subValue->customText = *context;
456e5aaf047SAppaRao Puli         }
457e5aaf047SAppaRao Puli 
458e5aaf047SAppaRao Puli         if (headers)
459e5aaf047SAppaRao Puli         {
460600af5f1SAppaRao Puli             size_t cumulativeLen = 0;
461600af5f1SAppaRao Puli 
462601c71aeSEd Tanous             for (const nlohmann::json& headerChunk : *headers)
463601c71aeSEd Tanous             {
464600af5f1SAppaRao Puli                 std::string hdr{headerChunk.dump(
465600af5f1SAppaRao Puli                     -1, ' ', true, nlohmann::json::error_handler_t::replace)};
466600af5f1SAppaRao Puli                 cumulativeLen += hdr.length();
467600af5f1SAppaRao Puli 
468600af5f1SAppaRao Puli                 // This value is selected to mirror http_connection.hpp
469600af5f1SAppaRao Puli                 constexpr const uint16_t maxHeaderSizeED = 8096;
470600af5f1SAppaRao Puli                 if (cumulativeLen > maxHeaderSizeED)
471600af5f1SAppaRao Puli                 {
472600af5f1SAppaRao Puli                     messages::arraySizeTooLong(asyncResp->res, "HttpHeaders",
473600af5f1SAppaRao Puli                                                maxHeaderSizeED);
474600af5f1SAppaRao Puli                     return;
475600af5f1SAppaRao Puli                 }
476601c71aeSEd Tanous                 for (const auto& item : headerChunk.items())
477601c71aeSEd Tanous                 {
478601c71aeSEd Tanous                     const std::string* value =
479601c71aeSEd Tanous                         item.value().get_ptr<const std::string*>();
480601c71aeSEd Tanous                     if (value == nullptr)
481601c71aeSEd Tanous                     {
482601c71aeSEd Tanous                         messages::propertyValueFormatError(
483f818b04dSEd Tanous                             asyncResp->res, item.value(),
484601c71aeSEd Tanous                             "HttpHeaders/" + item.key());
485601c71aeSEd Tanous                         return;
486601c71aeSEd Tanous                     }
487601c71aeSEd Tanous                     subValue->httpHeaders.set(item.key(), *value);
488601c71aeSEd Tanous                 }
489601c71aeSEd Tanous             }
490e5aaf047SAppaRao Puli         }
491e5aaf047SAppaRao Puli 
492e5aaf047SAppaRao Puli         if (regPrefixes)
493e5aaf047SAppaRao Puli         {
494e5aaf047SAppaRao Puli             for (const std::string& it : *regPrefixes)
495e5aaf047SAppaRao Puli             {
496e5aaf047SAppaRao Puli                 if (std::find(supportedRegPrefixes.begin(),
497e5aaf047SAppaRao Puli                               supportedRegPrefixes.end(),
498e5aaf047SAppaRao Puli                               it) == supportedRegPrefixes.end())
499e5aaf047SAppaRao Puli                 {
500fffb8c1fSEd Tanous                     messages::propertyValueNotInList(asyncResp->res, it,
501fffb8c1fSEd Tanous                                                      "RegistryPrefixes");
502e5aaf047SAppaRao Puli                     return;
503e5aaf047SAppaRao Puli                 }
504e5aaf047SAppaRao Puli             }
505b52664e2SAppaRao Puli             subValue->registryPrefixes = *regPrefixes;
506e5aaf047SAppaRao Puli         }
507e5aaf047SAppaRao Puli 
508e56f254cSSunitha Harish         if (resTypes)
509e56f254cSSunitha Harish         {
510e56f254cSSunitha Harish             for (const std::string& it : *resTypes)
511e56f254cSSunitha Harish             {
512e56f254cSSunitha Harish                 if (std::find(supportedResourceTypes.begin(),
513e56f254cSSunitha Harish                               supportedResourceTypes.end(),
514e56f254cSSunitha Harish                               it) == supportedResourceTypes.end())
515e56f254cSSunitha Harish                 {
516e56f254cSSunitha Harish                     messages::propertyValueNotInList(asyncResp->res, it,
517e56f254cSSunitha Harish                                                      "ResourceTypes");
518e56f254cSSunitha Harish                     return;
519e56f254cSSunitha Harish                 }
520e56f254cSSunitha Harish             }
521e56f254cSSunitha Harish             subValue->resourceTypes = *resTypes;
522e56f254cSSunitha Harish         }
523e56f254cSSunitha Harish 
524e5aaf047SAppaRao Puli         if (msgIds)
525e5aaf047SAppaRao Puli         {
526b304bd79SP Dheeraj Srujan Kumar             std::vector<std::string> registryPrefix;
527b304bd79SP Dheeraj Srujan Kumar 
5287e860f15SJohn Edward Broadbent             // If no registry prefixes are mentioned, consider all
5297e860f15SJohn Edward Broadbent             // supported prefixes
530b304bd79SP Dheeraj Srujan Kumar             if (subValue->registryPrefixes.empty())
531b304bd79SP Dheeraj Srujan Kumar             {
532b304bd79SP Dheeraj Srujan Kumar                 registryPrefix.assign(supportedRegPrefixes.begin(),
533b304bd79SP Dheeraj Srujan Kumar                                       supportedRegPrefixes.end());
534b304bd79SP Dheeraj Srujan Kumar             }
535b304bd79SP Dheeraj Srujan Kumar             else
536b304bd79SP Dheeraj Srujan Kumar             {
537b304bd79SP Dheeraj Srujan Kumar                 registryPrefix = subValue->registryPrefixes;
538b304bd79SP Dheeraj Srujan Kumar             }
539b304bd79SP Dheeraj Srujan Kumar 
540b304bd79SP Dheeraj Srujan Kumar             for (const std::string& id : *msgIds)
541b304bd79SP Dheeraj Srujan Kumar             {
542b304bd79SP Dheeraj Srujan Kumar                 bool validId = false;
543b304bd79SP Dheeraj Srujan Kumar 
544b304bd79SP Dheeraj Srujan Kumar                 // Check for Message ID in each of the selected Registry
545b304bd79SP Dheeraj Srujan Kumar                 for (const std::string& it : registryPrefix)
546b304bd79SP Dheeraj Srujan Kumar                 {
547fffb8c1fSEd Tanous                     const std::span<const redfish::registries::MessageEntry>
548fffb8c1fSEd Tanous                         registry =
549fffb8c1fSEd Tanous                             redfish::registries::getRegistryFromPrefix(it);
550b304bd79SP Dheeraj Srujan Kumar 
551b304bd79SP Dheeraj Srujan Kumar                     if (std::any_of(
55226702d01SEd Tanous                             registry.begin(), registry.end(),
553fffb8c1fSEd Tanous                             [&id](const redfish::registries::MessageEntry&
554fffb8c1fSEd Tanous                                       messageEntry) {
55555f79e6fSEd Tanous                         return id == messageEntry.first;
556b304bd79SP Dheeraj Srujan Kumar                             }))
557b304bd79SP Dheeraj Srujan Kumar                     {
558b304bd79SP Dheeraj Srujan Kumar                         validId = true;
559b304bd79SP Dheeraj Srujan Kumar                         break;
560b304bd79SP Dheeraj Srujan Kumar                     }
561b304bd79SP Dheeraj Srujan Kumar                 }
562b304bd79SP Dheeraj Srujan Kumar 
563b304bd79SP Dheeraj Srujan Kumar                 if (!validId)
564b304bd79SP Dheeraj Srujan Kumar                 {
565b304bd79SP Dheeraj Srujan Kumar                     messages::propertyValueNotInList(asyncResp->res, id,
566b304bd79SP Dheeraj Srujan Kumar                                                      "MessageIds");
567b304bd79SP Dheeraj Srujan Kumar                     return;
568b304bd79SP Dheeraj Srujan Kumar                 }
569b304bd79SP Dheeraj Srujan Kumar             }
570b304bd79SP Dheeraj Srujan Kumar 
571b52664e2SAppaRao Puli             subValue->registryMsgIds = *msgIds;
572e5aaf047SAppaRao Puli         }
573e5aaf047SAppaRao Puli 
574e5aaf047SAppaRao Puli         if (retryPolicy)
575e5aaf047SAppaRao Puli         {
576e5aaf047SAppaRao Puli             if (std::find(supportedRetryPolicies.begin(),
577e5aaf047SAppaRao Puli                           supportedRetryPolicies.end(),
578e5aaf047SAppaRao Puli                           *retryPolicy) == supportedRetryPolicies.end())
579e5aaf047SAppaRao Puli             {
580002d39b4SEd Tanous                 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
581002d39b4SEd Tanous                                                  "DeliveryRetryPolicy");
582e5aaf047SAppaRao Puli                 return;
583e5aaf047SAppaRao Puli             }
584b52664e2SAppaRao Puli             subValue->retryPolicy = *retryPolicy;
585e5aaf047SAppaRao Puli         }
586e5aaf047SAppaRao Puli         else
587e5aaf047SAppaRao Puli         {
588e5aaf047SAppaRao Puli             // Default "TerminateAfterRetries"
589b52664e2SAppaRao Puli             subValue->retryPolicy = "TerminateAfterRetries";
590e5aaf047SAppaRao Puli         }
591e5aaf047SAppaRao Puli 
592144b6318SAppaRao Puli         if (mrdJsonArray)
593156d6b00SAppaRao Puli         {
594144b6318SAppaRao Puli             for (nlohmann::json& mrdObj : *mrdJsonArray)
595144b6318SAppaRao Puli             {
596144b6318SAppaRao Puli                 std::string mrdUri;
597ea2e6eecSWilly Tu 
598002d39b4SEd Tanous                 if (!json_util::readJson(mrdObj, asyncResp->res, "@odata.id",
599002d39b4SEd Tanous                                          mrdUri))
600ea2e6eecSWilly Tu 
601144b6318SAppaRao Puli                 {
602144b6318SAppaRao Puli                     return;
603144b6318SAppaRao Puli                 }
604ea2e6eecSWilly Tu                 subValue->metricReportDefinitions.emplace_back(mrdUri);
605144b6318SAppaRao Puli             }
606156d6b00SAppaRao Puli         }
607156d6b00SAppaRao Puli 
608b52664e2SAppaRao Puli         std::string id =
609fffb8c1fSEd Tanous             EventServiceManager::getInstance().addSubscription(subValue);
610b52664e2SAppaRao Puli         if (id.empty())
611e5aaf047SAppaRao Puli         {
612e5aaf047SAppaRao Puli             messages::internalError(asyncResp->res);
613e5aaf047SAppaRao Puli             return;
614e5aaf047SAppaRao Puli         }
615e5aaf047SAppaRao Puli 
616e5aaf047SAppaRao Puli         messages::created(asyncResp->res);
617e5aaf047SAppaRao Puli         asyncResp->res.addHeader(
618e5aaf047SAppaRao Puli             "Location", "/redfish/v1/EventService/Subscriptions/" + id);
6197e860f15SJohn Edward Broadbent         });
620e5aaf047SAppaRao Puli }
621e5aaf047SAppaRao Puli 
6227e860f15SJohn Edward Broadbent inline void requestRoutesEventDestination(App& app)
623e5aaf047SAppaRao Puli {
6249d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
625ed398213SEd Tanous         .privileges(redfish::privileges::getEventDestination)
6267e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
62745ca1b86SEd Tanous             [&app](const crow::Request& req,
6287e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
6297e860f15SJohn Edward Broadbent                    const std::string& param) {
6303ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
63145ca1b86SEd Tanous         {
63245ca1b86SEd Tanous             return;
63345ca1b86SEd Tanous         }
634*3d30708fSChicago Duan 
635*3d30708fSChicago Duan         if (param.starts_with("snmp"))
636*3d30708fSChicago Duan         {
637*3d30708fSChicago Duan             getSnmpTrapClient(asyncResp, param);
638*3d30708fSChicago Duan             return;
639*3d30708fSChicago Duan         }
640*3d30708fSChicago Duan 
641b52664e2SAppaRao Puli         std::shared_ptr<Subscription> subValue =
6427e860f15SJohn Edward Broadbent             EventServiceManager::getInstance().getSubscription(param);
643b52664e2SAppaRao Puli         if (subValue == nullptr)
644e5aaf047SAppaRao Puli         {
645002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::not_found);
646e5aaf047SAppaRao Puli             return;
647e5aaf047SAppaRao Puli         }
6487e860f15SJohn Edward Broadbent         const std::string& id = param;
649e5aaf047SAppaRao Puli 
6501476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
651*3d30708fSChicago Duan             "#EventDestination.v1_8_0.EventDestination";
6521476687dSEd Tanous         asyncResp->res.jsonValue["Protocol"] = "Redfish";
653e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["@odata.id"] =
654e5aaf047SAppaRao Puli             "/redfish/v1/EventService/Subscriptions/" + id;
655e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["Id"] = id;
656e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
657002d39b4SEd Tanous         asyncResp->res.jsonValue["Destination"] = subValue->destinationUrl;
658b52664e2SAppaRao Puli         asyncResp->res.jsonValue["Context"] = subValue->customText;
659e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["SubscriptionType"] =
660b52664e2SAppaRao Puli             subValue->subscriptionType;
661002d39b4SEd Tanous         asyncResp->res.jsonValue["HttpHeaders"] = nlohmann::json::array();
662002d39b4SEd Tanous         asyncResp->res.jsonValue["EventFormatType"] = subValue->eventFormatType;
663e5aaf047SAppaRao Puli         asyncResp->res.jsonValue["RegistryPrefixes"] =
664b52664e2SAppaRao Puli             subValue->registryPrefixes;
665002d39b4SEd Tanous         asyncResp->res.jsonValue["ResourceTypes"] = subValue->resourceTypes;
666e56f254cSSunitha Harish 
667002d39b4SEd Tanous         asyncResp->res.jsonValue["MessageIds"] = subValue->registryMsgIds;
668002d39b4SEd Tanous         asyncResp->res.jsonValue["DeliveryRetryPolicy"] = subValue->retryPolicy;
669144b6318SAppaRao Puli 
6701476687dSEd Tanous         nlohmann::json::array_t mrdJsonArray;
671144b6318SAppaRao Puli         for (const auto& mdrUri : subValue->metricReportDefinitions)
672144b6318SAppaRao Puli         {
6731476687dSEd Tanous             nlohmann::json::object_t mdr;
6741476687dSEd Tanous             mdr["@odata.id"] = mdrUri;
6751476687dSEd Tanous             mrdJsonArray.emplace_back(std::move(mdr));
676144b6318SAppaRao Puli         }
677002d39b4SEd Tanous         asyncResp->res.jsonValue["MetricReportDefinitions"] = mrdJsonArray;
6787e860f15SJohn Edward Broadbent         });
6799d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
680ed398213SEd Tanous         // The below privilege is wrong, it should be ConfigureManager OR
681ed398213SEd Tanous         // ConfigureSelf
6827eeafa76SAbhishek Patel         // https://github.com/openbmc/bmcweb/issues/220
683ed398213SEd Tanous         //.privileges(redfish::privileges::patchEventDestination)
684432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
6857e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
68645ca1b86SEd Tanous             [&app](const crow::Request& req,
6877e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
6887e860f15SJohn Edward Broadbent                    const std::string& param) {
6893ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
69045ca1b86SEd Tanous         {
69145ca1b86SEd Tanous             return;
69245ca1b86SEd Tanous         }
693b52664e2SAppaRao Puli         std::shared_ptr<Subscription> subValue =
6947e860f15SJohn Edward Broadbent             EventServiceManager::getInstance().getSubscription(param);
695b52664e2SAppaRao Puli         if (subValue == nullptr)
696e5aaf047SAppaRao Puli         {
697002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::not_found);
698e5aaf047SAppaRao Puli             return;
699e5aaf047SAppaRao Puli         }
700e5aaf047SAppaRao Puli 
701e5aaf047SAppaRao Puli         std::optional<std::string> context;
702e5aaf047SAppaRao Puli         std::optional<std::string> retryPolicy;
703e5aaf047SAppaRao Puli         std::optional<std::vector<nlohmann::json>> headers;
704e5aaf047SAppaRao Puli 
705002d39b4SEd Tanous         if (!json_util::readJsonPatch(req, asyncResp->res, "Context", context,
706002d39b4SEd Tanous                                       "DeliveryRetryPolicy", retryPolicy,
707002d39b4SEd Tanous                                       "HttpHeaders", headers))
708e5aaf047SAppaRao Puli         {
709e5aaf047SAppaRao Puli             return;
710e5aaf047SAppaRao Puli         }
711e5aaf047SAppaRao Puli 
712e5aaf047SAppaRao Puli         if (context)
713e5aaf047SAppaRao Puli         {
714b52664e2SAppaRao Puli             subValue->customText = *context;
715e5aaf047SAppaRao Puli         }
716e5aaf047SAppaRao Puli 
717e5aaf047SAppaRao Puli         if (headers)
718e5aaf047SAppaRao Puli         {
719601c71aeSEd Tanous             boost::beast::http::fields fields;
720601c71aeSEd Tanous             for (const nlohmann::json& headerChunk : *headers)
721601c71aeSEd Tanous             {
72262bafc01SPatrick Williams                 for (const auto& it : headerChunk.items())
723601c71aeSEd Tanous                 {
724601c71aeSEd Tanous                     const std::string* value =
725601c71aeSEd Tanous                         it.value().get_ptr<const std::string*>();
726601c71aeSEd Tanous                     if (value == nullptr)
727601c71aeSEd Tanous                     {
728601c71aeSEd Tanous                         messages::propertyValueFormatError(
729f818b04dSEd Tanous                             asyncResp->res, it.value(),
730601c71aeSEd Tanous                             "HttpHeaders/" + it.key());
731601c71aeSEd Tanous                         return;
732601c71aeSEd Tanous                     }
733601c71aeSEd Tanous                     fields.set(it.key(), *value);
734601c71aeSEd Tanous                 }
735601c71aeSEd Tanous             }
736601c71aeSEd Tanous             subValue->httpHeaders = fields;
737e5aaf047SAppaRao Puli         }
738e5aaf047SAppaRao Puli 
739e5aaf047SAppaRao Puli         if (retryPolicy)
740e5aaf047SAppaRao Puli         {
741e5aaf047SAppaRao Puli             if (std::find(supportedRetryPolicies.begin(),
742e5aaf047SAppaRao Puli                           supportedRetryPolicies.end(),
743e5aaf047SAppaRao Puli                           *retryPolicy) == supportedRetryPolicies.end())
744e5aaf047SAppaRao Puli             {
745002d39b4SEd Tanous                 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
746e5aaf047SAppaRao Puli                                                  "DeliveryRetryPolicy");
747e5aaf047SAppaRao Puli                 return;
748e5aaf047SAppaRao Puli             }
749b52664e2SAppaRao Puli             subValue->retryPolicy = *retryPolicy;
750e5aaf047SAppaRao Puli         }
751e5aaf047SAppaRao Puli 
752b52664e2SAppaRao Puli         EventServiceManager::getInstance().updateSubscriptionData();
7537e860f15SJohn Edward Broadbent         });
7549d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
755ed398213SEd Tanous         // The below privilege is wrong, it should be ConfigureManager OR
756ed398213SEd Tanous         // ConfigureSelf
7577eeafa76SAbhishek Patel         // https://github.com/openbmc/bmcweb/issues/220
758ed398213SEd Tanous         //.privileges(redfish::privileges::deleteEventDestination)
759432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
7607e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
76145ca1b86SEd Tanous             [&app](const crow::Request& req,
7627e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7637e860f15SJohn Edward Broadbent                    const std::string& param) {
7643ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
76545ca1b86SEd Tanous         {
76645ca1b86SEd Tanous             return;
76745ca1b86SEd Tanous         }
768*3d30708fSChicago Duan 
769*3d30708fSChicago Duan         if (param.starts_with("snmp"))
770*3d30708fSChicago Duan         {
771*3d30708fSChicago Duan             deleteSnmpTrapClient(asyncResp, param);
772*3d30708fSChicago Duan             EventServiceManager::getInstance().deleteSubscription(param);
773*3d30708fSChicago Duan             return;
774*3d30708fSChicago Duan         }
775*3d30708fSChicago Duan 
776002d39b4SEd Tanous         if (!EventServiceManager::getInstance().isSubscriptionExist(param))
777e5aaf047SAppaRao Puli         {
778002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::not_found);
779e5aaf047SAppaRao Puli             return;
780e5aaf047SAppaRao Puli         }
7817e860f15SJohn Edward Broadbent         EventServiceManager::getInstance().deleteSubscription(param);
7827e860f15SJohn Edward Broadbent         });
783e5aaf047SAppaRao Puli }
784e5aaf047SAppaRao Puli 
785e5aaf047SAppaRao Puli } // namespace redfish
786