Ticket #3067: session.patch
| File session.patch, 13.5 kB (added by jonas, 2 years ago) |
|---|
-
trac/db_default.py
17 17 from trac.db import Table, Column, Index 18 18 19 19 # Database version identifier. Used for automatic upgrades. 20 db_version = 1 720 db_version = 18 21 21 22 22 def __mkreports(reports): 23 23 """Utility function used to create report data in same syntax as the … … 48 48 Column('time', type='int')], 49 49 Table('session', key=('sid', 'authenticated', 'var_name'))[ 50 50 Column('sid'), 51 Column('time', type='int'), 51 52 Column('authenticated', type='int'), 52 53 Column('var_name'), 53 Column('var_value')], 54 Column('var_value'), 55 Index(['sid']), 56 Index(['time']), 57 Index(['authenticated'])], 54 58 55 59 # Attachments 56 60 Table('attachment', key=('type', 'id', 'filename'))[ … … 119 123 Column('field'), 120 124 Column('oldvalue'), 121 125 Column('newvalue'), 122 Index(['ticket', 'time'])], 126 Index(['ticket']), 127 Index(['time'])], 123 128 Table('ticket_custom', key=('ticket', 'name'))[ 124 129 Column('ticket', type='int'), 125 130 Column('name'), -
trac/tests/env.py
27 27 """Testing env.get_known_users""" 28 28 cursor = self.db.cursor() 29 29 cursor.execute("INSERT INTO session " 30 "VALUES ('123',0, 'email','a@example.com')")31 cursor.executemany("INSERT INTO session VALUES (%s, 1,%s,%s)",30 "VALUES ('123',0,0,'email','a@example.com')") 31 cursor.executemany("INSERT INTO session VALUES (%s,0,1,%s,%s)", 32 32 [('tom', 'name', 'Tom'), 33 33 ('tom', 'email', 'tom@example.com'), 34 34 ('joe', 'email', 'joe@example.com'), -
trac/upgrades/db18.py
1 from trac.db import Table, Column, Index, DatabaseManager 2 3 def do_upgrade(env, ver, cursor): 4 cursor.execute("CREATE TEMP TABLE session_old AS SELECT * FROM session") 5 cursor.execute("DROP TABLE session") 6 cursor.execute("CREATE TEMP TABLE ticket_change_old AS SELECT * FROM ticket_change") 7 cursor.execute("DROP TABLE ticket_change") 8 9 # A slightly more denormalized session schema where the 'last_visit' values are 10 # stored in a column for performance reasons 11 session = Table('session', key=('sid', 'authenticated', 'var_name'))[ 12 Column('sid'), 13 Column('time', type='int'), 14 Column('authenticated', type='int'), 15 Column('var_name'), 16 Column('var_value'), 17 Index(['sid']), 18 Index(['time']), 19 Index(['authenticated'])] 20 21 # The old ticket_change table had a composite index on (ticket, time), this however 22 # does not help us when we need to order changes by time (for the timeline). 23 # 24 # Unfortunately this index is called "ticket_change_idx" on old environments 25 # and "ticket_change_ticket_time_idx" on newer ones. This makes it easiest to 26 # simply recreate the entire table. 27 ticket_change = Table('ticket_change', key=('ticket', 'time', 'field'))[ 28 Column('ticket', type='int'), 29 Column('time', type='int'), 30 Column('author'), 31 Column('field'), 32 Column('oldvalue'), 33 Column('newvalue'), 34 Index(['ticket']), 35 Index(['time'])] 36 37 db_connector, _ = DatabaseManager(env)._get_connector() 38 for stmt in db_connector.to_sql(session): 39 cursor.execute(stmt) 40 for stmt in db_connector.to_sql(ticket_change): 41 cursor.execute(stmt) 42 43 # Add an index to the temporary table to speed up the conversion 44 cursor.execute("CREATE INDEX session_old_sid_idx ON session_old(sid)") 45 # Insert the sessions into the new table 46 cursor.execute("INSERT INTO session (sid, time, authenticated, " 47 "var_name, var_value) SELECT " 48 "s.sid, s2.var_value, s.authenticated, s.var_name, s.var_value " 49 "FROM session_old s, session_old s2 " 50 "WHERE s.sid=s2.sid AND s2.var_name='last_visit' AND " 51 "s.var_name <> 'last_visit'") 52 53 # Insert ticket change data into the new table 54 cursor.execute("INSERT INTO ticket_change " 55 "(ticket, time, author, field, oldvalue, newvalue) " 56 "SELECT ticket, time, author, field, oldvalue, newvalue " 57 "FROM ticket_change_old") 58 59 -
trac/web/tests/session.py
65 65 authenticated session when the user logs in. 66 66 """ 67 67 cursor = self.db.cursor() 68 cursor.execute("INSERT INTO session VALUES ('123456', 0, 'foo', 'bar')")68 cursor.execute("INSERT INTO session VALUES ('123456', 0, 0, 'foo', 'bar')") 69 69 70 70 incookie = Cookie() 71 71 incookie['trac_session'] = '123456' … … 103 103 accordingly for an anonymous session. 104 104 """ 105 105 cursor = self.db.cursor() 106 cursor.execute("INSERT INTO session VALUES ('123456', 0, 'foo', 'bar')")106 cursor.execute("INSERT INTO session VALUES ('123456', 0, 0, 'foo', 'bar')") 107 107 108 108 incookie = Cookie() 109 109 incookie['trac_session'] = '123456' … … 123 123 for an anonymous session. 124 124 """ 125 125 cursor = self.db.cursor() 126 cursor.execute("INSERT INTO session VALUES ('123456', 0, 'foo', 'bar')")126 cursor.execute("INSERT INTO session VALUES ('123456', 0, 0, 'foo', 'bar')") 127 127 128 128 incookie = Cookie() 129 129 incookie['trac_session'] = '123456' … … 143 143 """ 144 144 cursor = self.db.cursor() 145 145 cursor.execute("INSERT INTO session " 146 "VALUES ('987654', 0, 'last_visit', %s)",146 "VALUES ('987654', %s, 0, 'foo', 'bar')", 147 147 (time.time() - PURGE_AGE - 3600,)) 148 148 149 149 # We need to modify a different session to trigger the purging … … 169 169 # Make sure the session has data so that it doesn't get dropped 170 170 cursor = self.db.cursor() 171 171 cursor.execute("INSERT INTO session " 172 "VALUES ('123456', 0, 'last_visit', %s)",172 "VALUES ('123456', %s, 0, 'foo', 'bar')", 173 173 (int(now - UPDATE_INTERVAL - 3600),)) 174 174 175 175 incookie = Cookie() … … 177 177 req = Mock(authname='anonymous', base_path='/', incookie=incookie, 178 178 outcookie=Cookie()) 179 179 session = Session(self.env, req) 180 del session['foo'] 180 181 session.save() 181 182 182 183 cursor.execute("SELECT COUNT(*) FROM session WHERE sid='123456' AND " … … 203 204 accordingly for an authenticated session. 204 205 """ 205 206 cursor = self.db.cursor() 206 cursor.execute("INSERT INTO session VALUES ('john', 1, 'foo', 'bar')")207 cursor.execute("INSERT INTO session VALUES ('john', 0, 1, 'foo', 'bar')") 207 208 208 209 req = Mock(authname='john', base_path='/', incookie=Cookie()) 209 210 session = Session(self.env, req) … … 220 221 for an authenticated session. 221 222 """ 222 223 cursor = self.db.cursor() 223 cursor.execute("INSERT INTO session VALUES ('john', 1, 'foo', 'bar')")224 cursor.execute("INSERT INTO session VALUES ('john', 0, 1, 'foo', 'bar')") 224 225 225 226 req = Mock(authname='john', base_path='/', incookie=Cookie()) 226 227 session = Session(self.env, req) … … 240 241 241 242 # Make sure the session has data so that it doesn't get dropped 242 243 cursor = self.db.cursor() 243 cursor.executemany("INSERT INTO session VALUES ('123456', 0, %s, %s)", 244 [('last_visit', int(now - UPDATE_INTERVAL - 3600)), 245 ('foo', 'bar')]) 244 cursor.execute("INSERT INTO session VALUES ('123456', %s, 0, %s, %s)", 245 (int(now - UPDATE_INTERVAL - 3600), 'foo', 'bar')) 246 246 247 247 incookie = Cookie() 248 248 incookie['trac_session'] = '123456' … … 254 254 255 255 self.assertEqual(PURGE_AGE, outcookie['trac_session']['expires']) 256 256 257 cursor.execute("SELECT var_value FROM session WHERE sid='123456' AND "258 "authenticated=0 AND var_name='last_visit'")257 cursor.execute("SELECT time FROM session WHERE sid='123456' AND " 258 "authenticated=0") 259 259 self.assertAlmostEqual(now, int(cursor.fetchone()[0]), -1) 260 260 261 261 -
trac/web/session.py
34 34 self.env = env 35 35 self.req = req 36 36 self.sid = None 37 self.last_visit = 0 37 38 self._old = {} 38 39 if req.authname == 'anonymous': 39 40 if not req.incookie.has_key(COOKIE_KEY): … … 58 59 db = self.env.get_db_cnx() 59 60 cursor = db.cursor() 60 61 self.sid = sid 61 cursor.execute("SELECT var_name,var_value FROM session "62 cursor.execute("SELECT var_name,var_value, time FROM session " 62 63 "WHERE sid=%s AND authenticated=%s", 63 64 (sid, int(authenticated))) 64 for name, value in cursor:65 for name, value, time_ in cursor: 65 66 self[name] = value 67 self.last_visit = int(time_) 66 68 self._old.update(self) 67 69 68 70 # Refresh the session cookie if this is the first visit since over a day 69 if not authenticated and self. has_key('last_visit'):70 if time.time() - int(self['last_visit'])> UPDATE_INTERVAL:71 if not authenticated and self.last_visit: 72 if time.time() - self.last_visit > UPDATE_INTERVAL: 71 73 self.bake_cookie() 74 #self.last_visit = time.time() 72 75 73 76 def change_sid(self, new_sid): 74 77 assert self.req.authname == 'anonymous', \ … … 127 130 # persist it 128 131 return 129 132 130 changed = False131 now = int(time.time())132 133 if self.req.authname == 'anonymous':134 # Update the session last visit time if it is over an hour old,135 # so that session doesn't get purged136 last_visit = int(self.get('last_visit', 0))137 if now - last_visit > UPDATE_INTERVAL:138 self.env.log.info("Refreshing session %s" % self.sid)139 self['last_visit'] = now140 141 # If the only data in the session is the last_visit time, it makes142 # no sense to keep the session around143 if len(self.items()) == 1:144 del self['last_visit']145 146 133 db = self.env.get_db_cnx() 147 134 cursor = db.cursor() 148 135 authenticated = int(self.req.authname != 'anonymous') … … 154 141 self.env.log.debug('Adding variable %s with value "%s" to ' 155 142 'session %s' % (k, v, 156 143 self.sid or self.req.authname)) 157 cursor.execute("INSERT INTO session VALUES(%s,%s,%s,%s)", 158 (self.sid, authenticated, k, v)) 159 changed = True 144 cursor.execute("INSERT INTO session " 145 "(sid,time,authenticated,var_name,var_value) " 146 "VALUES(%s,%s,%s,%s,%s)", 147 (self.sid, self.last_visit, authenticated, k, v)) 160 148 elif v != self._old[k]: 161 149 self.env.log.debug('Changing variable %s from "%s" to "%s" in ' 162 150 'session %s' % (k, self._old[k], v, … … 165 153 "WHERE sid=%s AND authenticated=%s " 166 154 "AND var_name=%s", (v, self.sid, authenticated, 167 155 k)) 168 changed = True169 156 170 157 # Find all variables that have been deleted and also remove them from 171 158 # the database … … 175 162 cursor.execute("DELETE FROM session WHERE sid=%s AND " 176 163 "authenticated=%s AND var_name=%s", 177 164 (self.sid, authenticated, k)) 178 changed = True179 165 180 if changed: 166 now = int(time.time()) 167 # Update the session last visit time if it is over an hour old, 168 # so that session doesn't get purged 169 if now - self.last_visit > UPDATE_INTERVAL: 170 self.last_visit = now 171 self.env.log.info("Refreshing session %s" % self.sid) 172 cursor.execute('UPDATE session SET time=%s WHERE sid=%s', 173 (self.last_visit, self.sid)) 174 181 175 # Purge expired sessions. We do this only when the session was 182 176 # changed as to minimize the purging. 183 177 mintime = now - PURGE_AGE 184 178 self.env.log.debug('Purging old, expired, sessions.') 185 179 cursor.execute("DELETE FROM session WHERE authenticated=0 AND " 186 "sid IN (SELECT sid FROM session WHERE " 187 "var_name='last_visit' AND var_value < %s)", 188 (mintime,)) 189 190 db.commit() 180 "time < %s", (mintime,)) 181 db.commit()
