/*
// Copyright (c) 2023 Google
/
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
#pragma once

#include "app.hpp"
#include "component_integrity.hpp"
#include "dbus_utility.hpp"
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "processor.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "chassis_utils.hpp"
#include "system_utils.hpp"
#include "collection.hpp"
#include "dbus_utils.hpp"
#include "json_utils.hpp"
#include "system_utils.hpp"

#include <boost/container/flat_map.hpp>
#include <boost/system/error_code.hpp>
#include <boost/url/format.hpp>
#include <sdbusplus/asio/property.hpp>
#include <sdbusplus/message/native_types.hpp>
#include <sdbusplus/unpack_properties.hpp>
#include <sdbusplus/utility/dedup_variant.hpp>

#include <array>
#include <limits>
#include <regex>
#include <string_view>
#include <tuple>
#include <variant>
#include <vector>

#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp" // NOLINT
#endif

namespace redfish
{
// Interfaces which imply a D-Bus object represents a TrustedComponent
constexpr std::array<std::string_view, 1> trustedComponentInterfaces = {
    "xyz.openbmc_project.Inventory.Item.TrustedComponent"};
constexpr char const* discreteAttachType =
    "xyz.openbmc_project.Inventory.Item.TrustedComponent.ComponentAttachType.Discrete";
constexpr char const* integratedAttachType =
    "xyz.openbmc_project.Inventory.Item.TrustedComponent.ComponentAttachType.Integrated";
constexpr char const* decoratorAssetIntf =
    "xyz.openbmc_project.Inventory.Decorator.Asset";
constexpr char const* uuidIntf =
    "xyz.openbmc_project.Common.UUID";
constexpr char const* trustedComponentIntf =
    "xyz.openbmc_project.Inventory.Item.TrustedComponent";

/**
 * Map a given vector of D-Bus object path to an array of Redfish
 * URI.
 *
 * @param[in]       property1       Redfish property name.
 * @param[in]       property2       Optional second Redfish property name.
 * @param[in]       nodeList        vector of path string.
 *
 * @return          entities        Array of Redfish URI in json.
 */
inline std::optional<nlohmann::json>
    mapObjectPathVector(const std::string& property1,
                        const std::string& property2,
                        const std::vector<std::string>& pathList)
{
    nlohmann::json entities = nlohmann::json::array();

    for (const std::string& node : pathList)
    {
        sdbusplus::message::object_path path(node);
        std::string entityId = path.filename();
        if (entityId.empty())
        {
            BMCWEB_LOG_ERROR << "Invalid object path:" << property1 << " "
                             << property2 << ":" << path.str;
            return std::nullopt;
        }

        nlohmann::json::object_t entity;
        if (property2.empty())
        {
            entity["@odata.id"] = crow::utility::urlFromPieces(
                "redfish", "v1", property1, entityId);
        } else
        {
            entity["@odata.id"] = crow::utility::urlFromPieces(
                "redfish", "v1", property1, property2, entityId);
        }
        entities.push_back(std::move(entity));
    }

    return {std::move(entities)};
}

/**
 * Find the D-Bus object representing the requested TrustedComponent, and call
 * the handler with the results. If matching object is not found, add 404 error
 * to response and don't call the handler.
 *
 * @param[in,out]   resp            Async HTTP response.
 * @param[in]       chassisId       Redfish Chassis Id.
 * @param[in]       componentId     Redfish TrustedComponent Id.
 * @param[in]       handler         Callback to continue processing request upon
 *                                  successfully finding object.
 */
