xref: /openbmc/bmcweb/features/redfish/src/error_message_utils.cpp (revision 761cdfa58b98cf17568e7dd4349330f1c523b144)
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