From 7c906de42727bd5ed6af789332adea558f050a83 Mon Sep 17 00:00:00 2001 From: Matt Wright Date: Thu, 1 Aug 2013 16:22:28 -0400 Subject: [PATCH] When logging in user lookups on email should be case insensitive --- flask_security/datastore.py | 27 +++++++++++++++++++++++++++ flask_security/forms.py | 2 +- tests/functional_tests.py | 4 ++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/flask_security/datastore.py b/flask_security/datastore.py index bbaecd9..28a91e4 100644 --- a/flask_security/datastore.py +++ b/flask_security/datastore.py @@ -82,6 +82,10 @@ class UserDatastore(object): kwargs['roles'] = roles return kwargs + def get_user(self, id_or_email): + """Returns a user matching the specified ID or email address""" + raise NotImplementedError + def find_user(self, *args, **kwargs): """Returns a user matching the provided parameters.""" raise NotImplementedError @@ -175,6 +179,11 @@ class SQLAlchemyUserDatastore(SQLAlchemyDatastore, UserDatastore): SQLAlchemyDatastore.__init__(self, db) UserDatastore.__init__(self, user_model, role_model) + def get_user(self, id_or_email): + return (self.user_model.query.get(id_or_email) or + self.user_model.query.filter( + self.user_model.email.ilike(id_or_email)).first()) + def find_user(self, **kwargs): return self.user_model.query.filter_by(**kwargs).first() @@ -190,6 +199,13 @@ class MongoEngineUserDatastore(MongoEngineDatastore, UserDatastore): MongoEngineDatastore.__init__(self, db) UserDatastore.__init__(self, user_model, role_model) + def get_user(self, id_or_email): + from mongoengine import ValidationError + try: + return self.user_model.objects(id=id_or_email).first() + except ValidationError: + return self.user_model.objects(email__iexact=id_or_email).first() + def find_user(self, **kwargs): try: from mongoengine.queryset import Q, QCombination @@ -217,6 +233,17 @@ class PeeweeUserDatastore(PeeweeDatastore, UserDatastore): UserDatastore.__init__(self, user_model, role_model) self.UserRole = role_link + def get_user(self, id_or_email): + try: + return self.user_model.get(self.user_model.id == id_or_email) + except ValueError: + pass + try: + return self.user_model.get(self.user_model.email ** id_or_email) + except self.user_model.DoesNotExist: + pass + return None + def find_user(self, **kwargs): try: return self.user_model.filter(**kwargs).get() diff --git a/flask_security/forms.py b/flask_security/forms.py index 57ab4e7..0c1bd70 100644 --- a/flask_security/forms.py +++ b/flask_security/forms.py @@ -219,7 +219,7 @@ class LoginForm(Form, NextFormMixin): self.password.errors.append(get_message('PASSWORD_NOT_PROVIDED')[0]) return False - self.user = _datastore.find_user(email=self.email.data) + self.user = _datastore.get_user(self.email.data) if self.user is None: self.email.errors.append(get_message('USER_DOES_NOT_EXIST')[0]) diff --git a/tests/functional_tests.py b/tests/functional_tests.py index 85087e2..90263e9 100644 --- a/tests/functional_tests.py +++ b/tests/functional_tests.py @@ -33,6 +33,10 @@ class DefaultSecurityTests(SecurityTest): r = self.authenticate() self.assertIn('Hello matt@lp.com', r.data) + def test_authenticate_case_insensitive_email(self): + r = self.authenticate(email='MATT@lp.com') + self.assertIn('Hello matt@lp.com', r.data) + def test_unprovided_username(self): r = self.authenticate("") self.assertIn(self.get_message('EMAIL_NOT_PROVIDED'), r.data)