summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crow/include/crow/app.h2
-rw-r--r--crow/include/crow/routing.h252
-rw-r--r--include/http_utility.hpp2
-rw-r--r--include/openbmc_dbus_rest.hpp29
-rw-r--r--redfish-core/include/node.hpp125
-rw-r--r--redfish-core/include/privileges.hpp4
-rw-r--r--redfish-core/include/redfish.hpp5
-rw-r--r--redfish-core/lib/account_service.hpp1
-rw-r--r--redfish-core/lib/redfish_sessions.hpp1
9 files changed, 292 insertions, 129 deletions
diff --git a/crow/include/crow/app.h b/crow/include/crow/app.h
index f1f3687723..95bbaed0bc 100644
--- a/crow/include/crow/app.h
+++ b/crow/include/crow/app.h
@@ -1,5 +1,7 @@
#pragma once
+#include "privileges.hpp"
+
#include <chrono>
#include <cstdint>
#include <functional>
diff --git a/crow/include/crow/routing.h b/crow/include/crow/routing.h
index 746e115894..e657e2ef1b 100644
--- a/crow/include/crow/routing.h
+++ b/crow/include/crow/routing.h
@@ -1,7 +1,9 @@
#pragma once
-#include "boost/container/flat_map.hpp"
+#include "privileges.hpp"
+#include <boost/container/flat_map.hpp>
+#include <boost/container/small_vector.hpp>
#include <boost/lexical_cast.hpp>
#include <cerrno>
#include <cstdint>
@@ -21,10 +23,14 @@
namespace crow
{
+
+constexpr int maxHttpVerbCount =
+ static_cast<int>(boost::beast::http::verb::unlink);
+
class BaseRule
{
public:
- BaseRule(std::string rule) : rule(std::move(rule))
+ BaseRule(std::string thisRule) : rule(std::move(thisRule))
{
}
@@ -62,9 +68,29 @@ class BaseRule
return methodsBitfield;
}
- protected:
+ bool checkPrivileges(const redfish::Privileges& userPrivileges)
+ {
+ // If there are no privileges assigned, assume no privileges
+ // required
+ if (privilegesSet.empty())
+ {
+ return true;
+ }
+
+ for (const redfish::Privileges& requiredPrivileges : privilegesSet)
+ {
+ if (userPrivileges.isSupersetOf(requiredPrivileges))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
uint32_t methodsBitfield{1 << (int)boost::beast::http::verb::get};
+ std::vector<redfish::Privileges> privilegesSet;
+
std::string rule;
std::string nameStr;
@@ -178,16 +204,11 @@ template <typename Func, typename... ArgsWrapped> struct Wrapped
const Request&>::value,
int>::type = 0)
{
- handler = (
-#ifdef BMCWEB_CAN_USE_CPP14
- [f = std::move(f)]
-#else
- [f]
-#endif
- (const Request&, Response& res, Args... args) {
- res = Response(f(args...));
- res.end();
- });
+ handler = [f = std::move(f)](const Request&, Response& res,
+ Args... args) {
+ res = Response(f(args...));
+ res.end();
+ };
}
template <typename Req, typename... Args> struct ReqHandlerWrapper
@@ -362,7 +383,7 @@ template <typename T> struct RuleParameterTraits
using self_t = T;
WebSocketRule& websocket()
{
- auto p = new WebSocketRule(((self_t*)this)->rule);
+ WebSocketRule* p = new WebSocketRule(((self_t*)this)->rule);
((self_t*)this)->ruleToUpgrade.reset(p);
return *p;
}
@@ -386,6 +407,23 @@ template <typename T> struct RuleParameterTraits
((self_t*)this)->methodsBitfield |= 1 << (int)method;
return (self_t&)*this;
}
+
+ template <typename... MethodArgs>
+ self_t& requires(std::initializer_list<const char*> l)
+ {
+ ((self_t*)this)->privilegesSet.emplace_back(l);
+ return (self_t&)*this;
+ }
+
+ template <typename... MethodArgs>
+ self_t& requires(const std::vector<redfish::Privileges>& p)
+ {
+ for (const redfish::Privileges& privilege : p)
+ {
+ ((self_t*)this)->privilegesSet.emplace_back(privilege);
+ }
+ return (self_t&)*this;
+ }
};
class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule>
@@ -547,7 +585,8 @@ class TaggedRule : public BaseRule,
std::is_same<void, decltype(f(std::declval<crow::Request>(),
std::declval<crow::Response&>(),
std::declval<Args>()...))>::value,
- "Handler function with response argument should have void return "
+ "Handler function with response argument should have void "
+ "return "
"type");
handler = std::move(f);
@@ -599,7 +638,7 @@ class Trie
private:
void optimizeNode(Node* node)
{
- for (auto x : node->paramChildrens)
+ for (unsigned int x : node->paramChildrens)
{
if (!x)
continue;
@@ -609,7 +648,7 @@ class Trie
if (node->children.empty())
return;
bool mergeWithChild = true;
- for (auto& kv : node->children)
+ for (const std::pair<std::string, unsigned>& kv : node->children)
{
Node* child = &nodes[kv.second];
if (!child->isSimpleNode())
@@ -621,10 +660,11 @@ class Trie
if (mergeWithChild)
{
decltype(node->children) merged;
- for (auto& kv : node->children)
+ for (const std::pair<std::string, unsigned>& kv : node->children)
{
Node* child = &nodes[kv.second];
- for (auto& childKv : child->children)
+ for (const std::pair<std::string, unsigned>& childKv :
+ child->children)
{
merged[kv.first + childKv.first] = childKv.second;
}
@@ -634,7 +674,7 @@ class Trie
}
else
{
- for (auto& kv : node->children)
+ for (const std::pair<std::string, unsigned>& kv : node->children)
{
Node* child = &nodes[kv.second];
optimizeNode(child);
@@ -658,13 +698,13 @@ class Trie
void findRouteIndexes(const std::string& req_url,
std::vector<unsigned>& route_indexes,
- const Node* node = nullptr, unsigned pos = 0)
+ const Node* node = nullptr, unsigned pos = 0) const
{
if (node == nullptr)
{
node = head();
}
- for (auto& kv : node->children)
+ for (const std::pair<std::string, unsigned>& kv : node->children)
{
const std::string& fragment = kv.first;
const Node* child = &nodes[kv.second];
@@ -725,7 +765,7 @@ class Trie
if (errno != ERANGE && eptr != req_url.data() + pos)
{
params->intParams.push_back(value);
- auto ret =
+ std::pair<unsigned, RoutingParams> ret =
find(req_url,
&nodes[node->paramChildrens[(int)ParamType::INT]],
eptr - req_url.data(), params);
@@ -747,7 +787,7 @@ class Trie
if (errno != ERANGE && eptr != req_url.data() + pos)
{
params->uintParams.push_back(value);
- auto ret =
+ std::pair<unsigned, RoutingParams> ret =
find(req_url,
&nodes[node->paramChildrens[(int)ParamType::UINT]],
eptr - req_url.data(), params);
@@ -768,7 +808,7 @@ class Trie
if (errno != ERANGE && eptr != req_url.data() + pos)
{
params->doubleParams.push_back(value);
- auto ret = find(
+ std::pair<unsigned, RoutingParams> ret = find(
req_url,
&nodes[node->paramChildrens[(int)ParamType::DOUBLE]],
eptr - req_url.data(), params);
@@ -791,7 +831,7 @@ class Trie
{
params->stringParams.emplace_back(
req_url.substr(pos, epos - pos));
- auto ret =
+ std::pair<unsigned, RoutingParams> ret =
find(req_url,
&nodes[node->paramChildrens[(int)ParamType::STRING]],
epos, params);
@@ -808,7 +848,7 @@ class Trie
{
params->stringParams.emplace_back(
req_url.substr(pos, epos - pos));
- auto ret = find(
+ std::pair<unsigned, RoutingParams> ret = find(
req_url, &nodes[node->paramChildrens[(int)ParamType::PATH]],
epos, params);
updateFound(ret);
@@ -816,14 +856,15 @@ class Trie
}
}
- for (auto& kv : node->children)
+ for (const std::pair<std::string, unsigned>& kv : node->children)
{
const std::string& fragment = kv.first;
const Node* child = &nodes[kv.second];
if (req_url.compare(pos, fragment.size(), fragment) == 0)
{
- auto ret = find(req_url, child, pos + fragment.size(), params);
+ std::pair<unsigned, RoutingParams> ret =
+ find(req_url, child, pos + fragment.size(), params);
updateFound(ret);
}
}
@@ -840,31 +881,29 @@ class Trie
char c = url[i];
if (c == '<')
{
- static struct ParamTraits
+ const static std::array<std::pair<ParamType, std::string>, 7>
+ paramTraits = {{
+ {ParamType::INT, "<int>"},
+ {ParamType::UINT, "<uint>"},
+ {ParamType::DOUBLE, "<float>"},
+ {ParamType::DOUBLE, "<double>"},
+ {ParamType::STRING, "<str>"},
+ {ParamType::STRING, "<string>"},
+ {ParamType::PATH, "<path>"},
+ }};
+
+ for (const std::pair<ParamType, std::string>& x : paramTraits)
{
- ParamType type;
- std::string name;
- } paramTraits[] = {
- {ParamType::INT, "<int>"},
- {ParamType::UINT, "<uint>"},
- {ParamType::DOUBLE, "<float>"},
- {ParamType::DOUBLE, "<double>"},
- {ParamType::STRING, "<str>"},
- {ParamType::STRING, "<string>"},
- {ParamType::PATH, "<path>"},
- };
-
- for (auto& x : paramTraits)
- {
- if (url.compare(i, x.name.size(), x.name) == 0)
+ if (url.compare(i, x.second.size(), x.second) == 0)
{
- if (!nodes[idx].paramChildrens[(int)x.type])
+ if (!nodes[idx].paramChildrens[(int)x.first])
{
- auto newNodeIdx = newNode();
- nodes[idx].paramChildrens[(int)x.type] = newNodeIdx;
+ unsigned newNodeIdx = newNode();
+ nodes[idx].paramChildrens[(int)x.first] =
+ newNodeIdx;
}
- idx = nodes[idx].paramChildrens[(int)x.type];
- i += x.name.size();
+ idx = nodes[idx].paramChildrens[(int)x.first];
+ i += x.second.size();
break;
}
}
@@ -876,7 +915,7 @@ class Trie
std::string piece(&c, 1);
if (!nodes[idx].children.count(piece))
{
- auto newNodeIdx = newNode();
+ unsigned newNodeIdx = newNode();
nodes[idx].children.emplace(piece, newNodeIdx);
}
idx = nodes[idx].children[piece];
@@ -921,7 +960,7 @@ class Trie
debugNodePrint(&nodes[n->paramChildrens[i]], level + 1);
}
}
- for (auto& kv : n->children)
+ for (const std::pair<std::string, unsigned>& kv : n->children)
{
BMCWEB_LOG_DEBUG
<< std::string(2 * level, ' ') /*<< "(" << kv.second << ") "*/
@@ -959,7 +998,7 @@ class Trie
class Router
{
public:
- Router() : rules(2)
+ Router()
{
}
@@ -968,7 +1007,7 @@ class Router
std::unique_ptr<DynamicRule> ruleObject =
std::make_unique<DynamicRule>(rule);
DynamicRule* ptr = ruleObject.get();
- internalAddRuleObject(rule, std::move(ruleObject));
+ allRules.emplace_back(std::move(ruleObject));
return *ptr;
}
@@ -981,45 +1020,67 @@ class Router
TaggedRule>;
std::unique_ptr<RuleT> ruleObject = std::make_unique<RuleT>(rule);
RuleT* ptr = ruleObject.get();
-
- internalAddRuleObject(rule, std::move(ruleObject));
+ allRules.emplace_back(std::move(ruleObject));
return *ptr;
}
- void internalAddRuleObject(const std::string& rule,
- std::unique_ptr<BaseRule> ruleObject)
+ void internalAddRuleObject(const std::string& rule, BaseRule* ruleObject)
{
- rules.emplace_back(std::move(ruleObject));
- trie.add(rule, rules.size() - 1);
-
- // directory case:
- // request to `/about' url matches `/about/' rule
- if (rule.size() > 2 && rule.back() == '/')
+ if (ruleObject == nullptr)
+ {
+ return;
+ }
+ for (uint32_t method = 0, method_bit = 1; method < maxHttpVerbCount;
+ method++, method_bit <<= 1)
{
- trie.add(rule.substr(0, rule.size() - 1), rules.size() - 1);
+ if (ruleObject->methodsBitfield & method_bit)
+ {
+ perMethods[method].rules.emplace_back(ruleObject);
+ perMethods[method].trie.add(
+ rule, perMethods[method].rules.size() - 1);
+ // directory case:
+ // request to `/about' url matches `/about/' rule
+ if (rule.size() > 2 && rule.back() == '/')
+ {
+ perMethods[method].trie.add(
+ rule.substr(0, rule.size() - 1),
+ perMethods[method].rules.size() - 1);
+ }
+ }
}
}
void validate()
{
- trie.validate();
- for (auto& rule : rules)
+ for (std::unique_ptr<BaseRule>& rule : allRules)
{
if (rule)
{
- auto upgraded = rule->upgrade();
+ std::unique_ptr<BaseRule> upgraded = rule->upgrade();
if (upgraded)
rule = std::move(upgraded);
rule->validate();
+ internalAddRuleObject(rule->rule, rule.get());
}
}
+ for (PerMethod& perMethod : perMethods)
+ {
+ perMethod.trie.validate();
+ }
}
template <typename Adaptor>
void handleUpgrade(const Request& req, Response& res, Adaptor&& adaptor)
{
- auto found = trie.find(req.url);
+ if (static_cast<int>(req.method()) >= perMethods.size())
+ return;
+
+ PerMethod& perMethod = perMethods[(int)req.method()];
+ Trie& trie = perMethod.trie;
+ std::vector<BaseRule*>& rules = perMethod.rules;
+
+ const std::pair<unsigned, RoutingParams>& found = trie.find(req.url);
unsigned ruleIndex = found.first;
if (!ruleIndex)
{
@@ -1097,7 +1158,13 @@ class Router
void handle(const Request& req, Response& res)
{
- auto found = trie.find(req.url);
+ if ((int)req.method() >= perMethods.size())
+ return;
+ PerMethod& perMethod = perMethods[(int)req.method()];
+ Trie& trie = perMethod.trie;
+ std::vector<BaseRule*>& rules = perMethod.rules;
+
+ const std::pair<unsigned, RoutingParams>& found = trie.find(req.url);
unsigned ruleIndex = found.first;
@@ -1150,6 +1217,19 @@ class Router
<< (uint32_t)req.method() << " / "
<< rules[ruleIndex]->getMethods();
+ // TODO: load user privileges from configuration as soon as its
+ // available now we are granting all privileges to everyone.
+ redfish::Privileges userPrivileges{"Login", "ConfigureManager",
+ "ConfigureSelf", "ConfigureUsers",
+ "ConfigureComponents"};
+
+ if (!rules[ruleIndex]->checkPrivileges(userPrivileges))
+ {
+ res.result(boost::beast::http::status::method_not_allowed);
+ res.end();
+ return;
+ }
+
// any uncaught exceptions become 500s
try
{
@@ -1175,23 +1255,41 @@ class Router
void debugPrint()
{
- trie.debugPrint();
+ for (int i = 0; i < perMethods.size(); i++)
+ {
+ BMCWEB_LOG_DEBUG << methodName((boost::beast::http::verb)i);
+ perMethods[i].trie.debugPrint();
+ }
}
std::vector<const std::string*> getRoutes(const std::string& parent)
{
- std::vector<unsigned> x;
std::vector<const std::string*> ret;
- trie.findRouteIndexes(parent, x);
- for (unsigned index : x)
+
+ for (const PerMethod& pm : perMethods)
{
- ret.push_back(&rules[index]->rule);
+ std::vector<unsigned> x;
+ pm.trie.findRouteIndexes(parent, x);
+ for (unsigned index : x)
+ {
+ ret.push_back(&pm.rules[index]->rule);
+ }
}
return ret;
}
private:
- std::vector<std::unique_ptr<BaseRule>> rules;
- Trie trie;
+ struct PerMethod
+ {
+ std::vector<BaseRule*> rules;
+ Trie trie;
+ // rule index 0, 1 has special meaning; preallocate it to avoid
+ // duplication.
+ PerMethod() : rules(2)
+ {
+ }
+ };
+ std::array<PerMethod, maxHttpVerbCount> perMethods;
+ std::vector<std::unique_ptr<BaseRule>> allRules;
};
} // namespace crow
diff --git a/include/http_utility.hpp b/include/http_utility.hpp
index e2b1a11f64..b20952b438 100644
--- a/include/http_utility.hpp
+++ b/include/http_utility.hpp
@@ -1,6 +1,8 @@
#pragma once
#include <boost/algorithm/string.hpp>
+#include "crow/http_request.h"
+
namespace http_helpers
{
inline bool requestPrefersHtml(const crow::Request& req)
diff --git a/include/openbmc_dbus_rest.hpp b/include/openbmc_dbus_rest.hpp
index ab35bb2efc..9f7a85508b 100644
--- a/include/openbmc_dbus_rest.hpp
+++ b/include/openbmc_dbus_rest.hpp
@@ -1982,6 +1982,7 @@ inline void handleDBusUrl(const crow::Request &req, crow::Response &res,
template <typename... Middlewares> void requestRoutes(Crow<Middlewares...> &app)
{
BMCWEB_ROUTE(app, "/bus/")
+ .requires({"Login"})
.methods("GET"_method)(
[](const crow::Request &req, crow::Response &res) {
res.jsonValue = {{"busses", {{{"name", "system"}}}},
@@ -1990,6 +1991,7 @@ template <typename... Middlewares> void requestRoutes(Crow<Middlewares...> &app)
});
BMCWEB_ROUTE(app, "/bus/system/")
+ .requires({"Login"})
.methods("GET"_method)(
[](const crow::Request &req, crow::Response &res) {
auto myCallback = [&res](const boost::system::error_code ec,
@@ -2018,13 +2020,23 @@ template <typename... Middlewares> void requestRoutes(Crow<Middlewares...> &app)
});
BMCWEB_ROUTE(app, "/list/")
+ .requires({"Login"})
.methods("GET"_method)(
[](const crow::Request &req, crow::Response &res) {
handleList(res, "/");
});
BMCWEB_ROUTE(app, "/xyz/<path>")
- .methods("GET"_method, "PUT"_method, "POST"_method, "DELETE"_method)(
+ .requires({"Login"})
+ .methods("GET"_method)([](const crow::Request &req, crow::Response &res,
+ const std::string &path) {
+ std::string objectPath = "/xyz/" + path;
+ handleDBusUrl(req, res, objectPath);
+ });
+
+ BMCWEB_ROUTE(app, "/xyz/<path>")
+ .requires({"ConfigureComponents", "ConfigureManager"})
+ .methods("PUT"_method, "POST"_method, "DELETE"_method)(
[](const crow::Request &req, crow::Response &res,
const std::string &path) {
std::string objectPath = "/xyz/" + path;
@@ -2032,14 +2044,24 @@ template <typename... Middlewares> void requestRoutes(Crow<Middlewares...> &app)
});
BMCWEB_ROUTE(app, "/org/<path>")
- .methods("GET"_method, "PUT"_method, "POST"_method, "DELETE"_method)(
+ .requires({"Login"})
+ .methods("GET"_method)([](const crow::Request &req, crow::Response &res,
+ const std::string &path) {
+ std::string objectPath = "/xyz/" + path;
+ handleDBusUrl(req, res, objectPath);
+ });
+
+ BMCWEB_ROUTE(app, "/org/<path>")
+ .requires({"ConfigureComponents", "ConfigureManager"})
+ .methods("PUT"_method, "POST"_method, "DELETE"_method)(
[](const crow::Request &req, crow::Response &res,
const std::string &path) {
- std::string objectPath = "/org/" + path;
+ std::string objectPath = "/xyz/" + path;
handleDBusUrl(req, res, objectPath);
});
BMCWEB_ROUTE(app, "/download/dump/<str>/")
+ .requires({"ConfigureManager"})
.methods("GET"_method)([](const crow::Request &req, crow::Response &res,
const std::string &dumpId) {
std::regex validFilename("^[\\w\\- ]+(\\.?[\\w\\- ]*)$");
@@ -2083,6 +2105,7 @@ template <typename... Middlewares> void requestRoutes(Crow<Middlewares...> &app)
});
BMCWEB_ROUTE(app, "/bus/system/<str>/")
+ .requires({"Login"})
.methods("GET"_method)([](const crow::Request &req, crow::Response &res,
const std::string &Connection) {
introspectObjects(Connection, "/",
diff --git a/redfish-core/include/node.hpp b/redfish-core/include/node.hpp
index 8e94a6f011..58195279e1 100644
--- a/redfish-core/include/node.hpp
+++ b/redfish-core/include/node.hpp
@@ -57,20 +57,88 @@ class Node
template <typename... Params>
Node(CrowApp& app, std::string&& entityUrl, Params... params)
{
- app.routeDynamic(entityUrl.c_str())
- .methods("GET"_method, "PATCH"_method, "POST"_method,
- "DELETE"_method)([&](const crow::Request& req,
- crow::Response& res,
- Params... params) {
- std::vector<std::string> paramVec = {params...};
- dispatchRequest(app, req, res, paramVec);
- });
+ 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,
@@ -100,47 +168,6 @@ class Node
res.result(boost::beast::http::status::method_not_allowed);
res.end();
}
-
- private:
- void dispatchRequest(CrowApp& app, const crow::Request& req,
- crow::Response& res,
- const std::vector<std::string>& params)
- {
- auto ctx =
- app.template getContext<crow::token_authorization::Middleware>(req);
-
- if (!isMethodAllowedForUser(req.method(), entityPrivileges,
- ctx.session->username))
- {
- res.result(boost::beast::http::status::method_not_allowed);
- res.end();
- return;
- }
-
- switch (req.method())
- {
- case "GET"_method:
- doGet(res, req, params);
- break;
-
- case "PATCH"_method:
- doPatch(res, req, params);
- break;
-
- case "POST"_method:
- doPost(res, req, params);
- break;
-
- case "DELETE"_method:
- doDelete(res, req, params);
- break;
-
- default:
- res.result(boost::beast::http::status::not_found);
- res.end();
- }
- return;
- }
};
} // namespace redfish
diff --git a/redfish-core/include/privileges.hpp b/redfish-core/include/privileges.hpp
index 3b20c9fda8..ca44551835 100644
--- a/redfish-core/include/privileges.hpp
+++ b/redfish-core/include/privileges.hpp
@@ -15,7 +15,11 @@
*/
#pragma once
+#include <crow/logging.h>
+
+#include <array>
#include <bitset>
+#include <boost/beast/http/verb.hpp>
#include <boost/container/flat_map.hpp>
#include <cstdint>
#include <vector>
diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
index 2a61c52b48..36b50e87c7 100644
--- a/redfish-core/include/redfish.hpp
+++ b/redfish-core/include/redfish.hpp
@@ -103,6 +103,11 @@ class RedfishService
nodes.emplace_back(std::make_unique<SystemsCollection>(app));
nodes.emplace_back(std::make_unique<Systems>(app));
nodes.emplace_back(std::make_unique<SystemActionsReset>(app));
+
+ for (const auto& node : nodes)
+ {
+ node->initPrivileges();
+ }
}
private:
diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp
index 9365ebb06f..a5c501d1b6 100644
--- a/redfish-core/lib/account_service.hpp
+++ b/redfish-core/lib/account_service.hpp
@@ -224,6 +224,7 @@ class AccountService : public Node
}
}
};
+
class AccountsCollection : public Node
{
public:
diff --git a/redfish-core/lib/redfish_sessions.hpp b/redfish-core/lib/redfish_sessions.hpp
index 59805a0c46..d4085af9a7 100644
--- a/redfish-core/lib/redfish_sessions.hpp
+++ b/redfish-core/lib/redfish_sessions.hpp
@@ -139,6 +139,7 @@ class SessionCollection : public Node
res.jsonValue["Members"].push_back(
{{"@odata.id", "/redfish/v1/SessionService/Sessions/" + *uid}});
}
+ res.jsonValue["Members@odata.count"] = sessionIds.size();
res.jsonValue["@odata.type"] = "#SessionCollection.SessionCollection";
res.jsonValue["@odata.id"] = "/redfish/v1/SessionService/Sessions/";
res.jsonValue["@odata.context"] =