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>
20*ed398213SEd Tanous #include <registries/privilege_registry.hpp>
21*ed398213SEd Tanous 
22e5aaf047SAppaRao Puli namespace redfish
23e5aaf047SAppaRao Puli {
24e5aaf047SAppaRao Puli 
25156d6b00SAppaRao Puli static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
26156d6b00SAppaRao Puli     eventFormatType, metricReportFormatType};
27e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
28b304bd79SP Dheeraj Srujan Kumar     "Base", "OpenBMC", "TaskEvent"};
29e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
30e5aaf047SAppaRao Puli     "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
31e5aaf047SAppaRao Puli 
32e56f254cSSunitha Harish #ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
33e56f254cSSunitha Harish static constexpr const std::array<const char*, 2> supportedResourceTypes = {
34e56f254cSSunitha Harish     "IBMConfigFile", "Task"};
35e56f254cSSunitha Harish #else
36e56f254cSSunitha Harish static constexpr const std::array<const char*, 1> supportedResourceTypes = {
37e56f254cSSunitha Harish     "Task"};
38e56f254cSSunitha Harish #endif
39e56f254cSSunitha Harish 
40e5aaf047SAppaRao Puli static constexpr const uint8_t maxNoOfSubscriptions = 20;
41e5aaf047SAppaRao Puli 
427e860f15SJohn Edward Broadbent inline void requestRoutesEventService(App& app)
43e5aaf047SAppaRao Puli {
447e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
45*ed398213SEd Tanous         .privileges(redfish::privileges::getEventService)
467e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
477e860f15SJohn Edward Broadbent             [](const crow::Request&,
487e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
498d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
50e5aaf047SAppaRao Puli                     {"@odata.type", "#EventService.v1_5_0.EventService"},
51e5aaf047SAppaRao Puli                     {"Id", "EventService"},
52e5aaf047SAppaRao Puli                     {"Name", "Event Service"},
53e5aaf047SAppaRao Puli                     {"Subscriptions",
54e5aaf047SAppaRao Puli                      {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}},
550b4bdd93SAppaRao Puli                     {"Actions",
560b4bdd93SAppaRao Puli                      {{"#EventService.SubmitTestEvent",
570b4bdd93SAppaRao Puli                        {{"target", "/redfish/v1/EventService/Actions/"
580b4bdd93SAppaRao Puli                                    "EventService.SubmitTestEvent"}}}}},
59e5aaf047SAppaRao Puli                     {"@odata.id", "/redfish/v1/EventService"}};
60e5aaf047SAppaRao Puli 
617d1cc387SAppaRao Puli                 const auto& [enabled, retryAttempts, retryTimeoutInterval] =
627d1cc387SAppaRao Puli                     EventServiceManager::getInstance().getEventServiceConfig();
637d1cc387SAppaRao Puli 
647d1cc387SAppaRao Puli                 asyncResp->res.jsonValue["Status"]["State"] =
657d1cc387SAppaRao Puli                     (enabled ? "Enabled" : "Disabled");
667d1cc387SAppaRao Puli                 asyncResp->res.jsonValue["ServiceEnabled"] = enabled;
677e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
687e860f15SJohn Edward Broadbent                     retryAttempts;
69e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
707d1cc387SAppaRao Puli                     retryTimeoutInterval;
717e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["EventFormatTypes"] =
727e860f15SJohn Edward Broadbent                     supportedEvtFormatTypes;
737e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["RegistryPrefixes"] =
747e860f15SJohn Edward Broadbent                     supportedRegPrefixes;
757e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["ResourceTypes"] =
767e860f15SJohn Edward Broadbent                     supportedResourceTypes;
7707941a88SAyushi Smriti 
7807941a88SAyushi Smriti                 nlohmann::json supportedSSEFilters = {
7907941a88SAyushi Smriti                     {"EventFormatType", true},        {"MessageId", true},
8007941a88SAyushi Smriti                     {"MetricReportDefinition", true}, {"RegistryPrefix", true},
8107941a88SAyushi Smriti                     {"OriginResource", false},        {"ResourceType", false}};
8207941a88SAyushi Smriti 
8307941a88SAyushi Smriti                 asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
8407941a88SAyushi Smriti                     supportedSSEFilters;
857e860f15SJohn Edward Broadbent             });
86e5aaf047SAppaRao Puli 
877e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
88*ed398213SEd Tanous         .privileges(redfish::privileges::patchEventService)
897e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
907e860f15SJohn Edward Broadbent             [](const crow::Request& req,
917e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
927e860f15SJohn Edward Broadbent 
93e5aaf047SAppaRao Puli             {
94e5aaf047SAppaRao Puli                 std::optional<bool> serviceEnabled;
95e5aaf047SAppaRao Puli                 std::optional<uint32_t> retryAttemps;
96e5aaf047SAppaRao Puli                 std::optional<uint32_t> retryInterval;
97e5aaf047SAppaRao Puli 
987e860f15SJohn Edward Broadbent                 if (!json_util::readJson(
997e860f15SJohn Edward Broadbent                         req, asyncResp->res, "ServiceEnabled", serviceEnabled,
1007e860f15SJohn Edward Broadbent                         "DeliveryRetryAttempts", retryAttemps,
1017e860f15SJohn Edward Broadbent                         "DeliveryRetryIntervalSeconds", retryInterval))
102e5aaf047SAppaRao Puli                 {
103e5aaf047SAppaRao Puli                     return;
104e5aaf047SAppaRao Puli                 }
105e5aaf047SAppaRao Puli 
1067d1cc387SAppaRao Puli                 auto [enabled, retryCount, retryTimeoutInterval] =
1077d1cc387SAppaRao Puli                     EventServiceManager::getInstance().getEventServiceConfig();
1087d1cc387SAppaRao Puli 
109e5aaf047SAppaRao Puli                 if (serviceEnabled)
110e5aaf047SAppaRao Puli                 {
1117d1cc387SAppaRao Puli                     enabled = *serviceEnabled;
112e5aaf047SAppaRao Puli                 }
113e5aaf047SAppaRao Puli 
114e5aaf047SAppaRao Puli                 if (retryAttemps)
115e5aaf047SAppaRao Puli                 {
116e5aaf047SAppaRao Puli                     // Supported range [1-3]
117e5aaf047SAppaRao Puli                     if ((*retryAttemps < 1) || (*retryAttemps > 3))
118e5aaf047SAppaRao Puli                     {
119e5aaf047SAppaRao Puli                         messages::queryParameterOutOfRange(
120e5aaf047SAppaRao Puli                             asyncResp->res, std::to_string(*retryAttemps),
121e5aaf047SAppaRao Puli                             "DeliveryRetryAttempts", "[1-3]");
122e5aaf047SAppaRao Puli                     }
123e5aaf047SAppaRao Puli                     else
124e5aaf047SAppaRao Puli                     {
1257d1cc387SAppaRao Puli                         retryCount = *retryAttemps;
126e5aaf047SAppaRao Puli                     }
127e5aaf047SAppaRao Puli                 }
128e5aaf047SAppaRao Puli 
129e5aaf047SAppaRao Puli                 if (retryInterval)
130e5aaf047SAppaRao Puli                 {
131e5aaf047SAppaRao Puli                     // Supported range [30 - 180]
132e5aaf047SAppaRao Puli                     if ((*retryInterval < 30) || (*retryInterval > 180))
133e5aaf047SAppaRao Puli                     {
134e5aaf047SAppaRao Puli                         messages::queryParameterOutOfRange(
135e5aaf047SAppaRao Puli                             asyncResp->res, std::to_string(*retryInterval),
136e5aaf047SAppaRao Puli                             "DeliveryRetryIntervalSeconds", "[30-180]");
137e5aaf047SAppaRao Puli                     }
138e5aaf047SAppaRao Puli                     else
139e5aaf047SAppaRao Puli                     {
1407d1cc387SAppaRao Puli                         retryTimeoutInterval = *retryInterval;
141e5aaf047SAppaRao Puli                     }
142e5aaf047SAppaRao Puli                 }
143e5aaf047SAppaRao Puli 
1447d1cc387SAppaRao Puli                 EventServiceManager::getInstance().setEventServiceConfig(
1457d1cc387SAppaRao Puli                     std::make_tuple(enabled, retryCount, retryTimeoutInterval));
1467e860f15SJohn Edward Broadbent             });
1470b4bdd93SAppaRao Puli }
1480b4bdd93SAppaRao Puli 
1497e860f15SJohn Edward Broadbent inline void requestRoutesSubmitTestEvent(App& app)
1500b4bdd93SAppaRao Puli {
1517e860f15SJohn Edward Broadbent 
1527e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
1537e860f15SJohn Edward Broadbent         app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
154*ed398213SEd Tanous         .privileges(redfish::privileges::postEventService)
1557e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
1567e860f15SJohn Edward Broadbent             [](const crow::Request&,
1577e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1580b4bdd93SAppaRao Puli                 EventServiceManager::getInstance().sendTestEventLog();
1598d1b46d7Szhanghch05                 asyncResp->res.result(boost::beast::http::status::no_content);
1607e860f15SJohn Edward Broadbent             });
161e5aaf047SAppaRao Puli }
162e5aaf047SAppaRao Puli 
1637e860f15SJohn Edward Broadbent inline void requestRoutesEventDestinationCollection(App& app)
164e5aaf047SAppaRao Puli {
1657e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions")
166*ed398213SEd Tanous         .privileges(redfish::privileges::getEventDestinationCollection)
1677e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
1687e860f15SJohn Edward Broadbent             [](const crow::Request&,
1697e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1708d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
171e5aaf047SAppaRao Puli                     {"@odata.type",
172e5aaf047SAppaRao Puli                      "#EventDestinationCollection.EventDestinationCollection"},
173e5aaf047SAppaRao Puli                     {"@odata.id", "/redfish/v1/EventService/Subscriptions"},
174e5aaf047SAppaRao Puli                     {"Name", "Event Destination Collections"}};
175e5aaf047SAppaRao Puli 
1767e860f15SJohn Edward Broadbent                 nlohmann::json& memberArray =
1777e860f15SJohn Edward Broadbent                     asyncResp->res.jsonValue["Members"];
178e5aaf047SAppaRao Puli 
179b52664e2SAppaRao Puli                 std::vector<std::string> subscripIds =
180b52664e2SAppaRao Puli                     EventServiceManager::getInstance().getAllIDs();
181b52664e2SAppaRao Puli                 memberArray = nlohmann::json::array();
1827e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["Members@odata.count"] =
1837e860f15SJohn Edward Broadbent                     subscripIds.size();
184b52664e2SAppaRao Puli 
185b52664e2SAppaRao Puli                 for (const std::string& id : subscripIds)
186e5aaf047SAppaRao Puli                 {
187e5aaf047SAppaRao Puli                     memberArray.push_back(
188e5aaf047SAppaRao Puli                         {{"@odata.id",
189b52664e2SAppaRao Puli                           "/redfish/v1/EventService/Subscriptions/" + id}});
190e5aaf047SAppaRao Puli                 }
1917e860f15SJohn Edward Broadbent             });
1927e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
193*ed398213SEd Tanous         // The below privilege is wrong, it should be ConfigureManager OR
194*ed398213SEd Tanous         // ConfigureComponents
195*ed398213SEd Tanous         //.privileges(redfish::privileges::postEventDestinationCollection)
196432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
1977e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
1987e860f15SJohn Edward Broadbent             [](const crow::Request& req,
1997e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2007e860f15SJohn Edward Broadbent                 if (EventServiceManager::getInstance()
2017e860f15SJohn Edward Broadbent                         .getNumberOfSubscriptions() >= maxNoOfSubscriptions)
202e5aaf047SAppaRao Puli                 {
203e5aaf047SAppaRao Puli                     messages::eventSubscriptionLimitExceeded(asyncResp->res);
204e5aaf047SAppaRao Puli                     return;
205e5aaf047SAppaRao Puli                 }
206e5aaf047SAppaRao Puli                 std::string destUrl;
207e5aaf047SAppaRao Puli                 std::string protocol;
208e5aaf047SAppaRao Puli                 std::optional<std::string> context;
209e5aaf047SAppaRao Puli                 std::optional<std::string> subscriptionType;
21023a21a1cSEd Tanous                 std::optional<std::string> eventFormatType2;
211e5aaf047SAppaRao Puli                 std::optional<std::string> retryPolicy;
212e5aaf047SAppaRao Puli                 std::optional<std::vector<std::string>> msgIds;
213e5aaf047SAppaRao Puli                 std::optional<std::vector<std::string>> regPrefixes;
214e56f254cSSunitha Harish                 std::optional<std::vector<std::string>> resTypes;
215e5aaf047SAppaRao Puli                 std::optional<std::vector<nlohmann::json>> headers;
216144b6318SAppaRao Puli                 std::optional<std::vector<nlohmann::json>> mrdJsonArray;
217e5aaf047SAppaRao Puli 
218e5aaf047SAppaRao Puli                 if (!json_util::readJson(
2197e860f15SJohn Edward Broadbent                         req, asyncResp->res, "Destination", destUrl, "Context",
2207e860f15SJohn Edward Broadbent                         context, "Protocol", protocol, "SubscriptionType",
2217e860f15SJohn Edward Broadbent                         subscriptionType, "EventFormatType", eventFormatType2,
2227e860f15SJohn Edward Broadbent                         "HttpHeaders", headers, "RegistryPrefixes", regPrefixes,
2237e860f15SJohn Edward Broadbent                         "MessageIds", msgIds, "DeliveryRetryPolicy",
2247e860f15SJohn Edward Broadbent                         retryPolicy, "MetricReportDefinitions", mrdJsonArray,
2257e860f15SJohn Edward Broadbent                         "ResourceTypes", resTypes))
226e5aaf047SAppaRao Puli                 {
227e5aaf047SAppaRao Puli                     return;
228e5aaf047SAppaRao Puli                 }
229e5aaf047SAppaRao Puli 
230dd28ba82SAppaRao Puli                 if (regPrefixes && msgIds)
231dd28ba82SAppaRao Puli                 {
232dd28ba82SAppaRao Puli                     if (regPrefixes->size() && msgIds->size())
233dd28ba82SAppaRao Puli                     {
234dd28ba82SAppaRao Puli                         messages::mutualExclusiveProperties(
235dd28ba82SAppaRao Puli                             asyncResp->res, "RegistryPrefixes", "MessageIds");
236dd28ba82SAppaRao Puli                         return;
237dd28ba82SAppaRao Puli                     }
238dd28ba82SAppaRao Puli                 }
239dd28ba82SAppaRao Puli 
240e5aaf047SAppaRao Puli                 // Validate the URL using regex expression
241b52664e2SAppaRao Puli                 // Format: <protocol>://<host>:<port>/<uri>
242b52664e2SAppaRao Puli                 // protocol: http/https
243b52664e2SAppaRao Puli                 // host: Exclude ' ', ':', '#', '?'
2444e0453b1SGunnar Mills                 // port: Empty or numeric value with ':' separator.
245b52664e2SAppaRao Puli                 // uri: Start with '/' and Exclude '#', ' '
246b52664e2SAppaRao Puli                 //      Can include query params(ex: '/event?test=1')
247b52664e2SAppaRao Puli                 // TODO: Need to validate hostname extensively(as per rfc)
248b52664e2SAppaRao Puli                 const std::regex urlRegex(
249b52664e2SAppaRao Puli                     "(http|https)://([^/\\x20\\x3f\\x23\\x3a]+):?([0-9]*)(/"
250b52664e2SAppaRao Puli                     "([^\\x20\\x23\\x3f]*\\x3f?([^\\x20\\x23\\x3f])*)?)");
251b52664e2SAppaRao Puli                 std::cmatch match;
252b52664e2SAppaRao Puli                 if (!std::regex_match(destUrl.c_str(), match, urlRegex))
253e5aaf047SAppaRao Puli                 {
254e5aaf047SAppaRao Puli                     messages::propertyValueFormatError(asyncResp->res, destUrl,
255e5aaf047SAppaRao Puli                                                        "Destination");
256e5aaf047SAppaRao Puli                     return;
257e5aaf047SAppaRao Puli                 }
258b52664e2SAppaRao Puli 
2597e860f15SJohn Edward Broadbent                 std::string uriProto =
2607e860f15SJohn Edward Broadbent                     std::string(match[1].first, match[1].second);
261b52664e2SAppaRao Puli                 if (uriProto == "http")
262b52664e2SAppaRao Puli                 {
263b52664e2SAppaRao Puli #ifndef BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING
264b52664e2SAppaRao Puli                     messages::propertyValueFormatError(asyncResp->res, destUrl,
265b52664e2SAppaRao Puli                                                        "Destination");
266b52664e2SAppaRao Puli                     return;
267b52664e2SAppaRao Puli #endif
268b52664e2SAppaRao Puli                 }
269b52664e2SAppaRao Puli 
270b52664e2SAppaRao Puli                 std::string host = std::string(match[2].first, match[2].second);
271b52664e2SAppaRao Puli                 std::string port = std::string(match[3].first, match[3].second);
272b52664e2SAppaRao Puli                 std::string path = std::string(match[4].first, match[4].second);
273b52664e2SAppaRao Puli                 if (port.empty())
274b52664e2SAppaRao Puli                 {
275b52664e2SAppaRao Puli                     if (uriProto == "http")
276b52664e2SAppaRao Puli                     {
277b52664e2SAppaRao Puli                         port = "80";
278b52664e2SAppaRao Puli                     }
279b52664e2SAppaRao Puli                     else
280b52664e2SAppaRao Puli                     {
281b52664e2SAppaRao Puli                         port = "443";
282b52664e2SAppaRao Puli                     }
283b52664e2SAppaRao Puli                 }
284b52664e2SAppaRao Puli                 if (path.empty())
285b52664e2SAppaRao Puli                 {
286b52664e2SAppaRao Puli                     path = "/";
287b52664e2SAppaRao Puli                 }
288b52664e2SAppaRao Puli 
289b52664e2SAppaRao Puli                 std::shared_ptr<Subscription> subValue =
290b52664e2SAppaRao Puli                     std::make_shared<Subscription>(host, port, path, uriProto);
291b52664e2SAppaRao Puli 
292b52664e2SAppaRao Puli                 subValue->destinationUrl = destUrl;
293e5aaf047SAppaRao Puli 
294e5aaf047SAppaRao Puli                 if (subscriptionType)
295e5aaf047SAppaRao Puli                 {
296e5aaf047SAppaRao Puli                     if (*subscriptionType != "RedfishEvent")
297e5aaf047SAppaRao Puli                     {
2987e860f15SJohn Edward Broadbent                         messages::propertyValueNotInList(asyncResp->res,
2997e860f15SJohn Edward Broadbent                                                          *subscriptionType,
3007e860f15SJohn Edward Broadbent                                                          "SubscriptionType");
301e5aaf047SAppaRao Puli                         return;
302e5aaf047SAppaRao Puli                     }
303b52664e2SAppaRao Puli                     subValue->subscriptionType = *subscriptionType;
304e5aaf047SAppaRao Puli                 }
305e5aaf047SAppaRao Puli                 else
306e5aaf047SAppaRao Puli                 {
307b52664e2SAppaRao Puli                     subValue->subscriptionType = "RedfishEvent"; // Default
308e5aaf047SAppaRao Puli                 }
309e5aaf047SAppaRao Puli 
310e5aaf047SAppaRao Puli                 if (protocol != "Redfish")
311e5aaf047SAppaRao Puli                 {
312e5aaf047SAppaRao Puli                     messages::propertyValueNotInList(asyncResp->res, protocol,
313e5aaf047SAppaRao Puli                                                      "Protocol");
314e5aaf047SAppaRao Puli                     return;
315e5aaf047SAppaRao Puli                 }
316b52664e2SAppaRao Puli                 subValue->protocol = protocol;
317e5aaf047SAppaRao Puli 
31823a21a1cSEd Tanous                 if (eventFormatType2)
319e5aaf047SAppaRao Puli                 {
320e5aaf047SAppaRao Puli                     if (std::find(supportedEvtFormatTypes.begin(),
321e5aaf047SAppaRao Puli                                   supportedEvtFormatTypes.end(),
3227e860f15SJohn Edward Broadbent                                   *eventFormatType2) ==
3237e860f15SJohn Edward Broadbent                         supportedEvtFormatTypes.end())
324e5aaf047SAppaRao Puli                     {
3257e860f15SJohn Edward Broadbent                         messages::propertyValueNotInList(asyncResp->res,
3267e860f15SJohn Edward Broadbent                                                          *eventFormatType2,
3277e860f15SJohn Edward Broadbent                                                          "EventFormatType");
328e5aaf047SAppaRao Puli                         return;
329e5aaf047SAppaRao Puli                     }
33023a21a1cSEd Tanous                     subValue->eventFormatType = *eventFormatType2;
331e5aaf047SAppaRao Puli                 }
332e5aaf047SAppaRao Puli                 else
333e5aaf047SAppaRao Puli                 {
334e5aaf047SAppaRao Puli                     // If not specified, use default "Event"
33523a21a1cSEd Tanous                     subValue->eventFormatType = "Event";
336e5aaf047SAppaRao Puli                 }
337e5aaf047SAppaRao Puli 
338e5aaf047SAppaRao Puli                 if (context)
339e5aaf047SAppaRao Puli                 {
340b52664e2SAppaRao Puli                     subValue->customText = *context;
341e5aaf047SAppaRao Puli                 }
342e5aaf047SAppaRao Puli 
343e5aaf047SAppaRao Puli                 if (headers)
344e5aaf047SAppaRao Puli                 {
345b52664e2SAppaRao Puli                     subValue->httpHeaders = *headers;
346e5aaf047SAppaRao Puli                 }
347e5aaf047SAppaRao Puli 
348e5aaf047SAppaRao Puli                 if (regPrefixes)
349e5aaf047SAppaRao Puli                 {
350e5aaf047SAppaRao Puli                     for (const std::string& it : *regPrefixes)
351e5aaf047SAppaRao Puli                     {
352e5aaf047SAppaRao Puli                         if (std::find(supportedRegPrefixes.begin(),
353e5aaf047SAppaRao Puli                                       supportedRegPrefixes.end(),
354e5aaf047SAppaRao Puli                                       it) == supportedRegPrefixes.end())
355e5aaf047SAppaRao Puli                         {
3567e860f15SJohn Edward Broadbent                             messages::propertyValueNotInList(
3577e860f15SJohn Edward Broadbent                                 asyncResp->res, it, "RegistryPrefixes");
358e5aaf047SAppaRao Puli                             return;
359e5aaf047SAppaRao Puli                         }
360e5aaf047SAppaRao Puli                     }
361b52664e2SAppaRao Puli                     subValue->registryPrefixes = *regPrefixes;
362e5aaf047SAppaRao Puli                 }
363e5aaf047SAppaRao Puli 
364e56f254cSSunitha Harish                 if (resTypes)
365e56f254cSSunitha Harish                 {
366e56f254cSSunitha Harish                     for (const std::string& it : *resTypes)
367e56f254cSSunitha Harish                     {
368e56f254cSSunitha Harish                         if (std::find(supportedResourceTypes.begin(),
369e56f254cSSunitha Harish                                       supportedResourceTypes.end(),
370e56f254cSSunitha Harish                                       it) == supportedResourceTypes.end())
371e56f254cSSunitha Harish                         {
372e56f254cSSunitha Harish                             messages::propertyValueNotInList(asyncResp->res, it,
373e56f254cSSunitha Harish                                                              "ResourceTypes");
374e56f254cSSunitha Harish                             return;
375e56f254cSSunitha Harish                         }
376e56f254cSSunitha Harish                     }
377e56f254cSSunitha Harish                     subValue->resourceTypes = *resTypes;
378e56f254cSSunitha Harish                 }
379e56f254cSSunitha Harish 
380e5aaf047SAppaRao Puli                 if (msgIds)
381e5aaf047SAppaRao Puli                 {
382b304bd79SP Dheeraj Srujan Kumar                     std::vector<std::string> registryPrefix;
383b304bd79SP Dheeraj Srujan Kumar 
3847e860f15SJohn Edward Broadbent                     // If no registry prefixes are mentioned, consider all
3857e860f15SJohn Edward Broadbent                     // supported prefixes
386b304bd79SP Dheeraj Srujan Kumar                     if (subValue->registryPrefixes.empty())
387b304bd79SP Dheeraj Srujan Kumar                     {
388b304bd79SP Dheeraj Srujan Kumar                         registryPrefix.assign(supportedRegPrefixes.begin(),
389b304bd79SP Dheeraj Srujan Kumar                                               supportedRegPrefixes.end());
390b304bd79SP Dheeraj Srujan Kumar                     }
391b304bd79SP Dheeraj Srujan Kumar                     else
392b304bd79SP Dheeraj Srujan Kumar                     {
393b304bd79SP Dheeraj Srujan Kumar                         registryPrefix = subValue->registryPrefixes;
394b304bd79SP Dheeraj Srujan Kumar                     }
395b304bd79SP Dheeraj Srujan Kumar 
396b304bd79SP Dheeraj Srujan Kumar                     for (const std::string& id : *msgIds)
397b304bd79SP Dheeraj Srujan Kumar                     {
398b304bd79SP Dheeraj Srujan Kumar                         bool validId = false;
399b304bd79SP Dheeraj Srujan Kumar 
400b304bd79SP Dheeraj Srujan Kumar                         // Check for Message ID in each of the selected Registry
401b304bd79SP Dheeraj Srujan Kumar                         for (const std::string& it : registryPrefix)
402b304bd79SP Dheeraj Srujan Kumar                         {
403b304bd79SP Dheeraj Srujan Kumar                             const boost::beast::span<
404b304bd79SP Dheeraj Srujan Kumar                                 const redfish::message_registries::MessageEntry>
4057e860f15SJohn Edward Broadbent                                 registry = redfish::message_registries::
4067e860f15SJohn Edward Broadbent                                     getRegistryFromPrefix(it);
407b304bd79SP Dheeraj Srujan Kumar 
408b304bd79SP Dheeraj Srujan Kumar                             if (std::any_of(
409b304bd79SP Dheeraj Srujan Kumar                                     registry.cbegin(), registry.cend(),
4107e860f15SJohn Edward Broadbent                                     [&id](const redfish::message_registries::
4117e860f15SJohn Edward Broadbent                                               MessageEntry& messageEntry) {
412b304bd79SP Dheeraj Srujan Kumar                                         return !id.compare(messageEntry.first);
413b304bd79SP Dheeraj Srujan Kumar                                     }))
414b304bd79SP Dheeraj Srujan Kumar                             {
415b304bd79SP Dheeraj Srujan Kumar                                 validId = true;
416b304bd79SP Dheeraj Srujan Kumar                                 break;
417b304bd79SP Dheeraj Srujan Kumar                             }
418b304bd79SP Dheeraj Srujan Kumar                         }
419b304bd79SP Dheeraj Srujan Kumar 
420b304bd79SP Dheeraj Srujan Kumar                         if (!validId)
421b304bd79SP Dheeraj Srujan Kumar                         {
422b304bd79SP Dheeraj Srujan Kumar                             messages::propertyValueNotInList(asyncResp->res, id,
423b304bd79SP Dheeraj Srujan Kumar                                                              "MessageIds");
424b304bd79SP Dheeraj Srujan Kumar                             return;
425b304bd79SP Dheeraj Srujan Kumar                         }
426b304bd79SP Dheeraj Srujan Kumar                     }
427b304bd79SP Dheeraj Srujan Kumar 
428b52664e2SAppaRao Puli                     subValue->registryMsgIds = *msgIds;
429e5aaf047SAppaRao Puli                 }
430e5aaf047SAppaRao Puli 
431e5aaf047SAppaRao Puli                 if (retryPolicy)
432e5aaf047SAppaRao Puli                 {
433e5aaf047SAppaRao Puli                     if (std::find(supportedRetryPolicies.begin(),
434e5aaf047SAppaRao Puli                                   supportedRetryPolicies.end(),
435e5aaf047SAppaRao Puli                                   *retryPolicy) == supportedRetryPolicies.end())
436e5aaf047SAppaRao Puli                     {
4377e860f15SJohn Edward Broadbent                         messages::propertyValueNotInList(asyncResp->res,
4387e860f15SJohn Edward Broadbent                                                          *retryPolicy,
439e5aaf047SAppaRao Puli                                                          "DeliveryRetryPolicy");
440e5aaf047SAppaRao Puli                         return;
441e5aaf047SAppaRao Puli                     }
442b52664e2SAppaRao Puli                     subValue->retryPolicy = *retryPolicy;
443e5aaf047SAppaRao Puli                 }
444e5aaf047SAppaRao Puli                 else
445e5aaf047SAppaRao Puli                 {
446e5aaf047SAppaRao Puli                     // Default "TerminateAfterRetries"
447b52664e2SAppaRao Puli                     subValue->retryPolicy = "TerminateAfterRetries";
448e5aaf047SAppaRao Puli                 }
449e5aaf047SAppaRao Puli 
450144b6318SAppaRao Puli                 if (mrdJsonArray)
451156d6b00SAppaRao Puli                 {
452144b6318SAppaRao Puli                     for (nlohmann::json& mrdObj : *mrdJsonArray)
453144b6318SAppaRao Puli                     {
454144b6318SAppaRao Puli                         std::string mrdUri;
4557e860f15SJohn Edward Broadbent                         if (json_util::getValueFromJsonObject(
4567e860f15SJohn Edward Broadbent                                 mrdObj, "@odata.id", mrdUri))
457144b6318SAppaRao Puli                         {
4587e860f15SJohn Edward Broadbent                             subValue->metricReportDefinitions.emplace_back(
4597e860f15SJohn Edward Broadbent                                 mrdUri);
460144b6318SAppaRao Puli                         }
461144b6318SAppaRao Puli                         else
462144b6318SAppaRao Puli                         {
463144b6318SAppaRao Puli                             messages::propertyValueFormatError(
46471f52d96SEd Tanous                                 asyncResp->res,
4657e860f15SJohn Edward Broadbent                                 mrdObj.dump(
4667e860f15SJohn Edward Broadbent                                     2, ' ', true,
46771f52d96SEd Tanous                                     nlohmann::json::error_handler_t::replace),
468144b6318SAppaRao Puli                                 "MetricReportDefinitions");
469144b6318SAppaRao Puli                             return;
470144b6318SAppaRao Puli                         }
471144b6318SAppaRao Puli                     }
472156d6b00SAppaRao Puli                 }
473156d6b00SAppaRao Puli 
474b52664e2SAppaRao Puli                 std::string id =
4757e860f15SJohn Edward Broadbent                     EventServiceManager::getInstance().addSubscription(
4767e860f15SJohn Edward Broadbent                         subValue);
477b52664e2SAppaRao Puli                 if (id.empty())
478e5aaf047SAppaRao Puli                 {
479e5aaf047SAppaRao Puli                     messages::internalError(asyncResp->res);
480e5aaf047SAppaRao Puli                     return;
481e5aaf047SAppaRao Puli                 }
482e5aaf047SAppaRao Puli 
483e5aaf047SAppaRao Puli                 messages::created(asyncResp->res);
484e5aaf047SAppaRao Puli                 asyncResp->res.addHeader(
485e5aaf047SAppaRao Puli                     "Location", "/redfish/v1/EventService/Subscriptions/" + id);
4867e860f15SJohn Edward Broadbent             });
487e5aaf047SAppaRao Puli }
488e5aaf047SAppaRao Puli 
4897e860f15SJohn Edward Broadbent inline void requestRoutesEventDestination(App& app)
490e5aaf047SAppaRao Puli {
491*ed398213SEd Tanous     BMCWEB_ROUTE(app, "redfish/v1/EventService/Subscriptions/<str>/")
492*ed398213SEd Tanous         .privileges(redfish::privileges::getEventDestination)
4937e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
4947e860f15SJohn Edward Broadbent             [](const crow::Request&,
4957e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
4967e860f15SJohn Edward Broadbent                const std::string& param) {
497b52664e2SAppaRao Puli                 std::shared_ptr<Subscription> subValue =
4987e860f15SJohn Edward Broadbent                     EventServiceManager::getInstance().getSubscription(param);
499b52664e2SAppaRao Puli                 if (subValue == nullptr)
500e5aaf047SAppaRao Puli                 {
5017e860f15SJohn Edward Broadbent                     asyncResp->res.result(
5027e860f15SJohn Edward Broadbent                         boost::beast::http::status::not_found);
503e5aaf047SAppaRao Puli                     return;
504e5aaf047SAppaRao Puli                 }
5057e860f15SJohn Edward Broadbent                 const std::string& id = param;
506e5aaf047SAppaRao Puli 
5078d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
5087e860f15SJohn Edward Broadbent                     {"@odata.type",
5097e860f15SJohn Edward Broadbent                      "#EventDestination.v1_7_0.EventDestination"},
510e5aaf047SAppaRao Puli                     {"Protocol", "Redfish"}};
511e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["@odata.id"] =
512e5aaf047SAppaRao Puli                     "/redfish/v1/EventService/Subscriptions/" + id;
513e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["Id"] = id;
514e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
5157e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["Destination"] =
5167e860f15SJohn Edward Broadbent                     subValue->destinationUrl;
517b52664e2SAppaRao Puli                 asyncResp->res.jsonValue["Context"] = subValue->customText;
518e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["SubscriptionType"] =
519b52664e2SAppaRao Puli                     subValue->subscriptionType;
520b52664e2SAppaRao Puli                 asyncResp->res.jsonValue["HttpHeaders"] = subValue->httpHeaders;
5217e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["EventFormatType"] =
5227e860f15SJohn Edward Broadbent                     subValue->eventFormatType;
523e5aaf047SAppaRao Puli                 asyncResp->res.jsonValue["RegistryPrefixes"] =
524b52664e2SAppaRao Puli                     subValue->registryPrefixes;
5257e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["ResourceTypes"] =
5267e860f15SJohn Edward Broadbent                     subValue->resourceTypes;
527e56f254cSSunitha Harish 
5287e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["MessageIds"] =
5297e860f15SJohn Edward Broadbent                     subValue->registryMsgIds;
5307e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["DeliveryRetryPolicy"] =
5317e860f15SJohn Edward Broadbent                     subValue->retryPolicy;
532144b6318SAppaRao Puli 
533144b6318SAppaRao Puli                 std::vector<nlohmann::json> mrdJsonArray;
534144b6318SAppaRao Puli                 for (const auto& mdrUri : subValue->metricReportDefinitions)
535144b6318SAppaRao Puli                 {
536144b6318SAppaRao Puli                     mrdJsonArray.push_back({{"@odata.id", mdrUri}});
537144b6318SAppaRao Puli                 }
5387e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["MetricReportDefinitions"] =
5397e860f15SJohn Edward Broadbent                     mrdJsonArray;
5407e860f15SJohn Edward Broadbent             });
5417e860f15SJohn Edward Broadbent     /////redfish/v1/EventService/Subscriptions/
5427e860f15SJohn Edward Broadbent     // ConfigureManager
543*ed398213SEd Tanous     BMCWEB_ROUTE(app, "redfish/v1/EventService/Subscriptions/<str>/")
544*ed398213SEd Tanous         // The below privilege is wrong, it should be ConfigureManager OR
545*ed398213SEd Tanous         // ConfigureSelf
546*ed398213SEd Tanous         // TODO(ed) follow up with DMTF spec and understand ConfigureSelf
547*ed398213SEd Tanous         //.privileges(redfish::privileges::patchEventDestination)
548432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
5497e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::patch)(
5507e860f15SJohn Edward Broadbent             [](const crow::Request& req,
5517e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
5527e860f15SJohn Edward Broadbent                const std::string& param) {
553b52664e2SAppaRao Puli                 std::shared_ptr<Subscription> subValue =
5547e860f15SJohn Edward Broadbent                     EventServiceManager::getInstance().getSubscription(param);
555b52664e2SAppaRao Puli                 if (subValue == nullptr)
556e5aaf047SAppaRao Puli                 {
5577e860f15SJohn Edward Broadbent                     asyncResp->res.result(
5587e860f15SJohn Edward Broadbent                         boost::beast::http::status::not_found);
559e5aaf047SAppaRao Puli                     return;
560e5aaf047SAppaRao Puli                 }
561e5aaf047SAppaRao Puli 
562e5aaf047SAppaRao Puli                 std::optional<std::string> context;
563e5aaf047SAppaRao Puli                 std::optional<std::string> retryPolicy;
564e5aaf047SAppaRao Puli                 std::optional<std::vector<nlohmann::json>> headers;
565e5aaf047SAppaRao Puli 
5667e860f15SJohn Edward Broadbent                 if (!json_util::readJson(req, asyncResp->res, "Context",
5677e860f15SJohn Edward Broadbent                                          context, "DeliveryRetryPolicy",
5687e860f15SJohn Edward Broadbent                                          retryPolicy, "HttpHeaders", headers))
569e5aaf047SAppaRao Puli                 {
570e5aaf047SAppaRao Puli                     return;
571e5aaf047SAppaRao Puli                 }
572e5aaf047SAppaRao Puli 
573e5aaf047SAppaRao Puli                 if (context)
574e5aaf047SAppaRao Puli                 {
575b52664e2SAppaRao Puli                     subValue->customText = *context;
576e5aaf047SAppaRao Puli                 }
577e5aaf047SAppaRao Puli 
578e5aaf047SAppaRao Puli                 if (headers)
579e5aaf047SAppaRao Puli                 {
580b52664e2SAppaRao Puli                     subValue->httpHeaders = *headers;
581e5aaf047SAppaRao Puli                 }
582e5aaf047SAppaRao Puli 
583e5aaf047SAppaRao Puli                 if (retryPolicy)
584e5aaf047SAppaRao Puli                 {
585e5aaf047SAppaRao Puli                     if (std::find(supportedRetryPolicies.begin(),
586e5aaf047SAppaRao Puli                                   supportedRetryPolicies.end(),
587e5aaf047SAppaRao Puli                                   *retryPolicy) == supportedRetryPolicies.end())
588e5aaf047SAppaRao Puli                     {
5897e860f15SJohn Edward Broadbent                         messages::propertyValueNotInList(asyncResp->res,
5907e860f15SJohn Edward Broadbent                                                          *retryPolicy,
591e5aaf047SAppaRao Puli                                                          "DeliveryRetryPolicy");
592e5aaf047SAppaRao Puli                         return;
593e5aaf047SAppaRao Puli                     }
594b52664e2SAppaRao Puli                     subValue->retryPolicy = *retryPolicy;
595fe44eb0bSAyushi Smriti                     subValue->updateRetryPolicy();
596e5aaf047SAppaRao Puli                 }
597e5aaf047SAppaRao Puli 
598b52664e2SAppaRao Puli                 EventServiceManager::getInstance().updateSubscriptionData();
5997e860f15SJohn Edward Broadbent             });
600*ed398213SEd Tanous     BMCWEB_ROUTE(app, "redfish/v1/EventService/Subscriptions/<str>/")
601*ed398213SEd Tanous         // The below privilege is wrong, it should be ConfigureManager OR
602*ed398213SEd Tanous         // ConfigureSelf
603*ed398213SEd Tanous         //.privileges(redfish::privileges::deleteEventDestination)
604432a890cSEd Tanous         .privileges({{"ConfigureManager"}})
6057e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
6067e860f15SJohn Edward Broadbent             [](const crow::Request&,
6077e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
6087e860f15SJohn Edward Broadbent                const std::string& param) {
6097e860f15SJohn Edward Broadbent                 if (!EventServiceManager::getInstance().isSubscriptionExist(
6107e860f15SJohn Edward Broadbent                         param))
611e5aaf047SAppaRao Puli                 {
6127e860f15SJohn Edward Broadbent                     asyncResp->res.result(
6137e860f15SJohn Edward Broadbent                         boost::beast::http::status::not_found);
614e5aaf047SAppaRao Puli                     return;
615e5aaf047SAppaRao Puli                 }
6167e860f15SJohn Edward Broadbent                 EventServiceManager::getInstance().deleteSubscription(param);
6177e860f15SJohn Edward Broadbent             });
618e5aaf047SAppaRao Puli }
619e5aaf047SAppaRao Puli 
620e5aaf047SAppaRao Puli } // namespace redfish
621