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 { 373ebd75f7SEd Tanous entityPrivileges = { 384b1b8683SBorawski.Lukasz {boost::beast::http::verb::get, 394b1b8683SBorawski.Lukasz {{"ConfigureUsers"}, {"ConfigureManager"}}}, 40e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 41e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureUsers"}}}, 42e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureUsers"}}}, 43e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureUsers"}}}, 44e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureUsers"}}}}; 4588d16c9aSLewanczyk, Dawid } 4688d16c9aSLewanczyk, Dawid 4788d16c9aSLewanczyk, Dawid private: 4855c7b7a2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 491abe55efSEd Tanous const std::vector<std::string>& params) override 501abe55efSEd Tanous { 51*0f74e643SEd Tanous res.jsonValue["@odata.id"] = "/redfish/v1/AccountService"; 52*0f74e643SEd Tanous res.jsonValue["@odata.type"] = "#AccountService.v1_1_0.AccountService"; 53*0f74e643SEd Tanous res.jsonValue["@odata.context"] = 54*0f74e643SEd Tanous "/redfish/v1/$metadata#AccountService.AccountService"; 55*0f74e643SEd Tanous res.jsonValue["Id"] = "AccountService"; 56*0f74e643SEd Tanous res.jsonValue["Description"] = "BMC User Accounts"; 57*0f74e643SEd Tanous res.jsonValue["Name"] = "Account Service"; 58*0f74e643SEd Tanous res.jsonValue["ServiceEnabled"] = true; 59*0f74e643SEd Tanous res.jsonValue["MinPasswordLength"] = 1; 60*0f74e643SEd Tanous res.jsonValue["MaxPasswordLength"] = 20; 61*0f74e643SEd Tanous res.jsonValue["Accounts"]["@odata.id"] = 62*0f74e643SEd Tanous "/redfish/v1/AccountService/Accounts"; 63*0f74e643SEd Tanous res.jsonValue["Roles"]["@odata.id"] = 64*0f74e643SEd Tanous "/redfish/v1/AccountService/Roles"; 65*0f74e643SEd Tanous 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 entityPrivileges = { 76b9b2e0b2SEd Tanous {boost::beast::http::verb::get, 77b9b2e0b2SEd Tanous {{"ConfigureUsers"}, {"ConfigureManager"}}}, 78b9b2e0b2SEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 79b9b2e0b2SEd Tanous {boost::beast::http::verb::patch, {{"ConfigureUsers"}}}, 80b9b2e0b2SEd Tanous {boost::beast::http::verb::put, {{"ConfigureUsers"}}}, 81b9b2e0b2SEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureUsers"}}}, 82b9b2e0b2SEd Tanous {boost::beast::http::verb::post, {{"ConfigureUsers"}}}}; 83b9b2e0b2SEd Tanous } 84b9b2e0b2SEd Tanous 85b9b2e0b2SEd Tanous private: 86b9b2e0b2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 87b9b2e0b2SEd Tanous const std::vector<std::string>& params) override 88b9b2e0b2SEd Tanous { 89b9b2e0b2SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 90*0f74e643SEd Tanous res.jsonValue = {{"@odata.context", 91*0f74e643SEd Tanous "/redfish/v1/" 92*0f74e643SEd Tanous "$metadata#ManagerAccountCollection." 93*0f74e643SEd Tanous "ManagerAccountCollection"}, 94*0f74e643SEd Tanous {"@odata.id", "/redfish/v1/AccountService/Accounts"}, 95*0f74e643SEd Tanous {"@odata.type", "#ManagerAccountCollection." 96*0f74e643SEd Tanous "ManagerAccountCollection"}, 97*0f74e643SEd Tanous {"Name", "Accounts Collection"}, 98*0f74e643SEd Tanous {"Description", "BMC User Accounts"}}; 99*0f74e643SEd Tanous 100b9b2e0b2SEd Tanous crow::connections::systemBus->async_method_call( 101b9b2e0b2SEd Tanous [asyncResp](const boost::system::error_code ec, 102b9b2e0b2SEd Tanous const ManagedObjectType& users) { 103b9b2e0b2SEd Tanous if (ec) 104b9b2e0b2SEd Tanous { 105f12894f8SJason M. Bills messages::internalError(asyncResp->res); 106b9b2e0b2SEd Tanous return; 107b9b2e0b2SEd Tanous } 108b9b2e0b2SEd Tanous 109b9b2e0b2SEd Tanous nlohmann::json& memberArray = 110b9b2e0b2SEd Tanous asyncResp->res.jsonValue["Members"]; 111b9b2e0b2SEd Tanous memberArray = nlohmann::json::array(); 112b9b2e0b2SEd Tanous 113b9b2e0b2SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = users.size(); 114b9b2e0b2SEd Tanous for (auto& user : users) 115b9b2e0b2SEd Tanous { 116b9b2e0b2SEd Tanous const std::string& path = 117b9b2e0b2SEd Tanous static_cast<const std::string&>(user.first); 118b9b2e0b2SEd Tanous std::size_t lastIndex = path.rfind("/"); 119b9b2e0b2SEd Tanous if (lastIndex == std::string::npos) 120b9b2e0b2SEd Tanous { 121b9b2e0b2SEd Tanous lastIndex = 0; 122b9b2e0b2SEd Tanous } 123b9b2e0b2SEd Tanous else 124b9b2e0b2SEd Tanous { 125b9b2e0b2SEd Tanous lastIndex += 1; 126b9b2e0b2SEd Tanous } 127b9b2e0b2SEd Tanous memberArray.push_back( 128b9b2e0b2SEd Tanous {{"@odata.id", "/redfish/v1/AccountService/Accounts/" + 129b9b2e0b2SEd Tanous path.substr(lastIndex)}}); 130b9b2e0b2SEd Tanous } 131b9b2e0b2SEd Tanous }, 132b9b2e0b2SEd Tanous "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", 133b9b2e0b2SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 134b9b2e0b2SEd Tanous } 13504ae99ecSEd Tanous void doPost(crow::Response& res, const crow::Request& req, 13604ae99ecSEd Tanous const std::vector<std::string>& params) override 13704ae99ecSEd Tanous { 13804ae99ecSEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 13904ae99ecSEd Tanous 1409712f8acSEd Tanous std::string username; 1419712f8acSEd Tanous std::string password; 1429712f8acSEd Tanous boost::optional<std::string> roleId("User"); 1439712f8acSEd Tanous boost::optional<bool> enabled = true; 1449712f8acSEd Tanous if (!json_util::readJson(req, res, "UserName", username, "Password", 1459712f8acSEd Tanous password, "RoleId", roleId, "Enabled", 1469712f8acSEd Tanous enabled)) 14704ae99ecSEd Tanous { 14804ae99ecSEd Tanous return; 14904ae99ecSEd Tanous } 15004ae99ecSEd Tanous 1519712f8acSEd Tanous const char* priv = getRoleIdFromPrivilege(*roleId); 15204ae99ecSEd Tanous if (priv == nullptr) 15304ae99ecSEd Tanous { 154f12894f8SJason M. Bills messages::propertyValueNotInList(asyncResp->res, *roleId, "RoleId"); 15504ae99ecSEd Tanous return; 15604ae99ecSEd Tanous } 1579712f8acSEd Tanous roleId = priv; 15804ae99ecSEd Tanous 15904ae99ecSEd Tanous crow::connections::systemBus->async_method_call( 1609712f8acSEd Tanous [asyncResp, username, password{std::move(password)}]( 16104ae99ecSEd Tanous const boost::system::error_code ec) { 16204ae99ecSEd Tanous if (ec) 16304ae99ecSEd Tanous { 16404ae99ecSEd Tanous messages::resourceAlreadyExists( 165f12894f8SJason M. Bills asyncResp->res, "#ManagerAccount.v1_0_3.ManagerAccount", 166f12894f8SJason M. Bills "UserName", username); 16704ae99ecSEd Tanous return; 16804ae99ecSEd Tanous } 16904ae99ecSEd Tanous 17004ae99ecSEd Tanous if (!pamUpdatePassword(username, password)) 17104ae99ecSEd Tanous { 17204ae99ecSEd Tanous // At this point we have a user that's been created, but the 17304ae99ecSEd Tanous // password set failed. Something is wrong, so delete the 17404ae99ecSEd Tanous // user that we've already created 17504ae99ecSEd Tanous crow::connections::systemBus->async_method_call( 17604ae99ecSEd Tanous [asyncResp](const boost::system::error_code ec) { 17704ae99ecSEd Tanous if (ec) 17804ae99ecSEd Tanous { 179f12894f8SJason M. Bills messages::internalError(asyncResp->res); 18004ae99ecSEd Tanous return; 18104ae99ecSEd Tanous } 18204ae99ecSEd Tanous 183f12894f8SJason M. Bills messages::invalidObject(asyncResp->res, "Password"); 18404ae99ecSEd Tanous }, 18504ae99ecSEd Tanous "xyz.openbmc_project.User.Manager", 18604ae99ecSEd Tanous "/xyz/openbmc_project/user/" + username, 18704ae99ecSEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 18804ae99ecSEd Tanous 18904ae99ecSEd Tanous BMCWEB_LOG_ERROR << "pamUpdatePassword Failed"; 19004ae99ecSEd Tanous return; 19104ae99ecSEd Tanous } 19204ae99ecSEd Tanous 193f12894f8SJason M. Bills messages::created(asyncResp->res); 19404ae99ecSEd Tanous asyncResp->res.addHeader( 19504ae99ecSEd Tanous "Location", 19604ae99ecSEd Tanous "/redfish/v1/AccountService/Accounts/" + username); 19704ae99ecSEd Tanous }, 19804ae99ecSEd Tanous "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", 1999712f8acSEd Tanous "xyz.openbmc_project.User.Manager", "CreateUser", username, 20004ae99ecSEd Tanous std::array<const char*, 4>{"ipmi", "redfish", "ssh", "web"}, 2019712f8acSEd Tanous *roleId, *enabled); 20204ae99ecSEd Tanous } 20304ae99ecSEd Tanous 20404ae99ecSEd Tanous static const char* getRoleIdFromPrivilege(boost::beast::string_view role) 20504ae99ecSEd Tanous { 20604ae99ecSEd Tanous if (role == "Administrator") 20704ae99ecSEd Tanous { 20804ae99ecSEd Tanous return "priv-admin"; 20904ae99ecSEd Tanous } 21004ae99ecSEd Tanous else if (role == "Callback") 21104ae99ecSEd Tanous { 21204ae99ecSEd Tanous return "priv-callback"; 21304ae99ecSEd Tanous } 21404ae99ecSEd Tanous else if (role == "User") 21504ae99ecSEd Tanous { 21604ae99ecSEd Tanous return "priv-user"; 21704ae99ecSEd Tanous } 21804ae99ecSEd Tanous else if (role == "Operator") 21904ae99ecSEd Tanous { 22004ae99ecSEd Tanous return "priv-operator"; 22104ae99ecSEd Tanous } 22204ae99ecSEd Tanous return nullptr; 22304ae99ecSEd Tanous } 224b9b2e0b2SEd Tanous }; 225b9b2e0b2SEd Tanous 226a840879dSEd Tanous template <typename Callback> 227a840879dSEd Tanous inline void checkDbusPathExists(const std::string& path, Callback&& callback) 228a840879dSEd Tanous { 229a840879dSEd Tanous using GetObjectType = 230a840879dSEd Tanous std::vector<std::pair<std::string, std::vector<std::string>>>; 231a840879dSEd Tanous 232a840879dSEd Tanous crow::connections::systemBus->async_method_call( 233a840879dSEd Tanous [callback{std::move(callback)}](const boost::system::error_code ec, 234a840879dSEd Tanous const GetObjectType& object_names) { 235a840879dSEd Tanous callback(ec || object_names.size() == 0); 236a840879dSEd Tanous }, 237a840879dSEd Tanous "xyz.openbmc_project.ObjectMapper", 238a840879dSEd Tanous "/xyz/openbmc_project/object_mapper", 239a840879dSEd Tanous "xyz.openbmc_project.ObjectMapper", "GetObject", path, 240a840879dSEd Tanous std::array<std::string, 0>()); 241a840879dSEd Tanous } 242a840879dSEd Tanous 243b9b2e0b2SEd Tanous class ManagerAccount : public Node 244b9b2e0b2SEd Tanous { 245b9b2e0b2SEd Tanous public: 246b9b2e0b2SEd Tanous ManagerAccount(CrowApp& app) : 247b9b2e0b2SEd Tanous Node(app, "/redfish/v1/AccountService/Accounts/<str>/", std::string()) 248b9b2e0b2SEd Tanous { 249b9b2e0b2SEd Tanous entityPrivileges = { 250b9b2e0b2SEd Tanous {boost::beast::http::verb::get, 251b9b2e0b2SEd Tanous {{"ConfigureUsers"}, {"ConfigureManager"}, {"ConfigureSelf"}}}, 252b9b2e0b2SEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 253b9b2e0b2SEd Tanous {boost::beast::http::verb::patch, {{"ConfigureUsers"}}}, 254b9b2e0b2SEd Tanous {boost::beast::http::verb::put, {{"ConfigureUsers"}}}, 255b9b2e0b2SEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureUsers"}}}, 256b9b2e0b2SEd Tanous {boost::beast::http::verb::post, {{"ConfigureUsers"}}}}; 257b9b2e0b2SEd Tanous } 258b9b2e0b2SEd Tanous 259b9b2e0b2SEd Tanous private: 260b9b2e0b2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 261b9b2e0b2SEd Tanous const std::vector<std::string>& params) override 262b9b2e0b2SEd Tanous { 263*0f74e643SEd Tanous res.jsonValue = { 264*0f74e643SEd Tanous {"@odata.context", 265*0f74e643SEd Tanous "/redfish/v1/$metadata#ManagerAccount.ManagerAccount"}, 266*0f74e643SEd Tanous {"@odata.type", "#ManagerAccount.v1_0_3.ManagerAccount"}, 267*0f74e643SEd Tanous 268*0f74e643SEd Tanous {"Name", "User Account"}, 269*0f74e643SEd Tanous {"Description", "User Account"}, 270*0f74e643SEd Tanous {"Password", nullptr}, 271*0f74e643SEd Tanous {"RoleId", "Administrator"}, 272*0f74e643SEd Tanous {"Links", 273*0f74e643SEd Tanous {{"Role", 274*0f74e643SEd Tanous {{"@odata.id", 275*0f74e643SEd Tanous "/redfish/v1/AccountService/Roles/Administrator"}}}}}}; 276*0f74e643SEd Tanous 277b9b2e0b2SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 278b9b2e0b2SEd Tanous 279b9b2e0b2SEd Tanous if (params.size() != 1) 280b9b2e0b2SEd Tanous { 281f12894f8SJason M. Bills messages::internalError(asyncResp->res); 282b9b2e0b2SEd Tanous return; 283b9b2e0b2SEd Tanous } 284b9b2e0b2SEd Tanous 285b9b2e0b2SEd Tanous crow::connections::systemBus->async_method_call( 286b9b2e0b2SEd Tanous [asyncResp, accountName{std::string(params[0])}]( 287b9b2e0b2SEd Tanous const boost::system::error_code ec, 288b9b2e0b2SEd Tanous const ManagedObjectType& users) { 289b9b2e0b2SEd Tanous if (ec) 290b9b2e0b2SEd Tanous { 291f12894f8SJason M. Bills messages::internalError(asyncResp->res); 292b9b2e0b2SEd Tanous return; 293b9b2e0b2SEd Tanous } 294b9b2e0b2SEd Tanous 295b9b2e0b2SEd Tanous for (auto& user : users) 296b9b2e0b2SEd Tanous { 297b9b2e0b2SEd Tanous const std::string& path = 298b9b2e0b2SEd Tanous static_cast<const std::string&>(user.first); 299b9b2e0b2SEd Tanous std::size_t lastIndex = path.rfind("/"); 300b9b2e0b2SEd Tanous if (lastIndex == std::string::npos) 301b9b2e0b2SEd Tanous { 302b9b2e0b2SEd Tanous lastIndex = 0; 303b9b2e0b2SEd Tanous } 304b9b2e0b2SEd Tanous else 305b9b2e0b2SEd Tanous { 306b9b2e0b2SEd Tanous lastIndex += 1; 307b9b2e0b2SEd Tanous } 308b9b2e0b2SEd Tanous if (path.substr(lastIndex) == accountName) 309b9b2e0b2SEd Tanous { 31065b0dc32SEd Tanous for (const auto& interface : user.second) 31165b0dc32SEd Tanous { 31265b0dc32SEd Tanous if (interface.first == 31365b0dc32SEd Tanous "xyz.openbmc_project.User.Attributes") 31465b0dc32SEd Tanous { 31565b0dc32SEd Tanous for (const auto& property : interface.second) 31665b0dc32SEd Tanous { 31765b0dc32SEd Tanous if (property.first == "UserEnabled") 31865b0dc32SEd Tanous { 31965b0dc32SEd Tanous const bool* userEnabled = 32065b0dc32SEd Tanous mapbox::getPtr<const bool>( 32165b0dc32SEd Tanous property.second); 32265b0dc32SEd Tanous if (userEnabled == nullptr) 32365b0dc32SEd Tanous { 32465b0dc32SEd Tanous BMCWEB_LOG_ERROR 32565b0dc32SEd Tanous << "UserEnabled wasn't a bool"; 32665b0dc32SEd Tanous continue; 32765b0dc32SEd Tanous } 32865b0dc32SEd Tanous asyncResp->res.jsonValue["Enabled"] = 32965b0dc32SEd Tanous *userEnabled; 33065b0dc32SEd Tanous } 33165b0dc32SEd Tanous else if (property.first == 33265b0dc32SEd Tanous "UserLockedForFailedAttempt") 33365b0dc32SEd Tanous { 33465b0dc32SEd Tanous const bool* userLocked = 33565b0dc32SEd Tanous mapbox::getPtr<const bool>( 33665b0dc32SEd Tanous property.second); 33765b0dc32SEd Tanous if (userLocked == nullptr) 33865b0dc32SEd Tanous { 33965b0dc32SEd Tanous BMCWEB_LOG_ERROR 34065b0dc32SEd Tanous << "UserEnabled wasn't a bool"; 34165b0dc32SEd Tanous continue; 34265b0dc32SEd Tanous } 34365b0dc32SEd Tanous asyncResp->res.jsonValue["Locked"] = 34465b0dc32SEd Tanous *userLocked; 34565b0dc32SEd Tanous } 34665b0dc32SEd Tanous } 34765b0dc32SEd Tanous } 34865b0dc32SEd Tanous } 34965b0dc32SEd Tanous 350b9b2e0b2SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 351b9b2e0b2SEd Tanous "/redfish/v1/AccountService/Accounts/" + 352b9b2e0b2SEd Tanous accountName; 353b9b2e0b2SEd Tanous asyncResp->res.jsonValue["Id"] = accountName; 354b9b2e0b2SEd Tanous asyncResp->res.jsonValue["UserName"] = accountName; 355b9b2e0b2SEd Tanous 356b9b2e0b2SEd Tanous return; 357b9b2e0b2SEd Tanous } 358b9b2e0b2SEd Tanous } 359b9b2e0b2SEd Tanous 360f12894f8SJason M. Bills messages::resourceNotFound(asyncResp->res, "ManagerAccount", 361f12894f8SJason M. Bills accountName); 362b9b2e0b2SEd Tanous }, 363b9b2e0b2SEd Tanous "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", 364b9b2e0b2SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 365b9b2e0b2SEd Tanous } 366a840879dSEd Tanous 367a840879dSEd Tanous void doPatch(crow::Response& res, const crow::Request& req, 368a840879dSEd Tanous const std::vector<std::string>& params) override 369a840879dSEd Tanous { 370a840879dSEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 371a840879dSEd Tanous if (params.size() != 1) 372a840879dSEd Tanous { 373f12894f8SJason M. Bills messages::internalError(asyncResp->res); 374a840879dSEd Tanous return; 375a840879dSEd Tanous } 376a840879dSEd Tanous 3779712f8acSEd Tanous boost::optional<std::string> password; 3789712f8acSEd Tanous boost::optional<bool> enabled; 3799712f8acSEd Tanous if (!json_util::readJson(req, res, "Password", password, "Enabled", 3809712f8acSEd Tanous enabled)) 381a840879dSEd Tanous { 382a840879dSEd Tanous return; 383a840879dSEd Tanous } 384a840879dSEd Tanous 385a840879dSEd Tanous // Check the user exists before updating the fields 386a840879dSEd Tanous checkDbusPathExists( 387a840879dSEd Tanous "/xyz/openbmc_project/users/" + params[0], 3889712f8acSEd Tanous [username{std::string(params[0])}, password(std::move(password)), 3899712f8acSEd Tanous enabled(std::move(enabled)), asyncResp](bool userExists) { 390a840879dSEd Tanous if (!userExists) 391a840879dSEd Tanous { 392a840879dSEd Tanous messages::resourceNotFound( 393f12894f8SJason M. Bills asyncResp->res, "#ManagerAccount.v1_0_3.ManagerAccount", 394f12894f8SJason M. Bills username); 395a840879dSEd Tanous return; 396a840879dSEd Tanous } 397a840879dSEd Tanous 3989712f8acSEd Tanous if (password) 399a840879dSEd Tanous { 4009712f8acSEd Tanous if (!pamUpdatePassword(username, *password)) 401a840879dSEd Tanous { 402a840879dSEd Tanous BMCWEB_LOG_ERROR << "pamUpdatePassword Failed"; 403f12894f8SJason M. Bills messages::internalError(asyncResp->res); 404a840879dSEd Tanous return; 405a840879dSEd Tanous } 406a840879dSEd Tanous } 407a840879dSEd Tanous 4089712f8acSEd Tanous if (enabled) 409a840879dSEd Tanous { 410a840879dSEd Tanous crow::connections::systemBus->async_method_call( 411a840879dSEd Tanous [asyncResp](const boost::system::error_code ec) { 412a840879dSEd Tanous if (ec) 413a840879dSEd Tanous { 4149712f8acSEd Tanous BMCWEB_LOG_ERROR << "D-Bus responses error: " 4159712f8acSEd Tanous << ec; 416f12894f8SJason M. Bills messages::internalError(asyncResp->res); 417a840879dSEd Tanous return; 418a840879dSEd Tanous } 419a840879dSEd Tanous // TODO Consider support polling mechanism to 420a840879dSEd Tanous // verify status of host and chassis after 421a840879dSEd Tanous // execute the requested action. 422f12894f8SJason M. Bills messages::success(asyncResp->res); 423a840879dSEd Tanous }, 424a840879dSEd Tanous "xyz.openbmc_project.User.Manager", 425a840879dSEd Tanous "/xyz/openbmc_project/users/" + username, 426a840879dSEd Tanous "org.freedesktop.DBus.Properties", "Set", 427a840879dSEd Tanous "xyz.openbmc_project.User.Attributes" 428a840879dSEd Tanous "UserEnabled", 4299712f8acSEd Tanous sdbusplus::message::variant<bool>{*enabled}); 430a840879dSEd Tanous } 431a840879dSEd Tanous }); 432a840879dSEd Tanous } 43306e086d9SEd Tanous 43406e086d9SEd Tanous void doDelete(crow::Response& res, const crow::Request& req, 43506e086d9SEd Tanous const std::vector<std::string>& params) override 43606e086d9SEd Tanous { 43706e086d9SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 43806e086d9SEd Tanous 43906e086d9SEd Tanous if (params.size() != 1) 44006e086d9SEd Tanous { 441f12894f8SJason M. Bills messages::internalError(asyncResp->res); 44206e086d9SEd Tanous return; 44306e086d9SEd Tanous } 44406e086d9SEd Tanous 44506e086d9SEd Tanous const std::string userPath = "/xyz/openbmc_project/user/" + params[0]; 44606e086d9SEd Tanous 44706e086d9SEd Tanous crow::connections::systemBus->async_method_call( 44806e086d9SEd Tanous [asyncResp, username{std::move(params[0])}]( 44906e086d9SEd Tanous const boost::system::error_code ec) { 45006e086d9SEd Tanous if (ec) 45106e086d9SEd Tanous { 45206e086d9SEd Tanous messages::resourceNotFound( 453f12894f8SJason M. Bills asyncResp->res, "#ManagerAccount.v1_0_3.ManagerAccount", 454f12894f8SJason M. Bills username); 45506e086d9SEd Tanous return; 45606e086d9SEd Tanous } 45706e086d9SEd Tanous 458f12894f8SJason M. Bills messages::accountRemoved(asyncResp->res); 45906e086d9SEd Tanous }, 46006e086d9SEd Tanous "xyz.openbmc_project.User.Manager", userPath, 46106e086d9SEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 46206e086d9SEd Tanous } 4639712f8acSEd Tanous }; // namespace redfish 46488d16c9aSLewanczyk, Dawid 46588d16c9aSLewanczyk, Dawid } // namespace redfish 466