1 #pragma once 2 3 #include "app.hpp" 4 #include "error_messages.hpp" 5 #include "http_request.hpp" 6 #include "http_response.hpp" 7 #include "query.hpp" 8 #include "registries/privilege_registry.hpp" 9 #include "schemas.hpp" 10 #include "utility.hpp" 11 12 #include <string> 13 14 namespace redfish 15 { 16 17 inline void redfishGet(App& app, const crow::Request& req, 18 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 19 { 20 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 21 { 22 return; 23 } 24 asyncResp->res.jsonValue["v1"] = "/redfish/v1/"; 25 } 26 27 inline void redfish404(App& app, const crow::Request& req, 28 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 29 const std::string& path) 30 { 31 asyncResp->res.addHeader(boost::beast::http::field::allow, ""); 32 33 // If we fall to this route, we didn't have a more specific route, so return 34 // 404 35 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 36 { 37 return; 38 } 39 40 BMCWEB_LOG_WARNING << "404 on path " << path; 41 42 std::string name = req.url().segments().back(); 43 // Note, if we hit the wildcard route, we don't know the "type" the user was 44 // actually requesting, but giving them a return with an empty string is 45 // still better than nothing. 46 messages::resourceNotFound(asyncResp->res, "", name); 47 } 48 49 inline void redfish405(App& app, const crow::Request& req, 50 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 51 const std::string& path) 52 { 53 // If we fall to this route, we didn't have a more specific route, so return 54 // 405 55 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 56 { 57 return; 58 } 59 60 BMCWEB_LOG_WARNING << "405 on path " << path; 61 asyncResp->res.result(boost::beast::http::status::method_not_allowed); 62 if (req.method() == boost::beast::http::verb::delete_) 63 { 64 messages::resourceCannotBeDeleted(asyncResp->res); 65 } 66 else 67 { 68 messages::operationNotAllowed(asyncResp->res); 69 } 70 } 71 72 inline void 73 jsonSchemaIndexGet(App& app, const crow::Request& req, 74 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 75 { 76 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 77 { 78 return; 79 } 80 nlohmann::json& json = asyncResp->res.jsonValue; 81 json["@odata.id"] = "/redfish/v1/JsonSchemas"; 82 json["@odata.type"] = "#JsonSchemaFileCollection.JsonSchemaFileCollection"; 83 json["Name"] = "JsonSchemaFile Collection"; 84 json["Description"] = "Collection of JsonSchemaFiles"; 85 nlohmann::json::array_t members; 86 for (std::string_view schema : schemas) 87 { 88 nlohmann::json::object_t member; 89 member["@odata.id"] = crow::utility::urlFromPieces( 90 "redfish", "v1", "JsonSchemas", schema); 91 members.emplace_back(std::move(member)); 92 } 93 json["Members"] = std::move(members); 94 json["Members@odata.count"] = schemas.size(); 95 } 96 97 inline void jsonSchemaGet(App& app, const crow::Request& req, 98 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 99 const std::string& schema) 100 { 101 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 102 { 103 return; 104 } 105 106 if (std::find(schemas.begin(), schemas.end(), schema) == schemas.end()) 107 { 108 messages::resourceNotFound(asyncResp->res, "JsonSchemaFile", schema); 109 return; 110 } 111 112 nlohmann::json& json = asyncResp->res.jsonValue; 113 json["@odata.id"] = crow::utility::urlFromPieces("redfish", "v1", 114 "JsonSchemas", schema); 115 json["@odata.type"] = "#JsonSchemaFile.v1_0_2.JsonSchemaFile"; 116 json["Name"] = schema + " Schema File"; 117 json["Description"] = schema + " Schema File Location"; 118 json["Id"] = schema; 119 std::string schemaName = "#"; 120 schemaName += schema; 121 schemaName += "."; 122 schemaName += schema; 123 json["Schema"] = std::move(schemaName); 124 constexpr std::array<std::string_view, 1> languages{"en"}; 125 json["Languages"] = languages; 126 json["Languages@odata.count"] = languages.size(); 127 128 nlohmann::json::array_t locationArray; 129 nlohmann::json::object_t locationEntry; 130 locationEntry["Language"] = "en"; 131 locationEntry["PublicationUri"] = "http://redfish.dmtf.org/schemas/v1/" + 132 schema + ".json"; 133 locationEntry["Uri"] = crow::utility::urlFromPieces( 134 "redfish", "v1", "JsonSchemas", schema, std::string(schema) + ".json"); 135 136 locationArray.emplace_back(locationEntry); 137 138 json["Location"] = std::move(locationArray); 139 json["Location@odata.count"] = 1; 140 } 141 142 inline void requestRoutesRedfish(App& app) 143 { 144 BMCWEB_ROUTE(app, "/redfish/") 145 .methods(boost::beast::http::verb::get)( 146 std::bind_front(redfishGet, std::ref(app))); 147 148 BMCWEB_ROUTE(app, "/redfish/v1/JsonSchemas/<str>/") 149 .privileges(redfish::privileges::getJsonSchemaFileCollection) 150 .methods(boost::beast::http::verb::get)( 151 std::bind_front(jsonSchemaGet, std::ref(app))); 152 153 BMCWEB_ROUTE(app, "/redfish/v1/JsonSchemas/") 154 .privileges(redfish::privileges::getJsonSchemaFile) 155 .methods(boost::beast::http::verb::get)( 156 std::bind_front(jsonSchemaIndexGet, std::ref(app))); 157 158 // Note, this route must always be registered last 159 BMCWEB_ROUTE(app, "/redfish/<path>") 160 .notFound() 161 .privileges(redfish::privileges::privilegeSetLogin)( 162 std::bind_front(redfish404, std::ref(app))); 163 164 BMCWEB_ROUTE(app, "/redfish/<path>") 165 .methodNotAllowed() 166 .privileges(redfish::privileges::privilegeSetLogin)( 167 std::bind_front(redfish405, std::ref(app))); 168 } 169 170 } // namespace redfish 171