xref: /openbmc/bmcweb/features/redfish/lib/event_service.hpp (revision 5064a25bc6d64424d716652c10f4fce953e0991a)
1e5aaf047SAppaRao Puli /*
26be832e2SEd Tanous Copyright (c) 2020 Intel Corporation
36be832e2SEd Tanous 
46be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License");
56be832e2SEd Tanous you may not use this file except in compliance with the License.
66be832e2SEd Tanous You may obtain a copy of the License at
76be832e2SEd Tanous 
86be832e2SEd Tanous       http://www.apache.org/licenses/LICENSE-2.0
96be832e2SEd Tanous 
106be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software
116be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS,
126be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136be832e2SEd Tanous See the License for the specific language governing permissions and
146be832e2SEd Tanous limitations under the License.
15e5aaf047SAppaRao Puli */
16e5aaf047SAppaRao Puli #pragma once
173ccb3adbSEd Tanous #include "app.hpp"
18b52664e2SAppaRao Puli #include "event_service_manager.hpp"
19539d8c6bSEd Tanous #include "generated/enums/event_service.hpp"
203ccb3adbSEd Tanous #include "http/utility.hpp"
213ccb3adbSEd Tanous #include "logging.hpp"
223ccb3adbSEd Tanous #include "query.hpp"
23d109e2b6SAlexander Hansen #include "registries.hpp"
243ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
25d109e2b6SAlexander Hansen #include "registries_selector.hpp"
263d30708fSChicago Duan #include "snmp_trap_event_clients.hpp"
27d109e2b6SAlexander Hansen #include "utils/json_utils.hpp"
28e5aaf047SAppaRao Puli 
29601c71aeSEd Tanous #include <boost/beast/http/fields.hpp>
303d30708fSChicago Duan #include <boost/system/error_code.hpp>
31a716aa74SEd Tanous #include <boost/url/parse.hpp>
323d30708fSChicago Duan #include <sdbusplus/unpack_properties.hpp>
333d30708fSChicago Duan #include <utils/dbus_utils.hpp>
34ed398213SEd Tanous 
353d30708fSChicago Duan #include <charconv>
363d30708fSChicago Duan #include <memory>
37*5064a25bSMyung Bae #include <optional>
383544d2a7SEd Tanous #include <ranges>
391e270c5fSPatrick Williams #include <span>
403d30708fSChicago Duan #include <string>
41a14c9113SEd Tanous #include <vector>
421e270c5fSPatrick Williams 
43e5aaf047SAppaRao Puli namespace redfish
44e5aaf047SAppaRao Puli {
45e5aaf047SAppaRao Puli 
46156d6b00SAppaRao Puli static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
47156d6b00SAppaRao Puli     eventFormatType, metricReportFormatType};
48e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
49b304bd79SP Dheeraj Srujan Kumar     "Base", "OpenBMC", "TaskEvent"};
50e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
51e5aaf047SAppaRao Puli     "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
52e5aaf047SAppaRao Puli 
53e56f254cSSunitha Harish static constexpr const std::array<const char*, 1> supportedResourceTypes = {
54e56f254cSSunitha Harish     "Task"};
55e56f254cSSunitha Harish 
567e860f15SJohn Edward Broadbent inline void requestRoutesEventService(App& app)
57e5aaf047SAppaRao Puli {
587e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
59ed398213SEd Tanous         .privileges(redfish::privileges::getEventService)
60bd79bce8SPatrick Williams         .methods(
61bd79bce8SPatrick Williams             boost::beast::http::verb::
62bd79bce8SPatrick Williams                 get)([&app](
63bd79bce8SPatrick Williams                          const crow::Request& req,
64002d39b4SEd Tanous                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
653ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
6645ca1b86SEd Tanous             {
6745ca1b86SEd Tanous                 return;
6845ca1b86SEd Tanous             }
691476687dSEd Tanous 
701476687dSEd Tanous             asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/EventService";
711476687dSEd Tanous             asyncResp->res.jsonValue["@odata.type"] =
721476687dSEd Tanous                 "#EventService.v1_5_0.EventService";
731476687dSEd Tanous             asyncResp->res.jsonValue["Id"] = "EventService";
741476687dSEd Tanous             asyncResp->res.jsonValue["Name"] = "Event Service";
755e44e3d8SAppaRao Puli             asyncResp->res.jsonValue["ServerSentEventUri"] =
765e44e3d8SAppaRao Puli                 "/redfish/v1/EventService/SSE";
775e44e3d8SAppaRao Puli 
781476687dSEd Tanous             asyncResp->res.jsonValue["Subscriptions"]["@odata.id"] =
791476687dSEd Tanous                 "/redfish/v1/EventService/Subscriptions";
80bd79bce8SPatrick Williams             asyncResp->res.jsonValue["Actions"]["#EventService.SubmitTestEvent"]
81bd79bce8SPatrick Williams                                     ["target"] =
821476687dSEd Tanous                 "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent";
83e5aaf047SAppaRao Puli 
8428afb49cSJunLin Chen             const persistent_data::EventServiceConfig eventServiceConfig =
8528afb49cSJunLin Chen                 persistent_data::EventServiceStore::getInstance()
8628afb49cSJunLin Chen                     .getEventServiceConfig();
877d1cc387SAppaRao Puli 
887d1cc387SAppaRao Puli             asyncResp->res.jsonValue["Status"]["State"] =
8928afb49cSJunLin Chen                 (eventServiceConfig.enabled ? "Enabled" : "Disabled");
90bd79bce8SPatrick Williams             asyncResp->res.jsonValue["ServiceEnabled"] =
91bd79bce8SPatrick Williams                 eventServiceConfig.enabled;
927e860f15SJohn Edward Broadbent             asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
9328afb49cSJunLin Chen                 eventServiceConfig.retryAttempts;
94e5aaf047SAppaRao Puli             asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
9528afb49cSJunLin Chen                 eventServiceConfig.retryTimeoutInterval;
96bd79bce8SPatrick Williams             asyncResp->res.jsonValue["EventFormatTypes"] =
97bd79bce8SPatrick Williams                 supportedEvtFormatTypes;
980fda0f12SGeorge Liu             asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
990fda0f12SGeorge Liu             asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
10007941a88SAyushi Smriti 
101613dabeaSEd Tanous             nlohmann::json::object_t supportedSSEFilters;
102613dabeaSEd Tanous             supportedSSEFilters["EventFormatType"] = true;
103613dabeaSEd Tanous             supportedSSEFilters["MessageId"] = true;
104613dabeaSEd Tanous             supportedSSEFilters["MetricReportDefinition"] = true;
105613dabeaSEd Tanous             supportedSSEFilters["RegistryPrefix"] = true;
106613dabeaSEd Tanous             supportedSSEFilters["OriginResource"] = false;
107613dabeaSEd Tanous             supportedSSEFilters["ResourceType"] = false;
10807941a88SAyushi Smriti 
10907941a88SAyushi Smriti             asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
110613dabeaSEd Tanous                 std::move(supportedSSEFilters);
1117e860f15SJohn Edward Broadbent         });
112e5aaf047SAppaRao Puli 
1137e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
114ed398213SEd Tanous         .privileges(redfish::privileges::patchEventService)
1157e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
11645ca1b86SEd Tanous             [&app](const crow::Request& req,
11745ca1b86SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1183ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
119e5aaf047SAppaRao Puli                 {
12045ca1b86SEd Tanous                     return;
12145ca1b86SEd Tanous                 }
122e5aaf047SAppaRao Puli                 std::optional<bool> serviceEnabled;
123e5aaf047SAppaRao Puli                 std::optional<uint32_t> retryAttemps;
124e5aaf047SAppaRao Puli                 std::optional<uint32_t> retryInterval;
125afc474aeSMyung Bae                 if (!json_util::readJsonPatch( //
126afc474aeSMyung Bae                         req, asyncResp->res, //
127afc474aeSMyung Bae                         "DeliveryRetryAttempts", retryAttemps, //
128afc474aeSMyung Bae                         "DeliveryRetryIntervalSeconds", retryInterval, //
129afc474aeSMyung Bae                         "ServiceEnabled", serviceEnabled //
130afc474aeSMyung Bae                         ))
131e5aaf047SAppaRao Puli                 {
132e5aaf047SAppaRao Puli                     return;
133e5aaf047SAppaRao Puli                 }
134e5aaf047SAppaRao Puli 
13528afb49cSJunLin Chen                 persistent_data::EventServiceConfig eventServiceConfig =
13628afb49cSJunLin Chen                     persistent_data::EventServiceStore::getInstance()
13728afb49cSJunLin Chen                         .getEventServiceConfig();
1387d1cc387SAppaRao Puli 
139e5aaf047SAppaRao Puli                 if (serviceEnabled)
140e5aaf047SAppaRao Puli                 {
14128afb49cSJunLin Chen                     eventServiceConfig.enabled = *serviceEnabled;
142e5aaf047SAppaRao Puli                 }
143e5aaf047SAppaRao Puli 
144e5aaf047SAppaRao Puli                 if (retryAttemps)
145e5aaf047SAppaRao Puli                 {
146e5aaf047SAppaRao Puli                     // Supported range [1-3]
147e5aaf047SAppaRao Puli                     if ((*retryAttemps < 1) || (*retryAttemps > 3))
148e5aaf047SAppaRao Puli                     {
149e5aaf047SAppaRao Puli                         messages::queryParameterOutOfRange(
150e5aaf047SAppaRao Puli                             asyncResp->res, std::to_string(*retryAttemps),
151e5aaf047SAppaRao Puli                             "DeliveryRetryAttempts", "[1-3]");
152e5aaf047SAppaRao Puli                     }
153e5aaf047SAppaRao Puli                     else
154e5aaf047SAppaRao Puli                     {
15528afb49cSJunLin Chen                         eventServiceConfig.retryAttempts = *retryAttemps;
156e5aaf047SAppaRao Puli                     }
157e5aaf047SAppaRao Puli                 }
158e5aaf047SAppaRao Puli 
159e5aaf047SAppaRao Puli                 if (retryInterval)
160e5aaf047SAppaRao Puli                 {
16133a32b34SGunnar Mills                     // Supported range [5 - 180]
16233a32b34SGunnar Mills                     if ((*retryInterval < 5) || (*retryInterval > 180))
163e5aaf047SAppaRao Puli                     {
164e5aaf047SAppaRao Puli                         messages::queryParameterOutOfRange(
165e5aaf047SAppaRao Puli                             asyncResp->res, std::to_string(*retryInterval),
16633a32b34SGunnar Mills                             "DeliveryRetryIntervalSeconds", "[5-180]");
167e5aaf047SAppaRao Puli                     }
168e5aaf047SAppaRao Puli                     else
169e5aaf047SAppaRao Puli                     {
170bd79bce8SPatrick Williams                         eventServiceConfig.retryTimeoutInterval =
171bd79bce8SPatrick Williams                             *retryInterval;
172e5aaf047SAppaRao Puli                     }
173e5aaf047SAppaRao Puli                 }
174e5aaf047SAppaRao Puli 
1757d1cc387SAppaRao Puli                 EventServiceManager::getInstance().setEventServiceConfig(
17628afb49cSJunLin Chen                     eventServiceConfig);
1777e860f15SJohn Edward Broadbent             });
1780b4bdd93SAppaRao Puli }
1790b4bdd93SAppaRao Puli 
1807e860f15SJohn Edward Broadbent inline void requestRoutesSubmitTestEvent(App& app)
1810b4bdd93SAppaRao Puli {
1827e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
1837e860f15SJohn Edward Broadbent         app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
184ed398213SEd Tanous         .privileges(redfish::privileges::postEventService)
1857e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
18645ca1b86SEd Tanous             [&app](const crow::Request& req,
1877e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1883ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
18945ca1b86SEd Tanous                 {
19045ca1b86SEd Tanous                     return;
19145ca1b86SEd Tanous                 }
1926ba8c82eSsunharis_in                 if (!EventServiceManager::getInstance().sendTestEventLog())
1936ba8c82eSsunharis_in                 {
1946ba8c82eSsunharis_in                     messages::serviceDisabled(asyncResp->res,
1956ba8c82eSsunharis_in                                               "/redfish/v1/EventService/");
1966ba8c82eSsunharis_in                     return;
1976ba8c82eSsunharis_in                 }
1988d1b46d7Szhanghch05                 asyncResp->res.result(boost::beast::http::status::no_content);
1997e860f15SJohn Edward Broadbent             });
200e5aaf047SAppaRao Puli }
201e5aaf047SAppaRao Puli 
2023d30708fSChicago Duan inline void doSubscriptionCollection(
203e81de512SEd Tanous     const boost::system::error_code& ec,
2043d30708fSChicago Duan     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2053d30708fSChicago Duan     const dbus::utility::ManagedObjectType& resp)
2063d30708fSChicago Duan {
2073d30708fSChicago Duan     if (ec)
2083d30708fSChicago Duan     {
2091306101eSEd Tanous         if (ec.value() == EBADR || ec.value() == EHOSTUNREACH)
2103d30708fSChicago Duan         {
2113d30708fSChicago Duan             // This is an optional process so just return if it isn't there
2123d30708fSChicago Duan             return;
2133d30708fSChicago Duan         }
2143d30708fSChicago Duan 
21562598e31SEd Tanous         BMCWEB_LOG_ERROR("D-Bus response error on GetManagedObjects {}", ec);
2163d30708fSChicago Duan         messages::internalError(asyncResp->res);
2173d30708fSChicago Duan         return;
2183d30708fSChicago Duan     }
2193d30708fSChicago Duan     nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
2203d30708fSChicago Duan     for (const auto& objpath : resp)
2213d30708fSChicago Duan     {
2223d30708fSChicago Duan         sdbusplus::message::object_path path(objpath.first);
2233d30708fSChicago Duan         const std::string snmpId = path.filename();
2243d30708fSChicago Duan         if (snmpId.empty())
2253d30708fSChicago Duan         {
22662598e31SEd Tanous             BMCWEB_LOG_ERROR("The SNMP client ID is wrong");
2273d30708fSChicago Duan             messages::internalError(asyncResp->res);
2283d30708fSChicago Duan             return;
2293d30708fSChicago Duan         }
2303d30708fSChicago Duan 
2313d30708fSChicago Duan         getSnmpSubscriptionList(asyncResp, snmpId, memberArray);
2323d30708fSChicago Duan     }
2333d30708fSChicago Duan }
2343d30708fSChicago Duan 
2357e860f15SJohn Edward Broadbent inline void requestRoutesEventDestinationCollection(App& app)
236e5aaf047SAppaRao Puli {
2371ebe3e41SGayathri Leburu     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
238ed398213SEd Tanous         .privileges(redfish::privileges::getEventDestinationCollection)
2397e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
24045ca1b86SEd Tanous             [&app](const crow::Request& req,
2417e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2423ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
24345ca1b86SEd Tanous                 {
24445ca1b86SEd Tanous                     return;
24545ca1b86SEd Tanous                 }
2461476687dSEd Tanous                 asyncResp->res.jsonValue["@odata.type"] =
2471476687dSEd Tanous                     "#EventDestinationCollection.EventDestinationCollection";
2481476687dSEd Tanous                 asyncResp->res.jsonValue["@odata.id"] =
2491476687dSEd Tanous                     "/redfish/v1/EventService/Subscriptions";
250bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["Name"] =
251bd79bce8SPatrick Williams                     "Event Destination Collections";
252e5aaf047SAppaRao Puli 
253bd79bce8SPatrick Williams                 nlohmann::json& memberArray =
254bd79bce8SPatrick Williams                     asyncResp->res.jsonValue["Members"];
255e5aaf047SAppaRao Puli 
256b52664e2SAppaRao Puli                 std::vector<std::string> subscripIds =
257b52664e2SAppaRao Puli                     EventServiceManager::getInstance().getAllIDs();
258b52664e2SAppaRao Puli                 memberArray = nlohmann::json::array();
259bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["Members@odata.count"] =
260bd79bce8SPatrick Williams                     subscripIds.size();
261b52664e2SAppaRao Puli 
262b52664e2SAppaRao Puli                 for (const std::string& id : subscripIds)
263e5aaf047SAppaRao Puli                 {
2641476687dSEd Tanous                     nlohmann::json::object_t member;
2653d30708fSChicago Duan                     member["@odata.id"] = boost::urls::format(
2663d30708fSChicago Duan                         "/redfish/v1/EventService/Subscriptions/{}" + id);
267b2ba3072SPatrick Williams                     memberArray.emplace_back(std::move(member));
268e5aaf047SAppaRao Puli                 }
2693d30708fSChicago Duan                 crow::connections::systemBus->async_method_call(
270e81de512SEd Tanous                     [asyncResp](const boost::system::error_code& ec,
2713d30708fSChicago Duan                                 const dbus::utility::ManagedObjectType& resp) {
2723d30708fSChicago Duan                         doSubscriptionCollection(ec, asyncResp, resp);
2733d30708fSChicago Duan                     },
2743d30708fSChicago Duan                     "xyz.openbmc_project.Network.SNMP",
2753d30708fSChicago Duan                     "/xyz/openbmc_project/network/snmp/manager",
2763d30708fSChicago Duan                     "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
2777e860f15SJohn Edward Broadbent             });
2783d30708fSChicago Duan 
2797e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
2807eeafa76SAbhishek Patel         .privileges(redfish::privileges::postEventDestinationCollection)
281bd79bce8SPatrick Williams         .methods(
282bd79bce8SPatrick Williams             boost::beast::http::verb::
283bd79bce8SPatrick Williams                 post)([&app](
284bd79bce8SPatrick Williams                           const crow::Request& req,
2857e860f15SJohn Edward Broadbent                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2863ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
28745ca1b86SEd Tanous             {
28845ca1b86SEd Tanous                 return;
28945ca1b86SEd Tanous             }
290fffb8c1fSEd Tanous             if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
291fffb8c1fSEd Tanous                 maxNoOfSubscriptions)
292e5aaf047SAppaRao Puli             {
293e5aaf047SAppaRao Puli                 messages::eventSubscriptionLimitExceeded(asyncResp->res);
294e5aaf047SAppaRao Puli                 return;
295e5aaf047SAppaRao Puli             }
296e5aaf047SAppaRao Puli             std::string destUrl;
297e5aaf047SAppaRao Puli             std::string protocol;
29819bb362bSEd Tanous             std::optional<bool> verifyCertificate;
299e5aaf047SAppaRao Puli             std::optional<std::string> context;
300e5aaf047SAppaRao Puli             std::optional<std::string> subscriptionType;
30123a21a1cSEd Tanous             std::optional<std::string> eventFormatType2;
302e5aaf047SAppaRao Puli             std::optional<std::string> retryPolicy;
303*5064a25bSMyung Bae             std::optional<bool> sendHeartbeat;
304*5064a25bSMyung Bae             std::optional<uint64_t> hbIntervalMinutes;
305e5aaf047SAppaRao Puli             std::optional<std::vector<std::string>> msgIds;
306e5aaf047SAppaRao Puli             std::optional<std::vector<std::string>> regPrefixes;
307a14c9113SEd Tanous             std::optional<std::vector<std::string>> originResources;
308e56f254cSSunitha Harish             std::optional<std::vector<std::string>> resTypes;
30978d4ec4fSEd Tanous             std::optional<std::vector<nlohmann::json::object_t>> headers;
31078d4ec4fSEd Tanous             std::optional<std::vector<nlohmann::json::object_t>> mrdJsonArray;
311e5aaf047SAppaRao Puli 
312afc474aeSMyung Bae             if (!json_util::readJsonPatch( //
313afc474aeSMyung Bae                     req, asyncResp->res, //
314afc474aeSMyung Bae                     "Context", context, //
315afc474aeSMyung Bae                     "DeliveryRetryPolicy", retryPolicy, //
316afc474aeSMyung Bae                     "Destination", destUrl, //
317afc474aeSMyung Bae                     "EventFormatType", eventFormatType2, //
318*5064a25bSMyung Bae                     "HeartbeatIntervalMinutes", hbIntervalMinutes, //
319afc474aeSMyung Bae                     "HttpHeaders", headers, //
320afc474aeSMyung Bae                     "MessageIds", msgIds, //
321afc474aeSMyung Bae                     "MetricReportDefinitions", mrdJsonArray, //
322afc474aeSMyung Bae                     "OriginResources", originResources, //
323afc474aeSMyung Bae                     "Protocol", protocol, //
324afc474aeSMyung Bae                     "RegistryPrefixes", regPrefixes, //
325afc474aeSMyung Bae                     "ResourceTypes", resTypes, //
326*5064a25bSMyung Bae                     "SendHeartbeat", sendHeartbeat, //
327afc474aeSMyung Bae                     "SubscriptionType", subscriptionType, //
328afc474aeSMyung Bae                     "VerifyCertificate", verifyCertificate //
3294b712a29SEd Tanous                     ))
330e5aaf047SAppaRao Puli             {
331e5aaf047SAppaRao Puli                 return;
332e5aaf047SAppaRao Puli             }
3334b712a29SEd Tanous             // clang-format on
334e5aaf047SAppaRao Puli 
335600af5f1SAppaRao Puli             // https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
336600af5f1SAppaRao Puli             static constexpr const uint16_t maxDestinationSize = 2000;
337600af5f1SAppaRao Puli             if (destUrl.size() > maxDestinationSize)
338600af5f1SAppaRao Puli             {
339600af5f1SAppaRao Puli                 messages::stringValueTooLong(asyncResp->res, "Destination",
340600af5f1SAppaRao Puli                                              maxDestinationSize);
341600af5f1SAppaRao Puli                 return;
342600af5f1SAppaRao Puli             }
343600af5f1SAppaRao Puli 
344dd28ba82SAppaRao Puli             if (regPrefixes && msgIds)
345dd28ba82SAppaRao Puli             {
34626f6976fSEd Tanous                 if (!regPrefixes->empty() && !msgIds->empty())
347dd28ba82SAppaRao Puli                 {
348bd79bce8SPatrick Williams                     messages::propertyValueConflict(
349bd79bce8SPatrick Williams                         asyncResp->res, "MessageIds", "RegistryPrefixes");
350dd28ba82SAppaRao Puli                     return;
351dd28ba82SAppaRao Puli                 }
352dd28ba82SAppaRao Puli             }
353dd28ba82SAppaRao Puli 
3546fd29553SEd Tanous             boost::system::result<boost::urls::url> url =
355a716aa74SEd Tanous                 boost::urls::parse_absolute_uri(destUrl);
356a716aa74SEd Tanous             if (!url)
357e5aaf047SAppaRao Puli             {
358bd79bce8SPatrick Williams                 BMCWEB_LOG_WARNING(
359bd79bce8SPatrick Williams                     "Failed to validate and split destination url");
360e5aaf047SAppaRao Puli                 messages::propertyValueFormatError(asyncResp->res, destUrl,
361e5aaf047SAppaRao Puli                                                    "Destination");
362e5aaf047SAppaRao Puli                 return;
363e5aaf047SAppaRao Puli             }
364a716aa74SEd Tanous             url->normalize();
365b07942e3SGeorge Liu 
366b07942e3SGeorge Liu             // port_number returns zero if it is not a valid representable port
367b07942e3SGeorge Liu             if (url->has_port() && url->port_number() == 0)
368b07942e3SGeorge Liu             {
369b07942e3SGeorge Liu                 BMCWEB_LOG_WARNING("{} is an invalid port in destination url",
370b07942e3SGeorge Liu                                    url->port());
371b07942e3SGeorge Liu                 messages::propertyValueFormatError(asyncResp->res, destUrl,
372b07942e3SGeorge Liu                                                    "Destination");
373b07942e3SGeorge Liu                 return;
374b07942e3SGeorge Liu             }
375b07942e3SGeorge Liu 
376a716aa74SEd Tanous             crow::utility::setProtocolDefaults(*url, protocol);
377a716aa74SEd Tanous             crow::utility::setPortDefaults(*url);
378a716aa74SEd Tanous 
379a716aa74SEd Tanous             if (url->path().empty())
380a716aa74SEd Tanous             {
381a716aa74SEd Tanous                 url->set_path("/");
382a716aa74SEd Tanous             }
383a716aa74SEd Tanous 
384a716aa74SEd Tanous             if (url->has_userinfo())
385a716aa74SEd Tanous             {
386a716aa74SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, destUrl,
387a716aa74SEd Tanous                                                    "Destination");
388a716aa74SEd Tanous                 return;
389a716aa74SEd Tanous             }
390b52664e2SAppaRao Puli 
3913d30708fSChicago Duan             if (protocol == "SNMPv2c")
3923d30708fSChicago Duan             {
3933d30708fSChicago Duan                 if (context)
3943d30708fSChicago Duan                 {
3953d30708fSChicago Duan                     messages::propertyValueConflict(asyncResp->res, "Context",
3963d30708fSChicago Duan                                                     "Protocol");
3973d30708fSChicago Duan                     return;
3983d30708fSChicago Duan                 }
3993d30708fSChicago Duan                 if (eventFormatType2)
4003d30708fSChicago Duan                 {
401bd79bce8SPatrick Williams                     messages::propertyValueConflict(
402bd79bce8SPatrick Williams                         asyncResp->res, "EventFormatType", "Protocol");
4033d30708fSChicago Duan                     return;
4043d30708fSChicago Duan                 }
4053d30708fSChicago Duan                 if (retryPolicy)
4063d30708fSChicago Duan                 {
407bd79bce8SPatrick Williams                     messages::propertyValueConflict(asyncResp->res,
408bd79bce8SPatrick Williams                                                     "RetryPolicy", "Protocol");
4093d30708fSChicago Duan                     return;
4103d30708fSChicago Duan                 }
411*5064a25bSMyung Bae                 if (sendHeartbeat)
412*5064a25bSMyung Bae                 {
413*5064a25bSMyung Bae                     messages::propertyValueConflict(
414*5064a25bSMyung Bae                         asyncResp->res, "SendHeartbeat", "Protocol");
415*5064a25bSMyung Bae                     return;
416*5064a25bSMyung Bae                 }
417*5064a25bSMyung Bae                 if (hbIntervalMinutes)
418*5064a25bSMyung Bae                 {
419*5064a25bSMyung Bae                     messages::propertyValueConflict(
420*5064a25bSMyung Bae                         asyncResp->res, "HeartbeatIntervalMinutes", "Protocol");
421*5064a25bSMyung Bae                     return;
422*5064a25bSMyung Bae                 }
4233d30708fSChicago Duan                 if (msgIds)
4243d30708fSChicago Duan                 {
425bd79bce8SPatrick Williams                     messages::propertyValueConflict(asyncResp->res,
426bd79bce8SPatrick Williams                                                     "MessageIds", "Protocol");
4273d30708fSChicago Duan                     return;
4283d30708fSChicago Duan                 }
4293d30708fSChicago Duan                 if (regPrefixes)
4303d30708fSChicago Duan                 {
431bd79bce8SPatrick Williams                     messages::propertyValueConflict(
432bd79bce8SPatrick Williams                         asyncResp->res, "RegistryPrefixes", "Protocol");
4333d30708fSChicago Duan                     return;
4343d30708fSChicago Duan                 }
4353d30708fSChicago Duan                 if (resTypes)
4363d30708fSChicago Duan                 {
437bd79bce8SPatrick Williams                     messages::propertyValueConflict(
438bd79bce8SPatrick Williams                         asyncResp->res, "ResourceTypes", "Protocol");
4393d30708fSChicago Duan                     return;
4403d30708fSChicago Duan                 }
4413d30708fSChicago Duan                 if (headers)
4423d30708fSChicago Duan                 {
443bd79bce8SPatrick Williams                     messages::propertyValueConflict(asyncResp->res,
444bd79bce8SPatrick Williams                                                     "HttpHeaders", "Protocol");
4453d30708fSChicago Duan                     return;
4463d30708fSChicago Duan                 }
4473d30708fSChicago Duan                 if (mrdJsonArray)
4483d30708fSChicago Duan                 {
4493d30708fSChicago Duan                     messages::propertyValueConflict(
4503d30708fSChicago Duan                         asyncResp->res, "MetricReportDefinitions", "Protocol");
4513d30708fSChicago Duan                     return;
4523d30708fSChicago Duan                 }
453a716aa74SEd Tanous                 if (url->scheme() != "snmp")
454a716aa74SEd Tanous                 {
455bd79bce8SPatrick Williams                     messages::propertyValueConflict(asyncResp->res,
456bd79bce8SPatrick Williams                                                     "Destination", "Protocol");
4573d30708fSChicago Duan                     return;
4583d30708fSChicago Duan                 }
4593d30708fSChicago Duan 
460a716aa74SEd Tanous                 addSnmpTrapClient(asyncResp, url->host_address(),
461a716aa74SEd Tanous                                   url->port_number());
462a716aa74SEd Tanous                 return;
463b52664e2SAppaRao Puli             }
4643d30708fSChicago Duan 
465a716aa74SEd Tanous             std::shared_ptr<Subscription> subValue =
46621a94d5cSMyung Bae                 std::make_shared<Subscription>(
4675fe4ef35SMyung Bae                     std::make_shared<persistent_data::UserSubscription>(), *url,
4685fe4ef35SMyung Bae                     app.ioContext());
469e5aaf047SAppaRao Puli 
470e5aaf047SAppaRao Puli             if (subscriptionType)
471e5aaf047SAppaRao Puli             {
472e5aaf047SAppaRao Puli                 if (*subscriptionType != "RedfishEvent")
473e5aaf047SAppaRao Puli                 {
474fffb8c1fSEd Tanous                     messages::propertyValueNotInList(
475fffb8c1fSEd Tanous                         asyncResp->res, *subscriptionType, "SubscriptionType");
476e5aaf047SAppaRao Puli                     return;
477e5aaf047SAppaRao Puli                 }
4785fe4ef35SMyung Bae                 subValue->userSub->subscriptionType = *subscriptionType;
479e5aaf047SAppaRao Puli             }
480e5aaf047SAppaRao Puli             else
481e5aaf047SAppaRao Puli             {
4824b712a29SEd Tanous                 // Default
4835fe4ef35SMyung Bae                 subValue->userSub->subscriptionType = "RedfishEvent";
484e5aaf047SAppaRao Puli             }
485e5aaf047SAppaRao Puli 
486e5aaf047SAppaRao Puli             if (protocol != "Redfish")
487e5aaf047SAppaRao Puli             {
488e5aaf047SAppaRao Puli                 messages::propertyValueNotInList(asyncResp->res, protocol,
489e5aaf047SAppaRao Puli                                                  "Protocol");
490e5aaf047SAppaRao Puli                 return;
491e5aaf047SAppaRao Puli             }
4925fe4ef35SMyung Bae             subValue->userSub->protocol = protocol;
493e5aaf047SAppaRao Puli 
49419bb362bSEd Tanous             if (verifyCertificate)
49519bb362bSEd Tanous             {
4965fe4ef35SMyung Bae                 subValue->userSub->verifyCertificate = *verifyCertificate;
49719bb362bSEd Tanous             }
49819bb362bSEd Tanous 
49923a21a1cSEd Tanous             if (eventFormatType2)
500e5aaf047SAppaRao Puli             {
501bd79bce8SPatrick Williams                 if (std::ranges::find(supportedEvtFormatTypes,
502bd79bce8SPatrick Williams                                       *eventFormatType2) ==
5033544d2a7SEd Tanous                     supportedEvtFormatTypes.end())
504e5aaf047SAppaRao Puli                 {
505fffb8c1fSEd Tanous                     messages::propertyValueNotInList(
506fffb8c1fSEd Tanous                         asyncResp->res, *eventFormatType2, "EventFormatType");
507e5aaf047SAppaRao Puli                     return;
508e5aaf047SAppaRao Puli                 }
5095fe4ef35SMyung Bae                 subValue->userSub->eventFormatType = *eventFormatType2;
510e5aaf047SAppaRao Puli             }
511e5aaf047SAppaRao Puli             else
512e5aaf047SAppaRao Puli             {
513e5aaf047SAppaRao Puli                 // If not specified, use default "Event"
5145fe4ef35SMyung Bae                 subValue->userSub->eventFormatType = "Event";
515e5aaf047SAppaRao Puli             }
516e5aaf047SAppaRao Puli 
517e5aaf047SAppaRao Puli             if (context)
518e5aaf047SAppaRao Puli             {
5198ece0e45SEd Tanous                 // This value is selected arbitrarily.
520600af5f1SAppaRao Puli                 constexpr const size_t maxContextSize = 256;
521600af5f1SAppaRao Puli                 if (context->size() > maxContextSize)
522600af5f1SAppaRao Puli                 {
523600af5f1SAppaRao Puli                     messages::stringValueTooLong(asyncResp->res, "Context",
524600af5f1SAppaRao Puli                                                  maxContextSize);
525600af5f1SAppaRao Puli                     return;
526600af5f1SAppaRao Puli                 }
5275fe4ef35SMyung Bae                 subValue->userSub->customText = *context;
528e5aaf047SAppaRao Puli             }
529e5aaf047SAppaRao Puli 
530e5aaf047SAppaRao Puli             if (headers)
531e5aaf047SAppaRao Puli             {
532600af5f1SAppaRao Puli                 size_t cumulativeLen = 0;
533600af5f1SAppaRao Puli 
53478d4ec4fSEd Tanous                 for (const nlohmann::json::object_t& headerChunk : *headers)
535601c71aeSEd Tanous                 {
53678d4ec4fSEd Tanous                     for (const auto& item : headerChunk)
53778d4ec4fSEd Tanous                     {
53878d4ec4fSEd Tanous                         const std::string* value =
53978d4ec4fSEd Tanous                             item.second.get_ptr<const std::string*>();
54078d4ec4fSEd Tanous                         if (value == nullptr)
54178d4ec4fSEd Tanous                         {
54278d4ec4fSEd Tanous                             messages::propertyValueFormatError(
54378d4ec4fSEd Tanous                                 asyncResp->res, item.second,
54478d4ec4fSEd Tanous                                 "HttpHeaders/" + item.first);
54578d4ec4fSEd Tanous                             return;
54678d4ec4fSEd Tanous                         }
54778d4ec4fSEd Tanous                         // Adding a new json value is the size of the key, +
54878d4ec4fSEd Tanous                         // the size of the value + 2 * 2 quotes for each, +
54978d4ec4fSEd Tanous                         // the colon and space between. example:
55078d4ec4fSEd Tanous                         // "key": "value"
55178d4ec4fSEd Tanous                         cumulativeLen += item.first.size() + value->size() + 6;
552600af5f1SAppaRao Puli                         // This value is selected to mirror http_connection.hpp
553600af5f1SAppaRao Puli                         constexpr const uint16_t maxHeaderSizeED = 8096;
554600af5f1SAppaRao Puli                         if (cumulativeLen > maxHeaderSizeED)
555600af5f1SAppaRao Puli                         {
55678d4ec4fSEd Tanous                             messages::arraySizeTooLong(
55778d4ec4fSEd Tanous                                 asyncResp->res, "HttpHeaders", maxHeaderSizeED);
558600af5f1SAppaRao Puli                             return;
559600af5f1SAppaRao Puli                         }
5605fe4ef35SMyung Bae                         subValue->userSub->httpHeaders.set(item.first, *value);
561601c71aeSEd Tanous                     }
562601c71aeSEd Tanous                 }
563e5aaf047SAppaRao Puli             }
564e5aaf047SAppaRao Puli 
565e5aaf047SAppaRao Puli             if (regPrefixes)
566e5aaf047SAppaRao Puli             {
567e5aaf047SAppaRao Puli                 for (const std::string& it : *regPrefixes)
568e5aaf047SAppaRao Puli                 {
5693544d2a7SEd Tanous                     if (std::ranges::find(supportedRegPrefixes, it) ==
5703544d2a7SEd Tanous                         supportedRegPrefixes.end())
571e5aaf047SAppaRao Puli                     {
572fffb8c1fSEd Tanous                         messages::propertyValueNotInList(asyncResp->res, it,
573fffb8c1fSEd Tanous                                                          "RegistryPrefixes");
574e5aaf047SAppaRao Puli                         return;
575e5aaf047SAppaRao Puli                     }
576e5aaf047SAppaRao Puli                 }
5775fe4ef35SMyung Bae                 subValue->userSub->registryPrefixes = *regPrefixes;
578e5aaf047SAppaRao Puli             }
579e5aaf047SAppaRao Puli 
580a14c9113SEd Tanous             if (originResources)
581a14c9113SEd Tanous             {
5825fe4ef35SMyung Bae                 subValue->userSub->originResources = *originResources;
583a14c9113SEd Tanous             }
584a14c9113SEd Tanous 
585e56f254cSSunitha Harish             if (resTypes)
586e56f254cSSunitha Harish             {
587e56f254cSSunitha Harish                 for (const std::string& it : *resTypes)
588e56f254cSSunitha Harish                 {
5893544d2a7SEd Tanous                     if (std::ranges::find(supportedResourceTypes, it) ==
5903544d2a7SEd Tanous                         supportedResourceTypes.end())
591e56f254cSSunitha Harish                     {
592e56f254cSSunitha Harish                         messages::propertyValueNotInList(asyncResp->res, it,
593e56f254cSSunitha Harish                                                          "ResourceTypes");
594e56f254cSSunitha Harish                         return;
595e56f254cSSunitha Harish                     }
596e56f254cSSunitha Harish                 }
5975fe4ef35SMyung Bae                 subValue->userSub->resourceTypes = *resTypes;
598e56f254cSSunitha Harish             }
599e56f254cSSunitha Harish 
600e5aaf047SAppaRao Puli             if (msgIds)
601e5aaf047SAppaRao Puli             {
602b304bd79SP Dheeraj Srujan Kumar                 std::vector<std::string> registryPrefix;
603b304bd79SP Dheeraj Srujan Kumar 
6047e860f15SJohn Edward Broadbent                 // If no registry prefixes are mentioned, consider all
6057e860f15SJohn Edward Broadbent                 // supported prefixes
6065fe4ef35SMyung Bae                 if (subValue->userSub->registryPrefixes.empty())
607b304bd79SP Dheeraj Srujan Kumar                 {
608b304bd79SP Dheeraj Srujan Kumar                     registryPrefix.assign(supportedRegPrefixes.begin(),
609b304bd79SP Dheeraj Srujan Kumar                                           supportedRegPrefixes.end());
610b304bd79SP Dheeraj Srujan Kumar                 }
611b304bd79SP Dheeraj Srujan Kumar                 else
612b304bd79SP Dheeraj Srujan Kumar                 {
6135fe4ef35SMyung Bae                     registryPrefix = subValue->userSub->registryPrefixes;
614b304bd79SP Dheeraj Srujan Kumar                 }
615b304bd79SP Dheeraj Srujan Kumar 
616b304bd79SP Dheeraj Srujan Kumar                 for (const std::string& id : *msgIds)
617b304bd79SP Dheeraj Srujan Kumar                 {
618b304bd79SP Dheeraj Srujan Kumar                     bool validId = false;
619b304bd79SP Dheeraj Srujan Kumar 
620b304bd79SP Dheeraj Srujan Kumar                     // Check for Message ID in each of the selected Registry
621b304bd79SP Dheeraj Srujan Kumar                     for (const std::string& it : registryPrefix)
622b304bd79SP Dheeraj Srujan Kumar                     {
623fffb8c1fSEd Tanous                         const std::span<const redfish::registries::MessageEntry>
624fffb8c1fSEd Tanous                             registry =
625fffb8c1fSEd Tanous                                 redfish::registries::getRegistryFromPrefix(it);
626b304bd79SP Dheeraj Srujan Kumar 
6273544d2a7SEd Tanous                         if (std::ranges::any_of(
6283544d2a7SEd Tanous                                 registry,
629fffb8c1fSEd Tanous                                 [&id](const redfish::registries::MessageEntry&
630fffb8c1fSEd Tanous                                           messageEntry) {
63155f79e6fSEd Tanous                                     return id == messageEntry.first;
632b304bd79SP Dheeraj Srujan Kumar                                 }))
633b304bd79SP Dheeraj Srujan Kumar                         {
634b304bd79SP Dheeraj Srujan Kumar                             validId = true;
635b304bd79SP Dheeraj Srujan Kumar                             break;
636b304bd79SP Dheeraj Srujan Kumar                         }
637b304bd79SP Dheeraj Srujan Kumar                     }
638b304bd79SP Dheeraj Srujan Kumar 
639b304bd79SP Dheeraj Srujan Kumar                     if (!validId)
640b304bd79SP Dheeraj Srujan Kumar                     {
641b304bd79SP Dheeraj Srujan Kumar                         messages::propertyValueNotInList(asyncResp->res, id,
642b304bd79SP Dheeraj Srujan Kumar                                                          "MessageIds");
643b304bd79SP Dheeraj Srujan Kumar                         return;
644b304bd79SP Dheeraj Srujan Kumar                     }
645b304bd79SP Dheeraj Srujan Kumar                 }
646b304bd79SP Dheeraj Srujan Kumar 
6475fe4ef35SMyung Bae                 subValue->userSub->registryMsgIds = *msgIds;
648e5aaf047SAppaRao Puli             }
649e5aaf047SAppaRao Puli 
650e5aaf047SAppaRao Puli             if (retryPolicy)
651e5aaf047SAppaRao Puli             {
6523544d2a7SEd Tanous                 if (std::ranges::find(supportedRetryPolicies, *retryPolicy) ==
6533544d2a7SEd Tanous                     supportedRetryPolicies.end())
654e5aaf047SAppaRao Puli                 {
655bd79bce8SPatrick Williams                     messages::propertyValueNotInList(
656bd79bce8SPatrick Williams                         asyncResp->res, *retryPolicy, "DeliveryRetryPolicy");
657e5aaf047SAppaRao Puli                     return;
658e5aaf047SAppaRao Puli                 }
6595fe4ef35SMyung Bae                 subValue->userSub->retryPolicy = *retryPolicy;
660e5aaf047SAppaRao Puli             }
661e5aaf047SAppaRao Puli             else
662e5aaf047SAppaRao Puli             {
663e5aaf047SAppaRao Puli                 // Default "TerminateAfterRetries"
6645fe4ef35SMyung Bae                 subValue->userSub->retryPolicy = "TerminateAfterRetries";
665e5aaf047SAppaRao Puli             }
666*5064a25bSMyung Bae             if (sendHeartbeat)
667*5064a25bSMyung Bae             {
668*5064a25bSMyung Bae                 subValue->userSub->sendHeartbeat = *sendHeartbeat;
669*5064a25bSMyung Bae             }
670*5064a25bSMyung Bae             if (hbIntervalMinutes)
671*5064a25bSMyung Bae             {
672*5064a25bSMyung Bae                 if (*hbIntervalMinutes < 1 || *hbIntervalMinutes > 65535)
673*5064a25bSMyung Bae                 {
674*5064a25bSMyung Bae                     messages::propertyValueOutOfRange(
675*5064a25bSMyung Bae                         asyncResp->res, *hbIntervalMinutes,
676*5064a25bSMyung Bae                         "HeartbeatIntervalMinutes");
677*5064a25bSMyung Bae                     return;
678*5064a25bSMyung Bae                 }
679*5064a25bSMyung Bae                 subValue->userSub->hbIntervalMinutes = *hbIntervalMinutes;
680*5064a25bSMyung Bae             }
681e5aaf047SAppaRao Puli 
682144b6318SAppaRao Puli             if (mrdJsonArray)
683156d6b00SAppaRao Puli             {
68478d4ec4fSEd Tanous                 for (nlohmann::json::object_t& mrdObj : *mrdJsonArray)
685144b6318SAppaRao Puli                 {
686144b6318SAppaRao Puli                     std::string mrdUri;
687ea2e6eecSWilly Tu 
68878d4ec4fSEd Tanous                     if (!json_util::readJsonObject(mrdObj, asyncResp->res,
68978d4ec4fSEd Tanous                                                    "@odata.id", mrdUri))
690ea2e6eecSWilly Tu 
691144b6318SAppaRao Puli                     {
692144b6318SAppaRao Puli                         return;
693144b6318SAppaRao Puli                     }
6945fe4ef35SMyung Bae                     subValue->userSub->metricReportDefinitions.emplace_back(
6954b712a29SEd Tanous                         mrdUri);
696144b6318SAppaRao Puli                 }
697156d6b00SAppaRao Puli             }
698156d6b00SAppaRao Puli 
699b52664e2SAppaRao Puli             std::string id =
700bd79bce8SPatrick Williams                 EventServiceManager::getInstance().addPushSubscription(
701bd79bce8SPatrick Williams                     subValue);
702b52664e2SAppaRao Puli             if (id.empty())
703e5aaf047SAppaRao Puli             {
704e5aaf047SAppaRao Puli                 messages::internalError(asyncResp->res);
705e5aaf047SAppaRao Puli                 return;
706e5aaf047SAppaRao Puli             }
707e5aaf047SAppaRao Puli 
708e5aaf047SAppaRao Puli             messages::created(asyncResp->res);
709e5aaf047SAppaRao Puli             asyncResp->res.addHeader(
710e5aaf047SAppaRao Puli                 "Location", "/redfish/v1/EventService/Subscriptions/" + id);
7117e860f15SJohn Edward Broadbent         });
712e5aaf047SAppaRao Puli }
713e5aaf047SAppaRao Puli 
7147e860f15SJohn Edward Broadbent inline void requestRoutesEventDestination(App& app)
715e5aaf047SAppaRao Puli {
7169d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
717ed398213SEd Tanous         .privileges(redfish::privileges::getEventDestination)
7187e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
71945ca1b86SEd Tanous             [&app](const crow::Request& req,
7207e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7217e860f15SJohn Edward Broadbent                    const std::string& param) {
7223ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
72345ca1b86SEd Tanous                 {
72445ca1b86SEd Tanous                     return;
72545ca1b86SEd Tanous                 }
7263d30708fSChicago Duan 
7273d30708fSChicago Duan                 if (param.starts_with("snmp"))
7283d30708fSChicago Duan                 {
7293d30708fSChicago Duan                     getSnmpTrapClient(asyncResp, param);
7303d30708fSChicago Duan                     return;
7313d30708fSChicago Duan                 }
7323d30708fSChicago Duan 
733b52664e2SAppaRao Puli                 std::shared_ptr<Subscription> subValue =
7347e860f15SJohn Edward Broadbent                     EventServiceManager::getInstance().getSubscription(param);
735b52664e2SAppaRao Puli                 if (subValue == nullptr)
736e5aaf047SAppaRao Puli                 {
737bd79bce8SPatrick Williams                     asyncResp->res.result(
738bd79bce8SPatrick Williams                         boost::beast::http::status::not_found);
739e5aaf047SAppaRao Puli                     return;
740e5aaf047SAppaRao Puli                 }
7417e860f15SJohn Edward Broadbent                 const std::string& id = param;
742e5aaf047SAppaRao Puli 
7434b712a29SEd Tanous                 const persistent_data::UserSubscription& userSub =
7445fe4ef35SMyung Bae                     *subValue->userSub;
745e56f254cSSunitha Harish 
7464b712a29SEd Tanous                 nlohmann::json& jVal = asyncResp->res.jsonValue;
7474b712a29SEd Tanous                 jVal["@odata.type"] =
7484b712a29SEd Tanous                     "#EventDestination.v1_14_1.EventDestination";
7494b712a29SEd Tanous                 jVal["Protocol"] =
7504b712a29SEd Tanous                     event_destination::EventDestinationProtocol::Redfish;
7514b712a29SEd Tanous                 jVal["@odata.id"] = boost::urls::format(
7524b712a29SEd Tanous                     "/redfish/v1/EventService/Subscriptions/{}", id);
7534b712a29SEd Tanous                 jVal["Id"] = id;
7544b712a29SEd Tanous                 jVal["Name"] = "Event Destination " + id;
7554b712a29SEd Tanous                 jVal["Destination"] = userSub.destinationUrl;
7564b712a29SEd Tanous                 jVal["Context"] = userSub.customText;
7574b712a29SEd Tanous                 jVal["SubscriptionType"] = userSub.subscriptionType;
7584b712a29SEd Tanous                 jVal["HttpHeaders"] = nlohmann::json::array();
7594b712a29SEd Tanous                 jVal["EventFormatType"] = userSub.eventFormatType;
7604b712a29SEd Tanous                 jVal["RegistryPrefixes"] = userSub.registryPrefixes;
7614b712a29SEd Tanous                 jVal["ResourceTypes"] = userSub.resourceTypes;
7624b712a29SEd Tanous 
7634b712a29SEd Tanous                 jVal["MessageIds"] = userSub.registryMsgIds;
7644b712a29SEd Tanous                 jVal["DeliveryRetryPolicy"] = userSub.retryPolicy;
765*5064a25bSMyung Bae                 jVal["SendHeartbeat"] = userSub.sendHeartbeat;
766*5064a25bSMyung Bae                 jVal["HeartbeatIntervalMinutes"] = userSub.hbIntervalMinutes;
7674b712a29SEd Tanous                 jVal["VerifyCertificate"] = userSub.verifyCertificate;
768144b6318SAppaRao Puli 
7691476687dSEd Tanous                 nlohmann::json::array_t mrdJsonArray;
7704b712a29SEd Tanous                 for (const auto& mdrUri : userSub.metricReportDefinitions)
771144b6318SAppaRao Puli                 {
7721476687dSEd Tanous                     nlohmann::json::object_t mdr;
7731476687dSEd Tanous                     mdr["@odata.id"] = mdrUri;
7741476687dSEd Tanous                     mrdJsonArray.emplace_back(std::move(mdr));
775144b6318SAppaRao Puli                 }
7764b712a29SEd Tanous                 jVal["MetricReportDefinitions"] = mrdJsonArray;
7777e860f15SJohn Edward Broadbent             });
7789d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
779ed398213SEd Tanous         // The below privilege is wrong, it should be ConfigureManager OR
780ed398213SEd Tanous         // ConfigureSelf
7817eeafa76SAbhishek Patel         // https://github.com/openbmc/bmcweb/issues/220
782ed398213SEd Tanous         //.privileges(redfish::privileges::patchEventDestination)
783432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
7847e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
78545ca1b86SEd Tanous             [&app](const crow::Request& req,
7867e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7877e860f15SJohn Edward Broadbent                    const std::string& param) {
7883ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
78945ca1b86SEd Tanous                 {
79045ca1b86SEd Tanous                     return;
79145ca1b86SEd Tanous                 }
792b52664e2SAppaRao Puli                 std::shared_ptr<Subscription> subValue =
7937e860f15SJohn Edward Broadbent                     EventServiceManager::getInstance().getSubscription(param);
794b52664e2SAppaRao Puli                 if (subValue == nullptr)
795e5aaf047SAppaRao Puli                 {
796bd79bce8SPatrick Williams                     asyncResp->res.result(
797bd79bce8SPatrick Williams                         boost::beast::http::status::not_found);
798e5aaf047SAppaRao Puli                     return;
799e5aaf047SAppaRao Puli                 }
800e5aaf047SAppaRao Puli 
801e5aaf047SAppaRao Puli                 std::optional<std::string> context;
802e5aaf047SAppaRao Puli                 std::optional<std::string> retryPolicy;
803*5064a25bSMyung Bae                 std::optional<bool> sendHeartbeat;
804*5064a25bSMyung Bae                 std::optional<uint64_t> hbIntervalMinutes;
80519bb362bSEd Tanous                 std::optional<bool> verifyCertificate;
80678d4ec4fSEd Tanous                 std::optional<std::vector<nlohmann::json::object_t>> headers;
807e5aaf047SAppaRao Puli 
808afc474aeSMyung Bae                 if (!json_util::readJsonPatch( //
809afc474aeSMyung Bae                         req, asyncResp->res, //
810afc474aeSMyung Bae                         "Context", context, //
811afc474aeSMyung Bae                         "DeliveryRetryPolicy", retryPolicy, //
812*5064a25bSMyung Bae                         "HeartbeatIntervalMinutes", hbIntervalMinutes, //
813afc474aeSMyung Bae                         "HttpHeaders", headers, //
814*5064a25bSMyung Bae                         "SendHeartbeat", sendHeartbeat, //
815afc474aeSMyung Bae                         "VerifyCertificate", verifyCertificate //
816afc474aeSMyung Bae                         ))
817e5aaf047SAppaRao Puli                 {
818e5aaf047SAppaRao Puli                     return;
819e5aaf047SAppaRao Puli                 }
820e5aaf047SAppaRao Puli 
821e5aaf047SAppaRao Puli                 if (context)
822e5aaf047SAppaRao Puli                 {
8235fe4ef35SMyung Bae                     subValue->userSub->customText = *context;
824e5aaf047SAppaRao Puli                 }
825e5aaf047SAppaRao Puli 
826e5aaf047SAppaRao Puli                 if (headers)
827e5aaf047SAppaRao Puli                 {
828601c71aeSEd Tanous                     boost::beast::http::fields fields;
82978d4ec4fSEd Tanous                     for (const nlohmann::json::object_t& headerChunk : *headers)
830601c71aeSEd Tanous                     {
83178d4ec4fSEd Tanous                         for (const auto& it : headerChunk)
832601c71aeSEd Tanous                         {
833601c71aeSEd Tanous                             const std::string* value =
83478d4ec4fSEd Tanous                                 it.second.get_ptr<const std::string*>();
835601c71aeSEd Tanous                             if (value == nullptr)
836601c71aeSEd Tanous                             {
837601c71aeSEd Tanous                                 messages::propertyValueFormatError(
83878d4ec4fSEd Tanous                                     asyncResp->res, it.second,
83978d4ec4fSEd Tanous                                     "HttpHeaders/" + it.first);
840601c71aeSEd Tanous                                 return;
841601c71aeSEd Tanous                             }
84278d4ec4fSEd Tanous                             fields.set(it.first, *value);
843601c71aeSEd Tanous                         }
844601c71aeSEd Tanous                     }
8455fe4ef35SMyung Bae                     subValue->userSub->httpHeaders = std::move(fields);
846e5aaf047SAppaRao Puli                 }
847e5aaf047SAppaRao Puli 
848e5aaf047SAppaRao Puli                 if (retryPolicy)
849e5aaf047SAppaRao Puli                 {
850bd79bce8SPatrick Williams                     if (std::ranges::find(supportedRetryPolicies,
851bd79bce8SPatrick Williams                                           *retryPolicy) ==
8523544d2a7SEd Tanous                         supportedRetryPolicies.end())
853e5aaf047SAppaRao Puli                     {
854bd79bce8SPatrick Williams                         messages::propertyValueNotInList(asyncResp->res,
855bd79bce8SPatrick Williams                                                          *retryPolicy,
856e5aaf047SAppaRao Puli                                                          "DeliveryRetryPolicy");
857e5aaf047SAppaRao Puli                         return;
858e5aaf047SAppaRao Puli                     }
8595fe4ef35SMyung Bae                     subValue->userSub->retryPolicy = *retryPolicy;
860e5aaf047SAppaRao Puli                 }
861e5aaf047SAppaRao Puli 
862*5064a25bSMyung Bae                 if (sendHeartbeat)
863*5064a25bSMyung Bae                 {
864*5064a25bSMyung Bae                     subValue->userSub->sendHeartbeat = *sendHeartbeat;
865*5064a25bSMyung Bae                 }
866*5064a25bSMyung Bae                 if (hbIntervalMinutes)
867*5064a25bSMyung Bae                 {
868*5064a25bSMyung Bae                     if (*hbIntervalMinutes < 1 || *hbIntervalMinutes > 65535)
869*5064a25bSMyung Bae                     {
870*5064a25bSMyung Bae                         messages::propertyValueOutOfRange(
871*5064a25bSMyung Bae                             asyncResp->res, *hbIntervalMinutes,
872*5064a25bSMyung Bae                             "HeartbeatIntervalMinutes");
873*5064a25bSMyung Bae                         return;
874*5064a25bSMyung Bae                     }
875*5064a25bSMyung Bae                     subValue->userSub->hbIntervalMinutes = *hbIntervalMinutes;
876*5064a25bSMyung Bae                 }
877*5064a25bSMyung Bae 
87819bb362bSEd Tanous                 if (verifyCertificate)
87919bb362bSEd Tanous                 {
8805fe4ef35SMyung Bae                     subValue->userSub->verifyCertificate = *verifyCertificate;
88119bb362bSEd Tanous                 }
88219bb362bSEd Tanous 
883b52664e2SAppaRao Puli                 EventServiceManager::getInstance().updateSubscriptionData();
8847e860f15SJohn Edward Broadbent             });
8859d41aec6SRavi Teja     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
886ed398213SEd Tanous         // The below privilege is wrong, it should be ConfigureManager OR
887ed398213SEd Tanous         // ConfigureSelf
8887eeafa76SAbhishek Patel         // https://github.com/openbmc/bmcweb/issues/220
889ed398213SEd Tanous         //.privileges(redfish::privileges::deleteEventDestination)
890432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
8917e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
89245ca1b86SEd Tanous             [&app](const crow::Request& req,
8937e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
8947e860f15SJohn Edward Broadbent                    const std::string& param) {
8953ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
89645ca1b86SEd Tanous                 {
89745ca1b86SEd Tanous                     return;
89845ca1b86SEd Tanous                 }
8994b712a29SEd Tanous                 EventServiceManager& event = EventServiceManager::getInstance();
9003d30708fSChicago Duan                 if (param.starts_with("snmp"))
9013d30708fSChicago Duan                 {
9023d30708fSChicago Duan                     deleteSnmpTrapClient(asyncResp, param);
9034b712a29SEd Tanous                     event.deleteSubscription(param);
9043d30708fSChicago Duan                     return;
9053d30708fSChicago Duan                 }
9063d30708fSChicago Duan 
9074b712a29SEd Tanous                 if (!event.deleteSubscription(param))
908e5aaf047SAppaRao Puli                 {
9094b712a29SEd Tanous                     messages::resourceNotFound(asyncResp->res,
9104b712a29SEd Tanous                                                "EventDestination", param);
911e5aaf047SAppaRao Puli                     return;
912e5aaf047SAppaRao Puli                 }
9134b712a29SEd Tanous                 messages::success(asyncResp->res);
9147e860f15SJohn Edward Broadbent             });
915e5aaf047SAppaRao Puli }
916e5aaf047SAppaRao Puli 
917e5aaf047SAppaRao Puli } // namespace redfish
918