blob: d9388cffd55170e1b9c301e033f9aeb2d681f63d [file] [log] [blame]
Lewanczyk, Dawid88d16c92018-02-02 14:51:09 +01001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
Lewanczyk, Dawid88d16c92018-02-02 14:51:09 +010017#include "node.hpp"
18
Ed Tanous65b0dc32018-09-19 16:04:03 -070019#include <error_messages.hpp>
Ed Tanousb9b2e0b2018-09-13 13:47:50 -070020#include <openbmc_dbus_rest.hpp>
Ed Tanousa8408792018-09-05 16:08:38 -070021#include <utils/json_utils.hpp>
Ed Tanousabf2add2019-01-22 16:40:12 -080022#include <variant>
Ed Tanousb9b2e0b2018-09-13 13:47:50 -070023
Ed Tanous1abe55e2018-09-05 08:30:59 -070024namespace redfish
25{
Lewanczyk, Dawid88d16c92018-02-02 14:51:09 +010026
Ed Tanousb9b2e0b2018-09-13 13:47:50 -070027using ManagedObjectType = std::vector<std::pair<
28 sdbusplus::message::object_path,
29 boost::container::flat_map<
Ed Tanousabf2add2019-01-22 16:40:12 -080030 std::string, boost::container::flat_map<
31 std::string, std::variant<bool, std::string>>>>>;
AppaRao Puli84e12cb2018-10-11 01:28:15 +053032
33inline std::string getPrivilegeFromRoleId(boost::beast::string_view role)
34{
35 if (role == "priv-admin")
36 {
37 return "Administrator";
38 }
39 else if (role == "priv-callback")
40 {
41 return "Callback";
42 }
43 else if (role == "priv-user")
44 {
45 return "User";
46 }
47 else if (role == "priv-operator")
48 {
49 return "Operator";
50 }
51 return "";
52}
53inline std::string getRoleIdFromPrivilege(boost::beast::string_view role)
54{
55 if (role == "Administrator")
56 {
57 return "priv-admin";
58 }
59 else if (role == "Callback")
60 {
61 return "priv-callback";
62 }
63 else if (role == "User")
64 {
65 return "priv-user";
66 }
67 else if (role == "Operator")
68 {
69 return "priv-operator";
70 }
71 return "";
72}
Ed Tanousb9b2e0b2018-09-13 13:47:50 -070073
Ed Tanous1abe55e2018-09-05 08:30:59 -070074class AccountService : public Node
75{
76 public:
77 AccountService(CrowApp& app) : Node(app, "/redfish/v1/AccountService/")
78 {
Ed Tanous1abe55e2018-09-05 08:30:59 -070079 entityPrivileges = {
80 {boost::beast::http::verb::get,
81 {{"ConfigureUsers"}, {"ConfigureManager"}}},
82 {boost::beast::http::verb::head, {{"Login"}}},
83 {boost::beast::http::verb::patch, {{"ConfigureUsers"}}},
84 {boost::beast::http::verb::put, {{"ConfigureUsers"}}},
85 {boost::beast::http::verb::delete_, {{"ConfigureUsers"}}},
86 {boost::beast::http::verb::post, {{"ConfigureUsers"}}}};
87 }
Lewanczyk, Dawid88d16c92018-02-02 14:51:09 +010088
Ed Tanous1abe55e2018-09-05 08:30:59 -070089 private:
90 void doGet(crow::Response& res, const crow::Request& req,
91 const std::vector<std::string>& params) override
92 {
AppaRao Puli3d958bb2018-12-25 12:45:54 +053093 auto asyncResp = std::make_shared<AsyncResp>(res);
94 res.jsonValue = {
95 {"@odata.context", "/redfish/v1/"
96 "$metadata#AccountService.AccountService"},
97 {"@odata.id", "/redfish/v1/AccountService"},
98 {"@odata.type", "#AccountService."
99 "v1_1_0.AccountService"},
100 {"Id", "AccountService"},
101 {"Name", "Account Service"},
102 {"Description", "Account Service"},
103 {"ServiceEnabled", true},
104 {"MaxPasswordLength", 31},
105 {"Accounts",
106 {{"@odata.id", "/redfish/v1/AccountService/Accounts"}}},
107 {"Roles", {{"@odata.id", "/redfish/v1/AccountService/Roles"}}}};
Ed Tanous0f74e642018-11-12 15:17:05 -0800108
AppaRao Puli3d958bb2018-12-25 12:45:54 +0530109 crow::connections::systemBus->async_method_call(
110 [asyncResp](
111 const boost::system::error_code ec,
112 const std::vector<std::pair<
Ed Tanousabf2add2019-01-22 16:40:12 -0800113 std::string, std::variant<uint32_t, uint16_t, uint8_t>>>&
AppaRao Puli3d958bb2018-12-25 12:45:54 +0530114 propertiesList) {
115 if (ec)
116 {
117 messages::internalError(asyncResp->res);
118 return;
119 }
120 BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
121 << "properties for AccountService";
122 for (const std::pair<std::string,
Ed Tanousabf2add2019-01-22 16:40:12 -0800123 std::variant<uint32_t, uint16_t, uint8_t>>&
AppaRao Puli3d958bb2018-12-25 12:45:54 +0530124 property : propertiesList)
125 {
126 if (property.first == "MinPasswordLength")
127 {
128 const uint8_t* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800129 std::get_if<uint8_t>(&property.second);
AppaRao Puli3d958bb2018-12-25 12:45:54 +0530130 if (value != nullptr)
131 {
132 asyncResp->res.jsonValue["MinPasswordLength"] =
133 *value;
134 }
135 }
136 if (property.first == "AccountUnlockTimeout")
137 {
138 const uint32_t* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800139 std::get_if<uint32_t>(&property.second);
AppaRao Puli3d958bb2018-12-25 12:45:54 +0530140 if (value != nullptr)
141 {
142 asyncResp->res.jsonValue["AccountLockoutDuration"] =
143 *value;
144 }
145 }
146 if (property.first == "MaxLoginAttemptBeforeLockout")
147 {
148 const uint16_t* value =
Ed Tanousabf2add2019-01-22 16:40:12 -0800149 std::get_if<uint16_t>(&property.second);
AppaRao Puli3d958bb2018-12-25 12:45:54 +0530150 if (value != nullptr)
151 {
152 asyncResp->res
153 .jsonValue["AccountLockoutThreshold"] = *value;
154 }
155 }
156 }
157 },
158 "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
159 "org.freedesktop.DBus.Properties", "GetAll",
160 "xyz.openbmc_project.User.AccountPolicy");
161 }
162 void doPatch(crow::Response& res, const crow::Request& req,
163 const std::vector<std::string>& params) override
164 {
165 auto asyncResp = std::make_shared<AsyncResp>(res);
166
167 std::optional<uint32_t> unlockTimeout;
168 std::optional<uint16_t> lockoutThreshold;
169 if (!json_util::readJson(req, res, "AccountLockoutDuration",
170 unlockTimeout, "AccountLockoutThreshold",
171 lockoutThreshold))
172 {
173 return;
174 }
175 if (unlockTimeout)
176 {
177 crow::connections::systemBus->async_method_call(
178 [asyncResp](const boost::system::error_code ec) {
179 if (ec)
180 {
181 messages::internalError(asyncResp->res);
182 return;
183 }
184 },
185 "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
186 "org.freedesktop.DBus.Properties", "Set",
187 "xyz.openbmc_project.User.AccountPolicy",
Ed Tanousabf2add2019-01-22 16:40:12 -0800188 "AccountUnlockTimeout", std::variant<uint32_t>(*unlockTimeout));
AppaRao Puli3d958bb2018-12-25 12:45:54 +0530189 }
190 if (lockoutThreshold)
191 {
192 crow::connections::systemBus->async_method_call(
193 [asyncResp](const boost::system::error_code ec) {
194 if (ec)
195 {
196 messages::internalError(asyncResp->res);
197 return;
198 }
199 },
200 "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
201 "org.freedesktop.DBus.Properties", "Set",
202 "xyz.openbmc_project.User.AccountPolicy",
203 "MaxLoginAttemptBeforeLockout",
Ed Tanousabf2add2019-01-22 16:40:12 -0800204 std::variant<uint16_t>(*lockoutThreshold));
AppaRao Puli3d958bb2018-12-25 12:45:54 +0530205 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700206 }
Lewanczyk, Dawid88d16c92018-02-02 14:51:09 +0100207};
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700208class AccountsCollection : public Node
209{
210 public:
211 AccountsCollection(CrowApp& app) :
212 Node(app, "/redfish/v1/AccountService/Accounts/")
213 {
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700214 entityPrivileges = {
215 {boost::beast::http::verb::get,
216 {{"ConfigureUsers"}, {"ConfigureManager"}}},
217 {boost::beast::http::verb::head, {{"Login"}}},
218 {boost::beast::http::verb::patch, {{"ConfigureUsers"}}},
219 {boost::beast::http::verb::put, {{"ConfigureUsers"}}},
220 {boost::beast::http::verb::delete_, {{"ConfigureUsers"}}},
221 {boost::beast::http::verb::post, {{"ConfigureUsers"}}}};
222 }
223
224 private:
225 void doGet(crow::Response& res, const crow::Request& req,
226 const std::vector<std::string>& params) override
227 {
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700228 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanous0f74e642018-11-12 15:17:05 -0800229 res.jsonValue = {{"@odata.context",
230 "/redfish/v1/"
231 "$metadata#ManagerAccountCollection."
232 "ManagerAccountCollection"},
233 {"@odata.id", "/redfish/v1/AccountService/Accounts"},
234 {"@odata.type", "#ManagerAccountCollection."
235 "ManagerAccountCollection"},
236 {"Name", "Accounts Collection"},
237 {"Description", "BMC User Accounts"}};
238
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700239 crow::connections::systemBus->async_method_call(
240 [asyncResp](const boost::system::error_code ec,
241 const ManagedObjectType& users) {
242 if (ec)
243 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700244 messages::internalError(asyncResp->res);
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700245 return;
246 }
247
248 nlohmann::json& memberArray =
249 asyncResp->res.jsonValue["Members"];
250 memberArray = nlohmann::json::array();
251
252 asyncResp->res.jsonValue["Members@odata.count"] = users.size();
253 for (auto& user : users)
254 {
255 const std::string& path =
256 static_cast<const std::string&>(user.first);
257 std::size_t lastIndex = path.rfind("/");
258 if (lastIndex == std::string::npos)
259 {
260 lastIndex = 0;
261 }
262 else
263 {
264 lastIndex += 1;
265 }
266 memberArray.push_back(
267 {{"@odata.id", "/redfish/v1/AccountService/Accounts/" +
268 path.substr(lastIndex)}});
269 }
270 },
271 "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
272 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
273 }
Ed Tanous04ae99e2018-09-20 15:54:36 -0700274 void doPost(crow::Response& res, const crow::Request& req,
275 const std::vector<std::string>& params) override
276 {
277 auto asyncResp = std::make_shared<AsyncResp>(res);
278
Ed Tanous9712f8a2018-09-21 13:38:49 -0700279 std::string username;
280 std::string password;
Ed Tanousa24526d2018-12-10 15:17:59 -0800281 std::optional<std::string> roleId("User");
282 std::optional<bool> enabled = true;
Ed Tanous9712f8a2018-09-21 13:38:49 -0700283 if (!json_util::readJson(req, res, "UserName", username, "Password",
284 password, "RoleId", roleId, "Enabled",
285 enabled))
Ed Tanous04ae99e2018-09-20 15:54:36 -0700286 {
287 return;
288 }
289
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530290 std::string priv = getRoleIdFromPrivilege(*roleId);
291 if (priv.empty())
Ed Tanous04ae99e2018-09-20 15:54:36 -0700292 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700293 messages::propertyValueNotInList(asyncResp->res, *roleId, "RoleId");
Ed Tanous04ae99e2018-09-20 15:54:36 -0700294 return;
295 }
Ed Tanous9712f8a2018-09-21 13:38:49 -0700296 roleId = priv;
Ed Tanous04ae99e2018-09-20 15:54:36 -0700297
298 crow::connections::systemBus->async_method_call(
Ed Tanous9712f8a2018-09-21 13:38:49 -0700299 [asyncResp, username, password{std::move(password)}](
Ed Tanous04ae99e2018-09-20 15:54:36 -0700300 const boost::system::error_code ec) {
301 if (ec)
302 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700303 messages::resourceAlreadyExists(
304 asyncResp->res, "#ManagerAccount.v1_0_3.ManagerAccount",
305 "UserName", username);
Ed Tanous04ae99e2018-09-20 15:54:36 -0700306 return;
307 }
308
309 if (!pamUpdatePassword(username, password))
310 {
311 // At this point we have a user that's been created, but the
312 // password set failed. Something is wrong, so delete the
313 // user that we've already created
314 crow::connections::systemBus->async_method_call(
315 [asyncResp](const boost::system::error_code ec) {
316 if (ec)
317 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700318 messages::internalError(asyncResp->res);
Ed Tanous04ae99e2018-09-20 15:54:36 -0700319 return;
320 }
321
Jason M. Billsf12894f2018-10-09 12:45:45 -0700322 messages::invalidObject(asyncResp->res, "Password");
Ed Tanous04ae99e2018-09-20 15:54:36 -0700323 },
324 "xyz.openbmc_project.User.Manager",
325 "/xyz/openbmc_project/user/" + username,
326 "xyz.openbmc_project.Object.Delete", "Delete");
327
328 BMCWEB_LOG_ERROR << "pamUpdatePassword Failed";
329 return;
330 }
331
Jason M. Billsf12894f2018-10-09 12:45:45 -0700332 messages::created(asyncResp->res);
Ed Tanous04ae99e2018-09-20 15:54:36 -0700333 asyncResp->res.addHeader(
334 "Location",
335 "/redfish/v1/AccountService/Accounts/" + username);
336 },
337 "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
Ed Tanous9712f8a2018-09-21 13:38:49 -0700338 "xyz.openbmc_project.User.Manager", "CreateUser", username,
Ed Tanous04ae99e2018-09-20 15:54:36 -0700339 std::array<const char*, 4>{"ipmi", "redfish", "ssh", "web"},
Ed Tanous9712f8a2018-09-21 13:38:49 -0700340 *roleId, *enabled);
Ed Tanous04ae99e2018-09-20 15:54:36 -0700341 }
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700342};
343
Ed Tanousa8408792018-09-05 16:08:38 -0700344template <typename Callback>
345inline void checkDbusPathExists(const std::string& path, Callback&& callback)
346{
347 using GetObjectType =
348 std::vector<std::pair<std::string, std::vector<std::string>>>;
349
350 crow::connections::systemBus->async_method_call(
351 [callback{std::move(callback)}](const boost::system::error_code ec,
352 const GetObjectType& object_names) {
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530353 callback(!ec && object_names.size() != 0);
Ed Tanousa8408792018-09-05 16:08:38 -0700354 },
355 "xyz.openbmc_project.ObjectMapper",
356 "/xyz/openbmc_project/object_mapper",
357 "xyz.openbmc_project.ObjectMapper", "GetObject", path,
358 std::array<std::string, 0>());
359}
360
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700361class ManagerAccount : public Node
362{
363 public:
364 ManagerAccount(CrowApp& app) :
365 Node(app, "/redfish/v1/AccountService/Accounts/<str>/", std::string())
366 {
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700367 entityPrivileges = {
368 {boost::beast::http::verb::get,
369 {{"ConfigureUsers"}, {"ConfigureManager"}, {"ConfigureSelf"}}},
370 {boost::beast::http::verb::head, {{"Login"}}},
371 {boost::beast::http::verb::patch, {{"ConfigureUsers"}}},
372 {boost::beast::http::verb::put, {{"ConfigureUsers"}}},
373 {boost::beast::http::verb::delete_, {{"ConfigureUsers"}}},
374 {boost::beast::http::verb::post, {{"ConfigureUsers"}}}};
375 }
376
377 private:
378 void doGet(crow::Response& res, const crow::Request& req,
379 const std::vector<std::string>& params) override
380 {
Ed Tanous0f74e642018-11-12 15:17:05 -0800381 res.jsonValue = {
382 {"@odata.context",
383 "/redfish/v1/$metadata#ManagerAccount.ManagerAccount"},
384 {"@odata.type", "#ManagerAccount.v1_0_3.ManagerAccount"},
Ed Tanous0f74e642018-11-12 15:17:05 -0800385 {"Name", "User Account"},
386 {"Description", "User Account"},
387 {"Password", nullptr},
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530388 {"RoleId", "Administrator"}};
Ed Tanous0f74e642018-11-12 15:17:05 -0800389
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700390 auto asyncResp = std::make_shared<AsyncResp>(res);
391
392 if (params.size() != 1)
393 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700394 messages::internalError(asyncResp->res);
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700395 return;
396 }
397
398 crow::connections::systemBus->async_method_call(
399 [asyncResp, accountName{std::string(params[0])}](
400 const boost::system::error_code ec,
401 const ManagedObjectType& users) {
402 if (ec)
403 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700404 messages::internalError(asyncResp->res);
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700405 return;
406 }
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530407 auto userIt = users.begin();
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700408
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530409 for (; userIt != users.end(); userIt++)
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700410 {
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530411 if (boost::ends_with(userIt->first.str, "/" + accountName))
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700412 {
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530413 break;
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700414 }
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530415 }
416 if (userIt == users.end())
417 {
418 messages::resourceNotFound(asyncResp->res, "ManagerAccount",
419 accountName);
420 return;
421 }
422 for (const auto& interface : userIt->second)
423 {
424 if (interface.first ==
425 "xyz.openbmc_project.User.Attributes")
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700426 {
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530427 for (const auto& property : interface.second)
Ed Tanous65b0dc32018-09-19 16:04:03 -0700428 {
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530429 if (property.first == "UserEnabled")
Ed Tanous65b0dc32018-09-19 16:04:03 -0700430 {
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530431 const bool* userEnabled =
Ed Tanousabf2add2019-01-22 16:40:12 -0800432 std::get_if<bool>(&property.second);
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530433 if (userEnabled == nullptr)
Ed Tanous65b0dc32018-09-19 16:04:03 -0700434 {
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530435 BMCWEB_LOG_ERROR
436 << "UserEnabled wasn't a bool";
437 messages::internalError(asyncResp->res);
438 return;
Ed Tanous65b0dc32018-09-19 16:04:03 -0700439 }
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530440 asyncResp->res.jsonValue["Enabled"] =
441 *userEnabled;
442 }
443 else if (property.first ==
444 "UserLockedForFailedAttempt")
445 {
446 const bool* userLocked =
Ed Tanousabf2add2019-01-22 16:40:12 -0800447 std::get_if<bool>(&property.second);
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530448 if (userLocked == nullptr)
449 {
450 BMCWEB_LOG_ERROR << "UserLockedForF"
451 "ailedAttempt "
452 "wasn't a bool";
453 messages::internalError(asyncResp->res);
454 return;
455 }
456 asyncResp->res.jsonValue["Locked"] =
457 *userLocked;
458 }
459 else if (property.first == "UserPrivilege")
460 {
461 const std::string* userRolePtr =
Ed Tanousabf2add2019-01-22 16:40:12 -0800462 std::get_if<std::string>(&property.second);
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530463 if (userRolePtr == nullptr)
464 {
465 BMCWEB_LOG_ERROR
466 << "UserPrivilege wasn't a "
467 "string";
468 messages::internalError(asyncResp->res);
469 return;
470 }
471 std::string priv =
472 getPrivilegeFromRoleId(*userRolePtr);
473 if (priv.empty())
474 {
475 BMCWEB_LOG_ERROR << "Invalid user role";
476 messages::internalError(asyncResp->res);
477 return;
478 }
479 asyncResp->res.jsonValue["RoleId"] = priv;
480
481 asyncResp->res.jsonValue["Links"]["Role"] = {
482 {"@odata.id", "/redfish/v1/AccountService/"
483 "Roles/" +
484 priv}};
Ed Tanous65b0dc32018-09-19 16:04:03 -0700485 }
486 }
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700487 }
488 }
489
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530490 asyncResp->res.jsonValue["@odata.id"] =
491 "/redfish/v1/AccountService/Accounts/" + accountName;
492 asyncResp->res.jsonValue["Id"] = accountName;
493 asyncResp->res.jsonValue["UserName"] = accountName;
Ed Tanousb9b2e0b2018-09-13 13:47:50 -0700494 },
495 "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
496 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
497 }
Ed Tanousa8408792018-09-05 16:08:38 -0700498
499 void doPatch(crow::Response& res, const crow::Request& req,
500 const std::vector<std::string>& params) override
501 {
502 auto asyncResp = std::make_shared<AsyncResp>(res);
Ed Tanousa8408792018-09-05 16:08:38 -0700503 if (params.size() != 1)
504 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700505 messages::internalError(asyncResp->res);
Ed Tanousa8408792018-09-05 16:08:38 -0700506 return;
507 }
508
Ed Tanousa24526d2018-12-10 15:17:59 -0800509 std::optional<std::string> newUserName;
510 std::optional<std::string> password;
511 std::optional<bool> enabled;
512 std::optional<std::string> roleId;
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530513 if (!json_util::readJson(req, res, "UserName", newUserName, "Password",
514 password, "RoleId", roleId, "Enabled",
Ed Tanous9712f8a2018-09-21 13:38:49 -0700515 enabled))
Ed Tanousa8408792018-09-05 16:08:38 -0700516 {
517 return;
518 }
519
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530520 const std::string& username = params[0];
Ed Tanousa8408792018-09-05 16:08:38 -0700521
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530522 if (!newUserName)
523 {
524 // If the username isn't being updated, we can update the properties
525 // directly
526 updateUserProperties(asyncResp, username, password, enabled,
527 roleId);
528 return;
529 }
530 else
531 {
532 crow::connections::systemBus->async_method_call(
533 [this, asyncResp, username, password(std::move(password)),
534 roleId(std::move(roleId)), enabled(std::move(enabled)),
535 newUser{std::string(*newUserName)}](
536 const boost::system::error_code ec) {
537 if (ec)
Ed Tanousa8408792018-09-05 16:08:38 -0700538 {
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530539 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
540 messages::resourceNotFound(
541 asyncResp->res,
542 "#ManagerAccount.v1_0_3.ManagerAccount", username);
543 return;
544 }
545
546 updateUserProperties(asyncResp, newUser, password, enabled,
547 roleId);
548 },
549 "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
550 "xyz.openbmc_project.User.Manager", "RenameUser", username,
551 *newUserName);
552 }
553 }
554
555 void updateUserProperties(std::shared_ptr<AsyncResp> asyncResp,
556 const std::string& username,
Ed Tanousa24526d2018-12-10 15:17:59 -0800557 std::optional<std::string> password,
558 std::optional<bool> enabled,
559 std::optional<std::string> roleId)
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530560 {
561 if (password)
562 {
563 if (!pamUpdatePassword(username, *password))
564 {
565 BMCWEB_LOG_ERROR << "pamUpdatePassword Failed";
566 messages::internalError(asyncResp->res);
567 return;
568 }
569 }
570
571 if (enabled)
572 {
573 crow::connections::systemBus->async_method_call(
574 [asyncResp](const boost::system::error_code ec) {
575 if (ec)
576 {
577 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
Jason M. Billsf12894f2018-10-09 12:45:45 -0700578 messages::internalError(asyncResp->res);
Ed Tanousa8408792018-09-05 16:08:38 -0700579 return;
580 }
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530581 messages::success(asyncResp->res);
582 return;
583 },
584 "xyz.openbmc_project.User.Manager",
585 "/xyz/openbmc_project/user/" + username,
586 "org.freedesktop.DBus.Properties", "Set",
587 "xyz.openbmc_project.User.Attributes", "UserEnabled",
Ed Tanousabf2add2019-01-22 16:40:12 -0800588 std::variant<bool>{*enabled});
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530589 }
Ed Tanous9712f8a2018-09-21 13:38:49 -0700590
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530591 if (roleId)
592 {
593 std::string priv = getRoleIdFromPrivilege(*roleId);
594 if (priv.empty())
595 {
596 messages::propertyValueNotInList(asyncResp->res, *roleId,
597 "RoleId");
598 return;
599 }
600
601 crow::connections::systemBus->async_method_call(
602 [asyncResp](const boost::system::error_code ec) {
603 if (ec)
604 {
605 BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
606 messages::internalError(asyncResp->res);
607 return;
608 }
609 messages::success(asyncResp->res);
610 },
611 "xyz.openbmc_project.User.Manager",
612 "/xyz/openbmc_project/user/" + username,
613 "org.freedesktop.DBus.Properties", "Set",
614 "xyz.openbmc_project.User.Attributes", "UserPrivilege",
Ed Tanousabf2add2019-01-22 16:40:12 -0800615 std::variant<std::string>{priv});
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530616 }
Ed Tanousa8408792018-09-05 16:08:38 -0700617 }
Ed Tanous06e086d2018-09-19 17:19:52 -0700618
619 void doDelete(crow::Response& res, const crow::Request& req,
620 const std::vector<std::string>& params) override
621 {
622 auto asyncResp = std::make_shared<AsyncResp>(res);
623
624 if (params.size() != 1)
625 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700626 messages::internalError(asyncResp->res);
Ed Tanous06e086d2018-09-19 17:19:52 -0700627 return;
628 }
629
630 const std::string userPath = "/xyz/openbmc_project/user/" + params[0];
631
632 crow::connections::systemBus->async_method_call(
633 [asyncResp, username{std::move(params[0])}](
634 const boost::system::error_code ec) {
635 if (ec)
636 {
Jason M. Billsf12894f2018-10-09 12:45:45 -0700637 messages::resourceNotFound(
638 asyncResp->res, "#ManagerAccount.v1_0_3.ManagerAccount",
639 username);
Ed Tanous06e086d2018-09-19 17:19:52 -0700640 return;
641 }
642
Jason M. Billsf12894f2018-10-09 12:45:45 -0700643 messages::accountRemoved(asyncResp->res);
Ed Tanous06e086d2018-09-19 17:19:52 -0700644 },
645 "xyz.openbmc_project.User.Manager", userPath,
646 "xyz.openbmc_project.Object.Delete", "Delete");
647 }
AppaRao Puli84e12cb2018-10-11 01:28:15 +0530648};
Lewanczyk, Dawid88d16c92018-02-02 14:51:09 +0100649
Ed Tanous1abe55e2018-09-05 08:30:59 -0700650} // namespace redfish