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