🚸(email) we should ignore case when looking for existing emails
Our products mostly rely on email regardless of their case. Next step would be to normalize email to lower case when storing them in database (or sending them to dimail if not done yet).
This commit is contained in:
@@ -22,6 +22,7 @@ and this project adheres to
|
||||
|
||||
### Changed
|
||||
|
||||
- 🚸(email) we should ignore case when looking for existing emails #1056
|
||||
- 🏗️(core) migrate from pip to uv
|
||||
- ✨(front) add show invitations mails domains access #1040
|
||||
|
||||
|
||||
@@ -998,7 +998,7 @@ class BaseInvitation(BaseModel):
|
||||
super().clean()
|
||||
|
||||
# Check if a user already exists for the provided email
|
||||
if User.objects.filter(email=self.email).exists():
|
||||
if User.objects.filter(email__iexact=self.email).exists():
|
||||
raise EmailAlreadyKnownException
|
||||
|
||||
@property
|
||||
|
||||
@@ -17,6 +17,8 @@ from freezegun import freeze_time
|
||||
|
||||
from core import factories, models
|
||||
|
||||
from mailbox_manager.exceptions import EmailAlreadyKnownException
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
@@ -48,6 +50,17 @@ def test_models_invitations_team_required():
|
||||
factories.InvitationFactory(team=None)
|
||||
|
||||
|
||||
def test_models_invitations_email_case_insensitive_duplicate_check():
|
||||
"""The email validation should be case-insensitive when checking for existing users."""
|
||||
# Create a user with a lowercase email
|
||||
factories.UserFactory(email="john.doe@example.com")
|
||||
|
||||
# Try to create an invitation with different case
|
||||
# This should raise the same exception as if the email was exactly the same
|
||||
with pytest.raises(EmailAlreadyKnownException):
|
||||
factories.InvitationFactory(email="John.Doe@Example.COM")
|
||||
|
||||
|
||||
def test_models_invitations_team_should_be_team_instance():
|
||||
"""The "team" field should be a team instance."""
|
||||
with pytest.raises(ValueError, match='Invitation.team" must be a "Team" instance'):
|
||||
|
||||
@@ -419,7 +419,7 @@ class MailDomainInvitationViewset(
|
||||
try:
|
||||
return super().create(request, *args, **kwargs)
|
||||
except EmailAlreadyKnownException as exc:
|
||||
user = models.User.objects.get(email=email)
|
||||
user = models.User.objects.get(email__iexact=email)
|
||||
|
||||
models.MailDomainAccess.objects.create(
|
||||
user=user,
|
||||
|
||||
@@ -158,3 +158,40 @@ def test_api_domain_invitations__inviting_known_email_should_create_access():
|
||||
|
||||
assert not models.MailDomainInvitation.objects.exists()
|
||||
assert models.MailDomainAccess.objects.filter(user=existing_user).exists()
|
||||
|
||||
|
||||
def test_api_domain_invitations__inviting_known_email_case_insensitive():
|
||||
"""Email matching should be case-insensitive when creating access for existing users."""
|
||||
# Create a user with lowercase email
|
||||
existing_user = core_factories.UserFactory(email="john.doe@example.com")
|
||||
access = factories.MailDomainAccessFactory(role=enums.MailDomainRoleChoices.OWNER)
|
||||
|
||||
client = APIClient()
|
||||
client.force_login(access.user)
|
||||
|
||||
# Try to invite with same email different case - should create access for existing user
|
||||
response = client.post(
|
||||
f"/api/v1.0/mail-domains/{access.domain.slug}/invitations/",
|
||||
{
|
||||
"email": "John.Doe@Example.COM",
|
||||
"role": "owner",
|
||||
},
|
||||
format="json",
|
||||
)
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
assert (
|
||||
response.json()["detail"]
|
||||
== "Email already known. Invitation not sent but access created instead."
|
||||
)
|
||||
|
||||
# No invitation should be created
|
||||
assert not models.MailDomainInvitation.objects.exists()
|
||||
|
||||
# Access should be created for the existing user (not a new user)
|
||||
assert models.MailDomainAccess.objects.filter(user=existing_user).exists()
|
||||
assert models.MailDomainAccess.objects.filter(
|
||||
user=existing_user, domain=access.domain
|
||||
).exists()
|
||||
|
||||
# Ensure only one user exists (no duplicate user created)
|
||||
assert models.User.objects.filter(email__iexact="john.doe@example.com").count() == 1
|
||||
|
||||
Reference in New Issue
Block a user