mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-06-11 23:14:49 +02:00
Send invitation email when invite is created
This commit is contained in:
parent
1e77bd9bf6
commit
8338704315
4 changed files with 64 additions and 7 deletions
|
@ -469,7 +469,9 @@ class DomainApplication(TimeStampedModel):
|
|||
nothing.
|
||||
"""
|
||||
if self.submitter is None or self.submitter.email is None:
|
||||
logger.warning("Cannot send confirmation email, no submitter email address.")
|
||||
logger.warning(
|
||||
"Cannot send confirmation email, no submitter email address."
|
||||
)
|
||||
return
|
||||
try:
|
||||
send_templated_email(
|
||||
|
|
6
src/registrar/templates/emails/domain_invitation.txt
Normal file
6
src/registrar/templates/emails/domain_invitation.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
You have been invited to manage a domain on get.gov, the registrar for
|
||||
.gov domain names.
|
||||
|
||||
To accept your invitation, go to <{{ domain_url }}>.
|
||||
|
||||
You will need to log in with a Login.gov account using this email address.
|
|
@ -1,4 +1,5 @@
|
|||
from unittest import skip
|
||||
from unittest.mock import MagicMock, ANY
|
||||
|
||||
from django.conf import settings
|
||||
from django.test import Client, TestCase
|
||||
|
@ -557,9 +558,7 @@ class DomainApplicationTests(TestWithUser, WebTest):
|
|||
# the post request should return a redirect to the contact
|
||||
# question
|
||||
self.assertEqual(election_result.status_code, 302)
|
||||
self.assertEqual(
|
||||
election_result["Location"], "/register/organization_contact/"
|
||||
)
|
||||
self.assertEqual(election_result["Location"], "/register/organization_contact/")
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
contact_page = election_result.follow()
|
||||
self.assertNotContains(contact_page, "Federal agency")
|
||||
|
@ -1139,8 +1138,13 @@ class TestDomainDetail(TestWithDomainPermissions, WebTest):
|
|||
success_page = success_result.follow()
|
||||
self.assertContains(success_page, "mayor@igorville.gov")
|
||||
|
||||
@boto3_mocking.patching
|
||||
def test_domain_invitation_created(self):
|
||||
"""Add user on a nonexistent email creates an invitation."""
|
||||
"""Add user on a nonexistent email creates an invitation.
|
||||
|
||||
Adding a non-existent user sends an email as a side-effect, so mock
|
||||
out the boto3 SES email sending here.
|
||||
"""
|
||||
# make sure there is no user with this email
|
||||
EMAIL = "mayor@igorville.gov"
|
||||
User.objects.filter(email=EMAIL).delete()
|
||||
|
@ -1159,10 +1163,36 @@ class TestDomainDetail(TestWithDomainPermissions, WebTest):
|
|||
self.assertContains(success_page, "Cancel") # link to cancel invitation
|
||||
self.assertTrue(DomainInvitation.objects.filter(email=EMAIL).exists())
|
||||
|
||||
@boto3_mocking.patching
|
||||
def test_domain_invitation_email_sent(self):
|
||||
"""Inviting a non-existent user sends them an email."""
|
||||
# make sure there is no user with this email
|
||||
EMAIL = "mayor@igorville.gov"
|
||||
User.objects.filter(email=EMAIL).delete()
|
||||
|
||||
mock_client = MagicMock()
|
||||
mock_client_instance = mock_client.return_value
|
||||
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
||||
add_page = self.app.get(
|
||||
reverse("domain-users-add", kwargs={"pk": self.domain.id})
|
||||
)
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
add_page.form["email"] = EMAIL
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
add_page.form.submit()
|
||||
# check the mock instance to see if `send_email` was called right
|
||||
mock_client_instance.send_email.assert_called_once_with(
|
||||
FromEmailAddress=settings.DEFAULT_FROM_EMAIL,
|
||||
Destination={"ToAddresses": [EMAIL]},
|
||||
Content=ANY,
|
||||
)
|
||||
|
||||
def test_domain_invitation_cancel(self):
|
||||
"""Posting to the delete view deletes an invitation."""
|
||||
EMAIL = "mayor@igorville.gov"
|
||||
invitation, _ = DomainInvitation.objects.get_or_create(domain=self.domain, email=EMAIL)
|
||||
invitation, _ = DomainInvitation.objects.get_or_create(
|
||||
domain=self.domain, email=EMAIL
|
||||
)
|
||||
self.client.post(reverse("invitation-delete", kwargs={"pk": invitation.id}))
|
||||
with self.assertRaises(DomainInvitation.DoesNotExist):
|
||||
DomainInvitation.objects.get(id=invitation.id)
|
||||
|
|
|
@ -11,6 +11,7 @@ from django.views.generic.edit import DeleteView, FormMixin
|
|||
from registrar.models import Domain, DomainInvitation, User, UserDomainRole
|
||||
|
||||
from ..forms import DomainAddUserForm
|
||||
from ..utility.email import send_templated_email, EmailSendingError
|
||||
from .utility import DomainPermission
|
||||
|
||||
|
||||
|
@ -56,6 +57,12 @@ class DomainAddUserView(DomainPermission, FormMixin, DetailView):
|
|||
else:
|
||||
return self.form_invalid(form)
|
||||
|
||||
def _domain_abs_url(self):
|
||||
"""Get an absolute URL for this domain."""
|
||||
return self.request.build_absolute_uri(
|
||||
reverse("domain", kwargs={"pk": self.object.id})
|
||||
)
|
||||
|
||||
def _make_invitation(self, email_address):
|
||||
"""Make a Domain invitation for this email and redirect with a message."""
|
||||
invitation, created = DomainInvitation.objects.get_or_create(
|
||||
|
@ -68,7 +75,19 @@ class DomainAddUserView(DomainPermission, FormMixin, DetailView):
|
|||
f"{email_address} has already been invited to this domain.",
|
||||
)
|
||||
else:
|
||||
messages.success(self.request, f"Invited {email_address} to this domain.")
|
||||
# created a new invitation in the database, so send an email
|
||||
try:
|
||||
send_templated_email(
|
||||
"emails/domain_invitation.txt",
|
||||
to_address=email_address,
|
||||
context={"domain_url": self._domain_abs_url()},
|
||||
)
|
||||
except EmailSendingError:
|
||||
messages.warning(self.request, "Could not send email invitation.")
|
||||
else:
|
||||
messages.success(
|
||||
self.request, f"Invited {email_address} to this domain."
|
||||
)
|
||||
return redirect(self.get_success_url())
|
||||
|
||||
def form_valid(self, form):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue