Redfish AccountService service modifications
- Updated code to get "UserPrivilege" from DBUS
- Updated Links->Role in AccountManager.
- Added code for "RenameUser".
- Added code to update Privilege over dbus.
UnitTest:
- Tested All methods(Get,Post,Delete,Patch) on
AccountCollections and ManageAccount over redfish
using postman tool.
Change-Id: Ib9d8713908bad28d8d411f113af0d72d6c0fc40b
Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp
index a93407a..97e5f64 100644
--- a/redfish-core/lib/account_service.hpp
+++ b/redfish-core/lib/account_service.hpp
@@ -26,8 +26,50 @@
using ManagedObjectType = std::vector<std::pair<
sdbusplus::message::object_path,
boost::container::flat_map<
- std::string, boost::container::flat_map<
- std::string, sdbusplus::message::variant<bool>>>>>;
+ std::string,
+ boost::container::flat_map<
+ std::string, sdbusplus::message::variant<bool, std::string>>>>>;
+
+inline std::string getPrivilegeFromRoleId(boost::beast::string_view role)
+{
+ if (role == "priv-admin")
+ {
+ return "Administrator";
+ }
+ else if (role == "priv-callback")
+ {
+ return "Callback";
+ }
+ else if (role == "priv-user")
+ {
+ return "User";
+ }
+ else if (role == "priv-operator")
+ {
+ return "Operator";
+ }
+ return "";
+}
+inline std::string getRoleIdFromPrivilege(boost::beast::string_view role)
+{
+ if (role == "Administrator")
+ {
+ return "priv-admin";
+ }
+ else if (role == "Callback")
+ {
+ return "priv-callback";
+ }
+ else if (role == "User")
+ {
+ return "priv-user";
+ }
+ else if (role == "Operator")
+ {
+ return "priv-operator";
+ }
+ return "";
+}
class AccountService : public Node
{
@@ -148,8 +190,8 @@
return;
}
- const char* priv = getRoleIdFromPrivilege(*roleId);
- if (priv == nullptr)
+ std::string priv = getRoleIdFromPrivilege(*roleId);
+ if (priv.empty())
{
messages::propertyValueNotInList(asyncResp->res, *roleId, "RoleId");
return;
@@ -200,27 +242,6 @@
std::array<const char*, 4>{"ipmi", "redfish", "ssh", "web"},
*roleId, *enabled);
}
-
- static const char* getRoleIdFromPrivilege(boost::beast::string_view role)
- {
- if (role == "Administrator")
- {
- return "priv-admin";
- }
- else if (role == "Callback")
- {
- return "priv-callback";
- }
- else if (role == "User")
- {
- return "priv-user";
- }
- else if (role == "Operator")
- {
- return "priv-operator";
- }
- return nullptr;
- }
};
template <typename Callback>
@@ -232,7 +253,7 @@
crow::connections::systemBus->async_method_call(
[callback{std::move(callback)}](const boost::system::error_code ec,
const GetObjectType& object_names) {
- callback(ec || object_names.size() == 0);
+ callback(!ec && object_names.size() != 0);
},
"xyz.openbmc_project.ObjectMapper",
"/xyz/openbmc_project/object_mapper",
@@ -264,15 +285,10 @@
{"@odata.context",
"/redfish/v1/$metadata#ManagerAccount.ManagerAccount"},
{"@odata.type", "#ManagerAccount.v1_0_3.ManagerAccount"},
-
{"Name", "User Account"},
{"Description", "User Account"},
{"Password", nullptr},
- {"RoleId", "Administrator"},
- {"Links",
- {{"Role",
- {{"@odata.id",
- "/redfish/v1/AccountService/Roles/Administrator"}}}}}};
+ {"RoleId", "Administrator"}};
auto asyncResp = std::make_shared<AsyncResp>(res);
@@ -291,74 +307,96 @@
messages::internalError(asyncResp->res);
return;
}
+ auto userIt = users.begin();
- for (auto& user : users)
+ for (; userIt != users.end(); userIt++)
{
- const std::string& path =
- static_cast<const std::string&>(user.first);
- std::size_t lastIndex = path.rfind("/");
- if (lastIndex == std::string::npos)
+ if (boost::ends_with(userIt->first.str, "/" + accountName))
{
- lastIndex = 0;
+ break;
}
- else
+ }
+ if (userIt == users.end())
+ {
+ messages::resourceNotFound(asyncResp->res, "ManagerAccount",
+ accountName);
+ return;
+ }
+ for (const auto& interface : userIt->second)
+ {
+ if (interface.first ==
+ "xyz.openbmc_project.User.Attributes")
{
- lastIndex += 1;
- }
- if (path.substr(lastIndex) == accountName)
- {
- for (const auto& interface : user.second)
+ for (const auto& property : interface.second)
{
- if (interface.first ==
- "xyz.openbmc_project.User.Attributes")
+ if (property.first == "UserEnabled")
{
- for (const auto& property : interface.second)
+ const bool* userEnabled =
+ sdbusplus::message::variant_ns::get_if<
+ bool>(&property.second);
+ if (userEnabled == nullptr)
{
- if (property.first == "UserEnabled")
- {
- const bool* userEnabled =
- sdbusplus::message::variant_ns::
- get_if<bool>(&property.second);
- if (userEnabled == nullptr)
- {
- BMCWEB_LOG_ERROR
- << "UserEnabled wasn't a bool";
- continue;
- }
- asyncResp->res.jsonValue["Enabled"] =
- *userEnabled;
- }
- else if (property.first ==
- "UserLockedForFailedAttempt")
- {
- const bool* userLocked =
- sdbusplus::message::variant_ns::
- get_if<bool>(&property.second);
- if (userLocked == nullptr)
- {
- BMCWEB_LOG_ERROR
- << "UserEnabled wasn't a bool";
- continue;
- }
- asyncResp->res.jsonValue["Locked"] =
- *userLocked;
- }
+ BMCWEB_LOG_ERROR
+ << "UserEnabled wasn't a bool";
+ messages::internalError(asyncResp->res);
+ return;
}
+ asyncResp->res.jsonValue["Enabled"] =
+ *userEnabled;
+ }
+ else if (property.first ==
+ "UserLockedForFailedAttempt")
+ {
+ const bool* userLocked =
+ sdbusplus::message::variant_ns::get_if<
+ bool>(&property.second);
+ if (userLocked == nullptr)
+ {
+ BMCWEB_LOG_ERROR << "UserLockedForF"
+ "ailedAttempt "
+ "wasn't a bool";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["Locked"] =
+ *userLocked;
+ }
+ else if (property.first == "UserPrivilege")
+ {
+ const std::string* userRolePtr =
+ sdbusplus::message::variant_ns::get_if<
+ std::string>(&property.second);
+ if (userRolePtr == nullptr)
+ {
+ BMCWEB_LOG_ERROR
+ << "UserPrivilege wasn't a "
+ "string";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ std::string priv =
+ getPrivilegeFromRoleId(*userRolePtr);
+ if (priv.empty())
+ {
+ BMCWEB_LOG_ERROR << "Invalid user role";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["RoleId"] = priv;
+
+ asyncResp->res.jsonValue["Links"]["Role"] = {
+ {"@odata.id", "/redfish/v1/AccountService/"
+ "Roles/" +
+ priv}};
}
}
-
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/AccountService/Accounts/" +
- accountName;
- asyncResp->res.jsonValue["Id"] = accountName;
- asyncResp->res.jsonValue["UserName"] = accountName;
-
- return;
}
}
- messages::resourceNotFound(asyncResp->res, "ManagerAccount",
- accountName);
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/AccountService/Accounts/" + accountName;
+ asyncResp->res.jsonValue["Id"] = accountName;
+ asyncResp->res.jsonValue["UserName"] = accountName;
},
"xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
"org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
@@ -374,61 +412,114 @@
return;
}
+ boost::optional<std::string> newUserName;
boost::optional<std::string> password;
boost::optional<bool> enabled;
- if (!json_util::readJson(req, res, "Password", password, "Enabled",
+ boost::optional<std::string> roleId;
+ if (!json_util::readJson(req, res, "UserName", newUserName, "Password",
+ password, "RoleId", roleId, "Enabled",
enabled))
{
return;
}
- // Check the user exists before updating the fields
- checkDbusPathExists(
- "/xyz/openbmc_project/users/" + params[0],
- [username{std::string(params[0])}, password(std::move(password)),
- enabled(std::move(enabled)), asyncResp](bool userExists) {
- if (!userExists)
- {
- messages::resourceNotFound(
- asyncResp->res, "#ManagerAccount.v1_0_3.ManagerAccount",
- username);
- return;
- }
+ const std::string& username = params[0];
- if (password)
- {
- if (!pamUpdatePassword(username, *password))
+ if (!newUserName)
+ {
+ // If the username isn't being updated, we can update the properties
+ // directly
+ updateUserProperties(asyncResp, username, password, enabled,
+ roleId);
+ return;
+ }
+ else
+ {
+ crow::connections::systemBus->async_method_call(
+ [this, asyncResp, username, password(std::move(password)),
+ roleId(std::move(roleId)), enabled(std::move(enabled)),
+ newUser{std::string(*newUserName)}](
+ const boost::system::error_code ec) {
+ if (ec)
{
- BMCWEB_LOG_ERROR << "pamUpdatePassword Failed";
+ BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
+ messages::resourceNotFound(
+ asyncResp->res,
+ "#ManagerAccount.v1_0_3.ManagerAccount", username);
+ return;
+ }
+
+ updateUserProperties(asyncResp, newUser, password, enabled,
+ roleId);
+ },
+ "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
+ "xyz.openbmc_project.User.Manager", "RenameUser", username,
+ *newUserName);
+ }
+ }
+
+ void updateUserProperties(std::shared_ptr<AsyncResp> asyncResp,
+ const std::string& username,
+ boost::optional<std::string> password,
+ boost::optional<bool> enabled,
+ boost::optional<std::string> roleId)
+ {
+ if (password)
+ {
+ if (!pamUpdatePassword(username, *password))
+ {
+ BMCWEB_LOG_ERROR << "pamUpdatePassword Failed";
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ }
+
+ if (enabled)
+ {
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
messages::internalError(asyncResp->res);
return;
}
- }
+ messages::success(asyncResp->res);
+ return;
+ },
+ "xyz.openbmc_project.User.Manager",
+ "/xyz/openbmc_project/user/" + username,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.User.Attributes", "UserEnabled",
+ sdbusplus::message::variant<bool>{*enabled});
+ }
- if (enabled)
- {
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR << "D-Bus responses error: "
- << ec;
- messages::internalError(asyncResp->res);
- return;
- }
- // TODO Consider support polling mechanism to
- // verify status of host and chassis after
- // execute the requested action.
- messages::success(asyncResp->res);
- },
- "xyz.openbmc_project.User.Manager",
- "/xyz/openbmc_project/users/" + username,
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.User.Attributes"
- "UserEnabled",
- sdbusplus::message::variant<bool>{*enabled});
- }
- });
+ if (roleId)
+ {
+ std::string priv = getRoleIdFromPrivilege(*roleId);
+ if (priv.empty())
+ {
+ messages::propertyValueNotInList(asyncResp->res, *roleId,
+ "RoleId");
+ return;
+ }
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ messages::success(asyncResp->res);
+ },
+ "xyz.openbmc_project.User.Manager",
+ "/xyz/openbmc_project/user/" + username,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.User.Attributes", "UserPrivilege",
+ sdbusplus::message::variant<std::string>{priv});
+ }
}
void doDelete(crow::Response& res, const crow::Request& req,
@@ -460,6 +551,6 @@
"xyz.openbmc_project.User.Manager", userPath,
"xyz.openbmc_project.Object.Delete", "Delete");
}
-}; // namespace redfish
+};
} // namespace redfish