#ifndef THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_ACCOUNT_SERVICE_H_
#define THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_ACCOUNT_SERVICE_H_

/*
// Copyright (c) 2018 Intel Corporation
//
// 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.
*/

#ifdef BMCWEB_ENABLE_GRPC
#include "bmcweb_authorizer_singleton.h"
#endif

#include <security/_pam_types.h>
#include <systemd/sd-bus.h>

#include <algorithm>
#include <array>
#include <cstdint>
#include <cstring>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <variant>
#include <vector>

#include "app.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include "logging.hpp"
#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "pam_authenticate.hpp"
#include "persistent_data.hpp"
#include "sessions.hpp"
#include "error_messages.hpp"
#include "generated/enums/account_service.hpp"
#include "privileges.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "dbus_utils.hpp"
#include "json_utils.hpp"
#include <nlohmann/json.hpp>
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "sdbusplus/message.hpp"
#include "sdbusplus/message/native_types.hpp"
#include "sdbusplus/unpack_properties.hpp"

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

namespace redfish {

constexpr const char* ldapConfigObjectName =
    "/xyz/openbmc_project/user/ldap/openldap";
constexpr const char* adConfigObject =
    "/xyz/openbmc_project/user/ldap/active_directory";

constexpr const char* rootUserDbusPath = "/xyz/openbmc_project/user/";
constexpr const char* ldapRootObject = "/xyz/openbmc_project/user/ldap";
constexpr const char* ldapDbusService = "xyz.openbmc_project.Ldap.Config";
constexpr const char* ldapConfigInterface =
    "xyz.openbmc_project.User.Ldap.Config";
constexpr const char* ldapCreateInterface =
    "xyz.openbmc_project.User.Ldap.Create";
constexpr const char* ldapEnableInterface = "xyz.openbmc_project.Object.Enable";
constexpr const char* ldapPrivMapperInterface =
    "xyz.openbmc_project.User.PrivilegeMapper";
constexpr const char* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager";
constexpr const char* propertyInterface = "org.freedesktop.DBus.Properties";

struct LDAPRoleMapData {
  std::string groupName;
  std::string privilege;
};

struct LDAPConfigData {
  std::string uri;
  std::string bindDN;
  std::string baseDN;
  std::string searchScope;
  std::string serverType;
  bool serviceEnabled = false;
  std::string userNameAttribute;
  std::string groupAttribute;
  std::vector<std::pair<std::string, LDAPRoleMapData>> groupRoleList;
};

inline std::string getRoleIdFromPrivilege(std::string_view role) {
  if (role == "priv-admin") {
    return "Administrator";
  }
  if (role == "priv-user") {
    return "ReadOnly";
  }
  if (role == "priv-operator") {
    return "Operator";
  }
  return "";
}
inline std::string getPrivilegeFromRoleId(std::string_view role) {
  if (role == "Administrator") {
    return "priv-admin";
  }
  if (role == "ReadOnly") {
    return "priv-user";
  }
  if (role == "Operator") {
    return "priv-operator";
  }
  return "";
}

/**
 * @brief Maps user group names retrieved from D-Bus object to
 * Account Types.
 *
 * @param[in] userGroups List of User groups
 * @param[out] res AccountTypes populated
 *
 * @return true in case of success, false if UserGroups contains
 * invalid group name(s).
 */
inline bool translateUserGroup(const std::vector<std::string>& userGroups,
                               crow::Response& res) {
  std::vector<std::string> accountTypes;
  for (const auto& userGroup : userGroups) {
    if (userGroup == "redfish") {
      accountTypes.emplace_back("Redfish");
      accountTypes.emplace_back("WebUI");
    } else if (userGroup == "ipmi") {
      accountTypes.emplace_back("IPMI");
    } else if (userGroup == "ssh") {
      accountTypes.emplace_back("HostConsole");
      accountTypes.emplace_back("ManagerConsole");
    } else if (userGroup == "web") {
      // 'web' is one of the valid groups in the UserGroups property of
      // the user account in the D-Bus object. This group is currently not
      // doing anything, and is considered to be equivalent to 'redfish'.
      // 'redfish' user group is mapped to 'Redfish'and 'WebUI'
      // AccountTypes, so do nothing here...
    } else {
      // Invalid user group name. Caller throws an exception.
      return false;
    }
  }

  res.jsonValue["AccountTypes"] = std::move(accountTypes);
  return true;
}

inline void userErrorMessageHandler(
    const sd_bus_error* e, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& newUser, const std::string& username) {
  if (e == nullptr) {
    messages::internalError(asyncResp->res);
    return;
  }

  const char* errorMessage = e->name;
  if (strcmp(errorMessage,
             "xyz.openbmc_project.User.Common.Error.UserNameExists") == 0) {
    messages::resourceAlreadyExists(asyncResp->res, "ManagerAccount",
                                    "UserName", newUser);
  } else if (strcmp(errorMessage,
                    "xyz.openbmc_project.User.Common.Error."
                    "UserNameDoesNotExist") == 0) {
    messages::resourceNotFound(asyncResp->res, "ManagerAccount", username);
  } else if ((strcmp(errorMessage,
                     "xyz.openbmc_project.Common.Error.InvalidArgument") ==
              0) ||
             (strcmp(
                  errorMessage,
                  "xyz.openbmc_project.User.Common.Error.UserNameGroupFail") ==
              0)) {
    messages::propertyValueFormatError(asyncResp->res, newUser, "UserName");
  } else if (strcmp(errorMessage,
                    "xyz.openbmc_project.User.Common.Error.NoResource") == 0) {
    messages::createLimitReachedForResource(asyncResp->res);
  } else {
    messages::internalError(asyncResp->res);
  }
}

inline void parseLDAPConfigData(nlohmann::json& jsonResponse,
                                const LDAPConfigData& confData,
                                const std::string& ldapType) {
  std::string service =
      (ldapType == "LDAP") ? "LDAPService" : "ActiveDirectoryService";

  nlohmann::json& ldap = jsonResponse[ldapType];

  ldap["ServiceEnabled"] = confData.serviceEnabled;
  ldap["ServiceAddresses"] = nlohmann::json::array({confData.uri});
  ldap["Authentication"]["AuthenticationType"] =
      account_service::AuthenticationTypes::UsernameAndPassword;
  ldap["Authentication"]["Username"] = confData.bindDN;
  ldap["Authentication"]["Password"] = nullptr;

  ldap["LDAPService"]["SearchSettings"]["BaseDistinguishedNames"] =
      nlohmann::json::array({confData.baseDN});
  ldap["LDAPService"]["SearchSettings"]["UsernameAttribute"] =
      confData.userNameAttribute;
  ldap["LDAPService"]["SearchSettings"]["GroupsAttribute"] =
      confData.groupAttribute;

  nlohmann::json& roleMapArray = ldap["RemoteRoleMapping"];
  roleMapArray = nlohmann::json::array();
  for (const auto& obj : confData.groupRoleList) {
    BMCWEB_LOG_DEBUG << "Pushing the data groupName=" << obj.second.groupName
                     << "\n";

    nlohmann::json::object_t remoteGroup;
    remoteGroup["RemoteGroup"] = obj.second.groupName;
    remoteGroup["LocalRole"] = getRoleIdFromPrivilege(obj.second.privilege);
    roleMapArray.emplace_back(std::move(remoteGroup));
  }
}

/**
 *  @brief validates given JSON input and then calls appropriate method to
 * create, to delete or to set Rolemapping object based on the given input.
 *
 */
inline void handleRoleMapPatch(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::vector<std::pair<std::string, LDAPRoleMapData>>& roleMapObjData,
    const std::string& serverType, const std::vector<nlohmann::json>& input) {
  for (size_t index = 0; index < input.size(); index++) {
    const nlohmann::json& thisJson = input[index];

    if (thisJson.is_null()) {
      // delete the existing object
      if (index < roleMapObjData.size()) {
        managedStore::GetManagedObjectStore()
            ->PostDbusCallToIoContextThreadSafe(
                asyncResp->strand_,
                [asyncResp, roleMapObjData, serverType,
                 index](const boost::system::error_code& ec) {
                  if (ec) {
                    BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
                    messages::internalError(asyncResp->res);
                    return;
                  }
                  asyncResp->res
                      .jsonValue[serverType]["RemoteRoleMapping"][index] =
                      nullptr;
                },
                ldapDbusService, roleMapObjData[index].first,
                "xyz.openbmc_project.Object.Delete", "Delete");
      } else {
        BMCWEB_LOG_ERROR << "Can't delete the object";
        messages::propertyValueTypeError(
            asyncResp->res,
            thisJson.dump(2, ' ', true,
                          nlohmann::json::error_handler_t::replace),
            "RemoteRoleMapping/" + std::to_string(index));
        return;
      }
    } else if (thisJson.empty()) {
      // Don't do anything for the empty objects,parse next json
      // eg {"RemoteRoleMapping",[{}]}
    } else {
      // update/create the object
      std::optional<std::string> remoteGroup;
      std::optional<std::string> localRole;

      // This is a copy, but it's required in this case because of how
      // readJson is structured
      nlohmann::json thisJsonCopy = thisJson;
      if (!json_util::readJson(thisJsonCopy, asyncResp->res, "RemoteGroup",
                               remoteGroup, "LocalRole", localRole)) {
        continue;
      }

      // Update existing RoleMapping Object
      if (index < roleMapObjData.size()) {
        BMCWEB_LOG_DEBUG << "Update Role Map Object";
        // If "RemoteGroup" info is provided
        if (remoteGroup) {
          managedStore::GetManagedObjectStore()
              ->PostDbusCallToIoContextThreadSafe(
                  asyncResp->strand_,
                  [asyncResp, roleMapObjData, serverType, index,
                   remoteGroup](const boost::system::error_code& ec) {
                    if (ec) {
                      BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
                      messages::internalError(asyncResp->res);
                      return;
                    }
                    asyncResp->res.jsonValue[serverType]["RemoteRoleMapping"]
                                            [index]["RemoteGroup"] =
                        *remoteGroup;
                  },
                  ldapDbusService, roleMapObjData[index].first,
                  propertyInterface, "Set",
                  "xyz.openbmc_project.User.PrivilegeMapperEntry", "GroupName",
                  dbus::utility::DbusVariantType(std::move(*remoteGroup)));
        }

        // If "LocalRole" info is provided
        if (localRole) {
          managedStore::GetManagedObjectStore()
              ->PostDbusCallToIoContextThreadSafe(
                  asyncResp->strand_,
                  [asyncResp, roleMapObjData, serverType, index,
                   localRole](const boost::system::error_code& ec) {
                    if (ec) {
                      BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
                      messages::internalError(asyncResp->res);
                      return;
                    }
                    asyncResp->res.jsonValue[serverType]["RemoteRoleMapping"]
                                            [index]["LocalRole"] = *localRole;
                  },
                  ldapDbusService, roleMapObjData[index].first,
                  propertyInterface, "Set",
                  "xyz.openbmc_project.User.PrivilegeMapperEntry", "Privilege",
                  dbus::utility::DbusVariantType(
                      getPrivilegeFromRoleId(std::move(*localRole))));
        }
      } else {  // Create a new RoleMapping Object.
        BMCWEB_LOG_DEBUG << "setRoleMappingProperties: Creating new Object";
        std::string pathString = "RemoteRoleMapping/" + std::to_string(index);

        if (!localRole) {
          messages::propertyMissing(asyncResp->res, pathString + "/LocalRole");
          continue;
        }
        if (!remoteGroup) {
          messages::propertyMissing(asyncResp->res,
                                    pathString + "/RemoteGroup");
          continue;
        }

        std::string dbusObjectPath;
        if (serverType == "ActiveDirectory") {
          dbusObjectPath = adConfigObject;
        } else if (serverType == "LDAP") {
          dbusObjectPath = ldapConfigObjectName;
        }

        BMCWEB_LOG_DEBUG << "Remote Group=" << *remoteGroup
                         << ",LocalRole=" << *localRole;

        managedStore::GetManagedObjectStore()
            ->PostDbusCallToIoContextThreadSafe(
                asyncResp->strand_,
                [asyncResp, serverType, localRole,
                 remoteGroup](const boost::system::error_code& ec) {
                  if (ec) {
                    BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
                    messages::internalError(asyncResp->res);
                    return;
                  }
                  nlohmann::json& remoteRoleJson =
                      asyncResp->res.jsonValue[serverType]["RemoteRoleMapping"];
                  nlohmann::json::object_t roleMapEntry;
                  roleMapEntry["LocalRole"] = *localRole;
                  roleMapEntry["RemoteGroup"] = *remoteGroup;
                  remoteRoleJson.push_back(std::move(roleMapEntry));
                },
                ldapDbusService, dbusObjectPath, ldapPrivMapperInterface,
                "Create", *remoteGroup,
                getPrivilegeFromRoleId(std::move(*localRole)));
      }
    }
  }
}

/**
 * Function that retrieves all properties for LDAP config object
 * into JSON
 */
template <typename CallbackFunc>
inline void getLDAPConfigData(
    const std::string& ldapType,
    const managedStore::ManagedObjectStoreContext& context,
    CallbackFunc&& callback) {
  constexpr std::array<std::string_view, 2> interfaces = {ldapEnableInterface,
                                                          ldapConfigInterface};

  managedStore::GetManagedObjectStore()->getDbusObject(
      ldapConfigObjectName, interfaces, context,
      [callback, ldapType, context = context](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetObject& resp) {
        if (ec || resp.empty()) {
          BMCWEB_LOG_ERROR
              << "DBUS response error during getting of service name: " << ec;
          LDAPConfigData empty{};
          callback(false, empty, ldapType);
          return;
        }
        std::string service = resp.begin()->first;

        managedStore::GetManagedObjectStore()->getManagedObjectsWithContext(
            service, {ldapRootObject}, context,
            [callback, ldapType](
                const boost::system::error_code& errorCode,
                const dbus::utility::ManagedObjectType& ldapObjects) {
              LDAPConfigData confData{};
              if (errorCode) {
                callback(false, confData, ldapType);
                BMCWEB_LOG_ERROR << "D-Bus responses error: " << errorCode;
                return;
              }

              std::string ldapDbusType;
              std::string searchString;

              if (ldapType == "LDAP") {
                ldapDbusType =
                    "xyz.openbmc_project.User.Ldap.Config.Type.OpenLdap";
                searchString = "openldap";
              } else if (ldapType == "ActiveDirectory") {
                ldapDbusType =
                    "xyz.openbmc_project.User.Ldap.Config.Type.ActiveDirectory";
                searchString = "active_directory";
              } else {
                BMCWEB_LOG_ERROR << "Can't get the DbusType for the given type="
                                 << ldapType;
                callback(false, confData, ldapType);
                return;
              }

              std::string ldapEnableInterfaceStr = ldapEnableInterface;
              std::string ldapConfigInterfaceStr = ldapConfigInterface;

              for (const auto& object : ldapObjects) {
                // let's find the object whose ldap type is equal to the
                // given type
                if (object.first.str.find(searchString) == std::string::npos) {
                  continue;
                }

                for (const auto& interface : object.second) {
                  if (interface.first == ldapEnableInterfaceStr) {
                    // rest of the properties are string.
                    for (const auto& property : interface.second) {
                      if (property.first == "Enabled") {
                        const bool* value = std::get_if<bool>(&property.second);
                        if (value == nullptr) {
                          continue;
                        }
                        confData.serviceEnabled = *value;
                        break;
                      }
                    }
                  } else if (interface.first == ldapConfigInterfaceStr) {
                    for (const auto& property : interface.second) {
                      const std::string* strValue =
                          std::get_if<std::string>(&property.second);
                      if (strValue == nullptr) {
                        continue;
                      }
                      if (property.first == "LDAPServerURI") {
                        confData.uri = *strValue;
                      } else if (property.first == "LDAPBindDN") {
                        confData.bindDN = *strValue;
                      } else if (property.first == "LDAPBaseDN") {
                        confData.baseDN = *strValue;
                      } else if (property.first == "LDAPSearchScope") {
                        confData.searchScope = *strValue;
                      } else if (property.first == "GroupNameAttribute") {
                        confData.groupAttribute = *strValue;
                      } else if (property.first == "UserNameAttribute") {
                        confData.userNameAttribute = *strValue;
                      } else if (property.first == "LDAPType") {
                        confData.serverType = *strValue;
                      }
                    }
                  } else if (interface.first ==
                             "xyz.openbmc_project.User.PrivilegeMapperEntry") {
                    LDAPRoleMapData roleMapData{};
                    for (const auto& property : interface.second) {
                      const std::string* strValue =
                          std::get_if<std::string>(&property.second);

                      if (strValue == nullptr) {
                        continue;
                      }

                      if (property.first == "GroupName") {
                        roleMapData.groupName = *strValue;
                      } else if (property.first == "Privilege") {
                        roleMapData.privilege = *strValue;
                      }
                    }

                    confData.groupRoleList.emplace_back(object.first.str,
                                                        roleMapData);
                  }
                }
              }
              callback(true, confData, ldapType);
            });
      });
}

/**
 * @brief parses the authentication section under the LDAP
 * @param input JSON data
 * @param asyncResp pointer to the JSON response
 * @param userName  userName to be filled from the given JSON.
 * @param password  password to be filled from the given JSON.
 */
inline void parseLDAPAuthenticationJson(
    nlohmann::json input, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    std::optional<std::string>& username,
    std::optional<std::string>& password) {
  std::optional<std::string> authType;

  if (!json_util::readJson(input, asyncResp->res, "AuthenticationType",
                           authType, "Username", username, "Password",
                           password)) {
    return;
  }
  if (!authType) {
    return;
  }
  if (*authType != "UsernameAndPassword") {
    messages::propertyValueNotInList(asyncResp->res, *authType,
                                     "AuthenticationType");
    return;
  }
}
/**
 * @brief parses the LDAPService section under the LDAP
 * @param input JSON data
 * @param asyncResp pointer to the JSON response
 * @param baseDNList baseDN to be filled from the given JSON.
 * @param userNameAttribute  userName to be filled from the given JSON.
 * @param groupaAttribute  password to be filled from the given JSON.
 */

inline void parseLDAPServiceJson(
    nlohmann::json input, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    std::optional<std::vector<std::string>>& baseDNList,
    std::optional<std::string>& userNameAttribute,
    std::optional<std::string>& groupsAttribute) {
  std::optional<nlohmann::json> searchSettings;

  if (!json_util::readJson(input, asyncResp->res, "SearchSettings",
                           searchSettings)) {
    return;
  }
  if (!searchSettings) {
    return;
  }
  if (!json_util::readJson(*searchSettings, asyncResp->res,
                           "BaseDistinguishedNames", baseDNList,
                           "UsernameAttribute", userNameAttribute,
                           "GroupsAttribute", groupsAttribute)) {
    return;
  }
}
/**
 * @brief updates the LDAP server address and updates the
          json response with the new value.
 * @param serviceAddressList address to be updated.
 * @param asyncResp pointer to the JSON response
 * @param ldapServerElementName Type of LDAP
 server(openLDAP/ActiveDirectory)
 */

inline void handleServiceAddressPatch(
    const std::vector<std::string>& serviceAddressList,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& ldapServerElementName,
    const std::string& ldapConfigObject) {
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, ldapServerElementName,
       serviceAddressList](const boost::system::error_code& ec) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "Error Occurred in updating the service address";
          messages::internalError(asyncResp->res);
          return;
        }
        std::vector<std::string> modifiedserviceAddressList = {
            serviceAddressList.front()};
        asyncResp->res.jsonValue[ldapServerElementName]["ServiceAddresses"] =
            modifiedserviceAddressList;
        if ((serviceAddressList).size() > 1) {
          messages::propertyValueModified(asyncResp->res, "ServiceAddresses",
                                          serviceAddressList.front());
        }
        BMCWEB_LOG_DEBUG << "Updated the service address";
      },
      ldapDbusService, ldapConfigObject, propertyInterface, "Set",
      ldapConfigInterface, "LDAPServerURI",
      dbus::utility::DbusVariantType(serviceAddressList.front()));
}
/**
 * @brief updates the LDAP Bind DN and updates the
          json response with the new value.
 * @param username name of the user which needs to be updated.
 * @param asyncResp pointer to the JSON response
 * @param ldapServerElementName Type of LDAP
 server(openLDAP/ActiveDirectory)
 */

