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