xref: /openbmc/bmcweb/features/redfish/lib/redfish_v1.hpp (revision 3544d2a719c8bb7b07f9a39f61a3770ec84b909f)
14c25d66eSEd Tanous #pragma once
24c25d66eSEd Tanous 
33ccb3adbSEd Tanous #include "app.hpp"
481d523a7SEd Tanous #include "error_messages.hpp"
53ccb3adbSEd Tanous #include "http_request.hpp"
63ccb3adbSEd Tanous #include "http_response.hpp"
73ccb3adbSEd Tanous #include "query.hpp"
83ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
93ccb3adbSEd Tanous #include "schemas.hpp"
1081d523a7SEd Tanous #include "utility.hpp"
1181d523a7SEd Tanous 
12ef4c65b7SEd Tanous #include <boost/url/format.hpp>
13ef4c65b7SEd Tanous 
14*3544d2a7SEd Tanous #include <ranges>
154c25d66eSEd Tanous #include <string>
164c25d66eSEd Tanous 
174c25d66eSEd Tanous namespace redfish
184c25d66eSEd Tanous {
194c25d66eSEd Tanous 
20d3355c5cSEd Tanous inline void redfishGet(App& app, const crow::Request& req,
21d3355c5cSEd Tanous                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
224c25d66eSEd Tanous {
233ba00073SCarson Labrado     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
241e925c84SEd Tanous     {
251e925c84SEd Tanous         return;
261e925c84SEd Tanous     }
271476687dSEd Tanous     asyncResp->res.jsonValue["v1"] = "/redfish/v1/";
28d3355c5cSEd Tanous }
29d3355c5cSEd Tanous 
308c623a96SEd Tanous inline void redfish404(App& app, const crow::Request& req,
318c623a96SEd Tanous                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
328c623a96SEd Tanous                        const std::string& path)
338c623a96SEd Tanous {
348c623a96SEd Tanous     asyncResp->res.addHeader(boost::beast::http::field::allow, "");
358c623a96SEd Tanous 
368c623a96SEd Tanous     // If we fall to this route, we didn't have a more specific route, so return
378c623a96SEd Tanous     // 404
38686b7093SNan Zhou     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
398c623a96SEd Tanous     {
408c623a96SEd Tanous         return;
418c623a96SEd Tanous     }
428c623a96SEd Tanous 
4362598e31SEd Tanous     BMCWEB_LOG_WARNING("404 on path {}", path);
448c623a96SEd Tanous 
4539662a3bSEd Tanous     std::string name = req.url().segments().back();
468c623a96SEd Tanous     // Note, if we hit the wildcard route, we don't know the "type" the user was
478c623a96SEd Tanous     // actually requesting, but giving them a return with an empty string is
488c623a96SEd Tanous     // still better than nothing.
49079360aeSEd Tanous     messages::resourceNotFound(asyncResp->res, "", name);
508c623a96SEd Tanous }
518c623a96SEd Tanous 
5244c70412SEd Tanous inline void redfish405(App& app, const crow::Request& req,
5344c70412SEd Tanous                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
5444c70412SEd Tanous                        const std::string& path)
5544c70412SEd Tanous {
5644c70412SEd Tanous     // If we fall to this route, we didn't have a more specific route, so return
5744c70412SEd Tanous     // 405
5844c70412SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
5944c70412SEd Tanous     {
6044c70412SEd Tanous         return;
6144c70412SEd Tanous     }
6244c70412SEd Tanous 
6362598e31SEd Tanous     BMCWEB_LOG_WARNING("405 on path {}", path);
6444c70412SEd Tanous     asyncResp->res.result(boost::beast::http::status::method_not_allowed);
6544c70412SEd Tanous     if (req.method() == boost::beast::http::verb::delete_)
6644c70412SEd Tanous     {
6744c70412SEd Tanous         messages::resourceCannotBeDeleted(asyncResp->res);
6844c70412SEd Tanous     }
6944c70412SEd Tanous     else
7044c70412SEd Tanous     {
7144c70412SEd Tanous         messages::operationNotAllowed(asyncResp->res);
7244c70412SEd Tanous     }
7344c70412SEd Tanous }
7444c70412SEd Tanous 
7581d523a7SEd Tanous inline void
7681d523a7SEd Tanous     jsonSchemaIndexGet(App& app, const crow::Request& req,
7781d523a7SEd Tanous                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7881d523a7SEd Tanous {
7981d523a7SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
8081d523a7SEd Tanous     {
8181d523a7SEd Tanous         return;
8281d523a7SEd Tanous     }
8381d523a7SEd Tanous     nlohmann::json& json = asyncResp->res.jsonValue;
8481d523a7SEd Tanous     json["@odata.id"] = "/redfish/v1/JsonSchemas";
8581d523a7SEd Tanous     json["@odata.type"] = "#JsonSchemaFileCollection.JsonSchemaFileCollection";
8681d523a7SEd Tanous     json["Name"] = "JsonSchemaFile Collection";
8781d523a7SEd Tanous     json["Description"] = "Collection of JsonSchemaFiles";
8881d523a7SEd Tanous     nlohmann::json::array_t members;
8926ccae32SEd Tanous     for (std::string_view schema : schemas)
9081d523a7SEd Tanous     {
9181d523a7SEd Tanous         nlohmann::json::object_t member;
92ef4c65b7SEd Tanous         member["@odata.id"] = boost::urls::format("/redfish/v1/JsonSchemas/{}",
93ef4c65b7SEd Tanous                                                   schema);
94ad539545SPatrick Williams         members.emplace_back(std::move(member));
9581d523a7SEd Tanous     }
9681d523a7SEd Tanous     json["Members"] = std::move(members);
9781d523a7SEd Tanous     json["Members@odata.count"] = schemas.size();
9881d523a7SEd Tanous }
9981d523a7SEd Tanous 
10081d523a7SEd Tanous inline void jsonSchemaGet(App& app, const crow::Request& req,
10181d523a7SEd Tanous                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
10281d523a7SEd Tanous                           const std::string& schema)
10381d523a7SEd Tanous {
10481d523a7SEd Tanous     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
10581d523a7SEd Tanous     {
10681d523a7SEd Tanous         return;
10781d523a7SEd Tanous     }
10881d523a7SEd Tanous 
109*3544d2a7SEd Tanous     if (std::ranges::find(schemas, schema) == schemas.end())
11081d523a7SEd Tanous     {
111d8a5d5d8SJiaqing Zhao         messages::resourceNotFound(asyncResp->res, "JsonSchemaFile", schema);
11281d523a7SEd Tanous         return;
11381d523a7SEd Tanous     }
11481d523a7SEd Tanous 
11581d523a7SEd Tanous     nlohmann::json& json = asyncResp->res.jsonValue;
116ef4c65b7SEd Tanous     json["@odata.id"] = boost::urls::format("/redfish/v1/JsonSchemas/{}",
117ef4c65b7SEd Tanous                                             schema);
11881d523a7SEd Tanous     json["@odata.type"] = "#JsonSchemaFile.v1_0_2.JsonSchemaFile";
11981d523a7SEd Tanous     json["Name"] = schema + " Schema File";
12081d523a7SEd Tanous     json["Description"] = schema + " Schema File Location";
12181d523a7SEd Tanous     json["Id"] = schema;
12281d523a7SEd Tanous     std::string schemaName = "#";
12381d523a7SEd Tanous     schemaName += schema;
12481d523a7SEd Tanous     schemaName += ".";
12581d523a7SEd Tanous     schemaName += schema;
12681d523a7SEd Tanous     json["Schema"] = std::move(schemaName);
12781d523a7SEd Tanous     constexpr std::array<std::string_view, 1> languages{"en"};
12881d523a7SEd Tanous     json["Languages"] = languages;
12981d523a7SEd Tanous     json["Languages@odata.count"] = languages.size();
13081d523a7SEd Tanous 
13181d523a7SEd Tanous     nlohmann::json::array_t locationArray;
13281d523a7SEd Tanous     nlohmann::json::object_t locationEntry;
13381d523a7SEd Tanous     locationEntry["Language"] = "en";
13489492a15SPatrick Williams     locationEntry["PublicationUri"] = "http://redfish.dmtf.org/schemas/v1/" +
13589492a15SPatrick Williams                                       schema + ".json";
136ef4c65b7SEd Tanous     locationEntry["Uri"] = boost::urls::format(
137ef4c65b7SEd Tanous         "/redfish/v1/JsonSchemas/{}/{}", schema, std::string(schema) + ".json");
13881d523a7SEd Tanous 
13981d523a7SEd Tanous     locationArray.emplace_back(locationEntry);
14081d523a7SEd Tanous 
14181d523a7SEd Tanous     json["Location"] = std::move(locationArray);
14281d523a7SEd Tanous     json["Location@odata.count"] = 1;
14381d523a7SEd Tanous }
14481d523a7SEd Tanous 
145f65fca6aSEd Tanous inline void requestRoutesRedfish(App& app)
146d3355c5cSEd Tanous {
147d3355c5cSEd Tanous     BMCWEB_ROUTE(app, "/redfish/")
148d3355c5cSEd Tanous         .methods(boost::beast::http::verb::get)(
149d3355c5cSEd Tanous             std::bind_front(redfishGet, std::ref(app)));
1508c623a96SEd Tanous 
15181d523a7SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/JsonSchemas/<str>/")
1520ea4b4e2SEd Tanous         .privileges(redfish::privileges::getJsonSchemaFileCollection)
15381d523a7SEd Tanous         .methods(boost::beast::http::verb::get)(
15481d523a7SEd Tanous             std::bind_front(jsonSchemaGet, std::ref(app)));
15581d523a7SEd Tanous 
15681d523a7SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/JsonSchemas/")
1570ea4b4e2SEd Tanous         .privileges(redfish::privileges::getJsonSchemaFile)
15881d523a7SEd Tanous         .methods(boost::beast::http::verb::get)(
15981d523a7SEd Tanous             std::bind_front(jsonSchemaIndexGet, std::ref(app)));
160e9dd1d31SEd Tanous 
161e9dd1d31SEd Tanous     // Note, this route must always be registered last
162e9dd1d31SEd Tanous     BMCWEB_ROUTE(app, "/redfish/<path>")
1630ea4b4e2SEd Tanous         .notFound()
1640ea4b4e2SEd Tanous         .privileges(redfish::privileges::privilegeSetLogin)(
1650ea4b4e2SEd Tanous             std::bind_front(redfish404, std::ref(app)));
16644c70412SEd Tanous 
16744c70412SEd Tanous     BMCWEB_ROUTE(app, "/redfish/<path>")
1680ea4b4e2SEd Tanous         .methodNotAllowed()
1690ea4b4e2SEd Tanous         .privileges(redfish::privileges::privilegeSetLogin)(
1700ea4b4e2SEd Tanous             std::bind_front(redfish405, std::ref(app)));
1714c25d66eSEd Tanous }
172f65fca6aSEd Tanous 
1734c25d66eSEd Tanous } // namespace redfish
174