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