blob: 8dbb0c2d70f8cfd362d5ce794a0f15cc1a12b571 [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
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010018#include "privileges.hpp"
19#include "token_authorization_middleware.hpp"
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010020#include "webserver_common.hpp"
Ed Tanous1abe55e2018-09-05 08:30:59 -070021
Borawski.Lukaszb6df6dc2018-01-24 10:20:45 +010022#include "crow.h"
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010023
Ed Tanous1abe55e2018-09-05 08:30:59 -070024namespace redfish
25{
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010026
27/**
Kowalski, Kamil588c3f02018-04-03 14:55:27 +020028 * AsyncResp
29 * Gathers data needed for response processing after async calls are done
30 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070031class AsyncResp
32{
33 public:
34 AsyncResp(crow::Response& response) : res(response)
35 {
36 }
Kowalski, Kamil588c3f02018-04-03 14:55:27 +020037
Ed Tanous1abe55e2018-09-05 08:30:59 -070038 ~AsyncResp()
39 {
40 res.end();
41 }
Kowalski, Kamil588c3f02018-04-03 14:55:27 +020042
Ed Tanous1abe55e2018-09-05 08:30:59 -070043 crow::Response& res;
Kowalski, Kamil588c3f02018-04-03 14:55:27 +020044};
45
46/**
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010047 * @brief Abstract class used for implementing Redfish nodes.
48 *
49 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070050class Node
51{
52 public:
53 template <typename... Params>
54 Node(CrowApp& app, std::string&& entityUrl, Params... params)
55 {
56 app.routeDynamic(entityUrl.c_str())
57 .methods("GET"_method, "PATCH"_method, "POST"_method,
58 "DELETE"_method)([&](const crow::Request& req,
59 crow::Response& res,
60 Params... params) {
61 std::vector<std::string> paramVec = {params...};
62 dispatchRequest(app, req, res, paramVec);
63 });
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010064 }
Ed Tanouscbbfa962018-03-13 16:46:28 -070065
Ed Tanous1abe55e2018-09-05 08:30:59 -070066 virtual ~Node() = default;
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010067
Ed Tanous1abe55e2018-09-05 08:30:59 -070068 const std::string* getUrl() const
69 {
70 auto odataId = json.find("@odata.id");
71 if (odataId == json.end())
72 {
73 return nullptr;
74 }
75
76 return odataId->get_ptr<const std::string*>();
Ed Tanouscbbfa962018-03-13 16:46:28 -070077 }
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010078
Ed Tanous1abe55e2018-09-05 08:30:59 -070079 /**
80 * @brief Inserts subroute fields into for the node's json in the form:
81 * "subroute_name" : { "odata.id": "node_url/subroute_name/" }
82 * Excludes metadata urls starting with "$" and child urls having
83 * more than one level.
84 *
85 * @return None
86 */
87 void getSubRoutes(const std::vector<std::unique_ptr<Node>>& allNodes)
88 {
89 const std::string* url = getUrl();
90 if (url == nullptr)
91 {
92 // BMCWEB_LOG_CRITICAL << "Unable to get url for route";
93 return;
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010094 }
95
Ed Tanous1abe55e2018-09-05 08:30:59 -070096 for (const auto& node : allNodes)
97 {
98 const std::string* route = node->getUrl();
99 if (route == nullptr)
100 {
101 // BMCWEB_LOG_CRITICAL << "Unable to get url for route";
102 continue;
103 }
104 if (boost::starts_with(*route, *url))
105 {
106 std::string subRoute = route->substr(url->size());
107 if (subRoute.empty())
108 {
109 continue;
110 }
111
112 if (boost::starts_with(subRoute, "/"))
113 {
114 subRoute.erase(0, 1);
115 }
116
117 if (boost::ends_with(subRoute, "/"))
118 {
119 subRoute.pop_back();
120 }
121
122 if (!boost::starts_with(subRoute, "$") &&
123 subRoute.find('/') == std::string::npos)
124 {
125 json[subRoute] = nlohmann::json{{"@odata.id", *route}};
126 }
127 }
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +0100128 }
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100129 }
130
Ed Tanous1abe55e2018-09-05 08:30:59 -0700131 OperationMap entityPrivileges;
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100132
Ed Tanous1abe55e2018-09-05 08:30:59 -0700133 protected:
134 // Node is designed to be an abstract class, so doGet is pure virtual
135 virtual void doGet(crow::Response& res, const crow::Request& req,
136 const std::vector<std::string>& params)
137 {
138 res.result(boost::beast::http::status::method_not_allowed);
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100139 res.end();
140 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700141
142 virtual void doPatch(crow::Response& res, const crow::Request& req,
143 const std::vector<std::string>& params)
144 {
145 res.result(boost::beast::http::status::method_not_allowed);
146 res.end();
147 }
148
149 virtual void doPost(crow::Response& res, const crow::Request& req,
150 const std::vector<std::string>& params)
151 {
152 res.result(boost::beast::http::status::method_not_allowed);
153 res.end();
154 }
155
156 virtual void doDelete(crow::Response& res, const crow::Request& req,
157 const std::vector<std::string>& params)
158 {
159 res.result(boost::beast::http::status::method_not_allowed);
160 res.end();
161 }
162
163 nlohmann::json json;
164
165 private:
166 void dispatchRequest(CrowApp& app, const crow::Request& req,
167 crow::Response& res,
168 const std::vector<std::string>& params)
169 {
170 auto ctx =
171 app.template getContext<crow::token_authorization::Middleware>(req);
172
173 if (!isMethodAllowedForUser(req.method(), entityPrivileges,
174 ctx.session->username))
175 {
176 res.result(boost::beast::http::status::method_not_allowed);
177 res.end();
178 return;
179 }
180
181 switch (req.method())
182 {
183 case "GET"_method:
184 doGet(res, req, params);
185 break;
186
187 case "PATCH"_method:
188 doPatch(res, req, params);
189 break;
190
191 case "POST"_method:
192 doPost(res, req, params);
193 break;
194
195 case "DELETE"_method:
196 doDelete(res, req, params);
197 break;
198
199 default:
200 res.result(boost::beast::http::status::not_found);
201 res.end();
202 }
203 return;
204 }
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100205};
206
Ed Tanous1abe55e2018-09-05 08:30:59 -0700207} // namespace redfish