xref: /openbmc/bmcweb/redfish-core/src/error_message_utils.cpp (revision 761cdfa58b98cf17568e7dd4349330f1c523b144)
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 
addMessageToErrorJson(nlohmann::json & target,const nlohmann::json & message)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 
moveErrorsToErrorJson(nlohmann::json & target,nlohmann::json & source)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 
addMessageToJsonRoot(nlohmann::json & target,const nlohmann::json & message)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 
addMessageToJson(nlohmann::json & target,const nlohmann::json & message,std::string_view fieldPath)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