diff options
author | Ed Tanous <ed.tanous@intel.com> | 2018-03-28 03:41:04 +0300 |
---|---|---|
committer | Ed Tanous <ed.tanous@intel.com> | 2018-06-29 21:18:14 +0300 |
commit | e0d918bc397350aa21af3dab9faa6e21748f6373 (patch) | |
tree | bdc13d1e9937c0f153e89f3ab1be050d4bf52ee7 /redfish-core | |
parent | 77dd8813e9a1f2baec63d959de15af39a8cd12d0 (diff) | |
download | bmcweb-e0d918bc397350aa21af3dab9faa6e21748f6373.tar.xz |
Boost beast
This commit is the beginings of attempting to transition away from
crow, and toward boost::beast. Unit tests are passing, and
implementation appears to be slightly faster than crow.
Change-Id: Ic8d946dc7a04f514c67b1098f181eee1ced69171
Diffstat (limited to 'redfish-core')
-rw-r--r-- | redfish-core/include/node.hpp | 14 | ||||
-rw-r--r-- | redfish-core/include/privileges.hpp | 8 | ||||
-rw-r--r-- | redfish-core/lib/account_service.hpp | 12 | ||||
-rw-r--r-- | redfish-core/lib/chassis.hpp | 46 | ||||
-rw-r--r-- | redfish-core/lib/ethernet.hpp | 30 | ||||
-rw-r--r-- | redfish-core/lib/managers.hpp | 24 | ||||
-rw-r--r-- | redfish-core/lib/network_protocol.hpp | 12 | ||||
-rw-r--r-- | redfish-core/lib/redfish_sessions.hpp | 76 | ||||
-rw-r--r-- | redfish-core/lib/roles.hpp | 24 | ||||
-rw-r--r-- | redfish-core/lib/sensors.hpp | 170 | ||||
-rw-r--r-- | redfish-core/lib/service_root.hpp | 12 | ||||
-rw-r--r-- | redfish-core/lib/thermal.hpp | 15 | ||||
-rw-r--r-- | redfish-core/src/utils/json_utils.cpp | 3 | ||||
-rw-r--r-- | redfish-core/ut/privileges_test.cpp | 28 |
14 files changed, 240 insertions, 234 deletions
diff --git a/redfish-core/include/node.hpp b/redfish-core/include/node.hpp index b41439aac1..3fb0ce7370 100644 --- a/redfish-core/include/node.hpp +++ b/redfish-core/include/node.hpp @@ -102,19 +102,19 @@ class Node { virtual void doPatch(crow::response& res, const crow::request& req, const std::vector<std::string>& params) { - res.code = static_cast<int>(HttpRespCode::METHOD_NOT_ALLOWED); + res.result(boost::beast::http::status::method_not_allowed); res.end(); } virtual void doPost(crow::response& res, const crow::request& req, const std::vector<std::string>& params) { - res.code = static_cast<int>(HttpRespCode::METHOD_NOT_ALLOWED); + res.result(boost::beast::http::status::method_not_allowed); res.end(); } virtual void doDelete(crow::response& res, const crow::request& req, const std::vector<std::string>& params) { - res.code = static_cast<int>(HttpRespCode::METHOD_NOT_ALLOWED); + res.result(boost::beast::http::status::method_not_allowed); res.end(); } @@ -127,14 +127,14 @@ class Node { auto ctx = app.template get_context<crow::TokenAuthorization::Middleware>(req); - if (!isMethodAllowedForUser(req.method, entityPrivileges, + if (!isMethodAllowedForUser(req.method(), entityPrivileges, ctx.session->username)) { - res.code = static_cast<int>(HttpRespCode::METHOD_NOT_ALLOWED); + res.result(boost::beast::http::status::method_not_allowed); res.end(); return; } - switch (req.method) { + switch (req.method()) { case "GET"_method: doGet(res, req, params); break; @@ -152,7 +152,7 @@ class Node { break; default: - res.code = static_cast<int>(HttpRespCode::NOT_FOUND); + res.result(boost::beast::http::status::not_found); res.end(); } return; diff --git a/redfish-core/include/privileges.hpp b/redfish-core/include/privileges.hpp index 1341f3614b..e98debbc6a 100644 --- a/redfish-core/include/privileges.hpp +++ b/redfish-core/include/privileges.hpp @@ -157,8 +157,8 @@ class Privileges { std::bitset<MAX_PRIVILEGE_COUNT> privilegeBitset = 0; }; -using OperationMap = - boost::container::flat_map<crow::HTTPMethod, std::vector<Privileges>>; +using OperationMap = boost::container::flat_map<boost::beast::http::verb, + std::vector<Privileges>>; /** * @brief Checks if given privileges allow to call an HTTP method @@ -169,7 +169,7 @@ using OperationMap = * @return True if method allowed, false otherwise * */ -inline bool isMethodAllowedWithPrivileges(const crow::HTTPMethod method, +inline bool isMethodAllowedWithPrivileges(const boost::beast::http::verb method, const OperationMap& operationMap, const Privileges& userPrivileges) { const auto& it = operationMap.find(method); @@ -199,7 +199,7 @@ inline bool isMethodAllowedWithPrivileges(const crow::HTTPMethod method, * @return True if method allowed, false otherwise * */ -inline bool isMethodAllowedForUser(const crow::HTTPMethod method, +inline bool isMethodAllowedForUser(const boost::beast::http::verb method, const OperationMap& operationMap, const std::string& user) { // TODO: load user privileges from configuration as soon as its available diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp index 53b67a4d82..48872f8ec8 100644 --- a/redfish-core/lib/account_service.hpp +++ b/redfish-core/lib/account_service.hpp @@ -37,12 +37,12 @@ class AccountService : public Node { Node::json["Roles"]["@odata.id"] = "/redfish/v1/AccountService/Roles"; entityPrivileges = { - {crow::HTTPMethod::GET, {{"ConfigureUsers"}, {"ConfigureManager"}}}, - {crow::HTTPMethod::HEAD, {{"Login"}}}, - {crow::HTTPMethod::PATCH, {{"ConfigureUsers"}}}, - {crow::HTTPMethod::PUT, {{"ConfigureUsers"}}}, - {crow::HTTPMethod::DELETE, {{"ConfigureUsers"}}}, - {crow::HTTPMethod::POST, {{"ConfigureUsers"}}}}; + {boost::beast::http::verb::get, {{"ConfigureUsers"}, {"ConfigureManager"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureUsers"}}}, + {boost::beast::http::verb::put, {{"ConfigureUsers"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureUsers"}}}, + {boost::beast::http::verb::post, {{"ConfigureUsers"}}}}; } private: diff --git a/redfish-core/lib/chassis.hpp b/redfish-core/lib/chassis.hpp index c2ea91d72c..6047f3e65d 100644 --- a/redfish-core/lib/chassis.hpp +++ b/redfish-core/lib/chassis.hpp @@ -108,12 +108,13 @@ class ChassisCollection : public Node { "/redfish/v1/$metadata#ChassisCollection.ChassisCollection"; Node::json["Name"] = "Chassis Collection"; - entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}}, - {crow::HTTPMethod::HEAD, {{"Login"}}}, - {crow::HTTPMethod::PATCH, {{"ConfigureComponents"}}}, - {crow::HTTPMethod::PUT, {{"ConfigureComponents"}}}, - {crow::HTTPMethod::DELETE, {{"ConfigureComponents"}}}, - {crow::HTTPMethod::POST, {{"ConfigureComponents"}}}}; + entityPrivileges = { + {boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; } private: @@ -138,7 +139,7 @@ class ChassisCollection : public Node { res.json_value = Node::json; } else { // ... otherwise, return INTERNALL ERROR - res.code = static_cast<int>(HttpRespCode::INTERNAL_ERROR); + res.result(boost::beast::http::status::internal_server_error); } res.end(); }); @@ -166,12 +167,13 @@ class Chassis : public Node { Node::json["Name"] = "Chassis Collection"; Node::json["ChassisType"] = "RackMount"; - entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}}, - {crow::HTTPMethod::HEAD, {{"Login"}}}, - {crow::HTTPMethod::PATCH, {{"ConfigureComponents"}}}, - {crow::HTTPMethod::PUT, {{"ConfigureComponents"}}}, - {crow::HTTPMethod::DELETE, {{"ConfigureComponents"}}}, - {crow::HTTPMethod::POST, {{"ConfigureComponents"}}}}; + entityPrivileges = { + {boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; } private: @@ -183,7 +185,7 @@ class Chassis : public Node { // Check if there is required param, truly entering this shall be // impossible. if (params.size() != 1) { - res.code = static_cast<int>(HttpRespCode::INTERNAL_ERROR); + res.result(boost::beast::http::status::internal_server_error); res.end(); return; } @@ -198,8 +200,8 @@ class Chassis : public Node { std::vector<std::pair<std::string, std::vector<std::string>>>>> &subtree) { if (error_code) { - res.code = static_cast<int>(HttpRespCode::INTERNAL_ERROR); res.json_value = {}; + res.result(boost::beast::http::status::internal_server_error); res.end(); return; } @@ -211,14 +213,16 @@ class Chassis : public Node { const std::string &path = object.first; const std::vector<std::pair<std::string, std::vector<std::string>>> &connectionNames = object.second; + if (!boost::ends_with(path, chassis_id)) { continue; } if (connectionNames.size() < 1) { - res.code = static_cast<int>(HttpRespCode::INTERNAL_ERROR); - res.end(); - return; + CROW_LOG_ERROR << "Only got " << connectionNames.size() + << " connection names"; + continue; } + const std::string connectionName = connectionNames[0].first; crow::connections::system_bus->async_method_call( [&res, chassis_id(std::string(chassis_id)) ]( @@ -244,8 +248,10 @@ class Chassis : public Node { // Found the connection we were looking for, return return; } + // Couldn't find an object with that name. return an error - res.code = static_cast<int>(HttpRespCode::NOT_FOUND); + res.result(boost::beast::http::status::not_found); + res.end(); }, "xyz.openbmc_project.ObjectMapper", @@ -259,6 +265,6 @@ class Chassis : public Node { // Chassis Provider object // TODO(Pawel) consider move it to singleton OnDemandChassisProvider chassis_provider; -}; +}; // namespace redfish } // namespace redfish diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp index ba69728f78..6c91cef12c 100644 --- a/redfish-core/lib/ethernet.hpp +++ b/redfish-core/lib/ethernet.hpp @@ -355,12 +355,12 @@ class EthernetCollection : public Node { Node::json["Description"] = "Collection of EthernetInterfaces for this Manager"; - entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}}, - {crow::HTTPMethod::HEAD, {{"Login"}}}, - {crow::HTTPMethod::PATCH, {{"ConfigureComponents"}}}, - {crow::HTTPMethod::PUT, {{"ConfigureComponents"}}}, - {crow::HTTPMethod::DELETE, {{"ConfigureComponents"}}}, - {crow::HTTPMethod::POST, {{"ConfigureComponents"}}}}; + entityPrivileges = {{boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; } private: @@ -391,7 +391,7 @@ class EthernetCollection : public Node { res.json_value = Node::json; } else { // No success, best what we can do is return INTERNALL ERROR - res.code = static_cast<int>(HttpRespCode::INTERNAL_ERROR); + res.result(boost::beast::http::status::internal_server_error); } res.end(); }); @@ -423,12 +423,12 @@ class EthernetInterface : public Node { Node::json["Name"] = "Manager Ethernet Interface"; Node::json["Description"] = "Management Network Interface"; - entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}}, - {crow::HTTPMethod::HEAD, {{"Login"}}}, - {crow::HTTPMethod::PATCH, {{"ConfigureComponents"}}}, - {crow::HTTPMethod::PUT, {{"ConfigureComponents"}}}, - {crow::HTTPMethod::DELETE, {{"ConfigureComponents"}}}, - {crow::HTTPMethod::POST, {{"ConfigureComponents"}}}}; + entityPrivileges = {{boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; } private: @@ -442,7 +442,7 @@ class EthernetInterface : public Node { // Check if there is required param, truly entering this shall be // impossible. if (params.size() != 1) { - res.code = static_cast<int>(HttpRespCode::INTERNAL_ERROR); + res.result(boost::beast::http::status::internal_server_error); res.end(); return; } @@ -503,7 +503,7 @@ class EthernetInterface : public Node { // ... otherwise return error // TODO(Pawel)consider distinguish between non existing object, and // other errors - res.code = static_cast<int>(HttpRespCode::NOT_FOUND); + res.result(boost::beast::http::status::not_found); } res.end(); }); diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp index 0ad768fea9..c8609b441a 100644 --- a/redfish-core/lib/managers.hpp +++ b/redfish-core/lib/managers.hpp @@ -43,12 +43,12 @@ class Manager : public Node { // will work // correctly - entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}}, - {crow::HTTPMethod::HEAD, {{"Login"}}}, - {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}}, - {crow::HTTPMethod::PUT, {{"ConfigureManager"}}}, - {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}}, - {crow::HTTPMethod::POST, {{"ConfigureManager"}}}}; + entityPrivileges = {{boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, + {boost::beast::http::verb::put, {{"ConfigureManager"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, + {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; } private: @@ -87,12 +87,12 @@ class ManagerCollection : public Node { Node::json["Members@odata.count"] = 1; Node::json["Members"] = {{{"@odata.id", "/redfish/v1/Managers/openbmc"}}}; - entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}}, - {crow::HTTPMethod::HEAD, {{"Login"}}}, - {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}}, - {crow::HTTPMethod::PUT, {{"ConfigureManager"}}}, - {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}}, - {crow::HTTPMethod::POST, {{"ConfigureManager"}}}}; + entityPrivileges = {{boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, + {boost::beast::http::verb::put, {{"ConfigureManager"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, + {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; } private: diff --git a/redfish-core/lib/network_protocol.hpp b/redfish-core/lib/network_protocol.hpp index 581eb038b4..438de41efc 100644 --- a/redfish-core/lib/network_protocol.hpp +++ b/redfish-core/lib/network_protocol.hpp @@ -36,12 +36,12 @@ class NetworkProtocol : public Node { Node::json["Status"]["HealthRollup"] = "OK"; Node::json["Status"]["State"] = "Enabled"; - entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}}, - {crow::HTTPMethod::HEAD, {{"Login"}}}, - {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}}, - {crow::HTTPMethod::PUT, {{"ConfigureManager"}}}, - {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}}, - {crow::HTTPMethod::POST, {{"ConfigureManager"}}}}; + entityPrivileges = {{boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, + {boost::beast::http::verb::put, {{"ConfigureManager"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, + {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; } private: diff --git a/redfish-core/lib/redfish_sessions.hpp b/redfish-core/lib/redfish_sessions.hpp index 507116da80..7de6d3ba9a 100644 --- a/redfish-core/lib/redfish_sessions.hpp +++ b/redfish-core/lib/redfish_sessions.hpp @@ -32,12 +32,13 @@ class Sessions : public Node { Node::json["Name"] = "User Session"; Node::json["Description"] = "Manager User Session"; - entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}}, - {crow::HTTPMethod::HEAD, {{"Login"}}}, - {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}}, - {crow::HTTPMethod::PUT, {{"ConfigureManager"}}}, - {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}}, - {crow::HTTPMethod::POST, {{"ConfigureManager"}}}}; + entityPrivileges = { + {boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, + {boost::beast::http::verb::put, {{"ConfigureManager"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, + {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; } private: @@ -50,7 +51,7 @@ class Sessions : public Node { messages::addMessageToErrorJson( res.json_value, messages::resourceNotFound("Session", params[0])); - res.code = static_cast<int>(HttpRespCode::NOT_FOUND); + res.result(boost::beast::http::status::not_found); res.end(); return; } @@ -72,8 +73,9 @@ class Sessions : public Node { CROW_LOG_ERROR << "Session DELETE has been called with invalid number of params"; - res.code = static_cast<int>(HttpRespCode::BAD_REQUEST); + res.result(boost::beast::http::status::bad_request); messages::addMessageToErrorJson(res.json_value, messages::generalError()); + res.end(); return; } @@ -85,7 +87,7 @@ class Sessions : public Node { messages::addMessageToErrorJson( res.json_value, messages::resourceNotFound("Session", params[0])); - res.code = static_cast<int>(HttpRespCode::NOT_FOUND); + res.result(boost::beast::http::status::not_found); res.end(); return; } @@ -117,12 +119,13 @@ class SessionCollection : public Node { Node::json["Members@odata.count"] = 0; Node::json["Members"] = nlohmann::json::array(); - entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}}, - {crow::HTTPMethod::HEAD, {{"Login"}}}, - {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}}, - {crow::HTTPMethod::PUT, {{"ConfigureManager"}}}, - {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}}, - {crow::HTTPMethod::POST, {}}}; + entityPrivileges = { + {boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, + {boost::beast::http::verb::put, {{"ConfigureManager"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, + {boost::beast::http::verb::post, {}}}; } private: @@ -134,7 +137,7 @@ class SessionCollection : public Node { Node::json["Members@odata.count"] = session_ids.size(); Node::json["Members"] = nlohmann::json::array(); - for (const auto& uid : session_ids) { + for (const std::string* uid : session_ids) { Node::json["Members"].push_back( {{"@odata.id", "/redfish/v1/SessionService/Sessions/" + *uid}}); } @@ -145,9 +148,12 @@ class SessionCollection : public Node { void doPost(crow::response& res, const crow::request& req, const std::vector<std::string>& params) override { + boost::beast::http::status status; std::string username; bool userAuthSuccessful = - authenticateUser(req, res.code, username, res.json_value); + authenticateUser(req, status, username, res.json_value); + res.result(status); + if (!userAuthSuccessful) { res.end(); return; @@ -156,10 +162,10 @@ class SessionCollection : public Node { // User is authenticated - create session for him auto session = crow::PersistentData::session_store->generate_user_session(username); - res.add_header("X-Auth-Token", session.session_token); + res.add_header("X-Auth-Token", session->session_token); // Return data for created session - memberSession.doGet(res, req, {session.unique_id}); + memberSession.doGet(res, req, {session->unique_id}); // No need for res.end(), as it is called by doGet() } @@ -174,7 +180,8 @@ class SessionCollection : public Node { * * @return true if authentication was successful, false otherwise */ - bool authenticateUser(const crow::request& req, int& httpRespCode, + bool authenticateUser(const crow::request& req, + boost::beast::http::status& httpRespCode, std::string& user, nlohmann::json& errJson) { // We need only UserName and Password - nothing more, nothing less static constexpr const unsigned int numberOfRequiredFieldsInReq = 2; @@ -182,7 +189,7 @@ class SessionCollection : public Node { // call with exceptions disabled auto login_credentials = nlohmann::json::parse(req.body, nullptr, false); if (login_credentials.is_discarded()) { - httpRespCode = static_cast<int>(HttpRespCode::BAD_REQUEST); + httpRespCode = boost::beast::http::status::bad_request; messages::addMessageToErrorJson(errJson, messages::malformedJSON()); @@ -191,7 +198,7 @@ class SessionCollection : public Node { // Check that there are only as many fields as there should be if (login_credentials.size() != numberOfRequiredFieldsInReq) { - httpRespCode = static_cast<int>(HttpRespCode::BAD_REQUEST); + httpRespCode = boost::beast::http::status::bad_request; messages::addMessageToErrorJson(errJson, messages::malformedJSON()); @@ -203,7 +210,7 @@ class SessionCollection : public Node { auto pass_it = login_credentials.find("Password"); if (user_it == login_credentials.end() || pass_it == login_credentials.end()) { - httpRespCode = static_cast<int>(HttpRespCode::BAD_REQUEST); + httpRespCode = boost::beast::http::status::bad_request; if (user_it == login_credentials.end()) { messages::addMessageToErrorJson(errJson, @@ -220,7 +227,7 @@ class SessionCollection : public Node { // Check that given data is of valid type (string) if (!user_it->is_string() || !pass_it->is_string()) { - httpRespCode = static_cast<int>(HttpRespCode::BAD_REQUEST); + httpRespCode = boost::beast::http::status::bad_request; if (!user_it->is_string()) { messages::addMessageToErrorJson( @@ -243,7 +250,7 @@ class SessionCollection : public Node { // Verify that required fields are not empty if (username.empty() || password.empty()) { - httpRespCode = static_cast<int>(HttpRespCode::BAD_REQUEST); + httpRespCode = boost::beast::http::status::bad_request; if (username.empty()) { messages::addMessageToErrorJson(errJson, @@ -260,17 +267,17 @@ class SessionCollection : public Node { // Finally - try to authenticate user if (!pam_authenticate_user(username, password)) { - httpRespCode = static_cast<int>(HttpRespCode::UNAUTHORIZED); + httpRespCode = boost::beast::http::status::unauthorized; messages::addMessageToErrorJson( errJson, messages::resourceAtUriUnauthorized( - req.url, "Invalid username or password")); + std::string(req.url), "Invalid username or password")); return false; } // User authenticated successfully - httpRespCode = static_cast<int>(HttpRespCode::OK); + httpRespCode = boost::beast::http::status::ok; user = username; return true; @@ -297,12 +304,13 @@ class SessionService : public Node { crow::PersistentData::session_store->get_timeout_in_seconds(); Node::json["ServiceEnabled"] = true; - entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}}, - {crow::HTTPMethod::HEAD, {{"Login"}}}, - {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}}, - {crow::HTTPMethod::PUT, {{"ConfigureManager"}}}, - {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}}, - {crow::HTTPMethod::POST, {{"ConfigureManager"}}}}; + entityPrivileges = { + {boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, + {boost::beast::http::verb::put, {{"ConfigureManager"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, + {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; } private: diff --git a/redfish-core/lib/roles.hpp b/redfish-core/lib/roles.hpp index 7b7a804579..f538c834f5 100644 --- a/redfish-core/lib/roles.hpp +++ b/redfish-core/lib/roles.hpp @@ -34,12 +34,12 @@ class Roles : public Node { "ConfigureUsers", "ConfigureSelf", "ConfigureComponents"}; Node::json["OemPrivileges"] = nlohmann::json::array(); - entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}}, - {crow::HTTPMethod::HEAD, {{"Login"}}}, - {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}}, - {crow::HTTPMethod::PUT, {{"ConfigureManager"}}}, - {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}}, - {crow::HTTPMethod::POST, {{"ConfigureManager"}}}}; + entityPrivileges = {{boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, + {boost::beast::http::verb::put, {{"ConfigureManager"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, + {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; } private: @@ -64,12 +64,12 @@ class RoleCollection : public Node { Node::json["Members"] = { {{"@odata.id", "/redfish/v1/AccountService/Roles/Administrator"}}}; - entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}}, - {crow::HTTPMethod::HEAD, {{"Login"}}}, - {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}}, - {crow::HTTPMethod::PUT, {{"ConfigureManager"}}}, - {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}}, - {crow::HTTPMethod::POST, {{"ConfigureManager"}}}}; + entityPrivileges = {{boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, + {boost::beast::http::verb::put, {{"ConfigureManager"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, + {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; } private: diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp index 4ba63e7ad0..a8b74ffb38 100644 --- a/redfish-core/lib/sensors.hpp +++ b/redfish-core/lib/sensors.hpp @@ -51,7 +51,7 @@ class AsyncResp { } ~AsyncResp() { - if (res.code != static_cast<int>(HttpRespCode::OK)) { + if (res.result() == boost::beast::http::status::internal_server_error) { // Reset the json object to clear out any data that made it in before the // error happened // todo(ed) handle error condition with proper code @@ -60,7 +60,7 @@ class AsyncResp { res.end(); } void setErrorStatus() { - res.code = static_cast<int>(HttpRespCode::INTERNAL_ERROR); + res.result(boost::beast::http::status::internal_server_error); } std::string chassisId{}; @@ -75,7 +75,7 @@ class AsyncResp { * @param callback Callback for processing gathered connections */ template <typename Callback> -void getConnections(const std::shared_ptr<AsyncResp>& asyncResp, +void getConnections(std::shared_ptr<AsyncResp> asyncResp, const boost::container::flat_set<std::string>& sensorNames, Callback&& callback) { CROW_LOG_DEBUG << "getConnections"; @@ -86,7 +86,7 @@ void getConnections(const std::shared_ptr<AsyncResp>& asyncResp, // Response handler for parsing objects subtree auto resp_handler = [ callback{std::move(callback)}, asyncResp, sensorNames ]( const boost::system::error_code ec, const GetSubTreeType& subtree) { - if (ec != 0) { + if (ec) { asyncResp->setErrorStatus(); CROW_LOG_ERROR << "resp_handler: Dbus error " << ec; return; @@ -144,8 +144,7 @@ void getConnections(const std::shared_ptr<AsyncResp>& asyncResp, * @param callback Callback for next step in gathered sensor processing */ template <typename Callback> -void getChassis(const std::shared_ptr<AsyncResp>& asyncResp, - Callback&& callback) { +void getChassis(std::shared_ptr<AsyncResp> asyncResp, Callback&& callback) { CROW_LOG_DEBUG << "getChassis Done"; // Process response from EntityManager and extract chassis data @@ -190,7 +189,7 @@ void getChassis(const std::shared_ptr<AsyncResp>& asyncResp, if (!foundChassis) { CROW_LOG_INFO << "Unable to find chassis named " << asyncResp->chassisId; - asyncResp->res.code = static_cast<int>(HttpRespCode::NOT_FOUND); + asyncResp->res.result(boost::beast::http::status::not_found); } else { callback(sensorNames); } @@ -325,6 +324,7 @@ void objectInterfacesToJson( } } } + CROW_LOG_DEBUG << "Added sensor " << sensorName; } /** @@ -332,94 +332,86 @@ void objectInterfacesToJson( * chassis. * @param asyncResp Pointer to object holding response data */ -void getChassisData(const std::shared_ptr<AsyncResp>& asyncResp) { +void getChassisData(std::shared_ptr<AsyncResp> asyncResp) { CROW_LOG_DEBUG << "getChassisData"; auto getChassisCb = [&, asyncResp](boost::container::flat_set<std::string>& sensorNames) { CROW_LOG_DEBUG << "getChassisCb Done"; - auto getConnectionCb = - [&, asyncResp, sensorNames]( - const boost::container::flat_set<std::string>& connections) { - CROW_LOG_DEBUG << "getConnectionCb Done"; - // Get managed objects from all services exposing sensors - for (const std::string& connection : connections) { - // Response handler to process managed objects - auto getManagedObjectsCb = [&, asyncResp, sensorNames]( - const boost::system::error_code ec, - ManagedObjectsVectorType& resp) { - // Go through all objects and update response with - // sensor data - for (const auto& objDictEntry : resp) { - const std::string& objPath = - static_cast<const std::string&>(objDictEntry.first); - CROW_LOG_DEBUG << "getManagedObjectsCb parsing object " - << objPath; - if (!boost::starts_with(objPath, DBUS_SENSOR_PREFIX)) { - CROW_LOG_ERROR << "Got path that isn't in sensor namespace: " - << objPath; - continue; - } - std::vector<std::string> split; - // Reserve space for - // /xyz/openbmc_project/Sensors/<name>/<subname> - split.reserve(6); - boost::algorithm::split(split, objPath, boost::is_any_of("/")); - if (split.size() < 6) { - CROW_LOG_ERROR << "Got path that isn't long enough " - << objPath; - continue; - } - // These indexes aren't intuitive, as boost::split puts an empty - // string at the beginning - const std::string& sensorType = split[4]; - const std::string& sensorName = split[5]; - CROW_LOG_DEBUG << "sensorName " << sensorName << " sensorType " - << sensorType; - if (sensorNames.find(sensorName) == sensorNames.end()) { - CROW_LOG_ERROR << sensorName << " not in sensor list "; - continue; - } - - const char* fieldName = nullptr; - if (sensorType == "temperature") { - fieldName = "Temperatures"; - } else if (sensorType == "fan" || sensorType == "fan_tach") { - fieldName = "Fans"; - } else if (sensorType == "voltage") { - fieldName = "Voltages"; - } else if (sensorType == "current") { - fieldName = "PowerSupply"; - } else if (sensorType == "power") { - fieldName = "PowerSupply"; - } else { - CROW_LOG_ERROR << "Unsure how to handle sensorType " - << sensorType; - continue; - } - - nlohmann::json& temp_array = - asyncResp->res.json_value[fieldName]; - - // Create the array if it doesn't yet exist - if (temp_array.is_array() == false) { - temp_array = nlohmann::json::array(); - } - - temp_array.push_back(nlohmann::json::object()); - nlohmann::json& sensor_json = temp_array.back(); - sensor_json["@odata.id"] = "/redfish/v1/Chassis/" + - asyncResp->chassisId + "/Thermal#/" + - sensorName; - objectInterfacesToJson(sensorName, sensorType, - objDictEntry.second, sensor_json); - } - }; + auto getConnectionCb = [&, asyncResp, sensorNames]( + const boost::container::flat_set<std::string>& + connections) { + CROW_LOG_DEBUG << "getConnectionCb Done"; + // Get managed objects from all services exposing sensors + for (const std::string& connection : connections) { + // Response handler to process managed objects + auto getManagedObjectsCb = [&, asyncResp, sensorNames]( + const boost::system::error_code ec, + ManagedObjectsVectorType& resp) { + // Go through all objects and update response with + // sensor data + for (const auto& objDictEntry : resp) { + const std::string& objPath = + static_cast<const std::string&>(objDictEntry.first); + CROW_LOG_DEBUG << "getManagedObjectsCb parsing object " << objPath; + + std::vector<std::string> split; + // Reserve space for + // /xyz/openbmc_project/Sensors/<name>/<subname> + split.reserve(6); + boost::algorithm::split(split, objPath, boost::is_any_of("/")); + if (split.size() < 6) { + CROW_LOG_ERROR << "Got path that isn't long enough " << objPath; + continue; + } + // These indexes aren't intuitive, as boost::split puts an empty + // string at the beggining + const std::string& sensorType = split[4]; + const std::string& sensorName = split[5]; + CROW_LOG_DEBUG << "sensorName " << sensorName << " sensorType " + << sensorType; + if (sensorNames.find(sensorName) == sensorNames.end()) { + CROW_LOG_ERROR << sensorName << " not in sensor list "; + continue; + } + + const char* fieldName = nullptr; + if (sensorType == "temperature") { + fieldName = "Temperatures"; + } else if (sensorType == "fan" || sensorType == "fan_tach") { + fieldName = "Fans"; + } else if (sensorType == "voltage") { + fieldName = "Voltages"; + } else if (sensorType == "current") { + fieldName = "PowerSupply"; + } else if (sensorType == "power") { + fieldName = "PowerSupply"; + } else { + CROW_LOG_ERROR << "Unsure how to handle sensorType " + << sensorType; + continue; + } - crow::connections::system_bus->async_method_call( - getManagedObjectsCb, connection, "/xyz/openbmc_project/Sensors", - "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); - }; + nlohmann::json& temp_array = asyncResp->res.json_value[fieldName]; + + // Create the array if it doesn't yet exist + if (temp_array.is_array() == false) { + temp_array = nlohmann::json::array(); + } + + temp_array.push_back( + {{"@odata.id", "/redfish/v1/Chassis/" + asyncResp->chassisId + + "/Thermal#/" + sensorName}}); + nlohmann::json& sensor_json = temp_array.back(); + objectInterfacesToJson(sensorName, sensorType, objDictEntry.second, + sensor_json); + } }; + + crow::connections::system_bus->async_method_call( + getManagedObjectsCb, connection, "/xyz/openbmc_project/Sensors", + "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); + }; + }; // Get connections and then pass it to get sensors getConnections(asyncResp, sensorNames, std::move(getConnectionCb)); }; diff --git a/redfish-core/lib/service_root.hpp b/redfish-core/lib/service_root.hpp index c57d3e7797..62796eeeae 100644 --- a/redfish-core/lib/service_root.hpp +++ b/redfish-core/lib/service_root.hpp @@ -35,12 +35,12 @@ class ServiceRoot : public Node { app.template get_middleware<crow::PersistentData::Middleware>() .system_uuid; - entityPrivileges = {{crow::HTTPMethod::GET, {}}, - {crow::HTTPMethod::HEAD, {}}, - {crow::HTTPMethod::PATCH, {{"ConfigureComponents"}}}, - {crow::HTTPMethod::PUT, {{"ConfigureComponents"}}}, - {crow::HTTPMethod::DELETE, {{"ConfigureComponents"}}}, - {crow::HTTPMethod::POST, {{"ConfigureComponents"}}}}; + entityPrivileges = {{boost::beast::http::verb::get, {}}, + {boost::beast::http::verb::head, {}}, + {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; } private: diff --git a/redfish-core/lib/thermal.hpp b/redfish-core/lib/thermal.hpp index b33c80f27f..506e32042e 100644 --- a/redfish-core/lib/thermal.hpp +++ b/redfish-core/lib/thermal.hpp @@ -29,19 +29,20 @@ class Thermal : public Node { Node::json["Id"] = "Thermal"; Node::json["Name"] = "Thermal"; - entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}}, - {crow::HTTPMethod::HEAD, {{"Login"}}}, - {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}}, - {crow::HTTPMethod::PUT, {{"ConfigureManager"}}}, - {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}}, - {crow::HTTPMethod::POST, {{"ConfigureManager"}}}}; + entityPrivileges = { + {boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, + {boost::beast::http::verb::put, {{"ConfigureManager"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, + {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; } private: void doGet(crow::response& res, const crow::request& req, const std::vector<std::string>& params) override { if (params.size() != 1) { - res.code = static_cast<int>(HttpRespCode::INTERNAL_ERROR); + res.result(boost::beast::http::status::internal_server_error); res.end(); return; } diff --git a/redfish-core/src/utils/json_utils.cpp b/redfish-core/src/utils/json_utils.cpp index b4bdba6d35..fea4d38964 100644 --- a/redfish-core/src/utils/json_utils.cpp +++ b/redfish-core/src/utils/json_utils.cpp @@ -15,7 +15,6 @@ */ #include "utils/json_utils.hpp" #include <error_messages.hpp> -#include <crow/http_codes.h> namespace redfish { @@ -440,7 +439,7 @@ bool processJsonFromRequest(crow::response& res, const crow::request& req, if (reqJson.is_discarded()) { messages::addMessageToErrorJson(res.json_value, messages::malformedJSON()); - res.code = static_cast<int>(HttpRespCode::BAD_REQUEST); + res.result(boost::beast::http::status::bad_request); res.end(); return false; diff --git a/redfish-core/ut/privileges_test.cpp b/redfish-core/ut/privileges_test.cpp index 36e02c67f2..92cd6c42a4 100644 --- a/redfish-core/ut/privileges_test.cpp +++ b/redfish-core/ut/privileges_test.cpp @@ -18,26 +18,26 @@ TEST(PrivilegeTest, PrivilegeConstructor) { TEST(PrivilegeTest, PrivilegeCheckForNoPrivilegesRequired) { Privileges userPrivileges{"Login"}; - OperationMap entityPrivileges{{crow::HTTPMethod::GET, {{"Login"}}}}; + OperationMap entityPrivileges{{boost::beast::http::verb::get, {{"Login"}}}}; - EXPECT_TRUE(isMethodAllowedWithPrivileges(crow::HTTPMethod::GET, + EXPECT_TRUE(isMethodAllowedWithPrivileges(boost::beast::http::verb::get, entityPrivileges, userPrivileges)); } TEST(PrivilegeTest, PrivilegeCheckForSingleCaseSuccess) { auto userPrivileges = Privileges{"Login"}; - OperationMap entityPrivileges{{crow::HTTPMethod::GET, {}}}; + OperationMap entityPrivileges{{boost::beast::http::verb::get, {}}}; - EXPECT_TRUE(isMethodAllowedWithPrivileges(crow::HTTPMethod::GET, + EXPECT_TRUE(isMethodAllowedWithPrivileges(boost::beast::http::verb::get, entityPrivileges, userPrivileges)); } TEST(PrivilegeTest, PrivilegeCheckForSingleCaseFailure) { auto userPrivileges = Privileges{"Login"}; OperationMap entityPrivileges{ - {crow::HTTPMethod::GET, {{"ConfigureManager"}}}}; + {boost::beast::http::verb::get, {{"ConfigureManager"}}}}; - EXPECT_FALSE(isMethodAllowedWithPrivileges(crow::HTTPMethod::GET, + EXPECT_FALSE(isMethodAllowedWithPrivileges(boost::beast::http::verb::get, entityPrivileges, userPrivileges)); } @@ -45,38 +45,38 @@ TEST(PrivilegeTest, PrivilegeCheckForANDCaseSuccess) { auto userPrivileges = Privileges{"Login", "ConfigureManager", "ConfigureSelf"}; OperationMap entityPrivileges{ - {crow::HTTPMethod::GET, + {boost::beast::http::verb::get, {{"Login", "ConfigureManager", "ConfigureSelf"}}}}; - EXPECT_TRUE(isMethodAllowedWithPrivileges(crow::HTTPMethod::GET, + EXPECT_TRUE(isMethodAllowedWithPrivileges(boost::beast::http::verb::get, entityPrivileges, userPrivileges)); } TEST(PrivilegeTest, PrivilegeCheckForANDCaseFailure) { auto userPrivileges = Privileges{"Login", "ConfigureManager"}; OperationMap entityPrivileges{ - {crow::HTTPMethod::GET, + {boost::beast::http::verb::get, {{"Login", "ConfigureManager", "ConfigureSelf"}}}}; - EXPECT_FALSE(isMethodAllowedWithPrivileges(crow::HTTPMethod::GET, + EXPECT_FALSE(isMethodAllowedWithPrivileges(boost::beast::http::verb::get, entityPrivileges, userPrivileges)); } TEST(PrivilegeTest, PrivilegeCheckForORCaseSuccess) { auto userPrivileges = Privileges{"ConfigureManager"}; OperationMap entityPrivileges{ - {crow::HTTPMethod::GET, {{"Login"}, {"ConfigureManager"}}}}; + {boost::beast::http::verb::get, {{"Login"}, {"ConfigureManager"}}}}; - EXPECT_TRUE(isMethodAllowedWithPrivileges(crow::HTTPMethod::GET, + EXPECT_TRUE(isMethodAllowedWithPrivileges(boost::beast::http::verb::get, entityPrivileges, userPrivileges)); } TEST(PrivilegeTest, PrivilegeCheckForORCaseFailure) { auto userPrivileges = Privileges{"ConfigureComponents"}; OperationMap entityPrivileges = OperationMap( - {{crow::HTTPMethod::GET, {{"Login"}, {"ConfigureManager"}}}}); + {{boost::beast::http::verb::get, {{"Login"}, {"ConfigureManager"}}}}); - EXPECT_FALSE(isMethodAllowedWithPrivileges(crow::HTTPMethod::GET, + EXPECT_FALSE(isMethodAllowedWithPrivileges(boost::beast::http::verb::get, entityPrivileges, userPrivileges)); } |