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