Add action 'user password set' for identiy v3
This new action will allow a user to change their own password by either providing the new password as an argument (--password) or by being prompted to enter the new password. In both cases user will be prompted to enter their current password as required by the v3 API. Closes-Bug: #1337245 Change-Id: I5e1e0fd2b46a4502318da57f7cce2b236fb2d93d
This commit is contained in:
parent
8e12949958
commit
0069adef5c
@ -233,12 +233,15 @@ def get_effective_log_level():
|
|||||||
return min_log_lvl
|
return min_log_lvl
|
||||||
|
|
||||||
|
|
||||||
def get_password(stdin):
|
def get_password(stdin, prompt=None, confirm=True):
|
||||||
|
message = prompt or "User Password:"
|
||||||
if hasattr(stdin, 'isatty') and stdin.isatty():
|
if hasattr(stdin, 'isatty') and stdin.isatty():
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
first_pass = getpass.getpass("User password: ")
|
first_pass = getpass.getpass(message)
|
||||||
second_pass = getpass.getpass("Repeat user password: ")
|
if not confirm:
|
||||||
|
return first_pass
|
||||||
|
second_pass = getpass.getpass("Repeat " + message)
|
||||||
if first_pass == second_pass:
|
if first_pass == second_pass:
|
||||||
return first_pass
|
return first_pass
|
||||||
print("The passwords entered were not the same")
|
print("The passwords entered were not the same")
|
||||||
|
@ -323,6 +323,35 @@ class SetUser(command.Command):
|
|||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
class SetPasswordUser(command.Command):
|
||||||
|
"""Change current user password"""
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + '.SetPasswordUser')
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(SetPasswordUser, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'--password',
|
||||||
|
metavar='<new-password>',
|
||||||
|
help='New user password'
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug('take_action(%s)', parsed_args)
|
||||||
|
identity_client = self.app.client_manager.identity
|
||||||
|
|
||||||
|
current_password = utils.get_password(
|
||||||
|
self.app.stdin, prompt="Current Password:", confirm=False)
|
||||||
|
|
||||||
|
password = parsed_args.password
|
||||||
|
if password is None:
|
||||||
|
password = utils.get_password(
|
||||||
|
self.app.stdin, prompt="New Password:")
|
||||||
|
|
||||||
|
identity_client.users.update_password(current_password, password)
|
||||||
|
|
||||||
|
|
||||||
class ShowUser(show.ShowOne):
|
class ShowUser(show.ShowOne):
|
||||||
"""Show user details"""
|
"""Show user details"""
|
||||||
|
|
||||||
|
@ -13,7 +13,9 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import contextlib
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from openstackclient.identity.v3 import user
|
from openstackclient.identity.v3 import user
|
||||||
@ -944,6 +946,52 @@ class TestUserSet(TestUser):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestUserSetPassword(TestUser):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestUserSetPassword, self).setUp()
|
||||||
|
self.cmd = user.SetPasswordUser(self.app, None)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def _mock_get_password(*passwords):
|
||||||
|
mocker = mock.Mock(side_effect=passwords)
|
||||||
|
with mock.patch("openstackclient.common.utils.get_password", mocker):
|
||||||
|
yield
|
||||||
|
|
||||||
|
def test_user_password_change(self):
|
||||||
|
current_pass = 'old_pass'
|
||||||
|
new_pass = 'new_pass'
|
||||||
|
arglist = [
|
||||||
|
'--password', new_pass,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('password', new_pass),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
# Mock getting user current password.
|
||||||
|
with self._mock_get_password(current_pass):
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.users_mock.update_password.assert_called_with(
|
||||||
|
current_pass, new_pass
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_user_create_password_prompt(self):
|
||||||
|
current_pass = 'old_pass'
|
||||||
|
new_pass = 'new_pass'
|
||||||
|
parsed_args = self.check_parser(self.cmd, [], [])
|
||||||
|
|
||||||
|
# Mock getting user current and new password.
|
||||||
|
with self._mock_get_password(current_pass, new_pass):
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.users_mock.update_password.assert_called_with(
|
||||||
|
current_pass, new_pass
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestUserShow(TestUser):
|
class TestUserShow(TestUser):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -242,6 +242,7 @@ openstack.identity.v3 =
|
|||||||
user_delete = openstackclient.identity.v3.user:DeleteUser
|
user_delete = openstackclient.identity.v3.user:DeleteUser
|
||||||
user_list = openstackclient.identity.v3.user:ListUser
|
user_list = openstackclient.identity.v3.user:ListUser
|
||||||
user_set = openstackclient.identity.v3.user:SetUser
|
user_set = openstackclient.identity.v3.user:SetUser
|
||||||
|
user_password_set = openstackclient.identity.v3.user:SetPasswordUser
|
||||||
user_show = openstackclient.identity.v3.user:ShowUser
|
user_show = openstackclient.identity.v3.user:ShowUser
|
||||||
|
|
||||||
openstack.image.v1 =
|
openstack.image.v1 =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user