inline void handleUserNamePatch(
    const std::string& username,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& ldapServerElementName,
    const std::string& ldapConfigObject) {
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, username,
       ldapServerElementName](const boost::system::error_code& ec) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "Error occurred in updating the username";
          messages::internalError(asyncResp->res);
          return;
        }
        asyncResp->res
            .jsonValue[ldapServerElementName]["Authentication"]["Username"] =
            username;
        BMCWEB_LOG_DEBUG << "Updated the username";
      },
      ldapDbusService, ldapConfigObject, propertyInterface, "Set",
      ldapConfigInterface, "LDAPBindDN",
      dbus::utility::DbusVariantType(username));
}

/**
 * @brief updates the LDAP password
 * @param password : ldap password which needs to be updated.
 * @param asyncResp pointer to the JSON response
 * @param ldapServerElementName Type of LDAP
 *        server(openLDAP/ActiveDirectory)
 */

inline void handlePasswordPatch(
    const std::string& password,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& ldapServerElementName,
    const std::string& ldapConfigObject) {
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, password,
       ldapServerElementName](const boost::system::error_code& ec) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "Error occurred in updating the password";
          messages::internalError(asyncResp->res);
          return;
        }
        asyncResp->res
            .jsonValue[ldapServerElementName]["Authentication"]["Password"] =
            "";
        BMCWEB_LOG_DEBUG << "Updated the password";
      },
      ldapDbusService, ldapConfigObject, propertyInterface, "Set",
      ldapConfigInterface, "LDAPBindDNPassword",
      dbus::utility::DbusVariantType(password));
}

