xref: /openbmc/bmcweb/redfish-core/lib/message_registries.hpp (revision 4a102cd48c588d32c0a4d6610b4a9ed616f255f3)
1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3 // SPDX-FileCopyrightText: Copyright 2019 Intel Corporation
4 #pragma once
5 
6 #include "app.hpp"
7 #include "async_resp.hpp"
8 #include "error_messages.hpp"
9 #include "http_request.hpp"
10 #include "query.hpp"
11 #include "registries.hpp"
12 #include "registries/privilege_registry.hpp"
13 
14 #include <boost/beast/http/verb.hpp>
15 #include <boost/url/format.hpp>
16 
17 #include <format>
18 #include <functional>
19 #include <memory>
20 #include <optional>
21 #include <ranges>
22 #include <utility>
23 
24 namespace redfish
25 {
26 
handleMessageRegistryFileCollectionGet(crow::App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)27 inline void handleMessageRegistryFileCollectionGet(
28     crow::App& app, const crow::Request& req,
29     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
30 {
31     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
32     {
33         return;
34     }
35     // Collections don't include the static data added by SubRoute
36     // because it has a duplicate entry for members
37 
38     asyncResp->res.jsonValue["@odata.type"] =
39         "#MessageRegistryFileCollection.MessageRegistryFileCollection";
40     asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Registries";
41     asyncResp->res.jsonValue["Name"] = "MessageRegistryFile Collection";
42     asyncResp->res.jsonValue["Description"] =
43         "Collection of MessageRegistryFiles";
44 
45     nlohmann::json& members = asyncResp->res.jsonValue["Members"];
46 
47     for (const auto& memberName : std::views::keys(registries::allRegistries()))
48     {
49         nlohmann::json::object_t member;
50         member["@odata.id"] =
51             boost::urls::format("/redfish/v1/Registries/{}", memberName);
52         members.emplace_back(std::move(member));
53     }
54     asyncResp->res.jsonValue["Members@odata.count"] = members.size();
55 }
56 
requestRoutesMessageRegistryFileCollection(App & app)57 inline void requestRoutesMessageRegistryFileCollection(App& app)
58 {
59     /**
60      * Functions triggers appropriate requests on DBus
61      */
62     BMCWEB_ROUTE(app, "/redfish/v1/Registries/")
63         .privileges(redfish::privileges::getMessageRegistryFileCollection)
64         .methods(boost::beast::http::verb::get)(std::bind_front(
65             handleMessageRegistryFileCollectionGet, std::ref(app)));
66 }
67 
handleMessageRoutesMessageRegistryFileGet(crow::App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & registry)68 inline void handleMessageRoutesMessageRegistryFileGet(
69     crow::App& app, const crow::Request& req,
70     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
71     const std::string& registry)
72 {
73     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
74     {
75         return;
76     }
77     std::string dmtf = "DMTF ";
78     std::optional<registries::RegistryEntryRef> registryEntry =
79         registries::getRegistryFromPrefix(registry);
80 
81     if (!registryEntry)
82     {
83         messages::resourceNotFound(asyncResp->res, "MessageRegistryFile",
84                                    registry);
85         return;
86     }
87     if (registry == "OpenBMC")
88     {
89         dmtf.clear();
90     }
91     const registries::Header& header = registryEntry->get().header;
92     const char* url = registryEntry->get().url;
93 
94     asyncResp->res.jsonValue["@odata.id"] =
95         boost::urls::format("/redfish/v1/Registries/{}", registry);
96     asyncResp->res.jsonValue["@odata.type"] =
97         "#MessageRegistryFile.v1_1_0.MessageRegistryFile";
98     asyncResp->res.jsonValue["Name"] = registry + " Message Registry File";
99     asyncResp->res.jsonValue["Description"] =
100         dmtf + registry + " Message Registry File Location";
101     asyncResp->res.jsonValue["Id"] = header.registryPrefix;
102     asyncResp->res.jsonValue["Registry"] =
103         std::format("{}.{}.{}", header.registryPrefix, header.versionMajor,
104                     header.versionMinor);
105     nlohmann::json::array_t languages;
106     languages.emplace_back(header.language);
107     asyncResp->res.jsonValue["Languages@odata.count"] = languages.size();
108     asyncResp->res.jsonValue["Languages"] = std::move(languages);
109     nlohmann::json::array_t locationMembers;
110     nlohmann::json::object_t location;
111     location["Language"] = header.language;
112     location["Uri"] = "/redfish/v1/Registries/" + registry + "/" + registry;
113 
114     if (url != nullptr)
115     {
116         location["PublicationUri"] = url;
117     }
118     locationMembers.emplace_back(std::move(location));
119     asyncResp->res.jsonValue["Location@odata.count"] = locationMembers.size();
120     asyncResp->res.jsonValue["Location"] = std::move(locationMembers);
121 }
122 
requestRoutesMessageRegistryFile(App & app)123 inline void requestRoutesMessageRegistryFile(App& app)
124 {
125     BMCWEB_ROUTE(app, "/redfish/v1/Registries/<str>/")
126         .privileges(redfish::privileges::getMessageRegistryFile)
127         .methods(boost::beast::http::verb::get)(std::bind_front(
128             handleMessageRoutesMessageRegistryFileGet, std::ref(app)));
129 }
130 
handleMessageRegistryGet(crow::App & app,const crow::Request & req,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & registry,const std::string & registryMatch)131 inline void handleMessageRegistryGet(
132     crow::App& app, const crow::Request& req,
133     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
134     const std::string& registry, const std::string& registryMatch)
135 
136 {
137     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
138     {
139         return;
140     }
141 
142     std::optional<registries::RegistryEntryRef> registryEntry =
143         registries::getRegistryFromPrefix(registry);
144     if (!registryEntry)
145     {
146         messages::resourceNotFound(asyncResp->res, "MessageRegistryFile",
147                                    registry);
148         return;
149     }
150 
151     const registries::Header& header = registryEntry->get().header;
152     if (registry != registryMatch)
153     {
154         messages::resourceNotFound(asyncResp->res, header.type, registryMatch);
155         return;
156     }
157 
158     asyncResp->res.jsonValue["@Redfish.Copyright"] = header.copyright;
159     asyncResp->res.jsonValue["@odata.type"] = header.type;
160     asyncResp->res.jsonValue["Id"] =
161         std::format("{}.{}.{}.{}", header.registryPrefix, header.versionMajor,
162                     header.versionMinor, header.versionPatch);
163     asyncResp->res.jsonValue["Name"] = header.name;
164     asyncResp->res.jsonValue["Language"] = header.language;
165     asyncResp->res.jsonValue["Description"] = header.description;
166     asyncResp->res.jsonValue["RegistryPrefix"] = header.registryPrefix;
167     asyncResp->res.jsonValue["RegistryVersion"] =
168         std::format("{}.{}.{}", header.versionMajor, header.versionMinor,
169                     header.versionPatch);
170     asyncResp->res.jsonValue["OwningEntity"] = header.owningEntity;
171 
172     nlohmann::json& messageObj = asyncResp->res.jsonValue["Messages"];
173 
174     // Go through the Message Registry and populate each Message
175     const registries::MessageEntries registryEntries =
176         registries::getRegistryMessagesFromPrefix(registry);
177 
178     for (const registries::MessageEntry& message : registryEntries)
179     {
180         nlohmann::json& obj = messageObj[message.first];
181         obj["Description"] = message.second.description;
182         obj["Message"] = message.second.message;
183         obj["Severity"] = message.second.messageSeverity;
184         obj["MessageSeverity"] = message.second.messageSeverity;
185         obj["NumberOfArgs"] = message.second.numberOfArgs;
186         obj["Resolution"] = message.second.resolution;
187         if (message.second.numberOfArgs > 0)
188         {
189             nlohmann::json& messageParamArray = obj["ParamTypes"];
190             messageParamArray = nlohmann::json::array();
191             for (const char* str : message.second.paramTypes)
192             {
193                 if (str == nullptr)
194                 {
195                     break;
196                 }
197                 messageParamArray.push_back(str);
198             }
199         }
200     }
201 }
202 
requestRoutesMessageRegistry(App & app)203 inline void requestRoutesMessageRegistry(App& app)
204 {
205     BMCWEB_ROUTE(app, "/redfish/v1/Registries/<str>/<str>/")
206         .privileges(redfish::privileges::getMessageRegistryFile)
207         .methods(boost::beast::http::verb::get)(
208             std::bind_front(handleMessageRegistryGet, std::ref(app)));
209 }
210 } // namespace redfish
211