From 588aaa3eaac302a1d8f60cce77103e9ac682fae8 Mon Sep 17 00:00:00 2001 From: Jamie Lennox Date: Wed, 18 Jun 2014 11:19:36 +1000 Subject: [PATCH] Add issued handlers to auth_ref and fixtures issued_at is a standard part of V2 and V3 tokens so add it to AccessInfo in a similar way to expiry. Also it should be included when generating tokens so include it in fixtures. Change-Id: I0d62d8ce6472466886751e10e98046b8e398e079 --- keystoneclient/access.py | 16 ++++++++++++ keystoneclient/fixture/v2.py | 30 ++++++++++++++++++++--- keystoneclient/fixture/v3.py | 31 +++++++++++++++++++++--- keystoneclient/tests/v2_0/test_access.py | 1 + keystoneclient/tests/v3/test_access.py | 5 ++++ 5 files changed, 77 insertions(+), 6 deletions(-) diff --git a/keystoneclient/access.py b/keystoneclient/access.py index 3ef4d72cb..8e123a3eb 100644 --- a/keystoneclient/access.py +++ b/keystoneclient/access.py @@ -120,6 +120,14 @@ class AccessInfo(dict): """ raise NotImplementedError() + @property + def issued(self): + """Returns the token issue time (as datetime object) + + :returns: datetime + """ + raise NotImplementedError() + @property def username(self): """Returns the username associated with the authentication request. @@ -363,6 +371,10 @@ class AccessInfoV2(AccessInfo): def expires(self): return timeutils.parse_isotime(self['token']['expires']) + @property + def issued(self): + return timeutils.parse_isotime(self['token']['issued_at']) + @property def username(self): return self['user'].get('name', self['user'].get('username')) @@ -529,6 +541,10 @@ class AccessInfoV3(AccessInfo): def expires(self): return timeutils.parse_isotime(self['expires_at']) + @property + def issued(self): + return timeutils.parse_isotime(self['issued_at']) + @property def user_id(self): return self['user']['id'] diff --git a/keystoneclient/fixture/v2.py b/keystoneclient/fixture/v2.py index 871410302..76cd1b816 100644 --- a/keystoneclient/fixture/v2.py +++ b/keystoneclient/fixture/v2.py @@ -40,8 +40,8 @@ class Token(dict): that matter to them and not copy and paste sample. """ - def __init__(self, token_id=None, - expires=None, tenant_id=None, tenant_name=None, user_id=None, + def __init__(self, token_id=None, expires=None, issued=None, + tenant_id=None, tenant_name=None, user_id=None, user_name=None): super(Token, self).__init__() @@ -49,8 +49,16 @@ class Token(dict): self.user_id = user_id or uuid.uuid4().hex self.user_name = user_name or uuid.uuid4().hex + if not issued: + issued = timeutils.utcnow() - datetime.timedelta(minutes=2) if not expires: - expires = timeutils.utcnow() + datetime.timedelta(hours=1) + expires = issued + datetime.timedelta(hours=1) + + try: + self.issued = issued + except (TypeError, AttributeError): + # issued should be able to be passed as a string so ignore + self.issued_str = issued try: self.expires = expires @@ -93,6 +101,22 @@ class Token(dict): def expires(self, value): self.expires_str = timeutils.isotime(value) + @property + def issued_str(self): + return self._token['issued_at'] + + @issued_str.setter + def issued_str(self, value): + self._token['issued_at'] = value + + @property + def issued(self): + return timeutils.parse_isotime(self.issued_str) + + @issued.setter + def issued(self, value): + self.issued_str = timeutils.isotime(value) + @property def _user(self): return self.root.setdefault('user', {}) diff --git a/keystoneclient/fixture/v3.py b/keystoneclient/fixture/v3.py index 7522f13f5..a0896f067 100644 --- a/keystoneclient/fixture/v3.py +++ b/keystoneclient/fixture/v3.py @@ -54,7 +54,7 @@ class Token(dict): that matter to them and not copy and paste sample. """ - def __init__(self, expires=None, user_id=None, user_name=None, + def __init__(self, expires=None, issued=None, user_id=None, user_name=None, user_domain_id=None, user_domain_name=None, methods=None, project_id=None, project_name=None, project_domain_id=None, project_domain_name=None, domain_id=None, domain_name=None, @@ -71,8 +71,17 @@ class Token(dict): methods = ['password'] self.methods.extend(methods) + if not issued: + issued = timeutils.utcnow() - datetime.timedelta(minutes=2) + + try: + self.issued = issued + except (TypeError, AttributeError): + # issued should be able to be passed as a string so ignore + self.issued_str = issued + if not expires: - expires = timeutils.utcnow() + datetime.timedelta(hours=1) + expires = self.issued + datetime.timedelta(hours=1) try: self.expires = expires @@ -115,7 +124,23 @@ class Token(dict): @expires.setter def expires(self, value): - self.expires_str = timeutils.isotime(value) + self.expires_str = timeutils.isotime(value, subsecond=True) + + @property + def issued_str(self): + return self.root.get('issued_at') + + @issued_str.setter + def issued_str(self, value): + self.root['issued_at'] = value + + @property + def issued(self): + return timeutils.parse_isotime(self.issued_str) + + @issued.setter + def issued(self, value): + self.issued_str = timeutils.isotime(value, subsecond=True) @property def _user(self): diff --git a/keystoneclient/tests/v2_0/test_access.py b/keystoneclient/tests/v2_0/test_access.py index 862bf5a5a..1627186d6 100644 --- a/keystoneclient/tests/v2_0/test_access.py +++ b/keystoneclient/tests/v2_0/test_access.py @@ -58,6 +58,7 @@ class AccessInfoTest(utils.TestCase, testresources.ResourcedTestCase): self.assertEqual(auth_ref.user_domain_name, 'Default') self.assertEqual(auth_ref.expires, token.expires) + self.assertEqual(auth_ref.issued, token.issued) def test_will_expire_soon(self): token = client_fixtures.unscoped_token() diff --git a/keystoneclient/tests/v3/test_access.py b/keystoneclient/tests/v3/test_access.py index 938a4b639..6dc5a70d5 100644 --- a/keystoneclient/tests/v3/test_access.py +++ b/keystoneclient/tests/v3/test_access.py @@ -61,6 +61,11 @@ class AccessInfoTest(utils.TestCase): self.assertEqual(auth_ref.expires, timeutils.parse_isotime( UNSCOPED_TOKEN['token']['expires_at'])) + self.assertEqual(auth_ref.issued, timeutils.parse_isotime( + UNSCOPED_TOKEN['token']['issued_at'])) + + self.assertEqual(auth_ref.expires, UNSCOPED_TOKEN.expires) + self.assertEqual(auth_ref.issued, UNSCOPED_TOKEN.issued) def test_will_expire_soon(self): expires = timeutils.utcnow() + datetime.timedelta(minutes=5)