/**
 * @brief updates the LDAP BaseDN and updates the
          json response with the new value.
 * @param baseDNList baseDN list which needs to be updated.
 * @param asyncResp pointer to the JSON response
 * @param ldapServerElementName Type of LDAP
 server(openLDAP/ActiveDirectory)
 */

inline void handleBaseDNPatch(
    const std::vector<std::string>& baseDNList,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& ldapServerElementName,
    const std::string& ldapConfigObject) {
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, baseDNList,
       ldapServerElementName](const boost::system::error_code& ec) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "Error Occurred in Updating the base DN";
          messages::internalError(asyncResp->res);
          return;
        }
        auto& serverTypeJson = asyncResp->res.jsonValue[ldapServerElementName];
        auto& searchSettingsJson =
            serverTypeJson["LDAPService"]["SearchSettings"];
        std::vector<std::string> modifiedBaseDNList = {baseDNList.front()};
        searchSettingsJson["BaseDistinguishedNames"] = modifiedBaseDNList;
        if (baseDNList.size() > 1) {
          messages::propertyValueModified(
              asyncResp->res, "BaseDistinguishedNames", baseDNList.front());
        }
        BMCWEB_LOG_DEBUG << "Updated the base DN";
      },
      ldapDbusService, ldapConfigObject, propertyInterface, "Set",
      ldapConfigInterface, "LDAPBaseDN",
      dbus::utility::DbusVariantType(baseDNList.front()));
}
/**
 * @brief updates the LDAP user name attribute and updates the
          json response with the new value.
 * @param userNameAttribute attribute to be updated.
 * @param asyncResp pointer to the JSON response
 * @param ldapServerElementName Type of LDAP
 server(openLDAP/ActiveDirectory)
 */

