blob: 3fb0ce73702e2340b0a913c719e157ffff5d1bea [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"
Borawski.Lukaszb6df6dc2018-01-24 10:20:45 +010021#include "crow.h"
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010022
23namespace redfish {
24
25/**
26 * @brief Abstract class used for implementing Redfish nodes.
27 *
28 */
29class Node {
30 public:
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010031 template <typename... Params>
Ed Tanous3ebd75f2018-03-05 18:20:01 -080032 Node(CrowApp& app, std::string&& entityUrl, Params... params) {
Borawski.Lukaszaecb47a2018-01-25 12:14:14 +010033 app.route_dynamic(entityUrl.c_str())
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010034 .methods("GET"_method, "PATCH"_method, "POST"_method,
35 "DELETE"_method)([&](const crow::request& req,
36 crow::response& res, Params... params) {
37 std::vector<std::string> paramVec = {params...};
38 dispatchRequest(app, req, res, paramVec);
39 });
40 }
41
Borawski.Lukaszaecb47a2018-01-25 12:14:14 +010042 virtual ~Node() = default;
43
Ed Tanouscbbfa962018-03-13 16:46:28 -070044 const std::string* getUrl() const {
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010045 auto odataId = json.find("@odata.id");
Ed Tanouscbbfa962018-03-13 16:46:28 -070046 if (odataId == json.end()) {
47 return nullptr;
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010048 }
Ed Tanouscbbfa962018-03-13 16:46:28 -070049
50 return odataId->get_ptr<const std::string*>();
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010051 }
52
53 /**
54 * @brief Inserts subroute fields into for the node's json in the form:
55 * "subroute_name" : { "odata.id": "node_url/subroute_name/" }
56 * Excludes metadata urls starting with "$" and child urls having
57 * more than one level.
58 *
59 * @return None
60 */
61 void getSubRoutes(const std::vector<std::unique_ptr<Node>>& allNodes) {
Ed Tanouscbbfa962018-03-13 16:46:28 -070062 const std::string* url = getUrl();
63 if (url == nullptr) {
64 CROW_LOG_CRITICAL << "Unable to get url for route";
65 return;
66 }
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010067
68 for (const auto& node : allNodes) {
Ed Tanouscbbfa962018-03-13 16:46:28 -070069 const std::string* route = node->getUrl();
70 if (route == nullptr) {
71 CROW_LOG_CRITICAL << "Unable to get url for route";
Rapkiewicz, Pawel9391bb92018-03-20 03:12:18 +010072 continue;
Ed Tanouscbbfa962018-03-13 16:46:28 -070073 }
74 if (boost::starts_with(*route, *url)) {
75 std::string subRoute = route->substr(url->size());
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010076 if (subRoute.empty()) {
77 continue;
78 }
79
Ed Tanouscbbfa962018-03-13 16:46:28 -070080 if (boost::starts_with(subRoute, "/")) {
81 subRoute.erase(0, 1);
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010082 }
83
Ed Tanouscbbfa962018-03-13 16:46:28 -070084 if (boost::ends_with(subRoute, "/")) {
85 subRoute.pop_back();
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010086 }
87
Ed Tanouscbbfa962018-03-13 16:46:28 -070088 if (!boost::starts_with(subRoute, "$") &&
89 subRoute.find('/') == std::string::npos) {
90 json[subRoute] = nlohmann::json{{"@odata.id", *route}};
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010091 }
92 }
93 }
94 }
95
Ed Tanous3ebd75f2018-03-05 18:20:01 -080096 OperationMap entityPrivileges;
97
Borawski.Lukaszaecb47a2018-01-25 12:14:14 +010098 protected:
99 // Node is designed to be an abstract class, so doGet is pure virtual
100 virtual void doGet(crow::response& res, const crow::request& req,
101 const std::vector<std::string>& params) = 0;
102
103 virtual void doPatch(crow::response& res, const crow::request& req,
104 const std::vector<std::string>& params) {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700105 res.result(boost::beast::http::status::method_not_allowed);
Borawski.Lukaszaecb47a2018-01-25 12:14:14 +0100106 res.end();
107 }
108
109 virtual void doPost(crow::response& res, const crow::request& req,
110 const std::vector<std::string>& params) {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700111 res.result(boost::beast::http::status::method_not_allowed);
Borawski.Lukaszaecb47a2018-01-25 12:14:14 +0100112 res.end();
113 }
114
115 virtual void doDelete(crow::response& res, const crow::request& req,
116 const std::vector<std::string>& params) {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700117 res.result(boost::beast::http::status::method_not_allowed);
Borawski.Lukaszaecb47a2018-01-25 12:14:14 +0100118 res.end();
119 }
120
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +0100121 nlohmann::json json;
122
Borawski.Lukaszaecb47a2018-01-25 12:14:14 +0100123 private:
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100124 void dispatchRequest(CrowApp& app, const crow::request& req,
125 crow::response& res,
126 const std::vector<std::string>& params) {
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100127 auto ctx =
128 app.template get_context<crow::TokenAuthorization::Middleware>(req);
129
Ed Tanouse0d918b2018-03-27 17:41:04 -0700130 if (!isMethodAllowedForUser(req.method(), entityPrivileges,
Ed Tanous3ebd75f2018-03-05 18:20:01 -0800131 ctx.session->username)) {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700132 res.result(boost::beast::http::status::method_not_allowed);
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100133 res.end();
134 return;
135 }
136
Ed Tanouse0d918b2018-03-27 17:41:04 -0700137 switch (req.method()) {
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100138 case "GET"_method:
139 doGet(res, req, params);
140 break;
141
142 case "PATCH"_method:
143 doPatch(res, req, params);
144 break;
145
146 case "POST"_method:
147 doPost(res, req, params);
148 break;
149
150 case "DELETE"_method:
151 doDelete(res, req, params);
152 break;
153
154 default:
Ed Tanouse0d918b2018-03-27 17:41:04 -0700155 res.result(boost::beast::http::status::not_found);
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100156 res.end();
157 }
158 return;
159 }
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100160};
161
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100162} // namespace redfish