#include "routing.hpp"

#include "bmcweb_config.h"

#include "error_messages.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include "logging.hpp"
#include "utils/dbus_utils.hpp"

#include <boost/beast/ssl/ssl_stream.hpp>
#include <cstdint>
#include <sdbusplus/unpack_properties.hpp>

namespace crow
{

bool Router::isUserPrivileged(
    Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    BaseRule& rule, const dbus::utility::DBusPropertiesMap& userInfoMap)
{
    std::string userRole{};
    const std::string* userRolePtr = nullptr;
    const bool* remoteUser = nullptr;
    const bool* passwordExpired = nullptr;

    const bool success = sdbusplus::unpackPropertiesNoThrow(
        redfish::dbus_utils::UnpackErrorPrinter(), userInfoMap, "UserPrivilege",
        userRolePtr, "RemoteUser", remoteUser, "UserPasswordExpired",
        passwordExpired);

    if (!success)
    {
        asyncResp->res.result(
            boost::beast::http::status::internal_server_error);
        return false;
    }

    if (userRolePtr != nullptr)
    {
        userRole = *userRolePtr;
        BMCWEB_LOG_DEBUG << "userName = " << req.session->username
                         << " userRole = " << *userRolePtr;
    }

    if (remoteUser == nullptr)
    {
        BMCWEB_LOG_ERROR << "RemoteUser property missing or wrong type";
        asyncResp->res.result(
            boost::beast::http::status::internal_server_error);
        return false;
    }
    bool expired = false;
    if (passwordExpired == nullptr)
    {
        if (!*remoteUser)
        {
            BMCWEB_LOG_ERROR << "UserPasswordExpired property is expected for"
                                " local user but is missing or wrong type";
            asyncResp->res.result(
                boost::beast::http::status::internal_server_error);
            return false;
        }
    }
    else
    {
        expired = *passwordExpired;
    }

    // Get the user's privileges from the role
    redfish::Privileges userPrivileges = redfish::getUserPrivileges(userRole);

    // Set isConfigureSelfOnly based on D-Bus results.  This
    // ignores the results from both pamAuthenticateUser and the
    // value from any previous use of this session.
    req.session->isConfigureSelfOnly = expired;

    // Modify privileges if isConfigureSelfOnly.
    if (req.session->isConfigureSelfOnly)
    {
        // Remove all privileges except ConfigureSelf
        userPrivileges =
            userPrivileges.intersection(redfish::Privileges{"ConfigureSelf"});
        BMCWEB_LOG_DEBUG << "Operation limited to ConfigureSelf";
    }

    if (!rule.checkPrivileges(userPrivileges))
    {
        asyncResp->res.result(boost::beast::http::status::forbidden);
        if (req.session->isConfigureSelfOnly)
        {
            redfish::messages::passwordChangeRequired(
                asyncResp->res, crow::utility::urlFromPieces(
                                    "redfish", "v1", "AccountService",
                                    "Accounts", req.session->username));
        }
        return false;
    }

    req.userRole = userRole;

    return true;
}

void Trie::optimizeNode(Node* node)
{
    for (size_t x : node->paramChildrens)
    {
        if (x == 0U)
        {
            continue;
        }
        Node* child = &nodes[x];
        optimizeNode(child);
    }
    if (node->children.empty())
    {
        return;
    }
    bool mergeWithChild = true;
    for (const Node::ChildMap::value_type& kv : node->children)
    {
        Node* child = &nodes[kv.second];
        if (!child->isSimpleNode())
        {
            mergeWithChild = false;
            break;
        }
    }
    if (mergeWithChild)
    {
        Node::ChildMap merged;
        for (const Node::ChildMap::value_type& kv : node->children)
        {
            Node* child = &nodes[kv.second];
            for (const Node::ChildMap::value_type& childKv : child->children)
            {
                merged[kv.first + childKv.first] = childKv.second;
            }
        }
        node->children = std::move(merged);
        optimizeNode(node);
    }
    else
    {
        for (const Node::ChildMap::value_type& kv : node->children)
        {
            Node* child = &nodes[kv.second];
            optimizeNode(child);
        }
    }
}

void Trie::findRouteIndexes(const std::string& reqUrl,
                            std::vector<unsigned>& routeIndexes,
                            const Node* node, unsigned pos) const
{
    if (node == nullptr)
    {
        node = head();
    }
    for (const Node::ChildMap::value_type& kv : node->children)
    {
        const std::string& fragment = kv.first;
        const Node* child = &nodes[kv.second];
        if (pos >= reqUrl.size())
        {
            if (child->ruleIndex != 0 && fragment != "/")
            {
                routeIndexes.push_back(child->ruleIndex);
            }
            findRouteIndexes(reqUrl, routeIndexes, child,
                             static_cast<unsigned>(pos + fragment.size()));
        }
        else
        {
            if (reqUrl.compare(pos, fragment.size(), fragment) == 0)
            {
                findRouteIndexes(reqUrl, routeIndexes, child,
                                 static_cast<unsigned>(pos + fragment.size()));
            }
        }
    }
}

std::pair<unsigned int, RoutingParams> Trie::find(std::string_view reqUrl,
                                                  const Node* node, size_t pos,
                                                  RoutingParams* params) const
{
    RoutingParams empty;
    if (params == nullptr)
    {
        params = &empty;
    }

    unsigned found{};
    RoutingParams matchParams;

    if (node == nullptr)
    {
        node = head();
    }
    if (pos == reqUrl.size())
    {
        return {node->ruleIndex, *params};
    }

    auto updateFound = [&found,
                        &matchParams](std::pair<unsigned, RoutingParams>& ret) {

        // Current Logic is to choose the rule with the lowest index in the allRules vector
        bool replaceFound = found == 0U || found > ret.first;

        // For platforms with plugins enabled, we will return the first matched found instead.
        // This results in matching fixed URI segments whenever possible relative to wildcards.
#ifdef PLATFORM_PLUGINS_ENABLED
        replaceFound = found == 0U;
#endif

        if (ret.first != 0U && replaceFound)
        {
            found = ret.first;
            matchParams = std::move(ret.second);
        }
    };

    for (const Node::ChildMap::value_type& kv : node->children)
    {
        const std::string& fragment = kv.first;
        const Node* child = &nodes[kv.second];

        if (reqUrl.compare(pos, fragment.size(), fragment) == 0)
        {
            std::pair<unsigned, RoutingParams> ret =
                find(reqUrl, child, pos + fragment.size(), params);
            updateFound(ret);
        }
    }

    if (node->paramChildrens[static_cast<size_t>(ParamType::INT)] != 0U)
    {
        char c = reqUrl[pos];
        if ((c >= '0' && c <= '9') || c == '+' || c == '-')
        {
            char* eptr = nullptr;
            errno = 0;
            int64_t value = std::strtoll(reqUrl.data() + pos, &eptr, 10);
            if (errno != ERANGE && eptr != reqUrl.data() + pos)
            {
                params->intParams.push_back(value);
                std::pair<unsigned, RoutingParams> ret =
                    find(reqUrl,
                         &nodes[node->paramChildrens[static_cast<size_t>(
                             ParamType::INT)]],
                         static_cast<size_t>(eptr - reqUrl.data()), params);
                updateFound(ret);
                params->intParams.pop_back();
            }
        }
    }

    if (node->paramChildrens[static_cast<size_t>(ParamType::UINT)] != 0U)
    {
        char c = reqUrl[pos];
        if ((c >= '0' && c <= '9') || c == '+')
        {
            char* eptr = nullptr;
            errno = 0;
            uint64_t value =
                std::strtoull(reqUrl.data() + pos, &eptr, 10);
            if (errno != ERANGE && eptr != reqUrl.data() + pos)
            {
                params->uintParams.push_back(value);
                std::pair<unsigned, RoutingParams> ret =
                    find(reqUrl,
                         &nodes[node->paramChildrens[static_cast<size_t>(
                             ParamType::UINT)]],
                         static_cast<size_t>(eptr - reqUrl.data()), params);
                updateFound(ret);
                params->uintParams.pop_back();
            }
        }
    }

    if (node->paramChildrens[static_cast<size_t>(ParamType::DOUBLE)] != 0U)
    {
        char c = reqUrl[pos];
        if ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.')
        {
            char* eptr = nullptr;
            errno = 0;
            double value = std::strtod(reqUrl.data() + pos, &eptr);
            if (errno != ERANGE && eptr != reqUrl.data() + pos)
            {
                params->doubleParams.push_back(value);
                std::pair<unsigned, RoutingParams> ret =
                    find(reqUrl,
                         &nodes[node->paramChildrens[static_cast<size_t>(
                             ParamType::DOUBLE)]],
                         static_cast<size_t>(eptr - reqUrl.data()), params);
                updateFound(ret);
                params->doubleParams.pop_back();
            }
        }
    }

    if (node->paramChildrens[static_cast<size_t>(ParamType::STRING)] != 0U)
    {
        size_t epos = pos;
        for (; epos < reqUrl.size(); epos++)
        {
            if (reqUrl[epos] == '/')
            {
                break;
            }
        }

        if (epos != pos)
        {
            params->stringParams.emplace_back(reqUrl.substr(pos, epos - pos));
            std::pair<unsigned, RoutingParams> ret =
                find(reqUrl,
                     &nodes[node->paramChildrens[static_cast<size_t>(
                         ParamType::STRING)]],
                     epos, params);
            updateFound(ret);
            params->stringParams.pop_back();
        }
    }

    if (node->paramChildrens[static_cast<size_t>(ParamType::PATH)] != 0U)
    {
        size_t epos = reqUrl.size();

        if (epos != pos)
        {
            params->stringParams.emplace_back(reqUrl.substr(pos, epos - pos));
            std::pair<unsigned, RoutingParams> ret =
                find(reqUrl,
                     &nodes[node->paramChildrens[static_cast<size_t>(
                         ParamType::PATH)]],
                     epos, params);
            updateFound(ret);
            params->stringParams.pop_back();
        }
    }

    return {found, matchParams};
}

void Trie::add(const std::string& url, unsigned int ruleIndex)
{
    size_t idx = 0;

    for (unsigned i = 0; i < url.size(); i++)
    {
        char c = url[i];
        if (c == '<')
        {
            const static std::array<std::pair<ParamType, std::string>, 7>
                paramTraits = {{
                    {ParamType::INT, "<int>"},
                    {ParamType::UINT, "<uint>"},
                    {ParamType::DOUBLE, "<float>"},
                    {ParamType::DOUBLE, "<double>"},
                    {ParamType::STRING, "<str>"},
                    {ParamType::STRING, "<string>"},
                    {ParamType::PATH, "<path>"},
                }};

            for (const std::pair<ParamType, std::string>& x : paramTraits)
            {
                if (url.compare(i, x.second.size(), x.second) == 0)
                {
                    size_t index = static_cast<size_t>(x.first);
                    if (nodes[idx].paramChildrens[index] == 0U)
                    {
                        unsigned newNodeIdx = newNode();
                        nodes[idx].paramChildrens[index] = newNodeIdx;
                    }
                    idx = nodes[idx].paramChildrens[index];
                    i += static_cast<unsigned>(x.second.size());
                    break;
                }
            }

            i--;
        }
        else
        {
            std::string piece(&c, 1);
            if (nodes[idx].children.count(piece) == 0U)
            {
                unsigned newNodeIdx = newNode();
                nodes[idx].children.emplace(piece, newNodeIdx);
            }
            idx = nodes[idx].children[piece];
        }
    }
    if (nodes[idx].ruleIndex != 0U)
    {
        throw std::runtime_error("handler already exists for " + url);
    }
    nodes[idx].ruleIndex = ruleIndex;
}

void Trie::debugNodePrint(Node* n, size_t level)

{
    for (size_t i = 0; i < static_cast<size_t>(ParamType::MAX); i++)
    {
        if (n->paramChildrens[i] != 0U)
        {
            BMCWEB_LOG_DEBUG << std::string(
                2U * level, ' ') /*<< "("<<n->paramChildrens[i]<<") "*/;
            switch (static_cast<ParamType>(i))
            {
                case ParamType::INT:
                    BMCWEB_LOG_DEBUG << "<int>";
                    break;
                case ParamType::UINT:
                    BMCWEB_LOG_DEBUG << "<uint>";
                    break;
                case ParamType::DOUBLE:
                    BMCWEB_LOG_DEBUG << "<float>";
                    break;
                case ParamType::STRING:
                    BMCWEB_LOG_DEBUG << "<str>";
                    break;
                case ParamType::PATH:
                    BMCWEB_LOG_DEBUG << "<path>";
                    break;
                case ParamType::MAX:
                    BMCWEB_LOG_DEBUG << "<ERROR>";
                    break;
            }

            debugNodePrint(&nodes[n->paramChildrens[i]], level + 1);
        }
    }
    for (const Node::ChildMap::value_type& kv : n->children)
    {
        BMCWEB_LOG_DEBUG << std::string(2U * level,
                                        ' ') /*<< "(" << kv.second << ") "*/
                         << kv.first;
        debugNodePrint(&nodes[kv.second], level + 1);
    }
}

void Router::internalAddRuleObject(const std::string& rule,
                                   BaseRule* ruleObject)
{
    if (ruleObject == nullptr)
    {
        return;
    }
    for (size_t method = 0, methodBit = 1; method <= methodNotAllowedIndex;
         method++, methodBit <<= 1)
    {
        if ((ruleObject->methodsBitfield & methodBit) > 0U)
        {
            perMethods[method].rules.emplace_back(ruleObject);
            perMethods[method].trie.add(
                rule,
                static_cast<unsigned>(perMethods[method].rules.size() - 1U));
            // directory case:
            //   request to `/about' url matches `/about/' rule
            if (rule.size() > 2 && rule.back() == '/')
            {
                perMethods[method].trie.add(
                    rule.substr(0, rule.size() - 1),
                    static_cast<unsigned>(perMethods[method].rules.size() - 1));
            }
        }
    }
}

void Router::validate()
{
    for (std::unique_ptr<BaseRule>& rule : allRules)
    {
        if (rule)
        {
            std::unique_ptr<BaseRule> upgraded = rule->upgrade();
            if (upgraded)
            {
                rule = std::move(upgraded);
            }
            rule->validate();
            internalAddRuleObject(rule->rule, rule.get());
        }
    }
    for (PerMethod& perMethod : perMethods)
    {
        perMethod.trie.validate();
    }
}

Router::FindRoute Router::findRouteByIndex(std::string_view url,
                                           size_t index) const
{
    FindRoute route;
    if (index >= perMethods.size())
    {
        BMCWEB_LOG_CRITICAL << "Bad index???";
        return route;
    }
    const PerMethod& perMethod = perMethods[index];
    std::pair<unsigned, RoutingParams> found = perMethod.trie.find(url);
    if (found.first >= perMethod.rules.size())
    {
        throw std::runtime_error("Trie internal structure corrupted!");
    }
    // Found a 404 route, switch that in
    if (found.first != 0U)
    {
        route.rule = perMethod.rules[found.first];
        route.params = std::move(found.second);
    }
    return route;
}

Router::FindRouteResponse Router::findRoute(Request& req) const
{
    FindRouteResponse findRoute;

    std::optional<HttpVerb> verb = httpVerbFromBoost(req.method());
    if (!verb)
    {
        return findRoute;
    }
    size_t reqMethodIndex = static_cast<size_t>(*verb);
    // Check to see if this url exists at any verb
    for (size_t perMethodIndex = 0; perMethodIndex <= maxVerbIndex;
         perMethodIndex++)
    {
        // Make sure it's safe to deference the array at that index
        static_assert(maxVerbIndex < std::tuple_size_v<decltype(perMethods)>);
        FindRoute route =
            findRouteByIndex(req.url().encoded_path(), perMethodIndex);
        if (route.rule == nullptr)
        {
            continue;
        }
        if (!findRoute.allowHeader.empty())
        {
            findRoute.allowHeader += ", ";
        }
        HttpVerb thisVerb = static_cast<HttpVerb>(perMethodIndex);
        findRoute.allowHeader += httpVerbToString(thisVerb);
        if (perMethodIndex == reqMethodIndex)
        {
            findRoute.route = route;
        }
    }
    return findRoute;
}

void Router::handle(Request& req,
                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    std::optional<HttpVerb> verb = httpVerbFromBoost(req.method());
    if (!verb || static_cast<size_t>(*verb) >= perMethods.size())
    {
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }

    FindRouteResponse foundRoute = findRoute(req);

    if (foundRoute.route.rule == nullptr)
    {
        // Couldn't find a normal route with any verb, try looking for a 404
        // route
        if (foundRoute.allowHeader.empty())
        {
            foundRoute.route =
                findRouteByIndex(req.url().encoded_path(), notFoundIndex);
        }
        else
        {
            // See if we have a method not allowed (405) handler
            foundRoute.route = findRouteByIndex(req.url().encoded_path(),
                                                methodNotAllowedIndex);
        }
    }

    // Fill in the allow header if it's valid
    if (!foundRoute.allowHeader.empty())
    {

        asyncResp->res.addHeader(boost::beast::http::field::allow,
                                 foundRoute.allowHeader);
    }

    // If we couldn't find a real route or a 404 route, return a generic
    // response
    if (foundRoute.route.rule == nullptr)
    {
        if (foundRoute.allowHeader.empty())
        {
            asyncResp->res.result(boost::beast::http::status::not_found);
        }
        else
        {
            asyncResp->res.result(
                boost::beast::http::status::method_not_allowed);
        }
        return;
    }

    BaseRule& rule = *foundRoute.route.rule;
    RoutingParams params = std::move(foundRoute.route.params);

    BMCWEB_LOG_INFO << "Matched rule '" << rule.rule << "' "
                    << static_cast<uint32_t>(*verb) << " / "
                    << rule.getMethods();

#ifdef BMCWEB_ENABLE_GRPC
    if (!req.fromGrpc ||
        (insecureDisableGrpcRedfishAuthz && req.peer_authenticated))
    {
        rule.handle(req, asyncResp, params);
        return;
    }

    // Handles dynamic fine-grained authorization
    std::string_view url_str = {req.url().encoded_path().data(),
                                req.url().encoded_path().size()};

    ::milotic::authz::BmcWebAuthorizerSingleton::RequestState authzState;
    authzState.with_trust_bundle = req.with_trust_bundle;
    authzState.peer_authenticated = req.peer_authenticated;
    authzState.peer_privileges = req.peer_privileges;

    grpc::Status status =
        ::milotic::authz::BmcWebAuthorizerSingleton::GetInstance().Authorize(
            url_str, req.method(), authzState);

    if (!status.ok())
    {
        asyncResp->res.addHeader("OData-Version", "4.0");
        LOG(WARNING) << "Authorization failure at " << req.url() << ": "
                     << status.error_message();
        ::redfish::messages::resourceAtUriUnauthorized(
            asyncResp->res, req.url(), status.error_message());
        return;
    }

    rule.handle(req, asyncResp, params);
#else
    validatePrivilege(req, asyncResp, rule,
                      [&rule, asyncResp, params](Request& thisReq) mutable {
        rule.handle(thisReq, asyncResp, params);
    });
#endif
}

void Router::debugPrint()
{
    for (size_t i = 0; i < perMethods.size(); i++)
    {
        BMCWEB_LOG_DEBUG << boost::beast::http::to_string(
            static_cast<boost::beast::http::verb>(i));
        perMethods[i].trie.debugPrint();
    }
}

std::vector<const std::string*> Router::getRoutes(const std::string& parent)

{
    std::vector<const std::string*> ret;

    for (const PerMethod& pm : perMethods)
    {
        std::vector<unsigned> x;
        pm.trie.findRouteIndexes(parent, x);
        for (unsigned index : x)
        {
            ret.push_back(&pm.rules[index]->rule);
        }
    }
    return ret;
}

void Router::throwHandlerNotFound(std::string_view url,
                                  boost::beast::http::verb boostVerb)
{

    std::string error = "handler doesn't exist for ";
    error += url;
    error += ", method ";
    error += boostVerbToString(boostVerb);
    throw std::runtime_error(error);
}

} // namespace crow