blob: 908d1a6a64df7e6fd3ac24081788d23de6239072 [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>
Borawski.Lukasz43a095a2018-02-19 15:39:01 +010032 Node(CrowApp& app, EntityPrivileges&& entityPrivileges,
33 std::string&& entityUrl, Params... params)
34 : entityPrivileges(std::move(entityPrivileges)) {
Borawski.Lukaszaecb47a2018-01-25 12:14:14 +010035 app.route_dynamic(entityUrl.c_str())
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010036 .methods("GET"_method, "PATCH"_method, "POST"_method,
37 "DELETE"_method)([&](const crow::request& req,
38 crow::response& res, Params... params) {
39 std::vector<std::string> paramVec = {params...};
40 dispatchRequest(app, req, res, paramVec);
41 });
42 }
43
Borawski.Lukaszaecb47a2018-01-25 12:14:14 +010044 virtual ~Node() = default;
45
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +010046 std::string getUrl() const {
47 auto odataId = json.find("@odata.id");
48 if (odataId != json.end() && odataId->is_string()) {
49 return odataId->get<std::string>();
50 }
51 return std::string();
52 }
53
54 /**
55 * @brief Inserts subroute fields into for the node's json in the form:
56 * "subroute_name" : { "odata.id": "node_url/subroute_name/" }
57 * Excludes metadata urls starting with "$" and child urls having
58 * more than one level.
59 *
60 * @return None
61 */
62 void getSubRoutes(const std::vector<std::unique_ptr<Node>>& allNodes) {
63 std::string url = getUrl();
64
65 for (const auto& node : allNodes) {
66 auto route = node->getUrl();
67
68 if (boost::starts_with(route, url)) {
69 auto subRoute = route.substr(url.size());
70 if (subRoute.empty()) {
71 continue;
72 }
73
74 if (subRoute.at(0) == '/') {
75 subRoute = subRoute.substr(1);
76 }
77
78 if (subRoute.at(subRoute.size() - 1) == '/') {
79 subRoute = subRoute.substr(0, subRoute.size() - 1);
80 }
81
82 if (subRoute[0] != '$' && subRoute.find('/') == std::string::npos) {
83 json[subRoute] = nlohmann::json{{"@odata.id", route}};
84 }
85 }
86 }
87 }
88
Borawski.Lukaszaecb47a2018-01-25 12:14:14 +010089 protected:
90 // Node is designed to be an abstract class, so doGet is pure virtual
91 virtual void doGet(crow::response& res, const crow::request& req,
92 const std::vector<std::string>& params) = 0;
93
94 virtual void doPatch(crow::response& res, const crow::request& req,
95 const std::vector<std::string>& params) {
96 res.code = static_cast<int>(HttpRespCode::METHOD_NOT_ALLOWED);
97 res.end();
98 }
99
100 virtual void doPost(crow::response& res, const crow::request& req,
101 const std::vector<std::string>& params) {
102 res.code = static_cast<int>(HttpRespCode::METHOD_NOT_ALLOWED);
103 res.end();
104 }
105
106 virtual void doDelete(crow::response& res, const crow::request& req,
107 const std::vector<std::string>& params) {
108 res.code = static_cast<int>(HttpRespCode::METHOD_NOT_ALLOWED);
109 res.end();
110 }
111
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +0100112 nlohmann::json json;
113
Borawski.Lukaszaecb47a2018-01-25 12:14:14 +0100114 private:
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100115 void dispatchRequest(CrowApp& app, const crow::request& req,
116 crow::response& res,
117 const std::vector<std::string>& params) {
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100118 auto ctx =
119 app.template get_context<crow::TokenAuthorization::Middleware>(req);
120
Borawski.Lukaszaecb47a2018-01-25 12:14:14 +0100121 if (!entityPrivileges.isMethodAllowedForUser(req.method,
122 ctx.session->username)) {
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100123 res.code = static_cast<int>(HttpRespCode::METHOD_NOT_ALLOWED);
124 res.end();
125 return;
126 }
127
128 switch (req.method) {
129 case "GET"_method:
130 doGet(res, req, params);
131 break;
132
133 case "PATCH"_method:
134 doPatch(res, req, params);
135 break;
136
137 case "POST"_method:
138 doPost(res, req, params);
139 break;
140
141 case "DELETE"_method:
142 doDelete(res, req, params);
143 break;
144
145 default:
146 res.code = static_cast<int>(HttpRespCode::NOT_FOUND);
147 res.end();
148 }
149 return;
150 }
151
Borawski.Lukasz43a095a2018-02-19 15:39:01 +0100152 EntityPrivileges entityPrivileges;
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100153};
154
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100155} // namespace redfish