From 41a6ef9dfc14fc5bb83a47de4f5496689b072927 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Wed, 14 Aug 2024 12:25:54 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=90(backend)=20user=20language=20from?= =?UTF-8?q?=20request=20Content-Language?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to adapt the email language depend the website choosen language. We get the website language from the request Content-Language header. We adapt the serializer to set the user language from the request Content-Language header. Thanks to that our email will be in the right language. --- src/backend/core/api/serializers.py | 1 + .../tests/test_api_document_invitations.py | 77 +++++++++++++++++++ .../core/tests/test_models_invitations.py | 32 +++++++- 3 files changed, 109 insertions(+), 1 deletion(-) diff --git a/src/backend/core/api/serializers.py b/src/backend/core/api/serializers.py index e43f7e76..c09b824f 100644 --- a/src/backend/core/api/serializers.py +++ b/src/backend/core/api/serializers.py @@ -262,6 +262,7 @@ class InvitationSerializer(serializers.ModelSerializer): "Only owners of a document can invite other users as owners." ) + user.language = request.headers.get("Content-Language", "en") attrs["document_id"] = document_id attrs["issuer"] = user return attrs diff --git a/src/backend/core/tests/test_api_document_invitations.py b/src/backend/core/tests/test_api_document_invitations.py index 7d95fce0..2452468e 100644 --- a/src/backend/core/tests/test_api_document_invitations.py +++ b/src/backend/core/tests/test_api_document_invitations.py @@ -4,6 +4,8 @@ Unit tests for the Invitation model import random import time +from django.core import mail + import pytest from rest_framework import status from rest_framework.test import APIClient @@ -113,6 +115,81 @@ def test_api_document_invitations__create__privileged_members( assert models.Invitation.objects.exists() is False +def test_api_document_invitations__create__email_from_content_language(): + """ + The email generated is from the language set in the Content-Language header + """ + 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}/invitations/", + invitation_values, + format="json", + headers={"Content-Language": "fr-fr"}, + ) + + assert response.status_code == status.HTTP_201_CREATED + 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 "Invitation à rejoindre Docs !" in email_content + + +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}/invitations/", + invitation_values, + format="json", + headers={"Content-Language": "not-supported"}, + ) + + assert response.status_code == status.HTTP_201_CREATED + 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 "Invitation to join Docs!" in email_content + + def test_api_document_invitations__create__issuer_and_document_override(): """It should not be possible to set the "document" and "issuer" fields.""" user = factories.UserFactory() diff --git a/src/backend/core/tests/test_models_invitations.py b/src/backend/core/tests/test_models_invitations.py index 57bef891..96de9c65 100644 --- a/src/backend/core/tests/test_models_invitations.py +++ b/src/backend/core/tests/test_models_invitations.py @@ -177,7 +177,10 @@ def test_models_document_invitations_email(): assert len(mail.outbox) == 0 factories.UserDocumentAccessFactory(document=document) - invitation = factories.InvitationFactory(document=document, email="john@people.com") + issuer = factories.UserFactory(language="en-us") + invitation = factories.InvitationFactory( + document=document, email="john@people.com", issuer=issuer + ) # pylint: disable-next=no-member assert len(mail.outbox) == 1 @@ -193,6 +196,33 @@ def test_models_document_invitations_email(): assert "[//example.com]" in email_content +def test_models_document_invitations_email_language_fr(): + """Check email invitation during invitation creation.""" + member_access = factories.UserDocumentAccessFactory(role="reader") + document = member_access.document + + # pylint: disable-next=no-member + assert len(mail.outbox) == 0 + + factories.UserDocumentAccessFactory(document=document) + issuer = factories.UserFactory(language="fr-fr") + invitation = factories.InvitationFactory( + document=document, email="john@people.com", issuer=issuer + ) + + # pylint: disable-next=no-member + assert len(mail.outbox) == 1 + + # pylint: disable-next=no-member + email = mail.outbox[0] + + assert email.to == [invitation.email] + + email_content = " ".join(email.body.split()) + assert "Invitation à rejoindre Docs !" in email_content + assert "[//example.com]" in email_content + + @mock.patch( "django.core.mail.send_mail", side_effect=smtplib.SMTPException("Error SMTPException"),