Redfish: Add the PATCH support for user locked property.
With this commit PATCH operation on the Locked property of
ManagerAccount schema would allow the user/admin to unlock
an account,however admin would not be allowed to lock an
account as account can be locked automatically by configured
consecutive authentication failures.
TestedBy: Run the following patch request to test the locked property.
GET https://${BMC_IP}/redfish/v1/AccountService/Accounts/esalinux0
{
"@odata.context": "/redfish/v1/$metadata#ManagerAccount.ManagerAccount",
"@odata.id": "/redfish/v1/AccountService/Accounts/esalinux0",
"@odata.type": "#ManagerAccount.v1_0_3.ManagerAccount",
"Description": "User Account",
"Enabled": true,
"Id": "esalinux0",
"Links": {
"Role": {
"@odata.id": "/redfish/v1/AccountService/Roles/Administrator"
}
},
"Locked": true,
"Locked@Redfish.AllowableValues": [
false
],
"Name": "User Account",
"Password": null,
"RoleId": "Administrator",
"UserName": "esalinux0"
}
PATCH https://${BMC_IP}/redfish/v1/AccountService/Accounts/esalinux0 -d '{"Locked" : false}'
{
"@Message.ExtendedInfo": [
{
"@odata.type": "/redfish/v1/$metadata#Message.v1_0_0.Message",
"Message": "Successfully Completed Request",
"MessageArgs": [],
"MessageId": "Base.1.4.0.Success",
"Resolution": "None",
"Severity": "OK"
}
]
}
Change-Id: I5d7a3d8f6330bbf01292ed4079542a1c65c9cc35
Signed-off-by: Ratan Gupta <ratagupt@linux.vnet.ibm.com>
diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp
index d9388cf..f698901 100644
--- a/redfish-core/lib/account_service.hpp
+++ b/redfish-core/lib/account_service.hpp
@@ -16,6 +16,7 @@
#pragma once
#include "node.hpp"
+#include <dbus_utility.hpp>
#include <error_messages.hpp>
#include <openbmc_dbus_rest.hpp>
#include <utils/json_utils.hpp>
@@ -455,6 +456,9 @@
}
asyncResp->res.jsonValue["Locked"] =
*userLocked;
+ asyncResp->res.jsonValue
+ ["Locked@Redfish.AllowableValues"] = {
+ false};
}
else if (property.first == "UserPrivilege")
{
@@ -510,9 +514,10 @@
std::optional<std::string> password;
std::optional<bool> enabled;
std::optional<std::string> roleId;
+ std::optional<bool> locked;
if (!json_util::readJson(req, res, "UserName", newUserName, "Password",
- password, "RoleId", roleId, "Enabled",
- enabled))
+ password, "RoleId", roleId, "Enabled", enabled,
+ "Locked", locked))
{
return;
}
@@ -523,8 +528,8 @@
{
// If the username isn't being updated, we can update the properties
// directly
- updateUserProperties(asyncResp, username, password, enabled,
- roleId);
+ updateUserProperties(asyncResp, username, password, enabled, roleId,
+ locked);
return;
}
else
@@ -532,7 +537,7 @@
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)}](
+ newUser{std::string(*newUserName)}, locked(std::move(locked))](
const boost::system::error_code ec) {
if (ec)
{
@@ -544,7 +549,7 @@
}
updateUserProperties(asyncResp, newUser, password, enabled,
- roleId);
+ roleId, locked);
},
"xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
"xyz.openbmc_project.User.Manager", "RenameUser", username,
@@ -556,7 +561,8 @@
const std::string& username,
std::optional<std::string> password,
std::optional<bool> enabled,
- std::optional<std::string> roleId)
+ std::optional<std::string> roleId,
+ std::optional<bool> locked)
{
if (password)
{
@@ -568,52 +574,101 @@
}
}
- 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);
+ std::string dbusObjectPath = "/xyz/openbmc_project/user/" + username;
+ dbus::utility::escapePathForDbus(dbusObjectPath);
+
+ checkDbusPathExists(
+ dbusObjectPath,
+ [dbusObjectPath(std::move(dbusObjectPath)), username,
+ password(std::move(password)), roleId(std::move(roleId)),
+ enabled(std::move(enabled)), locked(std::move(locked)),
+ asyncResp{std::move(asyncResp)}](int rc) {
+ if (!rc)
+ {
+ messages::invalidObject(asyncResp->res, username.c_str());
return;
- },
- "xyz.openbmc_project.User.Manager",
- "/xyz/openbmc_project/user/" + username,
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.User.Attributes", "UserEnabled",
- std::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;
+ }
+ messages::success(asyncResp->res);
+ return;
+ },
+ "xyz.openbmc_project.User.Manager",
+ dbusObjectPath.c_str(),
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.User.Attributes", "UserEnabled",
+ std::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)
+ if (roleId)
+ {
+ std::string priv = getRoleIdFromPrivilege(*roleId);
+ if (priv.empty())
{
- BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
- messages::internalError(asyncResp->res);
+ messages::propertyValueNotInList(asyncResp->res,
+ *roleId, "RoleId");
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",
- std::variant<std::string>{priv});
- }
+
+ 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",
+ dbusObjectPath.c_str(),
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.User.Attributes", "UserPrivilege",
+ std::variant<std::string>{priv});
+ }
+
+ if (locked)
+ {
+ // admin can unlock the account which is locked by
+ // successive authentication failures but admin should not
+ // be allowed to lock an account.
+ if (*locked)
+ {
+ messages::propertyValueNotInList(asyncResp->res, "true",
+ "Locked");
+ 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);
+ return;
+ },
+ "xyz.openbmc_project.User.Manager",
+ dbusObjectPath.c_str(),
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.User.Attributes",
+ "UserLockedForFailedAttempt",
+ sdbusplus::message::variant<bool>{*locked});
+ }
+ });
}
void doDelete(crow::Response& res, const crow::Request& req,