blob: f91c22b4b3e5d898a9e79084ceab2541377b4150 [file] [log] [blame]
Borawski.Lukasz86e1b662018-01-19 14:22:14 +01001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
Ed Tanous04e438c2020-10-03 08:06:26 -070018#include "http_request.hpp"
19#include "http_response.hpp"
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010020#include "privileges.hpp"
Ed Tanous1abe55e2018-09-05 08:30:59 -070021
Ed Tanousa0803ef2018-08-29 13:29:23 -070022#include <error_messages.hpp>
23
Gunnar Mills1214b7e2020-06-04 10:11:30 -050024#include <vector>
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010025
Ed Tanous1abe55e2018-09-05 08:30:59 -070026namespace redfish
27{
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010028
29/**
Kowalski, Kamil588c3f02018-04-03 14:55:27 +020030 * AsyncResp
31 * Gathers data needed for response processing after async calls are done
32 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070033class AsyncResp
34{
35 public:
36 AsyncResp(crow::Response& response) : res(response)
Gunnar Mills1214b7e2020-06-04 10:11:30 -050037 {}
Kowalski, Kamil588c3f02018-04-03 14:55:27 +020038
Ed Tanous1abe55e2018-09-05 08:30:59 -070039 ~AsyncResp()
40 {
41 res.end();
42 }
Kowalski, Kamil588c3f02018-04-03 14:55:27 +020043
Ed Tanous1abe55e2018-09-05 08:30:59 -070044 crow::Response& res;
Kowalski, Kamil588c3f02018-04-03 14:55:27 +020045};
46
47/**
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010048 * @brief Abstract class used for implementing Redfish nodes.
49 *
50 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070051class Node
52{
Ed Tanous4df1bee2021-03-24 08:23:03 -070053 private:
54 bool redfishPreChecks(const crow::Request& req, crow::Response& res)
55 {
56 std::string_view odataHeader = req.getHeaderValue("OData-Version");
57 if (odataHeader.empty())
58 {
59 // Clients aren't required to provide odata version
60 return true;
61 }
62 if (odataHeader != "4.0")
63 {
64 redfish::messages::preconditionFailed(res);
65 res.end();
66 return false;
67 }
68
69 res.addHeader("OData-Version", "4.0");
70 return true;
71 }
72
Ed Tanous1abe55e2018-09-05 08:30:59 -070073 public:
74 template <typename... Params>
Ed Tanouscb13a392020-07-25 19:02:03 +000075 Node(App& app, std::string&& entityUrl, [[maybe_unused]] Params... paramsIn)
Ed Tanous1abe55e2018-09-05 08:30:59 -070076 {
Tanousf00032d2018-11-05 01:18:10 -030077 crow::DynamicRule& get = app.routeDynamic(entityUrl.c_str());
78 getRule = &get;
Ed Tanousb41187f2019-10-24 16:30:02 -070079 get.methods(boost::beast::http::verb::get)(
80 [this](const crow::Request& req, crow::Response& res,
81 Params... params) {
Ed Tanous4df1bee2021-03-24 08:23:03 -070082 if (!redfishPreChecks(req, res))
83 {
84 return;
85 }
Ed Tanousb41187f2019-10-24 16:30:02 -070086 std::vector<std::string> paramVec = {params...};
87 doGet(res, req, paramVec);
88 });
Tanousf00032d2018-11-05 01:18:10 -030089
90 crow::DynamicRule& patch = app.routeDynamic(entityUrl.c_str());
91 patchRule = &patch;
Ed Tanousb41187f2019-10-24 16:30:02 -070092 patch.methods(boost::beast::http::verb::patch)(
93 [this](const crow::Request& req, crow::Response& res,
94 Params... params) {
Ed Tanous4df1bee2021-03-24 08:23:03 -070095 if (!redfishPreChecks(req, res))
96 {
97 return;
98 }
Ed Tanousb41187f2019-10-24 16:30:02 -070099 std::vector<std::string> paramVec = {params...};
100 doPatch(res, req, paramVec);
101 });
Tanousf00032d2018-11-05 01:18:10 -0300102
103 crow::DynamicRule& post = app.routeDynamic(entityUrl.c_str());
104 postRule = &post;
Ed Tanousb41187f2019-10-24 16:30:02 -0700105 post.methods(boost::beast::http::verb::post)(
106 [this](const crow::Request& req, crow::Response& res,
107 Params... params) {
Ed Tanous4df1bee2021-03-24 08:23:03 -0700108 if (!redfishPreChecks(req, res))
109 {
110 return;
111 }
Ed Tanousb41187f2019-10-24 16:30:02 -0700112 std::vector<std::string> paramVec = {params...};
113 doPost(res, req, paramVec);
114 });
Tanousf00032d2018-11-05 01:18:10 -0300115
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200116 crow::DynamicRule& put = app.routeDynamic(entityUrl.c_str());
117 putRule = &put;
118 put.methods(boost::beast::http::verb::put)(
119 [this](const crow::Request& req, crow::Response& res,
120 Params... params) {
Ed Tanous4df1bee2021-03-24 08:23:03 -0700121 if (!redfishPreChecks(req, res))
122 {
123 return;
124 }
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200125 std::vector<std::string> paramVec = {params...};
126 doPut(res, req, paramVec);
127 });
128
Ed Tanous2c70f802020-09-28 14:29:23 -0700129 crow::DynamicRule& deleteR = app.routeDynamic(entityUrl.c_str());
130 deleteRule = &deleteR;
131 deleteR.methods(boost::beast::http::verb::delete_)(
Ed Tanousb41187f2019-10-24 16:30:02 -0700132 [this](const crow::Request& req, crow::Response& res,
133 Params... params) {
Ed Tanous4df1bee2021-03-24 08:23:03 -0700134 if (!redfishPreChecks(req, res))
135 {
136 return;
137 }
Ed Tanousb41187f2019-10-24 16:30:02 -0700138 std::vector<std::string> paramVec = {params...};
139 doDelete(res, req, paramVec);
140 });
Tanousf00032d2018-11-05 01:18:10 -0300141 }
142
143 void initPrivileges()
144 {
145 auto it = entityPrivileges.find(boost::beast::http::verb::get);
146 if (it != entityPrivileges.end())
147 {
148 if (getRule != nullptr)
149 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000150 getRule->privileges(it->second);
Tanousf00032d2018-11-05 01:18:10 -0300151 }
152 }
153 it = entityPrivileges.find(boost::beast::http::verb::post);
154 if (it != entityPrivileges.end())
155 {
156 if (postRule != nullptr)
157 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000158 postRule->privileges(it->second);
Tanousf00032d2018-11-05 01:18:10 -0300159 }
160 }
161 it = entityPrivileges.find(boost::beast::http::verb::patch);
162 if (it != entityPrivileges.end())
163 {
164 if (patchRule != nullptr)
165 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000166 patchRule->privileges(it->second);
Tanousf00032d2018-11-05 01:18:10 -0300167 }
168 }
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200169 it = entityPrivileges.find(boost::beast::http::verb::put);
170 if (it != entityPrivileges.end())
171 {
172 if (putRule != nullptr)
173 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000174 putRule->privileges(it->second);
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200175 }
176 }
Tanousf00032d2018-11-05 01:18:10 -0300177 it = entityPrivileges.find(boost::beast::http::verb::delete_);
178 if (it != entityPrivileges.end())
179 {
180 if (deleteRule != nullptr)
181 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000182 deleteRule->privileges(it->second);
Tanousf00032d2018-11-05 01:18:10 -0300183 }
184 }
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +0100185 }
Ed Tanouscbbfa962018-03-13 16:46:28 -0700186
Ed Tanous1abe55e2018-09-05 08:30:59 -0700187 virtual ~Node() = default;
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +0100188
Ed Tanous1abe55e2018-09-05 08:30:59 -0700189 OperationMap entityPrivileges;
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100190
Tanousf00032d2018-11-05 01:18:10 -0300191 crow::DynamicRule* getRule = nullptr;
192 crow::DynamicRule* postRule = nullptr;
193 crow::DynamicRule* patchRule = nullptr;
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200194 crow::DynamicRule* putRule = nullptr;
Tanousf00032d2018-11-05 01:18:10 -0300195 crow::DynamicRule* deleteRule = nullptr;
196
Ed Tanous1abe55e2018-09-05 08:30:59 -0700197 protected:
198 // Node is designed to be an abstract class, so doGet is pure virtual
Ed Tanouscb13a392020-07-25 19:02:03 +0000199 virtual void doGet(crow::Response& res, const crow::Request&,
200 const std::vector<std::string>&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700201 {
202 res.result(boost::beast::http::status::method_not_allowed);
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100203 res.end();
204 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700205
Ed Tanouscb13a392020-07-25 19:02:03 +0000206 virtual void doPatch(crow::Response& res, const crow::Request&,
207 const std::vector<std::string>&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700208 {
209 res.result(boost::beast::http::status::method_not_allowed);
210 res.end();
211 }
212
Ed Tanouscb13a392020-07-25 19:02:03 +0000213 virtual void doPost(crow::Response& res, const crow::Request&,
214 const std::vector<std::string>&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700215 {
216 res.result(boost::beast::http::status::method_not_allowed);
217 res.end();
218 }
219
Ed Tanouscb13a392020-07-25 19:02:03 +0000220 virtual void doPut(crow::Response& res, const crow::Request&,
221 const std::vector<std::string>&)
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200222 {
223 res.result(boost::beast::http::status::method_not_allowed);
224 res.end();
225 }
226
Ed Tanouscb13a392020-07-25 19:02:03 +0000227 virtual void doDelete(crow::Response& res, const crow::Request&,
228 const std::vector<std::string>&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700229 {
230 res.result(boost::beast::http::status::method_not_allowed);
231 res.end();
232 }
Joseph Reynolds900f9492019-11-25 15:37:29 -0600233
Joseph Reynolds3bf4e632020-02-06 14:44:32 -0600234 /* @brief Would the operation be allowed if the user did not have the
235 * ConfigureSelf Privilege? Also honors session.isConfigureSelfOnly.
Joseph Reynolds900f9492019-11-25 15:37:29 -0600236 *
237 * @param req the request
238 *
239 * @returns True if allowed, false otherwise
240 */
241 inline bool isAllowedWithoutConfigureSelf(const crow::Request& req)
242 {
RAJESWARAN THILLAIGOVINDAN61dbeef2019-12-13 04:26:54 -0600243 const std::string& userRole = req.userRole;
244 BMCWEB_LOG_DEBUG << "isAllowedWithoutConfigureSelf for the role "
245 << req.userRole;
Joseph Reynolds3bf4e632020-02-06 14:44:32 -0600246 Privileges effectiveUserPrivileges;
247 if (req.session && req.session->isConfigureSelfOnly)
248 {
249 // The session has no privileges because it is limited to
250 // configureSelfOnly and we are disregarding that privilege.
251 // Note that some operations do not require any privilege.
252 }
253 else
254 {
255 effectiveUserPrivileges = redfish::getUserPrivileges(userRole);
256 effectiveUserPrivileges.resetSinglePrivilege("ConfigureSelf");
257 }
Joseph Reynolds900f9492019-11-25 15:37:29 -0600258 const auto& requiredPrivilegesIt = entityPrivileges.find(req.method());
259 return (requiredPrivilegesIt != entityPrivileges.end()) &&
260 isOperationAllowedWithPrivileges(requiredPrivilegesIt->second,
261 effectiveUserPrivileges);
262 }
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100263};
264
Ed Tanous1abe55e2018-09-05 08:30:59 -0700265} // namespace redfish