diff --git a/taiga/users/api.py b/taiga/users/api.py index d72d021d..20031395 100644 --- a/taiga/users/api.py +++ b/taiga/users/api.py @@ -35,7 +35,7 @@ from taiga.base.api.utils import get_object_or_404 from taiga.base.filters import MembersFilterBackend from taiga.base.mails import mail_builder from taiga.projects.votes import services as votes_service - +from taiga.users.services import get_user_by_username_or_email from easy_thumbnails.source_generators import pil_image from . import models @@ -145,13 +145,7 @@ class UsersViewSet(ModelCrudViewSet): if not username_or_email: raise exc.WrongArguments(_("Invalid username or email")) - try: - queryset = models.User.objects.all() - user = queryset.get(Q(username=username_or_email) | - Q(email=username_or_email)) - except models.User.DoesNotExist: - raise exc.WrongArguments(_("Invalid username or email")) - + user = get_user_by_username_or_email(username_or_email) user.token = str(uuid.uuid1()) user.save(update_fields=["token"]) diff --git a/taiga/users/services.py b/taiga/users/services.py index 3ef4672d..5dd8bc0f 100644 --- a/taiga/users/services.py +++ b/taiga/users/services.py @@ -37,6 +37,24 @@ from .gravatar import get_gravatar_url from django.conf import settings + +def get_user_by_username_or_email(username_or_email): + user_model = apps.get_model("users", "User") + qs = user_model.objects.filter(Q(username__iexact=username_or_email) | + Q(email__iexact=username_or_email)) + + if len(qs) > 1: + qs = qs.filter(Q(username=username_or_email) | + Q(email=username_or_email)) + + if len(qs) == 0: + raise exc.WrongArguments(_("Username or password does not matches user.")) + + user = qs[0] + return user + + + def get_and_validate_user(*, username:str, password:str) -> bool: """ Check if user with username/email exists and specified @@ -46,13 +64,7 @@ def get_and_validate_user(*, username:str, password:str) -> bool: exception is raised. """ - user_model = apps.get_model("users", "User") - qs = user_model.objects.filter(Q(username=username) | - Q(email=username)) - if len(qs) == 0: - raise exc.WrongArguments(_("Username or password does not matches user.")) - - user = qs[0] + user = get_user_by_username_or_email(username) if not user.check_password(password): raise exc.WrongArguments(_("Username or password does not matches user.")) diff --git a/tests/integration/test_auth_api.py b/tests/integration/test_auth_api.py index e7a7805a..02df17fa 100644 --- a/tests/integration/test_auth_api.py +++ b/tests/integration/test_auth_api.py @@ -106,3 +106,67 @@ def test_respond_400_if_username_or_email_is_duplicate(client, settings, registe register_form["email"] = "ff@dd.com" response = client.post(reverse("auth-register"), register_form) assert response.status_code == 400 + + +def test_auth_uppercase_ignore(client, settings): + settings.PUBLIC_REGISTER_ENABLED = True + + register_form = {"username": "Username", + "password": "password", + "full_name": "fname", + "email": "User@email.com", + "type": "public"} + response = client.post(reverse("auth-register"), register_form) + + #Only exists one user with the same lowercase version of username/password + login_form = {"type": "normal", + "username": "Username", + "password": "password"} + + response = client.post(reverse("auth-list"), login_form) + assert response.status_code == 200 + + login_form = {"type": "normal", + "username": "User@email.com", + "password": "password"} + + response = client.post(reverse("auth-list"), login_form) + assert response.status_code == 200 + + #Now we have two users with the same lowercase version of username/password + # 1.- The capitalized version works + register_form = {"username": "username", + "password": "password", + "full_name": "fname", + "email": "user@email.com", + "type": "public"} + response = client.post(reverse("auth-register"), register_form) + + login_form = {"type": "normal", + "username": "Username", + "password": "password"} + + response = client.post(reverse("auth-list"), login_form) + assert response.status_code == 200 + + login_form = {"type": "normal", + "username": "User@email.com", + "password": "password"} + + response = client.post(reverse("auth-list"), login_form) + assert response.status_code == 200 + + # 2.- If we capitalize a new version it doesn't + login_form = {"type": "normal", + "username": "uSername", + "password": "password"} + + response = client.post(reverse("auth-list"), login_form) + assert response.status_code == 400 + + login_form = {"type": "normal", + "username": "uSer@email.com", + "password": "password"} + + response = client.post(reverse("auth-list"), login_form) + assert response.status_code == 400