Add OpenIDStore to store associations and nonces
[cascardo/ipsilon.git] / ipsilon / providers / openid / store.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2014  Ipsilon project Contributors, for licensee see COPYING
4
5 from ipsilon.util.data import Store
6
7 from openid import oidutil
8 from openid.association import Association
9 from openid.store.nonce import SKEW as NonceSKEW
10 from openid.store.interface import OpenIDStore as OpenIDStoreInterface
11
12 from time import time
13
14 class OpenIDStore(Store, OpenIDStoreInterface):
15     def __init__(self, database_url):
16         Store.__init__(self, database_url=database_url)
17
18     def storeAssociation(self, server_url, assoc):
19         iden = '%s-%s' % (server_url, assoc.handle)
20         datum = {'secret': oidutil.toBase64(assoc.secret),
21                  'issued': str(assoc.issued),
22                  'lifetime': str(assoc.lifetime),
23                  'assoc_type': assoc.assoc_type}
24
25         data = {iden: datum}
26         self.save_unique_data('association', data)
27
28     def getAssociation(self, server_url, handle=None):
29         iden = '%s-%s' % (server_url, handle)
30         data = self.get_unique_data('association', iden)
31
32         if len(data) < 1:
33             return None
34
35         datum = data[iden]
36         assoc = Association(handle,
37                             oidutil.fromBase64(datum['secret']),
38                             int(datum['issued']),
39                             int(datum['lifetime']),
40                             datum['assoc_type'])
41
42         if assoc.expiresIn == 0:
43             self.del_unique_data('association', iden)
44             return None
45
46         return assoc
47
48     def removeAssociation(self, server_url, handle):
49         iden = '%s-%s' % (server_url, handle)
50         self.del_unique_data('association', iden)
51
52     def useNonce(self, server_url, timestamp, salt):
53         if abs(timestamp - time()) > NonceSKEW:
54             return False
55
56         iden = '%s-%s-%s' % (server_url, timestamp, salt)
57         data = self.get_unique_data('nonce', iden)
58
59         if len(data) > 0:
60             # This server_url, timestamp, salt combination is already seen
61             return False
62
63         datum = {'timestamp': timestamp}
64         data = {iden: datum}
65         self.save_unique_data('nonce', data)
66
67         return True
68
69     def cleanupNonces(self):
70         nonces = self.get_unique_data('nonce')
71         for iden in nonces:
72             if nonces[iden]['timestamp'] < (time() - NonceSKEW):
73                 self.del_unique_data('nonce', iden)
74
75     def cleanupAssociations(self):
76         assocs = self.get_unique_data('association')
77         for iden in assocs:
78             if ((int(assocs[iden]['issued']) + int(assocs[iden]['lifetime']))
79                     < time()):
80                 self.del_unique_data('association', iden)