(backend) send email to admins when user ask for access

When a user requests access to a document, an
email is sent to the admins and owners of the
document.
This commit is contained in:
Anthony LC
2025-06-20 15:24:46 +02:00
committed by Manuel Raynaud
parent 878de08b1e
commit 394f91387d
6 changed files with 104 additions and 5 deletions

View File

@@ -36,6 +36,7 @@ from rest_framework.throttling import UserRateThrottle
from core import authentication, enums, models
from core.services.ai_services import AIService
from core.services.collaboration_services import CollaborationService
from core.tasks.mail import send_ask_for_access_mail
from core.utils import extract_attachments, filter_descendants
from . import permissions, serializers, utils
@@ -1829,12 +1830,14 @@ class DocumentAskForAccessViewSet(
status=drf.status.HTTP_400_BAD_REQUEST,
)
models.DocumentAskForAccess.objects.create(
ask_for_access = models.DocumentAskForAccess.objects.create(
document=document,
user=request.user,
role=serializer.validated_data["role"],
)
send_ask_for_access_mail.delay(ask_for_access.id)
return drf.response.Response(status=drf.status.HTTP_201_CREATED)
@drf.decorators.action(detail=True, methods=["post"])

View File

@@ -876,8 +876,8 @@ class Document(MP_Node, BaseModel):
)
with override(language):
msg_html = render_to_string("mail/html/invitation.html", context)
msg_plain = render_to_string("mail/text/invitation.txt", context)
msg_html = render_to_string("mail/html/template.html", context)
msg_plain = render_to_string("mail/text/template.txt", context)
subject = str(subject) # Force translation
try:
@@ -1221,6 +1221,39 @@ class DocumentAskForAccess(BaseModel):
)
self.delete()
def send_ask_for_access_email(self, email, language=None):
"""
Method allowing a user to send an email notification when asking for access to a document.
"""
language = language or get_language()
sender = self.user
sender_name = sender.full_name or sender.email
sender_name_email = (
f"{sender.full_name:s} ({sender.email})"
if sender.full_name
else sender.email
)
with override(language):
context = {
"title": _("{name} would like access to a document!").format(
name=sender_name
),
"message": _(
"{name} would like access to the following document:"
).format(name=sender_name_email),
}
subject = (
context["title"]
if not self.document.title
else _("{name} is asking for access to the document: {title}").format(
name=sender_name, title=self.document.title
)
)
self.document.send_email(subject, [email], context, language)
class Template(BaseModel):
"""HTML and CSS code used for formatting the print around the MarkDown body."""

View File

View File

@@ -0,0 +1,24 @@
"""Send mail using celery task."""
from django.conf import settings
from core import models
from impress.celery_app import app
@app.task
def send_ask_for_access_mail(ask_for_access_id):
"""Send mail using celery task."""
# Send email to document owners/admins
ask_for_access = models.DocumentAskForAccess.objects.get(id=ask_for_access_id)
owner_admin_accesses = models.DocumentAccess.objects.filter(
document=ask_for_access.document, role__in=models.PRIVILEGED_ROLES
).select_related("user")
for access in owner_admin_accesses:
if access.user and access.user.email:
ask_for_access.send_ask_for_access_email(
access.user.email,
access.user.language or settings.LANGUAGE_CODE,
)

View File

@@ -2,6 +2,8 @@
import uuid
from django.core import mail
import pytest
from rest_framework.test import APIClient
@@ -41,13 +43,26 @@ def test_api_documents_ask_for_access_create_invalid_document_id():
def test_api_documents_ask_for_access_create_authenticated():
"""Authenticated users should be able to create a document ask for access."""
document = DocumentFactory()
"""
Authenticated users should be able to create a document ask for access.
An email should be sent to document owners and admins to notify them.
"""
owner_user = UserFactory(language="en-us")
admin_user = UserFactory(language="fr-fr")
document = DocumentFactory(
users=[
(owner_user, RoleChoices.OWNER),
(admin_user, RoleChoices.ADMIN),
]
)
user = UserFactory()
client = APIClient()
client.force_login(user)
assert len(mail.outbox) == 0
response = client.post(f"/api/v1.0/documents/{document.id}/ask-for-access/")
assert response.status_code == 201
@@ -57,6 +72,30 @@ def test_api_documents_ask_for_access_create_authenticated():
role=RoleChoices.READER,
).exists()
# Verify emails were sent to both owner and admin
assert len(mail.outbox) == 2
# Check that emails were sent to the right recipients
email_recipients = [email.to[0] for email in mail.outbox]
assert owner_user.email in email_recipients
assert admin_user.email in email_recipients
# Check email content for both users
for email in mail.outbox:
email_content = " ".join(email.body.split())
email_subject = " ".join(email.subject.split())
# Check that the requesting user's name is in the email
user_name = user.full_name or user.email
assert user_name.lower() in email_content.lower()
# Check that the subject mentions access request
assert "access" in email_subject.lower()
# Check that the document title is mentioned if it exists
if document.title:
assert document.title.lower() in email_subject.lower()
def test_api_documents_ask_for_access_create_authenticated_specific_role():
"""