memstore.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. """A simple store using only in-process memory."""
  2. from openid.store import nonce
  3. import copy
  4. import time
  5. class ServerAssocs(object):
  6. def __init__(self):
  7. self.assocs = {}
  8. def set(self, assoc):
  9. self.assocs[assoc.handle] = assoc
  10. def get(self, handle):
  11. return self.assocs.get(handle)
  12. def remove(self, handle):
  13. try:
  14. del self.assocs[handle]
  15. except KeyError:
  16. return False
  17. else:
  18. return True
  19. def best(self):
  20. """Returns association with the oldest issued date.
  21. or None if there are no associations.
  22. """
  23. best = None
  24. for assoc in self.assocs.values():
  25. if best is None or best.issued < assoc.issued:
  26. best = assoc
  27. return best
  28. def cleanup(self):
  29. """Remove expired associations.
  30. @return: tuple of (removed associations, remaining associations)
  31. """
  32. remove = []
  33. for handle, assoc in self.assocs.iteritems():
  34. if assoc.getExpiresIn() == 0:
  35. remove.append(handle)
  36. for handle in remove:
  37. del self.assocs[handle]
  38. return len(remove), len(self.assocs)
  39. class MemoryStore(object):
  40. """In-process memory store.
  41. Use for single long-running processes. No persistence supplied.
  42. """
  43. def __init__(self):
  44. self.server_assocs = {}
  45. self.nonces = {}
  46. def _getServerAssocs(self, server_url):
  47. try:
  48. return self.server_assocs[server_url]
  49. except KeyError:
  50. assocs = self.server_assocs[server_url] = ServerAssocs()
  51. return assocs
  52. def storeAssociation(self, server_url, assoc):
  53. assocs = self._getServerAssocs(server_url)
  54. assocs.set(copy.deepcopy(assoc))
  55. def getAssociation(self, server_url, handle=None):
  56. assocs = self._getServerAssocs(server_url)
  57. if handle is None:
  58. return assocs.best()
  59. else:
  60. return assocs.get(handle)
  61. def removeAssociation(self, server_url, handle):
  62. assocs = self._getServerAssocs(server_url)
  63. return assocs.remove(handle)
  64. def useNonce(self, server_url, timestamp, salt):
  65. if abs(timestamp - time.time()) > nonce.SKEW:
  66. return False
  67. anonce = (str(server_url), int(timestamp), str(salt))
  68. if anonce in self.nonces:
  69. return False
  70. else:
  71. self.nonces[anonce] = None
  72. return True
  73. def cleanupNonces(self):
  74. now = time.time()
  75. expired = []
  76. for anonce in self.nonces.iterkeys():
  77. if abs(anonce[1] - now) > nonce.SKEW:
  78. # removing items while iterating over the set could be bad.
  79. expired.append(anonce)
  80. for anonce in expired:
  81. del self.nonces[anonce]
  82. return len(expired)
  83. def cleanupAssociations(self):
  84. remove_urls = []
  85. removed_assocs = 0
  86. for server_url, assocs in self.server_assocs.iteritems():
  87. removed, remaining = assocs.cleanup()
  88. removed_assocs += removed
  89. if not remaining:
  90. remove_urls.append(server_url)
  91. # Remove entries from server_assocs that had none remaining.
  92. for server_url in remove_urls:
  93. del self.server_assocs[server_url]
  94. return removed_assocs
  95. def __eq__(self, other):
  96. return ((self.server_assocs == other.server_assocs) and
  97. (self.nonces == other.nonces))
  98. def __ne__(self, other):
  99. return not (self == other)