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 
27 #include <array>
28 
29 namespace redfish
30 {
31 
32 inline void handleMessageRegistryFileCollectionGet(
33     crow::App& app, const crow::Request& req,
34     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
35 {
36     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
37     {
38         return;
39     }
40     // Collections don't include the static data added by SubRoute
41     // because it has a duplicate entry for members
42 
43     asyncResp->res.jsonValue["@odata.type"] =
44         "#MessageRegistryFileCollection.MessageRegistryFileCollection";
45     asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Registries";
46     asyncResp->res.jsonValue["Name"] = "MessageRegistryFile Collection";
47     asyncResp->res.jsonValue["Description"] =
48         "Collection of MessageRegistryFiles";
49     asyncResp->res.jsonValue["Members@odata.count"] = 4;
50 
51     nlohmann::json& members = asyncResp->res.jsonValue["Members"];
52     for (const char* memberName :
53          std::to_array({"Base", "TaskEvent", "ResourceEvent", "OpenBMC"}))
54     {
55         nlohmann::json::object_t member;
56         member["@odata.id"] = crow::utility::urlFromPieces(
57             "redfish", "v1", "Registries", memberName);
58         members.emplace_back(std::move(member));
59     }
60 }
61 
62 inline void requestRoutesMessageRegistryFileCollection(App& app)
63 {
64     /**
65      * Functions triggers appropriate requests on DBus
66      */
67     BMCWEB_ROUTE(app, "/redfish/v1/Registries/")
68         .privileges(redfish::privileges::getMessageRegistryFileCollection)
69         .methods(boost::beast::http::verb::get)(std::bind_front(
70             handleMessageRegistryFileCollectionGet, std::ref(app)));
71 }
72 
73 inline void handleMessageRoutesMessageRegistryFileGet(
74     crow::App& app, const crow::Request& req,
75     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
76     const std::string& registry)
77 {
78     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
79     {
80         return;
81     }
82     const registries::Header* header = nullptr;
83     std::string dmtf = "DMTF ";
84     const char* url = nullptr;
85 
86     if (registry == "Base")
87     {
88         header = &registries::base::header;
89         url = registries::base::url;
90     }
91     else if (registry == "TaskEvent")
92     {
93         header = &registries::task_event::header;
94         url = registries::task_event::url;
95     }
96     else if (registry == "OpenBMC")
97     {
98         header = &registries::openbmc::header;
99         dmtf.clear();
100     }
101     else if (registry == "ResourceEvent")
102     {
103         header = &registries::resource_event::header;
104         url = registries::resource_event::url;
105     }
106     else
107     {
108         messages::resourceNotFound(asyncResp->res, "MessageRegistryFile",
109                                    registry);
110         return;
111     }
112 
113     asyncResp->res.jsonValue["@odata.id"] =
114         "/redfish/v1/Registries/" + registry;
115     asyncResp->res.jsonValue["@odata.type"] =
116         "#MessageRegistryFile.v1_1_0.MessageRegistryFile";
117     asyncResp->res.jsonValue["Name"] = registry + " Message Registry File";
118     asyncResp->res.jsonValue["Description"] =
119         dmtf + registry + " Message Registry File Location";
120     asyncResp->res.jsonValue["Id"] = header->registryPrefix;
121     asyncResp->res.jsonValue["Registry"] = header->id;
122     nlohmann::json::array_t languages;
123     languages.push_back("en");
124     asyncResp->res.jsonValue["Languages@odata.count"] = languages.size();
125     asyncResp->res.jsonValue["Languages"] = std::move(languages);
126     nlohmann::json::array_t locationMembers;
127     nlohmann::json::object_t location;
128     location["Language"] = "en";
129     location["Uri"] = "/redfish/v1/Registries/" + registry + "/" + registry;
130 
131     if (url != nullptr)
132     {
133         location["PublicationUri"] = url;
134     }
135     locationMembers.emplace_back(std::move(location));
136     asyncResp->res.jsonValue["Location@odata.count"] = locationMembers.size();
137     asyncResp->res.jsonValue["Location"] = std::move(locationMembers);
138 }
139 
140 inline void requestRoutesMessageRegistryFile(App& app)
141 {
142     BMCWEB_ROUTE(app, "/redfish/v1/Registries/<str>/")
143         .privileges(redfish::privileges::getMessageRegistryFile)
144         .methods(boost::beast::http::verb::get)(std::bind_front(
145             handleMessageRoutesMessageRegistryFileGet, std::ref(app)));
146 }
147 
148 inline void handleMessageRegistryGet(
149     crow::App& app, const crow::Request& req,
150     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
151     const std::string& registry, const std::string& registryMatch)
152 
153 {
154     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
155     {
156         return;
157     }
158     const registries::Header* header = nullptr;
159     std::vector<const registries::MessageEntry*> registryEntries;
160     if (registry == "Base")
161     {
162         header = &registries::base::header;
163         for (const registries::MessageEntry& entry : registries::base::registry)
164         {
165             registryEntries.emplace_back(&entry);
166         }
167     }
168     else if (registry == "TaskEvent")
169     {
170         header = &registries::task_event::header;
171         for (const registries::MessageEntry& entry :
172              registries::task_event::registry)
173         {
174             registryEntries.emplace_back(&entry);
175         }
176     }
177     else if (registry == "OpenBMC")
178     {
179         header = &registries::openbmc::header;
180         for (const registries::MessageEntry& entry :
181              registries::openbmc::registry)
182         {
183             registryEntries.emplace_back(&entry);
184         }
185     }
186     else if (registry == "ResourceEvent")
187     {
188         header = &registries::resource_event::header;
189         for (const registries::MessageEntry& entry :
190              registries::resource_event::registry)
191         {
192             registryEntries.emplace_back(&entry);
193         }
194     }
195     else
196     {
197         messages::resourceNotFound(asyncResp->res, "MessageRegistryFile",
198                                    registry);
199         return;
200     }
201 
202     if (registry != registryMatch)
203     {
204         messages::resourceNotFound(asyncResp->res, header->type, registryMatch);
205         return;
206     }
207 
208     asyncResp->res.jsonValue["@Redfish.Copyright"] = header->copyright;
209     asyncResp->res.jsonValue["@odata.type"] = header->type;
210     asyncResp->res.jsonValue["Id"] = header->id;
211     asyncResp->res.jsonValue["Name"] = header->name;
212     asyncResp->res.jsonValue["Language"] = header->language;
213     asyncResp->res.jsonValue["Description"] = header->description;
214     asyncResp->res.jsonValue["RegistryPrefix"] = header->registryPrefix;
215     asyncResp->res.jsonValue["RegistryVersion"] = header->registryVersion;
216     asyncResp->res.jsonValue["OwningEntity"] = header->owningEntity;
217 
218     nlohmann::json& messageObj = asyncResp->res.jsonValue["Messages"];
219 
220     // Go through the Message Registry and populate each Message
221     for (const registries::MessageEntry* message : registryEntries)
222     {
223         nlohmann::json& obj = messageObj[message->first];
224         obj["Description"] = message->second.description;
225         obj["Message"] = message->second.message;
226         obj["Severity"] = message->second.messageSeverity;
227         obj["MessageSeverity"] = message->second.messageSeverity;
228         obj["NumberOfArgs"] = message->second.numberOfArgs;
229         obj["Resolution"] = message->second.resolution;
230         if (message->second.numberOfArgs > 0)
231         {
232             nlohmann::json& messageParamArray = obj["ParamTypes"];
233             messageParamArray = nlohmann::json::array();
234             for (const char* str : message->second.paramTypes)
235             {
236                 if (str == nullptr)
237                 {
238                     break;
239                 }
240                 messageParamArray.push_back(str);
241             }
242         }
243     }
244 }
245 
246 inline void requestRoutesMessageRegistry(App& app)
247 {
248     BMCWEB_ROUTE(app, "/redfish/v1/Registries/<str>/<str>/")
249         .privileges(redfish::privileges::getMessageRegistryFile)
250         .methods(boost::beast::http::verb::get)(
251             std::bind_front(handleMessageRegistryGet, std::ref(app)));
252 }
253 } // namespace redfish
254