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