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