Commit | Line | Data |
---|---|---|
c638d827 CR |
1 | #$Id: sessions_rdbms.py,v 1.8 2008-08-18 05:04:01 richard Exp $ |
2 | """This module defines a very basic store that's used by the CGI interface | |
3 | to store session and one-time-key information. | |
4 | ||
5 | Yes, it's called "sessions" - because originally it only defined a session | |
6 | class. It's now also used for One Time Key handling too. | |
7 | """ | |
8 | __docformat__ = 'restructuredtext' | |
9 | ||
10 | import os, time | |
11 | ||
12 | class BasicDatabase: | |
13 | ''' Provide a nice encapsulation of an RDBMS table. | |
14 | ||
15 | Keys are id strings, values are automatically marshalled data. | |
16 | ''' | |
17 | def __init__(self, db): | |
18 | self.db = db | |
19 | self.cursor = self.db.cursor | |
20 | ||
21 | def clear(self): | |
22 | self.cursor.execute('delete from %ss'%self.name) | |
23 | ||
24 | def exists(self, infoid): | |
25 | n = self.name | |
26 | self.cursor.execute('select count(*) from %ss where %s_key=%s'%(n, | |
27 | n, self.db.arg), (infoid,)) | |
28 | return int(self.cursor.fetchone()[0]) | |
29 | ||
30 | _marker = [] | |
31 | def get(self, infoid, value, default=_marker): | |
32 | n = self.name | |
33 | self.cursor.execute('select %s_value from %ss where %s_key=%s'%(n, | |
34 | n, n, self.db.arg), (infoid,)) | |
35 | res = self.cursor.fetchone() | |
36 | if not res: | |
37 | if default != self._marker: | |
38 | return default | |
39 | raise KeyError('No such %s "%s"'%(self.name, infoid)) | |
40 | values = eval(res[0]) | |
41 | return values.get(value, None) | |
42 | ||
43 | def getall(self, infoid): | |
44 | n = self.name | |
45 | self.cursor.execute('select %s_value from %ss where %s_key=%s'%(n, | |
46 | n, n, self.db.arg), (infoid,)) | |
47 | res = self.cursor.fetchone() | |
48 | if not res: | |
49 | raise KeyError('No such %s "%s"'%(self.name, infoid)) | |
50 | return eval(res[0]) | |
51 | ||
52 | def set(self, infoid, **newvalues): | |
53 | c = self.cursor | |
54 | n = self.name | |
55 | a = self.db.arg | |
56 | c.execute('select %s_value from %ss where %s_key=%s'%(n, n, n, a), | |
57 | (infoid,)) | |
58 | res = c.fetchone() | |
59 | if res: | |
60 | values = eval(res[0]) | |
61 | else: | |
62 | values = {} | |
63 | values.update(newvalues) | |
64 | ||
65 | if res: | |
66 | sql = 'update %ss set %s_value=%s where %s_key=%s'%(n, n, | |
67 | a, n, a) | |
68 | args = (repr(values), infoid) | |
69 | else: | |
70 | sql = 'insert into %ss (%s_key, %s_time, %s_value) '\ | |
71 | 'values (%s, %s, %s)'%(n, n, n, n, a, a, a) | |
72 | args = (infoid, time.time(), repr(values)) | |
73 | c.execute(sql, args) | |
74 | ||
75 | def destroy(self, infoid): | |
76 | self.cursor.execute('delete from %ss where %s_key=%s'%(self.name, | |
77 | self.name, self.db.arg), (infoid,)) | |
78 | ||
79 | def updateTimestamp(self, infoid): | |
80 | """ don't update every hit - once a minute should be OK """ | |
81 | now = time.time() | |
82 | self.cursor.execute('''update %ss set %s_time=%s where %s_key=%s | |
83 | and %s_time < %s'''%(self.name, self.name, self.db.arg, | |
84 | self.name, self.db.arg, self.name, self.db.arg), | |
85 | (now, infoid, now-60)) | |
86 | ||
87 | def clean(self): | |
88 | ''' Remove session records that haven't been used for a week. ''' | |
89 | now = time.time() | |
90 | week = 60*60*24*7 | |
91 | old = now - week | |
92 | self.cursor.execute('delete from %ss where %s_time < %s'%(self.name, | |
93 | self.name, self.db.arg), (old, )) | |
94 | ||
95 | class Sessions(BasicDatabase): | |
96 | name = 'session' | |
97 | ||
98 | class OneTimeKeys(BasicDatabase): | |
99 | name = 'otk' | |
100 | ||
101 | # vim: set et sts=4 sw=4 : |