blob: d3ed416c6216489cabbf2a1ca382754bceb2d3cf [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
19namespace redfish
20{
21
AppaRao Puli156d6b02020-04-25 06:04:05 +053022static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
23 eventFormatType, metricReportFormatType};
AppaRao Pulie5aaf042020-03-20 01:05:52 +053024static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
25 "Base", "OpenBMC", "Task"};
26static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
27 "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
28
Sunitha Harishe56f2542020-07-22 02:38:59 -050029#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
30static constexpr const std::array<const char*, 2> supportedResourceTypes = {
31 "IBMConfigFile", "Task"};
32#else
33static constexpr const std::array<const char*, 1> supportedResourceTypes = {
34 "Task"};
35#endif
36
AppaRao Pulie5aaf042020-03-20 01:05:52 +053037static constexpr const uint8_t maxNoOfSubscriptions = 20;
38
AppaRao Pulie5aaf042020-03-20 01:05:52 +053039class EventService : public Node
40{
41 public:
42 EventService(CrowApp& app) : Node(app, "/redfish/v1/EventService/")
43 {
AppaRao Pulie5aaf042020-03-20 01:05:52 +053044 entityPrivileges = {
45 {boost::beast::http::verb::get, {{"Login"}}},
46 {boost::beast::http::verb::head, {{"Login"}}},
47 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
48 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
49 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
50 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
51 }
52
53 private:
54 void doGet(crow::Response& res, const crow::Request& req,
55 const std::vector<std::string>& params) override
56 {
57 auto asyncResp = std::make_shared<AsyncResp>(res);
58 res.jsonValue = {
59 {"@odata.type", "#EventService.v1_5_0.EventService"},
60 {"Id", "EventService"},
61 {"Name", "Event Service"},
62 {"ServerSentEventUri",
63 "/redfish/v1/EventService/Subscriptions/SSE"},
64 {"Subscriptions",
65 {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}},
AppaRao Puli0b4bdd92020-04-14 17:57:45 +053066 {"Actions",
67 {{"#EventService.SubmitTestEvent",
68 {{"target", "/redfish/v1/EventService/Actions/"
69 "EventService.SubmitTestEvent"}}}}},
AppaRao Pulie5aaf042020-03-20 01:05:52 +053070 {"@odata.id", "/redfish/v1/EventService"}};
71
AppaRao Puli7d1cc382020-05-16 02:42:22 +053072 const auto& [enabled, retryAttempts, retryTimeoutInterval] =
73 EventServiceManager::getInstance().getEventServiceConfig();
74
75 asyncResp->res.jsonValue["Status"]["State"] =
76 (enabled ? "Enabled" : "Disabled");
77 asyncResp->res.jsonValue["ServiceEnabled"] = enabled;
78 asyncResp->res.jsonValue["DeliveryRetryAttempts"] = retryAttempts;
AppaRao Pulie5aaf042020-03-20 01:05:52 +053079 asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
AppaRao Puli7d1cc382020-05-16 02:42:22 +053080 retryTimeoutInterval;
AppaRao Pulie5aaf042020-03-20 01:05:52 +053081 asyncResp->res.jsonValue["EventFormatTypes"] = supportedEvtFormatTypes;
82 asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
Sunitha Harishe56f2542020-07-22 02:38:59 -050083 asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
Ayushi Smriti07941a82020-05-21 15:55:34 +053084
85 nlohmann::json supportedSSEFilters = {
86 {"EventFormatType", true}, {"MessageId", true},
87 {"MetricReportDefinition", true}, {"RegistryPrefix", true},
88 {"OriginResource", false}, {"ResourceType", false}};
89
90 asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
91 supportedSSEFilters;
AppaRao Pulie5aaf042020-03-20 01:05:52 +053092 }
93
94 void doPatch(crow::Response& res, const crow::Request& req,
95 const std::vector<std::string>& params) override
96 {
97 auto asyncResp = std::make_shared<AsyncResp>(res);
98
99 std::optional<bool> serviceEnabled;
100 std::optional<uint32_t> retryAttemps;
101 std::optional<uint32_t> retryInterval;
102
103 if (!json_util::readJson(req, res, "ServiceEnabled", serviceEnabled,
104 "DeliveryRetryAttempts", retryAttemps,
105 "DeliveryRetryIntervalSeconds", retryInterval))
106 {
107 return;
108 }
109
AppaRao Puli7d1cc382020-05-16 02:42:22 +0530110 auto [enabled, retryCount, retryTimeoutInterval] =
111 EventServiceManager::getInstance().getEventServiceConfig();
112
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530113 if (serviceEnabled)
114 {
AppaRao Puli7d1cc382020-05-16 02:42:22 +0530115 enabled = *serviceEnabled;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530116 }
117
118 if (retryAttemps)
119 {
120 // Supported range [1-3]
121 if ((*retryAttemps < 1) || (*retryAttemps > 3))
122 {
123 messages::queryParameterOutOfRange(
124 asyncResp->res, std::to_string(*retryAttemps),
125 "DeliveryRetryAttempts", "[1-3]");
126 }
127 else
128 {
AppaRao Puli7d1cc382020-05-16 02:42:22 +0530129 retryCount = *retryAttemps;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530130 }
131 }
132
133 if (retryInterval)
134 {
135 // Supported range [30 - 180]
136 if ((*retryInterval < 30) || (*retryInterval > 180))
137 {
138 messages::queryParameterOutOfRange(
139 asyncResp->res, std::to_string(*retryInterval),
140 "DeliveryRetryIntervalSeconds", "[30-180]");
141 }
142 else
143 {
AppaRao Puli7d1cc382020-05-16 02:42:22 +0530144 retryTimeoutInterval = *retryInterval;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530145 }
146 }
147
AppaRao Puli7d1cc382020-05-16 02:42:22 +0530148 EventServiceManager::getInstance().setEventServiceConfig(
149 std::make_tuple(enabled, retryCount, retryTimeoutInterval));
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530150 }
151};
152
AppaRao Puli0b4bdd92020-04-14 17:57:45 +0530153class SubmitTestEvent : public Node
154{
155 public:
156 SubmitTestEvent(CrowApp& app) :
157 Node(app,
158 "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent/")
159 {
160 entityPrivileges = {
161 {boost::beast::http::verb::get, {{"Login"}}},
162 {boost::beast::http::verb::head, {{"Login"}}},
163 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
164 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
165 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
166 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
167 }
168
169 private:
170 void doPost(crow::Response& res, const crow::Request& req,
171 const std::vector<std::string>& params) override
172 {
173 EventServiceManager::getInstance().sendTestEventLog();
174 res.result(boost::beast::http::status::no_content);
175 res.end();
176 }
177};
178
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530179class EventDestinationCollection : public Node
180{
181 public:
182 EventDestinationCollection(CrowApp& app) :
183 Node(app, "/redfish/v1/EventService/Subscriptions/")
184 {
185 entityPrivileges = {
186 {boost::beast::http::verb::get, {{"Login"}}},
187 {boost::beast::http::verb::head, {{"Login"}}},
188 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
189 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
190 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
191 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
192 }
193
194 private:
195 void doGet(crow::Response& res, const crow::Request& req,
196 const std::vector<std::string>& params) override
197 {
198 auto asyncResp = std::make_shared<AsyncResp>(res);
199
200 res.jsonValue = {
201 {"@odata.type",
202 "#EventDestinationCollection.EventDestinationCollection"},
203 {"@odata.id", "/redfish/v1/EventService/Subscriptions"},
204 {"Name", "Event Destination Collections"}};
205
206 nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530207
AppaRao Pulib52664e2020-04-09 21:36:51 +0530208 std::vector<std::string> subscripIds =
209 EventServiceManager::getInstance().getAllIDs();
210 memberArray = nlohmann::json::array();
211 asyncResp->res.jsonValue["Members@odata.count"] = subscripIds.size();
212
213 for (const std::string& id : subscripIds)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530214 {
215 memberArray.push_back(
216 {{"@odata.id",
AppaRao Pulib52664e2020-04-09 21:36:51 +0530217 "/redfish/v1/EventService/Subscriptions/" + id}});
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530218 }
219 }
220
221 void doPost(crow::Response& res, const crow::Request& req,
222 const std::vector<std::string>& params) override
223 {
224 auto asyncResp = std::make_shared<AsyncResp>(res);
225
AppaRao Pulib52664e2020-04-09 21:36:51 +0530226 if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
227 maxNoOfSubscriptions)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530228 {
229 messages::eventSubscriptionLimitExceeded(asyncResp->res);
230 return;
231 }
232 std::string destUrl;
233 std::string protocol;
234 std::optional<std::string> context;
235 std::optional<std::string> subscriptionType;
236 std::optional<std::string> eventFormatType;
237 std::optional<std::string> retryPolicy;
238 std::optional<std::vector<std::string>> msgIds;
239 std::optional<std::vector<std::string>> regPrefixes;
Sunitha Harishe56f2542020-07-22 02:38:59 -0500240 std::optional<std::vector<std::string>> resTypes;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530241 std::optional<std::vector<nlohmann::json>> headers;
AppaRao Puli156d6b02020-04-25 06:04:05 +0530242 std::optional<std::vector<nlohmann::json>> metricReportDefinitions;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530243
244 if (!json_util::readJson(
245 req, res, "Destination", destUrl, "Context", context,
246 "Protocol", protocol, "SubscriptionType", subscriptionType,
247 "EventFormatType", eventFormatType, "HttpHeaders", headers,
248 "RegistryPrefixes", regPrefixes, "MessageIds", msgIds,
AppaRao Puli156d6b02020-04-25 06:04:05 +0530249 "DeliveryRetryPolicy", retryPolicy, "MetricReportDefinitions",
Sunitha Harishe56f2542020-07-22 02:38:59 -0500250 metricReportDefinitions, "ResourceTypes", resTypes))
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530251 {
252 return;
253 }
254
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530255 // Validate the URL using regex expression
AppaRao Pulib52664e2020-04-09 21:36:51 +0530256 // Format: <protocol>://<host>:<port>/<uri>
257 // protocol: http/https
258 // host: Exclude ' ', ':', '#', '?'
Gunnar Mills4e0453b2020-07-08 14:00:30 -0500259 // port: Empty or numeric value with ':' separator.
AppaRao Pulib52664e2020-04-09 21:36:51 +0530260 // uri: Start with '/' and Exclude '#', ' '
261 // Can include query params(ex: '/event?test=1')
262 // TODO: Need to validate hostname extensively(as per rfc)
263 const std::regex urlRegex(
264 "(http|https)://([^/\\x20\\x3f\\x23\\x3a]+):?([0-9]*)(/"
265 "([^\\x20\\x23\\x3f]*\\x3f?([^\\x20\\x23\\x3f])*)?)");
266 std::cmatch match;
267 if (!std::regex_match(destUrl.c_str(), match, urlRegex))
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530268 {
269 messages::propertyValueFormatError(asyncResp->res, destUrl,
270 "Destination");
271 return;
272 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530273
274 std::string uriProto = std::string(match[1].first, match[1].second);
275 if (uriProto == "http")
276 {
277#ifndef BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING
278 messages::propertyValueFormatError(asyncResp->res, destUrl,
279 "Destination");
280 return;
281#endif
282 }
283
284 std::string host = std::string(match[2].first, match[2].second);
285 std::string port = std::string(match[3].first, match[3].second);
286 std::string path = std::string(match[4].first, match[4].second);
287 if (port.empty())
288 {
289 if (uriProto == "http")
290 {
291 port = "80";
292 }
293 else
294 {
295 port = "443";
296 }
297 }
298 if (path.empty())
299 {
300 path = "/";
301 }
302
303 std::shared_ptr<Subscription> subValue =
304 std::make_shared<Subscription>(host, port, path, uriProto);
305
306 subValue->destinationUrl = destUrl;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530307
308 if (subscriptionType)
309 {
310 if (*subscriptionType != "RedfishEvent")
311 {
312 messages::propertyValueNotInList(
313 asyncResp->res, *subscriptionType, "SubscriptionType");
314 return;
315 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530316 subValue->subscriptionType = *subscriptionType;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530317 }
318 else
319 {
AppaRao Pulib52664e2020-04-09 21:36:51 +0530320 subValue->subscriptionType = "RedfishEvent"; // Default
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530321 }
322
323 if (protocol != "Redfish")
324 {
325 messages::propertyValueNotInList(asyncResp->res, protocol,
326 "Protocol");
327 return;
328 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530329 subValue->protocol = protocol;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530330
331 if (eventFormatType)
332 {
333 if (std::find(supportedEvtFormatTypes.begin(),
334 supportedEvtFormatTypes.end(),
335 *eventFormatType) == supportedEvtFormatTypes.end())
336 {
337 messages::propertyValueNotInList(
338 asyncResp->res, *eventFormatType, "EventFormatType");
339 return;
340 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530341 subValue->eventFormatType = *eventFormatType;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530342 }
343 else
344 {
345 // If not specified, use default "Event"
AppaRao Pulib52664e2020-04-09 21:36:51 +0530346 subValue->eventFormatType.assign({"Event"});
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530347 }
348
349 if (context)
350 {
AppaRao Pulib52664e2020-04-09 21:36:51 +0530351 subValue->customText = *context;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530352 }
353
354 if (headers)
355 {
AppaRao Pulib52664e2020-04-09 21:36:51 +0530356 subValue->httpHeaders = *headers;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530357 }
358
359 if (regPrefixes)
360 {
361 for (const std::string& it : *regPrefixes)
362 {
363 if (std::find(supportedRegPrefixes.begin(),
364 supportedRegPrefixes.end(),
365 it) == supportedRegPrefixes.end())
366 {
367 messages::propertyValueNotInList(asyncResp->res, it,
368 "RegistryPrefixes");
369 return;
370 }
371 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530372 subValue->registryPrefixes = *regPrefixes;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530373 }
374
Sunitha Harishe56f2542020-07-22 02:38:59 -0500375 if (resTypes)
376 {
377 for (const std::string& it : *resTypes)
378 {
379 if (std::find(supportedResourceTypes.begin(),
380 supportedResourceTypes.end(),
381 it) == supportedResourceTypes.end())
382 {
383 messages::propertyValueNotInList(asyncResp->res, it,
384 "ResourceTypes");
385 return;
386 }
387 }
388 subValue->resourceTypes = *resTypes;
389 }
390
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530391 if (msgIds)
392 {
393 // Do we need to loop-up MessageRegistry and validate
394 // data for authenticity??? Not mandate, i believe.
AppaRao Pulib52664e2020-04-09 21:36:51 +0530395 subValue->registryMsgIds = *msgIds;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530396 }
397
398 if (retryPolicy)
399 {
400 if (std::find(supportedRetryPolicies.begin(),
401 supportedRetryPolicies.end(),
402 *retryPolicy) == supportedRetryPolicies.end())
403 {
404 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
405 "DeliveryRetryPolicy");
406 return;
407 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530408 subValue->retryPolicy = *retryPolicy;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530409 }
410 else
411 {
412 // Default "TerminateAfterRetries"
AppaRao Pulib52664e2020-04-09 21:36:51 +0530413 subValue->retryPolicy = "TerminateAfterRetries";
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530414 }
415
AppaRao Puli156d6b02020-04-25 06:04:05 +0530416 if (metricReportDefinitions)
417 {
418 subValue->metricReportDefinitions = *metricReportDefinitions;
419 }
420
AppaRao Pulib52664e2020-04-09 21:36:51 +0530421 std::string id =
422 EventServiceManager::getInstance().addSubscription(subValue);
423 if (id.empty())
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530424 {
425 messages::internalError(asyncResp->res);
426 return;
427 }
428
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530429 messages::created(asyncResp->res);
430 asyncResp->res.addHeader(
431 "Location", "/redfish/v1/EventService/Subscriptions/" + id);
432 }
433};
434
AppaRao Puli4bbf2372020-05-15 21:09:54 +0530435class EventServiceSSE : public Node
436{
437 public:
438 EventServiceSSE(CrowApp& app) :
439 Node(app, "/redfish/v1/EventService/Subscriptions/SSE/")
440 {
441 entityPrivileges = {
442 {boost::beast::http::verb::get, {{"ConfigureManager"}}},
443 {boost::beast::http::verb::head, {{"ConfigureManager"}}},
444 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
445 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
446 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
447 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
448 }
449
450 private:
451 void doGet(crow::Response& res, const crow::Request& req,
452 const std::vector<std::string>& params) override
453 {
454 if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
455 maxNoOfSubscriptions)
456 {
457 messages::eventSubscriptionLimitExceeded(res);
458 res.end();
459 return;
460 }
461
462 std::shared_ptr<crow::Request::Adaptor> sseConn =
463 std::make_shared<crow::Request::Adaptor>(std::move(req.socket()));
464 std::shared_ptr<Subscription> subValue =
465 std::make_shared<Subscription>(sseConn);
466
467 // GET on this URI means, Its SSE subscriptionType.
468 subValue->subscriptionType = "SSE";
Ayushi Smriti07941a82020-05-21 15:55:34 +0530469
470 // Default values
AppaRao Puli4bbf2372020-05-15 21:09:54 +0530471 subValue->protocol = "Redfish";
Ayushi Smriti07941a82020-05-21 15:55:34 +0530472 subValue->retryPolicy = "TerminateAfterRetries";
AppaRao Puli4bbf2372020-05-15 21:09:54 +0530473
474 char* filters = req.urlParams.get("$filter");
475 if (filters == nullptr)
476 {
477 subValue->eventFormatType = "Event";
AppaRao Puli4bbf2372020-05-15 21:09:54 +0530478 }
479 else
480 {
Ayushi Smriti07941a82020-05-21 15:55:34 +0530481 // Reading from query params.
482 bool status = readSSEQueryParams(
483 filters, subValue->eventFormatType, subValue->registryMsgIds,
484 subValue->registryPrefixes, subValue->metricReportDefinitions);
485
486 if (!status)
487 {
488 messages::invalidObject(res, filters);
489 return;
490 }
491
492 if (!subValue->eventFormatType.empty())
493 {
494 if (std::find(supportedEvtFormatTypes.begin(),
495 supportedEvtFormatTypes.end(),
496 subValue->eventFormatType) ==
497 supportedEvtFormatTypes.end())
498 {
499 messages::propertyValueNotInList(
500 res, subValue->eventFormatType, "EventFormatType");
501 return;
502 }
503 }
504 else
505 {
506 // If nothing specified, using default "Event"
507 subValue->eventFormatType.assign({"Event"});
508 }
509
510 if (!subValue->registryPrefixes.empty())
511 {
512 for (const std::string& it : subValue->registryPrefixes)
513 {
514 if (std::find(supportedRegPrefixes.begin(),
515 supportedRegPrefixes.end(),
516 it) == supportedRegPrefixes.end())
517 {
518 messages::propertyValueNotInList(res, it,
519 "RegistryPrefixes");
520 return;
521 }
522 }
523 }
AppaRao Puli4bbf2372020-05-15 21:09:54 +0530524 }
525
526 std::string id =
527 EventServiceManager::getInstance().addSubscription(subValue, false);
528 if (id.empty())
529 {
530 messages::internalError(res);
531 res.end();
532 return;
533 }
534 }
535};
536
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530537class EventDestination : public Node
538{
539 public:
540 EventDestination(CrowApp& app) :
541 Node(app, "/redfish/v1/EventService/Subscriptions/<str>/",
542 std::string())
543 {
544 entityPrivileges = {
545 {boost::beast::http::verb::get, {{"Login"}}},
546 {boost::beast::http::verb::head, {{"Login"}}},
547 {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
548 {boost::beast::http::verb::put, {{"ConfigureManager"}}},
549 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
550 {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
551 }
552
553 private:
554 void doGet(crow::Response& res, const crow::Request& req,
555 const std::vector<std::string>& params) override
556 {
557 auto asyncResp = std::make_shared<AsyncResp>(res);
558 if (params.size() != 1)
559 {
560 messages::internalError(asyncResp->res);
561 return;
562 }
563
AppaRao Pulib52664e2020-04-09 21:36:51 +0530564 std::shared_ptr<Subscription> subValue =
565 EventServiceManager::getInstance().getSubscription(params[0]);
566 if (subValue == nullptr)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530567 {
568 res.result(boost::beast::http::status::not_found);
569 res.end();
570 return;
571 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530572 const std::string& id = params[0];
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530573
574 res.jsonValue = {
575 {"@odata.type", "#EventDestination.v1_7_0.EventDestination"},
576 {"Protocol", "Redfish"}};
577 asyncResp->res.jsonValue["@odata.id"] =
578 "/redfish/v1/EventService/Subscriptions/" + id;
579 asyncResp->res.jsonValue["Id"] = id;
580 asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
AppaRao Pulib52664e2020-04-09 21:36:51 +0530581 asyncResp->res.jsonValue["Destination"] = subValue->destinationUrl;
582 asyncResp->res.jsonValue["Context"] = subValue->customText;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530583 asyncResp->res.jsonValue["SubscriptionType"] =
AppaRao Pulib52664e2020-04-09 21:36:51 +0530584 subValue->subscriptionType;
585 asyncResp->res.jsonValue["HttpHeaders"] = subValue->httpHeaders;
586 asyncResp->res.jsonValue["EventFormatType"] = subValue->eventFormatType;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530587 asyncResp->res.jsonValue["RegistryPrefixes"] =
AppaRao Pulib52664e2020-04-09 21:36:51 +0530588 subValue->registryPrefixes;
Sunitha Harishe56f2542020-07-22 02:38:59 -0500589 asyncResp->res.jsonValue["ResourceTypes"] = subValue->resourceTypes;
590
AppaRao Pulib52664e2020-04-09 21:36:51 +0530591 asyncResp->res.jsonValue["MessageIds"] = subValue->registryMsgIds;
592 asyncResp->res.jsonValue["DeliveryRetryPolicy"] = subValue->retryPolicy;
AppaRao Puli156d6b02020-04-25 06:04:05 +0530593 asyncResp->res.jsonValue["MetricReportDefinitions"] =
594 subValue->metricReportDefinitions;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530595 }
596
597 void doPatch(crow::Response& res, const crow::Request& req,
598 const std::vector<std::string>& params) override
599 {
600 auto asyncResp = std::make_shared<AsyncResp>(res);
601 if (params.size() != 1)
602 {
603 messages::internalError(asyncResp->res);
604 return;
605 }
606
AppaRao Pulib52664e2020-04-09 21:36:51 +0530607 std::shared_ptr<Subscription> subValue =
608 EventServiceManager::getInstance().getSubscription(params[0]);
609 if (subValue == nullptr)
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530610 {
611 res.result(boost::beast::http::status::not_found);
612 res.end();
613 return;
614 }
615
616 std::optional<std::string> context;
617 std::optional<std::string> retryPolicy;
618 std::optional<std::vector<nlohmann::json>> headers;
619
620 if (!json_util::readJson(req, res, "Context", context,
621 "DeliveryRetryPolicy", retryPolicy,
622 "HttpHeaders", headers))
623 {
624 return;
625 }
626
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530627 if (context)
628 {
AppaRao Pulib52664e2020-04-09 21:36:51 +0530629 subValue->customText = *context;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530630 }
631
632 if (headers)
633 {
AppaRao Pulib52664e2020-04-09 21:36:51 +0530634 subValue->httpHeaders = *headers;
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530635 }
636
637 if (retryPolicy)
638 {
639 if (std::find(supportedRetryPolicies.begin(),
640 supportedRetryPolicies.end(),
641 *retryPolicy) == supportedRetryPolicies.end())
642 {
643 messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
644 "DeliveryRetryPolicy");
645 return;
646 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530647 subValue->retryPolicy = *retryPolicy;
Ayushi Smritife44eb02020-05-15 15:24:45 +0530648 subValue->updateRetryPolicy();
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530649 }
650
AppaRao Pulib52664e2020-04-09 21:36:51 +0530651 EventServiceManager::getInstance().updateSubscriptionData();
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530652 }
653
654 void doDelete(crow::Response& res, const crow::Request& req,
655 const std::vector<std::string>& params) override
656 {
657 auto asyncResp = std::make_shared<AsyncResp>(res);
658
659 if (params.size() != 1)
660 {
661 messages::internalError(asyncResp->res);
662 return;
663 }
664
AppaRao Pulib52664e2020-04-09 21:36:51 +0530665 if (!EventServiceManager::getInstance().isSubscriptionExist(params[0]))
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530666 {
667 res.result(boost::beast::http::status::not_found);
668 res.end();
669 return;
670 }
AppaRao Pulib52664e2020-04-09 21:36:51 +0530671 EventServiceManager::getInstance().deleteSubscription(params[0]);
AppaRao Pulie5aaf042020-03-20 01:05:52 +0530672 }
673};
674
675} // namespace redfish