blob: 70c757ac270d4afa28686cac74bd1d2054b3282c [file] [log] [blame]
Ratan Gupta453fed02019-12-14 09:39:47 +05301#pragma once
2#include <app.h>
3#include <tinyxml2.h>
4
5#include <async_resp.hpp>
Sunitha Harish97b0e432019-11-21 04:59:29 -06006#include <boost/algorithm/string.hpp>
7#include <boost/container/flat_set.hpp>
8#include <filesystem>
9#include <fstream>
10#include <regex>
11#include <sdbusplus/message/types.hpp>
12
13#define MAX_SAVE_AREA_FILESIZE 200000
Ratan Gupta453fed02019-12-14 09:39:47 +053014
15namespace crow
16{
17namespace ibm_mc
18{
Sunitha Harish97b0e432019-11-21 04:59:29 -060019constexpr const char *methodNotAllowedMsg = "Method Not Allowed";
20constexpr const char *resourceNotFoundMsg = "Resource Not Found";
21constexpr const char *contentNotAcceptableMsg = "Content Not Acceptable";
22constexpr const char *internalServerError = "Internal Server Error";
23
24bool createSaveAreaPath(crow::Response &res)
25{
26 // The path /var/lib/obmc will be created by initrdscripts
27 // Create the directories for the save-area files, when we get
28 // first file upload request
29 std::error_code ec;
30 if (!std::filesystem::is_directory("/var/lib/obmc/bmc-console-mgmt", ec))
31 {
32 std::filesystem::create_directory("/var/lib/obmc/bmc-console-mgmt", ec);
33 }
34 if (ec)
35 {
36 res.result(boost::beast::http::status::internal_server_error);
37 res.jsonValue["Description"] = internalServerError;
38 BMCWEB_LOG_DEBUG
39 << "handleIbmPost: Failed to prepare save-area directory. ec : "
40 << ec;
41 return false;
42 }
43
44 if (!std::filesystem::is_directory(
45 "/var/lib/obmc/bmc-console-mgmt/save-area", ec))
46 {
47 std::filesystem::create_directory(
48 "/var/lib/obmc/bmc-console-mgmt/save-area", ec);
49 }
50 if (ec)
51 {
52 res.result(boost::beast::http::status::internal_server_error);
53 res.jsonValue["Description"] = internalServerError;
54 BMCWEB_LOG_DEBUG
55 << "handleIbmPost: Failed to prepare save-area directory. ec : "
56 << ec;
57 return false;
58 }
59 return true;
60}
61void handleFilePut(const crow::Request &req, crow::Response &res,
asmithakarun1c7b07c2019-09-09 03:42:59 -050062 const std::string &fileID)
Sunitha Harish97b0e432019-11-21 04:59:29 -060063{
64 // Check the content-type of the request
65 std::string_view contentType = req.getHeaderValue("content-type");
66 if (boost::starts_with(contentType, "multipart/form-data"))
67 {
68 BMCWEB_LOG_DEBUG
69 << "This is multipart/form-data. Invalid content for PUT";
70
71 res.result(boost::beast::http::status::not_acceptable);
72 res.jsonValue["Description"] = contentNotAcceptableMsg;
73 return;
74 }
75 else
76 {
77 BMCWEB_LOG_DEBUG << "Not a multipart/form-data. Continue..";
78 }
asmithakarun1c7b07c2019-09-09 03:42:59 -050079
80 BMCWEB_LOG_DEBUG
81 << "handleIbmPut: Request to create/update the save-area file";
82 if (!createSaveAreaPath(res))
Sunitha Harish97b0e432019-11-21 04:59:29 -060083 {
asmithakarun1c7b07c2019-09-09 03:42:59 -050084 res.result(boost::beast::http::status::not_found);
85 res.jsonValue["Description"] = resourceNotFoundMsg;
86 return;
87 }
88 // Create the file
89 std::ofstream file;
90 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area");
91 loc /= fileID;
Sunitha Harish97b0e432019-11-21 04:59:29 -060092
asmithakarun1c7b07c2019-09-09 03:42:59 -050093 std::string data = std::move(req.body);
94 BMCWEB_LOG_DEBUG << "data capaticty : " << data.capacity();
95 if (data.capacity() > MAX_SAVE_AREA_FILESIZE)
96 {
97 res.result(boost::beast::http::status::bad_request);
98 res.jsonValue["Description"] =
99 "File size exceeds 200KB. Maximum allowed size is 200KB";
100 return;
101 }
asmithakarun1c7b07c2019-09-09 03:42:59 -0500102 BMCWEB_LOG_DEBUG << "Creating file " << loc;
103 file.open(loc, std::ofstream::out);
104 if (file.fail())
105 {
106 BMCWEB_LOG_DEBUG << "Error while opening the file for writing";
107 res.result(boost::beast::http::status::internal_server_error);
108 res.jsonValue["Description"] = "Error while creating the file";
109 return;
Sunitha Harish97b0e432019-11-21 04:59:29 -0600110 }
111 else
112 {
asmithakarun1c7b07c2019-09-09 03:42:59 -0500113 file << data;
114 BMCWEB_LOG_DEBUG << "save-area file is created";
115 res.jsonValue["Description"] = "File Created";
116 }
Ratan Guptad3630cb2019-12-14 11:21:35 +0530117}
asmithakarun1c7b07c2019-09-09 03:42:59 -0500118
Ratan Guptad3630cb2019-12-14 11:21:35 +0530119void handleConfigFileList(crow::Response &res)
120{
121 std::vector<std::string> pathObjList;
122 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area");
123 if (std::filesystem::exists(loc) && std::filesystem::is_directory(loc))
124 {
125 for (const auto &file : std::filesystem::directory_iterator(loc))
126 {
127 std::filesystem::path pathObj(file.path());
128 pathObjList.push_back("/ibm/v1/Host/ConfigFiles/" +
129 pathObj.filename().string());
130 }
131 }
132 res.jsonValue["@odata.type"] = "#FileCollection.v1_0_0.FileCollection";
133 res.jsonValue["@odata.id"] = "/ibm/v1/Host/ConfigFiles/";
134 res.jsonValue["Id"] = "ConfigFiles";
135 res.jsonValue["Name"] = "ConfigFiles";
136
137 res.jsonValue["Members"] = std::move(pathObjList);
138 res.jsonValue["Actions"]["#FileCollection.DeleteAll"] = {
139 {"target",
140 "/ibm/v1/Host/ConfigFiles/Actions/FileCollection.DeleteAll"}};
141 res.end();
142}
143
144void deleteConfigFiles(crow::Response &res)
145{
146 std::vector<std::string> pathObjList;
147 std::error_code ec;
148 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area");
149 if (std::filesystem::exists(loc) && std::filesystem::is_directory(loc))
150 {
151 std::filesystem::remove_all(loc, ec);
152 if (ec)
153 {
154 res.result(boost::beast::http::status::internal_server_error);
155 res.jsonValue["Description"] = internalServerError;
156 BMCWEB_LOG_DEBUG << "deleteConfigFiles: Failed to delete the "
157 "config files directory. ec : "
158 << ec;
159 }
160 }
161 res.end();
asmithakarun1c7b07c2019-09-09 03:42:59 -0500162}
163
164void handleFileGet(crow::Response &res, const std::string &fileID)
165{
166 BMCWEB_LOG_DEBUG << "HandleGet on SaveArea files on path: " << fileID;
167 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area/" +
168 fileID);
169 if (!std::filesystem::exists(loc))
170 {
171 BMCWEB_LOG_ERROR << loc << "Not found";
172 res.result(boost::beast::http::status::not_found);
173 res.jsonValue["Description"] = resourceNotFoundMsg;
174 return;
175 }
176
177 std::ifstream readfile(loc.string());
178 if (!readfile)
179 {
180 BMCWEB_LOG_ERROR << loc.string() << "Not found";
181 res.result(boost::beast::http::status::not_found);
182 res.jsonValue["Description"] = resourceNotFoundMsg;
183 return;
184 }
185
186 std::string contentDispositionParam =
187 "attachment; filename=\"" + fileID + "\"";
188 res.addHeader("Content-Disposition", contentDispositionParam);
189 std::string fileData;
190 fileData = {std::istreambuf_iterator<char>(readfile),
191 std::istreambuf_iterator<char>()};
192 res.jsonValue["Data"] = fileData;
193 return;
194}
195
196void handleFileDelete(crow::Response &res, const std::string &fileID)
197{
198 std::string filePath("/var/lib/obmc/bmc-console-mgmt/save-area/" + fileID);
199 BMCWEB_LOG_DEBUG << "Removing the file : " << filePath << "\n";
200
201 std::ifstream file_open(filePath.c_str());
202 if (static_cast<bool>(file_open))
203 if (remove(filePath.c_str()) == 0)
204 {
205 BMCWEB_LOG_DEBUG << "File removed!\n";
206 res.jsonValue["Description"] = "File Deleted";
207 }
208 else
209 {
210 BMCWEB_LOG_ERROR << "File not removed!\n";
211 res.result(boost::beast::http::status::internal_server_error);
212 res.jsonValue["Description"] = internalServerError;
213 }
214 else
215 {
216 BMCWEB_LOG_ERROR << "File not found!\n";
Sunitha Harish97b0e432019-11-21 04:59:29 -0600217 res.result(boost::beast::http::status::not_found);
218 res.jsonValue["Description"] = resourceNotFoundMsg;
219 }
220 return;
221}
222
223inline void handleFileUrl(const crow::Request &req, crow::Response &res,
asmithakarun1c7b07c2019-09-09 03:42:59 -0500224 const std::string &fileID)
Sunitha Harish97b0e432019-11-21 04:59:29 -0600225{
Sunitha Harish97b0e432019-11-21 04:59:29 -0600226 if (req.method() == "PUT"_method)
227 {
asmithakarun1c7b07c2019-09-09 03:42:59 -0500228 handleFilePut(req, res, fileID);
Sunitha Harish97b0e432019-11-21 04:59:29 -0600229 res.end();
230 return;
231 }
asmithakarun1c7b07c2019-09-09 03:42:59 -0500232 if (req.method() == "GET"_method)
233 {
234 handleFileGet(res, fileID);
235 res.end();
236 return;
237 }
238 if (req.method() == "DELETE"_method)
239 {
240 handleFileDelete(res, fileID);
241 res.end();
242 return;
243 }
Sunitha Harish97b0e432019-11-21 04:59:29 -0600244}
Ratan Gupta453fed02019-12-14 09:39:47 +0530245
246template <typename... Middlewares> void requestRoutes(Crow<Middlewares...> &app)
247{
248
249 // allowed only for admin
250 BMCWEB_ROUTE(app, "/ibm/v1/")
251 .requires({"ConfigureComponents", "ConfigureManager"})
252 .methods("GET"_method)(
253 [](const crow::Request &req, crow::Response &res) {
254 res.jsonValue["@odata.type"] =
255 "#ibmServiceRoot.v1_0_0.ibmServiceRoot";
256 res.jsonValue["@odata.id"] = "/ibm/v1/";
257 res.jsonValue["Id"] = "IBM Rest RootService";
258 res.jsonValue["Name"] = "IBM Service Root";
259 res.jsonValue["ConfigFiles"] = {
260 {"@odata.id", "/ibm/v1/Host/ConfigFiles"}};
261 res.jsonValue["LockService"] = {
262 {"@odata.id", "/ibm/v1/HMC/LockService"}};
263 res.end();
264 });
Sunitha Harish97b0e432019-11-21 04:59:29 -0600265
Ratan Guptad3630cb2019-12-14 11:21:35 +0530266 BMCWEB_ROUTE(app, "/ibm/v1/Host/ConfigFiles")
267 .requires({"ConfigureComponents", "ConfigureManager"})
268 .methods("GET"_method)(
269 [](const crow::Request &req, crow::Response &res) {
270 handleConfigFileList(res);
271 });
272
273 BMCWEB_ROUTE(app,
274 "/ibm/v1/Host/ConfigFiles/Actions/FileCollection.DeleteAll")
275 .requires({"ConfigureComponents", "ConfigureManager"})
276 .methods("POST"_method)(
277 [](const crow::Request &req, crow::Response &res) {
278 deleteConfigFiles(res);
279 });
280
asmithakarun1c7b07c2019-09-09 03:42:59 -0500281 BMCWEB_ROUTE(app, "/ibm/v1/Host/ConfigFiles/<path>")
Sunitha Harish97b0e432019-11-21 04:59:29 -0600282 .requires({"ConfigureComponents", "ConfigureManager"})
asmithakarun1c7b07c2019-09-09 03:42:59 -0500283 .methods("PUT"_method, "GET"_method, "DELETE"_method)(
284 [](const crow::Request &req, crow::Response &res,
285 const std::string &path) { handleFileUrl(req, res, path); });
Ratan Gupta453fed02019-12-14 09:39:47 +0530286}
287
288} // namespace ibm_mc
289} // namespace crow