template <typename Handler>
inline void
    getTrustedComponentObject(const std::shared_ptr<bmcweb::AsyncResp>& resp,
                              const std::string& chassisId,
                              const std::string& componentId,
                              Handler&& handler)
{
    BMCWEB_LOG_DEBUG << "Get available chassis trusted_component resources.";

    // GetSubTree on all interfaces which provide info about TrustedComponent
    constexpr std::array<std::string_view, 1> interfaces = {
        trustedComponentIntf};
    std::string trustedComponentsPath =
        sdbusplus::message::object_path("/xyz/openbmc_project/Chassis") /
        chassisId / "TrustedComponents" ;
    managedStore::ManagedObjectStoreContext context(resp);
    managedStore::GetManagedObjectStore()->getSubTree(
        trustedComponentsPath, 0, interfaces, context,
        [resp, chassisId, componentId, handler](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
            messages::internalError(resp->res);
            return;
        }

        for (const auto& [objectPath, serviceMap] : subtree)
        {
            // Ignore any objects which don't end with our desired component
            // name
            if (!objectPath.ends_with(componentId))
            {
                continue;
            }

            bool found = false;
            for (const auto& [serviceName, interfaceList] : serviceMap)
            {
                if (std::find_first_of(interfaceList.begin(),
                                       interfaceList.end(),
                                       trustedComponentInterfaces.begin(),
                                       trustedComponentInterfaces.end()) !=
                    interfaceList.end())
                {
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                continue;
            }

            // Found something, populate Name and Id before get Interface info
            resp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
                "redfish", "v1", "Chassis", chassisId, "TrustedComponents",
                componentId);
            resp->res.jsonValue["Name"] = componentId;
            resp->res.jsonValue["Id"] = componentId;

            handler(objectPath, serviceMap);
            return;
        }
        messages::resourceNotFound(resp->res, "TrustedComponent", componentId);
    });
}

