🔨(backend) email invitation in invited user's language
- language for invitation emails => language saved on the invited user - if invited user does not exist yet => language of the sending user - if for some reason no sending user => system default language
This commit is contained in:
@@ -1167,13 +1167,14 @@ class DocumentAccessViewSet(
|
|||||||
def perform_create(self, serializer):
|
def perform_create(self, serializer):
|
||||||
"""Add a new access to the document and send an email to the new added user."""
|
"""Add a new access to the document and send an email to the new added user."""
|
||||||
access = serializer.save()
|
access = serializer.save()
|
||||||
language = self.request.headers.get("Content-Language", "en-us")
|
|
||||||
|
|
||||||
access.document.send_invitation_email(
|
access.document.send_invitation_email(
|
||||||
access.user.email,
|
access.user.email,
|
||||||
access.role,
|
access.role,
|
||||||
self.request.user,
|
self.request.user,
|
||||||
language,
|
access.user.language
|
||||||
|
or self.request.user.language
|
||||||
|
or settings.LANGUAGE_CODE,
|
||||||
)
|
)
|
||||||
|
|
||||||
def perform_update(self, serializer):
|
def perform_update(self, serializer):
|
||||||
@@ -1399,10 +1400,11 @@ class InvitationViewset(
|
|||||||
"""Save invitation to a document then send an email to the invited user."""
|
"""Save invitation to a document then send an email to the invited user."""
|
||||||
invitation = serializer.save()
|
invitation = serializer.save()
|
||||||
|
|
||||||
language = self.request.headers.get("Content-Language", "en-us")
|
|
||||||
|
|
||||||
invitation.document.send_invitation_email(
|
invitation.document.send_invitation_email(
|
||||||
invitation.email, invitation.role, self.request.user, language
|
invitation.email,
|
||||||
|
invitation.role,
|
||||||
|
self.request.user,
|
||||||
|
self.request.user.language or settings.LANGUAGE_CODE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ from core.tests.conftest import TEAM, USER, VIA
|
|||||||
pytestmark = pytest.mark.django_db
|
pytestmark = pytest.mark.django_db
|
||||||
|
|
||||||
|
|
||||||
|
# Create
|
||||||
|
|
||||||
|
|
||||||
def test_api_document_accesses_create_anonymous():
|
def test_api_document_accesses_create_anonymous():
|
||||||
"""Anonymous users should not be allowed to create document accesses."""
|
"""Anonymous users should not be allowed to create document accesses."""
|
||||||
document = factories.DocumentFactory()
|
document = factories.DocumentFactory()
|
||||||
@@ -123,7 +126,7 @@ def test_api_document_accesses_create_authenticated_administrator(via, mock_user
|
|||||||
document=document, team="lasuite", role="administrator"
|
document=document, team="lasuite", role="administrator"
|
||||||
)
|
)
|
||||||
|
|
||||||
other_user = factories.UserFactory()
|
other_user = factories.UserFactory(language="en-us")
|
||||||
|
|
||||||
# It should not be allowed to create an owner access
|
# It should not be allowed to create an owner access
|
||||||
response = client.post(
|
response = client.post(
|
||||||
@@ -199,7 +202,7 @@ def test_api_document_accesses_create_authenticated_owner(via, mock_user_teams):
|
|||||||
document=document, team="lasuite", role="owner"
|
document=document, team="lasuite", role="owner"
|
||||||
)
|
)
|
||||||
|
|
||||||
other_user = factories.UserFactory()
|
other_user = factories.UserFactory(language="en-us")
|
||||||
|
|
||||||
role = random.choice([role[0] for role in models.RoleChoices.choices])
|
role = random.choice([role[0] for role in models.RoleChoices.choices])
|
||||||
|
|
||||||
@@ -235,3 +238,73 @@ def test_api_document_accesses_create_authenticated_owner(via, mock_user_teams):
|
|||||||
f"on the following document: {document.title}"
|
f"on the following document: {document.title}"
|
||||||
) in email_content
|
) in email_content
|
||||||
assert "docs/" + str(document.id) + "/" in email_content
|
assert "docs/" + str(document.id) + "/" in email_content
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("via", VIA)
|
||||||
|
def test_api_document_accesses_create_email_in_receivers_language(via, mock_user_teams):
|
||||||
|
"""
|
||||||
|
The email sent to the accesses to notify them of the adding, should be in their language.
|
||||||
|
"""
|
||||||
|
user = factories.UserFactory()
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
document = factories.DocumentFactory()
|
||||||
|
if via == USER:
|
||||||
|
factories.UserDocumentAccessFactory(document=document, user=user, role="owner")
|
||||||
|
elif via == TEAM:
|
||||||
|
mock_user_teams.return_value = ["lasuite", "unknown"]
|
||||||
|
factories.TeamDocumentAccessFactory(
|
||||||
|
document=document, team="lasuite", role="owner"
|
||||||
|
)
|
||||||
|
|
||||||
|
role = random.choice([role[0] for role in models.RoleChoices.choices])
|
||||||
|
|
||||||
|
assert len(mail.outbox) == 0
|
||||||
|
|
||||||
|
other_users = (
|
||||||
|
factories.UserFactory(language="en-us"),
|
||||||
|
factories.UserFactory(language="fr-fr"),
|
||||||
|
)
|
||||||
|
|
||||||
|
for index, other_user in enumerate(other_users):
|
||||||
|
expected_language = other_user.language
|
||||||
|
response = client.post(
|
||||||
|
f"/api/v1.0/documents/{document.id!s}/accesses/",
|
||||||
|
{
|
||||||
|
"user_id": str(other_user.id),
|
||||||
|
"role": role,
|
||||||
|
},
|
||||||
|
format="json",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 201
|
||||||
|
assert models.DocumentAccess.objects.filter(user=other_user).count() == 1
|
||||||
|
new_document_access = models.DocumentAccess.objects.filter(
|
||||||
|
user=other_user
|
||||||
|
).get()
|
||||||
|
other_user_data = serializers.UserSerializer(instance=other_user).data
|
||||||
|
assert response.json() == {
|
||||||
|
"id": str(new_document_access.id),
|
||||||
|
"user": other_user_data,
|
||||||
|
"team": "",
|
||||||
|
"role": role,
|
||||||
|
"abilities": new_document_access.get_abilities(user),
|
||||||
|
}
|
||||||
|
assert len(mail.outbox) == index + 1
|
||||||
|
email = mail.outbox[index]
|
||||||
|
assert email.to == [other_user_data["email"]]
|
||||||
|
email_content = " ".join(email.body.split())
|
||||||
|
email_subject = " ".join(email.subject.split())
|
||||||
|
if expected_language == "en-us":
|
||||||
|
assert (
|
||||||
|
f"{user.full_name} shared a document with you: {document.title}".lower()
|
||||||
|
in email_subject.lower()
|
||||||
|
)
|
||||||
|
elif expected_language == "fr-fr":
|
||||||
|
assert (
|
||||||
|
f"{user.full_name} a partagé un document avec vous: {document.title}".lower()
|
||||||
|
in email_subject.lower()
|
||||||
|
)
|
||||||
|
assert "docs/" + str(document.id) + "/" in email_content.lower()
|
||||||
|
|||||||
@@ -370,7 +370,7 @@ def test_api_document_invitations_create_privileged_members(
|
|||||||
Only owners and administrators should be able to invite new users.
|
Only owners and administrators should be able to invite new users.
|
||||||
Only owners can invite owners.
|
Only owners can invite owners.
|
||||||
"""
|
"""
|
||||||
user = factories.UserFactory()
|
user = factories.UserFactory(language="en-us")
|
||||||
document = factories.DocumentFactory()
|
document = factories.DocumentFactory()
|
||||||
if via == USER:
|
if via == USER:
|
||||||
factories.UserDocumentAccessFactory(document=document, user=user, role=inviting)
|
factories.UserDocumentAccessFactory(document=document, user=user, role=inviting)
|
||||||
@@ -422,11 +422,11 @@ def test_api_document_invitations_create_privileged_members(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_api_document_invitations_create_email_from_content_language():
|
def test_api_document_invitations_create_email_from_senders_language():
|
||||||
"""
|
"""
|
||||||
The email generated is from the language set in the Content-Language header
|
When inviting on a document a user who does not exist yet in our database, the invitation email should be sent in the language of the sending user.
|
||||||
"""
|
"""
|
||||||
user = factories.UserFactory()
|
user = factories.UserFactory(language="fr-fr")
|
||||||
document = factories.DocumentFactory()
|
document = factories.DocumentFactory()
|
||||||
factories.UserDocumentAccessFactory(document=document, user=user, role="owner")
|
factories.UserDocumentAccessFactory(document=document, user=user, role="owner")
|
||||||
|
|
||||||
@@ -444,7 +444,6 @@ def test_api_document_invitations_create_email_from_content_language():
|
|||||||
f"/api/v1.0/documents/{document.id!s}/invitations/",
|
f"/api/v1.0/documents/{document.id!s}/invitations/",
|
||||||
invitation_values,
|
invitation_values,
|
||||||
format="json",
|
format="json",
|
||||||
headers={"Content-Language": "fr-fr"},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
assert response.status_code == 201
|
assert response.status_code == 201
|
||||||
@@ -464,50 +463,11 @@ def test_api_document_invitations_create_email_from_content_language():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_api_document_invitations_create_email_from_content_language_not_supported():
|
|
||||||
"""
|
|
||||||
If the language from the Content-Language is not supported
|
|
||||||
it will display the default language, English.
|
|
||||||
"""
|
|
||||||
user = factories.UserFactory()
|
|
||||||
document = factories.DocumentFactory()
|
|
||||||
factories.UserDocumentAccessFactory(document=document, user=user, role="owner")
|
|
||||||
|
|
||||||
invitation_values = {
|
|
||||||
"email": "guest@example.com",
|
|
||||||
"role": "reader",
|
|
||||||
}
|
|
||||||
|
|
||||||
assert len(mail.outbox) == 0
|
|
||||||
|
|
||||||
client = APIClient()
|
|
||||||
client.force_login(user)
|
|
||||||
|
|
||||||
response = client.post(
|
|
||||||
f"/api/v1.0/documents/{document.id!s}/invitations/",
|
|
||||||
invitation_values,
|
|
||||||
format="json",
|
|
||||||
headers={"Content-Language": "not-supported"},
|
|
||||||
)
|
|
||||||
|
|
||||||
assert response.status_code == 201
|
|
||||||
assert response.json()["email"] == "guest@example.com"
|
|
||||||
assert models.Invitation.objects.count() == 1
|
|
||||||
assert len(mail.outbox) == 1
|
|
||||||
|
|
||||||
email = mail.outbox[0]
|
|
||||||
|
|
||||||
assert email.to == ["guest@example.com"]
|
|
||||||
|
|
||||||
email_content = " ".join(email.body.split())
|
|
||||||
assert f"{user.full_name} shared a document with you!" in email_content
|
|
||||||
|
|
||||||
|
|
||||||
def test_api_document_invitations_create_email_full_name_empty():
|
def test_api_document_invitations_create_email_full_name_empty():
|
||||||
"""
|
"""
|
||||||
If the full name of the user is empty, it will display the email address.
|
If the full name of the user is empty, it will display the email address.
|
||||||
"""
|
"""
|
||||||
user = factories.UserFactory(full_name="")
|
user = factories.UserFactory(full_name="", language="en-us")
|
||||||
document = factories.DocumentFactory()
|
document = factories.DocumentFactory()
|
||||||
factories.UserDocumentAccessFactory(document=document, user=user, role="owner")
|
factories.UserDocumentAccessFactory(document=document, user=user, role="owner")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user