Skip to content

Commit

Permalink
Envoi d'un mail lorsqu'une personne tente de créer un profil demandeu…
Browse files Browse the repository at this point in the history
…r avec une adresse email déjà référencée #578
  • Loading branch information
christophehenry authored Mar 22, 2022
2 parents 2a06ff4 + eab10d2 commit 227b77b
Show file tree
Hide file tree
Showing 14 changed files with 268 additions and 132 deletions.
69 changes: 68 additions & 1 deletion aidants_connect/common/tests/test_templatetags.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from unittest import TestCase
from urllib.parse import quote

from django.template import Context, Template
from django.test import TestCase

from aidants_connect.templatetags.ac_common import mailto


Expand All @@ -15,3 +17,68 @@ def test_mailto(self):
f'<a href="mailto:{recipient}?subject={quote(subject, "")}&'
f'body={quote(body, "")}">{mail_link}</a>',
)


class LinebreaklessTests(TestCase):
def test_linebreaks_are_stripped(self):
result = self._render_template(
"""{% load ac_common %}
{% linebreakless %}
<p>
This is a test with a list
</p>
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
</ul>
{% endlinebreakless %}"""
)

self.assertEqual(
"<p>This is a test with a list</p><ul><li>item 1</li><li>item 2</li>"
"<li>item 3</li></ul>",
result.strip(),
)

def test_keeplinebreak_keeps_linebreaks(self):
result = self._render_template(
"""
{% load ac_common %}
{% linebreakless %}
<p>
This is a test with a list
</p>
<ul>{% keeplinebreak %}
<li>item 1</li>{% keeplinebreak %}
<li>item 2</li>{% keeplinebreak %}
<li>item 3</li>{% keeplinebreak %}
</ul>
{% endlinebreakless %}"""
)

self.assertEqual(
"<p>This is a test with a list</p><ul>\n<li>item 1</li>\n<li>item 2</li>\n"
"<li>item 3</li>\n</ul>",
result.strip(),
)

def test_keeplinebreak_throws_expception_when_not_followed_by_a_linebreak(self):
template = """
{% load ac_common %}
{% linebreakless %}
<p>
This is a test with a list
</p>
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
</ul>
{% keeplinebreak %}{% endlinebreakless %}"""

with self.assertRaises(ValueError):
self._render_template(template)