inline void getTrustedComponentIntegratedIntoInfo(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& trustedComponentObjPath,
    const boost::system::error_code& ec,
    const dbus::utility::MapperEndPoints& integratedIntoObjPaths)
{
    if (ec)
    {
        if (ec.value() != EBADR)
        {
            BMCWEB_LOG_ERROR << "DBUS response error " << ec;
            messages::internalError(asyncResp->res);
        }
        return;
    }

    if (integratedIntoObjPaths.empty())
    {
        return;
    }

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    for (const auto& objpath: integratedIntoObjPaths)
    {
        sdbusplus::message::object_path integratedIntoObjPath(objpath);
        const std::string objName = integratedIntoObjPath.filename();
        if (objName.empty())
        {
            BMCWEB_LOG_WARNING << "Malformed integratedInto object path "
                               << integratedIntoObjPath.str << " for "
                               << trustedComponentObjPath;
            continue;
        }
        managedStore::GetManagedObjectStore()->getDbusObject(
            objpath, {}, requestContext,
            [asyncResp, integratedIntoObjPath, trustedComponentObjPath,
             requestContext, objName](
                const boost::system::error_code& ec2,
                const dbus::utility::MapperGetObject& object) {
            if (ec2)
            {
                BMCWEB_LOG_ERROR << "DBUS response error";
                messages::internalError(asyncResp->res);
                return;
            }

            nlohmann::json::object_t integratedPath;

            // Link can be Chassis or Board, Processor, and NetworkAdapters
            // handle Chassis or Board case
            if (redfish::dbus_utils::findInterfacesInServiceMap(
                    object, redfish::chassis_utils::chassisInterfaces))
            {
                integratedPath["@odata.id"] = crow::utility::urlFromPieces(
                    "redfish", "v1", "Chassis", objName);
                asyncResp->res.jsonValue["Links"]["IntegratedInto"] =
                    std::move(integratedPath);
                return;
            }

            // handle NetworkAdaptors: parent resource can only be Chassis.
            if (redfish::dbus_utils::findInterfacesInServiceMap(
                    object, networkAdapterInterfaces))
            {
                const std::string parentObj =
                    integratedIntoObjPath.parent_path().filename();
                if (parentObj.empty())
                {
                    BMCWEB_LOG_WARNING << "Malformed integratedInto object path "
                                       << integratedIntoObjPath.str << " for "
                                       << trustedComponentObjPath;
                    return;
                }

                integratedPath["@odata.id"] = crow::utility::urlFromPieces(
                    "redfish", "v1", "Chassis", parentObj, "NetworkAdapters", objName);
                asyncResp->res.jsonValue["Links"]["IntegratedInto"] =
                    std::move(integratedPath);
                return;
            }

            if (redfish::dbus_utils::findInterfacesInServiceMap(
                    object, processorsInterfaces))
            {
                std::string parentPath =
                    integratedIntoObjPath.parent_path().str;
                std::string parentObj =
                    integratedIntoObjPath.parent_path().filename();
                // e.g., /xyz/openbmc_project/inventory/system/board/BoardName/system1/chassis/motherboard/cpu0
                // filter out chassis|motherboard in object path.
                while (parentObj == "motherboard" || parentObj == "chassis") {
                    sdbusplus::message::object_path tempObjPath(parentPath);
                    parentPath = tempObjPath.parent_path().str;
                    parentObj = tempObjPath.parent_path().filename();
                }
                if (parentObj.empty())
                {
                    BMCWEB_LOG_WARNING << "Malformed integratedInto object path "
                                       << integratedIntoObjPath.str << " for "
                                       << trustedComponentObjPath;
                    return;
                }
                managedStore::GetManagedObjectStore()->getDbusObject(
                    parentPath, {}, requestContext,
                    [asyncResp, objName,
                     parentObj](const boost::system::error_code& ec2,
                                        const dbus::utility::MapperGetObject& object) {
                    if (ec2)
                    {
                        BMCWEB_LOG_ERROR << "DBUS response error";
                        messages::internalError(asyncResp->res);
                        return;
                    }

                    // handle Processor: parent resource has to be Systems as OpenBMC
                    // only search for Processor under Systems though Redfish SPEC
                    // allows Processors to be modeled under Chassis starting from
                    // DSP2046_2022.3.pdf.
                    nlohmann::json::object_t integratedProcessorPath;
                    std::string parentResourceType;
                    std::string parentResourceName;
                    if (redfish::dbus_utils::findInterfacesInServiceMap(
                            object, redfish::chassis_utils::chassisInterfaces))
                    {
                        parentResourceType = "Systems";
                        parentResourceName = "system";
                    } else if (redfish::dbus_utils::findInterfacesInServiceMap(
                            object, redfish::system_utils::systemInterfaces))
                    {
                        parentResourceType = "Systems";
                        parentResourceName = parentObj;
                    } else
                    {
                        BMCWEB_LOG_ERROR << "Parent resource type not "
                                            "supported for Processor resource";
                        messages::internalError(asyncResp->res);
                        return;
                    }

                    integratedProcessorPath["@odata.id"] = crow::utility::urlFromPieces(
                        "redfish", "v1", parentResourceType, parentResourceName,
                        "Processors", objName);
                    asyncResp->res.jsonValue["Links"]["IntegratedInto"] =
                        std::move(integratedProcessorPath);
                    return;
                });

                return;
            } // end of Processor interfaces handling

            // Unsupported resource type
            BMCWEB_LOG_ERROR << "Unsupported IntegratedInto resource for "
                             << integratedIntoObjPath.str;
            messages::internalError(asyncResp->res);
            return;
        });
    }
}

/**
 * @brief Fill out TrustedComponent interface related info by
 * requesting data from the given D-Bus object.
 *
 * @param[in,out]   aResp       Async HTTP response.
 * @param[in]       service     D-Bus service to query.
 * @param[in]       objPath     D-Bus object to query.
 */
