blob: 0b14575e145a06e7095536abd6b140dcdd1b8e2f [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
Ratan Gupta453fed02019-12-14 09:39:47 +05303#pragma once
Ratan Gupta453fed02019-12-14 09:39:47 +05304
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08005#include "app.hpp"
6#include "async_resp.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08007#include "http_request.hpp"
Sunitha Harish56d0bb02024-04-06 03:35:34 -05008#include "ibm/utils.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08009#include "logging.hpp"
Ed Tanous18f8f602023-07-18 10:07:23 -070010#include "str_utility.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080011#include "utils/json_utils.hpp"
12
Ed Tanousd7857202025-01-28 15:32:26 -080013#include <boost/beast/core/string_type.hpp>
14#include <boost/beast/http/field.hpp>
15#include <boost/beast/http/status.hpp>
16#include <boost/beast/http/verb.hpp>
manojkiraneda0b631ae2019-12-03 17:54:28 +053017#include <nlohmann/json.hpp>
Sunitha Harish97b0e432019-11-21 04:59:29 -060018
Ed Tanousd7857202025-01-28 15:32:26 -080019#include <cstddef>
20#include <cstdint>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050021#include <filesystem>
22#include <fstream>
Ed Tanousd7857202025-01-28 15:32:26 -080023#include <iterator>
24#include <memory>
25#include <string>
26#include <system_error>
27#include <utility>
28#include <vector>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050029
Ratan Gupta453fed02019-12-14 09:39:47 +053030namespace crow
31{
32namespace ibm_mc
33{
Gunnar Mills1214b7e2020-06-04 10:11:30 -050034constexpr const char* methodNotAllowedMsg = "Method Not Allowed";
35constexpr const char* resourceNotFoundMsg = "Resource Not Found";
36constexpr const char* contentNotAcceptableMsg = "Content Not Acceptable";
37constexpr const char* internalServerError = "Internal Server Error";
Sunitha Harish97b0e432019-11-21 04:59:29 -060038
Sunitha Harish7c0bbe72020-07-30 08:25:28 -050039constexpr size_t maxSaveareaDirSize =
Sunitha Harishf8a43472022-08-08 02:07:12 -050040 25000000; // Allow save area dir size to be max 25MB
Sunitha Harish7c0bbe72020-07-30 08:25:28 -050041constexpr size_t minSaveareaFileSize =
Patrick Williams504af5a2025-02-03 14:29:03 -050042 100; // Allow save area file size of minimum 100B
Asmitha Karunanithi5738de52020-07-17 02:03:31 -050043constexpr size_t maxSaveareaFileSize =
Patrick Williams504af5a2025-02-03 14:29:03 -050044 500000; // Allow save area file size upto 500KB
Asmitha Karunanithi5738de52020-07-17 02:03:31 -050045constexpr size_t maxBroadcastMsgSize =
Patrick Williams504af5a2025-02-03 14:29:03 -050046 1000; // Allow Broadcast message size upto 1KB
Asmitha Karunanithi5738de52020-07-17 02:03:31 -050047
Sunitha Harishdb81c072021-01-21 23:33:21 -060048inline void handleFilePut(const crow::Request& req,
49 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanous02379d32020-09-15 21:15:44 -070050 const std::string& fileID)
Sunitha Harish97b0e432019-11-21 04:59:29 -060051{
Sunitha Harish7c0bbe72020-07-30 08:25:28 -050052 std::error_code ec;
Sunitha Harish97b0e432019-11-21 04:59:29 -060053 // Check the content-type of the request
Sunitha Harish086d32c2021-02-01 02:11:49 -060054 boost::beast::string_view contentType = req.getHeaderValue("content-type");
Ed Tanous18f8f602023-07-18 10:07:23 -070055 if (!bmcweb::asciiIEquals(contentType, "application/octet-stream"))
Sunitha Harish97b0e432019-11-21 04:59:29 -060056 {
Sunitha Harishdb81c072021-01-21 23:33:21 -060057 asyncResp->res.result(boost::beast::http::status::not_acceptable);
58 asyncResp->res.jsonValue["Description"] = contentNotAcceptableMsg;
Sunitha Harish97b0e432019-11-21 04:59:29 -060059 return;
60 }
Ed Tanous62598e32023-07-17 17:06:25 -070061 BMCWEB_LOG_DEBUG(
62 "File upload in application/octet-stream format. Continue..");
asmithakarun1c7b07c2019-09-09 03:42:59 -050063
Ed Tanous62598e32023-07-17 17:06:25 -070064 BMCWEB_LOG_DEBUG(
65 "handleIbmPut: Request to create/update the save-area file");
Sunitha Harish3e919b52020-10-13 01:21:48 -050066 std::string_view path =
67 "/var/lib/bmcweb/ibm-management-console/configfiles";
68 if (!crow::ibm_utils::createDirectory(path))
Sunitha Harish97b0e432019-11-21 04:59:29 -060069 {
Sunitha Harishdb81c072021-01-21 23:33:21 -060070 asyncResp->res.result(boost::beast::http::status::not_found);
71 asyncResp->res.jsonValue["Description"] = resourceNotFoundMsg;
asmithakarun1c7b07c2019-09-09 03:42:59 -050072 return;
73 }
Sunitha Harish7c0bbe72020-07-30 08:25:28 -050074
asmithakarun1c7b07c2019-09-09 03:42:59 -050075 std::ofstream file;
Sunitha Harish3e919b52020-10-13 01:21:48 -050076 std::filesystem::path loc(
77 "/var/lib/bmcweb/ibm-management-console/configfiles");
Sunitha Harish97b0e432019-11-21 04:59:29 -060078
Sunitha Harish7c0bbe72020-07-30 08:25:28 -050079 // Get the current size of the savearea directory
80 std::filesystem::recursive_directory_iterator iter(loc, ec);
81 if (ec)
82 {
Sunitha Harishdb81c072021-01-21 23:33:21 -060083 asyncResp->res.result(
84 boost::beast::http::status::internal_server_error);
85 asyncResp->res.jsonValue["Description"] = internalServerError;
Ed Tanous62598e32023-07-17 17:06:25 -070086 BMCWEB_LOG_DEBUG("handleIbmPut: Failed to prepare save-area "
87 "directory iterator. ec : {}",
88 ec.message());
Sunitha Harish7c0bbe72020-07-30 08:25:28 -050089 return;
90 }
91 std::uintmax_t saveAreaDirSize = 0;
Ed Tanous9eb808c2022-01-25 10:19:23 -080092 for (const auto& it : iter)
Sunitha Harish7c0bbe72020-07-30 08:25:28 -050093 {
94 if (!std::filesystem::is_directory(it, ec))
95 {
96 if (ec)
97 {
Sunitha Harishdb81c072021-01-21 23:33:21 -060098 asyncResp->res.result(
99 boost::beast::http::status::internal_server_error);
100 asyncResp->res.jsonValue["Description"] = internalServerError;
Ed Tanous62598e32023-07-17 17:06:25 -0700101 BMCWEB_LOG_DEBUG("handleIbmPut: Failed to find save-area "
102 "directory . ec : {}",
103 ec.message());
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500104 return;
105 }
106 std::uintmax_t fileSize = std::filesystem::file_size(it, ec);
107 if (ec)
108 {
Sunitha Harishdb81c072021-01-21 23:33:21 -0600109 asyncResp->res.result(
110 boost::beast::http::status::internal_server_error);
111 asyncResp->res.jsonValue["Description"] = internalServerError;
Ed Tanous62598e32023-07-17 17:06:25 -0700112 BMCWEB_LOG_DEBUG("handleIbmPut: Failed to find save-area "
113 "file size inside the directory . ec : {}",
114 ec.message());
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500115 return;
116 }
117 saveAreaDirSize += fileSize;
118 }
119 }
Ed Tanous62598e32023-07-17 17:06:25 -0700120 BMCWEB_LOG_DEBUG("saveAreaDirSize: {}", saveAreaDirSize);
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500121
122 // Get the file size getting uploaded
Ed Tanous33c6b582023-02-14 15:05:48 -0800123 const std::string& data = req.body();
Ed Tanous62598e32023-07-17 17:06:25 -0700124 BMCWEB_LOG_DEBUG("data length: {}", data.length());
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500125
126 if (data.length() < minSaveareaFileSize)
127 {
Sunitha Harishdb81c072021-01-21 23:33:21 -0600128 asyncResp->res.result(boost::beast::http::status::bad_request);
129 asyncResp->res.jsonValue["Description"] =
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500130 "File size is less than minimum allowed size[100B]";
131 return;
132 }
133 if (data.length() > maxSaveareaFileSize)
asmithakarun1c7b07c2019-09-09 03:42:59 -0500134 {
Sunitha Harishdb81c072021-01-21 23:33:21 -0600135 asyncResp->res.result(boost::beast::http::status::bad_request);
136 asyncResp->res.jsonValue["Description"] =
Ratan Guptae46946a2020-05-11 13:22:59 +0530137 "File size exceeds maximum allowed size[500KB]";
asmithakarun1c7b07c2019-09-09 03:42:59 -0500138 return;
139 }
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500140
141 // Form the file path
142 loc /= fileID;
Ed Tanous62598e32023-07-17 17:06:25 -0700143 BMCWEB_LOG_DEBUG("Writing to the file: {}", loc.string());
Asmitha Karunanithi10693fa2020-07-27 02:27:49 -0500144
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500145 // Check if the same file exists in the directory
146 bool fileExists = std::filesystem::exists(loc, ec);
147 if (ec)
Asmitha Karunanithi10693fa2020-07-27 02:27:49 -0500148 {
Sunitha Harishdb81c072021-01-21 23:33:21 -0600149 asyncResp->res.result(
150 boost::beast::http::status::internal_server_error);
151 asyncResp->res.jsonValue["Description"] = internalServerError;
Ed Tanous62598e32023-07-17 17:06:25 -0700152 BMCWEB_LOG_DEBUG("handleIbmPut: Failed to find if file exists. ec : {}",
153 ec.message());
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500154 return;
Asmitha Karunanithi10693fa2020-07-27 02:27:49 -0500155 }
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500156
157 std::uintmax_t newSizeToWrite = 0;
158 if (fileExists)
159 {
160 // File exists. Get the current file size
161 std::uintmax_t currentFileSize = std::filesystem::file_size(loc, ec);
162 if (ec)
163 {
Sunitha Harishdb81c072021-01-21 23:33:21 -0600164 asyncResp->res.result(
165 boost::beast::http::status::internal_server_error);
166 asyncResp->res.jsonValue["Description"] = internalServerError;
Ed Tanous62598e32023-07-17 17:06:25 -0700167 BMCWEB_LOG_DEBUG("handleIbmPut: Failed to find file size. ec : {}",
168 ec.message());
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500169 return;
170 }
171 // Calculate the difference in the file size.
172 // If the data.length is greater than the existing file size, then
173 // calculate the difference. Else consider the delta size as zero -
174 // because there is no increase in the total directory size.
175 // We need to add the diff only if the incoming data is larger than the
176 // existing filesize
177 if (data.length() > currentFileSize)
178 {
179 newSizeToWrite = data.length() - currentFileSize;
180 }
Ed Tanous62598e32023-07-17 17:06:25 -0700181 BMCWEB_LOG_DEBUG("newSizeToWrite: {}", newSizeToWrite);
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500182 }
183 else
184 {
185 // This is a new file upload
186 newSizeToWrite = data.length();
187 }
188
189 // Calculate the total dir size before writing the new file
Ed Tanous62598e32023-07-17 17:06:25 -0700190 BMCWEB_LOG_DEBUG("total new size: {}", saveAreaDirSize + newSizeToWrite);
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500191
192 if ((saveAreaDirSize + newSizeToWrite) > maxSaveareaDirSize)
193 {
Sunitha Harishdb81c072021-01-21 23:33:21 -0600194 asyncResp->res.result(boost::beast::http::status::bad_request);
195 asyncResp->res.jsonValue["Description"] =
196 "File size does not fit in the savearea "
Sunitha Harishf8a43472022-08-08 02:07:12 -0500197 "directory maximum allowed size[25MB]";
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500198 return;
199 }
200
asmithakarun1c7b07c2019-09-09 03:42:59 -0500201 file.open(loc, std::ofstream::out);
Sunitha Harish3e919b52020-10-13 01:21:48 -0500202
203 // set the permission of the file to 600
204 std::filesystem::perms permission = std::filesystem::perms::owner_write |
205 std::filesystem::perms::owner_read;
206 std::filesystem::permissions(loc, permission);
207
asmithakarun1c7b07c2019-09-09 03:42:59 -0500208 if (file.fail())
209 {
Ed Tanous62598e32023-07-17 17:06:25 -0700210 BMCWEB_LOG_DEBUG("Error while opening the file for writing");
Sunitha Harishdb81c072021-01-21 23:33:21 -0600211 asyncResp->res.result(
212 boost::beast::http::status::internal_server_error);
213 asyncResp->res.jsonValue["Description"] =
214 "Error while creating the file";
asmithakarun1c7b07c2019-09-09 03:42:59 -0500215 return;
Sunitha Harish97b0e432019-11-21 04:59:29 -0600216 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700217 file << data;
Sunitha Harish3e919b52020-10-13 01:21:48 -0500218
Ed Tanous3174e4d2020-10-07 11:41:22 -0700219 // Push an event
220 if (fileExists)
221 {
Ed Tanous62598e32023-07-17 17:06:25 -0700222 BMCWEB_LOG_DEBUG("config file is updated");
Sunitha Harishdb81c072021-01-21 23:33:21 -0600223 asyncResp->res.jsonValue["Description"] = "File Updated";
Ed Tanous3174e4d2020-10-07 11:41:22 -0700224 }
Sunitha Harish97b0e432019-11-21 04:59:29 -0600225 else
226 {
Ed Tanous62598e32023-07-17 17:06:25 -0700227 BMCWEB_LOG_DEBUG("config file is created");
Sunitha Harishdb81c072021-01-21 23:33:21 -0600228 asyncResp->res.jsonValue["Description"] = "File Created";
asmithakarun1c7b07c2019-09-09 03:42:59 -0500229 }
Ratan Guptad3630cb2019-12-14 11:21:35 +0530230}
asmithakarun1c7b07c2019-09-09 03:42:59 -0500231
Patrick Williams504af5a2025-02-03 14:29:03 -0500232inline void handleConfigFileList(
233 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ratan Guptad3630cb2019-12-14 11:21:35 +0530234{
235 std::vector<std::string> pathObjList;
Sunitha Harish3e919b52020-10-13 01:21:48 -0500236 std::filesystem::path loc(
237 "/var/lib/bmcweb/ibm-management-console/configfiles");
Ratan Guptad3630cb2019-12-14 11:21:35 +0530238 if (std::filesystem::exists(loc) && std::filesystem::is_directory(loc))
239 {
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500240 for (const auto& file : std::filesystem::directory_iterator(loc))
Ratan Guptad3630cb2019-12-14 11:21:35 +0530241 {
Ed Tanous3174e4d2020-10-07 11:41:22 -0700242 const std::filesystem::path& pathObj = file.path();
cm-jishnu5a193962022-12-02 03:45:27 -0600243 if (std::filesystem::is_regular_file(pathObj))
244 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400245 pathObjList.emplace_back(
246 "/ibm/v1/Host/ConfigFiles/" + pathObj.filename().string());
cm-jishnu5a193962022-12-02 03:45:27 -0600247 }
Ratan Guptad3630cb2019-12-14 11:21:35 +0530248 }
249 }
Sunitha Harishdb81c072021-01-21 23:33:21 -0600250 asyncResp->res.jsonValue["@odata.type"] =
251 "#IBMConfigFile.v1_0_0.IBMConfigFile";
252 asyncResp->res.jsonValue["@odata.id"] = "/ibm/v1/Host/ConfigFiles/";
253 asyncResp->res.jsonValue["Id"] = "ConfigFiles";
254 asyncResp->res.jsonValue["Name"] = "ConfigFiles";
Ratan Guptad3630cb2019-12-14 11:21:35 +0530255
Sunitha Harishdb81c072021-01-21 23:33:21 -0600256 asyncResp->res.jsonValue["Members"] = std::move(pathObjList);
Ed Tanous20fa6a22024-05-20 18:02:58 -0700257 asyncResp->res.jsonValue["Actions"]["#IBMConfigFiles.DeleteAll"]["target"] =
258 "/ibm/v1/Host/ConfigFiles/Actions/IBMConfigFiles.DeleteAll";
Ratan Guptad3630cb2019-12-14 11:21:35 +0530259}
260
Patrick Williams504af5a2025-02-03 14:29:03 -0500261inline void deleteConfigFiles(
262 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ratan Guptad3630cb2019-12-14 11:21:35 +0530263{
Ratan Guptad3630cb2019-12-14 11:21:35 +0530264 std::error_code ec;
Sunitha Harish3e919b52020-10-13 01:21:48 -0500265 std::filesystem::path loc(
266 "/var/lib/bmcweb/ibm-management-console/configfiles");
Ratan Guptad3630cb2019-12-14 11:21:35 +0530267 if (std::filesystem::exists(loc) && std::filesystem::is_directory(loc))
268 {
269 std::filesystem::remove_all(loc, ec);
270 if (ec)
271 {
Sunitha Harishdb81c072021-01-21 23:33:21 -0600272 asyncResp->res.result(
273 boost::beast::http::status::internal_server_error);
274 asyncResp->res.jsonValue["Description"] = internalServerError;
Ed Tanous62598e32023-07-17 17:06:25 -0700275 BMCWEB_LOG_DEBUG("deleteConfigFiles: Failed to delete the "
276 "config files directory. ec : {}",
277 ec.message());
Ratan Guptad3630cb2019-12-14 11:21:35 +0530278 }
279 }
asmithakarun1c7b07c2019-09-09 03:42:59 -0500280}
281
Sunitha Harishdb81c072021-01-21 23:33:21 -0600282inline void handleFileGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
283 const std::string& fileID)
asmithakarun1c7b07c2019-09-09 03:42:59 -0500284{
Ed Tanous62598e32023-07-17 17:06:25 -0700285 BMCWEB_LOG_DEBUG("HandleGet on SaveArea files on path: {}", fileID);
Sunitha Harish3e919b52020-10-13 01:21:48 -0500286 std::filesystem::path loc(
287 "/var/lib/bmcweb/ibm-management-console/configfiles/" + fileID);
cm-jishnu5a193962022-12-02 03:45:27 -0600288 if (!std::filesystem::exists(loc) || !std::filesystem::is_regular_file(loc))
asmithakarun1c7b07c2019-09-09 03:42:59 -0500289 {
Ed Tanous62598e32023-07-17 17:06:25 -0700290 BMCWEB_LOG_WARNING("{} Not found", loc.string());
Sunitha Harishdb81c072021-01-21 23:33:21 -0600291 asyncResp->res.result(boost::beast::http::status::not_found);
292 asyncResp->res.jsonValue["Description"] = resourceNotFoundMsg;
asmithakarun1c7b07c2019-09-09 03:42:59 -0500293 return;
294 }
295
296 std::ifstream readfile(loc.string());
297 if (!readfile)
298 {
Ed Tanous62598e32023-07-17 17:06:25 -0700299 BMCWEB_LOG_WARNING("{} Not found", loc.string());
Sunitha Harishdb81c072021-01-21 23:33:21 -0600300 asyncResp->res.result(boost::beast::http::status::not_found);
301 asyncResp->res.jsonValue["Description"] = resourceNotFoundMsg;
asmithakarun1c7b07c2019-09-09 03:42:59 -0500302 return;
303 }
304
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400305 std::string contentDispositionParam =
306 "attachment; filename=\"" + fileID + "\"";
Ed Tanousd9f6c622022-03-17 09:12:17 -0700307 asyncResp->res.addHeader(boost::beast::http::field::content_disposition,
308 contentDispositionParam);
asmithakarun1c7b07c2019-09-09 03:42:59 -0500309 std::string fileData;
310 fileData = {std::istreambuf_iterator<char>(readfile),
311 std::istreambuf_iterator<char>()};
Sunitha Harishdb81c072021-01-21 23:33:21 -0600312 asyncResp->res.jsonValue["Data"] = fileData;
asmithakarun1c7b07c2019-09-09 03:42:59 -0500313}
314
Patrick Williams504af5a2025-02-03 14:29:03 -0500315inline void handleFileDelete(
316 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
317 const std::string& fileID)
asmithakarun1c7b07c2019-09-09 03:42:59 -0500318{
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400319 std::string filePath(
320 "/var/lib/bmcweb/ibm-management-console/configfiles/" + fileID);
Ed Tanous62598e32023-07-17 17:06:25 -0700321 BMCWEB_LOG_DEBUG("Removing the file : {}", filePath);
Ed Tanous2c70f802020-09-28 14:29:23 -0700322 std::ifstream fileOpen(filePath.c_str());
323 if (static_cast<bool>(fileOpen))
Ed Tanous3174e4d2020-10-07 11:41:22 -0700324 {
asmithakarun1c7b07c2019-09-09 03:42:59 -0500325 if (remove(filePath.c_str()) == 0)
326 {
Ed Tanous62598e32023-07-17 17:06:25 -0700327 BMCWEB_LOG_DEBUG("File removed!");
Sunitha Harishdb81c072021-01-21 23:33:21 -0600328 asyncResp->res.jsonValue["Description"] = "File Deleted";
asmithakarun1c7b07c2019-09-09 03:42:59 -0500329 }
330 else
331 {
Ed Tanous62598e32023-07-17 17:06:25 -0700332 BMCWEB_LOG_ERROR("File not removed!");
Sunitha Harishdb81c072021-01-21 23:33:21 -0600333 asyncResp->res.result(
334 boost::beast::http::status::internal_server_error);
335 asyncResp->res.jsonValue["Description"] = internalServerError;
asmithakarun1c7b07c2019-09-09 03:42:59 -0500336 }
Ed Tanous3174e4d2020-10-07 11:41:22 -0700337 }
asmithakarun1c7b07c2019-09-09 03:42:59 -0500338 else
339 {
Ed Tanous62598e32023-07-17 17:06:25 -0700340 BMCWEB_LOG_WARNING("File not found!");
Sunitha Harishdb81c072021-01-21 23:33:21 -0600341 asyncResp->res.result(boost::beast::http::status::not_found);
342 asyncResp->res.jsonValue["Description"] = resourceNotFoundMsg;
Sunitha Harish97b0e432019-11-21 04:59:29 -0600343 }
Sunitha Harish97b0e432019-11-21 04:59:29 -0600344}
345
Patrick Williams504af5a2025-02-03 14:29:03 -0500346inline void handleBroadcastService(
347 const crow::Request& req,
348 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Asmitha Karunanithi5738de52020-07-17 02:03:31 -0500349{
350 std::string broadcastMsg;
351
Willy Tu15ed6782021-12-14 11:03:16 -0800352 if (!redfish::json_util::readJsonPatch(req, asyncResp->res, "Message",
353 broadcastMsg))
Asmitha Karunanithi5738de52020-07-17 02:03:31 -0500354 {
Ed Tanous62598e32023-07-17 17:06:25 -0700355 BMCWEB_LOG_DEBUG("Not a Valid JSON");
Sunitha Harishdb81c072021-01-21 23:33:21 -0600356 asyncResp->res.result(boost::beast::http::status::bad_request);
Asmitha Karunanithi5738de52020-07-17 02:03:31 -0500357 return;
358 }
359 if (broadcastMsg.size() > maxBroadcastMsgSize)
360 {
Ed Tanous62598e32023-07-17 17:06:25 -0700361 BMCWEB_LOG_ERROR("Message size exceeds maximum allowed size[1KB]");
Sunitha Harishdb81c072021-01-21 23:33:21 -0600362 asyncResp->res.result(boost::beast::http::status::bad_request);
Asmitha Karunanithi5738de52020-07-17 02:03:31 -0500363 return;
364 }
Asmitha Karunanithi5738de52020-07-17 02:03:31 -0500365}
366
zhanghch058d1b46d2021-04-01 11:18:24 +0800367inline void handleFileUrl(const crow::Request& req,
368 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500369 const std::string& fileID)
Sunitha Harish97b0e432019-11-21 04:59:29 -0600370{
Ed Tanousb41187f2019-10-24 16:30:02 -0700371 if (req.method() == boost::beast::http::verb::put)
Sunitha Harish97b0e432019-11-21 04:59:29 -0600372 {
Sunitha Harishdb81c072021-01-21 23:33:21 -0600373 handleFilePut(req, asyncResp, fileID);
Sunitha Harish97b0e432019-11-21 04:59:29 -0600374 return;
375 }
Ed Tanousb41187f2019-10-24 16:30:02 -0700376 if (req.method() == boost::beast::http::verb::get)
asmithakarun1c7b07c2019-09-09 03:42:59 -0500377 {
Sunitha Harishdb81c072021-01-21 23:33:21 -0600378 handleFileGet(asyncResp, fileID);
asmithakarun1c7b07c2019-09-09 03:42:59 -0500379 return;
380 }
Ed Tanousb41187f2019-10-24 16:30:02 -0700381 if (req.method() == boost::beast::http::verb::delete_)
asmithakarun1c7b07c2019-09-09 03:42:59 -0500382 {
Sunitha Harishdb81c072021-01-21 23:33:21 -0600383 handleFileDelete(asyncResp, fileID);
asmithakarun1c7b07c2019-09-09 03:42:59 -0500384 return;
385 }
Sunitha Harish97b0e432019-11-21 04:59:29 -0600386}
Ratan Gupta453fed02019-12-14 09:39:47 +0530387
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500388inline bool isValidConfigFileName(const std::string& fileName,
389 crow::Response& res)
390{
391 if (fileName.empty())
392 {
Ed Tanous62598e32023-07-17 17:06:25 -0700393 BMCWEB_LOG_ERROR("Empty filename");
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500394 res.jsonValue["Description"] = "Empty file path in the url";
395 return false;
396 }
397
398 // ConfigFile name is allowed to take upper and lowercase letters,
399 // numbers and hyphen
400 std::size_t found = fileName.find_first_not_of(
401 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-");
402 if (found != std::string::npos)
403 {
Ed Tanous62598e32023-07-17 17:06:25 -0700404 BMCWEB_LOG_ERROR("Unsupported character in filename: {}", fileName);
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500405 res.jsonValue["Description"] = "Unsupported character in filename";
406 return false;
407 }
408
409 // Check the filename length
410 if (fileName.length() > 20)
411 {
Ed Tanous62598e32023-07-17 17:06:25 -0700412 BMCWEB_LOG_ERROR("Name must be maximum 20 characters. "
413 "Input filename length is: {}",
414 fileName.length());
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500415 res.jsonValue["Description"] = "Filename must be maximum 20 characters";
416 return false;
417 }
418
419 return true;
420}
421
Ed Tanous02379d32020-09-15 21:15:44 -0700422inline void requestRoutes(App& app)
Ratan Gupta453fed02019-12-14 09:39:47 +0530423{
Ratan Gupta453fed02019-12-14 09:39:47 +0530424 // allowed only for admin
425 BMCWEB_ROUTE(app, "/ibm/v1/")
Ed Tanous432a8902021-06-14 15:28:56 -0700426 .privileges({{"ConfigureComponents", "ConfigureManager"}})
Ed Tanousb41187f2019-10-24 16:30:02 -0700427 .methods(boost::beast::http::verb::get)(
zhanghch058d1b46d2021-04-01 11:18:24 +0800428 [](const crow::Request&,
429 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400430 asyncResp->res.jsonValue["@odata.type"] =
431 "#ibmServiceRoot.v1_0_0.ibmServiceRoot";
432 asyncResp->res.jsonValue["@odata.id"] = "/ibm/v1/";
433 asyncResp->res.jsonValue["Id"] = "IBM Rest RootService";
434 asyncResp->res.jsonValue["Name"] = "IBM Service Root";
435 asyncResp->res.jsonValue["ConfigFiles"]["@odata.id"] =
436 "/ibm/v1/Host/ConfigFiles";
437 asyncResp->res.jsonValue["BroadcastService"]["@odata.id"] =
438 "/ibm/v1/HMC/BroadcastService";
439 });
Sunitha Harish97b0e432019-11-21 04:59:29 -0600440
Ratan Guptad3630cb2019-12-14 11:21:35 +0530441 BMCWEB_ROUTE(app, "/ibm/v1/Host/ConfigFiles")
Ed Tanous432a8902021-06-14 15:28:56 -0700442 .privileges({{"ConfigureComponents", "ConfigureManager"}})
Ed Tanousb41187f2019-10-24 16:30:02 -0700443 .methods(boost::beast::http::verb::get)(
zhanghch058d1b46d2021-04-01 11:18:24 +0800444 [](const crow::Request&,
445 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400446 handleConfigFileList(asyncResp);
447 });
Ratan Guptad3630cb2019-12-14 11:21:35 +0530448
449 BMCWEB_ROUTE(app,
Sunitha Harishe56f2542020-07-22 02:38:59 -0500450 "/ibm/v1/Host/ConfigFiles/Actions/IBMConfigFiles.DeleteAll")
Ed Tanous432a8902021-06-14 15:28:56 -0700451 .privileges({{"ConfigureComponents", "ConfigureManager"}})
Ed Tanousb41187f2019-10-24 16:30:02 -0700452 .methods(boost::beast::http::verb::post)(
zhanghch058d1b46d2021-04-01 11:18:24 +0800453 [](const crow::Request&,
454 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400455 deleteConfigFiles(asyncResp);
456 });
Ratan Guptad3630cb2019-12-14 11:21:35 +0530457
Sunitha Harish7c0bbe72020-07-30 08:25:28 -0500458 BMCWEB_ROUTE(app, "/ibm/v1/Host/ConfigFiles/<str>")
Ed Tanous432a8902021-06-14 15:28:56 -0700459 .privileges({{"ConfigureComponents", "ConfigureManager"}})
zhanghch058d1b46d2021-04-01 11:18:24 +0800460 .methods(boost::beast::http::verb::put, boost::beast::http::verb::get,
461 boost::beast::http::verb::delete_)(
462 [](const crow::Request& req,
463 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
464 const std::string& fileName) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400465 BMCWEB_LOG_DEBUG("ConfigFile : {}", fileName);
466 // Validate the incoming fileName
467 if (!isValidConfigFileName(fileName, asyncResp->res))
468 {
469 asyncResp->res.result(
470 boost::beast::http::status::bad_request);
471 return;
472 }
473 handleFileUrl(req, asyncResp, fileName);
474 });
Ratan Gupta734a1c32019-12-14 11:53:48 +0530475
Asmitha Karunanithi5738de52020-07-17 02:03:31 -0500476 BMCWEB_ROUTE(app, "/ibm/v1/HMC/BroadcastService")
Ed Tanous432a8902021-06-14 15:28:56 -0700477 .privileges({{"ConfigureComponents", "ConfigureManager"}})
Asmitha Karunanithi5738de52020-07-17 02:03:31 -0500478 .methods(boost::beast::http::verb::post)(
zhanghch058d1b46d2021-04-01 11:18:24 +0800479 [](const crow::Request& req,
480 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400481 handleBroadcastService(req, asyncResp);
482 });
Ratan Gupta453fed02019-12-14 09:39:47 +0530483}
484
485} // namespace ibm_mc
486} // namespace crow