blob: 02bb21f898f6213f47a59f75ed4c27c9f72aca04 [file] [log] [blame]
AppaRao Pulie5aaf042020-03-20 01:05:52 +05301/*
2// Copyright (c) 2020 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080017#include "app.hpp"
AppaRao Pulib52664e2020-04-09 21:36:51 +053018#include "event_service_manager.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080019#include "http/utility.hpp"
20#include "logging.hpp"
21#include "query.hpp"
22#include "registries/privilege_registry.hpp"
AppaRao Pulie5aaf042020-03-20 01:05:52 +053023
Ed Tanous601c71a2021-09-08 16:40:12 -070024#include <boost/beast/http/fields.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070025
Patrick Williams1e270c52021-12-04 06:06:56 -060026#include <span>
27
AppaRao Pulie5aaf042020-03-20 01:05:52 +053028namespace redfish
29{
30
AppaRao Puli156d6b02020-04-25 06:04:05 +053031static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
32 eventFormatType, metricReportFormatType};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053033static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +053034 "Base", "OpenBMC", "TaskEvent"};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053035static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
36 "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
37
Sunitha Harishe56f2542020-07-22 02:38:59 -050038#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
39static constexpr const std::array<const char*, 2> supportedResourceTypes = {
40 "IBMConfigFile", "Task"};
41#else
42static constexpr const std::array<const char*, 1> supportedResourceTypes = {
43 "Task"};
44#endif
45
John Edward Broadbent7e860f12021-04-08 15:57:16 -070046inline void requestRoutesEventService(App& app)
AppaRao Pulie5aaf042020-03-20 01:05:52 +053047{
John Edward Broadbent7e860f12021-04-08 15:57:16 -070048 BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
Ed Tanoused398212021-06-09 17:05:54 -070049 .privileges(redfish::privileges::getEventService)
Ed Tanous002d39b2022-05-31 08:59:27 -070050 .methods(boost::beast::http::verb::get)(
51 [&app](const crow::Request& req,
52 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +000053 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -070054 {
55 return;
56 }
Ed Tanous14766872022-03-15 10:44:42 -070057
Ed Tanous002d39b2022-05-31 08:59:27 -070058 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/EventService";
59 asyncResp->res.jsonValue["@odata.type"] =
60 "#EventService.v1_5_0.EventService";
61 asyncResp->res.jsonValue["Id"] = "EventService";
62 asyncResp->res.jsonValue["Name"] = "Event Service";
AppaRao Puli5e44e3d2021-03-16 15:37:24 +000063 asyncResp->res.jsonValue["ServerSentEventUri"] =
64 "/redfish/v1/EventService/SSE";
65
Ed Tanous002d39b2022-05-31 08:59:27 -070066 asyncResp->res.jsonValue["Subscriptions"]["@odata.id"] =
67 "/redfish/v1/EventService/Subscriptions";
68 asyncResp->res
69 .jsonValue["Actions"]["#EventService.SubmitTestEvent"]["target"] =
70 "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent";
AppaRao Pulie5aaf042020-03-20 01:05:52 +053071
Ed Tanous002d39b2022-05-31 08:59:27 -070072 const persistent_data::EventServiceConfig eventServiceConfig =
73 persistent_data::EventServiceStore::getInstance()
74 .getEventServiceConfig();
zhanghch058d1b46d2021-04-01 11:18:24 +080075
Ed Tanous002d39b2022-05-31 08:59:27 -070076 asyncResp->res.jsonValue["Status"]["State"] =
77 (eventServiceConfig.enabled ? "Enabled" : "Disabled");
78 asyncResp->res.jsonValue["ServiceEnabled"] = eventServiceConfig.enabled;
79 asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
80 eventServiceConfig.retryAttempts;
81 asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
82 eventServiceConfig.retryTimeoutInterval;
83 asyncResp->res.jsonValue["EventFormatTypes"] = supportedEvtFormatTypes;
84 asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
85 asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
AppaRao Pulie5aaf042020-03-20 01:05:52 +053086
Ed Tanous613dabe2022-07-09 11:17:36 -070087 nlohmann::json::object_t supportedSSEFilters;
88 supportedSSEFilters["EventFormatType"] = true;
89 supportedSSEFilters["MessageId"] = true;
90 supportedSSEFilters["MetricReportDefinition"] = true;
91 supportedSSEFilters["RegistryPrefix"] = true;
92 supportedSSEFilters["OriginResource"] = false;
93 supportedSSEFilters["ResourceType"] = false;
AppaRao Puli7d1cc382020-05-16 02:42:22 +053094
Ed Tanous002d39b2022-05-31 08:59:27 -070095 asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
Ed Tanous613dabe2022-07-09 11:17:36 -070096 std::move(supportedSSEFilters);
George Liu0fda0f12021-11-16 10:06:17 +080097 });
Ayushi Smriti07941a82020-05-21 15:55:34 +053098
John Edward Broadbent7e860f12021-04-08 15:57:16 -070099 BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
Ed Tanoused398212021-06-09 17:05:54 -0700100 .privileges(redfish::privileges::patchEventService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700101 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700102 [&app](const crow::Request& req,
103 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000104 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700105 {
106 return;
107 }
108 std::optional<bool> serviceEnabled;
109 std::optional<uint32_t> retryAttemps;
110 std::optional<uint32_t> retryInterval;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530111
Ed Tanous002d39b2022-05-31 08:59:27 -0700112 if (!json_util::readJsonPatch(
113 req, asyncResp->res, "ServiceEnabled", serviceEnabled,
114 "DeliveryRetryAttempts", retryAttemps,
115 "DeliveryRetryIntervalSeconds", retryInterval))
116 {
117 return;
118 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530119
Ed Tanous002d39b2022-05-31 08:59:27 -0700120 persistent_data::EventServiceConfig eventServiceConfig =
121 persistent_data::EventServiceStore::getInstance()
122 .getEventServiceConfig();
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700123
Ed Tanous002d39b2022-05-31 08:59:27 -0700124 if (serviceEnabled)
125 {
126 eventServiceConfig.enabled = *serviceEnabled;
127 }
Sunitha Harishe56f2542020-07-22 02:38:59 -0500128
Ed Tanous002d39b2022-05-31 08:59:27 -0700129 if (retryAttemps)
130 {
131 // Supported range [1-3]
132 if ((*retryAttemps < 1) || (*retryAttemps > 3))
133 {
134 messages::queryParameterOutOfRange(
135 asyncResp->res, std::to_string(*retryAttemps),
136 "DeliveryRetryAttempts", "[1-3]");
137 }
138 else
139 {
140 eventServiceConfig.retryAttempts = *retryAttemps;
141 }
142 }
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530143
Ed Tanous002d39b2022-05-31 08:59:27 -0700144 if (retryInterval)
145 {
Gunnar Mills33a32b32022-11-17 14:29:07 -0600146 // Supported range [5 - 180]
147 if ((*retryInterval < 5) || (*retryInterval > 180))
Ed Tanous002d39b2022-05-31 08:59:27 -0700148 {
149 messages::queryParameterOutOfRange(
150 asyncResp->res, std::to_string(*retryInterval),
Gunnar Mills33a32b32022-11-17 14:29:07 -0600151 "DeliveryRetryIntervalSeconds", "[5-180]");
Ed Tanous002d39b2022-05-31 08:59:27 -0700152 }
153 else
154 {
155 eventServiceConfig.retryTimeoutInterval = *retryInterval;
156 }
157 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700158
Ed Tanous002d39b2022-05-31 08:59:27 -0700159 EventServiceManager::getInstance().setEventServiceConfig(
160 eventServiceConfig);
161 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700162}
163
164inline void requestRoutesSubmitTestEvent(App& app)
165{
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700166 BMCWEB_ROUTE(
167 app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
Ed Tanoused398212021-06-09 17:05:54 -0700168 .privileges(redfish::privileges::postEventService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700169 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700170 [&app](const crow::Request& req,
171 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000172 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700173 {
174 return;
175 }
176 if (!EventServiceManager::getInstance().sendTestEventLog())
177 {
178 messages::serviceDisabled(asyncResp->res,
179 "/redfish/v1/EventService/");
180 return;
181 }
182 asyncResp->res.result(boost::beast::http::status::no_content);
183 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700184}
185
186inline void requestRoutesEventDestinationCollection(App& app)
187{
Gayathri Leburu1ebe3e42022-02-09 10:45:19 +0000188 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
Ed Tanoused398212021-06-09 17:05:54 -0700189 .privileges(redfish::privileges::getEventDestinationCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700190 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700191 [&app](const crow::Request& req,
192 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000193 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700194 {
195 return;
196 }
197 asyncResp->res.jsonValue["@odata.type"] =
198 "#EventDestinationCollection.EventDestinationCollection";
199 asyncResp->res.jsonValue["@odata.id"] =
200 "/redfish/v1/EventService/Subscriptions";
201 asyncResp->res.jsonValue["Name"] = "Event Destination Collections";
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700202
Ed Tanous002d39b2022-05-31 08:59:27 -0700203 nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700204
Ed Tanous002d39b2022-05-31 08:59:27 -0700205 std::vector<std::string> subscripIds =
206 EventServiceManager::getInstance().getAllIDs();
207 memberArray = nlohmann::json::array();
208 asyncResp->res.jsonValue["Members@odata.count"] = subscripIds.size();
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700209
Ed Tanous002d39b2022-05-31 08:59:27 -0700210 for (const std::string& id : subscripIds)
211 {
212 nlohmann::json::object_t member;
Patrick Williams89492a12023-05-10 07:51:34 -0500213 member["@odata.id"] = "/redfish/v1/EventService/Subscriptions/" +
214 id;
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500215 memberArray.emplace_back(std::move(member));
Ed Tanous002d39b2022-05-31 08:59:27 -0700216 }
217 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700218 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500219 .privileges(redfish::privileges::postEventDestinationCollection)
Ed Tanous002d39b2022-05-31 08:59:27 -0700220 .methods(boost::beast::http::verb::post)(
221 [&app](const crow::Request& req,
222 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000223 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700224 {
225 return;
226 }
227 if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
228 maxNoOfSubscriptions)
229 {
230 messages::eventSubscriptionLimitExceeded(asyncResp->res);
231 return;
232 }
233 std::string destUrl;
234 std::string protocol;
235 std::optional<std::string> context;
236 std::optional<std::string> subscriptionType;
237 std::optional<std::string> eventFormatType2;
238 std::optional<std::string> retryPolicy;
239 std::optional<std::vector<std::string>> msgIds;
240 std::optional<std::vector<std::string>> regPrefixes;
241 std::optional<std::vector<std::string>> resTypes;
242 std::optional<std::vector<nlohmann::json>> headers;
243 std::optional<std::vector<nlohmann::json>> mrdJsonArray;
Ed Tanousfffb8c12022-02-07 23:53:03 -0800244
Ed Tanous002d39b2022-05-31 08:59:27 -0700245 if (!json_util::readJsonPatch(
246 req, asyncResp->res, "Destination", destUrl, "Context", context,
247 "Protocol", protocol, "SubscriptionType", subscriptionType,
248 "EventFormatType", eventFormatType2, "HttpHeaders", headers,
249 "RegistryPrefixes", regPrefixes, "MessageIds", msgIds,
250 "DeliveryRetryPolicy", retryPolicy, "MetricReportDefinitions",
251 mrdJsonArray, "ResourceTypes", resTypes))
252 {
253 return;
254 }
255
AppaRao Puli600af5f2021-10-06 21:51:16 +0000256 // https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
257 static constexpr const uint16_t maxDestinationSize = 2000;
258 if (destUrl.size() > maxDestinationSize)
259 {
260 messages::stringValueTooLong(asyncResp->res, "Destination",
261 maxDestinationSize);
262 return;
263 }
264
Ed Tanous002d39b2022-05-31 08:59:27 -0700265 if (regPrefixes && msgIds)
266 {
267 if (!regPrefixes->empty() && !msgIds->empty())
Ed Tanousfffb8c12022-02-07 23:53:03 -0800268 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700269 messages::propertyValueConflict(asyncResp->res, "MessageIds",
270 "RegistryPrefixes");
Ed Tanousfffb8c12022-02-07 23:53:03 -0800271 return;
272 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700273 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800274
Ed Tanous002d39b2022-05-31 08:59:27 -0700275 std::string host;
276 std::string urlProto;
277 uint16_t port = 0;
278 std::string path;
279
280 if (!crow::utility::validateAndSplitUrl(destUrl, urlProto, host, port,
281 path))
282 {
283 BMCWEB_LOG_WARNING
284 << "Failed to validate and split destination url";
285 messages::propertyValueFormatError(asyncResp->res, destUrl,
286 "Destination");
287 return;
288 }
289
290 if (path.empty())
291 {
292 path = "/";
293 }
Ed Tanousf8ca6d72022-06-28 12:12:03 -0700294 std::shared_ptr<Subscription> subValue = std::make_shared<Subscription>(
295 host, port, path, urlProto, app.ioContext());
Ed Tanous002d39b2022-05-31 08:59:27 -0700296
297 subValue->destinationUrl = destUrl;
298
299 if (subscriptionType)
300 {
301 if (*subscriptionType != "RedfishEvent")
Ed Tanousfffb8c12022-02-07 23:53:03 -0800302 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700303 messages::propertyValueNotInList(
304 asyncResp->res, *subscriptionType, "SubscriptionType");
305 return;
306 }
307 subValue->subscriptionType = *subscriptionType;
308 }
309 else
310 {
311 subValue->subscriptionType = "RedfishEvent"; // Default
312 }
313
314 if (protocol != "Redfish")
315 {
316 messages::propertyValueNotInList(asyncResp->res, protocol,
317 "Protocol");
318 return;
319 }
320 subValue->protocol = protocol;
321
322 if (eventFormatType2)
323 {
324 if (std::find(supportedEvtFormatTypes.begin(),
325 supportedEvtFormatTypes.end(),
326 *eventFormatType2) == supportedEvtFormatTypes.end())
327 {
328 messages::propertyValueNotInList(
329 asyncResp->res, *eventFormatType2, "EventFormatType");
330 return;
331 }
332 subValue->eventFormatType = *eventFormatType2;
333 }
334 else
335 {
336 // If not specified, use default "Event"
337 subValue->eventFormatType = "Event";
338 }
339
340 if (context)
341 {
AppaRao Puli600af5f2021-10-06 21:51:16 +0000342 // This value is selected aribitrarily.
343 constexpr const size_t maxContextSize = 256;
344 if (context->size() > maxContextSize)
345 {
346 messages::stringValueTooLong(asyncResp->res, "Context",
347 maxContextSize);
348 return;
349 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700350 subValue->customText = *context;
351 }
352
353 if (headers)
354 {
AppaRao Puli600af5f2021-10-06 21:51:16 +0000355 size_t cumulativeLen = 0;
356
Ed Tanous002d39b2022-05-31 08:59:27 -0700357 for (const nlohmann::json& headerChunk : *headers)
358 {
AppaRao Puli600af5f2021-10-06 21:51:16 +0000359 std::string hdr{headerChunk.dump(
360 -1, ' ', true, nlohmann::json::error_handler_t::replace)};
361 cumulativeLen += hdr.length();
362
363 // This value is selected to mirror http_connection.hpp
364 constexpr const uint16_t maxHeaderSizeED = 8096;
365 if (cumulativeLen > maxHeaderSizeED)
366 {
367 messages::arraySizeTooLong(asyncResp->res, "HttpHeaders",
368 maxHeaderSizeED);
369 return;
370 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700371 for (const auto& item : headerChunk.items())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700372 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700373 const std::string* value =
374 item.value().get_ptr<const std::string*>();
375 if (value == nullptr)
376 {
377 messages::propertyValueFormatError(
378 asyncResp->res, item.value().dump(2, 1),
379 "HttpHeaders/" + item.key());
380 return;
381 }
382 subValue->httpHeaders.set(item.key(), *value);
383 }
384 }
385 }
386
387 if (regPrefixes)
388 {
389 for (const std::string& it : *regPrefixes)
390 {
391 if (std::find(supportedRegPrefixes.begin(),
392 supportedRegPrefixes.end(),
393 it) == supportedRegPrefixes.end())
394 {
395 messages::propertyValueNotInList(asyncResp->res, it,
396 "RegistryPrefixes");
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530397 return;
398 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800399 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700400 subValue->registryPrefixes = *regPrefixes;
401 }
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530402
Ed Tanous002d39b2022-05-31 08:59:27 -0700403 if (resTypes)
404 {
405 for (const std::string& it : *resTypes)
Ed Tanousfffb8c12022-02-07 23:53:03 -0800406 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700407 if (std::find(supportedResourceTypes.begin(),
408 supportedResourceTypes.end(),
409 it) == supportedResourceTypes.end())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700410 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700411 messages::propertyValueNotInList(asyncResp->res, it,
412 "ResourceTypes");
AppaRao Puli144b6312020-08-03 22:23:12 +0530413 return;
414 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700415 }
416 subValue->resourceTypes = *resTypes;
417 }
418
419 if (msgIds)
420 {
421 std::vector<std::string> registryPrefix;
422
423 // If no registry prefixes are mentioned, consider all
424 // supported prefixes
425 if (subValue->registryPrefixes.empty())
426 {
427 registryPrefix.assign(supportedRegPrefixes.begin(),
428 supportedRegPrefixes.end());
Ed Tanousfffb8c12022-02-07 23:53:03 -0800429 }
430 else
431 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700432 registryPrefix = subValue->registryPrefixes;
Ed Tanousfffb8c12022-02-07 23:53:03 -0800433 }
AppaRao Puli156d6b02020-04-25 06:04:05 +0530434
Ed Tanous002d39b2022-05-31 08:59:27 -0700435 for (const std::string& id : *msgIds)
Ed Tanousfffb8c12022-02-07 23:53:03 -0800436 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700437 bool validId = false;
Ed Tanousfffb8c12022-02-07 23:53:03 -0800438
Ed Tanous002d39b2022-05-31 08:59:27 -0700439 // Check for Message ID in each of the selected Registry
440 for (const std::string& it : registryPrefix)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700441 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700442 const std::span<const redfish::registries::MessageEntry>
443 registry =
444 redfish::registries::getRegistryFromPrefix(it);
445
446 if (std::any_of(
447 registry.begin(), registry.end(),
448 [&id](const redfish::registries::MessageEntry&
449 messageEntry) {
450 return id == messageEntry.first;
451 }))
452 {
453 validId = true;
454 break;
455 }
456 }
457
458 if (!validId)
459 {
460 messages::propertyValueNotInList(asyncResp->res, id,
461 "MessageIds");
Ed Tanousfffb8c12022-02-07 23:53:03 -0800462 return;
463 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800464 }
465
Ed Tanous002d39b2022-05-31 08:59:27 -0700466 subValue->registryMsgIds = *msgIds;
467 }
468
469 if (retryPolicy)
470 {
471 if (std::find(supportedRetryPolicies.begin(),
472 supportedRetryPolicies.end(),
473 *retryPolicy) == supportedRetryPolicies.end())
Ed Tanousfffb8c12022-02-07 23:53:03 -0800474 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700475 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
476 "DeliveryRetryPolicy");
Ed Tanousfffb8c12022-02-07 23:53:03 -0800477 return;
478 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700479 subValue->retryPolicy = *retryPolicy;
480 }
481 else
482 {
483 // Default "TerminateAfterRetries"
484 subValue->retryPolicy = "TerminateAfterRetries";
485 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800486
Ed Tanous002d39b2022-05-31 08:59:27 -0700487 if (mrdJsonArray)
488 {
489 for (nlohmann::json& mrdObj : *mrdJsonArray)
490 {
491 std::string mrdUri;
492
493 if (!json_util::readJson(mrdObj, asyncResp->res, "@odata.id",
494 mrdUri))
495
496 {
497 return;
498 }
499 subValue->metricReportDefinitions.emplace_back(mrdUri);
500 }
501 }
502
503 std::string id =
504 EventServiceManager::getInstance().addSubscription(subValue);
505 if (id.empty())
506 {
507 messages::internalError(asyncResp->res);
508 return;
509 }
510
511 messages::created(asyncResp->res);
512 asyncResp->res.addHeader(
513 "Location", "/redfish/v1/EventService/Subscriptions/" + id);
Ed Tanousfffb8c12022-02-07 23:53:03 -0800514 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700515}
516
517inline void requestRoutesEventDestination(App& app)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530518{
Ravi Teja9d41aec2021-07-23 01:57:01 -0500519 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700520 .privileges(redfish::privileges::getEventDestination)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700521 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700522 [&app](const crow::Request& req,
523 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
524 const std::string& param) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000525 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700526 {
527 return;
528 }
529 std::shared_ptr<Subscription> subValue =
530 EventServiceManager::getInstance().getSubscription(param);
531 if (subValue == nullptr)
532 {
533 asyncResp->res.result(boost::beast::http::status::not_found);
534 return;
535 }
536 const std::string& id = param;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530537
Ed Tanous002d39b2022-05-31 08:59:27 -0700538 asyncResp->res.jsonValue["@odata.type"] =
539 "#EventDestination.v1_7_0.EventDestination";
540 asyncResp->res.jsonValue["Protocol"] = "Redfish";
541 asyncResp->res.jsonValue["@odata.id"] =
542 "/redfish/v1/EventService/Subscriptions/" + id;
543 asyncResp->res.jsonValue["Id"] = id;
544 asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
545 asyncResp->res.jsonValue["Destination"] = subValue->destinationUrl;
546 asyncResp->res.jsonValue["Context"] = subValue->customText;
547 asyncResp->res.jsonValue["SubscriptionType"] =
548 subValue->subscriptionType;
549 asyncResp->res.jsonValue["HttpHeaders"] = nlohmann::json::array();
550 asyncResp->res.jsonValue["EventFormatType"] = subValue->eventFormatType;
551 asyncResp->res.jsonValue["RegistryPrefixes"] =
552 subValue->registryPrefixes;
553 asyncResp->res.jsonValue["ResourceTypes"] = subValue->resourceTypes;
zhanghch058d1b46d2021-04-01 11:18:24 +0800554
Ed Tanous002d39b2022-05-31 08:59:27 -0700555 asyncResp->res.jsonValue["MessageIds"] = subValue->registryMsgIds;
556 asyncResp->res.jsonValue["DeliveryRetryPolicy"] = subValue->retryPolicy;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530557
Ed Tanous002d39b2022-05-31 08:59:27 -0700558 nlohmann::json::array_t mrdJsonArray;
559 for (const auto& mdrUri : subValue->metricReportDefinitions)
560 {
561 nlohmann::json::object_t mdr;
562 mdr["@odata.id"] = mdrUri;
563 mrdJsonArray.emplace_back(std::move(mdr));
564 }
565 asyncResp->res.jsonValue["MetricReportDefinitions"] = mrdJsonArray;
566 });
Ravi Teja9d41aec2021-07-23 01:57:01 -0500567 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700568 // The below privilege is wrong, it should be ConfigureManager OR
569 // ConfigureSelf
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500570 // https://github.com/openbmc/bmcweb/issues/220
Ed Tanoused398212021-06-09 17:05:54 -0700571 //.privileges(redfish::privileges::patchEventDestination)
Ed Tanous432a8902021-06-14 15:28:56 -0700572 .privileges({{"ConfigureManager"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700573 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700574 [&app](const crow::Request& req,
575 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
576 const std::string& param) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000577 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700578 {
579 return;
580 }
581 std::shared_ptr<Subscription> subValue =
582 EventServiceManager::getInstance().getSubscription(param);
583 if (subValue == nullptr)
584 {
585 asyncResp->res.result(boost::beast::http::status::not_found);
586 return;
587 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530588
Ed Tanous002d39b2022-05-31 08:59:27 -0700589 std::optional<std::string> context;
590 std::optional<std::string> retryPolicy;
591 std::optional<std::vector<nlohmann::json>> headers;
Sunitha Harishe56f2542020-07-22 02:38:59 -0500592
Ed Tanous002d39b2022-05-31 08:59:27 -0700593 if (!json_util::readJsonPatch(req, asyncResp->res, "Context", context,
594 "DeliveryRetryPolicy", retryPolicy,
595 "HttpHeaders", headers))
596 {
597 return;
598 }
AppaRao Puli144b6312020-08-03 22:23:12 +0530599
Ed Tanous002d39b2022-05-31 08:59:27 -0700600 if (context)
601 {
602 subValue->customText = *context;
603 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530604
Ed Tanous002d39b2022-05-31 08:59:27 -0700605 if (headers)
606 {
607 boost::beast::http::fields fields;
608 for (const nlohmann::json& headerChunk : *headers)
609 {
Patrick Williams62bafc02022-09-08 17:35:35 -0500610 for (const auto& it : headerChunk.items())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700611 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700612 const std::string* value =
613 it.value().get_ptr<const std::string*>();
614 if (value == nullptr)
Ed Tanous601c71a2021-09-08 16:40:12 -0700615 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700616 messages::propertyValueFormatError(
617 asyncResp->res, it.value().dump(2, ' ', true),
618 "HttpHeaders/" + it.key());
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700619 return;
620 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700621 fields.set(it.key(), *value);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700622 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700623 }
624 subValue->httpHeaders = fields;
625 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530626
Ed Tanous002d39b2022-05-31 08:59:27 -0700627 if (retryPolicy)
628 {
629 if (std::find(supportedRetryPolicies.begin(),
630 supportedRetryPolicies.end(),
631 *retryPolicy) == supportedRetryPolicies.end())
632 {
633 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
634 "DeliveryRetryPolicy");
635 return;
636 }
637 subValue->retryPolicy = *retryPolicy;
Ed Tanous002d39b2022-05-31 08:59:27 -0700638 }
639
640 EventServiceManager::getInstance().updateSubscriptionData();
641 });
Ravi Teja9d41aec2021-07-23 01:57:01 -0500642 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700643 // The below privilege is wrong, it should be ConfigureManager OR
644 // ConfigureSelf
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500645 // https://github.com/openbmc/bmcweb/issues/220
Ed Tanoused398212021-06-09 17:05:54 -0700646 //.privileges(redfish::privileges::deleteEventDestination)
Ed Tanous432a8902021-06-14 15:28:56 -0700647 .privileges({{"ConfigureManager"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700648 .methods(boost::beast::http::verb::delete_)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700649 [&app](const crow::Request& req,
650 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
651 const std::string& param) {
Carson Labrado3ba00072022-06-06 19:40:56 +0000652 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous002d39b2022-05-31 08:59:27 -0700653 {
654 return;
655 }
656 if (!EventServiceManager::getInstance().isSubscriptionExist(param))
657 {
658 asyncResp->res.result(boost::beast::http::status::not_found);
659 return;
660 }
661 EventServiceManager::getInstance().deleteSubscription(param);
662 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700663}
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530664
665} // namespace redfish