xref: /openbmc/bmcweb/redfish-core/src/error_message_utils.cpp (revision 6c038f260633414c52ac34ac44d0d3ab23c3d9a5)
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     if (!source.is_object())
65     {
66         return;
67     }
68     auto errorIt = source.find("error");
69     if (errorIt == source.end())
70     {
71         // caller puts error message in root
72         messages::addMessageToErrorJson(target, source);
73         source.clear();
74         return;
75     }
76     auto extendedInfoIt = errorIt->find(messages::messageAnnotation);
77     if (extendedInfoIt == errorIt->end())
78     {
79         return;
80     }
81     const nlohmann::json::array_t* extendedInfo =
82         (*extendedInfoIt).get_ptr<const nlohmann::json::array_t*>();
83     if (extendedInfo == nullptr)
84     {
85         source.erase(errorIt);
86         return;
87     }
88     for (const nlohmann::json& message : *extendedInfo)
89     {
90         addMessageToErrorJson(target, message);
91     }
92     source.erase(errorIt);
93 }
94 
addMessageToJsonRoot(nlohmann::json & target,const nlohmann::json & message)95 void addMessageToJsonRoot(nlohmann::json& target, const nlohmann::json& message)
96 {
97     if (!target[messages::messageAnnotation].is_array())
98     {
99         // Force object to be an array
100         target[messages::messageAnnotation] = nlohmann::json::array();
101     }
102 
103     target[messages::messageAnnotation].push_back(message);
104 }
105 
addMessageToJson(nlohmann::json & target,const nlohmann::json & message,std::string_view fieldPath)106 void addMessageToJson(nlohmann::json& target, const nlohmann::json& message,
107                       std::string_view fieldPath)
108 {
109     std::string extendedInfo(fieldPath);
110     extendedInfo += messages::messageAnnotation;
111 
112     nlohmann::json& field = target[extendedInfo];
113     if (!field.is_array())
114     {
115         // Force object to be an array
116         field = nlohmann::json::array();
117     }
118 
119     // Object exists and it is an array so we can just push in the message
120     field.push_back(message);
121 }
122 
123 } // namespace messages
124 } // namespace redfish
125