6 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/cfd108a99a24/ Changeset: cfd108a99a24 User: dannon Date: 2014-06-09 13:58:18 Summary: Update user honeypot error message. Affected #: 1 file diff -r 2f1a585a7eaf76c687675c84c054bcc326812af1 -r cfd108a99a24d97eafbd81fd5c9ab565fd3486a2 lib/galaxy/webapps/galaxy/controllers/user.py --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -628,7 +628,7 @@ # If the honeypot field is not empty we are dealing with a bot. honeypot_field = params.get( 'bear_field', '' ) if honeypot_field != '': - return trans.show_error_message( "You are considered a bot. If you are not one please try registering again and follow the form's legend. <a target=\"_top\" href=\"%s\">Go to the home page</a>." ) % url_for( '/' ) + return trans.show_error_message( "You've been flagged as a possible bot. If you are not, please try registering again and fill the form out carefully. <a target=\"_top\" href=\"%s\">Go to the home page</a>." ) % url_for( '/' ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) https://bitbucket.org/galaxy/galaxy-central/commits/9b908e6dd95b/ Changeset: 9b908e6dd95b User: dannon Date: 2014-06-09 14:14:18 Summary: Fix impersonation when using external authentication. Admins can now impersonate (and then log out of) users when using external auth. Affected #: 2 files diff -r cfd108a99a24d97eafbd81fd5c9ab565fd3486a2 -r 9b908e6dd95b9949dd47065528093c1ae36950b7 lib/galaxy/web/framework/__init__.py --- a/lib/galaxy/web/framework/__init__.py +++ b/lib/galaxy/web/framework/__init__.py @@ -743,8 +743,10 @@ # 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 + elif galaxy_session.user.email != remote_user_email and self.app.config.allow_user_impersonation and remote_user_email not in [ x.strip() for x in self.app.config.get( "admin_users", "" ).split( "," ) ]: + # Session exists but is not associated with the correct + # remote user, and the currently set remote_user is not a + # potentially impersonating admin. 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", diff -r cfd108a99a24d97eafbd81fd5c9ab565fd3486a2 -r 9b908e6dd95b9949dd47065528093c1ae36950b7 lib/galaxy/web/framework/middleware/remoteuser.py --- a/lib/galaxy/web/framework/middleware/remoteuser.py +++ b/lib/galaxy/web/framework/middleware/remoteuser.py @@ -76,6 +76,8 @@ return self.error( start_response, title, message ) if path_info.startswith( '/user/create' ) and environ[ self.remote_user_header ] in self.admin_users: pass # admins can create users + elif path_info.startswith( '/user/logout' ) and environ[ self.remote_user_header ] in self.admin_users: + pass # Admin users may be impersonating, allow logout. elif path_info.startswith( '/user/api_keys' ): pass # api keys can be managed when remote_user is in use elif path_info.startswith( '/user/edit_username' ): https://bitbucket.org/galaxy/galaxy-central/commits/fe917a59d474/ Changeset: fe917a59d474 User: dannon Date: 2014-06-09 14:33:25 Summary: pep8/cleanup. set NERD_tree_1noqa for impossible sqlalchemy lines. Affected #: 1 file diff -r 9b908e6dd95b9949dd47065528093c1ae36950b7 -r fe917a59d4749503db66fe7c01ffe3e41fb1a3cf lib/galaxy/web/framework/__init__.py --- a/lib/galaxy/web/framework/__init__.py +++ b/lib/galaxy/web/framework/__init__.py @@ -35,10 +35,10 @@ import mako.lookup import mako.runtime -eggs.require( "pytz" ) # Used by Babel. +eggs.require( "pytz" ) # Used by Babel. eggs.require( "Babel" ) from babel.support import Translations -from babel import Locale, UnknownLocaleError +from babel import Locale eggs.require( "SQLAlchemy >= 0.4" ) from sqlalchemy import and_ @@ -63,6 +63,7 @@ 'hgw8.cse.ucsc.edu', ) + def expose( func ): """ Decorator: mark a function as 'exposed' and thus web accessible @@ -70,6 +71,7 @@ func.exposed = True return func + def json( func ): @wraps(func) def decorator( self, trans, *args, **kwargs ): @@ -80,6 +82,7 @@ decorator.exposed = True return decorator + def json_pretty( func ): @wraps(func) def decorator( self, trans, *args, **kwargs ): @@ -90,6 +93,7 @@ decorator.exposed = True return decorator + def require_login( verb="perform this action", use_panels=False, webapp='galaxy' ): def argcatcher( func ): @wraps(func) @@ -132,6 +136,7 @@ payload = util.recursively_stringify_dictionary_keys( from_json_string( trans.request.body ) ) return payload + def expose_api_raw( func ): """ Expose this function via the API but don't dump the results @@ -139,7 +144,7 @@ """ return expose_api( func, to_json=False ) -#DBTODO refactor these post-dist. + def expose_api_raw_anonymous( func ): """ Expose this function via the API but don't dump the results @@ -147,12 +152,14 @@ """ return expose_api( func, to_json=False, user_required=False ) + def expose_api_anonymous( func, to_json=True ): """ Expose this function via the API but don't require a set user. """ return expose_api( func, to_json=to_json, user_required=False ) + def expose_api( func, to_json=True, user_required=True ): """ Expose this function via the API. @@ -203,7 +210,7 @@ rval = to_json_string( rval ) return rval except paste.httpexceptions.HTTPException: - raise # handled + raise # handled except: log.exception( 'Uncaught exception in exposed API method:' ) raise paste.httpexceptions.HTTPServerError() @@ -379,9 +386,11 @@ NOT_SET = object() + def error( message ): raise MessageException( message, type='error' ) + def form( *args, **kwargs ): return FormBuilder( *args, **kwargs ) @@ -405,15 +414,15 @@ # Then look in root directory paths.append( galaxy_app.config.template_path ) # Create TemplateLookup with a small cache - return mako.lookup.TemplateLookup( - directories = paths, - module_directory = galaxy_app.config.template_cache, - collection_size = 500, - output_encoding = 'utf-8' ) + return mako.lookup.TemplateLookup(directories=paths, + module_directory=galaxy_app.config.template_cache, + collection_size=500, + output_encoding='utf-8' ) def handle_controller_exception( self, e, trans, **kwargs ): if isinstance( e, MessageException ): - #In the case of a controller exception, sanitize to make sure unsafe html input isn't reflected back to the user + # In the case of a controller exception, sanitize to make sure + # unsafe html input isn't reflected back to the user return trans.show_message( sanitize_html(e.err_msg), e.type ) def make_body_iterable( self, trans, body ): @@ -509,7 +518,7 @@ elif self.app.name == "reports": self.galaxy_session = None else: - #This is a web request, get or create session. + # This is a web request, get or create session. self._ensure_valid_session( session_cookie ) if self.galaxy_session: # When we've authenticated by session, we have to check the @@ -534,7 +543,7 @@ # Default to English locales = 'en' t = Translations.load( dirname='locale', locales=locales, domain='ginga' ) - self.template_context.update ( dict( _=t.ugettext, n_=t.ugettext, N_=t.ungettext ) ) + self.template_context.update( dict( _=t.ugettext, n_=t.ugettext, N_=t.ungettext ) ) @property def anonymous( self ): @@ -644,8 +653,8 @@ # using a server secret key. Any other value is invalid and could pose security issues. self.response.cookies[name] = value self.response.cookies[name]['path'] = path - self.response.cookies[name]['max-age'] = 3600 * 24 * age # 90 days - tstamp = time.localtime ( time.time() + 3600 * 24 * age ) + self.response.cookies[name]['max-age'] = 3600 * 24 * age # 90 days + 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 try: @@ -724,14 +733,13 @@ if session_key: # Retrieve the galaxy_session id via the unique session_key galaxy_session = self.sa_session.query( self.app.model.GalaxySession ) \ - .filter( and_( self.app.model.GalaxySession.table.c.session_key==session_key, - self.app.model.GalaxySession.table.c.is_valid==True ) ) \ - .first() + .filter( and_( self.app.model.GalaxySession.table.c.session_key==session_key, #noqa + self.app.model.GalaxySession.table.c.is_valid==True ) ).first() #noqa # If remote user is in use it can invalidate the session and in some # cases won't have a cookie set above, so we need to to check some # things now. if self.app.config.use_remote_user: - #If this is an api request, and they've passed a key, we let this go. + # If this is an api request, and they've passed a key, we let this go. assert self.app.config.remote_user_header in self.environ, \ "use_remote_user is set but %s header was not provided" % self.app.config.remote_user_header remote_user_email = self.environ[ self.app.config.remote_user_header ] @@ -828,9 +836,9 @@ if self.request.path.startswith( external_display_path ): request_path_split = self.request.path.split( '/' ) try: - if self.app.datatypes_registry.display_applications.get( request_path_split[-5] ) and \ - request_path_split[-4] in self.app.datatypes_registry.display_applications.get( request_path_split[-5] ).links and \ - request_path_split[-3] != 'None': + if (self.app.datatypes_registry.display_applications.get( request_path_split[-5] ) + and request_path_split[-4] in self.app.datatypes_registry.display_applications.get( request_path_split[-5] ).links + and request_path_split[-3] != 'None'): return except IndexError: pass @@ -849,9 +857,9 @@ 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 ) ) + remote_host=self.request.remote_host, + remote_addr=self.request.remote_addr, + referer=self.request.headers.get( 'Referer', None ) ) if prev_galaxy_session: # Invalidated an existing session for some reason, keep track galaxy_session.prev_session_id = prev_galaxy_session.id @@ -868,9 +876,8 @@ return None if getattr( self.app.config, "normalize_remote_user_email", False ): remote_user_email = remote_user_email.lower() - user = self.sa_session.query( self.app.model.User ) \ - .filter( self.app.model.User.table.c.email==remote_user_email ) \ - .first() + user = self.sa_session.query( self.app.model.User + ).filter( self.app.model.User.table.c.email==remote_user_email ).first() #noqa if user: # GVK: June 29, 2009 - This is to correct the behavior of a previous bug where a private # role and default user / history permissions were not set for remote users. When a @@ -903,7 +910,7 @@ # We set default user permissions, before we log in and set the default history permissions if 'webapp' not in self.environ or self.environ['webapp'] != 'tool_shed': self.app.security_agent.user_set_default_permissions( user ) - #self.log_event( "Automatically created account '%s'", user.email ) + # self.log_event( "Automatically created account '%s'", user.email ) return user def __update_session_cookie( self, name='galaxysession' ): @@ -973,7 +980,6 @@ # This method is not called from the Galaxy reports, so the cookie will always be galaxysession self.__update_session_cookie( name=cookie_name ) - def handle_user_logout( self, logout_all=False ): """ Logout the current user: @@ -986,10 +992,10 @@ self.sa_session.add_all( ( prev_galaxy_session, self.galaxy_session ) ) galaxy_user_id = prev_galaxy_session.user_id if logout_all and galaxy_user_id is not None: - for other_galaxy_session in self.sa_session.query( self.app.model.GalaxySession ) \ - .filter( and_( self.app.model.GalaxySession.table.c.user_id==galaxy_user_id, - self.app.model.GalaxySession.table.c.is_valid==True, - self.app.model.GalaxySession.table.c.id!=prev_galaxy_session.id ) ): + for other_galaxy_session in self.sa_session.query( self.app.model.GalaxySession + ).filter( and_( self.app.model.GalaxySession.table.c.user_id==galaxy_user_id, #noqa + self.app.model.GalaxySession.table.c.is_valid==True, #noqa + self.app.model.GalaxySession.table.c.id!=prev_galaxy_session.id ) ): #noqa other_galaxy_session.is_valid = False self.sa_session.add( other_galaxy_session ) self.sa_session.flush() @@ -1041,9 +1047,9 @@ # (b) has no datasets. If suitable history found, use it; otherwise, create # new history. unnamed_histories = self.sa_session.query( self.app.model.History ).filter_by( - user=self.galaxy_session.user, - name=self.app.model.History.default_name, - deleted=False ) + user=self.galaxy_session.user, + name=self.app.model.History.default_name, + deleted=False ) default_history = None for history in unnamed_histories: if len( history.datasets ) == 0: @@ -1180,8 +1186,9 @@ Convenience method for displaying a simple page with a single HTML form. """ - return self.fill_template( template, form=form, header=header, use_panels=( form.use_panels or use_panels ), - active_view=active_view ) + return self.fill_template( template, form=form, header=header, + use_panels=( form.use_panels or use_panels ), + active_view=active_view ) def fill_template(self, filename, **kwargs): """ @@ -1214,9 +1221,10 @@ data = dict( caller=self, t=self, trans=self, h=helpers, util=util, request=self.request, response=self.response, app=self.app ) data.update( self.template_context ) data.update( kwargs ) - ## return template.render( **data ) + def render( environ, start_response ): response_write = start_response( self.response.wsgi_status(), self.response.wsgi_headeritems() ) + class StreamBuffer( object ): def write( self, d ): response_write( d.encode( 'utf-8' ) ) @@ -1240,7 +1248,7 @@ Returns the builds defined by galaxy and the builds defined by the user (chromInfo in history). """ - #FIXME: This method should be removed + # FIXME: This method should be removed return self.app.genome_builds.get_genome_build_names( trans=self ) @property @@ -1365,6 +1373,6 @@ def __getattr__( self, key ): if key not in self: raise AttributeError, key return self[key] + def __setattr__( self, key, value ): self[key] = value - https://bitbucket.org/galaxy/galaxy-central/commits/305d4bd1db40/ Changeset: 305d4bd1db40 User: dannon Date: 2014-06-09 14:35:32 Summary: One more touchup in webframework -- correct raise form and use multiple lines. Affected #: 1 file diff -r fe917a59d4749503db66fe7c01ffe3e41fb1a3cf -r 305d4bd1db404b13f49b6cc49e36115b4d2e33d4 lib/galaxy/web/framework/__init__.py --- a/lib/galaxy/web/framework/__init__.py +++ b/lib/galaxy/web/framework/__init__.py @@ -1371,7 +1371,8 @@ Bunch based on a dict """ def __getattr__( self, key ): - if key not in self: raise AttributeError, key + if key not in self: + raise AttributeError(key) return self[key] def __setattr__( self, key, value ): https://bitbucket.org/galaxy/galaxy-central/commits/8e4483daa6e8/ Changeset: 8e4483daa6e8 User: dannon Date: 2014-06-09 14:38:47 Summary: Cleanup/pep8 of remoteuser middleware. Affected #: 1 file diff -r 305d4bd1db404b13f49b6cc49e36115b4d2e33d4 -r 8e4483daa6e8a76044b7ec0bc06877b4244a0125 lib/galaxy/web/framework/middleware/remoteuser.py --- a/lib/galaxy/web/framework/middleware/remoteuser.py +++ b/lib/galaxy/web/framework/middleware/remoteuser.py @@ -35,6 +35,7 @@ </html> """ + class RemoteUser( object ): def __init__( self, app, maildomain=None, display_servers=None, admin_users=None, remote_user_header=None ): self.app = app @@ -42,9 +43,10 @@ self.display_servers = display_servers or [] self.admin_users = admin_users or [] self.remote_user_header = remote_user_header or 'HTTP_REMOTE_USER' + def __call__( self, environ, start_response ): # Allow display servers - if self.display_servers and environ.has_key( 'REMOTE_ADDR' ): + if self.display_servers and 'REMOTE_ADDR' in environ: try: host = socket.gethostbyaddr( environ[ 'REMOTE_ADDR' ] )[0] except( socket.error, socket.herror, socket.gaierror, socket.timeout ): @@ -57,7 +59,7 @@ # Rewrite* method for passing REMOTE_USER and a user is # un-authenticated. Any other possible values need to go here as well. path_info = environ.get('PATH_INFO', '') - if environ.has_key( self.remote_user_header ) and environ[ self.remote_user_header ] != '(null)': + if self.remote_user_header in environ and environ[ self.remote_user_header ] != '(null)': if not environ[ self.remote_user_header ].count( '@' ): if self.maildomain is not None: environ[ self.remote_user_header ] += '@' + self.maildomain @@ -75,15 +77,15 @@ """ return self.error( start_response, title, message ) if path_info.startswith( '/user/create' ) and environ[ self.remote_user_header ] in self.admin_users: - pass # admins can create users + pass # admins can create users elif path_info.startswith( '/user/logout' ) and environ[ self.remote_user_header ] in self.admin_users: pass # Admin users may be impersonating, allow logout. elif path_info.startswith( '/user/api_keys' ): - pass # api keys can be managed when remote_user is in use + pass # api keys can be managed when remote_user is in use elif path_info.startswith( '/user/edit_username' ): - pass # username can be managed when remote_user is in use + pass # username can be managed when remote_user is in use elif path_info.startswith( '/user/dbkeys' ): - pass # dbkeys can be managed when remote_user is in use + pass # dbkeys can be managed when remote_user is in use elif path_info.startswith( '/user' ): title = "Access to Galaxy user controls is disabled" message = """ @@ -105,6 +107,7 @@ <p>Please contact your local Galaxy administrator. """ return self.error( start_response, title, message ) + def error( self, start_response, title="Access denied", message="Please contact your local Galaxy administrator." ): start_response( '403 Forbidden', [('Content-type', 'text/html')] ) return [errorpage % (title, message)] https://bitbucket.org/galaxy/galaxy-central/commits/095b6ea1888e/ Changeset: 095b6ea1888e User: dannon Date: 2014-06-09 14:40:40 Summary: Slightly simplify remote_user_header access logic. Affected #: 1 file diff -r 8e4483daa6e8a76044b7ec0bc06877b4244a0125 -r 095b6ea1888ee97313a9aff40258a96bb471b219 lib/galaxy/web/framework/middleware/remoteuser.py --- a/lib/galaxy/web/framework/middleware/remoteuser.py +++ b/lib/galaxy/web/framework/middleware/remoteuser.py @@ -59,7 +59,7 @@ # Rewrite* method for passing REMOTE_USER and a user is # un-authenticated. Any other possible values need to go here as well. path_info = environ.get('PATH_INFO', '') - if self.remote_user_header in environ and environ[ self.remote_user_header ] != '(null)': + if environ.get(self.remote_user_header, '(null)') != '(null)': if not environ[ self.remote_user_header ].count( '@' ): if self.maildomain is not None: environ[ self.remote_user_header ] += '@' + self.maildomain Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.