Add a unique_key fields to the auth context type for tracking different instances

This will allow us to lookup a cache for the catalog without needing to make a database call
This commit is contained in:
Joseph Schorr 2018-06-19 11:09:58 -04:00
parent 7604e9842b
commit a1c06042c6
2 changed files with 28 additions and 2 deletions

View file

@ -1,8 +1,7 @@
import logging import logging
from cachetools import lru_cache
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from cachetools import lru_cache
from six import add_metaclass from six import add_metaclass
from app import app from app import app
@ -90,6 +89,17 @@ class AuthContext(object):
""" """
pass pass
@property
@abstractmethod
def unique_key(self):
""" Returns a key that is unique to this auth context type and its data. For example, an
instance of the auth context type for the user might be a string of the form
`user-{user-uuid}`. Callers should treat this key as opaque and not rely on the contents
for anything besides uniqueness. This is typically used by callers when they'd like to
check cache but not hit the database to get a fully validated auth context.
"""
pass
class ValidatedAuthContext(AuthContext): class ValidatedAuthContext(AuthContext):
""" ValidatedAuthContext represents the loaded, authenticated and validated auth information """ ValidatedAuthContext represents the loaded, authenticated and validated auth information
@ -213,6 +223,11 @@ class ValidatedAuthContext(AuthContext):
if self.identity: if self.identity:
identity_changed.send(app, identity=self.identity) identity_changed.send(app, identity=self.identity)
@property
def unique_key(self):
signed_dict = self.to_signed_dict()
return '%s-%s' % (signed_dict['entity_kind'], signed_dict.get('entity_reference', '(anon)'))
def to_signed_dict(self): def to_signed_dict(self):
""" Serializes the auth context into a dictionary suitable for inclusion in a JWT or other """ Serializes the auth context into a dictionary suitable for inclusion in a JWT or other
form of signed serialization. form of signed serialization.
@ -274,6 +289,15 @@ class SignedAuthContext(AuthContext):
self.signed_data = signed_data self.signed_data = signed_data
self.v1_dict_format = v1_dict_format self.v1_dict_format = v1_dict_format
@property
def unique_key(self):
if self.v1_dict_format:
# Since V1 data format is verbose, just use the validated version to get the key.
return self._get_validated().unique_key
signed_dict = self.signed_data
return '%s-%s' % (signed_dict['entity_kind'], signed_dict.get('entity_reference', '(anon)'))
@classmethod @classmethod
def build_from_signed_dict(cls, dict_data, v1_dict_format=False): def build_from_signed_dict(cls, dict_data, v1_dict_format=False):
if not v1_dict_format: if not v1_dict_format:

View file

@ -26,6 +26,7 @@ def test_signed_auth_context(kind, entity_reference, loader, v1_dict_format, ini
assert not validated.is_anonymous assert not validated.is_anonymous
assert validated.entity_kind == kind assert validated.entity_kind == kind
assert validated.unique_key
signed = SignedAuthContext.build_from_signed_dict(validated.to_signed_dict(), signed = SignedAuthContext.build_from_signed_dict(validated.to_signed_dict(),
v1_dict_format=v1_dict_format) v1_dict_format=v1_dict_format)
@ -36,6 +37,7 @@ def test_signed_auth_context(kind, entity_reference, loader, v1_dict_format, ini
assert signed.description == validated.description assert signed.description == validated.description
assert signed.credential_username == validated.credential_username assert signed.credential_username == validated.credential_username
assert signed.analytics_id_and_public_metadata() == validated.analytics_id_and_public_metadata() assert signed.analytics_id_and_public_metadata() == validated.analytics_id_and_public_metadata()
assert signed.unique_key == validated.unique_key
assert signed.is_anonymous == validated.is_anonymous assert signed.is_anonymous == validated.is_anonymous
assert signed.authed_user == validated.authed_user assert signed.authed_user == validated.authed_user