diff --git a/taiga/auth/services.py b/taiga/auth/services.py index 26f3d0db..dee8c606 100644 --- a/taiga/auth/services.py +++ b/taiga/auth/services.py @@ -34,6 +34,7 @@ from djmail.template_mail import MagicMailBuilder from taiga.base import exceptions as exc from taiga.users.serializers import UserSerializer from taiga.users.services import get_and_validate_user +from taiga.base.utils.slug import slugify_uniquely from .tokens import get_token_for_user from .signals import user_registered as user_registered_signal @@ -50,7 +51,7 @@ def send_register_email(user) -> bool: return bool(email.send()) -def is_user_already_registered(*, username:str, email:str, github_id:int=None) -> (bool, str): +def is_user_already_registered(*, username:str, email:str) -> (bool, str): """ Checks if a specified user is already registred. @@ -65,9 +66,6 @@ def is_user_already_registered(*, username:str, email:str, github_id:int=None) - if user_model.objects.filter(email=email): return (True, _("Email is already in use.")) - if github_id and user_model.objects.filter(github_id=github_id): - return (True, _("GitHub id is already in use")) - return (False, None) @@ -182,20 +180,33 @@ def github_register(username:str, email:str, full_name:str, github_id:int, bio:s :returns: User """ user_model = apps.get_model("users", "User") - user, created = user_model.objects.get_or_create(github_id=github_id, - defaults={"username": username, - "email": email, - "full_name": full_name, - "bio": bio}) + + try: + # Github user association exist? + user = user_model.objects.get(github_id=github_id) + except user_model.DoesNotExist: + try: + # Is a user with the same email as the github user? + user = user_model.objects.get(email=email) + user.github_id = github_id + user.save(update_fields=["github_id"]) + except user_model.DoesNotExist: + # Create a new user + username_unique = slugify_uniquely(username, user_model, slugfield="username") + user = user_model.objects.create(email=email, + username=username_unique, + github_id=github_id, + full_name=full_name, + bio=bio) + + send_register_email(user) + user_registered_signal.send(sender=user.__class__, user=user) + if token: membership = get_membership_by_token(token) membership.user = user membership.save(update_fields=["user"]) - if created: - send_register_email(user) - user_registered_signal.send(sender=user.__class__, user=user) - return user diff --git a/tests/integration/test_auth_api.py b/tests/integration/test_auth_api.py index 60dced10..d322fa32 100644 --- a/tests/integration/test_auth_api.py +++ b/tests/integration/test_auth_api.py @@ -115,6 +115,78 @@ def test_response_200_in_registration_with_github_account(client, settings): assert response.data["bio"] == "time traveler" assert response.data["github_id"] == 1955 +def test_response_200_in_registration_with_github_account_and_existed_user_by_email(client, settings): + settings.PUBLIC_REGISTER_ENABLED = False + form = {"type": "github", + "code": "xxxxxx"} + user = factories.UserFactory() + user.email = "mmcfly@bttf.com" + user.github_id = None + user.save() + + with patch("taiga.base.connectors.github.me") as m_me: + m_me.return_value = ("mmcfly@bttf.com", + github.User(id=1955, + username="mmcfly", + full_name="martin seamus mcfly", + bio="time traveler")) + + response = client.post(reverse("auth-list"), form) + assert response.status_code == 200 + assert response.data["username"] == user.username + assert response.data["auth_token"] != "" and response.data["auth_token"] != None + assert response.data["email"] == user.email + assert response.data["full_name"] == user.full_name + assert response.data["bio"] == user.bio + assert response.data["github_id"] == 1955 + +def test_response_200_in_registration_with_github_account_and_existed_user_by_github_id(client, settings): + settings.PUBLIC_REGISTER_ENABLED = False + form = {"type": "github", + "code": "xxxxxx"} + user = factories.UserFactory() + user.github_id = 1955 + user.save() + + with patch("taiga.base.connectors.github.me") as m_me: + m_me.return_value = ("mmcfly@bttf.com", + github.User(id=1955, + username="mmcfly", + full_name="martin seamus mcfly", + bio="time traveler")) + + response = client.post(reverse("auth-list"), form) + assert response.status_code == 200 + assert response.data["username"] != "mmcfly" + assert response.data["auth_token"] != "" and response.data["auth_token"] != None + assert response.data["email"] != "mmcfly@bttf.com" + assert response.data["full_name"] != "martin seamus mcfly" + assert response.data["bio"] != "time traveler" + assert response.data["github_id"] == user.github_id + +def test_response_200_in_registration_with_github_account_and_change_github_username(client, settings): + settings.PUBLIC_REGISTER_ENABLED = False + form = {"type": "github", + "code": "xxxxxx"} + user = factories.UserFactory() + user.username = "mmcfly" + user.save() + + with patch("taiga.base.connectors.github.me") as m_me: + m_me.return_value = ("mmcfly@bttf.com", + github.User(id=1955, + username="mmcfly", + full_name="martin seamus mcfly", + bio="time traveler")) + + response = client.post(reverse("auth-list"), form) + assert response.status_code == 200 + assert response.data["username"] == "mmcfly-1" + assert response.data["auth_token"] != "" and response.data["auth_token"] != None + assert response.data["email"] == "mmcfly@bttf.com" + assert response.data["full_name"] == "martin seamus mcfly" + assert response.data["bio"] == "time traveler" + assert response.data["github_id"] == 1955 def test_response_200_in_registration_with_github_account_in_a_project(client, settings): settings.PUBLIC_REGISTER_ENABLED = False @@ -171,7 +243,6 @@ def test_respond_400_if_username_or_email_is_duplicate(client, settings, registe response = client.post(reverse("auth-register"), register_form) assert response.status_code == 201 - register_form["username"] = "username" register_form["email"] = "ff@dd.com" response = client.post(reverse("auth-register"), register_form)