inline void
    getTrustedComponentInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                                     const std::string& service,
                                     const std::string& objPath)
{
    BMCWEB_LOG_DEBUG << "Get TrustedComponent Interface Data";
    managedStore::ManagedObjectStoreContext context(aResp);
    managedStore::GetManagedObjectStore()->getAllProperties(
        service, objPath,
        trustedComponentIntf,
        context,
        [objPath, aResp{aResp}, context](
            const boost::system::error_code& ec,
            const std::vector<std::pair<
                std::string, dbus::utility::DbusVariantType>>& properties) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "DBUS response error";
            messages::internalError(aResp->res);
            return;
        }

        const std::string* type = nullptr;
        const std::string* firmwareVersion = nullptr;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), properties, "FirmwareVersion",
            firmwareVersion, "TrustedComponentType", type);

        if (!success)
        {
            messages::internalError(aResp->res);
            return;
        }

        if ((firmwareVersion != nullptr) && !firmwareVersion->empty())
        {
            aResp->res.jsonValue["FirmwareVersion"] = *firmwareVersion;
        }

        // For Root-of-Trust, it is safe to hardcode it as Embedded.
        aResp->res.jsonValue["Location"]["PartLocation"]["LocationType"] =
            "Embedded";

        // Get active software image info from associations.
        std::string activeSoftwarePath = objPath + "/actively_running";
        dbus_utils::getAssociationEndPoints(
            activeSoftwarePath, context,
            [aResp](
                const boost::system::error_code& e,
                const dbus::utility::MapperEndPoints& nodeActiveSoftwareList) {
            if (e)
            {
                if (e.value() != EBADR)
                {
                    messages::internalError(aResp->res);
                    return;
                }
                // No resource found.
                return;
            }

            // One TrustedComponent object should be associated with one
            // activeSoftwareImage object
            if (nodeActiveSoftwareList.size() != 1)
            {
                BMCWEB_LOG_ERROR
                    << "Unexpected ActiveSoftwareImage #objs (expecting 1): "
                    << nodeActiveSoftwareList.size();
                messages::internalError(aResp->res);
                return;
            }

            const std::string& softwareImageURI =
                nodeActiveSoftwareList.at(0);
            sdbusplus::message::object_path activeSoftwareImage(
                softwareImageURI);
            std::string softwareId = activeSoftwareImage.filename();

            nlohmann::json::object_t imagePath;

            if (softwareId.empty())
            {
                BMCWEB_LOG_ERROR
                    << "TrustedComponent contains invalid activeSoftwareImage:"
                    << activeSoftwareImage.str;
                messages::internalError(aResp->res);
                return;
            }

            imagePath["@odata.id"] = crow::utility::urlFromPieces(
                "redfish", "v1", "UpdateService", "FirmwareInventory",
                softwareId);
            aResp->res.jsonValue["Links"]["ActiveSoftwareImage"] =
                std::move(imagePath);
        });

        // Get ComponentIntegrity info from associations.
        std::string componentIntegrityPath = objPath + "/reported_by";
        dbus_utils::getAssociationEndPoints(
            componentIntegrityPath, context,
            [aResp](const boost::system::error_code& e,
                    const dbus::utility::MapperEndPoints&
                        nodeComponentIntegrityList) {
            if (e)
            {
                if (e.value() != EBADR)
                {
                    messages::internalError(aResp->res);
                    return;
                }
                // No resource found.
                return;
            }

            if (nodeComponentIntegrityList.empty())
            {
                BMCWEB_LOG_DEBUG << "No ComponentIntegrity objects found!";
                return;
            }

            std::optional<nlohmann::json> components = mapObjectPathVector(
                "ComponentIntegrity", "", nodeComponentIntegrityList);
            if (!components)
            {
                BMCWEB_LOG_ERROR << "ComponentIntegrity is invalid.";
                messages::internalError(aResp->res);
                return;
            }

            aResp->res.jsonValue["Links"]["ComponentIntegrity"] = *components;
        });

        // Get protected components info from associations.
        std::string protectedComponentPath = objPath + "/protecting";
        dbus_utils::getAssociationEndPoints(
            protectedComponentPath, context,
            std::bind_front(getProtectedComponentsInfo, aResp,
            objPath));

        // Get integratedInto info from associations.
        std::string integratedInto = objPath + "/integrated_into";
        dbus_utils::getAssociationEndPoints(
            integratedInto, context,
            std::bind_front(getTrustedComponentIntegratedIntoInfo, aResp,
            objPath));

        // Get software images info from associations.
        std::string softwareImagesPath = objPath + "/runs";
        dbus_utils::getAssociationEndPoints(
            softwareImagesPath, context,
            [aResp](
                const boost::system::error_code& e,
                const dbus::utility::MapperEndPoints& nodeSoftwareImagesList) {
            if (e)
            {
                if (e.value() != EBADR)
                {
                    messages::internalError(aResp->res);
                    return;
                }
                // No resource found.
                return;
            }

            // One TrustedComponent object may be associated with one
            // or more SoftwareImage objects
            if (nodeSoftwareImagesList.empty())
            {
                BMCWEB_LOG_DEBUG << "No software image objects found!";
                return;
            }

            std::optional<nlohmann::json> images =
                mapObjectPathVector("UpdateService", "FirmwareInventory",
                                    nodeSoftwareImagesList);
            if (!images)
            {
                BMCWEB_LOG_ERROR << "SoftwareImages is invalid.";
                messages::internalError(aResp->res);
                return;
            }
            aResp->res.jsonValue["Links"]["SoftwareImages"] = *images;
        });

        if ((type != nullptr) && !type->empty())
        {
            if (*type == discreteAttachType)
            {
                aResp->res.jsonValue["TrustedComponentType"] = "Discrete";
            } else if (*type == integratedAttachType)
            {
                aResp->res.jsonValue["TrustedComponentType"] = "Integrated";
            } else
            {
                BMCWEB_LOG_ERROR << "Unrecognized ComponentAttachType!";
                messages::internalError(aResp->res);
                return;
            }
        } else {
            BMCWEB_LOG_ERROR << "No ComponentAttachType found!";
            messages::internalError(aResp->res);
            return;
        }
    });
}

