From abb0fca807eb6e8fcc403eb4dca1873af386f174 Mon Sep 17 00:00:00 2001 From: Bayle Shanks Date: Sun, 30 Jan 2011 17:22:49 -0800 Subject: [PATCH] added memcachedstore (memcached store)w --- openid/store/__init__.py | 4 +- openid/store/memcachedstore.py | 73 ++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) create mode 100755 openid/store/memcachedstore.py diff --git a/openid/store/__init__.py b/openid/store/__init__.py index 76509b51..87ab6b12 100644 --- a/openid/store/__init__.py +++ b/openid/store/__init__.py @@ -2,7 +2,7 @@ This package contains the modules related to this library's use of persistent storage. -@sort: interface, filestore, sqlstore, memstore +@sort: interface, filestore, sqlstore, memstore, memcachedstore """ -__all__ = ['interface', 'filestore', 'sqlstore', 'memstore', 'nonce'] +__all__ = ['interface', 'filestore', 'sqlstore', 'memstore', 'nonce', 'memcachedstore'] diff --git a/openid/store/memcachedstore.py b/openid/store/memcachedstore.py new file mode 100755 index 00000000..2b98b9e3 --- /dev/null +++ b/openid/store/memcachedstore.py @@ -0,0 +1,73 @@ +"""Store using memcached.""" + +import logging +log = logging.getLogger(__name__) + +try: + import memcache +except ImportError: + # fall back for Google App Engine -- hasnt been tested though + from google.appengine.api import memcache + +from openid.store import nonce +import time + +# mostly ported from https://github.com/openid/ruby-openid/blob/master/lib/openid/store/memcache.rb , but i made some small changes, so there may be bugs. NOT TESTED MUCH + + + + +class MemcachedStore(object): + """In-process memory store. + + Use for single long-running processes. No persistence supplied. + """ + def __init__(self, key_prefix= 'openid-store'): + self.key_prefix = key_prefix + + def _serverKey(self, server_url): + return self.key_prefix + 'S' + server_url + + def _assocKey(self, server_url, assoc_handle): + return self.key_prefix + 'A' + server_url + '|' + assoc_handle + + def _nonceKey(self, server_url, timestamp, salt): + return self.key_prefix + 'N' + str(server_url) + '|' + str(timestamp) + '|' + str(salt) + + def storeAssociation(self, server_url, assoc): + memcache.set(self._serverKey(server_url), assoc, assoc.lifetime) + memcache.set(self._assocKey(server_url, assoc.handle), assoc, assoc.lifetime) + + + def getAssociation(self, server_url, handle=None): + if handle is None: + return memcache.get(self._serverKey(server_url)) + else: + return memcache.get(self._assocKey(server_url, handle)) + + def removeAssociation(self, server_url, handle): + deleted = memcache.delete(self._assocKey(server_url, handle)) + serverAssoc = memcache.get(self._serverKey(server_url)) + if serverAssoc and serverAssoc.handle == handle: + deleted = memcache.delete(self._serverKey(server_url)) or deleted + return deleted + + def useNonce(self, server_url, timestamp, salt): + if abs(timestamp - time.time()) > nonce.SKEW: + return False + + key = self._nonceKey(server_url, timestamp, salt) + + result = memcache.get(key) + if (result == None): + return memcache.set(key, True, nonce.SKEW + 5) + else: + return False + + + def cleanupNonces(self): + pass + + def cleanupAssociations(self): + pass +