|  | /* | 
|  | // Copyright (c) 2018 Intel Corporation | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  | */ | 
|  | #pragma once | 
|  |  | 
|  | #include "privileges.hpp" | 
|  | #include "token_authorization_middleware.hpp" | 
|  | #include "webserver_common.hpp" | 
|  |  | 
|  | #include <error_messages.hpp> | 
|  | #include <vector> | 
|  |  | 
|  | #include "http_request.h" | 
|  | #include "http_response.h" | 
|  |  | 
|  | namespace redfish | 
|  | { | 
|  |  | 
|  | /** | 
|  | * AsyncResp | 
|  | * Gathers data needed for response processing after async calls are done | 
|  | */ | 
|  | class AsyncResp | 
|  | { | 
|  | public: | 
|  | AsyncResp(crow::Response& response) : res(response) | 
|  | { | 
|  | } | 
|  |  | 
|  | ~AsyncResp() | 
|  | { | 
|  | res.end(); | 
|  | } | 
|  |  | 
|  | crow::Response& res; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * @brief  Abstract class used for implementing Redfish nodes. | 
|  | * | 
|  | */ | 
|  | class Node | 
|  | { | 
|  | public: | 
|  | template <typename... Params> | 
|  | Node(CrowApp& app, std::string&& entityUrl, Params... paramsIn) | 
|  | { | 
|  | crow::DynamicRule& get = app.routeDynamic(entityUrl.c_str()); | 
|  | getRule = &get; | 
|  | get.methods("GET"_method)([this](const crow::Request& req, | 
|  | crow::Response& res, | 
|  | Params... params) { | 
|  | std::vector<std::string> paramVec = {params...}; | 
|  | doGet(res, req, paramVec); | 
|  | }); | 
|  |  | 
|  | crow::DynamicRule& patch = app.routeDynamic(entityUrl.c_str()); | 
|  | patchRule = &patch; | 
|  | patch.methods("PATCH"_method)([this](const crow::Request& req, | 
|  | crow::Response& res, | 
|  | Params... params) { | 
|  | std::vector<std::string> paramVec = {params...}; | 
|  | doPatch(res, req, paramVec); | 
|  | }); | 
|  |  | 
|  | crow::DynamicRule& post = app.routeDynamic(entityUrl.c_str()); | 
|  | postRule = &post; | 
|  | post.methods("POST"_method)([this](const crow::Request& req, | 
|  | crow::Response& res, | 
|  | Params... params) { | 
|  | std::vector<std::string> paramVec = {params...}; | 
|  | doPost(res, req, paramVec); | 
|  | }); | 
|  |  | 
|  | crow::DynamicRule& delete_ = app.routeDynamic(entityUrl.c_str()); | 
|  | deleteRule = &delete_; | 
|  | delete_.methods("DELETE"_method)([this](const crow::Request& req, | 
|  | crow::Response& res, | 
|  | Params... params) { | 
|  | std::vector<std::string> paramVec = {params...}; | 
|  | doDelete(res, req, paramVec); | 
|  | }); | 
|  | } | 
|  |  | 
|  | void initPrivileges() | 
|  | { | 
|  | auto it = entityPrivileges.find(boost::beast::http::verb::get); | 
|  | if (it != entityPrivileges.end()) | 
|  | { | 
|  | if (getRule != nullptr) | 
|  | { | 
|  | getRule->requires(it->second); | 
|  | } | 
|  | } | 
|  | it = entityPrivileges.find(boost::beast::http::verb::post); | 
|  | if (it != entityPrivileges.end()) | 
|  | { | 
|  | if (postRule != nullptr) | 
|  | { | 
|  | postRule->requires(it->second); | 
|  | } | 
|  | } | 
|  | it = entityPrivileges.find(boost::beast::http::verb::patch); | 
|  | if (it != entityPrivileges.end()) | 
|  | { | 
|  | if (patchRule != nullptr) | 
|  | { | 
|  | patchRule->requires(it->second); | 
|  | } | 
|  | } | 
|  | it = entityPrivileges.find(boost::beast::http::verb::delete_); | 
|  | if (it != entityPrivileges.end()) | 
|  | { | 
|  | if (deleteRule != nullptr) | 
|  | { | 
|  | deleteRule->requires(it->second); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | virtual ~Node() = default; | 
|  |  | 
|  | OperationMap entityPrivileges; | 
|  |  | 
|  | crow::DynamicRule* getRule = nullptr; | 
|  | crow::DynamicRule* postRule = nullptr; | 
|  | crow::DynamicRule* patchRule = nullptr; | 
|  | crow::DynamicRule* deleteRule = nullptr; | 
|  |  | 
|  | protected: | 
|  | // Node is designed to be an abstract class, so doGet is pure virtual | 
|  | virtual void doGet(crow::Response& res, const crow::Request& req, | 
|  | const std::vector<std::string>& params) | 
|  | { | 
|  | res.result(boost::beast::http::status::method_not_allowed); | 
|  | res.end(); | 
|  | } | 
|  |  | 
|  | virtual void doPatch(crow::Response& res, const crow::Request& req, | 
|  | const std::vector<std::string>& params) | 
|  | { | 
|  | 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.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.result(boost::beast::http::status::method_not_allowed); | 
|  | res.end(); | 
|  | } | 
|  |  | 
|  | /* @brief Would the operation be allowed if the user did not have | 
|  | * the ConfigureSelf Privilege? | 
|  | * | 
|  | * @param req      the request | 
|  | * | 
|  | * @returns        True if allowed, false otherwise | 
|  | */ | 
|  | inline bool isAllowedWithoutConfigureSelf(const crow::Request& req) | 
|  | { | 
|  | const std::string& userRole = | 
|  | crow::persistent_data::UserRoleMap::getInstance().getUserRole( | 
|  | req.session->username); | 
|  | Privileges effectiveUserPrivileges = | 
|  | redfish::getUserPrivileges(userRole); | 
|  | effectiveUserPrivileges.resetSinglePrivilege("ConfigureSelf"); | 
|  | const auto& requiredPrivilegesIt = entityPrivileges.find(req.method()); | 
|  | return (requiredPrivilegesIt != entityPrivileges.end()) && | 
|  | isOperationAllowedWithPrivileges(requiredPrivilegesIt->second, | 
|  | effectiveUserPrivileges); | 
|  | } | 
|  | }; | 
|  |  | 
|  | } // namespace redfish |