"""A openid store using django cache""" from openid.store.interface import OpenIDStore from openid.store import nonce from django.core.cache import cache import logging import time DEFAULT_ASSOCIATIONS_TIMEOUT = 60 DEFAULT_NONCE_TIMEOUT = 600 ASSOCIATIONS_KEY_PREFIX = 'openid.provider.associations.' NONCE_KEY_PREFIX = 'openid.provider.nonce.' log = logging.getLogger('DjangoOpenIDStore') def get_url_key(server_url): key = ASSOCIATIONS_KEY_PREFIX + server_url return key def get_nonce_key(server_url, timestamp, salt): key = '{prefix}{url}.{ts}.{salt}'.format(prefix=NONCE_KEY_PREFIX, url=server_url, ts=timestamp, salt=salt) return key class DjangoOpenIDStore(OpenIDStore): def __init__(self): log.info('DjangoStore cache:' + str(cache.__class__)) def storeAssociation(self, server_url, assoc): key = get_url_key(server_url) log.info('storeAssociation {0}'.format(key)) associations = cache.get(key, {}) associations[assoc.handle] = assoc cache.set(key, associations, DEFAULT_ASSOCIATIONS_TIMEOUT) def getAssociation(self, server_url, handle=None): key = get_url_key(server_url) log.info('getAssociation {0}'.format(key)) associations = cache.get(key, {}) assoc = None if handle is None: # get best association valid_assocs = [a for a in associations if a.getExpiresIn() > 0] if valid_assocs: valid_assocs.sort(lambda a: a.getExpiresIn(), reverse=True) assoc = valid_assocs.sort[0] else: assoc = associations.get(handle) # check expiration and remove if it has expired if assoc and assoc.getExpiresIn() <= 0: if handle is None: cache.delete(key) else: associations.pop(handle) cache.set(key, associations, DEFAULT_ASSOCIATIONS_TIMEOUT) assoc = None return assoc def removeAssociation(self, server_url, handle): key = get_url_key(server_url) log.info('removeAssociation {0}'.format(key)) associations = cache.get(key, {}) removed = False if associations: if handle is None: cache.delete(key) removed = True else: assoc = associations.pop(handle, None) if assoc: cache.set(key, associations, DEFAULT_ASSOCIATIONS_TIMEOUT) removed = True return removed def useNonce(self, server_url, timestamp, salt): key = get_nonce_key(server_url, timestamp, salt) log.info('useNonce {0}'.format(key)) if abs(timestamp - time.time()) > nonce.SKEW: return False anonce = cache.get(key) found = False if anonce is None: cache.set(key, '-', DEFAULT_NONCE_TIMEOUT) found = False else: found = True return found def cleanupNonces(self): # not necesary, keys will timeout return 0 def cleanupAssociations(self): # not necesary, keys will timeout return 0