inline void handleUserNameAttrPatch(
    const std::string& userNameAttribute,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& ldapServerElementName,
    const std::string& ldapConfigObject) {
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, userNameAttribute,
       ldapServerElementName](const boost::system::error_code& ec) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "Error Occurred in Updating the "
                              "username attribute";
          messages::internalError(asyncResp->res);
          return;
        }
        auto& serverTypeJson = asyncResp->res.jsonValue[ldapServerElementName];
        auto& searchSettingsJson =
            serverTypeJson["LDAPService"]["SearchSettings"];
        searchSettingsJson["UsernameAttribute"] = userNameAttribute;
        BMCWEB_LOG_DEBUG << "Updated the user name attr.";
      },
      ldapDbusService, ldapConfigObject, propertyInterface, "Set",
      ldapConfigInterface, "UserNameAttribute",
      dbus::utility::DbusVariantType(userNameAttribute));
}
/**
 * @brief updates the LDAP group attribute and updates the
          json response with the new value.
 * @param groupsAttribute attribute to be updated.
 * @param asyncResp pointer to the JSON response
 * @param ldapServerElementName Type of LDAP
 server(openLDAP/ActiveDirectory)
 */

inline void handleGroupNameAttrPatch(
    const std::string& groupsAttribute,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& ldapServerElementName,
    const std::string& ldapConfigObject) {
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, groupsAttribute,
       ldapServerElementName](const boost::system::error_code& ec) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "Error Occurred in Updating the "
                              "groupname attribute";
          messages::internalError(asyncResp->res);
          return;
        }
        auto& serverTypeJson = asyncResp->res.jsonValue[ldapServerElementName];
        auto& searchSettingsJson =
            serverTypeJson["LDAPService"]["SearchSettings"];
        searchSettingsJson["GroupsAttribute"] = groupsAttribute;
        BMCWEB_LOG_DEBUG << "Updated the groupname attr";
      },
      ldapDbusService, ldapConfigObject, propertyInterface, "Set",
      ldapConfigInterface, "GroupNameAttribute",
      dbus::utility::DbusVariantType(groupsAttribute));
}
/**
 * @brief updates the LDAP service enable and updates the
          json response with the new value.
 * @param input JSON data.
 * @param asyncResp pointer to the JSON response
 * @param ldapServerElementName Type of LDAP
 server(openLDAP/ActiveDirectory)
 */

inline void handleServiceEnablePatch(
    bool serviceEnabled, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& ldapServerElementName,
    const std::string& ldapConfigObject) {
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, serviceEnabled,
       ldapServerElementName](const boost::system::error_code& ec) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "Error Occurred in Updating the service enable";
          messages::internalError(asyncResp->res);
          return;
        }
        asyncResp->res.jsonValue[ldapServerElementName]["ServiceEnabled"] =
            serviceEnabled;
        BMCWEB_LOG_DEBUG << "Updated Service enable = " << serviceEnabled;
      },
      ldapDbusService, ldapConfigObject, propertyInterface, "Set",
      ldapEnableInterface, "Enabled",
      dbus::utility::DbusVariantType(serviceEnabled));
}

inline void handleAuthMethodsPatch(
    nlohmann::json& input,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  std::optional<bool> basicAuth;
  std::optional<bool> cookie;
  std::optional<bool> sessionToken;
  std::optional<bool> xToken;
  std::optional<bool> tls;

  if (!json_util::readJson(input, asyncResp->res, "BasicAuth", basicAuth,
                           "Cookie", cookie, "SessionToken", sessionToken,
                           "XToken", xToken, "TLS", tls)) {
    BMCWEB_LOG_ERROR << "Cannot read values from AuthMethod tag";
    return;
  }

  // Make a copy of methods configuration
  persistent_data::AuthConfigMethods authMethodsConfig =
      persistent_data::SessionStore::getInstance().getAuthMethodsConfig();

  if (basicAuth) {
#ifndef BMCWEB_ENABLE_BASIC_AUTHENTICATION
    messages::actionNotSupported(
        asyncResp->res,
        "Setting BasicAuth when basic-auth feature is disabled");
    return;
#else
    authMethodsConfig.basic = *basicAuth;
#endif
  }

  if (cookie) {
#ifndef BMCWEB_ENABLE_COOKIE_AUTHENTICATION
    messages::actionNotSupported(
        asyncResp->res, "Setting Cookie when cookie-auth feature is disabled");
    return;
#else
    authMethodsConfig.cookie = *cookie;
#endif
  }

  if (sessionToken) {
#ifndef BMCWEB_ENABLE_SESSION_AUTHENTICATION
    messages::actionNotSupported(
        asyncResp->res,
        "Setting SessionToken when session-auth feature is disabled");
    return;
#else
    authMethodsConfig.sessionToken = *sessionToken;
#endif
  }

  if (xToken) {
#ifndef BMCWEB_ENABLE_XTOKEN_AUTHENTICATION
    messages::actionNotSupported(
        asyncResp->res, "Setting XToken when xtoken-auth feature is disabled");
    return;
#else
    authMethodsConfig.xtoken = *xToken;
#endif
  }

  if (tls) {
#ifndef BMCWEB_ENABLE_MUTUAL_TLS_AUTHENTICATION
    messages::actionNotSupported(
        asyncResp->res, "Setting TLS when mutual-tls-auth feature is disabled");
    return;
#else
    authMethodsConfig.tls = *tls;
#endif
  }

  if (!authMethodsConfig.basic && !authMethodsConfig.cookie &&
      !authMethodsConfig.sessionToken && !authMethodsConfig.xtoken &&
      !authMethodsConfig.tls) {
    // Do not allow user to disable everything
    messages::actionNotSupported(asyncResp->res,
                                 "of disabling all available methods");
    return;
  }

  persistent_data::SessionStore::getInstance().updateAuthMethodsConfig(
      authMethodsConfig);
  // Save configuration immediately
  persistent_data::getConfig().writeData();

  messages::success(asyncResp->res);
}

/**
 * @brief Get the required values from the given JSON, validates the
 *        value and create the LDAP config object.
 * @param input JSON data
 * @param asyncResp pointer to the JSON response
 * @param serverType Type of LDAP server(openLDAP/ActiveDirectory)
 */

