blob: ba391407a0c1401b93584ff0bccd05529225e45b [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 Tanoused398212021-06-09 17:05:54 -070021#include <registries/privilege_registry.hpp>
22
Patrick Williams1e270c52021-12-04 06:06:56 -060023#include <span>
24
AppaRao Pulie5aaf042020-03-20 01:05:52 +053025namespace redfish
26{
27
AppaRao Puli156d6b02020-04-25 06:04:05 +053028static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
29 eventFormatType, metricReportFormatType};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053030static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +053031 "Base", "OpenBMC", "TaskEvent"};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053032static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
33 "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
34
Sunitha Harishe56f2542020-07-22 02:38:59 -050035#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
36static constexpr const std::array<const char*, 2> supportedResourceTypes = {
37 "IBMConfigFile", "Task"};
38#else
39static constexpr const std::array<const char*, 1> supportedResourceTypes = {
40 "Task"};
41#endif
42
AppaRao Pulie5aaf042020-03-20 01:05:52 +053043static constexpr const uint8_t maxNoOfSubscriptions = 20;
44
John Edward Broadbent7e860f12021-04-08 15:57:16 -070045inline void requestRoutesEventService(App& app)
AppaRao Pulie5aaf042020-03-20 01:05:52 +053046{
John Edward Broadbent7e860f12021-04-08 15:57:16 -070047 BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
Ed Tanoused398212021-06-09 17:05:54 -070048 .privileges(redfish::privileges::getEventService)
George Liu0fda0f12021-11-16 10:06:17 +080049 .methods(
50 boost::beast::http::verb::
51 get)([](const crow::Request&,
52 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
53 asyncResp->res.jsonValue = {
54 {"@odata.type", "#EventService.v1_5_0.EventService"},
55 {"Id", "EventService"},
56 {"Name", "Event Service"},
57 {"Subscriptions",
58 {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}},
59 {"Actions",
60 {{"#EventService.SubmitTestEvent",
61 {{"target",
62 "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent"}}}}},
63 {"@odata.id", "/redfish/v1/EventService"}};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053064
George Liu0fda0f12021-11-16 10:06:17 +080065 const persistent_data::EventServiceConfig eventServiceConfig =
66 persistent_data::EventServiceStore::getInstance()
67 .getEventServiceConfig();
zhanghch058d1b46d2021-04-01 11:18:24 +080068
George Liu0fda0f12021-11-16 10:06:17 +080069 asyncResp->res.jsonValue["Status"]["State"] =
70 (eventServiceConfig.enabled ? "Enabled" : "Disabled");
71 asyncResp->res.jsonValue["ServiceEnabled"] =
72 eventServiceConfig.enabled;
73 asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
74 eventServiceConfig.retryAttempts;
75 asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
76 eventServiceConfig.retryTimeoutInterval;
77 asyncResp->res.jsonValue["EventFormatTypes"] =
78 supportedEvtFormatTypes;
79 asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
80 asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
AppaRao Pulie5aaf042020-03-20 01:05:52 +053081
George Liu0fda0f12021-11-16 10:06:17 +080082 nlohmann::json supportedSSEFilters = {
83 {"EventFormatType", true}, {"MessageId", true},
84 {"MetricReportDefinition", true}, {"RegistryPrefix", true},
85 {"OriginResource", false}, {"ResourceType", false}};
AppaRao Puli7d1cc382020-05-16 02:42:22 +053086
George Liu0fda0f12021-11-16 10:06:17 +080087 asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
88 supportedSSEFilters;
89 });
Ayushi Smriti07941a82020-05-21 15:55:34 +053090
John Edward Broadbent7e860f12021-04-08 15:57:16 -070091 BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
Ed Tanoused398212021-06-09 17:05:54 -070092 .privileges(redfish::privileges::patchEventService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -070093 .methods(boost::beast::http::verb::patch)(
94 [](const crow::Request& req,
95 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ayushi Smriti07941a82020-05-21 15:55:34 +053096
AppaRao Pulie5aaf042020-03-20 01:05:52 +053097 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -070098 std::optional<bool> serviceEnabled;
99 std::optional<uint32_t> retryAttemps;
100 std::optional<uint32_t> retryInterval;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530101
Willy Tu15ed6782021-12-14 11:03:16 -0800102 if (!json_util::readJsonPatch(
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700103 req, asyncResp->res, "ServiceEnabled", serviceEnabled,
104 "DeliveryRetryAttempts", retryAttemps,
105 "DeliveryRetryIntervalSeconds", retryInterval))
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530106 {
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530107 return;
108 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530109
JunLin Chen28afb492021-02-24 17:13:29 +0800110 persistent_data::EventServiceConfig eventServiceConfig =
111 persistent_data::EventServiceStore::getInstance()
112 .getEventServiceConfig();
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700113
114 if (serviceEnabled)
Sunitha Harishe56f2542020-07-22 02:38:59 -0500115 {
JunLin Chen28afb492021-02-24 17:13:29 +0800116 eventServiceConfig.enabled = *serviceEnabled;
Sunitha Harishe56f2542020-07-22 02:38:59 -0500117 }
Sunitha Harishe56f2542020-07-22 02:38:59 -0500118
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700119 if (retryAttemps)
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530120 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700121 // Supported range [1-3]
122 if ((*retryAttemps < 1) || (*retryAttemps > 3))
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530123 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700124 messages::queryParameterOutOfRange(
125 asyncResp->res, std::to_string(*retryAttemps),
126 "DeliveryRetryAttempts", "[1-3]");
127 }
128 else
129 {
JunLin Chen28afb492021-02-24 17:13:29 +0800130 eventServiceConfig.retryAttempts = *retryAttemps;
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530131 }
132 }
133
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700134 if (retryInterval)
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530135 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700136 // Supported range [30 - 180]
137 if ((*retryInterval < 30) || (*retryInterval > 180))
138 {
139 messages::queryParameterOutOfRange(
140 asyncResp->res, std::to_string(*retryInterval),
141 "DeliveryRetryIntervalSeconds", "[30-180]");
142 }
143 else
144 {
JunLin Chen28afb492021-02-24 17:13:29 +0800145 eventServiceConfig.retryTimeoutInterval =
146 *retryInterval;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700147 }
148 }
149
150 EventServiceManager::getInstance().setEventServiceConfig(
JunLin Chen28afb492021-02-24 17:13:29 +0800151 eventServiceConfig);
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700152 });
153}
154
155inline void requestRoutesSubmitTestEvent(App& app)
156{
157
158 BMCWEB_ROUTE(
159 app, "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
Ed Tanoused398212021-06-09 17:05:54 -0700160 .privileges(redfish::privileges::postEventService)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700161 .methods(boost::beast::http::verb::post)(
162 [](const crow::Request&,
163 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
sunharis_in6ba8c822021-07-06 06:06:58 -0500164 if (!EventServiceManager::getInstance().sendTestEventLog())
165 {
166 messages::serviceDisabled(asyncResp->res,
167 "/redfish/v1/EventService/");
168 return;
169 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700170 asyncResp->res.result(boost::beast::http::status::no_content);
171 });
172}
173
174inline void requestRoutesEventDestinationCollection(App& app)
175{
Gayathri Leburu1ebe3e42022-02-09 10:45:19 +0000176 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
Ed Tanoused398212021-06-09 17:05:54 -0700177 .privileges(redfish::privileges::getEventDestinationCollection)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700178 .methods(boost::beast::http::verb::get)(
179 [](const crow::Request&,
180 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
181 asyncResp->res.jsonValue = {
182 {"@odata.type",
183 "#EventDestinationCollection.EventDestinationCollection"},
184 {"@odata.id", "/redfish/v1/EventService/Subscriptions"},
185 {"Name", "Event Destination Collections"}};
186
187 nlohmann::json& memberArray =
188 asyncResp->res.jsonValue["Members"];
189
190 std::vector<std::string> subscripIds =
191 EventServiceManager::getInstance().getAllIDs();
192 memberArray = nlohmann::json::array();
193 asyncResp->res.jsonValue["Members@odata.count"] =
194 subscripIds.size();
195
196 for (const std::string& id : subscripIds)
197 {
198 memberArray.push_back(
199 {{"@odata.id",
200 "/redfish/v1/EventService/Subscriptions/" + id}});
201 }
202 });
203 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500204 .privileges(redfish::privileges::postEventDestinationCollection)
Ed Tanousfffb8c12022-02-07 23:53:03 -0800205 .methods(
206 boost::beast::http::verb::
207 post)([](const crow::Request& req,
208 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
209 if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
210 maxNoOfSubscriptions)
211 {
212 messages::eventSubscriptionLimitExceeded(asyncResp->res);
213 return;
214 }
215 std::string destUrl;
216 std::string protocol;
217 std::optional<std::string> context;
218 std::optional<std::string> subscriptionType;
219 std::optional<std::string> eventFormatType2;
220 std::optional<std::string> retryPolicy;
221 std::optional<std::vector<std::string>> msgIds;
222 std::optional<std::vector<std::string>> regPrefixes;
223 std::optional<std::vector<std::string>> resTypes;
224 std::optional<std::vector<nlohmann::json>> headers;
225 std::optional<std::vector<nlohmann::json>> mrdJsonArray;
226
227 if (!json_util::readJsonPatch(
228 req, asyncResp->res, "Destination", destUrl, "Context",
229 context, "Protocol", protocol, "SubscriptionType",
230 subscriptionType, "EventFormatType", eventFormatType2,
231 "HttpHeaders", headers, "RegistryPrefixes", regPrefixes,
232 "MessageIds", msgIds, "DeliveryRetryPolicy", retryPolicy,
233 "MetricReportDefinitions", mrdJsonArray, "ResourceTypes",
234 resTypes))
235 {
236 return;
237 }
238
239 if (regPrefixes && msgIds)
240 {
241 if (!regPrefixes->empty() && !msgIds->empty())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700242 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800243 messages::propertyValueConflict(
244 asyncResp->res, "MessageIds", "RegistryPrefixes");
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530245 return;
246 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800247 }
P Dheeraj Srujan Kumarb304bd72021-01-29 17:46:35 +0530248
Ed Tanousfffb8c12022-02-07 23:53:03 -0800249 // Validate the URL using regex expression
250 // Format: <protocol>://<host>:<port>/<uri>
251 // protocol: http/https
252 // host: Exclude ' ', ':', '#', '?'
253 // port: Empty or numeric value with ':' separator.
254 // uri: Start with '/' and Exclude '#', ' '
255 // Can include query params(ex: '/event?test=1')
256 // TODO: Need to validate hostname extensively(as per rfc)
257 const std::regex urlRegex(
258 "(http|https)://([^/\\x20\\x3f\\x23\\x3a]+):?([0-9]*)(/"
259 "([^\\x20\\x23\\x3f]*\\x3f?([^\\x20\\x23\\x3f])*)?)");
260 std::cmatch match;
261 if (!std::regex_match(destUrl.c_str(), match, urlRegex))
262 {
263 messages::propertyValueFormatError(asyncResp->res, destUrl,
264 "Destination");
265 return;
266 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700267
Ed Tanousfffb8c12022-02-07 23:53:03 -0800268 std::string uriProto = std::string(match[1].first, match[1].second);
269 if (uriProto == "http")
270 {
271#ifndef BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING
272 messages::propertyValueFormatError(asyncResp->res, destUrl,
273 "Destination");
274 return;
275#endif
276 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700277
Ed Tanousfffb8c12022-02-07 23:53:03 -0800278 std::string host = std::string(match[2].first, match[2].second);
279 std::string port = std::string(match[3].first, match[3].second);
280 std::string path = std::string(match[4].first, match[4].second);
281 if (port.empty())
282 {
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700283 if (uriProto == "http")
284 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800285 port = "80";
AppaRao Puli144b6312020-08-03 22:23:12 +0530286 }
287 else
288 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800289 port = "443";
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700290 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800291 }
292 if (path.empty())
293 {
294 path = "/";
295 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700296
Ed Tanousfffb8c12022-02-07 23:53:03 -0800297 std::shared_ptr<Subscription> subValue =
298 std::make_shared<Subscription>(host, port, path, uriProto);
299
300 subValue->destinationUrl = destUrl;
301
302 if (subscriptionType)
303 {
304 if (*subscriptionType != "RedfishEvent")
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700305 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800306 messages::propertyValueNotInList(
307 asyncResp->res, *subscriptionType, "SubscriptionType");
AppaRao Puli144b6312020-08-03 22:23:12 +0530308 return;
309 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800310 subValue->subscriptionType = *subscriptionType;
311 }
312 else
313 {
314 subValue->subscriptionType = "RedfishEvent"; // Default
315 }
AppaRao Puli156d6b02020-04-25 06:04:05 +0530316
Ed Tanousfffb8c12022-02-07 23:53:03 -0800317 if (protocol != "Redfish")
318 {
319 messages::propertyValueNotInList(asyncResp->res, protocol,
320 "Protocol");
321 return;
322 }
323 subValue->protocol = protocol;
324
325 if (eventFormatType2)
326 {
327 if (std::find(supportedEvtFormatTypes.begin(),
328 supportedEvtFormatTypes.end(),
329 *eventFormatType2) ==
330 supportedEvtFormatTypes.end())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700331 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800332 messages::propertyValueNotInList(
333 asyncResp->res, *eventFormatType2, "EventFormatType");
334 return;
335 }
336 subValue->eventFormatType = *eventFormatType2;
337 }
338 else
339 {
340 // If not specified, use default "Event"
341 subValue->eventFormatType = "Event";
342 }
343
344 if (context)
345 {
346 subValue->customText = *context;
347 }
348
349 if (headers)
350 {
351 for (const nlohmann::json& headerChunk : *headers)
352 {
353 for (const auto& item : headerChunk.items())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700354 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800355 const std::string* value =
356 item.value().get_ptr<const std::string*>();
357 if (value == nullptr)
358 {
359 messages::propertyValueFormatError(
360 asyncResp->res, item.value().dump(2, 1),
361 "HttpHeaders/" + item.key());
362 return;
363 }
364 subValue->httpHeaders.set(item.key(), *value);
365 }
366 }
367 }
368
369 if (regPrefixes)
370 {
371 for (const std::string& it : *regPrefixes)
372 {
373 if (std::find(supportedRegPrefixes.begin(),
374 supportedRegPrefixes.end(),
375 it) == supportedRegPrefixes.end())
376 {
377 messages::propertyValueNotInList(asyncResp->res, it,
378 "RegistryPrefixes");
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700379 return;
380 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800381 }
382 subValue->registryPrefixes = *regPrefixes;
383 }
384
385 if (resTypes)
386 {
387 for (const std::string& it : *resTypes)
388 {
389 if (std::find(supportedResourceTypes.begin(),
390 supportedResourceTypes.end(),
391 it) == supportedResourceTypes.end())
392 {
393 messages::propertyValueNotInList(asyncResp->res, it,
394 "ResourceTypes");
395 return;
396 }
397 }
398 subValue->resourceTypes = *resTypes;
399 }
400
401 if (msgIds)
402 {
403 std::vector<std::string> registryPrefix;
404
405 // If no registry prefixes are mentioned, consider all
406 // supported prefixes
407 if (subValue->registryPrefixes.empty())
408 {
409 registryPrefix.assign(supportedRegPrefixes.begin(),
410 supportedRegPrefixes.end());
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700411 }
412 else
413 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800414 registryPrefix = subValue->registryPrefixes;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700415 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530416
Ed Tanousfffb8c12022-02-07 23:53:03 -0800417 for (const std::string& id : *msgIds)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700418 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800419 bool validId = false;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530420
Ed Tanousfffb8c12022-02-07 23:53:03 -0800421 // Check for Message ID in each of the selected Registry
422 for (const std::string& it : registryPrefix)
Ed Tanous601c71a2021-09-08 16:40:12 -0700423 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800424 const std::span<const redfish::registries::MessageEntry>
425 registry =
426 redfish::registries::getRegistryFromPrefix(it);
427
428 if (std::any_of(
429 registry.begin(), registry.end(),
430 [&id](const redfish::registries::MessageEntry&
431 messageEntry) {
432 return id.compare(messageEntry.first) == 0;
433 }))
Ed Tanous601c71a2021-09-08 16:40:12 -0700434 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800435 validId = true;
436 break;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700437 }
438 }
439
Ed Tanousfffb8c12022-02-07 23:53:03 -0800440 if (!validId)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700441 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800442 messages::propertyValueNotInList(asyncResp->res, id,
443 "MessageIds");
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700444 return;
445 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700446 }
447
Ed Tanousfffb8c12022-02-07 23:53:03 -0800448 subValue->registryMsgIds = *msgIds;
449 }
450
451 if (retryPolicy)
452 {
453 if (std::find(supportedRetryPolicies.begin(),
454 supportedRetryPolicies.end(),
455 *retryPolicy) == supportedRetryPolicies.end())
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700456 {
Ed Tanousfffb8c12022-02-07 23:53:03 -0800457 messages::propertyValueNotInList(
458 asyncResp->res, *retryPolicy, "DeliveryRetryPolicy");
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700459 return;
460 }
Ed Tanousfffb8c12022-02-07 23:53:03 -0800461 subValue->retryPolicy = *retryPolicy;
462 }
463 else
464 {
465 // Default "TerminateAfterRetries"
466 subValue->retryPolicy = "TerminateAfterRetries";
467 }
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700468
Ed Tanousfffb8c12022-02-07 23:53:03 -0800469 if (mrdJsonArray)
470 {
471 for (nlohmann::json& mrdObj : *mrdJsonArray)
472 {
473 std::string mrdUri;
474
475 if (!json_util::readJson(mrdObj, asyncResp->res,
476 "@odata.id", mrdUri))
477
478 {
479 return;
480 }
481 subValue->metricReportDefinitions.emplace_back(mrdUri);
482 }
483 }
484
485 std::string id =
486 EventServiceManager::getInstance().addSubscription(subValue);
487 if (id.empty())
488 {
489 messages::internalError(asyncResp->res);
490 return;
491 }
492
493 messages::created(asyncResp->res);
494 asyncResp->res.addHeader(
495 "Location", "/redfish/v1/EventService/Subscriptions/" + id);
496 });
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700497}
498
499inline void requestRoutesEventDestination(App& app)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530500{
Ravi Teja9d41aec2021-07-23 01:57:01 -0500501 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700502 .privileges(redfish::privileges::getEventDestination)
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700503 .methods(boost::beast::http::verb::get)(
504 [](const crow::Request&,
505 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
506 const std::string& param) {
507 std::shared_ptr<Subscription> subValue =
508 EventServiceManager::getInstance().getSubscription(param);
509 if (subValue == nullptr)
510 {
511 asyncResp->res.result(
512 boost::beast::http::status::not_found);
513 return;
514 }
515 const std::string& id = param;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530516
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700517 asyncResp->res.jsonValue = {
518 {"@odata.type",
519 "#EventDestination.v1_7_0.EventDestination"},
520 {"Protocol", "Redfish"}};
521 asyncResp->res.jsonValue["@odata.id"] =
522 "/redfish/v1/EventService/Subscriptions/" + id;
523 asyncResp->res.jsonValue["Id"] = id;
524 asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
525 asyncResp->res.jsonValue["Destination"] =
526 subValue->destinationUrl;
527 asyncResp->res.jsonValue["Context"] = subValue->customText;
528 asyncResp->res.jsonValue["SubscriptionType"] =
529 subValue->subscriptionType;
Ed Tanousad22fef2021-09-13 13:07:32 -0700530 asyncResp->res.jsonValue["HttpHeaders"] =
531 nlohmann::json::array();
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700532 asyncResp->res.jsonValue["EventFormatType"] =
533 subValue->eventFormatType;
534 asyncResp->res.jsonValue["RegistryPrefixes"] =
535 subValue->registryPrefixes;
536 asyncResp->res.jsonValue["ResourceTypes"] =
537 subValue->resourceTypes;
zhanghch058d1b46d2021-04-01 11:18:24 +0800538
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700539 asyncResp->res.jsonValue["MessageIds"] =
540 subValue->registryMsgIds;
541 asyncResp->res.jsonValue["DeliveryRetryPolicy"] =
542 subValue->retryPolicy;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530543
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700544 std::vector<nlohmann::json> mrdJsonArray;
545 for (const auto& mdrUri : subValue->metricReportDefinitions)
546 {
547 mrdJsonArray.push_back({{"@odata.id", mdrUri}});
548 }
549 asyncResp->res.jsonValue["MetricReportDefinitions"] =
550 mrdJsonArray;
551 });
Ravi Teja9d41aec2021-07-23 01:57:01 -0500552 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700553 // The below privilege is wrong, it should be ConfigureManager OR
554 // ConfigureSelf
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500555 // https://github.com/openbmc/bmcweb/issues/220
Ed Tanoused398212021-06-09 17:05:54 -0700556 //.privileges(redfish::privileges::patchEventDestination)
Ed Tanous432a8902021-06-14 15:28:56 -0700557 .privileges({{"ConfigureManager"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700558 .methods(boost::beast::http::verb::patch)(
559 [](const crow::Request& req,
560 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
561 const std::string& param) {
562 std::shared_ptr<Subscription> subValue =
563 EventServiceManager::getInstance().getSubscription(param);
564 if (subValue == nullptr)
565 {
566 asyncResp->res.result(
567 boost::beast::http::status::not_found);
568 return;
569 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530570
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700571 std::optional<std::string> context;
572 std::optional<std::string> retryPolicy;
573 std::optional<std::vector<nlohmann::json>> headers;
Sunitha Harishe56f2542020-07-22 02:38:59 -0500574
Willy Tu15ed6782021-12-14 11:03:16 -0800575 if (!json_util::readJsonPatch(req, asyncResp->res, "Context",
576 context, "DeliveryRetryPolicy",
577 retryPolicy, "HttpHeaders",
578 headers))
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700579 {
580 return;
581 }
AppaRao Puli144b6312020-08-03 22:23:12 +0530582
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700583 if (context)
584 {
585 subValue->customText = *context;
586 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530587
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700588 if (headers)
589 {
Ed Tanous601c71a2021-09-08 16:40:12 -0700590 boost::beast::http::fields fields;
591 for (const nlohmann::json& headerChunk : *headers)
592 {
593 for (auto& it : headerChunk.items())
594 {
595 const std::string* value =
596 it.value().get_ptr<const std::string*>();
597 if (value == nullptr)
598 {
599 messages::propertyValueFormatError(
600 asyncResp->res,
601 it.value().dump(2, ' ', true),
602 "HttpHeaders/" + it.key());
603 return;
604 }
605 fields.set(it.key(), *value);
606 }
607 }
608 subValue->httpHeaders = fields;
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700609 }
zhanghch058d1b46d2021-04-01 11:18:24 +0800610
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700611 if (retryPolicy)
612 {
613 if (std::find(supportedRetryPolicies.begin(),
614 supportedRetryPolicies.end(),
615 *retryPolicy) == supportedRetryPolicies.end())
616 {
617 messages::propertyValueNotInList(asyncResp->res,
618 *retryPolicy,
619 "DeliveryRetryPolicy");
620 return;
621 }
622 subValue->retryPolicy = *retryPolicy;
623 subValue->updateRetryPolicy();
624 }
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530625
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700626 EventServiceManager::getInstance().updateSubscriptionData();
627 });
Ravi Teja9d41aec2021-07-23 01:57:01 -0500628 BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700629 // The below privilege is wrong, it should be ConfigureManager OR
630 // ConfigureSelf
Abhishek Patel7eeafa72021-07-28 10:59:16 -0500631 // https://github.com/openbmc/bmcweb/issues/220
Ed Tanoused398212021-06-09 17:05:54 -0700632 //.privileges(redfish::privileges::deleteEventDestination)
Ed Tanous432a8902021-06-14 15:28:56 -0700633 .privileges({{"ConfigureManager"}})
John Edward Broadbent7e860f12021-04-08 15:57:16 -0700634 .methods(boost::beast::http::verb::delete_)(
635 [](const crow::Request&,
636 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
637 const std::string& param) {
638 if (!EventServiceManager::getInstance().isSubscriptionExist(
639 param))
640 {
641 asyncResp->res.result(
642 boost::beast::http::status::not_found);
643 return;
644 }
645 EventServiceManager::getInstance().deleteSubscription(param);
646 });
647}
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530648
649} // namespace redfish