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< 29*84e12cb7SAppaRao Puli std::string, 30*84e12cb7SAppaRao Puli boost::container::flat_map< 31*84e12cb7SAppaRao Puli std::string, sdbusplus::message::variant<bool, std::string>>>>>; 32*84e12cb7SAppaRao Puli 33*84e12cb7SAppaRao Puli inline std::string getPrivilegeFromRoleId(boost::beast::string_view role) 34*84e12cb7SAppaRao Puli { 35*84e12cb7SAppaRao Puli if (role == "priv-admin") 36*84e12cb7SAppaRao Puli { 37*84e12cb7SAppaRao Puli return "Administrator"; 38*84e12cb7SAppaRao Puli } 39*84e12cb7SAppaRao Puli else if (role == "priv-callback") 40*84e12cb7SAppaRao Puli { 41*84e12cb7SAppaRao Puli return "Callback"; 42*84e12cb7SAppaRao Puli } 43*84e12cb7SAppaRao Puli else if (role == "priv-user") 44*84e12cb7SAppaRao Puli { 45*84e12cb7SAppaRao Puli return "User"; 46*84e12cb7SAppaRao Puli } 47*84e12cb7SAppaRao Puli else if (role == "priv-operator") 48*84e12cb7SAppaRao Puli { 49*84e12cb7SAppaRao Puli return "Operator"; 50*84e12cb7SAppaRao Puli } 51*84e12cb7SAppaRao Puli return ""; 52*84e12cb7SAppaRao Puli } 53*84e12cb7SAppaRao Puli inline std::string getRoleIdFromPrivilege(boost::beast::string_view role) 54*84e12cb7SAppaRao Puli { 55*84e12cb7SAppaRao Puli if (role == "Administrator") 56*84e12cb7SAppaRao Puli { 57*84e12cb7SAppaRao Puli return "priv-admin"; 58*84e12cb7SAppaRao Puli } 59*84e12cb7SAppaRao Puli else if (role == "Callback") 60*84e12cb7SAppaRao Puli { 61*84e12cb7SAppaRao Puli return "priv-callback"; 62*84e12cb7SAppaRao Puli } 63*84e12cb7SAppaRao Puli else if (role == "User") 64*84e12cb7SAppaRao Puli { 65*84e12cb7SAppaRao Puli return "priv-user"; 66*84e12cb7SAppaRao Puli } 67*84e12cb7SAppaRao Puli else if (role == "Operator") 68*84e12cb7SAppaRao Puli { 69*84e12cb7SAppaRao Puli return "priv-operator"; 70*84e12cb7SAppaRao Puli } 71*84e12cb7SAppaRao Puli return ""; 72*84e12cb7SAppaRao Puli } 73b9b2e0b2SEd Tanous 741abe55efSEd Tanous class AccountService : public Node 751abe55efSEd Tanous { 7688d16c9aSLewanczyk, Dawid public: 771abe55efSEd Tanous AccountService(CrowApp& app) : Node(app, "/redfish/v1/AccountService/") 781abe55efSEd Tanous { 793ebd75f7SEd Tanous entityPrivileges = { 804b1b8683SBorawski.Lukasz {boost::beast::http::verb::get, 814b1b8683SBorawski.Lukasz {{"ConfigureUsers"}, {"ConfigureManager"}}}, 82e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 83e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureUsers"}}}, 84e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureUsers"}}}, 85e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureUsers"}}}, 86e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureUsers"}}}}; 8788d16c9aSLewanczyk, Dawid } 8888d16c9aSLewanczyk, Dawid 8988d16c9aSLewanczyk, Dawid private: 9055c7b7a2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 911abe55efSEd Tanous const std::vector<std::string>& params) override 921abe55efSEd Tanous { 930f74e643SEd Tanous res.jsonValue["@odata.id"] = "/redfish/v1/AccountService"; 940f74e643SEd Tanous res.jsonValue["@odata.type"] = "#AccountService.v1_1_0.AccountService"; 950f74e643SEd Tanous res.jsonValue["@odata.context"] = 960f74e643SEd Tanous "/redfish/v1/$metadata#AccountService.AccountService"; 970f74e643SEd Tanous res.jsonValue["Id"] = "AccountService"; 980f74e643SEd Tanous res.jsonValue["Description"] = "BMC User Accounts"; 990f74e643SEd Tanous res.jsonValue["Name"] = "Account Service"; 1000f74e643SEd Tanous res.jsonValue["ServiceEnabled"] = true; 1010f74e643SEd Tanous res.jsonValue["MinPasswordLength"] = 1; 1020f74e643SEd Tanous res.jsonValue["MaxPasswordLength"] = 20; 1030f74e643SEd Tanous res.jsonValue["Accounts"]["@odata.id"] = 1040f74e643SEd Tanous "/redfish/v1/AccountService/Accounts"; 1050f74e643SEd Tanous res.jsonValue["Roles"]["@odata.id"] = 1060f74e643SEd Tanous "/redfish/v1/AccountService/Roles"; 1070f74e643SEd Tanous 10888d16c9aSLewanczyk, Dawid res.end(); 10988d16c9aSLewanczyk, Dawid } 11088d16c9aSLewanczyk, Dawid }; 111b9b2e0b2SEd Tanous class AccountsCollection : public Node 112b9b2e0b2SEd Tanous { 113b9b2e0b2SEd Tanous public: 114b9b2e0b2SEd Tanous AccountsCollection(CrowApp& app) : 115b9b2e0b2SEd Tanous Node(app, "/redfish/v1/AccountService/Accounts/") 116b9b2e0b2SEd Tanous { 117b9b2e0b2SEd Tanous entityPrivileges = { 118b9b2e0b2SEd Tanous {boost::beast::http::verb::get, 119b9b2e0b2SEd Tanous {{"ConfigureUsers"}, {"ConfigureManager"}}}, 120b9b2e0b2SEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 121b9b2e0b2SEd Tanous {boost::beast::http::verb::patch, {{"ConfigureUsers"}}}, 122b9b2e0b2SEd Tanous {boost::beast::http::verb::put, {{"ConfigureUsers"}}}, 123b9b2e0b2SEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureUsers"}}}, 124b9b2e0b2SEd Tanous {boost::beast::http::verb::post, {{"ConfigureUsers"}}}}; 125b9b2e0b2SEd Tanous } 126b9b2e0b2SEd Tanous 127b9b2e0b2SEd Tanous private: 128b9b2e0b2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 129b9b2e0b2SEd Tanous const std::vector<std::string>& params) override 130b9b2e0b2SEd Tanous { 131b9b2e0b2SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 1320f74e643SEd Tanous res.jsonValue = {{"@odata.context", 1330f74e643SEd Tanous "/redfish/v1/" 1340f74e643SEd Tanous "$metadata#ManagerAccountCollection." 1350f74e643SEd Tanous "ManagerAccountCollection"}, 1360f74e643SEd Tanous {"@odata.id", "/redfish/v1/AccountService/Accounts"}, 1370f74e643SEd Tanous {"@odata.type", "#ManagerAccountCollection." 1380f74e643SEd Tanous "ManagerAccountCollection"}, 1390f74e643SEd Tanous {"Name", "Accounts Collection"}, 1400f74e643SEd Tanous {"Description", "BMC User Accounts"}}; 1410f74e643SEd Tanous 142b9b2e0b2SEd Tanous crow::connections::systemBus->async_method_call( 143b9b2e0b2SEd Tanous [asyncResp](const boost::system::error_code ec, 144b9b2e0b2SEd Tanous const ManagedObjectType& users) { 145b9b2e0b2SEd Tanous if (ec) 146b9b2e0b2SEd Tanous { 147f12894f8SJason M. Bills messages::internalError(asyncResp->res); 148b9b2e0b2SEd Tanous return; 149b9b2e0b2SEd Tanous } 150b9b2e0b2SEd Tanous 151b9b2e0b2SEd Tanous nlohmann::json& memberArray = 152b9b2e0b2SEd Tanous asyncResp->res.jsonValue["Members"]; 153b9b2e0b2SEd Tanous memberArray = nlohmann::json::array(); 154b9b2e0b2SEd Tanous 155b9b2e0b2SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = users.size(); 156b9b2e0b2SEd Tanous for (auto& user : users) 157b9b2e0b2SEd Tanous { 158b9b2e0b2SEd Tanous const std::string& path = 159b9b2e0b2SEd Tanous static_cast<const std::string&>(user.first); 160b9b2e0b2SEd Tanous std::size_t lastIndex = path.rfind("/"); 161b9b2e0b2SEd Tanous if (lastIndex == std::string::npos) 162b9b2e0b2SEd Tanous { 163b9b2e0b2SEd Tanous lastIndex = 0; 164b9b2e0b2SEd Tanous } 165b9b2e0b2SEd Tanous else 166b9b2e0b2SEd Tanous { 167b9b2e0b2SEd Tanous lastIndex += 1; 168b9b2e0b2SEd Tanous } 169b9b2e0b2SEd Tanous memberArray.push_back( 170b9b2e0b2SEd Tanous {{"@odata.id", "/redfish/v1/AccountService/Accounts/" + 171b9b2e0b2SEd Tanous path.substr(lastIndex)}}); 172b9b2e0b2SEd Tanous } 173b9b2e0b2SEd Tanous }, 174b9b2e0b2SEd Tanous "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", 175b9b2e0b2SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 176b9b2e0b2SEd Tanous } 17704ae99ecSEd Tanous void doPost(crow::Response& res, const crow::Request& req, 17804ae99ecSEd Tanous const std::vector<std::string>& params) override 17904ae99ecSEd Tanous { 18004ae99ecSEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 18104ae99ecSEd Tanous 1829712f8acSEd Tanous std::string username; 1839712f8acSEd Tanous std::string password; 1849712f8acSEd Tanous boost::optional<std::string> roleId("User"); 1859712f8acSEd Tanous boost::optional<bool> enabled = true; 1869712f8acSEd Tanous if (!json_util::readJson(req, res, "UserName", username, "Password", 1879712f8acSEd Tanous password, "RoleId", roleId, "Enabled", 1889712f8acSEd Tanous enabled)) 18904ae99ecSEd Tanous { 19004ae99ecSEd Tanous return; 19104ae99ecSEd Tanous } 19204ae99ecSEd Tanous 193*84e12cb7SAppaRao Puli std::string priv = getRoleIdFromPrivilege(*roleId); 194*84e12cb7SAppaRao Puli if (priv.empty()) 19504ae99ecSEd Tanous { 196f12894f8SJason M. Bills messages::propertyValueNotInList(asyncResp->res, *roleId, "RoleId"); 19704ae99ecSEd Tanous return; 19804ae99ecSEd Tanous } 1999712f8acSEd Tanous roleId = priv; 20004ae99ecSEd Tanous 20104ae99ecSEd Tanous crow::connections::systemBus->async_method_call( 2029712f8acSEd Tanous [asyncResp, username, password{std::move(password)}]( 20304ae99ecSEd Tanous const boost::system::error_code ec) { 20404ae99ecSEd Tanous if (ec) 20504ae99ecSEd Tanous { 20604ae99ecSEd Tanous messages::resourceAlreadyExists( 207f12894f8SJason M. Bills asyncResp->res, "#ManagerAccount.v1_0_3.ManagerAccount", 208f12894f8SJason M. Bills "UserName", username); 20904ae99ecSEd Tanous return; 21004ae99ecSEd Tanous } 21104ae99ecSEd Tanous 21204ae99ecSEd Tanous if (!pamUpdatePassword(username, password)) 21304ae99ecSEd Tanous { 21404ae99ecSEd Tanous // At this point we have a user that's been created, but the 21504ae99ecSEd Tanous // password set failed. Something is wrong, so delete the 21604ae99ecSEd Tanous // user that we've already created 21704ae99ecSEd Tanous crow::connections::systemBus->async_method_call( 21804ae99ecSEd Tanous [asyncResp](const boost::system::error_code ec) { 21904ae99ecSEd Tanous if (ec) 22004ae99ecSEd Tanous { 221f12894f8SJason M. Bills messages::internalError(asyncResp->res); 22204ae99ecSEd Tanous return; 22304ae99ecSEd Tanous } 22404ae99ecSEd Tanous 225f12894f8SJason M. Bills messages::invalidObject(asyncResp->res, "Password"); 22604ae99ecSEd Tanous }, 22704ae99ecSEd Tanous "xyz.openbmc_project.User.Manager", 22804ae99ecSEd Tanous "/xyz/openbmc_project/user/" + username, 22904ae99ecSEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 23004ae99ecSEd Tanous 23104ae99ecSEd Tanous BMCWEB_LOG_ERROR << "pamUpdatePassword Failed"; 23204ae99ecSEd Tanous return; 23304ae99ecSEd Tanous } 23404ae99ecSEd Tanous 235f12894f8SJason M. Bills messages::created(asyncResp->res); 23604ae99ecSEd Tanous asyncResp->res.addHeader( 23704ae99ecSEd Tanous "Location", 23804ae99ecSEd Tanous "/redfish/v1/AccountService/Accounts/" + username); 23904ae99ecSEd Tanous }, 24004ae99ecSEd Tanous "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", 2419712f8acSEd Tanous "xyz.openbmc_project.User.Manager", "CreateUser", username, 24204ae99ecSEd Tanous std::array<const char*, 4>{"ipmi", "redfish", "ssh", "web"}, 2439712f8acSEd Tanous *roleId, *enabled); 24404ae99ecSEd Tanous } 245b9b2e0b2SEd Tanous }; 246b9b2e0b2SEd Tanous 247a840879dSEd Tanous template <typename Callback> 248a840879dSEd Tanous inline void checkDbusPathExists(const std::string& path, Callback&& callback) 249a840879dSEd Tanous { 250a840879dSEd Tanous using GetObjectType = 251a840879dSEd Tanous std::vector<std::pair<std::string, std::vector<std::string>>>; 252a840879dSEd Tanous 253a840879dSEd Tanous crow::connections::systemBus->async_method_call( 254a840879dSEd Tanous [callback{std::move(callback)}](const boost::system::error_code ec, 255a840879dSEd Tanous const GetObjectType& object_names) { 256*84e12cb7SAppaRao Puli callback(!ec && object_names.size() != 0); 257a840879dSEd Tanous }, 258a840879dSEd Tanous "xyz.openbmc_project.ObjectMapper", 259a840879dSEd Tanous "/xyz/openbmc_project/object_mapper", 260a840879dSEd Tanous "xyz.openbmc_project.ObjectMapper", "GetObject", path, 261a840879dSEd Tanous std::array<std::string, 0>()); 262a840879dSEd Tanous } 263a840879dSEd Tanous 264b9b2e0b2SEd Tanous class ManagerAccount : public Node 265b9b2e0b2SEd Tanous { 266b9b2e0b2SEd Tanous public: 267b9b2e0b2SEd Tanous ManagerAccount(CrowApp& app) : 268b9b2e0b2SEd Tanous Node(app, "/redfish/v1/AccountService/Accounts/<str>/", std::string()) 269b9b2e0b2SEd Tanous { 270b9b2e0b2SEd Tanous entityPrivileges = { 271b9b2e0b2SEd Tanous {boost::beast::http::verb::get, 272b9b2e0b2SEd Tanous {{"ConfigureUsers"}, {"ConfigureManager"}, {"ConfigureSelf"}}}, 273b9b2e0b2SEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 274b9b2e0b2SEd Tanous {boost::beast::http::verb::patch, {{"ConfigureUsers"}}}, 275b9b2e0b2SEd Tanous {boost::beast::http::verb::put, {{"ConfigureUsers"}}}, 276b9b2e0b2SEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureUsers"}}}, 277b9b2e0b2SEd Tanous {boost::beast::http::verb::post, {{"ConfigureUsers"}}}}; 278b9b2e0b2SEd Tanous } 279b9b2e0b2SEd Tanous 280b9b2e0b2SEd Tanous private: 281b9b2e0b2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 282b9b2e0b2SEd Tanous const std::vector<std::string>& params) override 283b9b2e0b2SEd Tanous { 2840f74e643SEd Tanous res.jsonValue = { 2850f74e643SEd Tanous {"@odata.context", 2860f74e643SEd Tanous "/redfish/v1/$metadata#ManagerAccount.ManagerAccount"}, 2870f74e643SEd Tanous {"@odata.type", "#ManagerAccount.v1_0_3.ManagerAccount"}, 2880f74e643SEd Tanous {"Name", "User Account"}, 2890f74e643SEd Tanous {"Description", "User Account"}, 2900f74e643SEd Tanous {"Password", nullptr}, 291*84e12cb7SAppaRao Puli {"RoleId", "Administrator"}}; 2920f74e643SEd Tanous 293b9b2e0b2SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 294b9b2e0b2SEd Tanous 295b9b2e0b2SEd Tanous if (params.size() != 1) 296b9b2e0b2SEd Tanous { 297f12894f8SJason M. Bills messages::internalError(asyncResp->res); 298b9b2e0b2SEd Tanous return; 299b9b2e0b2SEd Tanous } 300b9b2e0b2SEd Tanous 301b9b2e0b2SEd Tanous crow::connections::systemBus->async_method_call( 302b9b2e0b2SEd Tanous [asyncResp, accountName{std::string(params[0])}]( 303b9b2e0b2SEd Tanous const boost::system::error_code ec, 304b9b2e0b2SEd Tanous const ManagedObjectType& users) { 305b9b2e0b2SEd Tanous if (ec) 306b9b2e0b2SEd Tanous { 307f12894f8SJason M. Bills messages::internalError(asyncResp->res); 308b9b2e0b2SEd Tanous return; 309b9b2e0b2SEd Tanous } 310*84e12cb7SAppaRao Puli auto userIt = users.begin(); 311b9b2e0b2SEd Tanous 312*84e12cb7SAppaRao Puli for (; userIt != users.end(); userIt++) 313b9b2e0b2SEd Tanous { 314*84e12cb7SAppaRao Puli if (boost::ends_with(userIt->first.str, "/" + accountName)) 315b9b2e0b2SEd Tanous { 316*84e12cb7SAppaRao Puli break; 317b9b2e0b2SEd Tanous } 318b9b2e0b2SEd Tanous } 319*84e12cb7SAppaRao Puli if (userIt == users.end()) 320b9b2e0b2SEd Tanous { 321*84e12cb7SAppaRao Puli messages::resourceNotFound(asyncResp->res, "ManagerAccount", 322*84e12cb7SAppaRao Puli accountName); 323*84e12cb7SAppaRao Puli return; 324*84e12cb7SAppaRao Puli } 325*84e12cb7SAppaRao Puli for (const auto& interface : userIt->second) 32665b0dc32SEd Tanous { 32765b0dc32SEd Tanous if (interface.first == 32865b0dc32SEd Tanous "xyz.openbmc_project.User.Attributes") 32965b0dc32SEd Tanous { 33065b0dc32SEd Tanous for (const auto& property : interface.second) 33165b0dc32SEd Tanous { 33265b0dc32SEd Tanous if (property.first == "UserEnabled") 33365b0dc32SEd Tanous { 33465b0dc32SEd Tanous const bool* userEnabled = 335*84e12cb7SAppaRao Puli sdbusplus::message::variant_ns::get_if< 336*84e12cb7SAppaRao Puli bool>(&property.second); 33765b0dc32SEd Tanous if (userEnabled == nullptr) 33865b0dc32SEd Tanous { 33965b0dc32SEd Tanous BMCWEB_LOG_ERROR 34065b0dc32SEd Tanous << "UserEnabled wasn't a bool"; 341*84e12cb7SAppaRao Puli messages::internalError(asyncResp->res); 342*84e12cb7SAppaRao Puli return; 34365b0dc32SEd Tanous } 34465b0dc32SEd Tanous asyncResp->res.jsonValue["Enabled"] = 34565b0dc32SEd Tanous *userEnabled; 34665b0dc32SEd Tanous } 34765b0dc32SEd Tanous else if (property.first == 34865b0dc32SEd Tanous "UserLockedForFailedAttempt") 34965b0dc32SEd Tanous { 35065b0dc32SEd Tanous const bool* userLocked = 351*84e12cb7SAppaRao Puli sdbusplus::message::variant_ns::get_if< 352*84e12cb7SAppaRao Puli bool>(&property.second); 35365b0dc32SEd Tanous if (userLocked == nullptr) 35465b0dc32SEd Tanous { 355*84e12cb7SAppaRao Puli BMCWEB_LOG_ERROR << "UserLockedForF" 356*84e12cb7SAppaRao Puli "ailedAttempt " 357*84e12cb7SAppaRao Puli "wasn't a bool"; 358*84e12cb7SAppaRao Puli messages::internalError(asyncResp->res); 359*84e12cb7SAppaRao Puli return; 36065b0dc32SEd Tanous } 36165b0dc32SEd Tanous asyncResp->res.jsonValue["Locked"] = 36265b0dc32SEd Tanous *userLocked; 36365b0dc32SEd Tanous } 364*84e12cb7SAppaRao Puli else if (property.first == "UserPrivilege") 365*84e12cb7SAppaRao Puli { 366*84e12cb7SAppaRao Puli const std::string* userRolePtr = 367*84e12cb7SAppaRao Puli sdbusplus::message::variant_ns::get_if< 368*84e12cb7SAppaRao Puli std::string>(&property.second); 369*84e12cb7SAppaRao Puli if (userRolePtr == nullptr) 370*84e12cb7SAppaRao Puli { 371*84e12cb7SAppaRao Puli BMCWEB_LOG_ERROR 372*84e12cb7SAppaRao Puli << "UserPrivilege wasn't a " 373*84e12cb7SAppaRao Puli "string"; 374*84e12cb7SAppaRao Puli messages::internalError(asyncResp->res); 375*84e12cb7SAppaRao Puli return; 376*84e12cb7SAppaRao Puli } 377*84e12cb7SAppaRao Puli std::string priv = 378*84e12cb7SAppaRao Puli getPrivilegeFromRoleId(*userRolePtr); 379*84e12cb7SAppaRao Puli if (priv.empty()) 380*84e12cb7SAppaRao Puli { 381*84e12cb7SAppaRao Puli BMCWEB_LOG_ERROR << "Invalid user role"; 382*84e12cb7SAppaRao Puli messages::internalError(asyncResp->res); 383*84e12cb7SAppaRao Puli return; 384*84e12cb7SAppaRao Puli } 385*84e12cb7SAppaRao Puli asyncResp->res.jsonValue["RoleId"] = priv; 386*84e12cb7SAppaRao Puli 387*84e12cb7SAppaRao Puli asyncResp->res.jsonValue["Links"]["Role"] = { 388*84e12cb7SAppaRao Puli {"@odata.id", "/redfish/v1/AccountService/" 389*84e12cb7SAppaRao Puli "Roles/" + 390*84e12cb7SAppaRao Puli priv}}; 391*84e12cb7SAppaRao Puli } 39265b0dc32SEd Tanous } 39365b0dc32SEd Tanous } 39465b0dc32SEd Tanous } 39565b0dc32SEd Tanous 396b9b2e0b2SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 397*84e12cb7SAppaRao Puli "/redfish/v1/AccountService/Accounts/" + accountName; 398b9b2e0b2SEd Tanous asyncResp->res.jsonValue["Id"] = accountName; 399b9b2e0b2SEd Tanous asyncResp->res.jsonValue["UserName"] = accountName; 400b9b2e0b2SEd Tanous }, 401b9b2e0b2SEd Tanous "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", 402b9b2e0b2SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 403b9b2e0b2SEd Tanous } 404a840879dSEd Tanous 405a840879dSEd Tanous void doPatch(crow::Response& res, const crow::Request& req, 406a840879dSEd Tanous const std::vector<std::string>& params) override 407a840879dSEd Tanous { 408a840879dSEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 409a840879dSEd Tanous if (params.size() != 1) 410a840879dSEd Tanous { 411f12894f8SJason M. Bills messages::internalError(asyncResp->res); 412a840879dSEd Tanous return; 413a840879dSEd Tanous } 414a840879dSEd Tanous 415*84e12cb7SAppaRao Puli boost::optional<std::string> newUserName; 4169712f8acSEd Tanous boost::optional<std::string> password; 4179712f8acSEd Tanous boost::optional<bool> enabled; 418*84e12cb7SAppaRao Puli boost::optional<std::string> roleId; 419*84e12cb7SAppaRao Puli if (!json_util::readJson(req, res, "UserName", newUserName, "Password", 420*84e12cb7SAppaRao Puli password, "RoleId", roleId, "Enabled", 4219712f8acSEd Tanous enabled)) 422a840879dSEd Tanous { 423a840879dSEd Tanous return; 424a840879dSEd Tanous } 425a840879dSEd Tanous 426*84e12cb7SAppaRao Puli const std::string& username = params[0]; 427*84e12cb7SAppaRao Puli 428*84e12cb7SAppaRao Puli if (!newUserName) 429a840879dSEd Tanous { 430*84e12cb7SAppaRao Puli // If the username isn't being updated, we can update the properties 431*84e12cb7SAppaRao Puli // directly 432*84e12cb7SAppaRao Puli updateUserProperties(asyncResp, username, password, enabled, 433*84e12cb7SAppaRao Puli roleId); 434*84e12cb7SAppaRao Puli return; 435*84e12cb7SAppaRao Puli } 436*84e12cb7SAppaRao Puli else 437*84e12cb7SAppaRao Puli { 438*84e12cb7SAppaRao Puli crow::connections::systemBus->async_method_call( 439*84e12cb7SAppaRao Puli [this, asyncResp, username, password(std::move(password)), 440*84e12cb7SAppaRao Puli roleId(std::move(roleId)), enabled(std::move(enabled)), 441*84e12cb7SAppaRao Puli newUser{std::string(*newUserName)}]( 442*84e12cb7SAppaRao Puli const boost::system::error_code ec) { 443*84e12cb7SAppaRao Puli if (ec) 444*84e12cb7SAppaRao Puli { 445*84e12cb7SAppaRao Puli BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 446a840879dSEd Tanous messages::resourceNotFound( 447*84e12cb7SAppaRao Puli asyncResp->res, 448*84e12cb7SAppaRao Puli "#ManagerAccount.v1_0_3.ManagerAccount", username); 449a840879dSEd Tanous return; 450a840879dSEd Tanous } 451a840879dSEd Tanous 452*84e12cb7SAppaRao Puli updateUserProperties(asyncResp, newUser, password, enabled, 453*84e12cb7SAppaRao Puli roleId); 454*84e12cb7SAppaRao Puli }, 455*84e12cb7SAppaRao Puli "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", 456*84e12cb7SAppaRao Puli "xyz.openbmc_project.User.Manager", "RenameUser", username, 457*84e12cb7SAppaRao Puli *newUserName); 458*84e12cb7SAppaRao Puli } 459*84e12cb7SAppaRao Puli } 460*84e12cb7SAppaRao Puli 461*84e12cb7SAppaRao Puli void updateUserProperties(std::shared_ptr<AsyncResp> asyncResp, 462*84e12cb7SAppaRao Puli const std::string& username, 463*84e12cb7SAppaRao Puli boost::optional<std::string> password, 464*84e12cb7SAppaRao Puli boost::optional<bool> enabled, 465*84e12cb7SAppaRao Puli boost::optional<std::string> roleId) 466*84e12cb7SAppaRao Puli { 4679712f8acSEd Tanous if (password) 468a840879dSEd Tanous { 4699712f8acSEd Tanous if (!pamUpdatePassword(username, *password)) 470a840879dSEd Tanous { 471a840879dSEd Tanous BMCWEB_LOG_ERROR << "pamUpdatePassword Failed"; 472f12894f8SJason M. Bills messages::internalError(asyncResp->res); 473a840879dSEd Tanous return; 474a840879dSEd Tanous } 475a840879dSEd Tanous } 476a840879dSEd Tanous 4779712f8acSEd Tanous if (enabled) 478a840879dSEd Tanous { 479a840879dSEd Tanous crow::connections::systemBus->async_method_call( 480a840879dSEd Tanous [asyncResp](const boost::system::error_code ec) { 481a840879dSEd Tanous if (ec) 482a840879dSEd Tanous { 483*84e12cb7SAppaRao Puli BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 484f12894f8SJason M. Bills messages::internalError(asyncResp->res); 485a840879dSEd Tanous return; 486a840879dSEd Tanous } 487*84e12cb7SAppaRao Puli messages::success(asyncResp->res); 488*84e12cb7SAppaRao Puli return; 489*84e12cb7SAppaRao Puli }, 490*84e12cb7SAppaRao Puli "xyz.openbmc_project.User.Manager", 491*84e12cb7SAppaRao Puli "/xyz/openbmc_project/user/" + username, 492*84e12cb7SAppaRao Puli "org.freedesktop.DBus.Properties", "Set", 493*84e12cb7SAppaRao Puli "xyz.openbmc_project.User.Attributes", "UserEnabled", 494*84e12cb7SAppaRao Puli sdbusplus::message::variant<bool>{*enabled}); 495*84e12cb7SAppaRao Puli } 496*84e12cb7SAppaRao Puli 497*84e12cb7SAppaRao Puli if (roleId) 498*84e12cb7SAppaRao Puli { 499*84e12cb7SAppaRao Puli std::string priv = getRoleIdFromPrivilege(*roleId); 500*84e12cb7SAppaRao Puli if (priv.empty()) 501*84e12cb7SAppaRao Puli { 502*84e12cb7SAppaRao Puli messages::propertyValueNotInList(asyncResp->res, *roleId, 503*84e12cb7SAppaRao Puli "RoleId"); 504*84e12cb7SAppaRao Puli return; 505*84e12cb7SAppaRao Puli } 506*84e12cb7SAppaRao Puli 507*84e12cb7SAppaRao Puli crow::connections::systemBus->async_method_call( 508*84e12cb7SAppaRao Puli [asyncResp](const boost::system::error_code ec) { 509*84e12cb7SAppaRao Puli if (ec) 510*84e12cb7SAppaRao Puli { 511*84e12cb7SAppaRao Puli BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 512*84e12cb7SAppaRao Puli messages::internalError(asyncResp->res); 513*84e12cb7SAppaRao Puli return; 514*84e12cb7SAppaRao Puli } 515f12894f8SJason M. Bills messages::success(asyncResp->res); 516a840879dSEd Tanous }, 517a840879dSEd Tanous "xyz.openbmc_project.User.Manager", 518*84e12cb7SAppaRao Puli "/xyz/openbmc_project/user/" + username, 519a840879dSEd Tanous "org.freedesktop.DBus.Properties", "Set", 520*84e12cb7SAppaRao Puli "xyz.openbmc_project.User.Attributes", "UserPrivilege", 521*84e12cb7SAppaRao Puli sdbusplus::message::variant<std::string>{priv}); 522a840879dSEd Tanous } 523a840879dSEd Tanous } 52406e086d9SEd Tanous 52506e086d9SEd Tanous void doDelete(crow::Response& res, const crow::Request& req, 52606e086d9SEd Tanous const std::vector<std::string>& params) override 52706e086d9SEd Tanous { 52806e086d9SEd Tanous auto asyncResp = std::make_shared<AsyncResp>(res); 52906e086d9SEd Tanous 53006e086d9SEd Tanous if (params.size() != 1) 53106e086d9SEd Tanous { 532f12894f8SJason M. Bills messages::internalError(asyncResp->res); 53306e086d9SEd Tanous return; 53406e086d9SEd Tanous } 53506e086d9SEd Tanous 53606e086d9SEd Tanous const std::string userPath = "/xyz/openbmc_project/user/" + params[0]; 53706e086d9SEd Tanous 53806e086d9SEd Tanous crow::connections::systemBus->async_method_call( 53906e086d9SEd Tanous [asyncResp, username{std::move(params[0])}]( 54006e086d9SEd Tanous const boost::system::error_code ec) { 54106e086d9SEd Tanous if (ec) 54206e086d9SEd Tanous { 54306e086d9SEd Tanous messages::resourceNotFound( 544f12894f8SJason M. Bills asyncResp->res, "#ManagerAccount.v1_0_3.ManagerAccount", 545f12894f8SJason M. Bills username); 54606e086d9SEd Tanous return; 54706e086d9SEd Tanous } 54806e086d9SEd Tanous 549f12894f8SJason M. Bills messages::accountRemoved(asyncResp->res); 55006e086d9SEd Tanous }, 55106e086d9SEd Tanous "xyz.openbmc_project.User.Manager", userPath, 55206e086d9SEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 55306e086d9SEd Tanous } 554*84e12cb7SAppaRao Puli }; 55588d16c9aSLewanczyk, Dawid 55688d16c9aSLewanczyk, Dawid } // namespace redfish 557