From 660cfcbdf88b5aa48bef998c980460ccd9f06716 Mon Sep 17 00:00:00 2001 From: David Trudgian Date: Thu, 2 Apr 2015 13:01:49 -0500 Subject: [PATCH 1/5] Initial attempt at LDAP login with username - WIP --- config/galaxy.ini.sample | 2 +- lib/galaxy/auth/__init__.py | 49 +++++++++------- lib/galaxy/auth/providers/__init__.py | 12 ++-- lib/galaxy/auth/providers/alwaysreject.py | 4 +- .../{activedirectory.py => ldap_ad.py} | 58 +++++++++++-------- lib/galaxy/auth/providers/localdb.py | 4 +- lib/galaxy/security/validate_user_input.py | 4 +- .../webapps/galaxy/controllers/mobile.py | 14 +++-- lib/galaxy/webapps/galaxy/controllers/user.py | 26 +++++---- templates/user/login.mako | 4 +- 10 files changed, 99 insertions(+), 78 deletions(-) rename lib/galaxy/auth/providers/{activedirectory.py => ldap_ad.py} (60%) diff --git a/config/galaxy.ini.sample b/config/galaxy.ini.sample index 3ddf929677b..69b2b925ae9 100644 --- a/config/galaxy.ini.sample +++ b/config/galaxy.ini.sample @@ -856,7 +856,7 @@ use_interactive = True #openid_consumer_cache_path = database/openid_consumer_cache # XML config file that allows the use of different authentication providers -# (e.g. Active Directory) instead or in addition to local authentication +# (e.g. LDAP) instead or in addition to local authentication # (.sample is used if default does not exist). #auth_config_file = config/auth_conf.xml diff --git a/lib/galaxy/auth/__init__.py b/lib/galaxy/auth/__init__.py index 116229659a1..aa4efc6f498 100644 --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -20,19 +20,23 @@ log = logging.getLogger(__name__) # # -# activedirectory -# '[username]'.endswith('@students.latrobe.edu.au') +# ldap_ad +# '[login]'.endswith('@students.latrobe.edu.au') # # True # ldap://STUDENTS.ltu.edu.au -# [(&(objectClass=user)(mail={username})) +# [(&(objectClass=user)(mail={login})) # dc=STUDENTS,dc=ltu,dc=edu,dc=au # jsmith # mysecret -# sAMAccountName] +# sAMAccountName,mail] # {sAMAccountName}@STUDENTS.ltu.edu.au # {password} # {sAMAccountName} +# {mail} +# # # # ... @@ -80,18 +84,18 @@ class AuthManager(object): authenticators.append(authenticator) self.authenticators = authenticators - def check_registration_allowed(self, email, password): - """Checks if the provided email is allowed to register.""" + def check_registration_allowed(self, login, password): + """Checks if the provided email/username is allowed to register.""" message = '' status = 'done' - for provider, options in self.active_authenticators(email, password): + for provider, options in self.active_authenticators(login, password): allow_reg = _get_tri_state(options, 'allow-register', True) if allow_reg is None: # i.e. challenge - auth_result, msg = provider.authenticate(email, password, options) + auth_result, msg = provider.authenticate(login, password, options) if auth_result is True: break if auth_result is None: - message = 'Invalid email address or password' + message = 'Invalid email address/username or password' status = 'error' break elif allow_reg is True: @@ -102,16 +106,17 @@ class AuthManager(object): break return message, status - def check_auto_registration(self, trans, email, password): + def check_auto_registration(self, trans, login, password): """ - Checks the email/password using auth providers in order. If a match is - found, returns the 'auto-register' option for that provider. + Checks the username/email & password using auth providers in order. + If a match is found, returns the 'auto-register' option for that provider. """ - for provider, options in self.active_authenticators(email, password): + for provider, options in self.active_authenticators(login, password): if provider is None: log.debug( "Unable to find module: %s" % options ) else: - auth_result, auto_username = provider.authenticate(email, password, options) + auth_result, auto_email, auto_username = provider.authenticate(login, password, options) + auto_email = str(auto_email).lower() auto_username = str(auto_username).lower() if auth_result is True: # make username unique @@ -124,16 +129,16 @@ class AuthManager(object): i += 1 else: break # end for loop if we can't make a unique username - log.debug( "Email: %s, auto-register with username: %s" % (email, auto_username) ) - return (_get_bool(options, 'auto-register', False), auto_username) + log.debug( "Email: %s, auto-register with username: %s" % (auto_email, auto_username) ) + return (_get_bool(options, 'auto-register', False), auto_email, auto_username) elif auth_result is None: - log.debug( "Email: %s, stopping due to failed non-continue" % (email) ) + log.debug( "Email: %s, Username %s, stopping due to failed non-continue" % (auto_email, auto_username) ) break # end authentication (skip rest) return (False, '') def check_password(self, user, password): - """Checks the email/password using auth providers.""" - for provider, options in self.active_authenticators(user.email, password): + """Checks the username/email and password using auth providers.""" + for provider, options in self.active_authenticators(user, password): if provider is None: log.debug( "Unable to find module: %s" % options ) else: @@ -148,7 +153,7 @@ class AuthManager(object): """Checks that auth provider allows password changes and current_password matches. """ - for provider, options in self.active_authenticators(user.email, current_password): + for provider, options in self.active_authenticators(user, current_password): if provider is None: log.debug( "Unable to find module: %s" % options ) else: @@ -162,7 +167,7 @@ class AuthManager(object): return (False, 'Password change not supported') return (False, 'Invalid current password') - def active_authenticators(self, username, password): + def active_authenticators(self, login, password): """Yields AuthProvider instances for the provided configfile that match the filters. """ @@ -170,7 +175,7 @@ class AuthManager(object): for authenticator in self.authenticators: filter_template = authenticator.filter_template if filter_template: - filter_str = filter_template.format(username=username, password=password) + filter_str = filter_template.format(login=login, password=password) passed_filter = eval(filter_str, {"__builtins__": None}, {'str': str}) if not passed_filter: continue # skip to next diff --git a/lib/galaxy/auth/providers/__init__.py b/lib/galaxy/auth/providers/__init__.py index 724192007ce..5552193f257 100644 --- a/lib/galaxy/auth/providers/__init__.py +++ b/lib/galaxy/auth/providers/__init__.py @@ -16,23 +16,23 @@ class AuthProvider(object): """ Short string providing labelling this plugin """ @abc.abstractmethod - def authenticate(self, username, password, options): + def authenticate(self, login, password, options): """ Check that the username and password are correct. NOTE: Used within auto-registration to check it is ok to register this user. - :param username: the users email address - :type username: str + :param login: the users email address + :type login: str :param password: the plain text password they typed :type password: str :param options: options provided in auth_config_file :type options: dict :returns: True: accept user, False: reject user and None: reject user - and don't try any other providers. str is the username to register - with if accepting - :rtype: (bool, str) + and don't try any other providers. str, str is the email and + username to register with if accepting + :rtype: (bool, str, str) """ @abc.abstractmethod diff --git a/lib/galaxy/auth/providers/alwaysreject.py b/lib/galaxy/auth/providers/alwaysreject.py index a9cb54faf94..a2c27b6293a 100644 --- a/lib/galaxy/auth/providers/alwaysreject.py +++ b/lib/galaxy/auth/providers/alwaysreject.py @@ -16,11 +16,11 @@ class AlwaysReject(AuthProvider): """ plugin_type = 'alwaysreject' - def authenticate(self, username, password, options): + def authenticate(self, login, password, options): """ See abstract method documentation. """ - return (None, '') + return (None, '', '') def authenticate_user(self, user, password, options): """ diff --git a/lib/galaxy/auth/providers/activedirectory.py b/lib/galaxy/auth/providers/ldap_ad.py similarity index 60% rename from lib/galaxy/auth/providers/activedirectory.py rename to lib/galaxy/auth/providers/ldap_ad.py index 8f77a9703aa..76986ca33dd 100644 --- a/lib/galaxy/auth/providers/activedirectory.py +++ b/lib/galaxy/auth/providers/ldap_ad.py @@ -4,34 +4,37 @@ Created on 15/07/2014 @author: Andrew Robinson """ +import logging + from galaxy.exceptions import ConfigurationError from ..providers import AuthProvider +from galaxy.util import string_as_bool +from galaxy.auth import _get_bool -import logging log = logging.getLogger(__name__) def _get_subs(d, k, params): if k not in d: - raise ConfigurationError("Missing '%s' parameter in Active Directory options" % k) + raise ConfigurationError("Missing '%s' parameter in LDAP options" % k) return str(d[k]).format(**params) -class ActiveDirectory(AuthProvider): +class LDAPAD(AuthProvider): """ - Attempts to authenticate users against an Active Directory server. + Attempts to authenticate users against an LDAP server. - If options include search-fields then it will attempt to search the AD for - those fields first. After that it will bind to the AD with the username + If options include search-fields then it will attempt to search LDAP for + those fields first. After that it will bind to LDAP with the username (formatted as specified). """ - plugin_type = 'activedirectory' + plugin_type = 'ldap_ad' - def authenticate(self, username, password, options): + def authenticate(self, login, password, options): """ See abstract method documentation. """ - log.debug("Username: %s" % username) + log.debug("Login: %s" % login) log.debug("Options: %s" % options) failure_mode = False # reject but continue @@ -41,11 +44,11 @@ class ActiveDirectory(AuthProvider): try: import ldap except: - log.debug("User: %s, ACTIVEDIRECTORY: False (no ldap)" % (username)) + log.debug("Login: %s, LDAP: False (could not load ldap module)" % (login)) return (failure_mode, '') - # do AD search (if required) - params = {'username': username, 'password': password} + # do LDAP search (if required) + params = {'login': login, 'password': password} if 'search-fields' in options: try: # setup connection @@ -54,7 +57,8 @@ class ActiveDirectory(AuthProvider): l.protocol_version = 3 if 'search-user' in options: - l.simple_bind_s(_get_subs(options, 'search-user', params), _get_subs(options, 'search-password', params)) + l.simple_bind_s(_get_subs(options, 'search-user', params), + _get_subs(options, 'search-password', params)) else: l.simple_bind_s() @@ -62,13 +66,14 @@ class ActiveDirectory(AuthProvider): # setup search attributes = [_.strip().format(**params) for _ in options['search-fields'].split(',')] - result = l.search(_get_subs(options, 'search-base', params), scope, _get_subs(options, 'search-filter', params), attributes) + result = l.search(_get_subs(options, 'search-base', params), scope, + _get_subs(options, 'search-filter', params), attributes) # parse results _, suser = l.result(result, 60) dn, attrs = suser[0] - log.debug(("AD dn: %s" % dn)) - log.debug(("AD Search attributes: %s" % attrs)) + log.debug(("LDAP dn: %s" % dn)) + log.debug(("LDAP Search attributes: %s" % attrs)) if hasattr(attrs, 'has_key'): for attr in attributes: if attr in attrs: @@ -77,8 +82,8 @@ class ActiveDirectory(AuthProvider): params[attr] = "" params['dn'] = dn except Exception: - log.exception('ACTIVEDIRECTORY Search Exception for User: %s' % username) - return (failure_mode, '') + log.exception('LDAP Search Exception for login: %s' % login) + return (failure_mode, '', '') # end search # bind as user to check their credentials @@ -89,17 +94,22 @@ class ActiveDirectory(AuthProvider): l.protocol_version = 3 l.simple_bind_s(_get_subs(options, 'bind-user', params), _get_subs(options, 'bind-password', params)) except Exception: - log.exception('ACTIVEDIRECTORY Authenticate Exception for User %s' % username) - return (failure_mode, '') + log.exception('LDAP Authentication Exception for login %s' % login) + return (failure_mode, '', '') - log.debug("User: %s, ACTIVEDIRECTORY: True" % (username)) - return (True, _get_subs(options, 'auto-register-username', params)) + log.debug("Login: %s, LDAP: True" % (login)) + return (True, + _get_subs(options, 'auto-register-email', params), + _get_subs(options, 'auto-register-username', params)) def authenticate_user(self, user, password, options): """ See abstract method documentation. """ - return self.authenticate(user.email, password, options)[0] + if _get_bool(options, 'login-use-username', False): + return self.authenticate(user.username, password, options)[0] + else: + return self.authenticate(user.email, password, options)[0] -__all__ = ['ActiveDirectory'] +__all__ = ['LDAPAD'] diff --git a/lib/galaxy/auth/providers/localdb.py b/lib/galaxy/auth/providers/localdb.py index 5f01e6e5208..718889acad0 100644 --- a/lib/galaxy/auth/providers/localdb.py +++ b/lib/galaxy/auth/providers/localdb.py @@ -13,11 +13,11 @@ class LocalDB(AuthProvider): """Authenticate users against the local Galaxy database (as per usual).""" plugin_type = 'localdb' - def authenticate(self, username, password, options): + def authenticate(self, login, password, options): """ See abstract method documentation. """ - return (False, '') # it can never auto-create based of localdb (chicken-egg) + return (False, '', '') # it can never auto-create based of localdb (chicken-egg) def authenticate_user(self, user, password, options): """ diff --git a/lib/galaxy/security/validate_user_input.py b/lib/galaxy/security/validate_user_input.py index 0c15cacdc01..96c676c89e0 100644 --- a/lib/galaxy/security/validate_user_input.py +++ b/lib/galaxy/security/validate_user_input.py @@ -37,7 +37,7 @@ def validate_email( trans, email, user=None, check_dup=True ): def validate_publicname( trans, publicname, user=None ): - # User names must be at least four characters in length and contain only lower-case + # User names must be at least three characters in length and contain only lower-case # letters, numbers, and the '-' character. if user and user.username == publicname: return '' @@ -45,7 +45,7 @@ def validate_publicname( trans, publicname, user=None ): if len( publicname ) < 3: return "Public name must be at least 3 characters in length" else: - if len( publicname ) < 4: + if len( publicname ) < 3: return "Public name must be at least 4 characters in length" if len( publicname ) > 255: return "Public name cannot be more than 255 characters in length" diff --git a/lib/galaxy/webapps/galaxy/controllers/mobile.py b/lib/galaxy/webapps/galaxy/controllers/mobile.py index 592d424046a..b0fa11cbd19 100644 --- a/lib/galaxy/webapps/galaxy/controllers/mobile.py +++ b/lib/galaxy/webapps/galaxy/controllers/mobile.py @@ -53,17 +53,21 @@ class Mobile( BaseUIController ): # trans.log_event( "User logged out" ) # trans.handle_user_logout() - def __login( self, trans, email="", password="" ): + def __login(self, trans, login="", password=""): return trans.response.send_redirect( web.url_for(controller='root', action='index' ) ) # error = password_error = None - # user = trans.sa_session.query( model.User ).filter_by( email = email ).first() + # user = trans.sa_session.query( model.User ).filter(or_( + # email == login, + # username == login + # )).first() # if not user: - # autoreg = galaxy.auth.check_auto_registration(trans, email, password, trans.app.config.auth_config_file) + # autoreg = galaxy.auth.check_auto_registration(trans, login, password, trans.app.config.auth_config_file) # if autoreg[0]: # kwd = {} - # kwd['username'] = autoreg[1] + # kwd['email'] = autoreg[1] + # kwd['username'] = autoreg[2] # params = util.Params( kwd ) - # message = validate_email( trans, email ) + # message = validate_email( trans, kwd['email'] ) # if not message: # message, status, user, success = self.__register( trans, 'user', False, **kwd ) # if success: diff --git a/lib/galaxy/webapps/galaxy/controllers/user.py b/lib/galaxy/webapps/galaxy/controllers/user.py index 6077e340672..bea04c02c2e 100644 --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -14,7 +14,7 @@ from datetime import datetime, timedelta from galaxy import model from galaxy import util from galaxy import web -from galaxy.model.orm import and_ +from galaxy.model.orm import and_, or_ from galaxy.security.validate_user_input import (transform_publicname, validate_email, validate_password, @@ -467,7 +467,7 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat status = kwd.get( 'status', 'done' ) header = '' user = trans.user - email = kwd.get( 'email', '' ) + login = kwd.get( 'login', '' ) if user: # Already logged in. redirect_url = redirect @@ -496,7 +496,7 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat else: header = REQUIRE_LOGIN_TEMPLATE % ( "Galaxy tool shed", "" ) return trans.fill_template( '/user/login.mako', - email=email, + login=login, header=header, use_panels=use_panels, redirect_url=redirect_url, @@ -510,21 +510,23 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat def __validate_login( self, trans, **kwd ): """Validates numerous cases that might happen during the login time.""" - message = escape( kwd.get( 'message', '' ) ) status = kwd.get( 'status', 'error' ) - email = kwd.get( 'email', '' ) + login = kwd.get( 'login', '' ) password = kwd.get( 'password', '' ) - username = kwd.get( 'username', '' ) redirect = kwd.get( 'redirect', trans.request.referer ).strip() success = False - user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email == email ).first() + user = trans.sa_session.query( trans.app.model.User ).filter(or_( + trans.app.model.User.table.c.email == login, + trans.app.model.User.table.c.username == login + )).first() log.debug("trans.app.config.auth_config_file: %s" % trans.app.config.auth_config_file) if not user: - autoreg = trans.app.auth_manager.check_auto_registration(trans, email, password) + autoreg = trans.app.auth_manager.check_auto_registration(trans, login, password) if autoreg[0]: - kwd['username'] = autoreg[1] + kwd['email'] = autoreg[1] + kwd['username'] = autoreg[2] params = util.Params( kwd ) - message = validate_email( trans, email ) #self.__validate( trans, params, email, password, password, username ) + message = validate_email( trans, kwd['email'] ) #self.__validate( trans, params, email, password, password, username ) if not message: message, status, user, success = self.__register( trans, 'user', False, **kwd ) if success: @@ -552,11 +554,11 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat elif trans.app.config.user_activation_on and not user.active: # activation is ON and the user is INACTIVE if ( trans.app.config.activation_grace_period != 0 ): # grace period is ON if self.is_outside_grace_period( trans, user.create_time ): # User is outside the grace period. Login is disabled and he will have the activation email resent. - message, status = self.resend_verification_email( trans, email, username ) + message, status = self.resend_verification_email( trans, user.email, user.username ) else: # User is within the grace period, let him log in. message, success, status = self.proceed_login( trans, user, redirect ) else: # Grace period is off. Login is disabled and user will have the activation email resent. - message, status = self.resend_verification_email( trans, email, username ) + message, status = self.resend_verification_email( trans, user.email, user.username ) else: # activation is OFF message, success, status = self.proceed_login( trans, user, redirect ) return ( message, status, user, success ) diff --git a/templates/user/login.mako b/templates/user/login.mako index 26358f5e062..91c58604597 100644 --- a/templates/user/login.mako +++ b/templates/user/login.mako @@ -80,8 +80,8 @@ def inherit(context):
Login
- - + +
From 204314a7801f362691519d7a039d6a2daa0371e0 Mon Sep 17 00:00:00 2001 From: David Trudgian Date: Fri, 3 Apr 2015 21:55:15 -0500 Subject: [PATCH 2/5] Fix some PEP8 complaints and comments --- lib/galaxy/auth/__init__.py | 13 +++++++------ lib/galaxy/auth/providers/__init__.py | 4 ++-- lib/galaxy/auth/providers/ldap_ad.py | 17 ++++++++++------- lib/galaxy/security/validate_user_input.py | 4 +++- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/lib/galaxy/auth/__init__.py b/lib/galaxy/auth/__init__.py index aa4efc6f498..ad2d2b6fcbd 100644 --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -27,16 +27,17 @@ log = logging.getLogger(__name__) # ldap://STUDENTS.ltu.edu.au # [(&(objectClass=user)(mail={login})) # dc=STUDENTS,dc=ltu,dc=edu,dc=au +# # jsmith # mysecret # sAMAccountName,mail] # {sAMAccountName}@STUDENTS.ltu.edu.au # {password} # {sAMAccountName} -# {mail} -# +# {mail} +# # # # ... @@ -48,7 +49,7 @@ class AuthManager(object): def __init__(self, app): self.__app = app import galaxy.auth.providers - self.__plugins_dict = plugin_config.plugins_dict( galaxy.auth.providers, 'plugin_type' ) + self.__plugins_dict = plugin_config.plugins_dict(galaxy.auth.providers, 'plugin_type' ) auth_config_file = app.config.auth_config_file self.__init_authenticators(auth_config_file) @@ -116,7 +117,7 @@ class AuthManager(object): log.debug( "Unable to find module: %s" % options ) else: auth_result, auto_email, auto_username = provider.authenticate(login, password, options) - auto_email = str(auto_email).lower() + auto_email = str(auto_email).lower() auto_username = str(auto_username).lower() if auth_result is True: # make username unique diff --git a/lib/galaxy/auth/providers/__init__.py b/lib/galaxy/auth/providers/__init__.py index 5552193f257..fd200c01db4 100644 --- a/lib/galaxy/auth/providers/__init__.py +++ b/lib/galaxy/auth/providers/__init__.py @@ -23,7 +23,7 @@ class AuthProvider(object): NOTE: Used within auto-registration to check it is ok to register this user. - :param login: the users email address + :param login: the user's email address or username :type login: str :param password: the plain text password they typed :type password: str @@ -44,7 +44,7 @@ class AuthProvider(object): NOTE: used on normal login to check authentication and update user details if required. - :param username: the users email address + :param username: the user's email address or username :type username: str :param password: the plain text password they typed :type password: str diff --git a/lib/galaxy/auth/providers/ldap_ad.py b/lib/galaxy/auth/providers/ldap_ad.py index 76986ca33dd..b4b6c87a8fd 100644 --- a/lib/galaxy/auth/providers/ldap_ad.py +++ b/lib/galaxy/auth/providers/ldap_ad.py @@ -8,7 +8,6 @@ import logging from galaxy.exceptions import ConfigurationError from ..providers import AuthProvider -from galaxy.util import string_as_bool from galaxy.auth import _get_bool log = logging.getLogger(__name__) @@ -21,6 +20,7 @@ def _get_subs(d, k, params): class LDAPAD(AuthProvider): + """ Attempts to authenticate users against an LDAP server. @@ -44,7 +44,8 @@ class LDAPAD(AuthProvider): try: import ldap except: - log.debug("Login: %s, LDAP: False (could not load ldap module)" % (login)) + log.debug( + "Login: %s, LDAP: False (could not load ldap module)" % (login)) return (failure_mode, '') # do LDAP search (if required) @@ -65,7 +66,8 @@ class LDAPAD(AuthProvider): scope = ldap.SCOPE_SUBTREE # setup search - attributes = [_.strip().format(**params) for _ in options['search-fields'].split(',')] + attributes = [_.strip().format(**params) + for _ in options['search-fields'].split(',')] result = l.search(_get_subs(options, 'search-base', params), scope, _get_subs(options, 'search-filter', params), attributes) @@ -92,7 +94,8 @@ class LDAPAD(AuthProvider): ldap.set_option(ldap.OPT_REFERRALS, 0) l = ldap.initialize(_get_subs(options, 'server', params)) l.protocol_version = 3 - l.simple_bind_s(_get_subs(options, 'bind-user', params), _get_subs(options, 'bind-password', params)) + l.simple_bind_s(_get_subs( + options, 'bind-user', params), _get_subs(options, 'bind-password', params)) except Exception: log.exception('LDAP Authentication Exception for login %s' % login) return (failure_mode, '', '') @@ -107,9 +110,9 @@ class LDAPAD(AuthProvider): See abstract method documentation. """ - if _get_bool(options, 'login-use-username', False): + if _get_bool(options, 'login-use-username', False): return self.authenticate(user.username, password, options)[0] - else: - return self.authenticate(user.email, password, options)[0] + else: + return self.authenticate(user.email, password, options)[0] __all__ = ['LDAPAD'] diff --git a/lib/galaxy/security/validate_user_input.py b/lib/galaxy/security/validate_user_input.py index 96c676c89e0..59cbb6a5640 100644 --- a/lib/galaxy/security/validate_user_input.py +++ b/lib/galaxy/security/validate_user_input.py @@ -45,8 +45,10 @@ def validate_publicname( trans, publicname, user=None ): if len( publicname ) < 3: return "Public name must be at least 3 characters in length" else: + # DCT - TODO - Simplify logic if 3 chars is okay for publicname for + # galaxy as well as toolshed if len( publicname ) < 3: - return "Public name must be at least 4 characters in length" + return "Public name must be at least 3 characters in length" if len( publicname ) > 255: return "Public name cannot be more than 255 characters in length" if not( VALID_PUBLICNAME_RE.match( publicname ) ): From 0cb2e7548faa1394f567d64fa6f0d14e2aaff9b9 Mon Sep 17 00:00:00 2001 From: David Trudgian Date: Fri, 3 Apr 2015 22:06:17 -0500 Subject: [PATCH 3/5] 3 char for username in user info and registration Assuming 3 character username is okay, update the info and registration forms. NB - username regex in register.mako already allowed 3 char. In info.mako was 4 char. --- templates/user/info.mako | 8 ++++---- templates/user/register.mako | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/templates/user/info.mako b/templates/user/info.mako index 7447085a722..5ecc1847c7a 100644 --- a/templates/user/info.mako +++ b/templates/user/info.mako @@ -9,7 +9,7 @@ function validateString(test_string, type) { var mail_re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; - var username_re = /^[a-z0-9\-]{4,255}$/; + var username_re = /^[a-z0-9\-]{3,255}$/; if (type === 'email') { return mail_re.test(test_string); } else if (type === 'username'){ @@ -47,7 +47,7 @@ $( '#login_info' ).bind( 'submit', function( e ) { var error_text_email= 'Please enter your valid email address.'; var error_text_email_long= 'Email cannot be more than 255 characters in length.'; - var error_text_username_characters = 'Public name must contain only lowercase letters, numbers and "-". It also has to be shorter than 255 characters but longer than 3.'; + var error_text_username_characters = 'Public name must contain only lowercase letters, numbers and "-". It also has to be shorter than 255 characters but longer than 2.'; var email = $( '#email_input' ).val(); var name = $( '#name_input' ).val(); var validForm = true; @@ -108,7 +108,7 @@
Your public name provides a means of identifying you publicly within this tool shed. Public - names must be at least four characters in length and contain only lower-case letters, numbers, + names must be at least three characters in length and contain only lower-case letters, numbers, and the '-' character. You cannot change your public name after you have created a repository in this tool shed.
@@ -117,7 +117,7 @@
Your public name is an optional identifier that will be used to generate addresses for information - you share publicly. Public names must be at least four characters in length and contain only lower-case + you share publicly. Public names must be at least three characters in length and contain only lower-case letters, numbers, and the '-' character.
%endif diff --git a/templates/user/register.mako b/templates/user/register.mako index 549d8f77d7b..68393e1b703 100644 --- a/templates/user/register.mako +++ b/templates/user/register.mako @@ -96,7 +96,7 @@ def inherit(context): var error_text_email= 'Please enter your valid email address'; var error_text_email_long= 'Email cannot be more than 255 characters in length'; - var error_text_username_characters = 'Public name must contain only lowercase letters, numbers and "-". It also has to be shorter than 255 characters but longer than 3.'; + var error_text_username_characters = 'Public name must contain only lowercase letters, numbers and "-". It also has to be shorter than 255 characters but longer than 2.'; var error_text_password_short = 'Please use a password of at least 6 characters'; var error_text_password_match = "Passwords don't match"; @@ -141,13 +141,13 @@ def inherit(context): %if t.webapp.name == 'galaxy':
Your public name is an identifier that will be used to generate addresses for information - you share publicly. Public names must be at least four characters in length and contain only lower-case + you share publicly. Public names must be at least three characters in length and contain only lower-case letters, numbers, and the '-' character.
%else:
Your public name provides a means of identifying you publicly within this tool shed. Public - names must be at least four characters in length and contain only lower-case letters, numbers, + names must be at least three characters in length and contain only lower-case letters, numbers, and the '-' character. You cannot change your public name after you have created a repository in this tool shed.
From 359dceabf83f7470c6766e2a19efd70c930d5df0 Mon Sep 17 00:00:00 2001 From: David Trudgian Date: Mon, 6 Apr 2015 14:31:06 -0500 Subject: [PATCH 4/5] Split LDAP from AD auth provider (in name only at present) Suggested and supplied by @jmchilton --- lib/galaxy/auth/providers/ldap_ad.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/galaxy/auth/providers/ldap_ad.py b/lib/galaxy/auth/providers/ldap_ad.py index b4b6c87a8fd..491fb0b26e7 100644 --- a/lib/galaxy/auth/providers/ldap_ad.py +++ b/lib/galaxy/auth/providers/ldap_ad.py @@ -19,7 +19,7 @@ def _get_subs(d, k, params): return str(d[k]).format(**params) -class LDAPAD(AuthProvider): +class LDAP(AuthProvider): """ Attempts to authenticate users against an LDAP server. @@ -28,7 +28,7 @@ class LDAPAD(AuthProvider): those fields first. After that it will bind to LDAP with the username (formatted as specified). """ - plugin_type = 'ldap_ad' + plugin_type = 'ldap' def authenticate(self, login, password, options): """ @@ -115,4 +115,10 @@ class LDAPAD(AuthProvider): else: return self.authenticate(user.email, password, options)[0] -__all__ = ['LDAPAD'] + +class ActiveDirectory(LDAP): + """ Effectively just an alias for LDAP auth, but may contain active directory specific + logic in the future. """ + plugin_type = 'activedirectory' + +__all__ = ['LDAP', 'ActiveDirectory'] From 42eb4837d8ab8e16fe3673d416d31c6f7ecfd46c Mon Sep 17 00:00:00 2001 From: David Trudgian Date: Mon, 6 Apr 2015 14:36:45 -0500 Subject: [PATCH 5/5] Missed PEP8 indent rule again - sorry --- lib/galaxy/auth/providers/ldap_ad.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/galaxy/auth/providers/ldap_ad.py b/lib/galaxy/auth/providers/ldap_ad.py index 491fb0b26e7..ef2dddb83b8 100644 --- a/lib/galaxy/auth/providers/ldap_ad.py +++ b/lib/galaxy/auth/providers/ldap_ad.py @@ -117,8 +117,8 @@ class LDAP(AuthProvider): class ActiveDirectory(LDAP): - """ Effectively just an alias for LDAP auth, but may contain active directory specific - logic in the future. """ - plugin_type = 'activedirectory' + """ Effectively just an alias for LDAP auth, but may contain active directory specific + logic in the future. """ + plugin_type = 'activedirectory' __all__ = ['LDAP', 'ActiveDirectory']