Skip to content

Commit

Permalink
Display a warning page when an issuer already exists with a given adr…
Browse files Browse the repository at this point in the history
…ess in DB
  • Loading branch information
christophehenry committed Mar 16, 2022
1 parent 2737ba6 commit 25a4990
Show file tree
Hide file tree
Showing 15 changed files with 282 additions and 132 deletions.
70 changes: 69 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,69 @@ 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_extras %}
{% 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_extras %}
{% 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_extras %}
{% 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,37 @@
{% 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>
Vous venez de tenter de créer un nouveau profil demandeur sur la page d'habilitations Aidants
Connect avec une adresse email qui existe déjà dans notre basse de données. Notez que si vous
souhaitez poduire une nouvelle demande d'habilitation pour une organisation, ou modifier une
demande existante, <a href="{{ url }}">vous pouvez visualiser toutes vos demandes en cours
en suivant ce lien</a> ou, si cela ne fonctionne pas, en copiant l'URL suivante dans votre
navigateur :
</p>
<p>{{ url }}</p>

<p>Bonne journée,</p>
<p>L'équipe 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,16 @@
{% load ac_common %}

Bonjour,

{% linebreakless %}
Vous venez de tenter de créer un nouveau profil demandeur sur la page d'habilitations Aidants
Connect avec une adresse email qui existe déjà dans notre basse de données.{% keeplinebreak %}
Notez que si vous souhaitez poduire une nouvelle demande d'habilitation pour une organisation,
ou modifier une demande existante, vous pouvez visualiser toutes vos demandes en cours en copiant
l'URL suivante dans votre navigateur :{% keeplinebreak %}
{% keeplinebreak %}
{{ url }}
{% endlinebreakless %}

Bonne journée,
L'équipe Aidants Connect
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{% 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-12 fr-col-md-8">
<h2>Un profil demandeur avec cet email existe déjà !</h2>
<div class="shadowed">
<p>
Un profil avec cette adresse email existe déjà. Nous venons d'envoyer un email à cette adresse contenant
un lien où vous pourrez retrouver toutes les demandes faites avec ce profil.
</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 @@ -97,6 +97,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
5 changes: 5 additions & 0 deletions aidants_connect_habilitation/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
IssuerPageView.as_view(),
name="habilitation_issuer_page",
),
path(
"demandeur/<str:issuer_id>/requetes",
IssuerPageView.as_view(),
name="habilitation_issuer_requests_page",
),
path(
"demandeur/<str:issuer_id>/modifier/",
ModifyIssuerFormView.as_view(),
Expand Down
44 changes: 38 additions & 6 deletions aidants_connect_habilitation/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from django.conf import settings
from django.shortcuts import get_object_or_404, redirect
from django.core.mail import send_mail
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 @@ -85,6 +87,10 @@ def setup(self, request, *args, **kwargs):


class OnlyNewRequestsView(LateStageRequestView):
@property
def step(self) -> HabilitationFormStep:
raise NotImplementedError()

def dispatch(self, request, *args, **kwargs):
if not self.issuer.email_verified:
# Duplicate logic of VerifiedEmailIssuerView
Expand Down Expand Up @@ -113,14 +119,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_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 @@ -131,8 +146,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_mail(self, email: str):
path = reverse(
"habilitation_issuer_requests_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 25a4990

Please sign in to comment.