diff --git a/keystoneclient/tests/v2_0/test_tokens.py b/keystoneclient/tests/v2_0/test_tokens.py index 335127390..f1a3b3493 100644 --- a/keystoneclient/tests/v2_0/test_tokens.py +++ b/keystoneclient/tests/v2_0/test_tokens.py @@ -12,6 +12,8 @@ import uuid +from keystoneclient import access +from keystoneclient import exceptions from keystoneclient import fixture from keystoneclient.tests.v2_0 import utils from keystoneclient.v2_0 import client @@ -161,6 +163,43 @@ class TokenTests(utils.TestCase): self.assertEqual(token_fixture.token_id, token_ref.id) self.assertEqual(token_fixture.expires_str, token_ref.expires) + def test_validate_token(self): + id_ = uuid.uuid4().hex + token_fixture = fixture.V2Token(token_id=id_) + self.stub_url('GET', ['tokens', id_], json=token_fixture) + + token_ref = self.client.tokens.validate(id_) + self.assertIsInstance(token_ref, tokens.Token) + self.assertEqual(id_, token_ref.id) + + def test_validate_token_invalid_token(self): + # If the token is invalid, typically a NotFound is raised. + + id_ = uuid.uuid4().hex + # The server is expected to return 404 if the token is invalid. + self.stub_url('GET', ['tokens', id_], status_code=404) + self.assertRaises(exceptions.NotFound, + self.client.tokens.validate, id_) + + def test_validate_token_access_info_with_token_id(self): + # Can validate a token passing a string token ID. + token_id = uuid.uuid4().hex + token_fixture = fixture.V2Token(token_id=token_id) + self.stub_url('GET', ['tokens', token_id], json=token_fixture) + access_info = self.client.tokens.validate_access_info(token_id) + self.assertIsInstance(access_info, access.AccessInfoV2) + self.assertEqual(token_id, access_info.auth_token) + + def test_validate_token_access_info_with_access_info(self): + # Can validate a token passing an access info. + token_id = uuid.uuid4().hex + token_fixture = fixture.V2Token(token_id=token_id) + self.stub_url('GET', ['tokens', token_id], json=token_fixture) + token = access.AccessInfo.factory(body=token_fixture) + access_info = self.client.tokens.validate_access_info(token) + self.assertIsInstance(access_info, access.AccessInfoV2) + self.assertEqual(token_id, access_info.auth_token) + def test_get_revoked(self): sample_revoked_response = {'signed': '-----BEGIN CMS-----\nMIIB...'} self.stub_url('GET', ['tokens', 'revoked'], diff --git a/keystoneclient/v2_0/tokens.py b/keystoneclient/v2_0/tokens.py index ed1c07e33..670d65b1c 100644 --- a/keystoneclient/v2_0/tokens.py +++ b/keystoneclient/v2_0/tokens.py @@ -10,6 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. +from keystoneclient import access from keystoneclient import auth from keystoneclient import base from keystoneclient import exceptions @@ -73,6 +74,37 @@ class TokenManager(base.Manager): def endpoints(self, token): return self._get("/tokens/%s/endpoints" % base.getid(token), "token") + def validate(self, token): + """Validate a token. + + :param token: Token to be validated. + + :rtype: :py:class:`.Token` + + """ + return self._get('/tokens/%s' % base.getid(token), 'access') + + def validate_access_info(self, token): + """Validate a token. + + :param token: Token to be validated. This can be an instance of + :py:class:`keystoneclient.access.AccessInfo` or a string + token_id. + + :rtype: :py:class:`keystoneclient.access.AccessInfoV2` + + """ + + def calc_id(token): + if isinstance(token, access.AccessInfo): + return token.auth_token + return base.getid(token) + + url = '/tokens/%s' % calc_id(token) + resp, body = self.client.get(url) + access_info = access.AccessInfo.factory(resp=resp, body=body) + return access_info + def get_revoked(self): """Returns the revoked tokens response.