xref: /openbmc/bmcweb/features/redfish/lib/event_service.hpp (revision 432a890cfca335e565b770b1604ed4e547c5a732)
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
17b52664e2SAppaRao Puli #include "event_service_manager.hpp"
18e5aaf047SAppaRao Puli 
197e860f15SJohn Edward Broadbent #include <app.hpp>
20e5aaf047SAppaRao Puli namespace redfish
21e5aaf047SAppaRao Puli {
22e5aaf047SAppaRao Puli 
23156d6b00SAppaRao Puli static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
24156d6b00SAppaRao Puli     eventFormatType, metricReportFormatType};
25e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
26b304bd79SP Dheeraj Srujan Kumar     "Base", "OpenBMC", "TaskEvent"};
27e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
28e5aaf047SAppaRao Puli     "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
29e5aaf047SAppaRao Puli 
30e56f254cSSunitha Harish #ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
31e56f254cSSunitha Harish static constexpr const std::array<const char*, 2> supportedResourceTypes = {
32e56f254cSSunitha Harish     "IBMConfigFile", "Task"};
33e56f254cSSunitha Harish #else
34e56f254cSSunitha Harish static constexpr const std::array<const char*, 1> supportedResourceTypes = {
35e56f254cSSunitha Harish     "Task"};
36e56f254cSSunitha Harish #endif
37e56f254cSSunitha Harish 
38e5aaf047SAppaRao Puli static constexpr const uint8_t maxNoOfSubscriptions = 20;
39e5aaf047SAppaRao Puli 
407e860f15SJohn Edward Broadbent inline void requestRoutesEventService(App& app)
41e5aaf047SAppaRao Puli {
427e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
43*432a890cSEd Tanous         .privileges({{"Login"}})
447e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
457e860f15SJohn Edward Broadbent             [](const crow::Request&,
467e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
478d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
48e5aaf047SAppaRao Puli                     {"@odata.type", "#EventService.v1_5_0.EventService"},
49e5aaf047SAppaRao Puli                     {"Id", "EventService"},
50e5aaf047SAppaRao Puli                     {"Name", "Event Service"},
51e5aaf047SAppaRao Puli                     {"Subscriptions",
52e5aaf047SAppaRao Puli                      {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}},
530b4bdd93SAppaRao Puli                     {"Actions",
540b4bdd93SAppaRao Puli                      {{"#EventService.SubmitTestEvent",
550b4bdd93SAppaRao Puli                        {{"target", "/redfish/v1/EventService/Actions/"
560b4bdd93SAppaRao Puli                                    "EventService.SubmitTestEvent"}}}}},
57e5aaf047SAppaRao Puli                     {"@odata.id", "/redfish/v1/EventService"}};
58e5aaf047SAppaRao Puli 
597d1cc387SAppaRao Puli                 const auto& [enabled, retryAttempts, retryTimeoutInterval] =
607d1cc387SAppaRao Puli                     EventServiceManager::getInstance().getEventServiceConfig();
617d1cc387SAppaRao Puli 
627d1cc387SAppaRao Puli                 asyncResp->res.jsonValue["Status"]["State"] =
637d1cc387SAppaRao Puli                     (enabled ? "Enabled" : "Disabled");
647d1cc387SAppaRao Puli                 asyncResp->res.jsonValue["ServiceEnabled"] = enabled;
657e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
667e860f15SJohn Edward Broadbent                     retryAttempts;
67e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
687d1cc387SAppaRao Puli                     retryTimeoutInterval;
697e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["EventFormatTypes"] =
707e860f15SJohn Edward Broadbent                     supportedEvtFormatTypes;
717e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["RegistryPrefixes"] =
727e860f15SJohn Edward Broadbent                     supportedRegPrefixes;
737e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["ResourceTypes"] =
747e860f15SJohn Edward Broadbent                     supportedResourceTypes;
7507941a88SAyushi Smriti 
7607941a88SAyushi Smriti                 nlohmann::json supportedSSEFilters = {
7707941a88SAyushi Smriti                     {"EventFormatType", true},        {"MessageId", true},
7807941a88SAyushi Smriti                     {"MetricReportDefinition", true}, {"RegistryPrefix", true},
7907941a88SAyushi Smriti                     {"OriginResource", false},        {"ResourceType", false}};
8007941a88SAyushi Smriti 
8107941a88SAyushi Smriti                 asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
8207941a88SAyushi Smriti                     supportedSSEFilters;
837e860f15SJohn Edward Broadbent             });
84e5aaf047SAppaRao Puli 
857e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
86*432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
877e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
887e860f15SJohn Edward Broadbent             [](const crow::Request& req,
897e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
907e860f15SJohn Edward Broadbent 
91e5aaf047SAppaRao Puli             {
92e5aaf047SAppaRao Puli                 std::optional<bool> serviceEnabled;
93e5aaf047SAppaRao Puli                 std::optional<uint32_t> retryAttemps;
94e5aaf047SAppaRao Puli                 std::optional<uint32_t> retryInterval;
95e5aaf047SAppaRao Puli 
967e860f15SJohn Edward Broadbent                 if (!json_util::readJson(
977e860f15SJohn Edward Broadbent                         req, asyncResp->res, "ServiceEnabled", serviceEnabled,
987e860f15SJohn Edward Broadbent                         "DeliveryRetryAttempts", retryAttemps,
997e860f15SJohn Edward Broadbent                         "DeliveryRetryIntervalSeconds", retryInterval))
100e5aaf047SAppaRao Puli                 {
101e5aaf047SAppaRao Puli                     return;
102e5aaf047SAppaRao Puli                 }
103e5aaf047SAppaRao Puli 
1047d1cc387SAppaRao Puli                 auto [enabled, retryCount, retryTimeoutInterval] =
1057d1cc387SAppaRao Puli                     EventServiceManager::getInstance().getEventServiceConfig();
1067d1cc387SAppaRao Puli 
107e5aaf047SAppaRao Puli                 if (serviceEnabled)
108e5aaf047SAppaRao Puli                 {
1097d1cc387SAppaRao Puli                     enabled = *serviceEnabled;
110e5aaf047SAppaRao Puli                 }
111e5aaf047SAppaRao Puli 
112e5aaf047SAppaRao Puli                 if (retryAttemps)
113e5aaf047SAppaRao Puli                 {
114e5aaf047SAppaRao Puli                     // Supported range [1-3]
115e5aaf047SAppaRao Puli                     if ((*retryAttemps < 1) || (*retryAttemps > 3))
116e5aaf047SAppaRao Puli                     {
117e5aaf047SAppaRao Puli                         messages::queryParameterOutOfRange(
118e5aaf047SAppaRao Puli                             asyncResp->res, std::to_string(*retryAttemps),
119e5aaf047SAppaRao Puli                             "DeliveryRetryAttempts", "[1-3]");
120e5aaf047SAppaRao Puli                     }
121e5aaf047SAppaRao Puli                     else
122e5aaf047SAppaRao Puli                     {
1237d1cc387SAppaRao Puli                         retryCount = *retryAttemps;
124e5aaf047SAppaRao Puli                     }
125e5aaf047SAppaRao Puli                 }
126e5aaf047SAppaRao Puli 
127e5aaf047SAppaRao Puli                 if (retryInterval)
128e5aaf047SAppaRao Puli                 {
129e5aaf047SAppaRao Puli                     // Supported range [30 - 180]
130e5aaf047SAppaRao Puli                     if ((*retryInterval < 30) || (*retryInterval > 180))
131e5aaf047SAppaRao Puli                     {
132e5aaf047SAppaRao Puli                         messages::queryParameterOutOfRange(
133e5aaf047SAppaRao Puli                             asyncResp->res, std::to_string(*retryInterval),
134e5aaf047SAppaRao Puli                             "DeliveryRetryIntervalSeconds", "[30-180]");
135e5aaf047SAppaRao Puli                     }
136e5aaf047SAppaRao Puli                     else
137e5aaf047SAppaRao Puli                     {
1387d1cc387SAppaRao Puli                         retryTimeoutInterval = *retryInterval;
139e5aaf047SAppaRao Puli                     }
140e5aaf047SAppaRao Puli                 }
141e5aaf047SAppaRao Puli 
1427d1cc387SAppaRao Puli                 EventServiceManager::getInstance().setEventServiceConfig(
1437d1cc387SAppaRao Puli                     std::make_tuple(enabled, retryCount, retryTimeoutInterval));
1447e860f15SJohn Edward Broadbent             });
1450b4bdd93SAppaRao Puli }
1460b4bdd93SAppaRao Puli 
1477e860f15SJohn Edward Broadbent inline void requestRoutesSubmitTestEvent(App& app)
1480b4bdd93SAppaRao Puli {
1497e860f15SJohn Edward Broadbent 
1507e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
1517e860f15SJohn Edward Broadbent         app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
152*432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
1537e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
1547e860f15SJohn Edward Broadbent             [](const crow::Request&,
1557e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1560b4bdd93SAppaRao Puli                 EventServiceManager::getInstance().sendTestEventLog();
1578d1b46d7Szhanghch05                 asyncResp->res.result(boost::beast::http::status::no_content);
1587e860f15SJohn Edward Broadbent             });
159e5aaf047SAppaRao Puli }
160e5aaf047SAppaRao Puli 
1617e860f15SJohn Edward Broadbent inline void requestRoutesEventDestinationCollection(App& app)
162e5aaf047SAppaRao Puli {
1637e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions")
164*432a890cSEd Tanous         .privileges({{"Login"}})
1657e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
1667e860f15SJohn Edward Broadbent             [](const crow::Request&,
1677e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1688d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
169e5aaf047SAppaRao Puli                     {"@odata.type",
170e5aaf047SAppaRao Puli                      "#EventDestinationCollection.EventDestinationCollection"},
171e5aaf047SAppaRao Puli                     {"@odata.id", "/redfish/v1/EventService/Subscriptions"},
172e5aaf047SAppaRao Puli                     {"Name", "Event Destination Collections"}};
173e5aaf047SAppaRao Puli 
1747e860f15SJohn Edward Broadbent                 nlohmann::json& memberArray =
1757e860f15SJohn Edward Broadbent                     asyncResp->res.jsonValue["Members"];
176e5aaf047SAppaRao Puli 
177b52664e2SAppaRao Puli                 std::vector<std::string> subscripIds =
178b52664e2SAppaRao Puli                     EventServiceManager::getInstance().getAllIDs();
179b52664e2SAppaRao Puli                 memberArray = nlohmann::json::array();
1807e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["Members@odata.count"] =
1817e860f15SJohn Edward Broadbent                     subscripIds.size();
182b52664e2SAppaRao Puli 
183b52664e2SAppaRao Puli                 for (const std::string& id : subscripIds)
184e5aaf047SAppaRao Puli                 {
185e5aaf047SAppaRao Puli                     memberArray.push_back(
186e5aaf047SAppaRao Puli                         {{"@odata.id",
187b52664e2SAppaRao Puli                           "/redfish/v1/EventService/Subscriptions/" + id}});
188e5aaf047SAppaRao Puli                 }
1897e860f15SJohn Edward Broadbent             });
1907e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
191*432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
1927e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
1937e860f15SJohn Edward Broadbent             [](const crow::Request& req,
1947e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1957e860f15SJohn Edward Broadbent                 if (EventServiceManager::getInstance()
1967e860f15SJohn Edward Broadbent                         .getNumberOfSubscriptions() >= maxNoOfSubscriptions)
197e5aaf047SAppaRao Puli                 {
198e5aaf047SAppaRao Puli                     messages::eventSubscriptionLimitExceeded(asyncResp->res);
199e5aaf047SAppaRao Puli                     return;
200e5aaf047SAppaRao Puli                 }
201e5aaf047SAppaRao Puli                 std::string destUrl;
202e5aaf047SAppaRao Puli                 std::string protocol;
203e5aaf047SAppaRao Puli                 std::optional<std::string> context;
204e5aaf047SAppaRao Puli                 std::optional<std::string> subscriptionType;
20523a21a1cSEd Tanous                 std::optional<std::string> eventFormatType2;
206e5aaf047SAppaRao Puli                 std::optional<std::string> retryPolicy;
207e5aaf047SAppaRao Puli                 std::optional<std::vector<std::string>> msgIds;
208e5aaf047SAppaRao Puli                 std::optional<std::vector<std::string>> regPrefixes;
209e56f254cSSunitha Harish                 std::optional<std::vector<std::string>> resTypes;
210e5aaf047SAppaRao Puli                 std::optional<std::vector<nlohmann::json>> headers;
211144b6318SAppaRao Puli                 std::optional<std::vector<nlohmann::json>> mrdJsonArray;
212e5aaf047SAppaRao Puli 
213e5aaf047SAppaRao Puli                 if (!json_util::readJson(
2147e860f15SJohn Edward Broadbent                         req, asyncResp->res, "Destination", destUrl, "Context",
2157e860f15SJohn Edward Broadbent                         context, "Protocol", protocol, "SubscriptionType",
2167e860f15SJohn Edward Broadbent                         subscriptionType, "EventFormatType", eventFormatType2,
2177e860f15SJohn Edward Broadbent                         "HttpHeaders", headers, "RegistryPrefixes", regPrefixes,
2187e860f15SJohn Edward Broadbent                         "MessageIds", msgIds, "DeliveryRetryPolicy",
2197e860f15SJohn Edward Broadbent                         retryPolicy, "MetricReportDefinitions", mrdJsonArray,
2207e860f15SJohn Edward Broadbent                         "ResourceTypes", resTypes))
221e5aaf047SAppaRao Puli                 {
222e5aaf047SAppaRao Puli                     return;
223e5aaf047SAppaRao Puli                 }
224e5aaf047SAppaRao Puli 
225dd28ba82SAppaRao Puli                 if (regPrefixes && msgIds)
226dd28ba82SAppaRao Puli                 {
227dd28ba82SAppaRao Puli                     if (regPrefixes->size() && msgIds->size())
228dd28ba82SAppaRao Puli                     {
229dd28ba82SAppaRao Puli                         messages::mutualExclusiveProperties(
230dd28ba82SAppaRao Puli                             asyncResp->res, "RegistryPrefixes", "MessageIds");
231dd28ba82SAppaRao Puli                         return;
232dd28ba82SAppaRao Puli                     }
233dd28ba82SAppaRao Puli                 }
234dd28ba82SAppaRao Puli 
235e5aaf047SAppaRao Puli                 // Validate the URL using regex expression
236b52664e2SAppaRao Puli                 // Format: <protocol>://<host>:<port>/<uri>
237b52664e2SAppaRao Puli                 // protocol: http/https
238b52664e2SAppaRao Puli                 // host: Exclude ' ', ':', '#', '?'
2394e0453b1SGunnar Mills                 // port: Empty or numeric value with ':' separator.
240b52664e2SAppaRao Puli                 // uri: Start with '/' and Exclude '#', ' '
241b52664e2SAppaRao Puli                 //      Can include query params(ex: '/event?test=1')
242b52664e2SAppaRao Puli                 // TODO: Need to validate hostname extensively(as per rfc)
243b52664e2SAppaRao Puli                 const std::regex urlRegex(
244b52664e2SAppaRao Puli                     "(http|https)://([^/\\x20\\x3f\\x23\\x3a]+):?([0-9]*)(/"
245b52664e2SAppaRao Puli                     "([^\\x20\\x23\\x3f]*\\x3f?([^\\x20\\x23\\x3f])*)?)");
246b52664e2SAppaRao Puli                 std::cmatch match;
247b52664e2SAppaRao Puli                 if (!std::regex_match(destUrl.c_str(), match, urlRegex))
248e5aaf047SAppaRao Puli                 {
249e5aaf047SAppaRao Puli                     messages::propertyValueFormatError(asyncResp->res, destUrl,
250e5aaf047SAppaRao Puli                                                        "Destination");
251e5aaf047SAppaRao Puli                     return;
252e5aaf047SAppaRao Puli                 }
253b52664e2SAppaRao Puli 
2547e860f15SJohn Edward Broadbent                 std::string uriProto =
2557e860f15SJohn Edward Broadbent                     std::string(match[1].first, match[1].second);
256b52664e2SAppaRao Puli                 if (uriProto == "http")
257b52664e2SAppaRao Puli                 {
258b52664e2SAppaRao Puli #ifndef BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING
259b52664e2SAppaRao Puli                     messages::propertyValueFormatError(asyncResp->res, destUrl,
260b52664e2SAppaRao Puli                                                        "Destination");
261b52664e2SAppaRao Puli                     return;
262b52664e2SAppaRao Puli #endif
263b52664e2SAppaRao Puli                 }
264b52664e2SAppaRao Puli 
265b52664e2SAppaRao Puli                 std::string host = std::string(match[2].first, match[2].second);
266b52664e2SAppaRao Puli                 std::string port = std::string(match[3].first, match[3].second);
267b52664e2SAppaRao Puli                 std::string path = std::string(match[4].first, match[4].second);
268b52664e2SAppaRao Puli                 if (port.empty())
269b52664e2SAppaRao Puli                 {
270b52664e2SAppaRao Puli                     if (uriProto == "http")
271b52664e2SAppaRao Puli                     {
272b52664e2SAppaRao Puli                         port = "80";
273b52664e2SAppaRao Puli                     }
274b52664e2SAppaRao Puli                     else
275b52664e2SAppaRao Puli                     {
276b52664e2SAppaRao Puli                         port = "443";
277b52664e2SAppaRao Puli                     }
278b52664e2SAppaRao Puli                 }
279b52664e2SAppaRao Puli                 if (path.empty())
280b52664e2SAppaRao Puli                 {
281b52664e2SAppaRao Puli                     path = "/";
282b52664e2SAppaRao Puli                 }
283b52664e2SAppaRao Puli 
284b52664e2SAppaRao Puli                 std::shared_ptr<Subscription> subValue =
285b52664e2SAppaRao Puli                     std::make_shared<Subscription>(host, port, path, uriProto);
286b52664e2SAppaRao Puli 
287b52664e2SAppaRao Puli                 subValue->destinationUrl = destUrl;
288e5aaf047SAppaRao Puli 
289e5aaf047SAppaRao Puli                 if (subscriptionType)
290e5aaf047SAppaRao Puli                 {
291e5aaf047SAppaRao Puli                     if (*subscriptionType != "RedfishEvent")
292e5aaf047SAppaRao Puli                     {
2937e860f15SJohn Edward Broadbent                         messages::propertyValueNotInList(asyncResp->res,
2947e860f15SJohn Edward Broadbent                                                          *subscriptionType,
2957e860f15SJohn Edward Broadbent                                                          "SubscriptionType");
296e5aaf047SAppaRao Puli                         return;
297e5aaf047SAppaRao Puli                     }
298b52664e2SAppaRao Puli                     subValue->subscriptionType = *subscriptionType;
299e5aaf047SAppaRao Puli                 }
300e5aaf047SAppaRao Puli                 else
301e5aaf047SAppaRao Puli                 {
302b52664e2SAppaRao Puli                     subValue->subscriptionType = "RedfishEvent"; // Default
303e5aaf047SAppaRao Puli                 }
304e5aaf047SAppaRao Puli 
305e5aaf047SAppaRao Puli                 if (protocol != "Redfish")
306e5aaf047SAppaRao Puli                 {
307e5aaf047SAppaRao Puli                     messages::propertyValueNotInList(asyncResp->res, protocol,
308e5aaf047SAppaRao Puli                                                      "Protocol");
309e5aaf047SAppaRao Puli                     return;
310e5aaf047SAppaRao Puli                 }
311b52664e2SAppaRao Puli                 subValue->protocol = protocol;
312e5aaf047SAppaRao Puli 
31323a21a1cSEd Tanous                 if (eventFormatType2)
314e5aaf047SAppaRao Puli                 {
315e5aaf047SAppaRao Puli                     if (std::find(supportedEvtFormatTypes.begin(),
316e5aaf047SAppaRao Puli                                   supportedEvtFormatTypes.end(),
3177e860f15SJohn Edward Broadbent                                   *eventFormatType2) ==
3187e860f15SJohn Edward Broadbent                         supportedEvtFormatTypes.end())
319e5aaf047SAppaRao Puli                     {
3207e860f15SJohn Edward Broadbent                         messages::propertyValueNotInList(asyncResp->res,
3217e860f15SJohn Edward Broadbent                                                          *eventFormatType2,
3227e860f15SJohn Edward Broadbent                                                          "EventFormatType");
323e5aaf047SAppaRao Puli                         return;
324e5aaf047SAppaRao Puli                     }
32523a21a1cSEd Tanous                     subValue->eventFormatType = *eventFormatType2;
326e5aaf047SAppaRao Puli                 }
327e5aaf047SAppaRao Puli                 else
328e5aaf047SAppaRao Puli                 {
329e5aaf047SAppaRao Puli                     // If not specified, use default "Event"
33023a21a1cSEd Tanous                     subValue->eventFormatType = "Event";
331e5aaf047SAppaRao Puli                 }
332e5aaf047SAppaRao Puli 
333e5aaf047SAppaRao Puli                 if (context)
334e5aaf047SAppaRao Puli                 {
335b52664e2SAppaRao Puli                     subValue->customText = *context;
336e5aaf047SAppaRao Puli                 }
337e5aaf047SAppaRao Puli 
338e5aaf047SAppaRao Puli                 if (headers)
339e5aaf047SAppaRao Puli                 {
340b52664e2SAppaRao Puli                     subValue->httpHeaders = *headers;
341e5aaf047SAppaRao Puli                 }
342e5aaf047SAppaRao Puli 
343e5aaf047SAppaRao Puli                 if (regPrefixes)
344e5aaf047SAppaRao Puli                 {
345e5aaf047SAppaRao Puli                     for (const std::string& it : *regPrefixes)
346e5aaf047SAppaRao Puli                     {
347e5aaf047SAppaRao Puli                         if (std::find(supportedRegPrefixes.begin(),
348e5aaf047SAppaRao Puli                                       supportedRegPrefixes.end(),
349e5aaf047SAppaRao Puli                                       it) == supportedRegPrefixes.end())
350e5aaf047SAppaRao Puli                         {
3517e860f15SJohn Edward Broadbent                             messages::propertyValueNotInList(
3527e860f15SJohn Edward Broadbent                                 asyncResp->res, it, "RegistryPrefixes");
353e5aaf047SAppaRao Puli                             return;
354e5aaf047SAppaRao Puli                         }
355e5aaf047SAppaRao Puli                     }
356b52664e2SAppaRao Puli                     subValue->registryPrefixes = *regPrefixes;
357e5aaf047SAppaRao Puli                 }
358e5aaf047SAppaRao Puli 
359e56f254cSSunitha Harish                 if (resTypes)
360e56f254cSSunitha Harish                 {
361e56f254cSSunitha Harish                     for (const std::string& it : *resTypes)
362e56f254cSSunitha Harish                     {
363e56f254cSSunitha Harish                         if (std::find(supportedResourceTypes.begin(),
364e56f254cSSunitha Harish                                       supportedResourceTypes.end(),
365e56f254cSSunitha Harish                                       it) == supportedResourceTypes.end())
366e56f254cSSunitha Harish                         {
367e56f254cSSunitha Harish                             messages::propertyValueNotInList(asyncResp->res, it,
368e56f254cSSunitha Harish                                                              "ResourceTypes");
369e56f254cSSunitha Harish                             return;
370e56f254cSSunitha Harish                         }
371e56f254cSSunitha Harish                     }
372e56f254cSSunitha Harish                     subValue->resourceTypes = *resTypes;
373e56f254cSSunitha Harish                 }
374e56f254cSSunitha Harish 
375e5aaf047SAppaRao Puli                 if (msgIds)
376e5aaf047SAppaRao Puli                 {
377b304bd79SP Dheeraj Srujan Kumar                     std::vector<std::string> registryPrefix;
378b304bd79SP Dheeraj Srujan Kumar 
3797e860f15SJohn Edward Broadbent                     // If no registry prefixes are mentioned, consider all
3807e860f15SJohn Edward Broadbent                     // supported prefixes
381b304bd79SP Dheeraj Srujan Kumar                     if (subValue->registryPrefixes.empty())
382b304bd79SP Dheeraj Srujan Kumar                     {
383b304bd79SP Dheeraj Srujan Kumar                         registryPrefix.assign(supportedRegPrefixes.begin(),
384b304bd79SP Dheeraj Srujan Kumar                                               supportedRegPrefixes.end());
385b304bd79SP Dheeraj Srujan Kumar                     }
386b304bd79SP Dheeraj Srujan Kumar                     else
387b304bd79SP Dheeraj Srujan Kumar                     {
388b304bd79SP Dheeraj Srujan Kumar                         registryPrefix = subValue->registryPrefixes;
389b304bd79SP Dheeraj Srujan Kumar                     }
390b304bd79SP Dheeraj Srujan Kumar 
391b304bd79SP Dheeraj Srujan Kumar                     for (const std::string& id : *msgIds)
392b304bd79SP Dheeraj Srujan Kumar                     {
393b304bd79SP Dheeraj Srujan Kumar                         bool validId = false;
394b304bd79SP Dheeraj Srujan Kumar 
395b304bd79SP Dheeraj Srujan Kumar                         // Check for Message ID in each of the selected Registry
396b304bd79SP Dheeraj Srujan Kumar                         for (const std::string& it : registryPrefix)
397b304bd79SP Dheeraj Srujan Kumar                         {
398b304bd79SP Dheeraj Srujan Kumar                             const boost::beast::span<
399b304bd79SP Dheeraj Srujan Kumar                                 const redfish::message_registries::MessageEntry>
4007e860f15SJohn Edward Broadbent                                 registry = redfish::message_registries::
4017e860f15SJohn Edward Broadbent                                     getRegistryFromPrefix(it);
402b304bd79SP Dheeraj Srujan Kumar 
403b304bd79SP Dheeraj Srujan Kumar                             if (std::any_of(
404b304bd79SP Dheeraj Srujan Kumar                                     registry.cbegin(), registry.cend(),
4057e860f15SJohn Edward Broadbent                                     [&id](const redfish::message_registries::
4067e860f15SJohn Edward Broadbent                                               MessageEntry& messageEntry) {
407b304bd79SP Dheeraj Srujan Kumar                                         return !id.compare(messageEntry.first);
408b304bd79SP Dheeraj Srujan Kumar                                     }))
409b304bd79SP Dheeraj Srujan Kumar                             {
410b304bd79SP Dheeraj Srujan Kumar                                 validId = true;
411b304bd79SP Dheeraj Srujan Kumar                                 break;
412b304bd79SP Dheeraj Srujan Kumar                             }
413b304bd79SP Dheeraj Srujan Kumar                         }
414b304bd79SP Dheeraj Srujan Kumar 
415b304bd79SP Dheeraj Srujan Kumar                         if (!validId)
416b304bd79SP Dheeraj Srujan Kumar                         {
417b304bd79SP Dheeraj Srujan Kumar                             messages::propertyValueNotInList(asyncResp->res, id,
418b304bd79SP Dheeraj Srujan Kumar                                                              "MessageIds");
419b304bd79SP Dheeraj Srujan Kumar                             return;
420b304bd79SP Dheeraj Srujan Kumar                         }
421b304bd79SP Dheeraj Srujan Kumar                     }
422b304bd79SP Dheeraj Srujan Kumar 
423b52664e2SAppaRao Puli                     subValue->registryMsgIds = *msgIds;
424e5aaf047SAppaRao Puli                 }
425e5aaf047SAppaRao Puli 
426e5aaf047SAppaRao Puli                 if (retryPolicy)
427e5aaf047SAppaRao Puli                 {
428e5aaf047SAppaRao Puli                     if (std::find(supportedRetryPolicies.begin(),
429e5aaf047SAppaRao Puli                                   supportedRetryPolicies.end(),
430e5aaf047SAppaRao Puli                                   *retryPolicy) == supportedRetryPolicies.end())
431e5aaf047SAppaRao Puli                     {
4327e860f15SJohn Edward Broadbent                         messages::propertyValueNotInList(asyncResp->res,
4337e860f15SJohn Edward Broadbent                                                          *retryPolicy,
434e5aaf047SAppaRao Puli                                                          "DeliveryRetryPolicy");
435e5aaf047SAppaRao Puli                         return;
436e5aaf047SAppaRao Puli                     }
437b52664e2SAppaRao Puli                     subValue->retryPolicy = *retryPolicy;
438e5aaf047SAppaRao Puli                 }
439e5aaf047SAppaRao Puli                 else
440e5aaf047SAppaRao Puli                 {
441e5aaf047SAppaRao Puli                     // Default "TerminateAfterRetries"
442b52664e2SAppaRao Puli                     subValue->retryPolicy = "TerminateAfterRetries";
443e5aaf047SAppaRao Puli                 }
444e5aaf047SAppaRao Puli 
445144b6318SAppaRao Puli                 if (mrdJsonArray)
446156d6b00SAppaRao Puli                 {
447144b6318SAppaRao Puli                     for (nlohmann::json& mrdObj : *mrdJsonArray)
448144b6318SAppaRao Puli                     {
449144b6318SAppaRao Puli                         std::string mrdUri;
4507e860f15SJohn Edward Broadbent                         if (json_util::getValueFromJsonObject(
4517e860f15SJohn Edward Broadbent                                 mrdObj, "@odata.id", mrdUri))
452144b6318SAppaRao Puli                         {
4537e860f15SJohn Edward Broadbent                             subValue->metricReportDefinitions.emplace_back(
4547e860f15SJohn Edward Broadbent                                 mrdUri);
455144b6318SAppaRao Puli                         }
456144b6318SAppaRao Puli                         else
457144b6318SAppaRao Puli                         {
458144b6318SAppaRao Puli                             messages::propertyValueFormatError(
45971f52d96SEd Tanous                                 asyncResp->res,
4607e860f15SJohn Edward Broadbent                                 mrdObj.dump(
4617e860f15SJohn Edward Broadbent                                     2, ' ', true,
46271f52d96SEd Tanous                                     nlohmann::json::error_handler_t::replace),
463144b6318SAppaRao Puli                                 "MetricReportDefinitions");
464144b6318SAppaRao Puli                             return;
465144b6318SAppaRao Puli                         }
466144b6318SAppaRao Puli                     }
467156d6b00SAppaRao Puli                 }
468156d6b00SAppaRao Puli 
469b52664e2SAppaRao Puli                 std::string id =
4707e860f15SJohn Edward Broadbent                     EventServiceManager::getInstance().addSubscription(
4717e860f15SJohn Edward Broadbent                         subValue);
472b52664e2SAppaRao Puli                 if (id.empty())
473e5aaf047SAppaRao Puli                 {
474e5aaf047SAppaRao Puli                     messages::internalError(asyncResp->res);
475e5aaf047SAppaRao Puli                     return;
476e5aaf047SAppaRao Puli                 }
477e5aaf047SAppaRao Puli 
478e5aaf047SAppaRao Puli                 messages::created(asyncResp->res);
479e5aaf047SAppaRao Puli                 asyncResp->res.addHeader(
480e5aaf047SAppaRao Puli                     "Location", "/redfish/v1/EventService/Subscriptions/" + id);
4817e860f15SJohn Edward Broadbent             });
482e5aaf047SAppaRao Puli }
483e5aaf047SAppaRao Puli 
4847e860f15SJohn Edward Broadbent inline void requestRoutesEventDestination(App& app)
485e5aaf047SAppaRao Puli {
4869552547cSChicago Duan     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
487*432a890cSEd Tanous         .privileges({{"Login"}})
4887e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
4897e860f15SJohn Edward Broadbent             [](const crow::Request&,
4907e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
4917e860f15SJohn Edward Broadbent                const std::string& param) {
492b52664e2SAppaRao Puli                 std::shared_ptr<Subscription> subValue =
4937e860f15SJohn Edward Broadbent                     EventServiceManager::getInstance().getSubscription(param);
494b52664e2SAppaRao Puli                 if (subValue == nullptr)
495e5aaf047SAppaRao Puli                 {
4967e860f15SJohn Edward Broadbent                     asyncResp->res.result(
4977e860f15SJohn Edward Broadbent                         boost::beast::http::status::not_found);
498e5aaf047SAppaRao Puli                     return;
499e5aaf047SAppaRao Puli                 }
5007e860f15SJohn Edward Broadbent                 const std::string& id = param;
501e5aaf047SAppaRao Puli 
5028d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
5037e860f15SJohn Edward Broadbent                     {"@odata.type",
5047e860f15SJohn Edward Broadbent                      "#EventDestination.v1_7_0.EventDestination"},
505e5aaf047SAppaRao Puli                     {"Protocol", "Redfish"}};
506e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["@odata.id"] =
507e5aaf047SAppaRao Puli                     "/redfish/v1/EventService/Subscriptions/" + id;
508e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["Id"] = id;
509e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
5107e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["Destination"] =
5117e860f15SJohn Edward Broadbent                     subValue->destinationUrl;
512b52664e2SAppaRao Puli                 asyncResp->res.jsonValue["Context"] = subValue->customText;
513e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["SubscriptionType"] =
514b52664e2SAppaRao Puli                     subValue->subscriptionType;
515b52664e2SAppaRao Puli                 asyncResp->res.jsonValue["HttpHeaders"] = subValue->httpHeaders;
5167e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["EventFormatType"] =
5177e860f15SJohn Edward Broadbent                     subValue->eventFormatType;
518e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["RegistryPrefixes"] =
519b52664e2SAppaRao Puli                     subValue->registryPrefixes;
5207e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["ResourceTypes"] =
5217e860f15SJohn Edward Broadbent                     subValue->resourceTypes;
522e56f254cSSunitha Harish 
5237e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["MessageIds"] =
5247e860f15SJohn Edward Broadbent                     subValue->registryMsgIds;
5257e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["DeliveryRetryPolicy"] =
5267e860f15SJohn Edward Broadbent                     subValue->retryPolicy;
527144b6318SAppaRao Puli 
528144b6318SAppaRao Puli                 std::vector<nlohmann::json> mrdJsonArray;
529144b6318SAppaRao Puli                 for (const auto& mdrUri : subValue->metricReportDefinitions)
530144b6318SAppaRao Puli                 {
531144b6318SAppaRao Puli                     mrdJsonArray.push_back({{"@odata.id", mdrUri}});
532144b6318SAppaRao Puli                 }
5337e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["MetricReportDefinitions"] =
5347e860f15SJohn Edward Broadbent                     mrdJsonArray;
5357e860f15SJohn Edward Broadbent             });
5367e860f15SJohn Edward Broadbent     /////redfish/v1/EventService/Subscriptions/
5377e860f15SJohn Edward Broadbent     // ConfigureManager
5389552547cSChicago Duan     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
539*432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
5407e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
5417e860f15SJohn Edward Broadbent             [](const crow::Request& req,
5427e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
5437e860f15SJohn Edward Broadbent                const std::string& param) {
544b52664e2SAppaRao Puli                 std::shared_ptr<Subscription> subValue =
5457e860f15SJohn Edward Broadbent                     EventServiceManager::getInstance().getSubscription(param);
546b52664e2SAppaRao Puli                 if (subValue == nullptr)
547e5aaf047SAppaRao Puli                 {
5487e860f15SJohn Edward Broadbent                     asyncResp->res.result(
5497e860f15SJohn Edward Broadbent                         boost::beast::http::status::not_found);
550e5aaf047SAppaRao Puli                     return;
551e5aaf047SAppaRao Puli                 }
552e5aaf047SAppaRao Puli 
553e5aaf047SAppaRao Puli                 std::optional<std::string> context;
554e5aaf047SAppaRao Puli                 std::optional<std::string> retryPolicy;
555e5aaf047SAppaRao Puli                 std::optional<std::vector<nlohmann::json>> headers;
556e5aaf047SAppaRao Puli 
5577e860f15SJohn Edward Broadbent                 if (!json_util::readJson(req, asyncResp->res, "Context",
5587e860f15SJohn Edward Broadbent                                          context, "DeliveryRetryPolicy",
5597e860f15SJohn Edward Broadbent                                          retryPolicy, "HttpHeaders", headers))
560e5aaf047SAppaRao Puli                 {
561e5aaf047SAppaRao Puli                     return;
562e5aaf047SAppaRao Puli                 }
563e5aaf047SAppaRao Puli 
564e5aaf047SAppaRao Puli                 if (context)
565e5aaf047SAppaRao Puli                 {
566b52664e2SAppaRao Puli                     subValue->customText = *context;
567e5aaf047SAppaRao Puli                 }
568e5aaf047SAppaRao Puli 
569e5aaf047SAppaRao Puli                 if (headers)
570e5aaf047SAppaRao Puli                 {
571b52664e2SAppaRao Puli                     subValue->httpHeaders = *headers;
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                     {
5807e860f15SJohn Edward Broadbent                         messages::propertyValueNotInList(asyncResp->res,
5817e860f15SJohn Edward Broadbent                                                          *retryPolicy,
582e5aaf047SAppaRao Puli                                                          "DeliveryRetryPolicy");
583e5aaf047SAppaRao Puli                         return;
584e5aaf047SAppaRao Puli                     }
585b52664e2SAppaRao Puli                     subValue->retryPolicy = *retryPolicy;
586fe44eb0bSAyushi Smriti                     subValue->updateRetryPolicy();
587e5aaf047SAppaRao Puli                 }
588e5aaf047SAppaRao Puli 
589b52664e2SAppaRao Puli                 EventServiceManager::getInstance().updateSubscriptionData();
5907e860f15SJohn Edward Broadbent             });
5919552547cSChicago Duan     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
592*432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
5937e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
5947e860f15SJohn Edward Broadbent             [](const crow::Request&,
5957e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
5967e860f15SJohn Edward Broadbent                const std::string& param) {
5977e860f15SJohn Edward Broadbent                 if (!EventServiceManager::getInstance().isSubscriptionExist(
5987e860f15SJohn Edward Broadbent                         param))
599e5aaf047SAppaRao Puli                 {
6007e860f15SJohn Edward Broadbent                     asyncResp->res.result(
6017e860f15SJohn Edward Broadbent                         boost::beast::http::status::not_found);
602e5aaf047SAppaRao Puli                     return;
603e5aaf047SAppaRao Puli                 }
6047e860f15SJohn Edward Broadbent                 EventServiceManager::getInstance().deleteSubscription(param);
6057e860f15SJohn Edward Broadbent             });
606e5aaf047SAppaRao Puli }
607e5aaf047SAppaRao Puli 
608e5aaf047SAppaRao Puli } // namespace redfish
609