/*
// 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 "utils/chassis_utils.hpp"
#include "utils/system_utils.hpp"
#include "utils/collection.hpp"
#include "utils/dbus_utils.hpp"
#include "utils/json_utils.hpp"
#include "utils/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;
            }

            // handle Processor: parent resource can be Systems or Chassis.
            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;
                    }

                    nlohmann::json::object_t integratedProcessorPath;
                    std::string parentResourceType;
                    if (redfish::dbus_utils::findInterfacesInServiceMap(
                            object, redfish::chassis_utils::chassisInterfaces))
                    {
                        parentResourceType = "Chassis";
                    } else if (redfish::dbus_utils::findInterfacesInServiceMap(
                            object, redfish::system_utils::systemInterfaces))
                    {
                        parentResourceType = "Systems";
                    } 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, parentObj,
                        "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
