Add support for linking to external users in entity search
This commit is contained in:
parent
845d1795a3
commit
d145222812
8 changed files with 156 additions and 15 deletions
|
@ -139,6 +139,31 @@ class UserAuthentication(object):
|
|||
|
||||
return data.get('password', encrypted)
|
||||
|
||||
@property
|
||||
def federated_service(self):
|
||||
""" Returns the name of the federated service for the auth system. If none, should return None.
|
||||
"""
|
||||
return self.state.federated_service
|
||||
|
||||
def query_users(self, query, limit=20):
|
||||
""" Performs a lookup against the user system for the specified query. The returned tuple
|
||||
will be of the form (results, federated_login_id, err_msg). If the method is unsupported,
|
||||
the results portion of the tuple will be None instead of empty list.
|
||||
|
||||
Note that this method can and will return results for users not yet found within the
|
||||
database; it is the responsibility of the caller to call link_user if they need the
|
||||
database row for the user system record.
|
||||
|
||||
Results will be in the form of objects's with username and email fields.
|
||||
"""
|
||||
return self.state.query_users(query, limit)
|
||||
|
||||
def link_user(self, username_or_email):
|
||||
""" Returns a tuple containing the database user record linked to the given username/email
|
||||
and any error that occurred when trying to link the user.
|
||||
"""
|
||||
return self.state.link_user(username_or_email)
|
||||
|
||||
def confirm_existing_user(self, username, password):
|
||||
""" Verifies that the given password matches to the given DB username. Unlike
|
||||
verify_credentials, this call first translates the DB user via the FederatedLogin table
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
from data import model
|
||||
|
||||
class DatabaseUsers(object):
|
||||
@property
|
||||
def federated_service(self):
|
||||
return None
|
||||
|
||||
def verify_credentials(self, username_or_email, password):
|
||||
""" Simply delegate to the model implementation. """
|
||||
result = model.user.verify_user(username_or_email, password)
|
||||
|
@ -16,3 +20,11 @@ class DatabaseUsers(object):
|
|||
def confirm_existing_user(self, username, password):
|
||||
return self.verify_credentials(username, password)
|
||||
|
||||
def link_user(self, username_or_email):
|
||||
""" Never used since all users being added are already, by definition, in the database. """
|
||||
return (None, 'Unsupported for this authentication system')
|
||||
|
||||
def query_users(self, query, limit):
|
||||
""" No need to implement, as we already query for users directly in the database. """
|
||||
return (None, '', '')
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ from util.validation import generate_valid_usernames
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
VerifiedCredentials = namedtuple('VerifiedCredentials', ['username', 'email'])
|
||||
UserInformation = namedtuple('UserInformation', ['username', 'email', 'id'])
|
||||
|
||||
class FederatedUsers(object):
|
||||
""" Base class for all federated users systems. """
|
||||
|
@ -15,11 +15,26 @@ class FederatedUsers(object):
|
|||
def __init__(self, federated_service):
|
||||
self._federated_service = federated_service
|
||||
|
||||
@property
|
||||
def federated_service(self):
|
||||
return self._federated_service
|
||||
|
||||
def get_user(self, username_or_email):
|
||||
""" Retrieves the user with the given username or email, returning a tuple containing
|
||||
a UserInformation (if success) and the error message (on failure).
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def verify_credentials(self, username_or_email, password):
|
||||
""" Verifies the given credentials against the backing federated service, returning
|
||||
a tuple containing a VerifiedCredentials (if success) and the error message (if failed). """
|
||||
a tuple containing a UserInformation (on success) and the error message (on failure).
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def query_users(self, query, limit=20):
|
||||
""" If implemented, get_user must be implemented as well. """
|
||||
return (None, 'Not supported')
|
||||
|
||||
def _get_federated_user(self, username, email):
|
||||
db_user = model.user.verify_federated_login(self._federated_service, username)
|
||||
if not db_user:
|
||||
|
@ -34,7 +49,8 @@ class FederatedUsers(object):
|
|||
return (None, 'Unable to pick a username. Please report this to your administrator.')
|
||||
|
||||
db_user = model.user.create_federated_user(valid_username, email, self._federated_service,
|
||||
username, set_password_notification=False)
|
||||
username,
|
||||
set_password_notification=False)
|
||||
else:
|
||||
# Update the db attributes from the federated service.
|
||||
db_user.email = email
|
||||
|
@ -42,6 +58,13 @@ class FederatedUsers(object):
|
|||
|
||||
return (db_user, None)
|
||||
|
||||
def link_user(self, username_or_email):
|
||||
(credentials, err_msg) = self.get_user(username_or_email)
|
||||
if credentials is None:
|
||||
return (None, err_msg)
|
||||
|
||||
return self._get_federated_user(credentials.username, credentials.email)
|
||||
|
||||
def verify_and_link_user(self, username_or_email, password):
|
||||
""" Verifies the given credentials and, if valid, creates/links a database user to the
|
||||
associated federated service.
|
||||
|
|
Reference in a new issue