16c038f26SEd Tanous #include "error_message_utils.hpp" 26c038f26SEd Tanous 36c038f26SEd Tanous #include "logging.hpp" 46c038f26SEd Tanous 56c038f26SEd Tanous #include <nlohmann/json.hpp> 66c038f26SEd Tanous 76c038f26SEd Tanous #include <string> 86c038f26SEd Tanous #include <string_view> 96c038f26SEd Tanous 106c038f26SEd Tanous namespace redfish 116c038f26SEd Tanous { 126c038f26SEd Tanous 136c038f26SEd Tanous namespace messages 146c038f26SEd Tanous { 156c038f26SEd Tanous 166c038f26SEd Tanous void addMessageToErrorJson(nlohmann::json& target, 176c038f26SEd Tanous const nlohmann::json& message) 186c038f26SEd Tanous { 196c038f26SEd Tanous auto& error = target["error"]; 206c038f26SEd Tanous 216c038f26SEd Tanous // If this is the first error message, fill in the information from the 226c038f26SEd Tanous // first error message to the top level struct 236c038f26SEd Tanous if (!error.is_object()) 246c038f26SEd Tanous { 256c038f26SEd Tanous auto messageIdIterator = message.find("MessageId"); 266c038f26SEd Tanous if (messageIdIterator == message.end()) 276c038f26SEd Tanous { 286c038f26SEd Tanous BMCWEB_LOG_CRITICAL( 296c038f26SEd Tanous "Attempt to add error message without MessageId"); 306c038f26SEd Tanous return; 316c038f26SEd Tanous } 326c038f26SEd Tanous 336c038f26SEd Tanous auto messageFieldIterator = message.find("Message"); 346c038f26SEd Tanous if (messageFieldIterator == message.end()) 356c038f26SEd Tanous { 366c038f26SEd Tanous BMCWEB_LOG_CRITICAL("Attempt to add error message without Message"); 376c038f26SEd Tanous return; 386c038f26SEd Tanous } 396c038f26SEd Tanous error["code"] = *messageIdIterator; 406c038f26SEd Tanous error["message"] = *messageFieldIterator; 416c038f26SEd Tanous } 426c038f26SEd Tanous else 436c038f26SEd Tanous { 446c038f26SEd Tanous // More than 1 error occurred, so the message has to be generic 456c038f26SEd Tanous error["code"] = std::string(messageVersionPrefix) + "GeneralError"; 466c038f26SEd Tanous error["message"] = "A general error has occurred. See Resolution for " 476c038f26SEd Tanous "information on how to resolve the error."; 486c038f26SEd Tanous } 496c038f26SEd Tanous 506c038f26SEd Tanous // This check could technically be done in the default construction 516c038f26SEd Tanous // branch above, but because we need the pointer to the extended info field 526c038f26SEd Tanous // anyway, it's more efficient to do it here. 536c038f26SEd Tanous auto& extendedInfo = error[messages::messageAnnotation]; 546c038f26SEd Tanous if (!extendedInfo.is_array()) 556c038f26SEd Tanous { 566c038f26SEd Tanous extendedInfo = nlohmann::json::array(); 576c038f26SEd Tanous } 586c038f26SEd Tanous 596c038f26SEd Tanous extendedInfo.push_back(message); 606c038f26SEd Tanous } 616c038f26SEd Tanous 626c038f26SEd Tanous void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source) 636c038f26SEd Tanous { 64*761cdfa5SEd Tanous nlohmann::json::object_t* sourceObj = 65*761cdfa5SEd Tanous source.get_ptr<nlohmann::json::object_t*>(); 66*761cdfa5SEd Tanous if (sourceObj == nullptr) 676c038f26SEd Tanous { 686c038f26SEd Tanous return; 696c038f26SEd Tanous } 70*761cdfa5SEd Tanous 71*761cdfa5SEd Tanous nlohmann::json::object_t::iterator errorIt = sourceObj->find("error"); 72*761cdfa5SEd Tanous if (errorIt == sourceObj->end()) 736c038f26SEd Tanous { 746c038f26SEd Tanous // caller puts error message in root 756c038f26SEd Tanous messages::addMessageToErrorJson(target, source); 766c038f26SEd Tanous source.clear(); 776c038f26SEd Tanous return; 786c038f26SEd Tanous } 79*761cdfa5SEd Tanous nlohmann::json::object_t* errorObj = 80*761cdfa5SEd Tanous errorIt->second.get_ptr<nlohmann::json::object_t*>(); 81*761cdfa5SEd Tanous if (errorObj == nullptr) 82*761cdfa5SEd Tanous { 83*761cdfa5SEd Tanous return; 84*761cdfa5SEd Tanous } 85*761cdfa5SEd Tanous 86*761cdfa5SEd Tanous nlohmann::json::object_t::iterator extendedInfoIt = 87*761cdfa5SEd Tanous errorObj->find(messages::messageAnnotation); 88*761cdfa5SEd Tanous if (extendedInfoIt == errorObj->end()) 896c038f26SEd Tanous { 906c038f26SEd Tanous return; 916c038f26SEd Tanous } 926c038f26SEd Tanous const nlohmann::json::array_t* extendedInfo = 93*761cdfa5SEd Tanous extendedInfoIt->second.get_ptr<const nlohmann::json::array_t*>(); 946c038f26SEd Tanous if (extendedInfo == nullptr) 956c038f26SEd Tanous { 96*761cdfa5SEd Tanous sourceObj->erase(errorIt); 976c038f26SEd Tanous return; 986c038f26SEd Tanous } 996c038f26SEd Tanous for (const nlohmann::json& message : *extendedInfo) 1006c038f26SEd Tanous { 1016c038f26SEd Tanous addMessageToErrorJson(target, message); 1026c038f26SEd Tanous } 103*761cdfa5SEd Tanous sourceObj->erase(errorIt); 1046c038f26SEd Tanous } 1056c038f26SEd Tanous 1066c038f26SEd Tanous void addMessageToJsonRoot(nlohmann::json& target, const nlohmann::json& message) 1076c038f26SEd Tanous { 1086c038f26SEd Tanous if (!target[messages::messageAnnotation].is_array()) 1096c038f26SEd Tanous { 1106c038f26SEd Tanous // Force object to be an array 1116c038f26SEd Tanous target[messages::messageAnnotation] = nlohmann::json::array(); 1126c038f26SEd Tanous } 1136c038f26SEd Tanous 1146c038f26SEd Tanous target[messages::messageAnnotation].push_back(message); 1156c038f26SEd Tanous } 1166c038f26SEd Tanous 1176c038f26SEd Tanous void addMessageToJson(nlohmann::json& target, const nlohmann::json& message, 1186c038f26SEd Tanous std::string_view fieldPath) 1196c038f26SEd Tanous { 1206c038f26SEd Tanous std::string extendedInfo(fieldPath); 1216c038f26SEd Tanous extendedInfo += messages::messageAnnotation; 1226c038f26SEd Tanous 1236c038f26SEd Tanous nlohmann::json& field = target[extendedInfo]; 1246c038f26SEd Tanous if (!field.is_array()) 1256c038f26SEd Tanous { 1266c038f26SEd Tanous // Force object to be an array 1276c038f26SEd Tanous field = nlohmann::json::array(); 1286c038f26SEd Tanous } 1296c038f26SEd Tanous 1306c038f26SEd Tanous // Object exists and it is an array so we can just push in the message 1316c038f26SEd Tanous field.push_back(message); 1326c038f26SEd Tanous } 1336c038f26SEd Tanous 1346c038f26SEd Tanous } // namespace messages 1356c038f26SEd Tanous } // namespace redfish 136