Skip to content

Commit 590b67f

Browse files
committed
🐛(backend) filter invitation with case insensitive email
A user can be invited and no control is made on the email case. Then, when a new user is created, we are looking if there are pending invitation and the lookup used is case sensitive. We change it using __iexact which is case insensitive.
1 parent b3980e7 commit 590b67f

File tree

3 files changed

+33
-2
lines changed

3 files changed

+33
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ and this project adheres to
4343
- 🐛(frontend) fix attachment download filename #1447
4444
- 🐛(frontend) exclude h4-h6 headings from table of contents #1441
4545
- 🔒(frontend) prevent readers from changing callout emoji #1449
46+
- 🐛(backend) filter invitation with case insensitive email
4647

4748
## [3.7.0] - 2025-09-12
4849

src/backend/core/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ def _convert_valid_invitations(self):
221221
Expired invitations are ignored.
222222
"""
223223
valid_invitations = Invitation.objects.filter(
224-
email=self.email,
224+
email__iexact=self.email,
225225
created_at__gte=(
226226
timezone.now()
227227
- timedelta(seconds=settings.INVITATION_VALIDITY_DURATION)

src/backend/core/tests/test_models_users.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import pytest
1010

11-
from core import factories
11+
from core import factories, models
1212

1313
pytestmark = pytest.mark.django_db
1414

@@ -66,3 +66,33 @@ def test_models_users_sub_validator(sub, is_valid):
6666
match=("Enter a valid sub. This value should be ASCII only."),
6767
):
6868
user.full_clean()
69+
70+
71+
def test_modes_users_convert_valid_invitations():
72+
"""
73+
The "convert_valid_invitations" method should convert valid invitations to document accesses.
74+
"""
75+
76+
document = factories.DocumentFactory()
77+
other_document = factories.DocumentFactory()
78+
invitation_document = factories.InvitationFactory(email=email, document=document)
79+
invitation_other_document = factories.InvitationFactory(
80+
email="[email protected]", document=other_document
81+
)
82+
other_email_invitation = factories.InvitationFactory(
83+
email="[email protected]", document=document
84+
)
85+
86+
assert document.accesses.count() == 0
87+
assert other_document.accesses.count() == 0
88+
89+
user = factories.UserFactory(email=email)
90+
91+
assert document.accesses.filter(user=user).count() == 1
92+
assert other_document.accesses.filter(user=user).count() == 1
93+
94+
assert not models.Invitation.objects.filter(id=invitation_document.id).exists()
95+
assert not models.Invitation.objects.filter(
96+
id=invitation_other_document.id
97+
).exists()
98+
assert models.Invitation.objects.filter(id=other_email_invitation.id).exists()

0 commit comments

Comments
 (0)