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