1 /*
2 // Copyright (c) 2019 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 #pragma once
17 
18 #include "app.hpp"
19 #include "query.hpp"
20 #include "registries.hpp"
21 #include "registries/base_message_registry.hpp"
22 #include "registries/openbmc_message_registry.hpp"
23 #include "registries/privilege_registry.hpp"
24 #include "registries/resource_event_message_registry.hpp"
25 #include "registries/task_event_message_registry.hpp"
26 #include "registries/telemetry_message_registry.hpp"
27 
28 #include <boost/url/format.hpp>
29 
30 #include <array>
31 
32 namespace redfish
33 {
34 
35 inline void handleMessageRegistryFileCollectionGet(
36     crow::App& app, const crow::Request& req,
37     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
38 {
39     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
40     {
41         return;
42     }
43     // Collections don't include the static data added by SubRoute
44     // because it has a duplicate entry for members
45 
46     asyncResp->res.jsonValue["@odata.type"] =
47         "#MessageRegistryFileCollection.MessageRegistryFileCollection";
48     asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Registries";
49     asyncResp->res.jsonValue["Name"] = "MessageRegistryFile Collection";
50     asyncResp->res.jsonValue["Description"] =
51         "Collection of MessageRegistryFiles";
52     asyncResp->res.jsonValue["Members@odata.count"] = 5;
53 
54     nlohmann::json& members = asyncResp->res.jsonValue["Members"];
55     for (const char* memberName : std::to_array(
56              {"Base", "TaskEvent", "ResourceEvent", "OpenBMC", "Telemetry"}))
57     {
58         nlohmann::json::object_t member;
59         member["@odata.id"] = boost::urls::format("/redfish/v1/Registries/{}",
60                                                   memberName);
61         members.emplace_back(std::move(member));
62     }
63 }
64 
65 inline void requestRoutesMessageRegistryFileCollection(App& app)
66 {
67     /**
68      * Functions triggers appropriate requests on DBus
69      */
70     BMCWEB_ROUTE(app, "/redfish/v1/Registries/")
71         .privileges(redfish::privileges::getMessageRegistryFileCollection)
72         .methods(boost::beast::http::verb::get)(std::bind_front(
73             handleMessageRegistryFileCollectionGet, std::ref(app)));
74 }
75 
76 inline void handleMessageRoutesMessageRegistryFileGet(
77     crow::App& app, const crow::Request& req,
78     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
79     const std::string& registry)
80 {
81     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
82     {
83         return;
84     }
85     const registries::Header* header = nullptr;
86     std::string dmtf = "DMTF ";
87     const char* url = nullptr;
88 
89     if (registry == "Base")
90     {
91         header = &registries::base::header;
92         url = registries::base::url;
93     }
94     else if (registry == "TaskEvent")
95     {
96         header = &registries::task_event::header;
97         url = registries::task_event::url;
98     }
99     else if (registry == "OpenBMC")
100     {
101         header = &registries::openbmc::header;
102         dmtf.clear();
103     }
104     else if (registry == "ResourceEvent")
105     {
106         header = &registries::resource_event::header;
107         url = registries::resource_event::url;
108     }
109     else if (registry == "Telemetry")
110     {
111         header = &registries::telemetry::header;
112         url = registries::telemetry::url;
113     }
114     else
115     {
116         messages::resourceNotFound(asyncResp->res, "MessageRegistryFile",
117                                    registry);
118         return;
119     }
120 
121     asyncResp->res.jsonValue["@odata.id"] =
122         boost::urls::format("/redfish/v1/Registries/{}", registry);
123     asyncResp->res.jsonValue["@odata.type"] =
124         "#MessageRegistryFile.v1_1_0.MessageRegistryFile";
125     asyncResp->res.jsonValue["Name"] = registry + " Message Registry File";
126     asyncResp->res.jsonValue["Description"] = dmtf + registry +
127                                               " Message Registry File Location";
128     asyncResp->res.jsonValue["Id"] = header->registryPrefix;
129     asyncResp->res.jsonValue["Registry"] = header->id;
130     nlohmann::json::array_t languages;
131     languages.emplace_back(header->language);
132     asyncResp->res.jsonValue["Languages@odata.count"] = languages.size();
133     asyncResp->res.jsonValue["Languages"] = std::move(languages);
134     nlohmann::json::array_t locationMembers;
135     nlohmann::json::object_t location;
136     location["Language"] = header->language;
137     location["Uri"] = "/redfish/v1/Registries/" + registry + "/" + registry;
138 
139     if (url != nullptr)
140     {
141         location["PublicationUri"] = url;
142     }
143     locationMembers.emplace_back(std::move(location));
144     asyncResp->res.jsonValue["Location@odata.count"] = locationMembers.size();
145     asyncResp->res.jsonValue["Location"] = std::move(locationMembers);
146 }
147 
148 inline void requestRoutesMessageRegistryFile(App& app)
149 {
150     BMCWEB_ROUTE(app, "/redfish/v1/Registries/<str>/")
151         .privileges(redfish::privileges::getMessageRegistryFile)
152         .methods(boost::beast::http::verb::get)(std::bind_front(
153             handleMessageRoutesMessageRegistryFileGet, std::ref(app)));
154 }
155 
156 inline void handleMessageRegistryGet(
157     crow::App& app, const crow::Request& req,
158     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
159     const std::string& registry, const std::string& registryMatch)
160 
161 {
162     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
163     {
164         return;
165     }
166     const registries::Header* header = nullptr;
167     std::vector<const registries::MessageEntry*> registryEntries;
168     if (registry == "Base")
169     {
170         header = &registries::base::header;
171         for (const registries::MessageEntry& entry : registries::base::registry)
172         {
173             registryEntries.emplace_back(&entry);
174         }
175     }
176     else if (registry == "TaskEvent")
177     {
178         header = &registries::task_event::header;
179         for (const registries::MessageEntry& entry :
180              registries::task_event::registry)
181         {
182             registryEntries.emplace_back(&entry);
183         }
184     }
185     else if (registry == "OpenBMC")
186     {
187         header = &registries::openbmc::header;
188         for (const registries::MessageEntry& entry :
189              registries::openbmc::registry)
190         {
191             registryEntries.emplace_back(&entry);
192         }
193     }
194     else if (registry == "ResourceEvent")
195     {
196         header = &registries::resource_event::header;
197         for (const registries::MessageEntry& entry :
198              registries::resource_event::registry)
199         {
200             registryEntries.emplace_back(&entry);
201         }
202     }
203     else if (registry == "Telemetry")
204     {
205         header = &registries::telemetry::header;
206         for (const registries::MessageEntry& entry :
207              registries::telemetry::registry)
208         {
209             registryEntries.emplace_back(&entry);
210         }
211     }
212     else
213     {
214         messages::resourceNotFound(asyncResp->res, "MessageRegistryFile",
215                                    registry);
216         return;
217     }
218 
219     if (registry != registryMatch)
220     {
221         messages::resourceNotFound(asyncResp->res, header->type, registryMatch);
222         return;
223     }
224 
225     asyncResp->res.jsonValue["@Redfish.Copyright"] = header->copyright;
226     asyncResp->res.jsonValue["@odata.type"] = header->type;
227     asyncResp->res.jsonValue["Id"] = header->id;
228     asyncResp->res.jsonValue["Name"] = header->name;
229     asyncResp->res.jsonValue["Language"] = header->language;
230     asyncResp->res.jsonValue["Description"] = header->description;
231     asyncResp->res.jsonValue["RegistryPrefix"] = header->registryPrefix;
232     asyncResp->res.jsonValue["RegistryVersion"] = header->registryVersion;
233     asyncResp->res.jsonValue["OwningEntity"] = header->owningEntity;
234 
235     nlohmann::json& messageObj = asyncResp->res.jsonValue["Messages"];
236 
237     // Go through the Message Registry and populate each Message
238     for (const registries::MessageEntry* message : registryEntries)
239     {
240         nlohmann::json& obj = messageObj[message->first];
241         obj["Description"] = message->second.description;
242         obj["Message"] = message->second.message;
243         obj["Severity"] = message->second.messageSeverity;
244         obj["MessageSeverity"] = message->second.messageSeverity;
245         obj["NumberOfArgs"] = message->second.numberOfArgs;
246         obj["Resolution"] = message->second.resolution;
247         if (message->second.numberOfArgs > 0)
248         {
249             nlohmann::json& messageParamArray = obj["ParamTypes"];
250             messageParamArray = nlohmann::json::array();
251             for (const char* str : message->second.paramTypes)
252             {
253                 if (str == nullptr)
254                 {
255                     break;
256                 }
257                 messageParamArray.push_back(str);
258             }
259         }
260     }
261 }
262 
263 inline void requestRoutesMessageRegistry(App& app)
264 {
265     BMCWEB_ROUTE(app, "/redfish/v1/Registries/<str>/<str>/")
266         .privileges(redfish::privileges::getMessageRegistryFile)
267         .methods(boost::beast::http::verb::get)(
268             std::bind_front(handleMessageRegistryGet, std::ref(app)));
269 }
270 } // namespace redfish
271