
details: http://www.bx.psu.edu/hg/galaxy/rev/7ae75e6d9d6a changeset: 1600:7ae75e6d9d6a user: Greg Von Kuster <greg@bx.psu.edu> date: Mon Nov 03 15:31:38 2008 -0500 description: Integrate "session_create_speed" and "faster_random" patches from James. 8 file(s) affected in this change: lib/galaxy/model/mapping.py lib/galaxy/tools/actions/__init__.py lib/galaxy/web/controllers/root.py lib/galaxy/web/controllers/tool_runner.py lib/galaxy/web/controllers/user.py lib/galaxy/web/framework/__init__.py lib/galaxy/web/security/__init__.py templates/root/history.mako diffs (650 lines): diff -r 13cbdd1bbd19 -r 7ae75e6d9d6a lib/galaxy/model/mapping.py --- a/lib/galaxy/model/mapping.py Mon Nov 03 15:21:03 2008 -0500 +++ b/lib/galaxy/model/mapping.py Mon Nov 03 15:31:38 2008 -0500 @@ -326,6 +326,7 @@ assign_mapper( context, GalaxySession, GalaxySession.table, properties=dict( histories=relation( GalaxySessionToHistoryAssociation ), + current_history=relation( History ), user=relation( User.mapper ) ) ) assign_mapper( context, GalaxySessionToHistoryAssociation, GalaxySessionToHistoryAssociation.table, diff -r 13cbdd1bbd19 -r 7ae75e6d9d6a lib/galaxy/tools/actions/__init__.py --- a/lib/galaxy/tools/actions/__init__.py Mon Nov 03 15:21:03 2008 -0500 +++ b/lib/galaxy/tools/actions/__init__.py Mon Nov 03 15:31:38 2008 -0500 @@ -177,7 +177,7 @@ trans.app.model.flush() # Create the job object job = trans.app.model.Job() - job.session_id = trans.get_galaxy_session( create=True ).id + job.session_id = trans.get_galaxy_session().id job.history_id = trans.history.id job.tool_id = tool.id try: diff -r 13cbdd1bbd19 -r 7ae75e6d9d6a lib/galaxy/web/controllers/root.py --- a/lib/galaxy/web/controllers/root.py Mon Nov 03 15:21:03 2008 -0500 +++ b/lib/galaxy/web/controllers/root.py Mon Nov 03 15:31:38 2008 -0500 @@ -54,10 +54,7 @@ NOTE: No longer accepts "id" or "template" options for security reasons. """ - try: - history = trans.get_history() - except: - return self.history_new(trans) + history = trans.get_history() if as_xml: trans.response.set_content_type('text/xml') return trans.fill_template_mako( "root/history_as_xml.mako", history=history ) diff -r 13cbdd1bbd19 -r 7ae75e6d9d6a lib/galaxy/web/controllers/tool_runner.py --- a/lib/galaxy/web/controllers/tool_runner.py Mon Nov 03 15:21:03 2008 -0500 +++ b/lib/galaxy/web/controllers/tool_runner.py Mon Nov 03 15:31:38 2008 -0500 @@ -41,7 +41,6 @@ return "Tool '%s' does not exist, kwd=%s " % (tool_id, kwd) params = util.Params( kwd, sanitize=tool.options.sanitize, tool=tool ) history = trans.get_history() - trans.ensure_valid_galaxy_session() template, vars = tool.handle_input( trans, params.__dict__ ) if len(params) > 0: trans.log_event( "Tool params: %s" % (str(params)), tool_id=tool_id ) diff -r 13cbdd1bbd19 -r 7ae75e6d9d6a lib/galaxy/web/controllers/user.py --- a/lib/galaxy/web/controllers/user.py Mon Nov 03 15:21:03 2008 -0500 +++ b/lib/galaxy/web/controllers/user.py Mon Nov 03 15:31:38 2008 -0500 @@ -82,10 +82,7 @@ elif not user.check_password( password ): password_error = "Invalid password" else: - trans.set_user( user ) - trans.ensure_valid_galaxy_session() - # Associate user with galaxy_session and history - trans.make_associations() + trans.handle_user_login( user ) trans.log_event( "User logged in" ) return trans.show_ok_message( "Now logged in as " + user.email, refresh_frames=['masthead', 'history'] ) return trans.show_form( @@ -97,7 +94,7 @@ def logout( self, trans ): # Since logging an event requires a session, we'll log prior to ending the session trans.log_event( "User logged out" ) - new_galaxy_session = trans.logout_galaxy_session() + trans.handle_user_logout() return trans.show_ok_message( "You are no longer logged in", refresh_frames=['masthead', 'history'] ) @web.expose @@ -118,12 +115,7 @@ user = trans.app.model.User( email=email ) user.set_password_cleartext( password ) user.flush() - trans.set_user( user ) - trans.ensure_valid_galaxy_session() - """ - Associate user with galaxy_session and history - """ - trans.make_associations() + trans.handle_user_login( user ) trans.log_event( "User created a new account" ) trans.log_event( "User logged in" ) #subscribe user to email list diff -r 13cbdd1bbd19 -r 7ae75e6d9d6a lib/galaxy/web/framework/__init__.py --- a/lib/galaxy/web/framework/__init__.py Mon Nov 03 15:21:03 2008 -0500 +++ b/lib/galaxy/web/framework/__init__.py Mon Nov 03 15:31:38 2008 -0500 @@ -109,12 +109,14 @@ self.__history = NOT_SET self.__galaxy_session = NOT_SET base.DefaultWebTransaction.__init__( self, environ ) - self.app.model.context.current.clear() + self.sa_session.clear() self.debug = asbool( self.app.config.get( 'debug', False ) ) # Flag indicating whether we are in workflow building mode (means # that the current history should not be used for parameter values # and such). self.workflow_building_mode = False + # Always have a valid galaxy session + self.__ensure_valid_session() @property def sa_session( self ): """ @@ -140,7 +142,6 @@ except: event.history_id = None event.user = self.user - self.ensure_valid_galaxy_session() event.session_id = self.galaxy_session.id event.flush() def get_cookie( self, name='galaxysession' ): @@ -163,277 +164,208 @@ tstamp = time.localtime ( time.time() + 3600 * 24 * age ) self.response.cookies[name]['expires'] = time.strftime( '%a, %d-%b-%Y %H:%M:%S GMT', tstamp ) self.response.cookies[name]['version'] = version + #@property + #def galaxy_session( self ): + # if not self.__galaxy_session: + # self.__ensure_valid_session() + # return self.__galaxy_session + def __ensure_valid_session( self ): + """ + Ensure that a valid Galaxy session exists and is available as + trans.session (part of initialization) + + Support for universe_session and universe_user cookies has been + removed as of 31 Oct 2008. + """ + sa_session = self.sa_session + # Try to load an existing session + secure_id = self.get_cookie( name='galaxysession' ) + galaxy_session = None + prev_galaxy_session = None + user_for_new_session = None + invalidate_existing_session = False + # Track whether the session has changed so we can avoid calling flush + # in the most common case (session exists and is valid). + galaxy_session_requires_flush = False + if secure_id: + # Decode the cookie value to get the session_key + session_key = self.security.decode_session_key( secure_id ) + # Retrive the galaxy_session id via the unique session_key + galaxy_session = sa_session.query( self.app.model.GalaxySession ).filter_by( session_key=session_key, is_valid=True ).first() + # If remote user is in use it can invalidate the session, so we need to + # to check some things now. + if self.app.config.use_remote_user: + assert "HTTP_REMOTE_USER" in self.environ, \ + "use_remote_user is set but no HTTP_REMOTE_USER variable" + remote_user_email = self.environ[ 'HTTP_REMOTE_USER' ] + if galaxy_session: + # An existing session, make sure correct association exists + if galaxy_session.user is None: + # No user, associate + galaxy_session.user = self.__get_or_create_remote_user( remote_user_email ) + galaxy_session_requires_flush = True + elif galaxy_session.user.email != remote_user_email: + # Session exists but is not associated with the correct + # remote user + invalidate_existing_session = True + user_for_new_session = self.__get_or_create_remote_user( remote_user_email ) + log.warning( "User logged in as '%s' externally, but has a cookie as '%s' invalidating session", + remote_user_email, prev_galaxy_session.user.email ) + else: + if galaxy_session is not None and galaxy_session.user and galaxy_session.user.external: + # Remote user support is not enabled, but there is an existing + # session with an external user, invalidate + invalidate_existing_session = True + log.warning( "User '%s' is an external user with an existing session, invalidating session since external auth is disabled", + galaxy_session.user.email ) + # Do we need to invalidate the session for some reason? + if invalidate_existing_session: + prev_galaxy_session = galaxy_session + prev_galaxy_session.is_valid = False + galaxy_session = None + # No relevant cookies, or couldn't find, or invalid, so create a new session + if galaxy_session is None: + galaxy_session = self.__create_new_session( prev_galaxy_session, user_for_new_session ) + galaxy_session_requires_flush = True + self.galaxy_session = galaxy_session + self.__update_session_cookie() + else: + self.galaxy_session = galaxy_session + # Do we need to flush the session? + if galaxy_session_requires_flush: + objects_to_flush = [ galaxy_session ] + # FIXME: If prev_session is a proper relation this would not + # be needed. + if prev_galaxy_session: + objects_to_flush.append( prev_galaxy_session ) + sa_session.flush( objects_to_flush ) + def __create_new_session( self, prev_galaxy_session=None, user_for_new_session=None ): + """ + Create a new GalaxySession for this request, possibly with a connection + to a previous session (in `prev_galaxy_session`) and an existing user + (in `user_for_new_session`). + + Caller is responsible for flushing the returned session. + """ + session_key = self.security.get_new_session_key() + galaxy_session = self.app.model.GalaxySession( + session_key=session_key, + is_valid=True, + remote_host = self.request.remote_host, + remote_addr = self.request.remote_addr, + referer = self.request.headers.get( 'Referer', None ) ) + # Invalidated an existing sesssion for some reason, keep track + if prev_galaxy_session: + galaxy_session.prev_session_id = prev_galaxy_session.id + # The new session should be immediately associated with a user + if user_for_new_session: + galaxy_session.user = user_for_new_session + return galaxy_session + def __get_or_create_remote_user( self, remote_user_email ): + """ + Return the user in $HTTP_REMOTE_USER and create if necessary + + Caller is responsible for flushing the returned user. + """ + # remote_user middleware ensures HTTP_REMOTE_USER exists + user = self.app.model.User.filter_by( email=remote_user_email ).first() + if user is None: + user = self.app.model.User( email=remote_user_email ) + user.set_password_cleartext( 'external' ) + user.external = True + self.log_event( "Automatically created account '%s'", user.email ) + return user + def __update_session_cookie( self ): + """ + Update the 'galaxysession' cookie to match the current session. + """ + self.set_cookie( name='galaxysession', + value=self.security.encode_session_key( self.galaxy_session.session_key ) ) + + def handle_user_login( self, user ): + """ + Login a new user (possibly newly created) + - create a new session + - associate new session with user + - if old session had a history and it was not associated with a user, associate it with the new session. + """ + prev_galaxy_session = self.galaxy_session + prev_galaxy_session.is_valid = False + self.galaxy_session = self.__create_new_session( prev_galaxy_session, user ) + if prev_galaxy_session.current_history: + history = prev_galaxy_session.current_history + if history.user is None: + self.galaxy_session.add_history( history ) + self.galaxy_session.current_history = history + history.user = user + self.sa_session.flush( [ prev_galaxy_session, self.galaxy_session, history ] ) + else: + self.sa_session.flush( [ prev_galaxy_session, self.galaxy_session ] ) + self.__update_session_cookie() + def handle_user_logout( self ): + """ + Logout the current user: + - invalidate the current session + - create a new session with no user associated + """ + prev_galaxy_session = self.galaxy_session + prev_galaxy_session.is_valid = False + self.galaxy_session = self.__create_new_session( prev_galaxy_session, None ) + self.sa_session.flush( [ prev_galaxy_session, self.galaxy_session ] ) + self.__update_session_cookie() + + def get_galaxy_session( self ): + """ + Return the current galaxy session + """ + return self.galaxy_session + def get_history( self, create=False ): - """Load the current history""" - if self.__history is NOT_SET: - self.__history = None - # See if we have a galaxysession cookie - secure_id = self.get_cookie( name='galaxysession' ) - if secure_id: - session_key = self.security.decode_session_key( secure_id ) - try: - galaxy_session = self.app.model.GalaxySession.filter_by( session_key=session_key ).first() - if galaxy_session and galaxy_session.is_valid and galaxy_session.current_history_id: - history = self.app.model.History.get( galaxy_session.current_history_id ) - if history and not history.deleted: - self.__history = history - except Exception, e: - # This should only occur in development if the cookie is not synced with the db - pass - else: - # See if we have a deprecated universe cookie - # TODO: this should be eliminated some time after October 1, 2008 - # We'll keep it until then because the old universe cookies are valid for 90 days - history_id = self.get_cookie( name='universe' ) - if history_id: - history = self.app.model.History.get( int( history_id ) ) - if history and not history.deleted: - self.__history = history - # Expire the universe cookie since it is deprecated - self.set_cookie( name='universe', value=id, age=0 ) - if self.__history is None: - return self.new_history() - if create is True and self.__history is None: - return self.new_history() - return self.__history + """ + Load the current history. + + NOTE: It looks like create was being ignored for a long time, so this + will currently *always* create a new history. This is wasteful + though, and we should verify that callers are using the create + flag correctly and fix. + """ + history = self.galaxy_session.current_history + if history is None: + history = self.new_history() + return history + def set_history( self, history ): + if history and not history.deleted: + self.galaxy_session.current_history = history + self.sa_session.flush( [ self.galaxy_session ] ) + history = property( get_history, set_history ) def new_history( self ): + """ + Create a new history and associate it with the current session and + its associated user (if set). + """ + # Create new history history = self.app.model.History() - # Make sure we have an id - history.flush() - # Immediately associate the new history with self - self.__history = history - # Make sure we have a valid session to associate with the new history - if self.galaxy_session_is_valid(): - galaxy_session = self.get_galaxy_session() - else: - galaxy_session = self.new_galaxy_session() - # We are associating the last used genome_build with histories, so we will always - # initialize a new history with the first dbkey in util.dbnames which is currently - # ? unspecified (?) + # Associate with session + history.add_galaxy_session( self.galaxy_session ) + # Make it the session's current history + self.galaxy_session.current_history = history + # Associate with user + if self.galaxy_session.user: + history.user = self.galaxy_session.user + # Track genome_build with history history.genome_build = util.dbnames.default_value - if self.user: - history.user_id = self.user.id - galaxy_session.user_id = self.user.id - try: - # See if we have already associated the history with the session - association = self.app.model.GalaxySessionToHistoryAssociation.filter_by( session_id=galaxy_session.id, history_id=history.id ).first() - except: - association = None - history.add_galaxy_session( galaxy_session, association=association ) - history.flush() - galaxy_session.current_history_id = history.id - galaxy_session.flush() - self.__history = history - return self.__history - def set_history( self, history ): - if history and not history.deleted and self.galaxy_session_is_valid(): - galaxy_session = self.get_galaxy_session() - galaxy_session.current_history_id = history.id - galaxy_session.flush() - self.__history = history - history = property( get_history, set_history ) + # Save + self.sa_session.flush( [ self.galaxy_session, history ] ) + return history + def get_user( self ): """Return the current user if logged in or None.""" - if self.__user is NOT_SET: - self.__user = None - user = self.get_cookie_user() - if self.app.config.use_remote_user: - remote_user = self.get_remote_user() - if user is not None and user.email != remote_user.email: - # The user has a cookie for a different user than the one - # they've authed as. - log.warning( "User logged in as '%s' externally, but has a cookie as '%s'," - % ( remote_user.email, user.email ) + " invalidating session" ) - self.logout_galaxy_session() - if user is None or ( user is not None and user.email != remote_user.email ): - # The user has no cookie, was not logged in, or the above. - self.set_user( remote_user ) - self.make_associations() - self.__user = remote_user - else: - if user is not None and user.external: - # use_remote_user is off, but the user still has a cookie - # from when it was on. Force the user to get a new - # unauthenticated session. - log.warning( "User '%s' is an external user with an existing " % user.email - + "session, invalidating session since external auth is disabled" ) - self.logout_galaxy_session() - else: - self.__user = user - return self.__user - def get_remote_user( self ): - """Return the user in $HTTP_REMOTE_USER and create if necessary""" - # remote_user middleware ensures HTTP_REMOTE_USER exists - try: - user = self.app.model.User.filter_by( email=self.environ[ 'HTTP_REMOTE_USER' ] ).first() - except: - user = self.app.model.User( email=self.environ[ 'HTTP_REMOTE_USER' ] ) - user.set_password_cleartext( 'external' ) - user.external = True - user.flush() - self.log_event( "Automatically created account '%s'" % user.email ) - return user - def get_cookie_user( self ): - """Return the user in the galaxysession cookie""" - __user = None - # See if we have a galaxysession cookie - secure_id = self.get_cookie( name='galaxysession' ) - if secure_id: - session_key = self.security.decode_session_key( secure_id ) - try: - galaxy_session = self.app.model.GalaxySession.filter_by( session_key=session_key ).first() - if galaxy_session and galaxy_session.is_valid and galaxy_session.user_id: - user = self.app.model.User.get( galaxy_session.user_id ) - if user: - __user = user - except: - # This should only occur in development if the cookie is not synced with the db - pass - else: - # See if we have a deprecated universe_user cookie - # TODO: this should be eliminated some time after October 1, 2008 - # We'll keep it until then because the old universe cookies are valid for 90 days - user_id = self.get_cookie( name='universe_user' ) - if user_id: - user = self.app.model.User.get( int( user_id ) ) - if user: - __user = user - # Expire the universe_user cookie since it is deprecated - self.set_cookie( name='universe_user', value='', age=0 ) - return __user + return self.galaxy_session.user def set_user( self, user ): - """Set the current user if logged in.""" - if user is not None and self.galaxy_session_is_valid(): - galaxy_session = self.get_galaxy_session() - if galaxy_session.user_id != user.id: - galaxy_session.user_id = user.id - galaxy_session.flush() - self.__user = user + """Set the current user.""" + self.galaxy_session.user = user + self.sa_session.flush( [ self.galaxy_session ] ) user = property( get_user, set_user ) - def get_galaxy_session( self, create=False ): - """Return the current user's GalaxySession""" - if self.__galaxy_session is NOT_SET: - self.__galaxy_session = None - # See if we have a galaxysession cookie - secure_id = self.get_cookie( name='galaxysession' ) - if secure_id: - # Decode the cookie value to get the session_key - session_key = self.security.decode_session_key( secure_id ) - try: - # Retrive the galaxy_session id via the unique session_key - galaxy_session = self.app.model.GalaxySession.filter_by( session_key=session_key ).first() - if galaxy_session and galaxy_session.is_valid: - self.__galaxy_session = galaxy_session - except: - # This should only occur in development if the cookie is not synced with the db - pass - else: - # See if we have a deprecated universe_session cookie - # TODO: this should be eliminated some time after October 1, 2008 - # We'll keep it until then because the old universe cookies are valid for 90 days - session_id = self.get_cookie( name='universe_session' ) - if session_id: - galaxy_session = self.app.model.GalaxySession.get( int( session_id ) ) - # NOTE: We can't test for is_valid here since the old session records did not include this flag - if galaxy_session: - # Set the new galaxysession cookie value, old session records did not have a session_key or is_valid flag - session_key = self.security.get_new_session_key() - galaxy_session.session_key = session_key - galaxy_session.is_valid = True - galaxy_session.flush() - secure_id = self.security.encode_session_key( session_key ) - self.set_cookie( name='galaxysession', value=secure_id ) - # Expire the universe_user cookie since it is deprecated - self.set_cookie( name='universe_session', value='', age=0 ) - self.__galaxy_session = galaxy_session - if create is True and self.__galaxy_session is None: - return self.new_galaxy_session() - return self.__galaxy_session - def new_galaxy_session( self, prev_session_id=None ): - """Create a new secure galaxy_session""" - session_key = self.security.get_new_session_key() - galaxy_session = self.app.model.GalaxySession( session_key=session_key, is_valid=True, prev_session_id=prev_session_id ) - # Make sure we have an id - galaxy_session.flush() - # Immediately associate the new session with self - self.__galaxy_session = galaxy_session - if prev_session_id is not None: - # User logged out, so we need to create a new history for this session - self.history = self.new_history() - galaxy_session.current_history_id = self.history.id - elif self.user is not None: - galaxy_session.user_id = self.user.id - # Set this session's current_history_id to the user's last updated history - h = self.app.model.History - ht = h.table - where = ( ht.c.user_id==self.user.id ) & ( ht.c.deleted=='f' ) - history = h.query().filter( where ).order_by( desc( ht.c.update_time ) ).first() - if history: - self.history = history - galaxy_session.current_history_id = self.history.id - elif self.history: - galaxy_session.current_history_id = self.history.id - galaxy_session.remote_host = self.request.remote_host - galaxy_session.remote_addr = self.request.remote_addr - try: - galaxy_session.referer = self.request.headers['Referer'] - except: - galaxy_session.referer = None - if self.history is not None: - # See if we have already associated the session with the history - try: - association = self.app.model.GalaxySessionToHistoryAssociation.filter_by( session_id=galaxy_session.id, history_id=self.history.id ).first() - except: - association = None - galaxy_session.add_history( self.history, association=association ) - galaxy_session.flush() - # Set the cookie value to the encrypted session_key - self.set_cookie( name='galaxysession', value=self.security.encode_session_key( session_key ) ) - self.__galaxy_session = galaxy_session - return self.__galaxy_session - def set_galaxy_session( self, galaxy_session ): - """Set the current galaxy_session""" - self.__galaxy_session = galaxy_session - galaxy_session = property( get_galaxy_session, set_galaxy_session ) - def galaxy_session_is_valid( self ): - try: - return self.galaxy_session.is_valid - except: - return False - def ensure_valid_galaxy_session( self ): - """Make sure we have a valid galaxy session, create a new one if necessary.""" - if not self.galaxy_session_is_valid(): - galaxy_session = self.new_galaxy_session() - def logout_galaxy_session( self ): - """ - Logout the current user by setting user to None and galaxy_session.is_valid to False - in the db. A new galaxy_session is automatically created with prev_session_id is set - to save a reference to the current one as a way of chaining them together - """ - if self.galaxy_session_is_valid(): - galaxy_session = self.get_galaxy_session() - old_session_id = galaxy_session.id - galaxy_session.is_valid = False - galaxy_session.flush() - self.set_user( None ) - return self.new_galaxy_session( prev_session_id=old_session_id ) - else: - error( "Attempted to logout an invalid galaxy_session" ) - def make_associations( self ): - history = self.get_history() - user = self.get_user() - if self.galaxy_session_is_valid(): - galaxy_session = self.get_galaxy_session() - if galaxy_session.user_id is None and user is not None: - galaxy_session.user_id = user.id - if history is not None: - galaxy_session.current_history_id = history.id - galaxy_session.flush() - self.__galaxy_session = galaxy_session - if history is not None and user is not None: - history.user_id = user.id - history.flush() - self.__history = history def get_toolbox(self): """Returns the application toolbox""" diff -r 13cbdd1bbd19 -r 7ae75e6d9d6a lib/galaxy/web/security/__init__.py --- a/lib/galaxy/web/security/__init__.py Mon Nov 03 15:21:03 2008 -0500 +++ b/lib/galaxy/web/security/__init__.py Mon Nov 03 15:31:38 2008 -0500 @@ -1,9 +1,35 @@ +import os, os.path, logging + import pkg_resources pkg_resources.require( "pycrypto" ) from Crypto.Cipher import Blowfish from Crypto.Util.randpool import RandomPool from Crypto.Util import number + +log = logging.getLogger( __name__ ) + +if os.path.exists( "/dev/urandom" ): + log.debug("###using /dev/urandom....") + # We have urandom, use it as the source of random data + random_fd = os.open( "/dev/urandom", os.O_RDONLY ) + def get_random_bytes( nbytes ): + value = os.read( random_fd, nbytes ) + # Normally we should get as much as we need + if len( value ) == nbytes: + return value + # If we don't, keep reading (this is slow and should never happen) + while len( value ) < nbytes: + value += os.read( random_fd, nbytes - len( value ) ) + return value +else: + def get_random_bytes( nbytes ): + nbits = nbytes * 8 + random_pool = RandomPool( 1064 ) + while random_pool.entropy < nbits: + random_pool.add_event() + random_pool.stir() + return( str( number.getRandomNumber( nbits, random_pool.get_bytes ) ) ) class SecurityHelper( object ): # TODO: checking if histories/datasets are owned by the current user) will be moved here. @@ -30,11 +56,5 @@ return self.id_cipher.decrypt( session_key.decode( 'hex' ) ).lstrip( "!" ) def get_new_session_key( self ): # Generate a unique, high entropy 128 bit random number - random_pool = RandomPool( 1064 ) - while random_pool.entropy < 128: - random_pool.add_event() - random_pool.stir() - rn = number.getRandomNumber( 128, random_pool.get_bytes ) - # session_key must be a string - return str( rn ) + return get_random_bytes( 16 ) \ No newline at end of file diff -r 13cbdd1bbd19 -r 7ae75e6d9d6a templates/root/history.mako --- a/templates/root/history.mako Mon Nov 03 15:21:03 2008 -0500 +++ b/templates/root/history.mako Mon Nov 03 15:31:38 2008 -0500 @@ -231,6 +231,7 @@ <body class="historyPage"> + <div id="top-links" class="historyLinks"> <a href="${h.url_for('history', show_deleted=show_deleted)}">refresh</a> %if show_deleted: