1*6c038f26SEd Tanous #include "error_message_utils.hpp" 2*6c038f26SEd Tanous 3*6c038f26SEd Tanous #include "logging.hpp" 4*6c038f26SEd Tanous 5*6c038f26SEd Tanous #include <nlohmann/json.hpp> 6*6c038f26SEd Tanous 7*6c038f26SEd Tanous #include <string> 8*6c038f26SEd Tanous #include <string_view> 9*6c038f26SEd Tanous 10*6c038f26SEd Tanous namespace redfish 11*6c038f26SEd Tanous { 12*6c038f26SEd Tanous 13*6c038f26SEd Tanous namespace messages 14*6c038f26SEd Tanous { 15*6c038f26SEd Tanous 16*6c038f26SEd Tanous void addMessageToErrorJson(nlohmann::json& target, 17*6c038f26SEd Tanous const nlohmann::json& message) 18*6c038f26SEd Tanous { 19*6c038f26SEd Tanous auto& error = target["error"]; 20*6c038f26SEd Tanous 21*6c038f26SEd Tanous // If this is the first error message, fill in the information from the 22*6c038f26SEd Tanous // first error message to the top level struct 23*6c038f26SEd Tanous if (!error.is_object()) 24*6c038f26SEd Tanous { 25*6c038f26SEd Tanous auto messageIdIterator = message.find("MessageId"); 26*6c038f26SEd Tanous if (messageIdIterator == message.end()) 27*6c038f26SEd Tanous { 28*6c038f26SEd Tanous BMCWEB_LOG_CRITICAL( 29*6c038f26SEd Tanous "Attempt to add error message without MessageId"); 30*6c038f26SEd Tanous return; 31*6c038f26SEd Tanous } 32*6c038f26SEd Tanous 33*6c038f26SEd Tanous auto messageFieldIterator = message.find("Message"); 34*6c038f26SEd Tanous if (messageFieldIterator == message.end()) 35*6c038f26SEd Tanous { 36*6c038f26SEd Tanous BMCWEB_LOG_CRITICAL("Attempt to add error message without Message"); 37*6c038f26SEd Tanous return; 38*6c038f26SEd Tanous } 39*6c038f26SEd Tanous error["code"] = *messageIdIterator; 40*6c038f26SEd Tanous error["message"] = *messageFieldIterator; 41*6c038f26SEd Tanous } 42*6c038f26SEd Tanous else 43*6c038f26SEd Tanous { 44*6c038f26SEd Tanous // More than 1 error occurred, so the message has to be generic 45*6c038f26SEd Tanous error["code"] = std::string(messageVersionPrefix) + "GeneralError"; 46*6c038f26SEd Tanous error["message"] = "A general error has occurred. See Resolution for " 47*6c038f26SEd Tanous "information on how to resolve the error."; 48*6c038f26SEd Tanous } 49*6c038f26SEd Tanous 50*6c038f26SEd Tanous // This check could technically be done in the default construction 51*6c038f26SEd Tanous // branch above, but because we need the pointer to the extended info field 52*6c038f26SEd Tanous // anyway, it's more efficient to do it here. 53*6c038f26SEd Tanous auto& extendedInfo = error[messages::messageAnnotation]; 54*6c038f26SEd Tanous if (!extendedInfo.is_array()) 55*6c038f26SEd Tanous { 56*6c038f26SEd Tanous extendedInfo = nlohmann::json::array(); 57*6c038f26SEd Tanous } 58*6c038f26SEd Tanous 59*6c038f26SEd Tanous extendedInfo.push_back(message); 60*6c038f26SEd Tanous } 61*6c038f26SEd Tanous 62*6c038f26SEd Tanous void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source) 63*6c038f26SEd Tanous { 64*6c038f26SEd Tanous if (!source.is_object()) 65*6c038f26SEd Tanous { 66*6c038f26SEd Tanous return; 67*6c038f26SEd Tanous } 68*6c038f26SEd Tanous auto errorIt = source.find("error"); 69*6c038f26SEd Tanous if (errorIt == source.end()) 70*6c038f26SEd Tanous { 71*6c038f26SEd Tanous // caller puts error message in root 72*6c038f26SEd Tanous messages::addMessageToErrorJson(target, source); 73*6c038f26SEd Tanous source.clear(); 74*6c038f26SEd Tanous return; 75*6c038f26SEd Tanous } 76*6c038f26SEd Tanous auto extendedInfoIt = errorIt->find(messages::messageAnnotation); 77*6c038f26SEd Tanous if (extendedInfoIt == errorIt->end()) 78*6c038f26SEd Tanous { 79*6c038f26SEd Tanous return; 80*6c038f26SEd Tanous } 81*6c038f26SEd Tanous const nlohmann::json::array_t* extendedInfo = 82*6c038f26SEd Tanous (*extendedInfoIt).get_ptr<const nlohmann::json::array_t*>(); 83*6c038f26SEd Tanous if (extendedInfo == nullptr) 84*6c038f26SEd Tanous { 85*6c038f26SEd Tanous source.erase(errorIt); 86*6c038f26SEd Tanous return; 87*6c038f26SEd Tanous } 88*6c038f26SEd Tanous for (const nlohmann::json& message : *extendedInfo) 89*6c038f26SEd Tanous { 90*6c038f26SEd Tanous addMessageToErrorJson(target, message); 91*6c038f26SEd Tanous } 92*6c038f26SEd Tanous source.erase(errorIt); 93*6c038f26SEd Tanous } 94*6c038f26SEd Tanous 95*6c038f26SEd Tanous void addMessageToJsonRoot(nlohmann::json& target, const nlohmann::json& message) 96*6c038f26SEd Tanous { 97*6c038f26SEd Tanous if (!target[messages::messageAnnotation].is_array()) 98*6c038f26SEd Tanous { 99*6c038f26SEd Tanous // Force object to be an array 100*6c038f26SEd Tanous target[messages::messageAnnotation] = nlohmann::json::array(); 101*6c038f26SEd Tanous } 102*6c038f26SEd Tanous 103*6c038f26SEd Tanous target[messages::messageAnnotation].push_back(message); 104*6c038f26SEd Tanous } 105*6c038f26SEd Tanous 106*6c038f26SEd Tanous void addMessageToJson(nlohmann::json& target, const nlohmann::json& message, 107*6c038f26SEd Tanous std::string_view fieldPath) 108*6c038f26SEd Tanous { 109*6c038f26SEd Tanous std::string extendedInfo(fieldPath); 110*6c038f26SEd Tanous extendedInfo += messages::messageAnnotation; 111*6c038f26SEd Tanous 112*6c038f26SEd Tanous nlohmann::json& field = target[extendedInfo]; 113*6c038f26SEd Tanous if (!field.is_array()) 114*6c038f26SEd Tanous { 115*6c038f26SEd Tanous // Force object to be an array 116*6c038f26SEd Tanous field = nlohmann::json::array(); 117*6c038f26SEd Tanous } 118*6c038f26SEd Tanous 119*6c038f26SEd Tanous // Object exists and it is an array so we can just push in the message 120*6c038f26SEd Tanous field.push_back(message); 121*6c038f26SEd Tanous } 122*6c038f26SEd Tanous 123*6c038f26SEd Tanous } // namespace messages 124*6c038f26SEd Tanous } // namespace redfish 125