/**
 * @brief Fill out Inventory.Decorator.Asset interface related info by
 * requesting data from the given D-Bus object.
 *
 * @param[in,out]   aResp       Async HTTP response.
 * @param[in]       service     D-Bus service to query.
 * @param[in]       objPath     D-Bus object to query.
 */
inline void
    getDecoratorAssetInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                                     const std::string& service,
                                     const std::string& objPath)
{
    BMCWEB_LOG_DEBUG << "Get Decorator.Asset Interface Data";
    managedStore::ManagedObjectStoreContext context(aResp);
    managedStore::GetManagedObjectStore()->getAllProperties(
        service, objPath,
        decoratorAssetIntf,
        context,
        [objPath, aResp{aResp}, context](
            const boost::system::error_code& ec,
            const std::vector<std::pair<
                std::string, dbus::utility::DbusVariantType>>& properties) {
        if (ec)
        {
            BMCWEB_LOG_ERROR<< "DBUS response error for DecoratorAssetIntf!";
            messages::internalError(aResp->res);
            return;
        }

        const std::string* manufacturer = nullptr;
        const std::string* serialNumber = nullptr;
        const std::string* sku = nullptr;
        const std::string* partNumber = nullptr;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), properties,
            "Manufacturer", manufacturer, "SerialNumber",
            serialNumber, "PartNumber", partNumber, "SKU", sku);

        if (!success)
        {
            BMCWEB_LOG_ERROR<< "Unpacking Inventory.Decorator.Asset failed!";
            messages::internalError(aResp->res);
            return;
        }

        if ((manufacturer != nullptr) && !manufacturer->empty())
        {
            aResp->res.jsonValue["Manufacturer"] = *manufacturer;
        }

        if ((serialNumber != nullptr) && !serialNumber->empty())
        {
            aResp->res.jsonValue["SerialNumber"] = *serialNumber;
        }

        if ((sku != nullptr) && !sku->empty())
        {
            aResp->res.jsonValue["SKU"] = *sku;
        }

        if ((partNumber != nullptr) && !partNumber->empty())
        {
            aResp->res.jsonValue["PartNumber"] = *partNumber;
        }
    });
}

