1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
/*
// 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 "crow.h"
namespace redfish {
/**
* @brief Abstract class used for implementing Redfish nodes.
*
*/
class Node {
public:
template <typename CrowApp, typename... Params>
Node(CrowApp& app, const PrivilegeProvider& privilegeProvider,
const std::string& entityType, const std::string& entityUrl,
Params... params)
: entityPrivileges(privilegeProvider.getPrivilegesRequiredByEntity(
entityUrl, entityType)) {
app.route_dynamic(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);
});
}
virtual ~Node() = default;
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) = 0;
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.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.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.end();
}
private:
template <typename CrowApp>
void dispatchRequest(CrowApp& app, const crow::request& req,
crow::response& res,
const std::vector<std::string>& params) {
auto ctx =
app.template get_context<crow::TokenAuthorization::Middleware>(req);
if (!entityPrivileges.isMethodAllowedForUser(req.method,
ctx.session->username)) {
res.code = static_cast<int>(HttpRespCode::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.code = static_cast<int>(HttpRespCode::NOT_FOUND);
res.end();
}
return;
}
const EntityPrivileges entityPrivileges;
};
template <typename CrowApp>
void getRedfishSubRoutes(CrowApp& app, const std::string& url,
nlohmann::json& j) {
std::vector<const std::string*> routes = app.get_routes(url);
for (auto route : routes) {
auto redfishSubRoute =
route->substr(url.size(), route->size() - url.size() - 1);
// Exclude: - exact matches,
// - metadata urls starting with "$",
// - urls at the same level
if (!redfishSubRoute.empty() && redfishSubRoute[0] != '$' &&
redfishSubRoute.find('/') == std::string::npos) {
j[redfishSubRoute] = nlohmann::json{{"@odata.id", *route}};
}
}
}
} // namespace redfish
|