xref: /openbmc/bmcweb/features/redfish/lib/account_service.hpp (revision 0f74e643ec246c333ef4724af1ecd5adeb1b6658)
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