1e5aaf047SAppaRao Puli /* 2e5aaf047SAppaRao Puli // Copyright (c) 2020 Intel Corporation 3e5aaf047SAppaRao Puli // 4e5aaf047SAppaRao Puli // Licensed under the Apache License, Version 2.0 (the "License"); 5e5aaf047SAppaRao Puli // you may not use this file except in compliance with the License. 6e5aaf047SAppaRao Puli // You may obtain a copy of the License at 7e5aaf047SAppaRao Puli // 8e5aaf047SAppaRao Puli // http://www.apache.org/licenses/LICENSE-2.0 9e5aaf047SAppaRao Puli // 10e5aaf047SAppaRao Puli // Unless required by applicable law or agreed to in writing, software 11e5aaf047SAppaRao Puli // distributed under the License is distributed on an "AS IS" BASIS, 12e5aaf047SAppaRao Puli // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e5aaf047SAppaRao Puli // See the License for the specific language governing permissions and 14e5aaf047SAppaRao Puli // limitations under the License. 15e5aaf047SAppaRao Puli */ 16e5aaf047SAppaRao Puli #pragma once 17*b52664e2SAppaRao Puli #include "event_service_manager.hpp" 18e5aaf047SAppaRao Puli 19e5aaf047SAppaRao Puli namespace redfish 20e5aaf047SAppaRao Puli { 21e5aaf047SAppaRao Puli 22e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 1> supportedEvtFormatTypes = { 23e5aaf047SAppaRao Puli "Event"}; 24e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRegPrefixes = { 25e5aaf047SAppaRao Puli "Base", "OpenBMC", "Task"}; 26e5aaf047SAppaRao Puli static constexpr const std::array<const char*, 3> supportedRetryPolicies = { 27e5aaf047SAppaRao Puli "TerminateAfterRetries", "SuspendRetries", "RetryForever"}; 28e5aaf047SAppaRao Puli 29e5aaf047SAppaRao Puli static constexpr const uint8_t maxNoOfSubscriptions = 20; 30e5aaf047SAppaRao Puli 31e5aaf047SAppaRao Puli class EventService : public Node 32e5aaf047SAppaRao Puli { 33e5aaf047SAppaRao Puli public: 34e5aaf047SAppaRao Puli EventService(CrowApp& app) : Node(app, "/redfish/v1/EventService/") 35e5aaf047SAppaRao Puli { 36e5aaf047SAppaRao Puli entityPrivileges = { 37e5aaf047SAppaRao Puli {boost::beast::http::verb::get, {{"Login"}}}, 38e5aaf047SAppaRao Puli {boost::beast::http::verb::head, {{"Login"}}}, 39e5aaf047SAppaRao Puli {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 40e5aaf047SAppaRao Puli {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 41e5aaf047SAppaRao Puli {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 42e5aaf047SAppaRao Puli {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 43e5aaf047SAppaRao Puli } 44e5aaf047SAppaRao Puli 45e5aaf047SAppaRao Puli private: 46e5aaf047SAppaRao Puli void doGet(crow::Response& res, const crow::Request& req, 47e5aaf047SAppaRao Puli const std::vector<std::string>& params) override 48e5aaf047SAppaRao Puli { 49e5aaf047SAppaRao Puli auto asyncResp = std::make_shared<AsyncResp>(res); 50e5aaf047SAppaRao Puli res.jsonValue = { 51e5aaf047SAppaRao Puli {"@odata.type", "#EventService.v1_5_0.EventService"}, 52e5aaf047SAppaRao Puli {"Id", "EventService"}, 53e5aaf047SAppaRao Puli {"Name", "Event Service"}, 54e5aaf047SAppaRao Puli {"ServerSentEventUri", 55e5aaf047SAppaRao Puli "/redfish/v1/EventService/Subscriptions/SSE"}, 56e5aaf047SAppaRao Puli {"Subscriptions", 57e5aaf047SAppaRao Puli {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}}, 58e5aaf047SAppaRao Puli {"@odata.id", "/redfish/v1/EventService"}}; 59e5aaf047SAppaRao Puli 60e5aaf047SAppaRao Puli asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 61*b52664e2SAppaRao Puli asyncResp->res.jsonValue["ServiceEnabled"] = 62*b52664e2SAppaRao Puli EventServiceManager::getInstance().enabled; 63e5aaf047SAppaRao Puli asyncResp->res.jsonValue["DeliveryRetryAttempts"] = 64*b52664e2SAppaRao Puli EventServiceManager::getInstance().retryAttempts; 65e5aaf047SAppaRao Puli asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] = 66*b52664e2SAppaRao Puli EventServiceManager::getInstance().retryTimeoutInterval; 67e5aaf047SAppaRao Puli asyncResp->res.jsonValue["EventFormatTypes"] = supportedEvtFormatTypes; 68e5aaf047SAppaRao Puli asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes; 69e5aaf047SAppaRao Puli } 70e5aaf047SAppaRao Puli 71e5aaf047SAppaRao Puli void doPatch(crow::Response& res, const crow::Request& req, 72e5aaf047SAppaRao Puli const std::vector<std::string>& params) override 73e5aaf047SAppaRao Puli { 74e5aaf047SAppaRao Puli auto asyncResp = std::make_shared<AsyncResp>(res); 75e5aaf047SAppaRao Puli 76e5aaf047SAppaRao Puli std::optional<bool> serviceEnabled; 77e5aaf047SAppaRao Puli std::optional<uint32_t> retryAttemps; 78e5aaf047SAppaRao Puli std::optional<uint32_t> retryInterval; 79e5aaf047SAppaRao Puli 80e5aaf047SAppaRao Puli if (!json_util::readJson(req, res, "ServiceEnabled", serviceEnabled, 81e5aaf047SAppaRao Puli "DeliveryRetryAttempts", retryAttemps, 82e5aaf047SAppaRao Puli "DeliveryRetryIntervalSeconds", retryInterval)) 83e5aaf047SAppaRao Puli { 84e5aaf047SAppaRao Puli return; 85e5aaf047SAppaRao Puli } 86e5aaf047SAppaRao Puli 87e5aaf047SAppaRao Puli if (serviceEnabled) 88e5aaf047SAppaRao Puli { 89*b52664e2SAppaRao Puli EventServiceManager::getInstance().enabled = *serviceEnabled; 90e5aaf047SAppaRao Puli } 91e5aaf047SAppaRao Puli 92e5aaf047SAppaRao Puli if (retryAttemps) 93e5aaf047SAppaRao Puli { 94e5aaf047SAppaRao Puli // Supported range [1-3] 95e5aaf047SAppaRao Puli if ((*retryAttemps < 1) || (*retryAttemps > 3)) 96e5aaf047SAppaRao Puli { 97e5aaf047SAppaRao Puli messages::queryParameterOutOfRange( 98e5aaf047SAppaRao Puli asyncResp->res, std::to_string(*retryAttemps), 99e5aaf047SAppaRao Puli "DeliveryRetryAttempts", "[1-3]"); 100e5aaf047SAppaRao Puli } 101e5aaf047SAppaRao Puli else 102e5aaf047SAppaRao Puli { 103*b52664e2SAppaRao Puli EventServiceManager::getInstance().retryAttempts = 104*b52664e2SAppaRao Puli *retryAttemps; 105e5aaf047SAppaRao Puli } 106e5aaf047SAppaRao Puli } 107e5aaf047SAppaRao Puli 108e5aaf047SAppaRao Puli if (retryInterval) 109e5aaf047SAppaRao Puli { 110e5aaf047SAppaRao Puli // Supported range [30 - 180] 111e5aaf047SAppaRao Puli if ((*retryInterval < 30) || (*retryInterval > 180)) 112e5aaf047SAppaRao Puli { 113e5aaf047SAppaRao Puli messages::queryParameterOutOfRange( 114e5aaf047SAppaRao Puli asyncResp->res, std::to_string(*retryInterval), 115e5aaf047SAppaRao Puli "DeliveryRetryIntervalSeconds", "[30-180]"); 116e5aaf047SAppaRao Puli } 117e5aaf047SAppaRao Puli else 118e5aaf047SAppaRao Puli { 119*b52664e2SAppaRao Puli EventServiceManager::getInstance().retryTimeoutInterval = 120*b52664e2SAppaRao Puli *retryInterval; 121e5aaf047SAppaRao Puli } 122e5aaf047SAppaRao Puli } 123e5aaf047SAppaRao Puli 124*b52664e2SAppaRao Puli EventServiceManager::getInstance().updateSubscriptionData(); 125e5aaf047SAppaRao Puli } 126e5aaf047SAppaRao Puli }; 127e5aaf047SAppaRao Puli 128e5aaf047SAppaRao Puli class EventDestinationCollection : public Node 129e5aaf047SAppaRao Puli { 130e5aaf047SAppaRao Puli public: 131e5aaf047SAppaRao Puli EventDestinationCollection(CrowApp& app) : 132e5aaf047SAppaRao Puli Node(app, "/redfish/v1/EventService/Subscriptions/") 133e5aaf047SAppaRao Puli { 134e5aaf047SAppaRao Puli entityPrivileges = { 135e5aaf047SAppaRao Puli {boost::beast::http::verb::get, {{"Login"}}}, 136e5aaf047SAppaRao Puli {boost::beast::http::verb::head, {{"Login"}}}, 137e5aaf047SAppaRao Puli {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 138e5aaf047SAppaRao Puli {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 139e5aaf047SAppaRao Puli {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 140e5aaf047SAppaRao Puli {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 141e5aaf047SAppaRao Puli } 142e5aaf047SAppaRao Puli 143e5aaf047SAppaRao Puli private: 144e5aaf047SAppaRao Puli void doGet(crow::Response& res, const crow::Request& req, 145e5aaf047SAppaRao Puli const std::vector<std::string>& params) override 146e5aaf047SAppaRao Puli { 147e5aaf047SAppaRao Puli auto asyncResp = std::make_shared<AsyncResp>(res); 148e5aaf047SAppaRao Puli 149e5aaf047SAppaRao Puli res.jsonValue = { 150e5aaf047SAppaRao Puli {"@odata.type", 151e5aaf047SAppaRao Puli "#EventDestinationCollection.EventDestinationCollection"}, 152e5aaf047SAppaRao Puli {"@odata.id", "/redfish/v1/EventService/Subscriptions"}, 153e5aaf047SAppaRao Puli {"Name", "Event Destination Collections"}}; 154e5aaf047SAppaRao Puli 155e5aaf047SAppaRao Puli nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"]; 156e5aaf047SAppaRao Puli 157*b52664e2SAppaRao Puli std::vector<std::string> subscripIds = 158*b52664e2SAppaRao Puli EventServiceManager::getInstance().getAllIDs(); 159*b52664e2SAppaRao Puli memberArray = nlohmann::json::array(); 160*b52664e2SAppaRao Puli asyncResp->res.jsonValue["Members@odata.count"] = subscripIds.size(); 161*b52664e2SAppaRao Puli 162*b52664e2SAppaRao Puli for (const std::string& id : subscripIds) 163e5aaf047SAppaRao Puli { 164e5aaf047SAppaRao Puli memberArray.push_back( 165e5aaf047SAppaRao Puli {{"@odata.id", 166*b52664e2SAppaRao Puli "/redfish/v1/EventService/Subscriptions/" + id}}); 167e5aaf047SAppaRao Puli } 168e5aaf047SAppaRao Puli } 169e5aaf047SAppaRao Puli 170e5aaf047SAppaRao Puli void doPost(crow::Response& res, const crow::Request& req, 171e5aaf047SAppaRao Puli const std::vector<std::string>& params) override 172e5aaf047SAppaRao Puli { 173e5aaf047SAppaRao Puli auto asyncResp = std::make_shared<AsyncResp>(res); 174e5aaf047SAppaRao Puli 175*b52664e2SAppaRao Puli if (EventServiceManager::getInstance().getNumberOfSubscriptions() >= 176*b52664e2SAppaRao Puli maxNoOfSubscriptions) 177e5aaf047SAppaRao Puli { 178e5aaf047SAppaRao Puli messages::eventSubscriptionLimitExceeded(asyncResp->res); 179e5aaf047SAppaRao Puli return; 180e5aaf047SAppaRao Puli } 181e5aaf047SAppaRao Puli std::string destUrl; 182e5aaf047SAppaRao Puli std::string protocol; 183e5aaf047SAppaRao Puli std::optional<std::string> context; 184e5aaf047SAppaRao Puli std::optional<std::string> subscriptionType; 185e5aaf047SAppaRao Puli std::optional<std::string> eventFormatType; 186e5aaf047SAppaRao Puli std::optional<std::string> retryPolicy; 187e5aaf047SAppaRao Puli std::optional<std::vector<std::string>> msgIds; 188e5aaf047SAppaRao Puli std::optional<std::vector<std::string>> regPrefixes; 189e5aaf047SAppaRao Puli std::optional<std::vector<nlohmann::json>> headers; 190e5aaf047SAppaRao Puli 191e5aaf047SAppaRao Puli if (!json_util::readJson( 192e5aaf047SAppaRao Puli req, res, "Destination", destUrl, "Context", context, 193e5aaf047SAppaRao Puli "Protocol", protocol, "SubscriptionType", subscriptionType, 194e5aaf047SAppaRao Puli "EventFormatType", eventFormatType, "HttpHeaders", headers, 195e5aaf047SAppaRao Puli "RegistryPrefixes", regPrefixes, "MessageIds", msgIds, 196e5aaf047SAppaRao Puli "DeliveryRetryPolicy", retryPolicy)) 197e5aaf047SAppaRao Puli { 198e5aaf047SAppaRao Puli return; 199e5aaf047SAppaRao Puli } 200e5aaf047SAppaRao Puli 201e5aaf047SAppaRao Puli // Validate the URL using regex expression 202*b52664e2SAppaRao Puli // Format: <protocol>://<host>:<port>/<uri> 203*b52664e2SAppaRao Puli // protocol: http/https 204*b52664e2SAppaRao Puli // host: Exclude ' ', ':', '#', '?' 205*b52664e2SAppaRao Puli // port: Empty or numeric value with ':' seperator. 206*b52664e2SAppaRao Puli // uri: Start with '/' and Exclude '#', ' ' 207*b52664e2SAppaRao Puli // Can include query params(ex: '/event?test=1') 208*b52664e2SAppaRao Puli // TODO: Need to validate hostname extensively(as per rfc) 209*b52664e2SAppaRao Puli const std::regex urlRegex( 210*b52664e2SAppaRao Puli "(http|https)://([^/\\x20\\x3f\\x23\\x3a]+):?([0-9]*)(/" 211*b52664e2SAppaRao Puli "([^\\x20\\x23\\x3f]*\\x3f?([^\\x20\\x23\\x3f])*)?)"); 212*b52664e2SAppaRao Puli std::cmatch match; 213*b52664e2SAppaRao Puli if (!std::regex_match(destUrl.c_str(), match, urlRegex)) 214e5aaf047SAppaRao Puli { 215e5aaf047SAppaRao Puli messages::propertyValueFormatError(asyncResp->res, destUrl, 216e5aaf047SAppaRao Puli "Destination"); 217e5aaf047SAppaRao Puli return; 218e5aaf047SAppaRao Puli } 219*b52664e2SAppaRao Puli 220*b52664e2SAppaRao Puli std::string uriProto = std::string(match[1].first, match[1].second); 221*b52664e2SAppaRao Puli if (uriProto == "http") 222*b52664e2SAppaRao Puli { 223*b52664e2SAppaRao Puli #ifndef BMCWEB_INSECURE_ENABLE_HTTP_PUSH_STYLE_EVENTING 224*b52664e2SAppaRao Puli messages::propertyValueFormatError(asyncResp->res, destUrl, 225*b52664e2SAppaRao Puli "Destination"); 226*b52664e2SAppaRao Puli return; 227*b52664e2SAppaRao Puli #endif 228*b52664e2SAppaRao Puli } 229*b52664e2SAppaRao Puli 230*b52664e2SAppaRao Puli std::string host = std::string(match[2].first, match[2].second); 231*b52664e2SAppaRao Puli std::string port = std::string(match[3].first, match[3].second); 232*b52664e2SAppaRao Puli std::string path = std::string(match[4].first, match[4].second); 233*b52664e2SAppaRao Puli if (port.empty()) 234*b52664e2SAppaRao Puli { 235*b52664e2SAppaRao Puli if (uriProto == "http") 236*b52664e2SAppaRao Puli { 237*b52664e2SAppaRao Puli port = "80"; 238*b52664e2SAppaRao Puli } 239*b52664e2SAppaRao Puli else 240*b52664e2SAppaRao Puli { 241*b52664e2SAppaRao Puli port = "443"; 242*b52664e2SAppaRao Puli } 243*b52664e2SAppaRao Puli } 244*b52664e2SAppaRao Puli if (path.empty()) 245*b52664e2SAppaRao Puli { 246*b52664e2SAppaRao Puli path = "/"; 247*b52664e2SAppaRao Puli } 248*b52664e2SAppaRao Puli 249*b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 250*b52664e2SAppaRao Puli std::make_shared<Subscription>(host, port, path, uriProto); 251*b52664e2SAppaRao Puli 252*b52664e2SAppaRao Puli subValue->destinationUrl = destUrl; 253e5aaf047SAppaRao Puli 254e5aaf047SAppaRao Puli if (subscriptionType) 255e5aaf047SAppaRao Puli { 256e5aaf047SAppaRao Puli if (*subscriptionType != "RedfishEvent") 257e5aaf047SAppaRao Puli { 258e5aaf047SAppaRao Puli messages::propertyValueNotInList( 259e5aaf047SAppaRao Puli asyncResp->res, *subscriptionType, "SubscriptionType"); 260e5aaf047SAppaRao Puli return; 261e5aaf047SAppaRao Puli } 262*b52664e2SAppaRao Puli subValue->subscriptionType = *subscriptionType; 263e5aaf047SAppaRao Puli } 264e5aaf047SAppaRao Puli else 265e5aaf047SAppaRao Puli { 266*b52664e2SAppaRao Puli subValue->subscriptionType = "RedfishEvent"; // Default 267e5aaf047SAppaRao Puli } 268e5aaf047SAppaRao Puli 269e5aaf047SAppaRao Puli if (protocol != "Redfish") 270e5aaf047SAppaRao Puli { 271e5aaf047SAppaRao Puli messages::propertyValueNotInList(asyncResp->res, protocol, 272e5aaf047SAppaRao Puli "Protocol"); 273e5aaf047SAppaRao Puli return; 274e5aaf047SAppaRao Puli } 275*b52664e2SAppaRao Puli subValue->protocol = protocol; 276e5aaf047SAppaRao Puli 277e5aaf047SAppaRao Puli if (eventFormatType) 278e5aaf047SAppaRao Puli { 279e5aaf047SAppaRao Puli if (std::find(supportedEvtFormatTypes.begin(), 280e5aaf047SAppaRao Puli supportedEvtFormatTypes.end(), 281e5aaf047SAppaRao Puli *eventFormatType) == supportedEvtFormatTypes.end()) 282e5aaf047SAppaRao Puli { 283e5aaf047SAppaRao Puli messages::propertyValueNotInList( 284e5aaf047SAppaRao Puli asyncResp->res, *eventFormatType, "EventFormatType"); 285e5aaf047SAppaRao Puli return; 286e5aaf047SAppaRao Puli } 287*b52664e2SAppaRao Puli subValue->eventFormatType = *eventFormatType; 288e5aaf047SAppaRao Puli } 289e5aaf047SAppaRao Puli else 290e5aaf047SAppaRao Puli { 291e5aaf047SAppaRao Puli // If not specified, use default "Event" 292*b52664e2SAppaRao Puli subValue->eventFormatType.assign({"Event"}); 293e5aaf047SAppaRao Puli } 294e5aaf047SAppaRao Puli 295e5aaf047SAppaRao Puli if (context) 296e5aaf047SAppaRao Puli { 297*b52664e2SAppaRao Puli subValue->customText = *context; 298e5aaf047SAppaRao Puli } 299e5aaf047SAppaRao Puli 300e5aaf047SAppaRao Puli if (headers) 301e5aaf047SAppaRao Puli { 302*b52664e2SAppaRao Puli subValue->httpHeaders = *headers; 303e5aaf047SAppaRao Puli } 304e5aaf047SAppaRao Puli 305e5aaf047SAppaRao Puli if (regPrefixes) 306e5aaf047SAppaRao Puli { 307e5aaf047SAppaRao Puli for (const std::string& it : *regPrefixes) 308e5aaf047SAppaRao Puli { 309e5aaf047SAppaRao Puli if (std::find(supportedRegPrefixes.begin(), 310e5aaf047SAppaRao Puli supportedRegPrefixes.end(), 311e5aaf047SAppaRao Puli it) == supportedRegPrefixes.end()) 312e5aaf047SAppaRao Puli { 313e5aaf047SAppaRao Puli messages::propertyValueNotInList(asyncResp->res, it, 314e5aaf047SAppaRao Puli "RegistryPrefixes"); 315e5aaf047SAppaRao Puli return; 316e5aaf047SAppaRao Puli } 317e5aaf047SAppaRao Puli } 318*b52664e2SAppaRao Puli subValue->registryPrefixes = *regPrefixes; 319e5aaf047SAppaRao Puli } 320e5aaf047SAppaRao Puli 321e5aaf047SAppaRao Puli if (msgIds) 322e5aaf047SAppaRao Puli { 323e5aaf047SAppaRao Puli // Do we need to loop-up MessageRegistry and validate 324e5aaf047SAppaRao Puli // data for authenticity??? Not mandate, i believe. 325*b52664e2SAppaRao Puli subValue->registryMsgIds = *msgIds; 326e5aaf047SAppaRao Puli } 327e5aaf047SAppaRao Puli 328e5aaf047SAppaRao Puli if (retryPolicy) 329e5aaf047SAppaRao Puli { 330e5aaf047SAppaRao Puli if (std::find(supportedRetryPolicies.begin(), 331e5aaf047SAppaRao Puli supportedRetryPolicies.end(), 332e5aaf047SAppaRao Puli *retryPolicy) == supportedRetryPolicies.end()) 333e5aaf047SAppaRao Puli { 334e5aaf047SAppaRao Puli messages::propertyValueNotInList(asyncResp->res, *retryPolicy, 335e5aaf047SAppaRao Puli "DeliveryRetryPolicy"); 336e5aaf047SAppaRao Puli return; 337e5aaf047SAppaRao Puli } 338*b52664e2SAppaRao Puli subValue->retryPolicy = *retryPolicy; 339e5aaf047SAppaRao Puli } 340e5aaf047SAppaRao Puli else 341e5aaf047SAppaRao Puli { 342e5aaf047SAppaRao Puli // Default "TerminateAfterRetries" 343*b52664e2SAppaRao Puli subValue->retryPolicy = "TerminateAfterRetries"; 344e5aaf047SAppaRao Puli } 345e5aaf047SAppaRao Puli 346*b52664e2SAppaRao Puli std::string id = 347*b52664e2SAppaRao Puli EventServiceManager::getInstance().addSubscription(subValue); 348*b52664e2SAppaRao Puli if (id.empty()) 349e5aaf047SAppaRao Puli { 350e5aaf047SAppaRao Puli messages::internalError(asyncResp->res); 351e5aaf047SAppaRao Puli return; 352e5aaf047SAppaRao Puli } 353e5aaf047SAppaRao Puli 354e5aaf047SAppaRao Puli messages::created(asyncResp->res); 355e5aaf047SAppaRao Puli asyncResp->res.addHeader( 356e5aaf047SAppaRao Puli "Location", "/redfish/v1/EventService/Subscriptions/" + id); 357e5aaf047SAppaRao Puli } 358e5aaf047SAppaRao Puli }; 359e5aaf047SAppaRao Puli 360e5aaf047SAppaRao Puli class EventDestination : public Node 361e5aaf047SAppaRao Puli { 362e5aaf047SAppaRao Puli public: 363e5aaf047SAppaRao Puli EventDestination(CrowApp& app) : 364e5aaf047SAppaRao Puli Node(app, "/redfish/v1/EventService/Subscriptions/<str>/", 365e5aaf047SAppaRao Puli std::string()) 366e5aaf047SAppaRao Puli { 367e5aaf047SAppaRao Puli entityPrivileges = { 368e5aaf047SAppaRao Puli {boost::beast::http::verb::get, {{"Login"}}}, 369e5aaf047SAppaRao Puli {boost::beast::http::verb::head, {{"Login"}}}, 370e5aaf047SAppaRao Puli {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 371e5aaf047SAppaRao Puli {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 372e5aaf047SAppaRao Puli {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 373e5aaf047SAppaRao Puli {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 374e5aaf047SAppaRao Puli } 375e5aaf047SAppaRao Puli 376e5aaf047SAppaRao Puli private: 377e5aaf047SAppaRao Puli void doGet(crow::Response& res, const crow::Request& req, 378e5aaf047SAppaRao Puli const std::vector<std::string>& params) override 379e5aaf047SAppaRao Puli { 380e5aaf047SAppaRao Puli auto asyncResp = std::make_shared<AsyncResp>(res); 381e5aaf047SAppaRao Puli if (params.size() != 1) 382e5aaf047SAppaRao Puli { 383e5aaf047SAppaRao Puli messages::internalError(asyncResp->res); 384e5aaf047SAppaRao Puli return; 385e5aaf047SAppaRao Puli } 386e5aaf047SAppaRao Puli 387*b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 388*b52664e2SAppaRao Puli EventServiceManager::getInstance().getSubscription(params[0]); 389*b52664e2SAppaRao Puli if (subValue == nullptr) 390e5aaf047SAppaRao Puli { 391e5aaf047SAppaRao Puli res.result(boost::beast::http::status::not_found); 392e5aaf047SAppaRao Puli res.end(); 393e5aaf047SAppaRao Puli return; 394e5aaf047SAppaRao Puli } 395*b52664e2SAppaRao Puli const std::string& id = params[0]; 396e5aaf047SAppaRao Puli 397e5aaf047SAppaRao Puli res.jsonValue = { 398e5aaf047SAppaRao Puli {"@odata.type", "#EventDestination.v1_7_0.EventDestination"}, 399e5aaf047SAppaRao Puli {"Protocol", "Redfish"}}; 400e5aaf047SAppaRao Puli asyncResp->res.jsonValue["@odata.id"] = 401e5aaf047SAppaRao Puli "/redfish/v1/EventService/Subscriptions/" + id; 402e5aaf047SAppaRao Puli asyncResp->res.jsonValue["Id"] = id; 403e5aaf047SAppaRao Puli asyncResp->res.jsonValue["Name"] = "Event Destination " + id; 404*b52664e2SAppaRao Puli asyncResp->res.jsonValue["Destination"] = subValue->destinationUrl; 405*b52664e2SAppaRao Puli asyncResp->res.jsonValue["Context"] = subValue->customText; 406e5aaf047SAppaRao Puli asyncResp->res.jsonValue["SubscriptionType"] = 407*b52664e2SAppaRao Puli subValue->subscriptionType; 408*b52664e2SAppaRao Puli asyncResp->res.jsonValue["HttpHeaders"] = subValue->httpHeaders; 409*b52664e2SAppaRao Puli asyncResp->res.jsonValue["EventFormatType"] = subValue->eventFormatType; 410e5aaf047SAppaRao Puli asyncResp->res.jsonValue["RegistryPrefixes"] = 411*b52664e2SAppaRao Puli subValue->registryPrefixes; 412*b52664e2SAppaRao Puli asyncResp->res.jsonValue["MessageIds"] = subValue->registryMsgIds; 413*b52664e2SAppaRao Puli asyncResp->res.jsonValue["DeliveryRetryPolicy"] = subValue->retryPolicy; 414e5aaf047SAppaRao Puli } 415e5aaf047SAppaRao Puli 416e5aaf047SAppaRao Puli void doPatch(crow::Response& res, const crow::Request& req, 417e5aaf047SAppaRao Puli const std::vector<std::string>& params) override 418e5aaf047SAppaRao Puli { 419e5aaf047SAppaRao Puli auto asyncResp = std::make_shared<AsyncResp>(res); 420e5aaf047SAppaRao Puli if (params.size() != 1) 421e5aaf047SAppaRao Puli { 422e5aaf047SAppaRao Puli messages::internalError(asyncResp->res); 423e5aaf047SAppaRao Puli return; 424e5aaf047SAppaRao Puli } 425e5aaf047SAppaRao Puli 426*b52664e2SAppaRao Puli std::shared_ptr<Subscription> subValue = 427*b52664e2SAppaRao Puli EventServiceManager::getInstance().getSubscription(params[0]); 428*b52664e2SAppaRao Puli if (subValue == nullptr) 429e5aaf047SAppaRao Puli { 430e5aaf047SAppaRao Puli res.result(boost::beast::http::status::not_found); 431e5aaf047SAppaRao Puli res.end(); 432e5aaf047SAppaRao Puli return; 433e5aaf047SAppaRao Puli } 434e5aaf047SAppaRao Puli 435e5aaf047SAppaRao Puli std::optional<std::string> context; 436e5aaf047SAppaRao Puli std::optional<std::string> retryPolicy; 437e5aaf047SAppaRao Puli std::optional<std::vector<nlohmann::json>> headers; 438e5aaf047SAppaRao Puli 439e5aaf047SAppaRao Puli if (!json_util::readJson(req, res, "Context", context, 440e5aaf047SAppaRao Puli "DeliveryRetryPolicy", retryPolicy, 441e5aaf047SAppaRao Puli "HttpHeaders", headers)) 442e5aaf047SAppaRao Puli { 443e5aaf047SAppaRao Puli return; 444e5aaf047SAppaRao Puli } 445e5aaf047SAppaRao Puli 446e5aaf047SAppaRao Puli if (context) 447e5aaf047SAppaRao Puli { 448*b52664e2SAppaRao Puli subValue->customText = *context; 449e5aaf047SAppaRao Puli } 450e5aaf047SAppaRao Puli 451e5aaf047SAppaRao Puli if (headers) 452e5aaf047SAppaRao Puli { 453*b52664e2SAppaRao Puli subValue->httpHeaders = *headers; 454e5aaf047SAppaRao Puli } 455e5aaf047SAppaRao Puli 456e5aaf047SAppaRao Puli if (retryPolicy) 457e5aaf047SAppaRao Puli { 458e5aaf047SAppaRao Puli if (std::find(supportedRetryPolicies.begin(), 459e5aaf047SAppaRao Puli supportedRetryPolicies.end(), 460e5aaf047SAppaRao Puli *retryPolicy) == supportedRetryPolicies.end()) 461e5aaf047SAppaRao Puli { 462e5aaf047SAppaRao Puli messages::propertyValueNotInList(asyncResp->res, *retryPolicy, 463e5aaf047SAppaRao Puli "DeliveryRetryPolicy"); 464e5aaf047SAppaRao Puli return; 465e5aaf047SAppaRao Puli } 466*b52664e2SAppaRao Puli subValue->retryPolicy = *retryPolicy; 467e5aaf047SAppaRao Puli } 468e5aaf047SAppaRao Puli 469*b52664e2SAppaRao Puli EventServiceManager::getInstance().updateSubscriptionData(); 470e5aaf047SAppaRao Puli } 471e5aaf047SAppaRao Puli 472e5aaf047SAppaRao Puli void doDelete(crow::Response& res, const crow::Request& req, 473e5aaf047SAppaRao Puli const std::vector<std::string>& params) override 474e5aaf047SAppaRao Puli { 475e5aaf047SAppaRao Puli auto asyncResp = std::make_shared<AsyncResp>(res); 476e5aaf047SAppaRao Puli 477e5aaf047SAppaRao Puli if (params.size() != 1) 478e5aaf047SAppaRao Puli { 479e5aaf047SAppaRao Puli messages::internalError(asyncResp->res); 480e5aaf047SAppaRao Puli return; 481e5aaf047SAppaRao Puli } 482e5aaf047SAppaRao Puli 483*b52664e2SAppaRao Puli if (!EventServiceManager::getInstance().isSubscriptionExist(params[0])) 484e5aaf047SAppaRao Puli { 485e5aaf047SAppaRao Puli res.result(boost::beast::http::status::not_found); 486e5aaf047SAppaRao Puli res.end(); 487e5aaf047SAppaRao Puli return; 488e5aaf047SAppaRao Puli } 489*b52664e2SAppaRao Puli EventServiceManager::getInstance().deleteSubscription(params[0]); 490e5aaf047SAppaRao Puli } 491e5aaf047SAppaRao Puli }; 492e5aaf047SAppaRao Puli 493e5aaf047SAppaRao Puli } // namespace redfish 494