inline void handleLDAPPatch(nlohmann::json& input,
                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                            const std::string& serverType) {
  managedStore::ManagedObjectStoreContext context(asyncResp);

  std::string dbusObjectPath;
  if (serverType == "ActiveDirectory") {
    dbusObjectPath = adConfigObject;
  } else if (serverType == "LDAP") {
    dbusObjectPath = ldapConfigObjectName;
  } else {
    return;
  }

  std::optional<nlohmann::json> authentication;
  std::optional<nlohmann::json> ldapService;
  std::optional<std::vector<std::string>> serviceAddressList;
  std::optional<bool> serviceEnabled;
  std::optional<std::vector<std::string>> baseDNList;
  std::optional<std::string> userNameAttribute;
  std::optional<std::string> groupsAttribute;
  std::optional<std::string> userName;
  std::optional<std::string> password;
  std::optional<std::vector<nlohmann::json>> remoteRoleMapData;

  if (!json_util::readJson(input, asyncResp->res, "Authentication",
                           authentication, "LDAPService", ldapService,
                           "ServiceAddresses", serviceAddressList,
                           "ServiceEnabled", serviceEnabled,
                           "RemoteRoleMapping", remoteRoleMapData)) {
    return;
  }

  if (authentication) {
    parseLDAPAuthenticationJson(*authentication, asyncResp, userName, password);
  }
  if (ldapService) {
    parseLDAPServiceJson(*ldapService, asyncResp, baseDNList, userNameAttribute,
                         groupsAttribute);
  }
  if (serviceAddressList) {
    if (serviceAddressList->empty()) {
      messages::propertyValueNotInList(asyncResp->res, "[]", "ServiceAddress");
      return;
    }
  }
  if (baseDNList) {
    if (baseDNList->empty()) {
      messages::propertyValueNotInList(asyncResp->res, "[]",
                                       "BaseDistinguishedNames");
      return;
    }
  }

  // nothing to update, then return
  if (!userName && !password && !serviceAddressList && !baseDNList &&
      !userNameAttribute && !groupsAttribute && !serviceEnabled &&
      !remoteRoleMapData) {
    return;
  }

  // Get the existing resource first then keep modifying
  // whenever any property gets updated.
  getLDAPConfigData(
      serverType, context,
      [asyncResp, userName, password, baseDNList, userNameAttribute,
       groupsAttribute, serviceAddressList, serviceEnabled, dbusObjectPath,
       remoteRoleMapData](bool success, const LDAPConfigData& confData,
                          const std::string& serverT) {
        if (!success) {
          messages::internalError(asyncResp->res);
          return;
        }
        parseLDAPConfigData(asyncResp->res.jsonValue, confData, serverT);
        if (confData.serviceEnabled) {
          // Disable the service first and update the rest of
          // the properties.
          handleServiceEnablePatch(false, asyncResp, serverT, dbusObjectPath);
        }

        if (serviceAddressList) {
          handleServiceAddressPatch(*serviceAddressList, asyncResp, serverT,
                                    dbusObjectPath);
        }
        if (userName) {
          handleUserNamePatch(*userName, asyncResp, serverT, dbusObjectPath);
        }
        if (password) {
          handlePasswordPatch(*password, asyncResp, serverT, dbusObjectPath);
        }

        if (baseDNList) {
          handleBaseDNPatch(*baseDNList, asyncResp, serverT, dbusObjectPath);
        }
        if (userNameAttribute) {
          handleUserNameAttrPatch(*userNameAttribute, asyncResp, serverT,
                                  dbusObjectPath);
        }
        if (groupsAttribute) {
          handleGroupNameAttrPatch(*groupsAttribute, asyncResp, serverT,
                                   dbusObjectPath);
        }
        if (serviceEnabled) {
          // if user has given the value as true then enable
          // the service. if user has given false then no-op
          // as service is already stopped.
          if (*serviceEnabled) {
            handleServiceEnablePatch(*serviceEnabled, asyncResp, serverT,
                                     dbusObjectPath);
          }
        } else {
          // if user has not given the service enabled value
          // then revert it to the same state as it was
          // before.
          handleServiceEnablePatch(confData.serviceEnabled, asyncResp, serverT,
                                   dbusObjectPath);
        }

        if (remoteRoleMapData) {
          handleRoleMapPatch(asyncResp, confData.groupRoleList, serverT,
                             *remoteRoleMapData);
        }
      });
}

inline void updateUserProperties(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
                                 const std::string& username,
                                 const std::optional<std::string>& password,
                                 const std::optional<bool>& enabled,
                                 const std::optional<std::string>& roleId,
                                 const std::optional<bool>& locked) {
  sdbusplus::message::object_path tempObjPath(rootUserDbusPath);
  tempObjPath /= username;
  std::string dbusObjectPath(tempObjPath);

  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  dbus_utils::checkDbusPathExists(
      dbusObjectPath, requestContext,
      [dbusObjectPath, username, password, roleId, enabled, locked,
       asyncResp{std::move(asyncResp)}](int rc) {
        if (rc <= 0) {
          messages::resourceNotFound(asyncResp->res, "ManagerAccount",
                                     username);
          return;
        }

        if (password) {
          int retval = pamUpdatePassword(username, *password);

          if (retval == PAM_USER_UNKNOWN) {
            messages::resourceNotFound(asyncResp->res, "ManagerAccount",
                                       username);
          } else if (retval == PAM_AUTHTOK_ERR) {
            // If password is invalid
            messages::propertyValueFormatError(asyncResp->res, *password,
                                               "Password");
            BMCWEB_LOG_ERROR << "pamUpdatePassword Failed";
          } else if (retval != PAM_SUCCESS) {
            messages::internalError(asyncResp->res);
            return;
          } else {
            messages::success(asyncResp->res);
          }
        }

        if (enabled) {
          managedStore::GetManagedObjectStore()
              ->PostDbusCallToIoContextThreadSafe(
                  asyncResp->strand_,
                  [asyncResp](const boost::system::error_code& ec) {
                    if (ec) {
                      BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
                      messages::internalError(asyncResp->res);
                      return;
                    }
                    messages::success(asyncResp->res);
                    return;
                  },
                  "xyz.openbmc_project.User.Manager", dbusObjectPath,
                  "org.freedesktop.DBus.Properties", "Set",
                  "xyz.openbmc_project.User.Attributes", "UserEnabled",
                  dbus::utility::DbusVariantType{*enabled});
        }

        if (roleId) {
          std::string priv = getPrivilegeFromRoleId(*roleId);
          if (priv.empty()) {
            messages::propertyValueNotInList(asyncResp->res, *roleId, "RoleId");
            return;
          }

          managedStore::GetManagedObjectStore()
              ->PostDbusCallToIoContextThreadSafe(
                  asyncResp->strand_,
                  [asyncResp](const boost::system::error_code& ec) {
                    if (ec) {
                      BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
                      messages::internalError(asyncResp->res);
                      return;
                    }
                    messages::success(asyncResp->res);
                  },
                  "xyz.openbmc_project.User.Manager", dbusObjectPath,
                  "org.freedesktop.DBus.Properties", "Set",
                  "xyz.openbmc_project.User.Attributes", "UserPrivilege",
                  dbus::utility::DbusVariantType{priv});
        }

        if (locked) {
          // admin can unlock the account which is locked by
          // successive authentication failures but admin should
          // not be allowed to lock an account.
          if (*locked) {
            messages::propertyValueNotInList(asyncResp->res, "true", "Locked");
            return;
          }

          managedStore::GetManagedObjectStore()
              ->PostDbusCallToIoContextThreadSafe(
                  asyncResp->strand_,
                  [asyncResp](const boost::system::error_code& ec) {
                    if (ec) {
                      BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
                      messages::internalError(asyncResp->res);
                      return;
                    }
                    messages::success(asyncResp->res);
                    return;
                  },
                  "xyz.openbmc_project.User.Manager", dbusObjectPath,
                  "org.freedesktop.DBus.Properties", "Set",
                  "xyz.openbmc_project.User.Attributes",
                  "UserLockedForFailedAttempt",
                  dbus::utility::DbusVariantType{*locked});
        }
      });
}

inline void handleAccountServiceHead(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.addHeader(boost::beast::http::field::link,
                           "</redfish/v1/JsonSchemas/AccountService/"
                           "AccountService.json>; rel=describedby");
}

inline void handleAccountServiceGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.addHeader(boost::beast::http::field::link,
                           "</redfish/v1/JsonSchemas/AccountService/"
                           "AccountService.json>; rel=describedby");

  const persistent_data::AuthConfigMethods& authMethodsConfig =
      persistent_data::SessionStore::getInstance().getAuthMethodsConfig();

  nlohmann::json& json = asyncResp->res.jsonValue;
  json["@odata.id"] = "/redfish/v1/AccountService";
  json["@odata.type"] =
      "#AccountService."
      "v1_10_0.AccountService";
  json["Id"] = "AccountService";
  json["Name"] = "Account Service";
  json["Description"] = "Account Service";
  json["ServiceEnabled"] = true;
  json["MaxPasswordLength"] = 20;
  json["Accounts"]["@odata.id"] = "/redfish/v1/AccountService/Accounts";
  json["Roles"]["@odata.id"] = "/redfish/v1/AccountService/Roles";
