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 { 106b9b2e0b2SEd Tanous asyncResp->res.result( 107b9b2e0b2SEd Tanous boost::beast::http::status::internal_server_error); 108b9b2e0b2SEd Tanous return; 109b9b2e0b2SEd Tanous } 110b9b2e0b2SEd Tanous 111b9b2e0b2SEd Tanous nlohmann::json& memberArray = 112b9b2e0b2SEd Tanous asyncResp->res.jsonValue["Members"]; 113b9b2e0b2SEd Tanous memberArray = nlohmann::json::array(); 114b9b2e0b2SEd Tanous 115b9b2e0b2SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = users.size(); 116b9b2e0b2SEd Tanous for (auto& user : users) 117b9b2e0b2SEd Tanous { 118b9b2e0b2SEd Tanous const std::string& path = 119b9b2e0b2SEd Tanous static_cast<const std::string&>(user.first); 120b9b2e0b2SEd Tanous std::size_t lastIndex = path.rfind("/"); 121b9b2e0b2SEd Tanous if (lastIndex == std::string::npos) 122b9b2e0b2SEd Tanous { 123b9b2e0b2SEd Tanous lastIndex = 0; 124b9b2e0b2SEd Tanous } 125b9b2e0b2SEd Tanous else 126b9b2e0b2SEd Tanous { 127b9b2e0b2SEd Tanous lastIndex += 1; 128b9b2e0b2SEd Tanous } 129b9b2e0b2SEd Tanous memberArray.push_back( 130b9b2e0b2SEd Tanous {{"@odata.id", "/redfish/v1/AccountService/Accounts/" + 131b9b2e0b2SEd Tanous path.substr(lastIndex)}}); 132b9b2e0b2SEd Tanous } 133b9b2e0b2SEd Tanous }, 134b9b2e0b2SEd Tanous "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", 135b9b2e0b2SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 136b9b2e0b2SEd Tanous } 13704ae99ecSEd Tanous void doPost(crow::Response& res, const crow::Request& req, 13804ae99ecSEd Tanous const std::vector<std::string>& params) override 13904ae99ecSEd Tanous { 14004ae99ecSEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 14104ae99ecSEd Tanous 142*9712f8acSEd Tanous std::string username; 143*9712f8acSEd Tanous std::string password; 144*9712f8acSEd Tanous boost::optional<std::string> roleId("User"); 145*9712f8acSEd Tanous boost::optional<bool> enabled = true; 146*9712f8acSEd Tanous if (!json_util::readJson(req, res, "UserName", username, "Password", 147*9712f8acSEd Tanous password, "RoleId", roleId, "Enabled", 148*9712f8acSEd Tanous enabled)) 14904ae99ecSEd Tanous { 15004ae99ecSEd Tanous return; 15104ae99ecSEd Tanous } 15204ae99ecSEd Tanous 153*9712f8acSEd Tanous const char* priv = getRoleIdFromPrivilege(*roleId); 15404ae99ecSEd Tanous if (priv == nullptr) 15504ae99ecSEd Tanous { 15604ae99ecSEd Tanous messages::addMessageToErrorJson( 157*9712f8acSEd Tanous res.jsonValue, 158*9712f8acSEd Tanous messages::propertyValueNotInList(*roleId, "RoleId")); 159*9712f8acSEd Tanous res.result(boost::beast::http::status::bad_request); 16004ae99ecSEd Tanous return; 16104ae99ecSEd Tanous } 162*9712f8acSEd Tanous roleId = priv; 16304ae99ecSEd Tanous 16404ae99ecSEd Tanous crow::connections::systemBus->async_method_call( 165*9712f8acSEd Tanous [asyncResp, username, password{std::move(password)}]( 16604ae99ecSEd Tanous const boost::system::error_code ec) { 16704ae99ecSEd Tanous if (ec) 16804ae99ecSEd Tanous { 16904ae99ecSEd Tanous messages::addMessageToErrorJson( 17004ae99ecSEd Tanous asyncResp->res.jsonValue, 17104ae99ecSEd Tanous messages::resourceAlreadyExists( 17204ae99ecSEd Tanous "#ManagerAccount.v1_0_3.ManagerAccount", "UserName", 17304ae99ecSEd Tanous username)); 17404ae99ecSEd Tanous asyncResp->res.result( 17504ae99ecSEd Tanous boost::beast::http::status::bad_request); 17604ae99ecSEd Tanous return; 17704ae99ecSEd Tanous } 17804ae99ecSEd Tanous 17904ae99ecSEd Tanous if (!pamUpdatePassword(username, password)) 18004ae99ecSEd Tanous { 18104ae99ecSEd Tanous // At this point we have a user that's been created, but the 18204ae99ecSEd Tanous // password set failed. Something is wrong, so delete the 18304ae99ecSEd Tanous // user that we've already created 18404ae99ecSEd Tanous crow::connections::systemBus->async_method_call( 18504ae99ecSEd Tanous [asyncResp](const boost::system::error_code ec) { 18604ae99ecSEd Tanous if (ec) 18704ae99ecSEd Tanous { 18804ae99ecSEd Tanous asyncResp->res.result( 18904ae99ecSEd Tanous boost::beast::http::status:: 19004ae99ecSEd Tanous internal_server_error); 19104ae99ecSEd Tanous return; 19204ae99ecSEd Tanous } 19304ae99ecSEd Tanous 19404ae99ecSEd Tanous asyncResp->res.result( 19504ae99ecSEd Tanous boost::beast::http::status::bad_request); 19604ae99ecSEd Tanous }, 19704ae99ecSEd Tanous "xyz.openbmc_project.User.Manager", 19804ae99ecSEd Tanous "/xyz/openbmc_project/user/" + username, 19904ae99ecSEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 20004ae99ecSEd Tanous 20104ae99ecSEd Tanous BMCWEB_LOG_ERROR << "pamUpdatePassword Failed"; 20204ae99ecSEd Tanous return; 20304ae99ecSEd Tanous } 20404ae99ecSEd Tanous 20504ae99ecSEd Tanous messages::addMessageToJsonRoot(asyncResp->res.jsonValue, 20604ae99ecSEd Tanous messages::created()); 20704ae99ecSEd Tanous asyncResp->res.addHeader( 20804ae99ecSEd Tanous "Location", 20904ae99ecSEd Tanous "/redfish/v1/AccountService/Accounts/" + username); 21004ae99ecSEd Tanous }, 21104ae99ecSEd Tanous "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", 212*9712f8acSEd Tanous "xyz.openbmc_project.User.Manager", "CreateUser", username, 21304ae99ecSEd Tanous std::array<const char*, 4>{"ipmi", "redfish", "ssh", "web"}, 214*9712f8acSEd Tanous *roleId, *enabled); 21504ae99ecSEd Tanous } 21604ae99ecSEd Tanous 21704ae99ecSEd Tanous static const char* getRoleIdFromPrivilege(boost::beast::string_view role) 21804ae99ecSEd Tanous { 21904ae99ecSEd Tanous if (role == "Administrator") 22004ae99ecSEd Tanous { 22104ae99ecSEd Tanous return "priv-admin"; 22204ae99ecSEd Tanous } 22304ae99ecSEd Tanous else if (role == "Callback") 22404ae99ecSEd Tanous { 22504ae99ecSEd Tanous return "priv-callback"; 22604ae99ecSEd Tanous } 22704ae99ecSEd Tanous else if (role == "User") 22804ae99ecSEd Tanous { 22904ae99ecSEd Tanous return "priv-user"; 23004ae99ecSEd Tanous } 23104ae99ecSEd Tanous else if (role == "Operator") 23204ae99ecSEd Tanous { 23304ae99ecSEd Tanous return "priv-operator"; 23404ae99ecSEd Tanous } 23504ae99ecSEd Tanous return nullptr; 23604ae99ecSEd Tanous } 237b9b2e0b2SEd Tanous }; 238b9b2e0b2SEd Tanous 239a840879dSEd Tanous template <typename Callback> 240a840879dSEd Tanous inline void checkDbusPathExists(const std::string& path, Callback&& callback) 241a840879dSEd Tanous { 242a840879dSEd Tanous using GetObjectType = 243a840879dSEd Tanous std::vector<std::pair<std::string, std::vector<std::string>>>; 244a840879dSEd Tanous 245a840879dSEd Tanous crow::connections::systemBus->async_method_call( 246a840879dSEd Tanous [callback{std::move(callback)}](const boost::system::error_code ec, 247a840879dSEd Tanous const GetObjectType& object_names) { 248a840879dSEd Tanous callback(ec || object_names.size() == 0); 249a840879dSEd Tanous }, 250a840879dSEd Tanous "xyz.openbmc_project.ObjectMapper", 251a840879dSEd Tanous "/xyz/openbmc_project/object_mapper", 252a840879dSEd Tanous "xyz.openbmc_project.ObjectMapper", "GetObject", path, 253a840879dSEd Tanous std::array<std::string, 0>()); 254a840879dSEd Tanous } 255a840879dSEd Tanous 256b9b2e0b2SEd Tanous class ManagerAccount : public Node 257b9b2e0b2SEd Tanous { 258b9b2e0b2SEd Tanous public: 259b9b2e0b2SEd Tanous ManagerAccount(CrowApp& app) : 260b9b2e0b2SEd Tanous Node(app, "/redfish/v1/AccountService/Accounts/<str>/", std::string()) 261b9b2e0b2SEd Tanous { 262b9b2e0b2SEd Tanous Node::json = {{"@odata.context", 263b9b2e0b2SEd Tanous "/redfish/v1/$metadata#ManagerAccount.ManagerAccount"}, 264b9b2e0b2SEd Tanous {"@odata.type", "#ManagerAccount.v1_0_3.ManagerAccount"}, 265b9b2e0b2SEd Tanous 266b9b2e0b2SEd Tanous {"Name", "User Account"}, 267b9b2e0b2SEd Tanous {"Description", "User Account"}, 268b9b2e0b2SEd Tanous {"Password", nullptr}, 269b9b2e0b2SEd Tanous {"RoleId", "Administrator"}, 270b9b2e0b2SEd Tanous {"Links", 271b9b2e0b2SEd Tanous {{"Role", 272b9b2e0b2SEd Tanous {{"@odata.id", "/redfish/v1/AccountService/Roles/" 273b9b2e0b2SEd Tanous "Administrator"}}}}}}; 274b9b2e0b2SEd Tanous 275b9b2e0b2SEd Tanous entityPrivileges = { 276b9b2e0b2SEd Tanous {boost::beast::http::verb::get, 277b9b2e0b2SEd Tanous {{"ConfigureUsers"}, {"ConfigureManager"}, {"ConfigureSelf"}}}, 278b9b2e0b2SEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 279b9b2e0b2SEd Tanous {boost::beast::http::verb::patch, {{"ConfigureUsers"}}}, 280b9b2e0b2SEd Tanous {boost::beast::http::verb::put, {{"ConfigureUsers"}}}, 281b9b2e0b2SEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureUsers"}}}, 282b9b2e0b2SEd Tanous {boost::beast::http::verb::post, {{"ConfigureUsers"}}}}; 283b9b2e0b2SEd Tanous } 284b9b2e0b2SEd Tanous 285b9b2e0b2SEd Tanous private: 286b9b2e0b2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 287b9b2e0b2SEd Tanous const std::vector<std::string>& params) override 288b9b2e0b2SEd Tanous { 289b9b2e0b2SEd Tanous res.jsonValue = Node::json; 290b9b2e0b2SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 291b9b2e0b2SEd Tanous 292b9b2e0b2SEd Tanous if (params.size() != 1) 293b9b2e0b2SEd Tanous { 294b9b2e0b2SEd Tanous res.result(boost::beast::http::status::internal_server_error); 295b9b2e0b2SEd Tanous return; 296b9b2e0b2SEd Tanous } 297b9b2e0b2SEd Tanous 298b9b2e0b2SEd Tanous crow::connections::systemBus->async_method_call( 299b9b2e0b2SEd Tanous [asyncResp, accountName{std::string(params[0])}]( 300b9b2e0b2SEd Tanous const boost::system::error_code ec, 301b9b2e0b2SEd Tanous const ManagedObjectType& users) { 302b9b2e0b2SEd Tanous if (ec) 303b9b2e0b2SEd Tanous { 304b9b2e0b2SEd Tanous asyncResp->res.result( 305b9b2e0b2SEd Tanous boost::beast::http::status::internal_server_error); 306b9b2e0b2SEd Tanous return; 307b9b2e0b2SEd Tanous } 308b9b2e0b2SEd Tanous 309b9b2e0b2SEd Tanous for (auto& user : users) 310b9b2e0b2SEd Tanous { 311b9b2e0b2SEd Tanous const std::string& path = 312b9b2e0b2SEd Tanous static_cast<const std::string&>(user.first); 313b9b2e0b2SEd Tanous std::size_t lastIndex = path.rfind("/"); 314b9b2e0b2SEd Tanous if (lastIndex == std::string::npos) 315b9b2e0b2SEd Tanous { 316b9b2e0b2SEd Tanous lastIndex = 0; 317b9b2e0b2SEd Tanous } 318b9b2e0b2SEd Tanous else 319b9b2e0b2SEd Tanous { 320b9b2e0b2SEd Tanous lastIndex += 1; 321b9b2e0b2SEd Tanous } 322b9b2e0b2SEd Tanous if (path.substr(lastIndex) == accountName) 323b9b2e0b2SEd Tanous { 32465b0dc32SEd Tanous for (const auto& interface : user.second) 32565b0dc32SEd Tanous { 32665b0dc32SEd Tanous if (interface.first == 32765b0dc32SEd Tanous "xyz.openbmc_project.User.Attributes") 32865b0dc32SEd Tanous { 32965b0dc32SEd Tanous for (const auto& property : interface.second) 33065b0dc32SEd Tanous { 33165b0dc32SEd Tanous if (property.first == "UserEnabled") 33265b0dc32SEd Tanous { 33365b0dc32SEd Tanous const bool* userEnabled = 33465b0dc32SEd Tanous mapbox::getPtr<const bool>( 33565b0dc32SEd Tanous property.second); 33665b0dc32SEd Tanous if (userEnabled == nullptr) 33765b0dc32SEd Tanous { 33865b0dc32SEd Tanous BMCWEB_LOG_ERROR 33965b0dc32SEd Tanous << "UserEnabled wasn't a bool"; 34065b0dc32SEd Tanous continue; 34165b0dc32SEd Tanous } 34265b0dc32SEd Tanous asyncResp->res.jsonValue["Enabled"] = 34365b0dc32SEd Tanous *userEnabled; 34465b0dc32SEd Tanous } 34565b0dc32SEd Tanous else if (property.first == 34665b0dc32SEd Tanous "UserLockedForFailedAttempt") 34765b0dc32SEd Tanous { 34865b0dc32SEd Tanous const bool* userLocked = 34965b0dc32SEd Tanous mapbox::getPtr<const bool>( 35065b0dc32SEd Tanous property.second); 35165b0dc32SEd Tanous if (userLocked == nullptr) 35265b0dc32SEd Tanous { 35365b0dc32SEd Tanous BMCWEB_LOG_ERROR 35465b0dc32SEd Tanous << "UserEnabled wasn't a bool"; 35565b0dc32SEd Tanous continue; 35665b0dc32SEd Tanous } 35765b0dc32SEd Tanous asyncResp->res.jsonValue["Locked"] = 35865b0dc32SEd Tanous *userLocked; 35965b0dc32SEd Tanous } 36065b0dc32SEd Tanous } 36165b0dc32SEd Tanous } 36265b0dc32SEd Tanous } 36365b0dc32SEd Tanous 364b9b2e0b2SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 365b9b2e0b2SEd Tanous "/redfish/v1/AccountService/Accounts/" + 366b9b2e0b2SEd Tanous accountName; 367b9b2e0b2SEd Tanous asyncResp->res.jsonValue["Id"] = accountName; 368b9b2e0b2SEd Tanous asyncResp->res.jsonValue["UserName"] = accountName; 369b9b2e0b2SEd Tanous 370b9b2e0b2SEd Tanous return; 371b9b2e0b2SEd Tanous } 372b9b2e0b2SEd Tanous } 373b9b2e0b2SEd Tanous 374b9b2e0b2SEd Tanous asyncResp->res.result(boost::beast::http::status::not_found); 375b9b2e0b2SEd Tanous }, 376b9b2e0b2SEd Tanous "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", 377b9b2e0b2SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 378b9b2e0b2SEd Tanous } 379a840879dSEd Tanous 380a840879dSEd Tanous void doPatch(crow::Response& res, const crow::Request& req, 381a840879dSEd Tanous const std::vector<std::string>& params) override 382a840879dSEd Tanous { 383a840879dSEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 384a840879dSEd Tanous if (params.size() != 1) 385a840879dSEd Tanous { 386a840879dSEd Tanous res.result(boost::beast::http::status::internal_server_error); 387a840879dSEd Tanous return; 388a840879dSEd Tanous } 389a840879dSEd Tanous 390*9712f8acSEd Tanous boost::optional<std::string> password; 391*9712f8acSEd Tanous boost::optional<bool> enabled; 392*9712f8acSEd Tanous if (!json_util::readJson(req, res, "Password", password, "Enabled", 393*9712f8acSEd Tanous enabled)) 394a840879dSEd Tanous { 395a840879dSEd Tanous return; 396a840879dSEd Tanous } 397a840879dSEd Tanous 398a840879dSEd Tanous // Check the user exists before updating the fields 399a840879dSEd Tanous checkDbusPathExists( 400a840879dSEd Tanous "/xyz/openbmc_project/users/" + params[0], 401*9712f8acSEd Tanous [username{std::string(params[0])}, password(std::move(password)), 402*9712f8acSEd Tanous enabled(std::move(enabled)), asyncResp](bool userExists) { 403a840879dSEd Tanous if (!userExists) 404a840879dSEd Tanous { 405a840879dSEd Tanous messages::addMessageToErrorJson( 406a840879dSEd Tanous asyncResp->res.jsonValue, 407a840879dSEd Tanous messages::resourceNotFound( 408a840879dSEd Tanous "#ManagerAccount.v1_0_3.ManagerAccount", username)); 409a840879dSEd Tanous 410a840879dSEd Tanous asyncResp->res.result( 411a840879dSEd Tanous boost::beast::http::status::not_found); 412a840879dSEd Tanous return; 413a840879dSEd Tanous } 414a840879dSEd Tanous 415*9712f8acSEd Tanous if (password) 416a840879dSEd Tanous { 417*9712f8acSEd Tanous if (!pamUpdatePassword(username, *password)) 418a840879dSEd Tanous { 419a840879dSEd Tanous BMCWEB_LOG_ERROR << "pamUpdatePassword Failed"; 420*9712f8acSEd Tanous asyncResp->res.result( 421*9712f8acSEd Tanous boost::beast::http::status::internal_server_error); 422a840879dSEd Tanous return; 423a840879dSEd Tanous } 424a840879dSEd Tanous } 425a840879dSEd Tanous 426*9712f8acSEd Tanous if (enabled) 427a840879dSEd Tanous { 428a840879dSEd Tanous crow::connections::systemBus->async_method_call( 429a840879dSEd Tanous [asyncResp](const boost::system::error_code ec) { 430a840879dSEd Tanous if (ec) 431a840879dSEd Tanous { 432*9712f8acSEd Tanous BMCWEB_LOG_ERROR << "D-Bus responses error: " 433*9712f8acSEd Tanous << ec; 434a840879dSEd Tanous asyncResp->res.result( 435a840879dSEd Tanous boost::beast::http::status:: 436a840879dSEd Tanous internal_server_error); 437a840879dSEd Tanous return; 438a840879dSEd Tanous } 439a840879dSEd Tanous // TODO Consider support polling mechanism to 440a840879dSEd Tanous // verify status of host and chassis after 441a840879dSEd Tanous // execute the requested action. 442a840879dSEd Tanous BMCWEB_LOG_DEBUG << "Response with no content"; 443a840879dSEd Tanous asyncResp->res.result( 444a840879dSEd Tanous boost::beast::http::status::no_content); 445a840879dSEd Tanous }, 446a840879dSEd Tanous "xyz.openbmc_project.User.Manager", 447a840879dSEd Tanous "/xyz/openbmc_project/users/" + username, 448a840879dSEd Tanous "org.freedesktop.DBus.Properties", "Set", 449a840879dSEd Tanous "xyz.openbmc_project.User.Attributes" 450a840879dSEd Tanous "UserEnabled", 451*9712f8acSEd Tanous sdbusplus::message::variant<bool>{*enabled}); 452a840879dSEd Tanous } 453a840879dSEd Tanous }); 454a840879dSEd Tanous } 45506e086d9SEd Tanous 45606e086d9SEd Tanous void doDelete(crow::Response& res, const crow::Request& req, 45706e086d9SEd Tanous const std::vector<std::string>& params) override 45806e086d9SEd Tanous { 45906e086d9SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 46006e086d9SEd Tanous 46106e086d9SEd Tanous if (params.size() != 1) 46206e086d9SEd Tanous { 46306e086d9SEd Tanous res.result(boost::beast::http::status::internal_server_error); 46406e086d9SEd Tanous return; 46506e086d9SEd Tanous } 46606e086d9SEd Tanous 46706e086d9SEd Tanous const std::string userPath = "/xyz/openbmc_project/user/" + params[0]; 46806e086d9SEd Tanous 46906e086d9SEd Tanous crow::connections::systemBus->async_method_call( 47006e086d9SEd Tanous [asyncResp, username{std::move(params[0])}]( 47106e086d9SEd Tanous const boost::system::error_code ec) { 47206e086d9SEd Tanous if (ec) 47306e086d9SEd Tanous { 47406e086d9SEd Tanous messages::addMessageToErrorJson( 47506e086d9SEd Tanous asyncResp->res.jsonValue, 47606e086d9SEd Tanous messages::resourceNotFound( 47706e086d9SEd Tanous "#ManagerAccount.v1_0_3.ManagerAccount", username)); 47806e086d9SEd Tanous asyncResp->res.result( 47906e086d9SEd Tanous boost::beast::http::status::not_found); 48006e086d9SEd Tanous return; 48106e086d9SEd Tanous } 48206e086d9SEd Tanous 48306e086d9SEd Tanous messages::addMessageToJsonRoot(asyncResp->res.jsonValue, 48406e086d9SEd Tanous messages::accountRemoved()); 48506e086d9SEd Tanous }, 48606e086d9SEd Tanous "xyz.openbmc_project.User.Manager", userPath, 48706e086d9SEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 48806e086d9SEd Tanous } 489*9712f8acSEd Tanous }; // namespace redfish 49088d16c9aSLewanczyk, Dawid 49188d16c9aSLewanczyk, Dawid } // namespace redfish 492