blob: 3d2bbc2463d2d04c1d7b0a1ed4d0a8cecf3c797d [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,
62 const std::string &objectPath,
63 const std::string &destProperty)
64{
65 // Check the content-type of the request
66 std::string_view contentType = req.getHeaderValue("content-type");
67 if (boost::starts_with(contentType, "multipart/form-data"))
68 {
69 BMCWEB_LOG_DEBUG
70 << "This is multipart/form-data. Invalid content for PUT";
71
72 res.result(boost::beast::http::status::not_acceptable);
73 res.jsonValue["Description"] = contentNotAcceptableMsg;
74 return;
75 }
76 else
77 {
78 BMCWEB_LOG_DEBUG << "Not a multipart/form-data. Continue..";
79 }
80 std::size_t pos = objectPath.find("ConfigFiles/");
81 if (pos != std::string::npos)
82 {
83 BMCWEB_LOG_DEBUG
84 << "handleIbmPut: Request to create/update the save-area file";
85 if (!createSaveAreaPath(res))
86 {
87 res.result(boost::beast::http::status::not_found);
88 res.jsonValue["Description"] = resourceNotFoundMsg;
89 return;
90 }
91 // Extract the file name from the objectPath
92 std::string fileId = objectPath.substr(pos + strlen("ConfigFiles/"));
93 // Create the file
94 std::ofstream file;
95 std::filesystem::path loc("/var/lib/obmc/bmc-console-mgmt/save-area");
96 loc /= fileId;
97
98 std::string data = std::move(req.body);
99 BMCWEB_LOG_DEBUG << "data capaticty : " << data.capacity();
100 if (data.capacity() > MAX_SAVE_AREA_FILESIZE)
101 {
102 res.result(boost::beast::http::status::bad_request);
103 res.jsonValue["Description"] =
104 "File size exceeds 200KB. Maximum allowed size is 200KB";
105 return;
106 }
107
108 BMCWEB_LOG_DEBUG << "Creating file " << loc;
109 file.open(loc, std::ofstream::out);
110 if (file.fail())
111 {
112 BMCWEB_LOG_DEBUG << "Error while opening the file for writing";
113 res.result(boost::beast::http::status::internal_server_error);
114 res.jsonValue["Description"] = "Error while creating the file";
115 return;
116 }
117 else
118 {
119 file << data;
120 BMCWEB_LOG_DEBUG << "save-area file is created";
121 res.jsonValue["Description"] = "File Created";
122 }
123 }
124 else
125 {
126 BMCWEB_LOG_DEBUG << "Bad URI";
127 res.result(boost::beast::http::status::not_found);
128 res.jsonValue["Description"] = resourceNotFoundMsg;
129 }
130 return;
131}
132
133inline void handleFileUrl(const crow::Request &req, crow::Response &res,
134 std::string &objectPath)
135{
136 std::string destProperty = "";
137 if (req.method() == "PUT"_method)
138 {
139 handleFilePut(req, res, objectPath, destProperty);
140 res.end();
141 return;
142 }
143 res.result(boost::beast::http::status::method_not_allowed);
144 res.jsonValue["Description"] = methodNotAllowedMsg;
145 res.end();
146}
Ratan Gupta453fed02019-12-14 09:39:47 +0530147
148template <typename... Middlewares> void requestRoutes(Crow<Middlewares...> &app)
149{
150
151 // allowed only for admin
152 BMCWEB_ROUTE(app, "/ibm/v1/")
153 .requires({"ConfigureComponents", "ConfigureManager"})
154 .methods("GET"_method)(
155 [](const crow::Request &req, crow::Response &res) {
156 res.jsonValue["@odata.type"] =
157 "#ibmServiceRoot.v1_0_0.ibmServiceRoot";
158 res.jsonValue["@odata.id"] = "/ibm/v1/";
159 res.jsonValue["Id"] = "IBM Rest RootService";
160 res.jsonValue["Name"] = "IBM Service Root";
161 res.jsonValue["ConfigFiles"] = {
162 {"@odata.id", "/ibm/v1/Host/ConfigFiles"}};
163 res.jsonValue["LockService"] = {
164 {"@odata.id", "/ibm/v1/HMC/LockService"}};
165 res.end();
166 });
Sunitha Harish97b0e432019-11-21 04:59:29 -0600167
168 BMCWEB_ROUTE(app, "/ibm/v1/Host/<path>")
169 .requires({"ConfigureComponents", "ConfigureManager"})
170 .methods("PUT"_method)([](const crow::Request &req, crow::Response &res,
171 const std::string &path) {
172 std::string objectPath = "/ibm/v1/Host/" + path;
173 handleFileUrl(req, res, objectPath);
174 });
Ratan Gupta453fed02019-12-14 09:39:47 +0530175}
176
177} // namespace ibm_mc
178} // namespace crow