#ifdef BMCWEB_ENABLE_GRPC
  json["PrivilegeMap"]["@odata.id"] = "/redfish/v1/AccountService/PrivilegeMap";
#endif
  json["Oem"]["OpenBMC"]["@odata.type"] =
      "#OpenBMCAccountService.v1_0_0.AccountService";
  json["Oem"]["OpenBMC"]["@odata.id"] =
      "/redfish/v1/AccountService#/Oem/OpenBMC";
  json["Oem"]["OpenBMC"]["AuthMethods"]["BasicAuth"] = authMethodsConfig.basic;
  json["Oem"]["OpenBMC"]["AuthMethods"]["SessionToken"] =
      authMethodsConfig.sessionToken;
  json["Oem"]["OpenBMC"]["AuthMethods"]["XToken"] = authMethodsConfig.xtoken;
  json["Oem"]["OpenBMC"]["AuthMethods"]["Cookie"] = authMethodsConfig.cookie;
  json["Oem"]["OpenBMC"]["AuthMethods"]["TLS"] = authMethodsConfig.tls;

  // /redfish/v1/AccountService/LDAP/Certificates is something only
  // ConfigureManager can access then only display when the user has
  // permissions ConfigureManager
  Privileges effectiveUserPrivileges = redfish::getUserPrivileges(req.userRole);

  if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
                                       effectiveUserPrivileges)) {
    asyncResp->res.jsonValue["LDAP"]["Certificates"]["@odata.id"] =
        "/redfish/v1/AccountService/LDAP/Certificates";
  }
  managedStore::ManagedObjectStoreContext context(asyncResp);
  managedStore::GetManagedObjectStore()->getAllProperties(
      "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
      "xyz.openbmc_project.User.AccountPolicy", context,
      [asyncResp](const boost::system::error_code& ec,
                  const dbus::utility::DBusPropertiesMap& propertiesList) {
        if (ec) {
          messages::internalError(asyncResp->res);
          return;
        }

        BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
                         << "properties for AccountService";

        const uint8_t* minPasswordLength = nullptr;
        const uint32_t* accountUnlockTimeout = nullptr;
        const uint16_t* maxLoginAttemptBeforeLockout = nullptr;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), propertiesList,
            "MinPasswordLength", minPasswordLength, "AccountUnlockTimeout",
            accountUnlockTimeout, "MaxLoginAttemptBeforeLockout",
            maxLoginAttemptBeforeLockout);

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

        if (minPasswordLength != nullptr) {
          asyncResp->res.jsonValue["MinPasswordLength"] = *minPasswordLength;
        }

        if (accountUnlockTimeout != nullptr) {
          asyncResp->res.jsonValue["AccountLockoutDuration"] =
              *accountUnlockTimeout;
        }

        if (maxLoginAttemptBeforeLockout != nullptr) {
          asyncResp->res.jsonValue["AccountLockoutThreshold"] =
              *maxLoginAttemptBeforeLockout;
        }
      });

  auto callback = [asyncResp](bool success, const LDAPConfigData& confData,
                              const std::string& ldapType) {
    if (!success) {
      return;
    }
    parseLDAPConfigData(asyncResp->res.jsonValue, confData, ldapType);
  };

  getLDAPConfigData("LDAP", context, callback);
  getLDAPConfigData("ActiveDirectory", context, callback);
}

inline void handleAccountServicePatch(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  std::optional<uint32_t> unlockTimeout;
  std::optional<uint16_t> lockoutThreshold;
  std::optional<uint8_t> minPasswordLength;
  std::optional<uint16_t> maxPasswordLength;
  std::optional<nlohmann::json> ldapObject;
  std::optional<nlohmann::json> activeDirectoryObject;
  std::optional<nlohmann::json> oemObject;

  if (!json_util::readJsonPatch(
          req, asyncResp->res, "AccountLockoutDuration", unlockTimeout,
          "AccountLockoutThreshold", lockoutThreshold, "MaxPasswordLength",
          maxPasswordLength, "MinPasswordLength", minPasswordLength, "LDAP",
          ldapObject, "ActiveDirectory", activeDirectoryObject, "Oem",
          oemObject)) {
    return;
  }

  if (minPasswordLength) {
    managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
        asyncResp->strand_,
        [asyncResp](const boost::system::error_code& ec) {
          if (ec) {
            messages::internalError(asyncResp->res);
            return;
          }
          messages::success(asyncResp->res);
        },
        "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
        "org.freedesktop.DBus.Properties", "Set",
        "xyz.openbmc_project.User.AccountPolicy", "MinPasswordLength",
        dbus::utility::DbusVariantType(*minPasswordLength));
  }

  if (maxPasswordLength) {
    messages::propertyNotWritable(asyncResp->res, "MaxPasswordLength");
  }

  if (ldapObject) {
    handleLDAPPatch(*ldapObject, asyncResp, "LDAP");
  }

  if (std::optional<nlohmann::json> oemOpenBMCObject;
      oemObject && json_util::readJson(*oemObject, asyncResp->res, "OpenBMC",
                                       oemOpenBMCObject)) {
    if (std::optional<nlohmann::json> authMethodsObject;
        oemOpenBMCObject &&
        json_util::readJson(*oemOpenBMCObject, asyncResp->res, "AuthMethods",
                            authMethodsObject)) {
      if (authMethodsObject) {
        handleAuthMethodsPatch(*authMethodsObject, asyncResp);
      }
    }
  }

  if (activeDirectoryObject) {
    handleLDAPPatch(*activeDirectoryObject, asyncResp, "ActiveDirectory");
  }

  if (unlockTimeout) {
    managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
        asyncResp->strand_,
        [asyncResp](const boost::system::error_code& ec) {
          if (ec) {
            messages::internalError(asyncResp->res);
            return;
          }
          messages::success(asyncResp->res);
        },
        "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
        "org.freedesktop.DBus.Properties", "Set",
        "xyz.openbmc_project.User.AccountPolicy", "AccountUnlockTimeout",
        dbus::utility::DbusVariantType(*unlockTimeout));
  }
  if (lockoutThreshold) {
    managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
        asyncResp->strand_,
        [asyncResp](const boost::system::error_code& ec) {
          if (ec) {
            messages::internalError(asyncResp->res);
            return;
          }
          messages::success(asyncResp->res);
        },
        "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
        "org.freedesktop.DBus.Properties", "Set",
        "xyz.openbmc_project.User.AccountPolicy",
        "MaxLoginAttemptBeforeLockout",
        dbus::utility::DbusVariantType(*lockoutThreshold));
  }
}

inline void handleAccountCollectionHead(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.addHeader(boost::beast::http::field::link,
                           "</redfish/v1/JsonSchemas/"
                           "ManagerAccountCollection.json>; rel=describedby");
}

