Skip to content

Commit 0069ade

Browse files
Mouad BenchchaouiSteve Martinelli
authored andcommitted
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
1 parent 8e12949 commit 0069ade

4 files changed

Lines changed: 84 additions & 3 deletions

File tree

‎openstackclient/common/utils.py‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,12 +233,15 @@ def get_effective_log_level():
233233
return min_log_lvl
234234

235235

236-
def get_password(stdin):
236+
def get_password(stdin, prompt=None, confirm=True):
237+
message = prompt or "User Password:"
237238
if hasattr(stdin, 'isatty') and stdin.isatty():
238239
try:
239240
while True:
240-
first_pass = getpass.getpass("User password: ")
241-
second_pass = getpass.getpass("Repeat user password: ")
241+
first_pass = getpass.getpass(message)
242+
if not confirm:
243+
return first_pass
244+
second_pass = getpass.getpass("Repeat " + message)
242245
if first_pass == second_pass:
243246
return first_pass
244247
print("The passwords entered were not the same")

‎openstackclient/identity/v3/user.py‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,35 @@ def take_action(self, parsed_args):
323323
return
324324

325325

326+
class SetPasswordUser(command.Command):
327+
"""Change current user password"""
328+
329+
log = logging.getLogger(__name__ + '.SetPasswordUser')
330+
331+
def get_parser(self, prog_name):
332+
parser = super(SetPasswordUser, self).get_parser(prog_name)
333+
parser.add_argument(
334+
'--password',
335+
metavar='<new-password>',
336+
help='New user password'
337+
)
338+
return parser
339+
340+
def take_action(self, parsed_args):
341+
self.log.debug('take_action(%s)', parsed_args)
342+
identity_client = self.app.client_manager.identity
343+
344+
current_password = utils.get_password(
345+
self.app.stdin, prompt="Current Password:", confirm=False)
346+
347+
password = parsed_args.password
348+
if password is None:
349+
password = utils.get_password(
350+
self.app.stdin, prompt="New Password:")
351+
352+
identity_client.users.update_password(current_password, password)
353+
354+
326355
class ShowUser(show.ShowOne):
327356
"""Show user details"""
328357

‎openstackclient/tests/identity/v3/test_user.py‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
# under the License.
1414
#
1515

16+
import contextlib
1617
import copy
18+
1719
import mock
1820

1921
from openstackclient.identity.v3 import user
@@ -944,6 +946,52 @@ def test_user_set_disable(self):
944946
)
945947

946948

949+
class TestUserSetPassword(TestUser):
950+
951+
def setUp(self):
952+
super(TestUserSetPassword, self).setUp()
953+
self.cmd = user.SetPasswordUser(self.app, None)
954+
955+
@staticmethod
956+
@contextlib.contextmanager
957+
def _mock_get_password(*passwords):
958+
mocker = mock.Mock(side_effect=passwords)
959+
with mock.patch("openstackclient.common.utils.get_password", mocker):
960+
yield
961+
962+
def test_user_password_change(self):
963+
current_pass = 'old_pass'
964+
new_pass = 'new_pass'
965+
arglist = [
966+
'--password', new_pass,
967+
]
968+
verifylist = [
969+
('password', new_pass),
970+
]
971+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
972+
973+
# Mock getting user current password.
974+
with self._mock_get_password(current_pass):
975+
self.cmd.take_action(parsed_args)
976+
977+
self.users_mock.update_password.assert_called_with(
978+
current_pass, new_pass
979+
)
980+
981+
def test_user_create_password_prompt(self):
982+
current_pass = 'old_pass'
983+
new_pass = 'new_pass'
984+
parsed_args = self.check_parser(self.cmd, [], [])
985+
986+
# Mock getting user current and new password.
987+
with self._mock_get_password(current_pass, new_pass):
988+
self.cmd.take_action(parsed_args)
989+
990+
self.users_mock.update_password.assert_called_with(
991+
current_pass, new_pass
992+
)
993+
994+
947995
class TestUserShow(TestUser):
948996

949997
def setUp(self):

‎setup.cfg‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ openstack.identity.v3 =
242242
user_delete = openstackclient.identity.v3.user:DeleteUser
243243
user_list = openstackclient.identity.v3.user:ListUser
244244
user_set = openstackclient.identity.v3.user:SetUser
245+
user_password_set = openstackclient.identity.v3.user:SetPasswordUser
245246
user_show = openstackclient.identity.v3.user:ShowUser
246247

247248
openstack.image.v1 =

0 commit comments

Comments
 (0)