blob: 41257e0451cf5510dc94d3e763276d39178f8d7f [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
Ed Tanousa0803ef2018-08-29 13:29:23 -070022#include <error_messages.hpp>
23
Borawski.Lukaszb6df6dc2018-01-24 10:20:45 +010024#include "crow.h"
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)
37 {
38 }
Kowalski, Kamil588c3f02018-04-03 14:55:27 +020039
Ed Tanous1abe55e2018-09-05 08:30:59 -070040 ~AsyncResp()
41 {
42 res.end();
43 }
Kowalski, Kamil588c3f02018-04-03 14:55:27 +020044
Ed Tanous1abe55e2018-09-05 08:30:59 -070045 crow::Response& res;
Kowalski, Kamil588c3f02018-04-03 14:55:27 +020046};
47
48/**
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010049 * @brief Abstract class used for implementing Redfish nodes.
50 *
51 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070052class Node
53{
54 public:
55 template <typename... Params>
56 Node(CrowApp& app, std::string&& entityUrl, Params... params)
57 {
58 app.routeDynamic(entityUrl.c_str())
59 .methods("GET"_method, "PATCH"_method, "POST"_method,
60 "DELETE"_method)([&](const crow::Request& req,
61 crow::Response& res,
62 Params... params) {
63 std::vector<std::string> paramVec = {params...};
64 dispatchRequest(app, req, res, paramVec);
65 });
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010066 }
Ed Tanouscbbfa962018-03-13 16:46:28 -070067
Ed Tanous1abe55e2018-09-05 08:30:59 -070068 virtual ~Node() = default;
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010069
Ed Tanous1abe55e2018-09-05 08:30:59 -070070 const std::string* getUrl() const
71 {
72 auto odataId = json.find("@odata.id");
73 if (odataId == json.end())
74 {
75 return nullptr;
76 }
77
78 return odataId->get_ptr<const std::string*>();
Ed Tanouscbbfa962018-03-13 16:46:28 -070079 }
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010080
Ed Tanous1abe55e2018-09-05 08:30:59 -070081 /**
82 * @brief Inserts subroute fields into for the node's json in the form:
83 * "subroute_name" : { "odata.id": "node_url/subroute_name/" }
84 * Excludes metadata urls starting with "$" and child urls having
85 * more than one level.
86 *
87 * @return None
88 */
89 void getSubRoutes(const std::vector<std::unique_ptr<Node>>& allNodes)
90 {
91 const std::string* url = getUrl();
92 if (url == nullptr)
93 {
94 // BMCWEB_LOG_CRITICAL << "Unable to get url for route";
95 return;
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010096 }
97
Ed Tanous1abe55e2018-09-05 08:30:59 -070098 for (const auto& node : allNodes)
99 {
100 const std::string* route = node->getUrl();
101 if (route == nullptr)
102 {
103 // BMCWEB_LOG_CRITICAL << "Unable to get url for route";
104 continue;
105 }
106 if (boost::starts_with(*route, *url))
107 {
108 std::string subRoute = route->substr(url->size());
109 if (subRoute.empty())
110 {
111 continue;
112 }
113
114 if (boost::starts_with(subRoute, "/"))
115 {
116 subRoute.erase(0, 1);
117 }
118
119 if (boost::ends_with(subRoute, "/"))
120 {
121 subRoute.pop_back();
122 }
123
124 if (!boost::starts_with(subRoute, "$") &&
125 subRoute.find('/') == std::string::npos)
126 {
127 json[subRoute] = nlohmann::json{{"@odata.id", *route}};
128 }
129 }
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +0100130 }
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100131 }
132
Ed Tanous1abe55e2018-09-05 08:30:59 -0700133 OperationMap entityPrivileges;
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100134
Ed Tanous1abe55e2018-09-05 08:30:59 -0700135 protected:
136 // Node is designed to be an abstract class, so doGet is pure virtual
137 virtual void doGet(crow::Response& res, const crow::Request& req,
138 const std::vector<std::string>& params)
139 {
140 res.result(boost::beast::http::status::method_not_allowed);
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100141 res.end();
142 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700143
144 virtual void doPatch(crow::Response& res, const crow::Request& req,
145 const std::vector<std::string>& params)
146 {
147 res.result(boost::beast::http::status::method_not_allowed);
148 res.end();
149 }
150
151 virtual void doPost(crow::Response& res, const crow::Request& req,
152 const std::vector<std::string>& params)
153 {
154 res.result(boost::beast::http::status::method_not_allowed);
155 res.end();
156 }
157
158 virtual void doDelete(crow::Response& res, const crow::Request& req,
159 const std::vector<std::string>& params)
160 {
161 res.result(boost::beast::http::status::method_not_allowed);
162 res.end();
163 }
164
165 nlohmann::json json;
166
167 private:
168 void dispatchRequest(CrowApp& app, const crow::Request& req,
169 crow::Response& res,
170 const std::vector<std::string>& params)
171 {
172 auto ctx =
173 app.template getContext<crow::token_authorization::Middleware>(req);
174
175 if (!isMethodAllowedForUser(req.method(), entityPrivileges,
176 ctx.session->username))
177 {
178 res.result(boost::beast::http::status::method_not_allowed);
179 res.end();
180 return;
181 }
182
183 switch (req.method())
184 {
185 case "GET"_method:
186 doGet(res, req, params);
187 break;
188
189 case "PATCH"_method:
190 doPatch(res, req, params);
191 break;
192
193 case "POST"_method:
194 doPost(res, req, params);
195 break;
196
197 case "DELETE"_method:
198 doDelete(res, req, params);
199 break;
200
201 default:
202 res.result(boost::beast::http::status::not_found);
203 res.end();
204 }
205 return;
206 }
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100207};
208
Ed Tanous1abe55e2018-09-05 08:30:59 -0700209} // namespace redfish