inline void handleAccountCollectionGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.addHeader(boost::beast::http::field::link,
                           "</redfish/v1/JsonSchemas/"
                           "ManagerAccountCollection.json>; rel=describedby");

  asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/AccountService/Accounts";
  asyncResp->res.jsonValue["@odata.type"] =
      "#ManagerAccountCollection."
      "ManagerAccountCollection";
  asyncResp->res.jsonValue["Name"] = "Accounts Collection";
  asyncResp->res.jsonValue["Description"] = "BMC User Accounts";

  Privileges effectiveUserPrivileges = redfish::getUserPrivileges(req.userRole);

  std::string thisUser;
  if (req.session) {
    thisUser = req.session->username;
  }

  managedStore::ManagedObjectStoreContext context(asyncResp);

  managedStore::GetManagedObjectStore()->getManagedObjectsWithContext(
      "xyz.openbmc_project.User.Manager", {"/xyz/openbmc_project/user"},
      context,
      [asyncResp, thisUser, effectiveUserPrivileges](
          const boost::system::error_code& ec,
          const dbus::utility::ManagedObjectType& users) {
        if (ec) {
          messages::internalError(asyncResp->res);
          return;
        }

        bool userCanSeeAllAccounts =
            effectiveUserPrivileges.isSupersetOf({"ConfigureUsers"});

        bool userCanSeeSelf =
            effectiveUserPrivileges.isSupersetOf({"ConfigureSelf"});

        nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
        memberArray = nlohmann::json::array();

        for (const auto& userpath : users) {
          std::string user = userpath.first.filename();
          if (user.empty()) {
            messages::internalError(asyncResp->res);
            BMCWEB_LOG_ERROR << "Invalid firmware ID";

            return;
          }

          // As clarified by Redfish here:
          // https://redfishforum.com/thread/281/manageraccountcollection-change-allows-account-enumeration
          // Users without ConfigureUsers, only see their own
          // account. Users with ConfigureUsers, see all
          // accounts.
          if (userCanSeeAllAccounts || (thisUser == user && userCanSeeSelf)) {
            nlohmann::json::object_t member;
            member["@odata.id"] = "/redfish/v1/AccountService/Accounts/" + user;
            memberArray.push_back(std::move(member));
          }
        }
        asyncResp->res.jsonValue["Members@odata.count"] = memberArray.size();
      });
}

inline void handleAccountCollectionPost(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  std::string username;
  std::string password;
  std::optional<std::string> roleId("User");
  std::optional<bool> enabled = true;
  if (!json_util::readJsonPatch(req, asyncResp->res, "UserName", username,
                                "Password", password, "RoleId", roleId,
                                "Enabled", enabled)) {
    return;
  }

  std::string priv = getPrivilegeFromRoleId(*roleId);
  if (priv.empty()) {
    messages::propertyValueNotInList(asyncResp->res, *roleId, "RoleId");
    return;
  }
  roleId = priv;

  // Reading AllGroups property
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  dbus_utils::getProperty<std::vector<std::string>>(
      "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
      "xyz.openbmc_project.User.Manager", "AllGroups", requestContext,
      [asyncResp, username, password{std::move(password)}, roleId, enabled](
          const boost::system::error_code& ec,
          const std::vector<std::string>& allGroupsList) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "ERROR with dbus call";
          messages::internalError(asyncResp->res);
          return;
        }

        if (allGroupsList.empty()) {
          messages::internalError(asyncResp->res);
          return;
        }

        managedStore::GetManagedObjectStore()
            ->PostDbusCallToIoContextThreadSafe(
                asyncResp->strand_,
                [asyncResp, username, password](
                    const boost::system::error_code& ec2,
                    sdbusplus::message_t& m) {
                  if (ec2) {
                    userErrorMessageHandler(m.get_error(), asyncResp, username,
                                            "");
                    return;
                  }

                  if (pamUpdatePassword(username, password) != PAM_SUCCESS) {
                    // At this point we have a user that's been
                    // created, but the password set
                    // failed.Something is wrong, so delete the user
                    // that we've already created
                    sdbusplus::message::object_path tempObjPath(
                        rootUserDbusPath);
                    tempObjPath /= username;
                    const std::string userPath(tempObjPath);

                    managedStore::GetManagedObjectStore()
                        ->PostDbusCallToIoContextThreadSafe(
                            asyncResp->strand_,
                            [asyncResp,
                             password](const boost::system::error_code& ec3) {
                              if (ec3) {
                                messages::internalError(asyncResp->res);
                                return;
                              }

                              // If password is invalid
                              messages::propertyValueFormatError(
                                  asyncResp->res, password, "Password");
                            },
                            "xyz.openbmc_project.User.Manager", userPath,
                            "xyz.openbmc_project.Object.Delete", "Delete");

                    BMCWEB_LOG_ERROR << "pamUpdatePassword Failed";
                    return;
                  }

                  messages::created(asyncResp->res);
                  asyncResp->res.addHeader(
                      "Location",
                      "/redfish/v1/AccountService/Accounts/" + username);
                },
                "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
                "xyz.openbmc_project.User.Manager", "CreateUser", username,
                allGroupsList, *roleId, *enabled);
      });
}

inline void handleAccountHead(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& /*accountName*/) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.addHeader(boost::beast::http::field::link,
                           "</redfish/v1/JsonSchemas/ManagerAccount/"
                           "ManagerAccount.json>; rel=describedby");
}

inline void handleAccountGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& accountName) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.addHeader(boost::beast::http::field::link,
                           "</redfish/v1/JsonSchemas/ManagerAccount/"
                           "ManagerAccount.json>; rel=describedby");

#ifdef BMCWEB_INSECURE_DISABLE_AUTHENTICATION
  // If authentication is disabled, there are no user accounts
  messages::resourceNotFound(asyncResp->res, "ManagerAccount", accountName);
  return;
#endif  // BMCWEB_INSECURE_DISABLE_AUTHENTICATION

  if (req.session == nullptr) {
    messages::internalError(asyncResp->res);
    return;
  }
  if (req.session->username != accountName) {
    // At this point we've determined that the user is trying to
    // modify a user that isn't them.  We need to verify that they
    // have permissions to modify other users, so re-run the auth
    // check with the same permissions, minus ConfigureSelf.
    Privileges effectiveUserPrivileges =
        redfish::getUserPrivileges(req.userRole);
    Privileges requiredPermissionsToChangeNonSelf = {"ConfigureUsers",
                                                     "ConfigureManager"};
    if (!effectiveUserPrivileges.isSupersetOf(
            requiredPermissionsToChangeNonSelf)) {
      BMCWEB_LOG_DEBUG << "GET Account denied access";
      messages::insufficientPrivilege(asyncResp->res);
      return;
    }
  }

  managedStore::ManagedObjectStoreContext context(asyncResp);
  managedStore::GetManagedObjectStore()->getManagedObjectsWithContext(
      "xyz.openbmc_project.User.Manager", {"/xyz/openbmc_project/user"},
      context,
      [asyncResp, accountName](const boost::system::error_code& ec,
                               const dbus::utility::ManagedObjectType& users) {
        if (ec) {
          messages::internalError(asyncResp->res);
          return;
        }
        const auto userIt = std::find_if(
            users.begin(), users.end(),
            [accountName](
                const std::pair<sdbusplus::message::object_path,
                                dbus::utility::DBusInteracesMap>& user) {
              return accountName == user.first.filename();
            });

        if (userIt == users.end()) {
          messages::resourceNotFound(asyncResp->res, "ManagerAccount",
                                     accountName);
          return;
        }

        asyncResp->res.jsonValue["@odata.type"] =
            "#ManagerAccount.v1_4_0.ManagerAccount";
        asyncResp->res.jsonValue["Name"] = "User Account";
        asyncResp->res.jsonValue["Description"] = "User Account";
        asyncResp->res.jsonValue["Password"] = nullptr;

        for (const auto& interface : userIt->second) {
          if (interface.first == "xyz.openbmc_project.User.Attributes") {
            for (const auto& property : interface.second) {
              if (property.first == "UserEnabled") {
                const bool* userEnabled = std::get_if<bool>(&property.second);
                if (userEnabled == nullptr) {
                  BMCWEB_LOG_ERROR << "UserEnabled wasn't a bool";
                  messages::internalError(asyncResp->res);
                  return;
                }
                asyncResp->res.jsonValue["Enabled"] = *userEnabled;
              } else if (property.first == "UserLockedForFailedAttempt") {
                const bool* userLocked = std::get_if<bool>(&property.second);
                if (userLocked == nullptr) {
                  BMCWEB_LOG_ERROR << "UserLockedForF"
                                      "ailedAttempt "
                                      "wasn't a bool";
                  messages::internalError(asyncResp->res);
                  return;
                }
                asyncResp->res.jsonValue["Locked"] = *userLocked;
                asyncResp->res.jsonValue["Locked@Redfish.AllowableValues"] = {
                    "false"};  // can only unlock accounts
              } else if (property.first == "UserPrivilege") {
                const std::string* userPrivPtr =
                    std::get_if<std::string>(&property.second);
                if (userPrivPtr == nullptr) {
                  BMCWEB_LOG_ERROR << "UserPrivilege wasn't a "
                                      "string";
                  messages::internalError(asyncResp->res);
                  return;
                }
                std::string role = getRoleIdFromPrivilege(*userPrivPtr);
                if (role.empty()) {
                  BMCWEB_LOG_ERROR << "Invalid user role";
                  messages::internalError(asyncResp->res);
                  return;
                }
                asyncResp->res.jsonValue["RoleId"] = role;

                nlohmann::json& roleEntry =
                    asyncResp->res.jsonValue["Links"]["Role"];
                roleEntry["@odata.id"] =
                    "/redfish/v1/AccountService/Roles/" + role;
              } else if (property.first == "UserPasswordExpired") {
                const bool* userPasswordExpired =
                    std::get_if<bool>(&property.second);
                if (userPasswordExpired == nullptr) {
                  BMCWEB_LOG_ERROR << "UserPasswordExpired wasn't a bool";
                  messages::internalError(asyncResp->res);
                  return;
                }
                asyncResp->res.jsonValue["PasswordChangeRequired"] =
                    *userPasswordExpired;
              } else if (property.first == "UserGroups") {
                const std::vector<std::string>* userGroups =
                    std::get_if<std::vector<std::string>>(&property.second);
                if (userGroups == nullptr) {
                  BMCWEB_LOG_ERROR << "userGroups wasn't a string vector";
                  messages::internalError(asyncResp->res);
                  return;
                }
                if (!translateUserGroup(*userGroups, asyncResp->res)) {
                  BMCWEB_LOG_ERROR << "userGroups mapping failed";
                  messages::internalError(asyncResp->res);
                  return;
                }
              }
            }
          }
        }

        asyncResp->res.jsonValue["@odata.id"] =
            "/redfish/v1/AccountService/Accounts/" + accountName;
        asyncResp->res.jsonValue["Id"] = accountName;
        asyncResp->res.jsonValue["UserName"] = accountName;
      });
}

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

