Handling of adding certificates the Redfish way

Added handling for POSTing certificates the Redfish way (as proper JSON).
Currently it was only possible to add certificate as a RAW certificate in
request body. Now user is able to add it as
{
	"CertificateType": "PEM",
	"CertificateString": "..."
}
as well as previously in RAW form.

Tested:
- Uploading certificates in RAW form
- Uploading certificates in JSON form
- Uploading invalid certificates
- Uploading invalid JSON requests

Change-Id: Icf0f6b928e63fc3cc5cd089b483b3799fbe715de
Signed-off-by: Kowalski, Kamil <kamil.kowalski@intel.com>
diff --git a/redfish-core/lib/certificate_service.hpp b/redfish-core/lib/certificate_service.hpp
index f2cd966..111bcec 100644
--- a/redfish-core/lib/certificate_service.hpp
+++ b/redfish-core/lib/certificate_service.hpp
@@ -117,6 +117,39 @@
     return -1;
 }
 
+std::string
+    getCertificateFromReqBody(const std::shared_ptr<AsyncResp> &asyncResp,
+                              const crow::Request &req)
+{
+    nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false);
+
+    if (reqJson.is_discarded())
+    {
+        // We did not receive JSON request, proceed as it is RAW data
+        return req.body;
+    }
+
+    std::string certificate;
+    std::optional<std::string> certificateType = "PEM";
+
+    if (!json_util::readJson(reqJson, asyncResp->res, "CertificateString",
+                             certificate, "CertificateType", certificateType))
+    {
+        BMCWEB_LOG_ERROR << "Required parameters are missing";
+        messages::internalError(asyncResp->res);
+        return std::string();
+    }
+
+    if (*certificateType != "PEM")
+    {
+        messages::propertyValueNotInList(asyncResp->res, *certificateType,
+                                         "CertificateType");
+        return std::string();
+    }
+
+    return certificate;
+}
+
 /**
  * Class to create a temporary certificate file for uploading to system
  */
@@ -897,8 +930,15 @@
         asyncResp->res.jsonValue = {{"Name", "HTTPS Certificate"},
                                     {"Description", "HTTPS Certificate"}};
 
+        std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
+
+        if (certFileBody.empty())
+        {
+            return;
+        }
+
         std::shared_ptr<CertificateFile> certFile =
-            std::make_shared<CertificateFile>(req.body);
+            std::make_shared<CertificateFile>(certFileBody);
 
         crow::connections::systemBus->async_method_call(
             [asyncResp, certFile](const boost::system::error_code ec) {
@@ -1083,9 +1123,17 @@
     void doPost(crow::Response &res, const crow::Request &req,
                 const std::vector<std::string> &params) override
     {
-        std::shared_ptr<CertificateFile> certFile =
-            std::make_shared<CertificateFile>(req.body);
         auto asyncResp = std::make_shared<AsyncResp>(res);
+        std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
+
+        if (certFileBody.empty())
+        {
+            return;
+        }
+
+        std::shared_ptr<CertificateFile> certFile =
+            std::make_shared<CertificateFile>(certFileBody);
+
         crow::connections::systemBus->async_method_call(
             [asyncResp, certFile](const boost::system::error_code ec) {
                 if (ec)