diff --git a/src/backend/core/api/viewsets.py b/src/backend/core/api/viewsets.py index e3a0003db..25c0039e5 100644 --- a/src/backend/core/api/viewsets.py +++ b/src/backend/core/api/viewsets.py @@ -576,8 +576,15 @@ def perform_create(self, serializer): """Add a new access to the document and send an email to the new added user.""" access = serializer.save() language = self.request.headers.get("Content-Language", "en-us") + + username_sender = self.request.user.full_name + email_sender = self.request.user.email + if(not username_sender): + username_sender = self.request.user.email + email_sender = "" + access.document.email_invitation( - language, access.user.email, access.role, self.request.user.email + language, access.user.email, access.role, username_sender, email_sender ) @@ -778,6 +785,13 @@ def perform_create(self, serializer): invitation = serializer.save() language = self.request.headers.get("Content-Language", "en-us") + + username_sender = self.request.user.full_name + email_sender = self.request.user.email + if(not username_sender): + username_sender = self.request.user.email + email_sender = "" + invitation.document.email_invitation( - language, invitation.email, invitation.role, self.request.user.email + language, invitation.email, invitation.role, username_sender, email_sender ) diff --git a/src/backend/core/models.py b/src/backend/core/models.py index bea277993..a84537784 100644 --- a/src/backend/core/models.py +++ b/src/backend/core/models.py @@ -520,7 +520,7 @@ def get_abilities(self, user): "versions_retrieve": can_get_versions, } - def email_invitation(self, language, email, role, username_sender): + def email_invitation(self, language, email, role, username_sender, email_sender): """Send email invitation.""" domain = Site.objects.get_current().domain @@ -537,6 +537,7 @@ def email_invitation(self, language, email, role, username_sender): "document": self, "link": f"{domain}/docs/{self.id}/", "username": username_sender, + "email": email_sender, "role": RoleChoices(role).label.lower(), } msg_html = render_to_string("mail/html/invitation.html", template_vars) diff --git a/src/backend/core/tests/documents/test_api_document_accesses_create.py b/src/backend/core/tests/documents/test_api_document_accesses_create.py index f19ee1b31..f831e8d0a 100644 --- a/src/backend/core/tests/documents/test_api_document_accesses_create.py +++ b/src/backend/core/tests/documents/test_api_document_accesses_create.py @@ -171,7 +171,7 @@ def test_api_document_accesses_create_authenticated_administrator(via, mock_user email = mail.outbox[0] assert email.to == [other_user["email"]] email_content = " ".join(email.body.split()) - assert f"{user.email} shared a document with you: {document.title}" in email_content + assert f"{user.full_name} shared a document with you: {document.title}" in email_content assert "docs/" + str(document.id) + "/" in email_content @@ -225,5 +225,5 @@ def test_api_document_accesses_create_authenticated_owner(via, mock_user_teams): email = mail.outbox[0] assert email.to == [other_user["email"]] email_content = " ".join(email.body.split()) - assert f"{user.email} shared a document with you: {document.title}" in email_content + assert f"{user.full_name} shared a document with you: {document.title}" in email_content assert "docs/" + str(document.id) + "/" in email_content diff --git a/src/backend/core/tests/documents/test_api_document_invitations.py b/src/backend/core/tests/documents/test_api_document_invitations.py index 1dd6870cf..25599de80 100644 --- a/src/backend/core/tests/documents/test_api_document_invitations.py +++ b/src/backend/core/tests/documents/test_api_document_invitations.py @@ -119,7 +119,7 @@ def test_api_document_invitations__create__privileged_members( assert email.to == ["guest@example.com"] email_content = " ".join(email.body.split()) assert ( - f"{user.email} shared a document with you: {document.title}" + f"{user.full_name} shared a document with you: {document.title}" in email_content ) else: @@ -201,8 +201,49 @@ def test_api_document_invitations__create__email_from_content_language_not_suppo assert email.to == ["guest@example.com"] + email_content = " ".join(email.body.split()) + assert f"{user.full_name} shared a document with you: {document.title}" in email_content + + +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. + """ + user = factories.UserFactory(full_name="") + 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 f"{user.email} shared a document with you: {document.title}" in email_content + assert ( + f"{user.email} invited you as an owner on the following document : {document.title}" + in email_content + ) def test_api_document_invitations__create__issuer_and_document_override(): diff --git a/src/backend/core/tests/test_models_documents.py b/src/backend/core/tests/test_models_documents.py index ed76321fb..690053c80 100644 --- a/src/backend/core/tests/test_models_documents.py +++ b/src/backend/core/tests/test_models_documents.py @@ -364,7 +364,7 @@ def test_models_documents__email_invitation__success(): assert len(mail.outbox) == 0 document.email_invitation( - "en", "guest@example.com", models.RoleChoices.EDITOR, "sender@example.com" + "en", "guest@example.com", models.RoleChoices.EDITOR, "Test Sender", "sender@example.com" ) # pylint: disable-next=no-member @@ -377,7 +377,7 @@ def test_models_documents__email_invitation__success(): email_content = " ".join(email.body.split()) assert ( - f"sender@example.com invited you as an editor on the following document : {document.title}" + f"Test Sender (sender@example.com) invited you as an editor on the following document : {document.title}" in email_content ) assert f"docs/{document.id}/" in email_content @@ -393,7 +393,7 @@ def test_models_documents__email_invitation__success_fr(): assert len(mail.outbox) == 0 document.email_invitation( - "fr-fr", "guest2@example.com", models.RoleChoices.OWNER, "sender2@example.com" + "fr-fr", "guest2@example.com", models.RoleChoices.OWNER, "Test Sender2", "sender2@example.com" ) # pylint: disable-next=no-member @@ -406,7 +406,7 @@ def test_models_documents__email_invitation__success_fr(): email_content = " ".join(email.body.split()) assert ( - f"sender2@example.com vous a invité en tant que propriétaire " + f"Test Sender2 (sender2@example.com) vous a invité en tant que propriétaire " f"sur le document suivant : {document.title}" in email_content ) assert f"docs/{document.id}/" in email_content @@ -425,7 +425,7 @@ def test_models_documents__email_invitation__failed(mock_logger, _mock_send_mail assert len(mail.outbox) == 0 document.email_invitation( - "en", "guest3@example.com", models.RoleChoices.ADMIN, "sender3@example.com" + "en", "guest3@example.com", models.RoleChoices.ADMIN, "sender3", "sender3@example.com" ) # No email has been sent diff --git a/src/backend/locale/en_US/LC_MESSAGES/django.mo b/src/backend/locale/en_US/LC_MESSAGES/django.mo index 65545c698..6d47e7dee 100644 Binary files a/src/backend/locale/en_US/LC_MESSAGES/django.mo and b/src/backend/locale/en_US/LC_MESSAGES/django.mo differ diff --git a/src/backend/locale/en_US/LC_MESSAGES/django.po b/src/backend/locale/en_US/LC_MESSAGES/django.po index 5320d813f..45c89e715 100644 --- a/src/backend/locale/en_US/LC_MESSAGES/django.po +++ b/src/backend/locale/en_US/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: lasuite-people\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-09-25 10:15+0000\n" -"PO-Revision-Date: 2024-09-25 10:17\n" +"POT-Creation-Date: 2024-10-09 13:28+0000\n" +"PO-Revision-Date: 2024-10-09 13:31\n" "Last-Translator: \n" "Language-Team: English\n" "Language: en_US\n" @@ -17,15 +17,15 @@ msgstr "" "X-Crowdin-File: backend-impress.pot\n" "X-Crowdin-File-ID: 8\n" -#: core/admin.py:32 +#: core/admin.py:33 msgid "Personal info" msgstr "" -#: core/admin.py:34 +#: core/admin.py:46 msgid "Permissions" msgstr "" -#: core/admin.py:46 +#: core/admin.py:58 msgid "Important dates" msgstr "" @@ -41,7 +41,7 @@ msgstr "" msgid "Format" msgstr "" -#: core/authentication/backends.py:56 +#: core/authentication/backends.py:57 msgid "Invalid response format or token verification failed" msgstr "" @@ -49,10 +49,6 @@ msgstr "" msgid "User info contained no recognizable user identification" msgstr "" -#: core/authentication/backends.py:101 -msgid "Claims contained no recognizable user identification" -msgstr "" - #: core/models.py:62 core/models.py:69 msgid "Reader" msgstr "" @@ -117,168 +113,176 @@ msgstr "" msgid "Required. 255 characters or fewer. Letters, numbers, and @/./+/-/_ characters only." msgstr "" -#: core/models.py:148 +#: core/models.py:149 +msgid "full name" +msgstr "" + +#: core/models.py:150 +msgid "short name" +msgstr "" + +#: core/models.py:152 msgid "identity email address" msgstr "" -#: core/models.py:153 +#: core/models.py:157 msgid "admin email address" msgstr "" -#: core/models.py:160 +#: core/models.py:164 msgid "language" msgstr "" -#: core/models.py:161 +#: core/models.py:165 msgid "The language in which the user wants to see the interface." msgstr "" -#: core/models.py:167 +#: core/models.py:171 msgid "The timezone in which the user wants to see times." msgstr "" -#: core/models.py:170 +#: core/models.py:174 msgid "device" msgstr "" -#: core/models.py:172 +#: core/models.py:176 msgid "Whether the user is a device or a real user." msgstr "" -#: core/models.py:175 +#: core/models.py:179 msgid "staff status" msgstr "" -#: core/models.py:177 +#: core/models.py:181 msgid "Whether the user can log into this admin site." msgstr "" -#: core/models.py:180 +#: core/models.py:184 msgid "active" msgstr "" -#: core/models.py:183 +#: core/models.py:187 msgid "Whether this user should be treated as active. Unselect this instead of deleting accounts." msgstr "" -#: core/models.py:195 +#: core/models.py:199 msgid "user" msgstr "" -#: core/models.py:196 +#: core/models.py:200 msgid "users" msgstr "" -#: core/models.py:328 core/models.py:644 +#: core/models.py:332 core/models.py:638 msgid "title" msgstr "" -#: core/models.py:343 +#: core/models.py:347 msgid "Document" msgstr "" -#: core/models.py:344 +#: core/models.py:348 msgid "Documents" msgstr "" -#: core/models.py:347 +#: core/models.py:351 msgid "Untitled Document" msgstr "" -#: core/models.py:537 +#: core/models.py:530 #, python-format msgid "%(username)s shared a document with you: %(document)s" msgstr "" -#: core/models.py:580 +#: core/models.py:574 msgid "Document/user link trace" msgstr "" -#: core/models.py:581 +#: core/models.py:575 msgid "Document/user link traces" msgstr "" -#: core/models.py:587 +#: core/models.py:581 msgid "A link trace already exists for this document/user." msgstr "" -#: core/models.py:608 +#: core/models.py:602 msgid "Document/user relation" msgstr "" -#: core/models.py:609 +#: core/models.py:603 msgid "Document/user relations" msgstr "" -#: core/models.py:615 +#: core/models.py:609 msgid "This user is already in this document." msgstr "" -#: core/models.py:621 +#: core/models.py:615 msgid "This team is already in this document." msgstr "" -#: core/models.py:627 core/models.py:816 +#: core/models.py:621 core/models.py:810 msgid "Either user or team must be set, not both." msgstr "" -#: core/models.py:645 +#: core/models.py:639 msgid "description" msgstr "" -#: core/models.py:646 +#: core/models.py:640 msgid "code" msgstr "" -#: core/models.py:647 +#: core/models.py:641 msgid "css" msgstr "" -#: core/models.py:649 +#: core/models.py:643 msgid "public" msgstr "" -#: core/models.py:651 +#: core/models.py:645 msgid "Whether this template is public for anyone to use." msgstr "" -#: core/models.py:657 +#: core/models.py:651 msgid "Template" msgstr "" -#: core/models.py:658 +#: core/models.py:652 msgid "Templates" msgstr "" -#: core/models.py:797 +#: core/models.py:791 msgid "Template/user relation" msgstr "" -#: core/models.py:798 +#: core/models.py:792 msgid "Template/user relations" msgstr "" -#: core/models.py:804 +#: core/models.py:798 msgid "This user is already in this template." msgstr "" -#: core/models.py:810 +#: core/models.py:804 msgid "This team is already in this template." msgstr "" -#: core/models.py:833 +#: core/models.py:827 msgid "email address" msgstr "" -#: core/models.py:850 +#: core/models.py:844 msgid "Document invitation" msgstr "" -#: core/models.py:851 +#: core/models.py:845 msgid "Document invitations" msgstr "" -#: core/models.py:868 +#: core/models.py:862 msgid "This email is already associated to a registered user." msgstr "" @@ -298,7 +302,7 @@ msgstr "" #: core/templates/mail/html/invitation.html:197 #: core/templates/mail/text/invitation.txt:8 #, python-format -msgid " %(username)s invited you as an %(role)s on the following document : " +msgid " %(username)s (%(email)s) invited you as an %(role)s on the following document : " msgstr "" #: core/templates/mail/html/invitation.html:206 diff --git a/src/backend/locale/fr_FR/LC_MESSAGES/django.mo b/src/backend/locale/fr_FR/LC_MESSAGES/django.mo index b6e0032a4..2a87f775f 100644 Binary files a/src/backend/locale/fr_FR/LC_MESSAGES/django.mo and b/src/backend/locale/fr_FR/LC_MESSAGES/django.mo differ diff --git a/src/backend/locale/fr_FR/LC_MESSAGES/django.po b/src/backend/locale/fr_FR/LC_MESSAGES/django.po index 8c4ad0b41..2fee5b2b5 100644 --- a/src/backend/locale/fr_FR/LC_MESSAGES/django.po +++ b/src/backend/locale/fr_FR/LC_MESSAGES/django.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: lasuite-people\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-09-25 10:15+0000\n" -"PO-Revision-Date: 2024-09-25 10:21\n" +"POT-Creation-Date: 2024-10-09 13:28+0000\n" +"PO-Revision-Date: 2024-10-09 13:31\n" "Last-Translator: \n" "Language-Team: French\n" "Language: fr_FR\n" @@ -17,15 +17,15 @@ msgstr "" "X-Crowdin-File: backend-impress.pot\n" "X-Crowdin-File-ID: 8\n" -#: core/admin.py:32 +#: core/admin.py:33 msgid "Personal info" msgstr "Infos Personnelles" -#: core/admin.py:34 +#: core/admin.py:46 msgid "Permissions" msgstr "Permissions" -#: core/admin.py:46 +#: core/admin.py:58 msgid "Important dates" msgstr "Dates importantes" @@ -41,7 +41,7 @@ msgstr "" msgid "Format" msgstr "" -#: core/authentication/backends.py:56 +#: core/authentication/backends.py:57 msgid "Invalid response format or token verification failed" msgstr "" @@ -49,10 +49,6 @@ msgstr "" msgid "User info contained no recognizable user identification" msgstr "" -#: core/authentication/backends.py:101 -msgid "Claims contained no recognizable user identification" -msgstr "" - #: core/models.py:62 core/models.py:69 msgid "Reader" msgstr "Lecteur" @@ -117,168 +113,176 @@ msgstr "" msgid "Required. 255 characters or fewer. Letters, numbers, and @/./+/-/_ characters only." msgstr "" -#: core/models.py:148 +#: core/models.py:149 +msgid "full name" +msgstr "" + +#: core/models.py:150 +msgid "short name" +msgstr "" + +#: core/models.py:152 msgid "identity email address" msgstr "" -#: core/models.py:153 +#: core/models.py:157 msgid "admin email address" msgstr "" -#: core/models.py:160 +#: core/models.py:164 msgid "language" msgstr "" -#: core/models.py:161 +#: core/models.py:165 msgid "The language in which the user wants to see the interface." msgstr "" -#: core/models.py:167 +#: core/models.py:171 msgid "The timezone in which the user wants to see times." msgstr "" -#: core/models.py:170 +#: core/models.py:174 msgid "device" msgstr "" -#: core/models.py:172 +#: core/models.py:176 msgid "Whether the user is a device or a real user." msgstr "" -#: core/models.py:175 +#: core/models.py:179 msgid "staff status" msgstr "" -#: core/models.py:177 +#: core/models.py:181 msgid "Whether the user can log into this admin site." msgstr "" -#: core/models.py:180 +#: core/models.py:184 msgid "active" msgstr "" -#: core/models.py:183 +#: core/models.py:187 msgid "Whether this user should be treated as active. Unselect this instead of deleting accounts." msgstr "" -#: core/models.py:195 +#: core/models.py:199 msgid "user" msgstr "" -#: core/models.py:196 +#: core/models.py:200 msgid "users" msgstr "" -#: core/models.py:328 core/models.py:644 +#: core/models.py:332 core/models.py:638 msgid "title" msgstr "" -#: core/models.py:343 +#: core/models.py:347 msgid "Document" msgstr "" -#: core/models.py:344 +#: core/models.py:348 msgid "Documents" msgstr "" -#: core/models.py:347 +#: core/models.py:351 msgid "Untitled Document" msgstr "" -#: core/models.py:537 +#: core/models.py:530 #, python-format msgid "%(username)s shared a document with you: %(document)s" msgstr "%(username)s a partagé un document avec vous: %(document)s" -#: core/models.py:580 +#: core/models.py:574 msgid "Document/user link trace" msgstr "" -#: core/models.py:581 +#: core/models.py:575 msgid "Document/user link traces" msgstr "" -#: core/models.py:587 +#: core/models.py:581 msgid "A link trace already exists for this document/user." msgstr "" -#: core/models.py:608 +#: core/models.py:602 msgid "Document/user relation" msgstr "" -#: core/models.py:609 +#: core/models.py:603 msgid "Document/user relations" msgstr "" -#: core/models.py:615 +#: core/models.py:609 msgid "This user is already in this document." msgstr "" -#: core/models.py:621 +#: core/models.py:615 msgid "This team is already in this document." msgstr "" -#: core/models.py:627 core/models.py:816 +#: core/models.py:621 core/models.py:810 msgid "Either user or team must be set, not both." msgstr "" -#: core/models.py:645 +#: core/models.py:639 msgid "description" msgstr "" -#: core/models.py:646 +#: core/models.py:640 msgid "code" msgstr "" -#: core/models.py:647 +#: core/models.py:641 msgid "css" msgstr "" -#: core/models.py:649 +#: core/models.py:643 msgid "public" msgstr "" -#: core/models.py:651 +#: core/models.py:645 msgid "Whether this template is public for anyone to use." msgstr "" -#: core/models.py:657 +#: core/models.py:651 msgid "Template" msgstr "" -#: core/models.py:658 +#: core/models.py:652 msgid "Templates" msgstr "" -#: core/models.py:797 +#: core/models.py:791 msgid "Template/user relation" msgstr "" -#: core/models.py:798 +#: core/models.py:792 msgid "Template/user relations" msgstr "" -#: core/models.py:804 +#: core/models.py:798 msgid "This user is already in this template." msgstr "" -#: core/models.py:810 +#: core/models.py:804 msgid "This team is already in this template." msgstr "" -#: core/models.py:833 +#: core/models.py:827 msgid "email address" msgstr "" -#: core/models.py:850 +#: core/models.py:844 msgid "Document invitation" msgstr "" -#: core/models.py:851 +#: core/models.py:845 msgid "Document invitations" msgstr "" -#: core/models.py:868 +#: core/models.py:862 msgid "This email is already associated to a registered user." msgstr "" @@ -298,8 +302,8 @@ msgstr " %(username)s a partagé un document avec vous ! " #: core/templates/mail/html/invitation.html:197 #: core/templates/mail/text/invitation.txt:8 #, python-format -msgid " %(username)s invited you as an %(role)s on the following document : " -msgstr " %(username)s vous a invité en tant que %(role)s sur le document suivant : " +msgid " %(username)s (%(email)s) invited you as an %(role)s on the following document : " +msgstr " %(username)s (%(email)s) vous a invité en tant que %(role)s sur le document suivant : " #: core/templates/mail/html/invitation.html:206 #: core/templates/mail/html/invitation2.html:211 diff --git a/src/mail/mjml/invitation.mjml b/src/mail/mjml/invitation.mjml index 4e5841b16..ee5e5f186 100644 --- a/src/mail/mjml/invitation.mjml +++ b/src/mail/mjml/invitation.mjml @@ -31,7 +31,7 @@ {% blocktrans %} - {{username}} invited you as an {{role}} on the following document : + {{username}} {{email}} invited you as an {{role}} on the following document : {% endblocktrans %} {{document.title}}