#ifdef BMCWEB_INSECURE_DISABLE_AUTHENTICATION
  // If authentication is disabled, there are no user accounts
  messages::resourceNotFound(asyncResp->res, "ManagerAccount", username);
  return;

#endif  // BMCWEB_INSECURE_DISABLE_AUTHENTICATION
  sdbusplus::message::object_path tempObjPath(rootUserDbusPath);
  tempObjPath /= username;
  const std::string userPath(tempObjPath);

  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, username](const boost::system::error_code& ec) {
        if (ec) {
          messages::resourceNotFound(asyncResp->res, "ManagerAccount",
                                     username);
          return;
        }

        messages::accountRemoved(asyncResp->res);
      },
      "xyz.openbmc_project.User.Manager", userPath,
      "xyz.openbmc_project.Object.Delete", "Delete");
}

inline void handleAccountPatch(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& username) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
#ifdef BMCWEB_INSECURE_DISABLE_AUTHENTICATION
  // If authentication is disabled, there are no user accounts
  messages::resourceNotFound(asyncResp->res, "ManagerAccount", username);
  return;

#endif  // BMCWEB_INSECURE_DISABLE_AUTHENTICATION
  std::optional<std::string> newUserName;
  std::optional<std::string> password;
  std::optional<bool> enabled;
  std::optional<std::string> roleId;
  std::optional<bool> locked;

  if (req.session == nullptr) {
    messages::internalError(asyncResp->res);
    return;
  }

  Privileges effectiveUserPrivileges = redfish::getUserPrivileges(req.userRole);
  Privileges configureUsers = {"ConfigureUsers"};
  bool userHasConfigureUsers =
      effectiveUserPrivileges.isSupersetOf(configureUsers);
  if (userHasConfigureUsers) {
    // Users with ConfigureUsers can modify for all users
    if (!json_util::readJsonPatch(req, asyncResp->res, "UserName", newUserName,
                                  "Password", password, "RoleId", roleId,
                                  "Enabled", enabled, "Locked", locked)) {
      return;
    }
  } else {
    // ConfigureSelf accounts can only modify their own account
    if (username != req.session->username) {
      messages::insufficientPrivilege(asyncResp->res);
      return;
    }

    // ConfigureSelf accounts can only modify their password
    if (!json_util::readJsonPatch(req, asyncResp->res, "Password", password)) {
      return;
    }
  }

  // if user name is not provided in the patch method or if it
  // matches the user name in the URI, then we are treating it as
  // updating user properties other then username. If username
  // provided doesn't match the URI, then we are treating this as
  // user rename request.
  if (!newUserName || (newUserName.value() == username)) {
    updateUserProperties(asyncResp, username, password, enabled, roleId,
                         locked);
    return;
  }
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, username, password(std::move(password)),
       roleId(std::move(roleId)), enabled, newUser{std::string(*newUserName)},
       locked](const boost::system::error_code& ec, sdbusplus::message_t& m) {
        if (ec) {
          userErrorMessageHandler(m.get_error(), asyncResp, newUser, username);
          return;
        }

        updateUserProperties(asyncResp, newUser, password, enabled, roleId,
                             locked);
      },
      "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
      "xyz.openbmc_project.User.Manager", "RenameUser", username, *newUserName);
}

inline void requestAccountServiceRoutes(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/")
      .privileges(redfish::privileges::headAccountService)
      .methods(boost::beast::http::verb::head)(
          std::bind_front(handleAccountServiceHead, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/")
      .privileges(redfish::privileges::getAccountService)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleAccountServiceGet, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/")
      .privileges(redfish::privileges::patchAccountService)
      .methods(boost::beast::http::verb::patch)(
          std::bind_front(handleAccountServicePatch, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/")
      .privileges(redfish::privileges::headManagerAccountCollection)
      .methods(boost::beast::http::verb::head)(
          std::bind_front(handleAccountCollectionHead, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/")
      .privileges(redfish::privileges::getManagerAccountCollection)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleAccountCollectionGet, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/")
      .privileges(redfish::privileges::postManagerAccountCollection)
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handleAccountCollectionPost, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/<str>/")
      .privileges(redfish::privileges::headManagerAccount)
      .methods(boost::beast::http::verb::head)(
          std::bind_front(handleAccountHead, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/<str>/")
      .privileges(redfish::privileges::getManagerAccount)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleAccountGet, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/<str>/")
      // TODO this privilege should be using the generated endpoints, but
      // because of the special handling of ConfigureSelf, it's not able to
      // yet
      .privileges({{"ConfigureUsers"}, {"ConfigureSelf"}})
      .methods(boost::beast::http::verb::patch)(
          std::bind_front(handleAccountPatch, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/<str>/")
      .privileges(redfish::privileges::deleteManagerAccount)
      .methods(boost::beast::http::verb::delete_)(
          std::bind_front(handleAccountDelete, std::ref(app)));

#ifdef BMCWEB_ENABLE_GRPC
  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/PrivilegeMap/")
      // Privileges obtained from https://github.com/DMTF/Redfish/pull/5474
      .privileges({{"Login"}})
      .methods(boost::beast::http::verb::get)(
          [&app](const crow::Request& req,
                 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
            if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
              return;
            }

            asyncResp->res.jsonValue =
                ::milotic::authz::BmcWebAuthorizerSingleton::GetInstance()
                    .GetRedfishPrivilegeRegistry();
          });
#endif
}

}  // namespace redfish

#endif  // THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_ACCOUNT_SERVICE_H_
