1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3 #pragma once 4 5 #include "async_resp.hpp" 6 #include "http_request.hpp" 7 #include "privileges.hpp" 8 #include "verb.hpp" 9 10 #include <boost/asio/ip/tcp.hpp> 11 #include <boost/asio/ssl/stream.hpp> 12 #include <boost/beast/http/status.hpp> 13 14 #include <cstddef> 15 #include <limits> 16 #include <memory> 17 #include <string> 18 #include <string_view> 19 #include <utility> 20 #include <vector> 21 22 namespace crow 23 { 24 class BaseRule 25 { 26 public: BaseRule(std::string_view thisRule)27 explicit BaseRule(std::string_view thisRule) : rule(thisRule) {} 28 29 virtual ~BaseRule() = default; 30 31 BaseRule(const BaseRule&) = delete; 32 BaseRule(BaseRule&&) = delete; 33 BaseRule& operator=(const BaseRule&) = delete; 34 BaseRule& operator=(const BaseRule&&) = delete; 35 36 virtual void validate() = 0; upgrade()37 std::unique_ptr<BaseRule> upgrade() 38 { 39 if (ruleToUpgrade) 40 { 41 return std::move(ruleToUpgrade); 42 } 43 return {}; 44 } 45 46 virtual void handle(const Request& /*req*/, 47 const std::shared_ptr<bmcweb::AsyncResp>&, 48 const std::vector<std::string>&) = 0; handleUpgrade(const Request &,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,boost::asio::ip::tcp::socket &&)49 virtual void handleUpgrade( 50 const Request& /*req*/, 51 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 52 boost::asio::ip::tcp::socket&& /*adaptor*/) 53 { 54 asyncResp->res.result(boost::beast::http::status::not_found); 55 } 56 handleUpgrade(const Request &,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &&)57 virtual void handleUpgrade( 58 const Request& /*req*/, 59 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 60 boost::asio::ssl::stream<boost::asio::ip::tcp::socket>&& /*adaptor*/) 61 { 62 asyncResp->res.result(boost::beast::http::status::not_found); 63 } 64 getMethods() const65 size_t getMethods() const 66 { 67 return methodsBitfield; 68 } 69 checkPrivileges(const redfish::Privileges & userPrivileges)70 bool checkPrivileges(const redfish::Privileges& userPrivileges) 71 { 72 // If there are no privileges assigned, assume no privileges 73 // required 74 if (privilegesSet.empty()) 75 { 76 return true; 77 } 78 79 for (const redfish::Privileges& requiredPrivileges : privilegesSet) 80 { 81 if (userPrivileges.isSupersetOf(requiredPrivileges)) 82 { 83 return true; 84 } 85 } 86 return false; 87 } 88 89 size_t methodsBitfield{1 << static_cast<size_t>(HttpVerb::Get)}; 90 static_assert(std::numeric_limits<decltype(methodsBitfield)>::digits > 91 static_cast<int>(HttpVerb::Max), 92 "Not enough bits to store bitfield"); 93 94 bool isNotFound = false; 95 bool isMethodNotAllowed = false; 96 bool isUpgrade = false; 97 98 std::vector<redfish::Privileges> privilegesSet; 99 100 std::string rule; 101 102 std::unique_ptr<BaseRule> ruleToUpgrade; 103 104 friend class Router; 105 template <typename T> 106 friend struct RuleParameterTraits; 107 }; 108 109 } // namespace crow 110