/**
 * @brief Fill out Common.UUID interface related info by
 * requesting data from the given D-Bus object.
 *
 * @param[in,out]   aResp       Async HTTP response.
 * @param[in]       service     D-Bus service to query.
 * @param[in]       objPath     D-Bus object to query.
 */
inline void
    getCommonUUIDInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                                     const std::string& service,
                                     const std::string& objPath)
{
    BMCWEB_LOG_DEBUG << "Get Common.UUID Interface Data";
    managedStore::ManagedObjectStoreContext context(aResp);
    managedStore::GetManagedObjectStore()->getAllProperties(
        service, objPath,
        uuidIntf,
        context,
        [objPath, aResp{aResp}, context](
            const boost::system::error_code& ec,
            const std::vector<std::pair<
                std::string, dbus::utility::DbusVariantType>>& properties) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "DBUS response error";
            messages::internalError(aResp->res);
            return;
        }

        const std::string* uuid = nullptr;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), properties,
            "UUID", uuid);

        if (!success)
        {
            messages::internalError(aResp->res);
            return;
        }

        if ((uuid != nullptr) && !uuid->empty())
        {
            aResp->res.jsonValue["UUID"] = *uuid;
        }
    });
}

inline void
    getTrustedComponentData(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                            const std::string& objectPath,
                            const dbus::utility::MapperServiceMap& serviceMap)
{
    for (const auto& [serviceName, interfaceList] : serviceMap)
    {
        for (const auto& interface : interfaceList)
        {
            if (interface == trustedComponentIntf)
            {
                getTrustedComponentInterfaceData(aResp, serviceName,
                                                 objectPath);
            } else if (interface == decoratorAssetIntf)
            {
                getDecoratorAssetInterfaceData(aResp, serviceName,
                                               objectPath);
            } else if (interface == uuidIntf)
            {
                getCommonUUIDInterfaceData(aResp, serviceName, objectPath);
            }
        }
    }
}

inline void handleTrustedComponentGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId,
    const std::string& componentId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

    asyncResp->res.addHeader(
        boost::beast::http::field::link,
        "</redfish/v1/JsonSchemas/TrustedComponent/TrustedComponent.json>; rel=describedby");
    asyncResp->res.jsonValue["@odata.type"] =
        "#TrustedComponent.v1_0_0.TrustedComponent";

    getTrustedComponentObject(
        asyncResp, chassisId, componentId,
        std::bind_front(getTrustedComponentData, asyncResp));
}

inline void handleTrustedComponentCollectionGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

    boost::urls::url url = crow::utility::urlFromPieces(
        "redfish", "v1", "Chassis", chassisId, "TrustedComponents");

    asyncResp->res.jsonValue["@odata.type"] =
        "#TrustedComponentCollection.TrustedComponentCollection";
    asyncResp->res.jsonValue["@odata.id"] = url.buffer();
    asyncResp->res.jsonValue["Name"] = "Trusted Component Collection";
    asyncResp->res.jsonValue["Description"] =
        "Collection of Trusted Components";

    std::string trustedComponentsPath =
        sdbusplus::message::object_path("/xyz/openbmc_project/Chassis") /
        chassisId / "TrustedComponents";

    collection_util::getCollectionMembers(asyncResp, url,
                                          trustedComponentInterfaces,
                                          trustedComponentsPath.c_str());
}

inline void requestRoutesTrustedComponent(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/TrustedComponents/<str>/")
        .privileges(redfish::privileges::getTrustedComponent)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleTrustedComponentGet, std::ref(app)));
}

inline void requestRoutesTrustedComponentCollection(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/TrustedComponents/")
        .privileges(redfish::privileges::getTrustedComponentCollection)
        .methods(boost::beast::http::verb::get)(std::bind_front(
            handleTrustedComponentCollectionGet, std::ref(app)));
}

} // namespace redfish