def _render_template(self, string, context=None):
return Template(string).render(Context(context or {}))
9 changes: 9 additions & 0 deletions aidants_connect/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -553,3 +553,12 @@ def getenv_bool(key: str, default: Optional[bool] = None) -> bool:
Je vous contacte car je ne reçois pas les emails de confirmation de mon adresse email.""",
)

EMAIL_HABILITATION_ISSUER_EMAIL_ALREADY_EXISTS_FROM = os.getenv(
"EMAIL_HABILITATION_ISSUER_EMAIL_ALREADY_EXISTS_FROM", SUPPORT_EMAIL
)

EMAIL_HABILITATION_ISSUER_EMAIL_ALREADY_EXISTS_SUBJECT = os.getenv(
"EMAIL_HABILITATION_ISSUER_EMAIL_ALREADY_EXISTS_SUBJECT",
"Rappel de votre profil demandeur",
)
51 changes: 51 additions & 0 deletions aidants_connect/templatetags/ac_common.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import re
from urllib.parse import quote, urlencode

from django import template
from django.conf import settings
from django.template.base import Node, NodeList, Parser, TextNode, Token
from django.utils.safestring import mark_safe

register = template.Library()
Expand All @@ -28,3 +30,52 @@ def quote_via(string, _, encoding, errors):
@register.simple_tag
def stimulusjs():
return mark_safe(f'<script src="{settings.STIMULUS_JS_URL}"></script>')


@register.tag
def linebreakless(parser: Parser, token: Token):
library = template.Library()
library.tag(LinebreaklessNode.KEEP_LINEBREAK_TAG, LinebreaklessNode.keeplinebreak)
parser.add_library(library)
nodelist = parser.parse(("endlinebreakless",))
parser.delete_first_token()
return LinebreaklessNode(token, nodelist)


class LinebreaklessNode(Node):
KEEP_LINEBREAK_TAG = "keeplinebreak"
KEEP_LINEBREAK_MARKUP = f"{{% {KEEP_LINEBREAK_TAG} %}}"

class KeepLineBreak(Node):
def __init__(self, token: Token):
self.token = token

def render(self, context):
return LinebreaklessNode.KEEP_LINEBREAK_MARKUP

@staticmethod
def keeplinebreak(_, token: Token):
return LinebreaklessNode.KeepLineBreak(token)

def __init__(self, token: Token, nodelist: NodeList):
self.token = token
self.nodelist = nodelist

def render(self, context):
for i, node in enumerate(self.nodelist):
if isinstance(node, LinebreaklessNode.KeepLineBreak) and (
len(self.nodelist) <= i + 1
or not isinstance(self.nodelist[i + 1], TextNode)
or not self.nodelist[i + 1].s.strip(" \t\r\f\v").startswith("\n")
):
raise ValueError(
f"{LinebreaklessNode.KEEP_LINEBREAK_MARKUP} needs to be followed "
"by a linebreak.\n"
f' File "{node.origin.name}", line {node.token.lineno}'
)

return re.sub(
"\\s*\n+\\s*",
"",
self.nodelist.render(context).strip(),
).replace(self.KEEP_LINEBREAK_MARKUP, "\n")
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{% extends "layouts/email_base.html" %}
{% block email_body %}
<table border="0" cellpadding="0" cellspacing="0" class="body">
<tr>
<td>&nbsp;</td>
<td class="container">
<div class="content">
<table class="main">
<tr>
<td class="wrapper">
<table border="0" cellpadding="6" cellspacing="0">
<tr>
<td>
<p>Bonjour,</p>
<p>Bonne nouvelle ! Il existe déjà un espace demandeur associé à cet email chez nous.</p>
<p>
Vous pouvez <a href="{{ url }}">suivre le lien suivant pour retrouver toutes vos demandes en
cours et en déposer de nouvelles</a> ou, si cela ne fonctionne pas, en copier l'URL suivante
dans votre navigateur :
</p>
<p>{{ url }}</p>

<p>À bientôt sur Aidants Connect</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% load ac_common %}

Bonjour,

Bonne nouvelle ! Il existe déjà un espace demandeur associé à cet email chez nous.
Vous pouvez suivre le lien suivant pour retrouver toutes vos demandes en cours et en déposer de nouvelles :
{{ url }}

À bientôt sur Aidants Connect
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{% extends 'layouts/main-habilitation.html' %}
{% load static form_extras %}

{% block title %}
Aidants Connect - Un compte demandeur existe déjà
{% endblock %}

{% block content %}
<div class="fr-container">
<div class="fr-grid-row fr-grid-row--gutters">
<div class="fr-col">
<h1>Formulaire d’habilitation</h1>
</div>
</div>

<div class="fr-grid-row fr-grid-row--gutters">
<div class="fr-col-12 fr-col-md-8">
<h2>On se connaît !</h2>
<div class="shadowed">
<p>
Votre profil demandeur existe déjà. Nous vous avons renvoyé un e-mail
qui vous permettra de retrouver toutes vos données et toutes vos demandes.
</p>
</div>
</div>
</div>

{% include "_more-info.html" %}

</div>
{% endblock %}
29 changes: 28 additions & 1 deletion aidants_connect_habilitation/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from datetime import timedelta
from unittest.mock import patch
from unittest.mock import ANY, Mock, patch
from uuid import UUID, uuid4

from django.forms import model_to_dict
Expand Down Expand Up @@ -98,6 +98,33 @@ def test_redirect_valid_post_creates_an_email_confirmation(self):
"Request should have created an instance of IssuerEmailConfirmation"
)

@patch("aidants_connect_habilitation.views.send_mail")
def test_send_email_when_issuer_already_exists(self, send_mail_mock: Mock):
issuer: Issuer = IssuerFactory()

data = utils.get_form(IssuerForm).clean()
data["email"] = issuer.email

self.client.post(reverse(self.pattern_name), data)

send_mail_mock.assert_called_with(
from_email=settings.EMAIL_HABILITATION_ISSUER_EMAIL_ALREADY_EXISTS_FROM,
recipient_list=[issuer.email],
subject=settings.EMAIL_HABILITATION_ISSUER_EMAIL_ALREADY_EXISTS_SUBJECT,
message=ANY,
html_message=ANY,
)

def test_render_warning_when_issuer_already_exists(self):
issuer: Issuer = IssuerFactory()

data = utils.get_form(IssuerForm).clean()
data["email"] = issuer.email

response = self.client.post(reverse(self.pattern_name), data)

self.assertTemplateUsed(response, "issuer_already_exists_warning.html")


@tag("habilitation")
class IssuerEmailConfirmationWaitingViewTests(TestCase):
Expand Down
40 changes: 34 additions & 6 deletions aidants_connect_habilitation/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from django.conf import settings
from django.core.mail import send_mail
from django.forms.models import model_to_dict
from django.shortcuts import get_object_or_404, redirect
from django.shortcuts import get_object_or_404, redirect, render
from django.template import loader
from django.urls import reverse
from django.views.generic import FormView, RedirectView, TemplateView, View
from django.views.generic.base import ContextMixin
Expand Down Expand Up @@ -118,14 +120,23 @@ class NewHabilitationView(RedirectView):


class NewIssuerFormView(HabilitationStepMixin, FormView):
template_name = "issuer_form.html"
form_class = IssuerForm

@property
def step(self) -> HabilitationFormStep:
return HabilitationFormStep.ISSUER

template_name = "issuer_form.html"
form_class = IssuerForm
def form_invalid(self, form: IssuerForm):
# Gets the error code of all the errors for email, if any
# See https://docs.djangoproject.com/en/dev/ref/forms/fields/#django.forms.Field.error_messages # noqa
error_codes = [error.code for error in form.errors["email"].as_data()]
if "unique" in error_codes:
self.send_issuer_profile_reminder_mail(form.data["email"])
return render(self.request, "issuer_already_exists_warning.html")
return super().form_invalid(form)

def form_valid(self, form):
def form_valid(self, form: IssuerForm):
self.saved_model: Issuer = form.save()
IssuerEmailConfirmation.for_issuer(self.saved_model).send(self.request)
return super().form_valid(form)
Expand All @@ -136,8 +147,25 @@ def get_success_url(self):
kwargs={"issuer_id": self.saved_model.issuer_id},
)

def get_context_data(self, **kwargs):
return {**super().get_context_data(**kwargs), "step": self.step}
def send_issuer_profile_reminder_mail(self, email: str):
path = reverse(
"habilitation_issuer_page",
kwargs={"issuer_id": str(Issuer.objects.get(email=email).issuer_id)},
)
context = {"url": self.request.build_absolute_uri(path)}
text_message = loader.render_to_string(
"email/issuer_profile_reminder.txt", context
)
html_message = loader.render_to_string(
"email/issuer_profile_reminder.html", context
)
send_mail(
from_email=settings.EMAIL_HABILITATION_ISSUER_EMAIL_ALREADY_EXISTS_FROM,
recipient_list=[email],
subject=settings.EMAIL_HABILITATION_ISSUER_EMAIL_ALREADY_EXISTS_SUBJECT,
message=text_message,
html_message=html_message,
)


class IssuerEmailConfirmationWaitingView(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{% extends 'layouts/main.html' %}

{% load static ac_extras %}
{% load static ac_extras ac_common %}

{% linebreakless %}
{% block title %}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% extends "layouts/email_base.html" %}
{% load ac_extras %}
{% load ac_extras ac_common %}

{% block email_body %}
<table border="0" cellpadding="0" cellspacing="0" class="body">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% load ac_extras %}
{% load ac_extras ac_common %}
Bonjour,
{% if not users %}
L’équipe Aidants Connect vous informe qu'aucune carte Aidants Connect n'est liée à votre compte.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% load ac_extras %}
{% load ac_extras ac_common %}

Bonjour,

Expand Down
Loading

0 comments on commit 227b77b

Please sign in to comment.