mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge pull request #216 from nsoranzo/release_15.05
[15.05] Fix AuthManager.active_authenticators(). Partially re...
This commit is contained in:
@@ -1,5 +1,35 @@
|
||||
<?xml version="1.0"?>
|
||||
<auth>
|
||||
<!--<authenticator>
|
||||
<type>ldap</type>
|
||||
-->
|
||||
<!-- Filter users for which this authenticator applies. This is a Python
|
||||
expression which is evaluated after replacing instances of {email}
|
||||
and {username} with the corresponding user's values. -->
|
||||
<!-- <filter>'{email}'.endswith('@example.com')</filter>
|
||||
<options>
|
||||
<auto-register>True</auto-register>
|
||||
<server>ldap://dc1.example.com</server>
|
||||
-->
|
||||
<!-- If search-fields is not present, all other search-* elements are ignored -->
|
||||
<!-- <search-fields>sAMAccountName,mail</search-fields>
|
||||
<search-filter>(&(objectClass=user)(mail={email}))</search-filter>
|
||||
<search-base>dc=dc1,dc=example,dc=com</search-base>
|
||||
-->
|
||||
<!-- If search-user not specified will bind anonymously to LDAP for search -->
|
||||
<!-- <search-user>jsmith</search-user>
|
||||
<search-password>mysecret</search-password>
|
||||
<bind-user>{sAMAccountName}@example.com</bind-user>
|
||||
<bind-password>{password}</bind-password>
|
||||
<auto-register-username>{sAMAccountName}</auto-register-username>
|
||||
<auto-register-email>{mail}</auto-register-email>
|
||||
-->
|
||||
<!-- To allow login with username instead of email, default is False -->
|
||||
<!-- <login-use-username>True</login-use-username>
|
||||
</options>
|
||||
</authenticator>
|
||||
-->
|
||||
|
||||
<authenticator>
|
||||
<type>localdb</type>
|
||||
<options>
|
||||
|
||||
+15
-34
@@ -18,31 +18,6 @@ from galaxy.util import plugin_config
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# <auth>
|
||||
# <authenticator>
|
||||
# <type>ldap</type>
|
||||
# <filter>'[login]'.endswith('@students.latrobe.edu.au')</filter>
|
||||
# <options>
|
||||
# <auto-register>True</auto-register>
|
||||
# <server>ldap://STUDENTS.ltu.edu.au</server>
|
||||
# [<search-filter>(&(objectClass=user)(mail={login}))</search-filter>
|
||||
# <search-base>dc=STUDENTS,dc=ltu,dc=edu,dc=au</search-base>
|
||||
# <!-- If search-user not specified will bind anonymously to LDAP for search -->
|
||||
# <search-user>jsmith</search-user>
|
||||
# <search-password>mysecret</search-password>
|
||||
# <search-fields>sAMAccountName,mail</search-fields>]
|
||||
# <bind-user>{sAMAccountName}@STUDENTS.ltu.edu.au</bind-user>
|
||||
# <bind-password>{password}</bind-password>
|
||||
# <auto-register-username>{sAMAccountName}</auto-register-username>
|
||||
# <auto-register-email>{mail}</auto-register-email>
|
||||
# <!-- To allow login with username instead of email
|
||||
# <login-use-username>True</login-use-username>
|
||||
# -->
|
||||
# </options>
|
||||
# </authenticator>
|
||||
# ...
|
||||
# </auth>
|
||||
|
||||
|
||||
class AuthManager(object):
|
||||
|
||||
@@ -85,14 +60,14 @@ class AuthManager(object):
|
||||
authenticators.append(authenticator)
|
||||
self.authenticators = authenticators
|
||||
|
||||
def check_registration_allowed(self, login, password):
|
||||
def check_registration_allowed(self, email, username, password):
|
||||
"""Checks if the provided email/username is allowed to register."""
|
||||
message = ''
|
||||
status = 'done'
|
||||
for provider, options in self.active_authenticators(login, password):
|
||||
for provider, options in self.active_authenticators(email, username, password):
|
||||
allow_reg = _get_tri_state(options, 'allow-register', True)
|
||||
if allow_reg is None: # i.e. challenge
|
||||
auth_result, msg = provider.authenticate(login, password, options)
|
||||
auth_result, msg = provider.authenticate(email, username, password, options)
|
||||
if auth_result is True:
|
||||
break
|
||||
if auth_result is None:
|
||||
@@ -112,11 +87,17 @@ class AuthManager(object):
|
||||
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(login, password):
|
||||
if '@' in login:
|
||||
email = login
|
||||
username = None
|
||||
else:
|
||||
email = None
|
||||
username = login
|
||||
for provider, options in self.active_authenticators(email, username, password):
|
||||
if provider is None:
|
||||
log.debug( "Unable to find module: %s" % options )
|
||||
else:
|
||||
auth_result, auto_email, auto_username = provider.authenticate(login, password, options)
|
||||
auth_result, auto_email, auto_username = provider.authenticate(email, username, password, options)
|
||||
auto_email = str(auto_email).lower()
|
||||
auto_username = str(auto_username).lower()
|
||||
if auth_result is True:
|
||||
@@ -139,7 +120,7 @@ class AuthManager(object):
|
||||
|
||||
def check_password(self, user, password):
|
||||
"""Checks the username/email and password using auth providers."""
|
||||
for provider, options in self.active_authenticators(user, password):
|
||||
for provider, options in self.active_authenticators(user.email, user.username, password):
|
||||
if provider is None:
|
||||
log.debug( "Unable to find module: %s" % options )
|
||||
else:
|
||||
@@ -154,7 +135,7 @@ class AuthManager(object):
|
||||
"""Checks that auth provider allows password changes and current_password
|
||||
matches.
|
||||
"""
|
||||
for provider, options in self.active_authenticators(user, current_password):
|
||||
for provider, options in self.active_authenticators(user.email, user.username, current_password):
|
||||
if provider is None:
|
||||
log.debug( "Unable to find module: %s" % options )
|
||||
else:
|
||||
@@ -168,7 +149,7 @@ class AuthManager(object):
|
||||
return (False, 'Password change not supported')
|
||||
return (False, 'Invalid current password')
|
||||
|
||||
def active_authenticators(self, login, password):
|
||||
def active_authenticators(self, email, username, password):
|
||||
"""Yields AuthProvider instances for the provided configfile that match the
|
||||
filters.
|
||||
"""
|
||||
@@ -176,7 +157,7 @@ class AuthManager(object):
|
||||
for authenticator in self.authenticators:
|
||||
filter_template = authenticator.filter_template
|
||||
if filter_template:
|
||||
filter_str = filter_template.format(login=login, password=password)
|
||||
filter_str = filter_template.format(email=email, username=username, password=password)
|
||||
passed_filter = eval(filter_str, {"__builtins__": None}, {'str': str})
|
||||
if not passed_filter:
|
||||
continue # skip to next
|
||||
|
||||
@@ -16,15 +16,17 @@ class AuthProvider(object):
|
||||
""" Short string providing labelling this plugin """
|
||||
|
||||
@abc.abstractmethod
|
||||
def authenticate(self, login, password, options):
|
||||
def authenticate(self, email, username, password, options):
|
||||
"""
|
||||
Check that the username and password are correct.
|
||||
Check that the user credentials are correct.
|
||||
|
||||
NOTE: Used within auto-registration to check it is ok to register this
|
||||
user.
|
||||
|
||||
:param login: the user's email address or username
|
||||
:type login: str
|
||||
:param email: the user's email address
|
||||
:type email: str
|
||||
:param username: the user's username
|
||||
:type username: str
|
||||
:param password: the plain text password they typed
|
||||
:type password: str
|
||||
:param options: options provided in auth_config_file
|
||||
@@ -44,8 +46,8 @@ class AuthProvider(object):
|
||||
NOTE: used on normal login to check authentication and update user
|
||||
details if required.
|
||||
|
||||
:param username: the user's email address or username
|
||||
:type username: str
|
||||
:param user: the user to authenticate
|
||||
:type user: galaxy.model.User
|
||||
:param password: the plain text password they typed
|
||||
:type password: str
|
||||
:param options: options provided in auth_config_file
|
||||
|
||||
@@ -16,7 +16,7 @@ class AlwaysReject(AuthProvider):
|
||||
"""
|
||||
plugin_type = 'alwaysreject'
|
||||
|
||||
def authenticate(self, login, password, options):
|
||||
def authenticate(self, email, username, password, options):
|
||||
"""
|
||||
See abstract method documentation.
|
||||
"""
|
||||
|
||||
@@ -30,26 +30,35 @@ class LDAP(AuthProvider):
|
||||
"""
|
||||
plugin_type = 'ldap'
|
||||
|
||||
def authenticate(self, login, password, options):
|
||||
def authenticate(self, email, username, password, options):
|
||||
"""
|
||||
See abstract method documentation.
|
||||
"""
|
||||
log.debug("Login: %s" % login)
|
||||
log.debug("Options: %s" % options)
|
||||
log.debug("LDAP authenticate: email is %s" % email)
|
||||
log.debug("LDAP authenticate: username is %s" % username)
|
||||
log.debug("LDAP authenticate: options are %s" % options)
|
||||
|
||||
failure_mode = False # reject but continue
|
||||
if options.get('continue-on-failure', 'False') == 'False':
|
||||
failure_mode = None # reject and do not continue
|
||||
|
||||
if _get_bool(options, 'login-use-username', False):
|
||||
if username is None:
|
||||
log.debug('LDAP authenticate: username must be used to login, cannot be None')
|
||||
return (failure_mode, '', '')
|
||||
else:
|
||||
if email is None:
|
||||
log.debug('LDAP authenticate: email must be used to login, cannot be None')
|
||||
return (failure_mode, '', '')
|
||||
|
||||
try:
|
||||
import ldap
|
||||
except:
|
||||
log.debug(
|
||||
"Login: %s, LDAP: False (could not load ldap module)" % (login))
|
||||
return (failure_mode, '')
|
||||
log.debug('LDAP authenticate: could not load ldap module')
|
||||
return (failure_mode, '', '')
|
||||
|
||||
# do LDAP search (if required)
|
||||
params = {'login': login, 'password': password}
|
||||
params = {'email': email, 'username': username, 'password': password}
|
||||
if 'search-fields' in options:
|
||||
try:
|
||||
# setup connection
|
||||
@@ -74,8 +83,8 @@ class LDAP(AuthProvider):
|
||||
# parse results
|
||||
_, suser = l.result(result, 60)
|
||||
dn, attrs = suser[0]
|
||||
log.debug(("LDAP dn: %s" % dn))
|
||||
log.debug(("LDAP Search attributes: %s" % attrs))
|
||||
log.debug(("LDAP authenticate: dn is %s" % dn))
|
||||
log.debug(("LDAP authenticate: search attributes are %s" % attrs))
|
||||
if hasattr(attrs, 'has_key'):
|
||||
for attr in attributes:
|
||||
if attr in attrs:
|
||||
@@ -84,7 +93,7 @@ class LDAP(AuthProvider):
|
||||
params[attr] = ""
|
||||
params['dn'] = dn
|
||||
except Exception:
|
||||
log.exception('LDAP Search Exception for login: %s' % login)
|
||||
log.exception('LDAP authenticate: search exception')
|
||||
return (failure_mode, '', '')
|
||||
# end search
|
||||
|
||||
@@ -97,10 +106,10 @@ class LDAP(AuthProvider):
|
||||
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)
|
||||
log.exception('LDAP authenticate: bind exception')
|
||||
return (failure_mode, '', '')
|
||||
|
||||
log.debug("Login: %s, LDAP: True" % (login))
|
||||
log.debug('LDAP authentication successful')
|
||||
return (True,
|
||||
_get_subs(options, 'auto-register-email', params),
|
||||
_get_subs(options, 'auto-register-username', params))
|
||||
@@ -109,11 +118,7 @@ class LDAP(AuthProvider):
|
||||
"""
|
||||
See abstract method documentation.
|
||||
"""
|
||||
|
||||
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]
|
||||
return self.authenticate(user.email, user.username, password, options)[0]
|
||||
|
||||
|
||||
class ActiveDirectory(LDAP):
|
||||
|
||||
@@ -13,7 +13,7 @@ class LocalDB(AuthProvider):
|
||||
"""Authenticate users against the local Galaxy database (as per usual)."""
|
||||
plugin_type = 'localdb'
|
||||
|
||||
def authenticate(self, login, password, options):
|
||||
def authenticate(self, email, username, password, options):
|
||||
"""
|
||||
See abstract method documentation.
|
||||
"""
|
||||
|
||||
@@ -678,7 +678,7 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat
|
||||
status = 'error'
|
||||
else:
|
||||
# check user is allowed to register
|
||||
message, status = trans.app.auth_manager.check_registration_allowed(email, password)
|
||||
message, status = trans.app.auth_manager.check_registration_allowed(email, username, password)
|
||||
if message == '':
|
||||
if not refresh_frames:
|
||||
if trans.webapp.name == 'galaxy':
|
||||
|
||||
Reference in New Issue
Block a user