188d16c9aSLewanczyk, Dawid /* 288d16c9aSLewanczyk, Dawid // Copyright (c) 2018 Intel Corporation 388d16c9aSLewanczyk, Dawid // 488d16c9aSLewanczyk, Dawid // Licensed under the Apache License, Version 2.0 (the "License"); 588d16c9aSLewanczyk, Dawid // you may not use this file except in compliance with the License. 688d16c9aSLewanczyk, Dawid // You may obtain a copy of the License at 788d16c9aSLewanczyk, Dawid // 888d16c9aSLewanczyk, Dawid // http://www.apache.org/licenses/LICENSE-2.0 988d16c9aSLewanczyk, Dawid // 1088d16c9aSLewanczyk, Dawid // Unless required by applicable law or agreed to in writing, software 1188d16c9aSLewanczyk, Dawid // distributed under the License is distributed on an "AS IS" BASIS, 1288d16c9aSLewanczyk, Dawid // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1388d16c9aSLewanczyk, Dawid // See the License for the specific language governing permissions and 1488d16c9aSLewanczyk, Dawid // limitations under the License. 1588d16c9aSLewanczyk, Dawid */ 1688d16c9aSLewanczyk, Dawid #pragma once 1788d16c9aSLewanczyk, Dawid #include "node.hpp" 1888d16c9aSLewanczyk, Dawid 1965b0dc32SEd Tanous #include <error_messages.hpp> 20b9b2e0b2SEd Tanous #include <openbmc_dbus_rest.hpp> 21a840879dSEd Tanous #include <utils/json_utils.hpp> 22b9b2e0b2SEd Tanous 231abe55efSEd Tanous namespace redfish 241abe55efSEd Tanous { 2588d16c9aSLewanczyk, Dawid 26b9b2e0b2SEd Tanous using ManagedObjectType = std::vector<std::pair< 27b9b2e0b2SEd Tanous sdbusplus::message::object_path, 28b9b2e0b2SEd Tanous boost::container::flat_map< 29b9b2e0b2SEd Tanous std::string, boost::container::flat_map< 30b9b2e0b2SEd Tanous std::string, sdbusplus::message::variant<bool>>>>>; 31b9b2e0b2SEd Tanous 321abe55efSEd Tanous class AccountService : public Node 331abe55efSEd Tanous { 3488d16c9aSLewanczyk, Dawid public: 351abe55efSEd Tanous AccountService(CrowApp& app) : Node(app, "/redfish/v1/AccountService/") 361abe55efSEd Tanous { 37c1a46bd2SBorawski.Lukasz Node::json["@odata.id"] = "/redfish/v1/AccountService"; 38c1a46bd2SBorawski.Lukasz Node::json["@odata.type"] = "#AccountService.v1_1_0.AccountService"; 39c1a46bd2SBorawski.Lukasz Node::json["@odata.context"] = 4088d16c9aSLewanczyk, Dawid "/redfish/v1/$metadata#AccountService.AccountService"; 41c1a46bd2SBorawski.Lukasz Node::json["Id"] = "AccountService"; 42c1a46bd2SBorawski.Lukasz Node::json["Description"] = "BMC User Accounts"; 43c1a46bd2SBorawski.Lukasz Node::json["Name"] = "Account Service"; 44c1a46bd2SBorawski.Lukasz Node::json["ServiceEnabled"] = true; 45c1a46bd2SBorawski.Lukasz Node::json["MinPasswordLength"] = 1; 46c1a46bd2SBorawski.Lukasz Node::json["MaxPasswordLength"] = 20; 471abe55efSEd Tanous Node::json["Accounts"]["@odata.id"] = 481abe55efSEd Tanous "/redfish/v1/AccountService/Accounts"; 49c1a46bd2SBorawski.Lukasz Node::json["Roles"]["@odata.id"] = "/redfish/v1/AccountService/Roles"; 503ebd75f7SEd Tanous 513ebd75f7SEd Tanous entityPrivileges = { 524b1b8683SBorawski.Lukasz {boost::beast::http::verb::get, 534b1b8683SBorawski.Lukasz {{"ConfigureUsers"}, {"ConfigureManager"}}}, 54e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 55e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureUsers"}}}, 56e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureUsers"}}}, 57e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureUsers"}}}, 58e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureUsers"}}}}; 5988d16c9aSLewanczyk, Dawid } 6088d16c9aSLewanczyk, Dawid 6188d16c9aSLewanczyk, Dawid private: 6255c7b7a2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 631abe55efSEd Tanous const std::vector<std::string>& params) override 641abe55efSEd Tanous { 6555c7b7a2SEd Tanous res.jsonValue = Node::json; 6688d16c9aSLewanczyk, Dawid res.end(); 6788d16c9aSLewanczyk, Dawid } 6888d16c9aSLewanczyk, Dawid }; 69b9b2e0b2SEd Tanous class AccountsCollection : public Node 70b9b2e0b2SEd Tanous { 71b9b2e0b2SEd Tanous public: 72b9b2e0b2SEd Tanous AccountsCollection(CrowApp& app) : 73b9b2e0b2SEd Tanous Node(app, "/redfish/v1/AccountService/Accounts/") 74b9b2e0b2SEd Tanous { 75b9b2e0b2SEd Tanous 76b9b2e0b2SEd Tanous Node::json = {{"@odata.context", "/redfish/v1/" 77b9b2e0b2SEd Tanous "$metadata#ManagerAccountCollection." 78b9b2e0b2SEd Tanous "ManagerAccountCollection"}, 79b9b2e0b2SEd Tanous {"@odata.id", "/redfish/v1/AccountService/Accounts"}, 80b9b2e0b2SEd Tanous {"@odata.type", "#ManagerAccountCollection." 81b9b2e0b2SEd Tanous "ManagerAccountCollection"}, 82b9b2e0b2SEd Tanous {"Name", "Accounts Collection"}, 83b9b2e0b2SEd Tanous {"Description", "BMC User Accounts"}}; 84b9b2e0b2SEd Tanous 85b9b2e0b2SEd Tanous entityPrivileges = { 86b9b2e0b2SEd Tanous {boost::beast::http::verb::get, 87b9b2e0b2SEd Tanous {{"ConfigureUsers"}, {"ConfigureManager"}}}, 88b9b2e0b2SEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 89b9b2e0b2SEd Tanous {boost::beast::http::verb::patch, {{"ConfigureUsers"}}}, 90b9b2e0b2SEd Tanous {boost::beast::http::verb::put, {{"ConfigureUsers"}}}, 91b9b2e0b2SEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureUsers"}}}, 92b9b2e0b2SEd Tanous {boost::beast::http::verb::post, {{"ConfigureUsers"}}}}; 93b9b2e0b2SEd Tanous } 94b9b2e0b2SEd Tanous 95b9b2e0b2SEd Tanous private: 96b9b2e0b2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 97b9b2e0b2SEd Tanous const std::vector<std::string>& params) override 98b9b2e0b2SEd Tanous { 99b9b2e0b2SEd Tanous res.jsonValue = Node::json; 100b9b2e0b2SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 101b9b2e0b2SEd Tanous crow::connections::systemBus->async_method_call( 102b9b2e0b2SEd Tanous [asyncResp](const boost::system::error_code ec, 103b9b2e0b2SEd Tanous const ManagedObjectType& users) { 104b9b2e0b2SEd Tanous if (ec) 105b9b2e0b2SEd Tanous { 106*f12894f8SJason M. Bills messages::internalError(asyncResp->res); 107b9b2e0b2SEd Tanous return; 108b9b2e0b2SEd Tanous } 109b9b2e0b2SEd Tanous 110b9b2e0b2SEd Tanous nlohmann::json& memberArray = 111b9b2e0b2SEd Tanous asyncResp->res.jsonValue["Members"]; 112b9b2e0b2SEd Tanous memberArray = nlohmann::json::array(); 113b9b2e0b2SEd Tanous 114b9b2e0b2SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = users.size(); 115b9b2e0b2SEd Tanous for (auto& user : users) 116b9b2e0b2SEd Tanous { 117b9b2e0b2SEd Tanous const std::string& path = 118b9b2e0b2SEd Tanous static_cast<const std::string&>(user.first); 119b9b2e0b2SEd Tanous std::size_t lastIndex = path.rfind("/"); 120b9b2e0b2SEd Tanous if (lastIndex == std::string::npos) 121b9b2e0b2SEd Tanous { 122b9b2e0b2SEd Tanous lastIndex = 0; 123b9b2e0b2SEd Tanous } 124b9b2e0b2SEd Tanous else 125b9b2e0b2SEd Tanous { 126b9b2e0b2SEd Tanous lastIndex += 1; 127b9b2e0b2SEd Tanous } 128b9b2e0b2SEd Tanous memberArray.push_back( 129b9b2e0b2SEd Tanous {{"@odata.id", "/redfish/v1/AccountService/Accounts/" + 130b9b2e0b2SEd Tanous path.substr(lastIndex)}}); 131b9b2e0b2SEd Tanous } 132b9b2e0b2SEd Tanous }, 133b9b2e0b2SEd Tanous "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", 134b9b2e0b2SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 135b9b2e0b2SEd Tanous } 13604ae99ecSEd Tanous void doPost(crow::Response& res, const crow::Request& req, 13704ae99ecSEd Tanous const std::vector<std::string>& params) override 13804ae99ecSEd Tanous { 13904ae99ecSEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 14004ae99ecSEd Tanous 1419712f8acSEd Tanous std::string username; 1429712f8acSEd Tanous std::string password; 1439712f8acSEd Tanous boost::optional<std::string> roleId("User"); 1449712f8acSEd Tanous boost::optional<bool> enabled = true; 1459712f8acSEd Tanous if (!json_util::readJson(req, res, "UserName", username, "Password", 1469712f8acSEd Tanous password, "RoleId", roleId, "Enabled", 1479712f8acSEd Tanous enabled)) 14804ae99ecSEd Tanous { 14904ae99ecSEd Tanous return; 15004ae99ecSEd Tanous } 15104ae99ecSEd Tanous 1529712f8acSEd Tanous const char* priv = getRoleIdFromPrivilege(*roleId); 15304ae99ecSEd Tanous if (priv == nullptr) 15404ae99ecSEd Tanous { 155*f12894f8SJason M. Bills messages::propertyValueNotInList(asyncResp->res, *roleId, "RoleId"); 15604ae99ecSEd Tanous return; 15704ae99ecSEd Tanous } 1589712f8acSEd Tanous roleId = priv; 15904ae99ecSEd Tanous 16004ae99ecSEd Tanous crow::connections::systemBus->async_method_call( 1619712f8acSEd Tanous [asyncResp, username, password{std::move(password)}]( 16204ae99ecSEd Tanous const boost::system::error_code ec) { 16304ae99ecSEd Tanous if (ec) 16404ae99ecSEd Tanous { 16504ae99ecSEd Tanous messages::resourceAlreadyExists( 166*f12894f8SJason M. Bills asyncResp->res, "#ManagerAccount.v1_0_3.ManagerAccount", 167*f12894f8SJason M. Bills "UserName", username); 16804ae99ecSEd Tanous return; 16904ae99ecSEd Tanous } 17004ae99ecSEd Tanous 17104ae99ecSEd Tanous if (!pamUpdatePassword(username, password)) 17204ae99ecSEd Tanous { 17304ae99ecSEd Tanous // At this point we have a user that's been created, but the 17404ae99ecSEd Tanous // password set failed. Something is wrong, so delete the 17504ae99ecSEd Tanous // user that we've already created 17604ae99ecSEd Tanous crow::connections::systemBus->async_method_call( 17704ae99ecSEd Tanous [asyncResp](const boost::system::error_code ec) { 17804ae99ecSEd Tanous if (ec) 17904ae99ecSEd Tanous { 180*f12894f8SJason M. Bills messages::internalError(asyncResp->res); 18104ae99ecSEd Tanous return; 18204ae99ecSEd Tanous } 18304ae99ecSEd Tanous 184*f12894f8SJason M. Bills messages::invalidObject(asyncResp->res, "Password"); 18504ae99ecSEd Tanous }, 18604ae99ecSEd Tanous "xyz.openbmc_project.User.Manager", 18704ae99ecSEd Tanous "/xyz/openbmc_project/user/" + username, 18804ae99ecSEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 18904ae99ecSEd Tanous 19004ae99ecSEd Tanous BMCWEB_LOG_ERROR << "pamUpdatePassword Failed"; 19104ae99ecSEd Tanous return; 19204ae99ecSEd Tanous } 19304ae99ecSEd Tanous 194*f12894f8SJason M. Bills messages::created(asyncResp->res); 19504ae99ecSEd Tanous asyncResp->res.addHeader( 19604ae99ecSEd Tanous "Location", 19704ae99ecSEd Tanous "/redfish/v1/AccountService/Accounts/" + username); 19804ae99ecSEd Tanous }, 19904ae99ecSEd Tanous "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", 2009712f8acSEd Tanous "xyz.openbmc_project.User.Manager", "CreateUser", username, 20104ae99ecSEd Tanous std::array<const char*, 4>{"ipmi", "redfish", "ssh", "web"}, 2029712f8acSEd Tanous *roleId, *enabled); 20304ae99ecSEd Tanous } 20404ae99ecSEd Tanous 20504ae99ecSEd Tanous static const char* getRoleIdFromPrivilege(boost::beast::string_view role) 20604ae99ecSEd Tanous { 20704ae99ecSEd Tanous if (role == "Administrator") 20804ae99ecSEd Tanous { 20904ae99ecSEd Tanous return "priv-admin"; 21004ae99ecSEd Tanous } 21104ae99ecSEd Tanous else if (role == "Callback") 21204ae99ecSEd Tanous { 21304ae99ecSEd Tanous return "priv-callback"; 21404ae99ecSEd Tanous } 21504ae99ecSEd Tanous else if (role == "User") 21604ae99ecSEd Tanous { 21704ae99ecSEd Tanous return "priv-user"; 21804ae99ecSEd Tanous } 21904ae99ecSEd Tanous else if (role == "Operator") 22004ae99ecSEd Tanous { 22104ae99ecSEd Tanous return "priv-operator"; 22204ae99ecSEd Tanous } 22304ae99ecSEd Tanous return nullptr; 22404ae99ecSEd Tanous } 225b9b2e0b2SEd Tanous }; 226b9b2e0b2SEd Tanous 227a840879dSEd Tanous template <typename Callback> 228a840879dSEd Tanous inline void checkDbusPathExists(const std::string& path, Callback&& callback) 229a840879dSEd Tanous { 230a840879dSEd Tanous using GetObjectType = 231a840879dSEd Tanous std::vector<std::pair<std::string, std::vector<std::string>>>; 232a840879dSEd Tanous 233a840879dSEd Tanous crow::connections::systemBus->async_method_call( 234a840879dSEd Tanous [callback{std::move(callback)}](const boost::system::error_code ec, 235a840879dSEd Tanous const GetObjectType& object_names) { 236a840879dSEd Tanous callback(ec || object_names.size() == 0); 237a840879dSEd Tanous }, 238a840879dSEd Tanous "xyz.openbmc_project.ObjectMapper", 239a840879dSEd Tanous "/xyz/openbmc_project/object_mapper", 240a840879dSEd Tanous "xyz.openbmc_project.ObjectMapper", "GetObject", path, 241a840879dSEd Tanous std::array<std::string, 0>()); 242a840879dSEd Tanous } 243a840879dSEd Tanous 244b9b2e0b2SEd Tanous class ManagerAccount : public Node 245b9b2e0b2SEd Tanous { 246b9b2e0b2SEd Tanous public: 247b9b2e0b2SEd Tanous ManagerAccount(CrowApp& app) : 248b9b2e0b2SEd Tanous Node(app, "/redfish/v1/AccountService/Accounts/<str>/", std::string()) 249b9b2e0b2SEd Tanous { 250b9b2e0b2SEd Tanous Node::json = {{"@odata.context", 251b9b2e0b2SEd Tanous "/redfish/v1/$metadata#ManagerAccount.ManagerAccount"}, 252b9b2e0b2SEd Tanous {"@odata.type", "#ManagerAccount.v1_0_3.ManagerAccount"}, 253b9b2e0b2SEd Tanous 254b9b2e0b2SEd Tanous {"Name", "User Account"}, 255b9b2e0b2SEd Tanous {"Description", "User Account"}, 256b9b2e0b2SEd Tanous {"Password", nullptr}, 257b9b2e0b2SEd Tanous {"RoleId", "Administrator"}, 258b9b2e0b2SEd Tanous {"Links", 259b9b2e0b2SEd Tanous {{"Role", 260b9b2e0b2SEd Tanous {{"@odata.id", "/redfish/v1/AccountService/Roles/" 261b9b2e0b2SEd Tanous "Administrator"}}}}}}; 262b9b2e0b2SEd Tanous 263b9b2e0b2SEd Tanous entityPrivileges = { 264b9b2e0b2SEd Tanous {boost::beast::http::verb::get, 265b9b2e0b2SEd Tanous {{"ConfigureUsers"}, {"ConfigureManager"}, {"ConfigureSelf"}}}, 266b9b2e0b2SEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 267b9b2e0b2SEd Tanous {boost::beast::http::verb::patch, {{"ConfigureUsers"}}}, 268b9b2e0b2SEd Tanous {boost::beast::http::verb::put, {{"ConfigureUsers"}}}, 269b9b2e0b2SEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureUsers"}}}, 270b9b2e0b2SEd Tanous {boost::beast::http::verb::post, {{"ConfigureUsers"}}}}; 271b9b2e0b2SEd Tanous } 272b9b2e0b2SEd Tanous 273b9b2e0b2SEd Tanous private: 274b9b2e0b2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 275b9b2e0b2SEd Tanous const std::vector<std::string>& params) override 276b9b2e0b2SEd Tanous { 277b9b2e0b2SEd Tanous res.jsonValue = Node::json; 278b9b2e0b2SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 279b9b2e0b2SEd Tanous 280b9b2e0b2SEd Tanous if (params.size() != 1) 281b9b2e0b2SEd Tanous { 282*f12894f8SJason M. Bills messages::internalError(asyncResp->res); 283b9b2e0b2SEd Tanous return; 284b9b2e0b2SEd Tanous } 285b9b2e0b2SEd Tanous 286b9b2e0b2SEd Tanous crow::connections::systemBus->async_method_call( 287b9b2e0b2SEd Tanous [asyncResp, accountName{std::string(params[0])}]( 288b9b2e0b2SEd Tanous const boost::system::error_code ec, 289b9b2e0b2SEd Tanous const ManagedObjectType& users) { 290b9b2e0b2SEd Tanous if (ec) 291b9b2e0b2SEd Tanous { 292*f12894f8SJason M. Bills messages::internalError(asyncResp->res); 293b9b2e0b2SEd Tanous return; 294b9b2e0b2SEd Tanous } 295b9b2e0b2SEd Tanous 296b9b2e0b2SEd Tanous for (auto& user : users) 297b9b2e0b2SEd Tanous { 298b9b2e0b2SEd Tanous const std::string& path = 299b9b2e0b2SEd Tanous static_cast<const std::string&>(user.first); 300b9b2e0b2SEd Tanous std::size_t lastIndex = path.rfind("/"); 301b9b2e0b2SEd Tanous if (lastIndex == std::string::npos) 302b9b2e0b2SEd Tanous { 303b9b2e0b2SEd Tanous lastIndex = 0; 304b9b2e0b2SEd Tanous } 305b9b2e0b2SEd Tanous else 306b9b2e0b2SEd Tanous { 307b9b2e0b2SEd Tanous lastIndex += 1; 308b9b2e0b2SEd Tanous } 309b9b2e0b2SEd Tanous if (path.substr(lastIndex) == accountName) 310b9b2e0b2SEd Tanous { 31165b0dc32SEd Tanous for (const auto& interface : user.second) 31265b0dc32SEd Tanous { 31365b0dc32SEd Tanous if (interface.first == 31465b0dc32SEd Tanous "xyz.openbmc_project.User.Attributes") 31565b0dc32SEd Tanous { 31665b0dc32SEd Tanous for (const auto& property : interface.second) 31765b0dc32SEd Tanous { 31865b0dc32SEd Tanous if (property.first == "UserEnabled") 31965b0dc32SEd Tanous { 32065b0dc32SEd Tanous const bool* userEnabled = 32165b0dc32SEd Tanous mapbox::getPtr<const bool>( 32265b0dc32SEd Tanous property.second); 32365b0dc32SEd Tanous if (userEnabled == nullptr) 32465b0dc32SEd Tanous { 32565b0dc32SEd Tanous BMCWEB_LOG_ERROR 32665b0dc32SEd Tanous << "UserEnabled wasn't a bool"; 32765b0dc32SEd Tanous continue; 32865b0dc32SEd Tanous } 32965b0dc32SEd Tanous asyncResp->res.jsonValue["Enabled"] = 33065b0dc32SEd Tanous *userEnabled; 33165b0dc32SEd Tanous } 33265b0dc32SEd Tanous else if (property.first == 33365b0dc32SEd Tanous "UserLockedForFailedAttempt") 33465b0dc32SEd Tanous { 33565b0dc32SEd Tanous const bool* userLocked = 33665b0dc32SEd Tanous mapbox::getPtr<const bool>( 33765b0dc32SEd Tanous property.second); 33865b0dc32SEd Tanous if (userLocked == nullptr) 33965b0dc32SEd Tanous { 34065b0dc32SEd Tanous BMCWEB_LOG_ERROR 34165b0dc32SEd Tanous << "UserEnabled wasn't a bool"; 34265b0dc32SEd Tanous continue; 34365b0dc32SEd Tanous } 34465b0dc32SEd Tanous asyncResp->res.jsonValue["Locked"] = 34565b0dc32SEd Tanous *userLocked; 34665b0dc32SEd Tanous } 34765b0dc32SEd Tanous } 34865b0dc32SEd Tanous } 34965b0dc32SEd Tanous } 35065b0dc32SEd Tanous 351b9b2e0b2SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 352b9b2e0b2SEd Tanous "/redfish/v1/AccountService/Accounts/" + 353b9b2e0b2SEd Tanous accountName; 354b9b2e0b2SEd Tanous asyncResp->res.jsonValue["Id"] = accountName; 355b9b2e0b2SEd Tanous asyncResp->res.jsonValue["UserName"] = accountName; 356b9b2e0b2SEd Tanous 357b9b2e0b2SEd Tanous return; 358b9b2e0b2SEd Tanous } 359b9b2e0b2SEd Tanous } 360b9b2e0b2SEd Tanous 361*f12894f8SJason M. Bills messages::resourceNotFound(asyncResp->res, "ManagerAccount", 362*f12894f8SJason M. Bills accountName); 363b9b2e0b2SEd Tanous }, 364b9b2e0b2SEd Tanous "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", 365b9b2e0b2SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 366b9b2e0b2SEd Tanous } 367a840879dSEd Tanous 368a840879dSEd Tanous void doPatch(crow::Response& res, const crow::Request& req, 369a840879dSEd Tanous const std::vector<std::string>& params) override 370a840879dSEd Tanous { 371a840879dSEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 372a840879dSEd Tanous if (params.size() != 1) 373a840879dSEd Tanous { 374*f12894f8SJason M. Bills messages::internalError(asyncResp->res); 375a840879dSEd Tanous return; 376a840879dSEd Tanous } 377a840879dSEd Tanous 3789712f8acSEd Tanous boost::optional<std::string> password; 3799712f8acSEd Tanous boost::optional<bool> enabled; 3809712f8acSEd Tanous if (!json_util::readJson(req, res, "Password", password, "Enabled", 3819712f8acSEd Tanous enabled)) 382a840879dSEd Tanous { 383a840879dSEd Tanous return; 384a840879dSEd Tanous } 385a840879dSEd Tanous 386a840879dSEd Tanous // Check the user exists before updating the fields 387a840879dSEd Tanous checkDbusPathExists( 388a840879dSEd Tanous "/xyz/openbmc_project/users/" + params[0], 3899712f8acSEd Tanous [username{std::string(params[0])}, password(std::move(password)), 3909712f8acSEd Tanous enabled(std::move(enabled)), asyncResp](bool userExists) { 391a840879dSEd Tanous if (!userExists) 392a840879dSEd Tanous { 393a840879dSEd Tanous messages::resourceNotFound( 394*f12894f8SJason M. Bills asyncResp->res, "#ManagerAccount.v1_0_3.ManagerAccount", 395*f12894f8SJason M. Bills username); 396a840879dSEd Tanous return; 397a840879dSEd Tanous } 398a840879dSEd Tanous 3999712f8acSEd Tanous if (password) 400a840879dSEd Tanous { 4019712f8acSEd Tanous if (!pamUpdatePassword(username, *password)) 402a840879dSEd Tanous { 403a840879dSEd Tanous BMCWEB_LOG_ERROR << "pamUpdatePassword Failed"; 404*f12894f8SJason M. Bills messages::internalError(asyncResp->res); 405a840879dSEd Tanous return; 406a840879dSEd Tanous } 407a840879dSEd Tanous } 408a840879dSEd Tanous 4099712f8acSEd Tanous if (enabled) 410a840879dSEd Tanous { 411a840879dSEd Tanous crow::connections::systemBus->async_method_call( 412a840879dSEd Tanous [asyncResp](const boost::system::error_code ec) { 413a840879dSEd Tanous if (ec) 414a840879dSEd Tanous { 4159712f8acSEd Tanous BMCWEB_LOG_ERROR << "D-Bus responses error: " 4169712f8acSEd Tanous << ec; 417*f12894f8SJason M. Bills messages::internalError(asyncResp->res); 418a840879dSEd Tanous return; 419a840879dSEd Tanous } 420a840879dSEd Tanous // TODO Consider support polling mechanism to 421a840879dSEd Tanous // verify status of host and chassis after 422a840879dSEd Tanous // execute the requested action. 423*f12894f8SJason M. Bills messages::success(asyncResp->res); 424a840879dSEd Tanous }, 425a840879dSEd Tanous "xyz.openbmc_project.User.Manager", 426a840879dSEd Tanous "/xyz/openbmc_project/users/" + username, 427a840879dSEd Tanous "org.freedesktop.DBus.Properties", "Set", 428a840879dSEd Tanous "xyz.openbmc_project.User.Attributes" 429a840879dSEd Tanous "UserEnabled", 4309712f8acSEd Tanous sdbusplus::message::variant<bool>{*enabled}); 431a840879dSEd Tanous } 432a840879dSEd Tanous }); 433a840879dSEd Tanous } 43406e086d9SEd Tanous 43506e086d9SEd Tanous void doDelete(crow::Response& res, const crow::Request& req, 43606e086d9SEd Tanous const std::vector<std::string>& params) override 43706e086d9SEd Tanous { 43806e086d9SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 43906e086d9SEd Tanous 44006e086d9SEd Tanous if (params.size() != 1) 44106e086d9SEd Tanous { 442*f12894f8SJason M. Bills messages::internalError(asyncResp->res); 44306e086d9SEd Tanous return; 44406e086d9SEd Tanous } 44506e086d9SEd Tanous 44606e086d9SEd Tanous const std::string userPath = "/xyz/openbmc_project/user/" + params[0]; 44706e086d9SEd Tanous 44806e086d9SEd Tanous crow::connections::systemBus->async_method_call( 44906e086d9SEd Tanous [asyncResp, username{std::move(params[0])}]( 45006e086d9SEd Tanous const boost::system::error_code ec) { 45106e086d9SEd Tanous if (ec) 45206e086d9SEd Tanous { 45306e086d9SEd Tanous messages::resourceNotFound( 454*f12894f8SJason M. Bills asyncResp->res, "#ManagerAccount.v1_0_3.ManagerAccount", 455*f12894f8SJason M. Bills username); 45606e086d9SEd Tanous return; 45706e086d9SEd Tanous } 45806e086d9SEd Tanous 459*f12894f8SJason M. Bills messages::accountRemoved(asyncResp->res); 46006e086d9SEd Tanous }, 46106e086d9SEd Tanous "xyz.openbmc_project.User.Manager", userPath, 46206e086d9SEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 46306e086d9SEd Tanous } 4649712f8acSEd Tanous }; // namespace redfish 46588d16c9aSLewanczyk, Dawid 46688d16c9aSLewanczyk, Dawid } // namespace redfish 467