diff --git a/keystoneclient/tests/v3/test_users.py b/keystoneclient/tests/v3/test_users.py index 613e6c944..153e27a6f 100644 --- a/keystoneclient/tests/v3/test_users.py +++ b/keystoneclient/tests/v3/test_users.py @@ -197,3 +197,55 @@ class UserTests(utils.TestCase, utils.CrudTests): ref[attr], 'Expected different %s' % attr) self.assertEntityRequestBodyIs(req_ref) + + @httpretty.activate + def test_update_password(self): + old_password = uuid.uuid4().hex + new_password = uuid.uuid4().hex + + self.stub_url(httpretty.POST, + [self.collection_key, self.TEST_USER, 'password']) + self.client.user_id = self.TEST_USER + self.manager.update_password(old_password, new_password) + + exp_req_body = { + 'user': { + 'password': new_password, 'original_password': old_password + } + } + + self.assertEqual('/v3/users/test/password', + httpretty.last_request().path) + self.assertRequestBodyIs(json=exp_req_body) + + def test_update_password_with_bad_inputs(self): + old_password = uuid.uuid4().hex + new_password = uuid.uuid4().hex + + # users can't unset their password + self.assertRaises(exceptions.ValidationError, + self.manager.update_password, + old_password, None) + self.assertRaises(exceptions.ValidationError, + self.manager.update_password, + old_password, '') + + # users can't start with empty passwords + self.assertRaises(exceptions.ValidationError, + self.manager.update_password, + None, new_password) + self.assertRaises(exceptions.ValidationError, + self.manager.update_password, + '', new_password) + + # this wouldn't result in any change anyway + self.assertRaises(exceptions.ValidationError, + self.manager.update_password, + None, None) + self.assertRaises(exceptions.ValidationError, + self.manager.update_password, + '', '') + password = uuid.uuid4().hex + self.assertRaises(exceptions.ValidationError, + self.manager.update_password, + password, password) diff --git a/keystoneclient/v3/users.py b/keystoneclient/v3/users.py index 70f569714..30d947cc5 100644 --- a/keystoneclient/v3/users.py +++ b/keystoneclient/v3/users.py @@ -136,6 +136,23 @@ class UserManager(base.CrudManager): enabled=enabled, **kwargs) + def update_password(self, old_password, new_password): + """Update the password for the user the token belongs to.""" + if not (old_password and new_password): + msg = 'Specify both the current password and a new password' + raise exceptions.ValidationError(msg) + + if old_password == new_password: + msg = 'Old password and new password appear to be identical.' + raise exceptions.ValidationError(msg) + + params = {'user': {'password': new_password, + 'original_password': old_password}} + + base_url = '/users/%s/password' % self.api.user_id + + return self._update(base_url, params, method='POST', management=False) + def add_to_group(self, user, group): self._require_user_and_group(user, group)