blob: 04b46e0cddd62339ae616a4b76821da7abb01588 [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
AppaRao Pulib52664e2020-04-09 21:36:51 +053017#include "event_service_manager.hpp"
AppaRao Pulie5aaf042020-03-20 01:05:52 +053018
John Edward Broadbent7e860f12021-04-08 15:57:16 -070019#include <app.hpp>
Ed Tanous601c71a2021-09-08 16:40:12 -070020#include <boost/beast/http/fields.hpp>
Ed Tanous45ca1b82022-03-25 13:07:27 -070021#include <query.hpp>
Ed Tanoused398212021-06-09 17:05:54 -070022#include <registries/privilege_registry.hpp>
23
Patrick Williams1e270c52021-12-04 06:06:56 -060024#include <span>
25
AppaRao Pulie5aaf042020-03-20 01:05:52 +053026namespace redfish
27{
28
AppaRao Puli156d6b02020-04-25 06:04:05 +053029static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
30 eventFormatType, metricReportFormatType};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053031static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +053032 "Base", "OpenBMC", "TaskEvent"};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053033static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
34 "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
35
Sunitha Harishe56f2542020-07-22 02:38:59 -050036#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
37static constexpr const std::array<const char*, 2> supportedResourceTypes = {
38 "IBMConfigFile", "Task"};
39#else
40static constexpr const std::array<const char*, 1> supportedResourceTypes = {
41 "Task"};
42#endif
43
AppaRao Pulie5aaf042020-03-20 01:05:52 +053044static constexpr const uint8_t maxNoOfSubscriptions = 20;
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 Tanous45ca1b82022-03-25 13:07:27 -070050 .methods(boost::beast::http::verb::get)([&app](const crow::Request& req,
51 const std::shared_ptr<
52 bmcweb::AsyncResp>&
53 asyncResp) {
54 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
55 {
56 return;
57 }
George Liu0fda0f12021-11-16 10:06:17 +080058 asyncResp->res.jsonValue = {
59 {"@odata.type", "#EventService.v1_5_0.EventService"},
60 {"Id", "EventService"},
61 {"Name", "Event Service"},
62 {"Subscriptions",
63 {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}},
64 {"Actions",
65 {{"#EventService.SubmitTestEvent",
66 {{"target",
67 "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent"}}}}},
68 {"@odata.id", "/redfish/v1/EventService"}};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053069
George Liu0fda0f12021-11-16 10:06:17 +080070 const persistent_data::EventServiceConfig eventServiceConfig =
71 persistent_data::EventServiceStore::getInstance()
72 .getEventServiceConfig();
zhanghch058d1b46d2021-04-01 11:18:24 +080073
George Liu0fda0f12021-11-16 10:06:17 +080074 asyncResp->res.jsonValue["Status"]["State"] =
75 (eventServiceConfig.enabled ? "Enabled" : "Disabled");
76 asyncResp->res.jsonValue["ServiceEnabled"] =
77 eventServiceConfig.enabled;
78 asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
79 eventServiceConfig.retryAttempts;
80 asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
81 eventServiceConfig.retryTimeoutInterval;
82 asyncResp->res.jsonValue["EventFormatTypes"] =
83 supportedEvtFormatTypes;
84 asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
85 asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
AppaRao Pulie5aaf042020-03-20 01:05:52 +053086
George Liu0fda0f12021-11-16 10:06:17 +080087 nlohmann::json supportedSSEFilters = {
88 {"EventFormatType", true}, {"MessageId", true},
89 {"MetricReportDefinition", true}, {"RegistryPrefix", true},
90 {"OriginResource", false}, {"ResourceType", false}};
AppaRao Puli7d1cc382020-05-16 02:42:22 +053091
George Liu0fda0f12021-11-16 10:06:17 +080092 asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
93 supportedSSEFilters;
94 });
Ayushi Smriti07941a82020-05-21 15:55:34 +053095
John Edward Broadbent7e860f12021-04-08 15:57:16 -070096 BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
Ed Tanoused398212021-06-09 17:05:54 -070097 .privileges(redfish::privileges::patchEventService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -070098 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -070099 [&app](const crow::Request& req,
100 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
101 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
102 {
103 return;
104 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700105 std::optional<bool> serviceEnabled;
106 std::optional<uint32_t> retryAttemps;
107 std::optional<uint32_t> retryInterval;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530108
Willy Tu15ed6782021-12-14 11:03:16 -0800109 if (!json_util::readJsonPatch(
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700110 req, asyncResp->res, "ServiceEnabled", serviceEnabled,
111 "DeliveryRetryAttempts", retryAttemps,
112 "DeliveryRetryIntervalSeconds", retryInterval))
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530113 {
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530114 return;
115 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530116
JunLin Chen28afb492021-02-24 17:13:29 +0800117 persistent_data::EventServiceConfig eventServiceConfig =
118 persistent_data::EventServiceStore::getInstance()
119 .getEventServiceConfig();
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700120
121 if (serviceEnabled)
Sunitha Harishe56f2542020-07-22 02:38:59 -0500122 {
JunLin Chen28afb492021-02-24 17:13:29 +0800123 eventServiceConfig.enabled = *serviceEnabled;
Sunitha Harishe56f2542020-07-22 02:38:59 -0500124 }
Sunitha Harishe56f2542020-07-22 02:38:59 -0500125
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700126 if (retryAttemps)
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530127 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700128 // Supported range [1-3]
129 if ((*retryAttemps < 1) || (*retryAttemps > 3))
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530130 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700131 messages::queryParameterOutOfRange(
132 asyncResp->res, std::to_string(*retryAttemps),
133 "DeliveryRetryAttempts", "[1-3]");
134 }
135 else
136 {
JunLin Chen28afb492021-02-24 17:13:29 +0800137 eventServiceConfig.retryAttempts = *retryAttemps;
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530138 }
139 }
140
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700141 if (retryInterval)
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530142 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700143 // Supported range [30 - 180]
144 if ((*retryInterval < 30) || (*retryInterval > 180))
145 {
146 messages::queryParameterOutOfRange(
147 asyncResp->res, std::to_string(*retryInterval),
148 "DeliveryRetryIntervalSeconds", "[30-180]");
149 }
150 else
151 {
JunLin Chen28afb492021-02-24 17:13:29 +0800152 eventServiceConfig.retryTimeoutInterval =
153 *retryInterval;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700154 }
155 }
156
157 EventServiceManager::getInstance().setEventServiceConfig(
JunLin Chen28afb492021-02-24 17:13:29 +0800158 eventServiceConfig);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700159 });
160}
161
162inline void requestRoutesSubmitTestEvent(App& app)
163{
164
165 BMCWEB_ROUTE(
166 app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
Ed Tanoused398212021-06-09 17:05:54 -0700167 .privileges(redfish::privileges::postEventService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700168 .methods(boost::beast::http::verb::post)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700169 [&app](const crow::Request& req,
170 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
171 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
172 {
173 return;
174 }
sunharis_in6ba8c822021-07-06 06:06:58 -0500175 if (!EventServiceManager::getInstance().sendTestEventLog())
176 {
177 messages::serviceDisabled(asyncResp->res,
178 "/redfish/v1/EventService/");
179 return;
180 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700181 asyncResp->res.result(boost::beast::http::status::no_content);
182 });
183}
184
185inline void requestRoutesEventDestinationCollection(App& app)
186{
Gayathri Leburu1ebe3e42022-02-09 10:45:19 +0000187 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
Ed Tanoused398212021-06-09 17:05:54 -0700188 .privileges(redfish::privileges::getEventDestinationCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700189 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700190 [&app](const crow::Request& req,
191 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
192 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
193 {
194 return;
195 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700196 asyncResp->res.jsonValue = {
197 {"@odata.type",
198 "#EventDestinationCollection.EventDestinationCollection"},
199 {"@odata.id", "/redfish/v1/EventService/Subscriptions"},
200 {"Name", "Event Destination Collections"}};
201
202 nlohmann::json& memberArray =
203 asyncResp->res.jsonValue["Members"];
204
205 std::vector<std::string> subscripIds =
206 EventServiceManager::getInstance().getAllIDs();
207 memberArray = nlohmann::json::array();
208 asyncResp->res.jsonValue["Members@odata.count"] =
209 subscripIds.size();
210
211 for (const std::string& id : subscripIds)
212 {
213 memberArray.push_back(
214 {{"@odata.id",
215 "/redfish/v1/EventService/Subscriptions/" + id}});
216 }
217 });
218 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500219 .privileges(redfish::privileges::postEventDestinationCollection)
Ed Tanousfffb8c12022-02-07 23:53:03 -0800220 .methods(
221 boost::beast::http::verb::
Ed Tanous45ca1b82022-03-25 13:07:27 -0700222 post)([&app](
223 const crow::Request& req,
224 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
225 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
226 {
227 return;
228 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800229 if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
230 maxNoOfSubscriptions)
231 {
232 messages::eventSubscriptionLimitExceeded(asyncResp->res);
233 return;
234 }
235 std::string destUrl;
236 std::string protocol;
237 std::optional<std::string> context;
238 std::optional<std::string> subscriptionType;
239 std::optional<std::string> eventFormatType2;
240 std::optional<std::string> retryPolicy;
241 std::optional<std::vector<std::string>> msgIds;
242 std::optional<std::vector<std::string>> regPrefixes;
243 std::optional<std::vector<std::string>> resTypes;
244 std::optional<std::vector<nlohmann::json>> headers;
245 std::optional<std::vector<nlohmann::json>> mrdJsonArray;
246
247 if (!json_util::readJsonPatch(
248 req, asyncResp->res, "Destination", destUrl, "Context",
249 context, "Protocol", protocol, "SubscriptionType",
250 subscriptionType, "EventFormatType", eventFormatType2,
251 "HttpHeaders", headers, "RegistryPrefixes", regPrefixes,
252 "MessageIds", msgIds, "DeliveryRetryPolicy", retryPolicy,
253 "MetricReportDefinitions", mrdJsonArray, "ResourceTypes",
254 resTypes))
255 {
256 return;
257 }
258
259 if (regPrefixes && msgIds)
260 {
261 if (!regPrefixes->empty() && !msgIds->empty())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700262 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800263 messages::propertyValueConflict(
264 asyncResp->res, "MessageIds", "RegistryPrefixes");
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530265 return;
266 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800267 }
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530268
Ed Tanousfffb8c12022-02-07 23:53:03 -0800269 // Validate the URL using regex expression
270 // Format: <protocol>://<host>:<port>/<uri>
271 // protocol: http/https
272 // host: Exclude ' ', ':', '#', '?'
273 // port: Empty or numeric value with ':' separator.
274 // uri: Start with '/' and Exclude '#', ' '
275 // Can include query params(ex: '/event?test=1')
276 // TODO: Need to validate hostname extensively(as per rfc)
277 const std::regex urlRegex(
278 "(http|https)://([^/\\x20\\x3f\\x23\\x3a]+):?([0-9]*)(/"
279 "([^\\x20\\x23\\x3f]*\\x3f?([^\\x20\\x23\\x3f])*)?)");
280 std::cmatch match;
281 if (!std::regex_match(destUrl.c_str(), match, urlRegex))
282 {
283 messages::propertyValueFormatError(asyncResp->res, destUrl,
284 "Destination");
285 return;
286 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700287
Ed Tanousfffb8c12022-02-07 23:53:03 -0800288 std::string uriProto = std::string(match[1].first, match[1].second);
289 if (uriProto == "http")
290 {
291#ifndef BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING
292 messages::propertyValueFormatError(asyncResp->res, destUrl,
293 "Destination");
294 return;
295#endif
296 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700297
Ed Tanousfffb8c12022-02-07 23:53:03 -0800298 std::string host = std::string(match[2].first, match[2].second);
299 std::string port = std::string(match[3].first, match[3].second);
300 std::string path = std::string(match[4].first, match[4].second);
301 if (port.empty())
302 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700303 if (uriProto == "http")
304 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800305 port = "80";
AppaRao Puli144b6312020-08-03 22:23:12 +0530306 }
307 else
308 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800309 port = "443";
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700310 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800311 }
312 if (path.empty())
313 {
314 path = "/";
315 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700316
Ed Tanousfffb8c12022-02-07 23:53:03 -0800317 std::shared_ptr<Subscription> subValue =
318 std::make_shared<Subscription>(host, port, path, uriProto);
319
320 subValue->destinationUrl = destUrl;
321
322 if (subscriptionType)
323 {
324 if (*subscriptionType != "RedfishEvent")
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700325 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800326 messages::propertyValueNotInList(
327 asyncResp->res, *subscriptionType, "SubscriptionType");
AppaRao Puli144b6312020-08-03 22:23:12 +0530328 return;
329 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800330 subValue->subscriptionType = *subscriptionType;
331 }
332 else
333 {
334 subValue->subscriptionType = "RedfishEvent"; // Default
335 }
AppaRao Puli156d6b02020-04-25 06:04:05 +0530336
Ed Tanousfffb8c12022-02-07 23:53:03 -0800337 if (protocol != "Redfish")
338 {
339 messages::propertyValueNotInList(asyncResp->res, protocol,
340 "Protocol");
341 return;
342 }
343 subValue->protocol = protocol;
344
345 if (eventFormatType2)
346 {
347 if (std::find(supportedEvtFormatTypes.begin(),
348 supportedEvtFormatTypes.end(),
349 *eventFormatType2) ==
350 supportedEvtFormatTypes.end())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700351 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800352 messages::propertyValueNotInList(
353 asyncResp->res, *eventFormatType2, "EventFormatType");
354 return;
355 }
356 subValue->eventFormatType = *eventFormatType2;
357 }
358 else
359 {
360 // If not specified, use default "Event"
361 subValue->eventFormatType = "Event";
362 }
363
364 if (context)
365 {
366 subValue->customText = *context;
367 }
368
369 if (headers)
370 {
371 for (const nlohmann::json& headerChunk : *headers)
372 {
373 for (const auto& item : headerChunk.items())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700374 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800375 const std::string* value =
376 item.value().get_ptr<const std::string*>();
377 if (value == nullptr)
378 {
379 messages::propertyValueFormatError(
380 asyncResp->res, item.value().dump(2, 1),
381 "HttpHeaders/" + item.key());
382 return;
383 }
384 subValue->httpHeaders.set(item.key(), *value);
385 }
386 }
387 }
388
389 if (regPrefixes)
390 {
391 for (const std::string& it : *regPrefixes)
392 {
393 if (std::find(supportedRegPrefixes.begin(),
394 supportedRegPrefixes.end(),
395 it) == supportedRegPrefixes.end())
396 {
397 messages::propertyValueNotInList(asyncResp->res, it,
398 "RegistryPrefixes");
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700399 return;
400 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800401 }
402 subValue->registryPrefixes = *regPrefixes;
403 }
404
405 if (resTypes)
406 {
407 for (const std::string& it : *resTypes)
408 {
409 if (std::find(supportedResourceTypes.begin(),
410 supportedResourceTypes.end(),
411 it) == supportedResourceTypes.end())
412 {
413 messages::propertyValueNotInList(asyncResp->res, it,
414 "ResourceTypes");
415 return;
416 }
417 }
418 subValue->resourceTypes = *resTypes;
419 }
420
421 if (msgIds)
422 {
423 std::vector<std::string> registryPrefix;
424
425 // If no registry prefixes are mentioned, consider all
426 // supported prefixes
427 if (subValue->registryPrefixes.empty())
428 {
429 registryPrefix.assign(supportedRegPrefixes.begin(),
430 supportedRegPrefixes.end());
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700431 }
432 else
433 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800434 registryPrefix = subValue->registryPrefixes;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700435 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530436
Ed Tanousfffb8c12022-02-07 23:53:03 -0800437 for (const std::string& id : *msgIds)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700438 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800439 bool validId = false;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530440
Ed Tanousfffb8c12022-02-07 23:53:03 -0800441 // Check for Message ID in each of the selected Registry
442 for (const std::string& it : registryPrefix)
Ed Tanous601c71a2021-09-08 16:40:12 -0700443 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800444 const std::span<const redfish::registries::MessageEntry>
445 registry =
446 redfish::registries::getRegistryFromPrefix(it);
447
448 if (std::any_of(
449 registry.begin(), registry.end(),
450 [&id](const redfish::registries::MessageEntry&
451 messageEntry) {
Ed Tanous55f79e62022-01-25 11:26:16 -0800452 return id == messageEntry.first;
Ed Tanousfffb8c12022-02-07 23:53:03 -0800453 }))
Ed Tanous601c71a2021-09-08 16:40:12 -0700454 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800455 validId = true;
456 break;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700457 }
458 }
459
Ed Tanousfffb8c12022-02-07 23:53:03 -0800460 if (!validId)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700461 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800462 messages::propertyValueNotInList(asyncResp->res, id,
463 "MessageIds");
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700464 return;
465 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700466 }
467
Ed Tanousfffb8c12022-02-07 23:53:03 -0800468 subValue->registryMsgIds = *msgIds;
469 }
470
471 if (retryPolicy)
472 {
473 if (std::find(supportedRetryPolicies.begin(),
474 supportedRetryPolicies.end(),
475 *retryPolicy) == supportedRetryPolicies.end())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700476 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800477 messages::propertyValueNotInList(
478 asyncResp->res, *retryPolicy, "DeliveryRetryPolicy");
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700479 return;
480 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800481 subValue->retryPolicy = *retryPolicy;
482 }
483 else
484 {
485 // Default "TerminateAfterRetries"
486 subValue->retryPolicy = "TerminateAfterRetries";
487 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700488
Ed Tanousfffb8c12022-02-07 23:53:03 -0800489 if (mrdJsonArray)
490 {
491 for (nlohmann::json& mrdObj : *mrdJsonArray)
492 {
493 std::string mrdUri;
494
495 if (!json_util::readJson(mrdObj, asyncResp->res,
496 "@odata.id", mrdUri))
497
498 {
499 return;
500 }
501 subValue->metricReportDefinitions.emplace_back(mrdUri);
502 }
503 }
504
505 std::string id =
506 EventServiceManager::getInstance().addSubscription(subValue);
507 if (id.empty())
508 {
509 messages::internalError(asyncResp->res);
510 return;
511 }
512
513 messages::created(asyncResp->res);
514 asyncResp->res.addHeader(
515 "Location", "/redfish/v1/EventService/Subscriptions/" + id);
516 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700517}
518
519inline void requestRoutesEventDestination(App& app)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530520{
Ravi Teja9d41aec2021-07-23 01:57:01 -0500521 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700522 .privileges(redfish::privileges::getEventDestination)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700523 .methods(boost::beast::http::verb::get)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700524 [&app](const crow::Request& req,
525 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
526 const std::string& param) {
527 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
528 {
529 return;
530 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700531 std::shared_ptr<Subscription> subValue =
532 EventServiceManager::getInstance().getSubscription(param);
533 if (subValue == nullptr)
534 {
535 asyncResp->res.result(
536 boost::beast::http::status::not_found);
537 return;
538 }
539 const std::string& id = param;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530540
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700541 asyncResp->res.jsonValue = {
542 {"@odata.type",
543 "#EventDestination.v1_7_0.EventDestination"},
544 {"Protocol", "Redfish"}};
545 asyncResp->res.jsonValue["@odata.id"] =
546 "/redfish/v1/EventService/Subscriptions/" + id;
547 asyncResp->res.jsonValue["Id"] = id;
548 asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
549 asyncResp->res.jsonValue["Destination"] =
550 subValue->destinationUrl;
551 asyncResp->res.jsonValue["Context"] = subValue->customText;
552 asyncResp->res.jsonValue["SubscriptionType"] =
553 subValue->subscriptionType;
Ed Tanousad22fef2021-09-13 13:07:32 -0700554 asyncResp->res.jsonValue["HttpHeaders"] =
555 nlohmann::json::array();
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700556 asyncResp->res.jsonValue["EventFormatType"] =
557 subValue->eventFormatType;
558 asyncResp->res.jsonValue["RegistryPrefixes"] =
559 subValue->registryPrefixes;
560 asyncResp->res.jsonValue["ResourceTypes"] =
561 subValue->resourceTypes;
zhanghch058d1b46d2021-04-01 11:18:24 +0800562
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700563 asyncResp->res.jsonValue["MessageIds"] =
564 subValue->registryMsgIds;
565 asyncResp->res.jsonValue["DeliveryRetryPolicy"] =
566 subValue->retryPolicy;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530567
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700568 std::vector<nlohmann::json> mrdJsonArray;
569 for (const auto& mdrUri : subValue->metricReportDefinitions)
570 {
571 mrdJsonArray.push_back({{"@odata.id", mdrUri}});
572 }
573 asyncResp->res.jsonValue["MetricReportDefinitions"] =
574 mrdJsonArray;
575 });
Ravi Teja9d41aec2021-07-23 01:57:01 -0500576 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700577 // The below privilege is wrong, it should be ConfigureManager OR
578 // ConfigureSelf
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500579 // https://github.com/openbmc/bmcweb/issues/220
Ed Tanoused398212021-06-09 17:05:54 -0700580 //.privileges(redfish::privileges::patchEventDestination)
Ed Tanous432a8902021-06-14 15:28:56 -0700581 .privileges({{"ConfigureManager"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700582 .methods(boost::beast::http::verb::patch)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700583 [&app](const crow::Request& req,
584 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
585 const std::string& param) {
586 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
587 {
588 return;
589 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700590 std::shared_ptr<Subscription> subValue =
591 EventServiceManager::getInstance().getSubscription(param);
592 if (subValue == nullptr)
593 {
594 asyncResp->res.result(
595 boost::beast::http::status::not_found);
596 return;
597 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530598
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700599 std::optional<std::string> context;
600 std::optional<std::string> retryPolicy;
601 std::optional<std::vector<nlohmann::json>> headers;
Sunitha Harishe56f2542020-07-22 02:38:59 -0500602
Willy Tu15ed6782021-12-14 11:03:16 -0800603 if (!json_util::readJsonPatch(req, asyncResp->res, "Context",
604 context, "DeliveryRetryPolicy",
605 retryPolicy, "HttpHeaders",
606 headers))
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700607 {
608 return;
609 }
AppaRao Puli144b6312020-08-03 22:23:12 +0530610
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700611 if (context)
612 {
613 subValue->customText = *context;
614 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530615
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700616 if (headers)
617 {
Ed Tanous601c71a2021-09-08 16:40:12 -0700618 boost::beast::http::fields fields;
619 for (const nlohmann::json& headerChunk : *headers)
620 {
621 for (auto& it : headerChunk.items())
622 {
623 const std::string* value =
624 it.value().get_ptr<const std::string*>();
625 if (value == nullptr)
626 {
627 messages::propertyValueFormatError(
628 asyncResp->res,
629 it.value().dump(2, ' ', true),
630 "HttpHeaders/" + it.key());
631 return;
632 }
633 fields.set(it.key(), *value);
634 }
635 }
636 subValue->httpHeaders = fields;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700637 }
zhanghch058d1b46d2021-04-01 11:18:24 +0800638
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700639 if (retryPolicy)
640 {
641 if (std::find(supportedRetryPolicies.begin(),
642 supportedRetryPolicies.end(),
643 *retryPolicy) == supportedRetryPolicies.end())
644 {
645 messages::propertyValueNotInList(asyncResp->res,
646 *retryPolicy,
647 "DeliveryRetryPolicy");
648 return;
649 }
650 subValue->retryPolicy = *retryPolicy;
651 subValue->updateRetryPolicy();
652 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530653
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700654 EventServiceManager::getInstance().updateSubscriptionData();
655 });
Ravi Teja9d41aec2021-07-23 01:57:01 -0500656 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700657 // The below privilege is wrong, it should be ConfigureManager OR
658 // ConfigureSelf
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500659 // https://github.com/openbmc/bmcweb/issues/220
Ed Tanoused398212021-06-09 17:05:54 -0700660 //.privileges(redfish::privileges::deleteEventDestination)
Ed Tanous432a8902021-06-14 15:28:56 -0700661 .privileges({{"ConfigureManager"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700662 .methods(boost::beast::http::verb::delete_)(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700663 [&app](const crow::Request& req,
664 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
665 const std::string& param) {
666 if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
667 {
668 return;
669 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700670 if (!EventServiceManager::getInstance().isSubscriptionExist(
671 param))
672 {
673 asyncResp->res.result(
674 boost::beast::http::status::not_found);
675 return;
676 }
677 EventServiceManager::getInstance().deleteSubscription(param);
678 });
679}
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530680
681} // namespace redfish