updates to complete initial implementation of invitation emails to admins

This commit is contained in:
David Kennedy 2025-01-30 15:06:00 -05:00
parent f62dd762e8
commit 4ce9efffcd
No known key found for this signature in database
GPG key ID: 6528A5386E66B96B
5 changed files with 50 additions and 19 deletions

View file

@ -1543,7 +1543,9 @@ class DomainInvitationAdmin(BaseInvitationAdmin):
and not member_of_this_org and not member_of_this_org
and not member_of_a_different_org and not member_of_a_different_org
): ):
send_portfolio_invitation_email(email=requested_email, requestor=requestor, portfolio=domain_org) send_portfolio_invitation_email(
email=requested_email, requestor=requestor, portfolio=domain_org, is_admin_invitation=False
)
portfolio_invitation, _ = PortfolioInvitation.objects.get_or_create( portfolio_invitation, _ = PortfolioInvitation.objects.get_or_create(
email=requested_email, email=requested_email,
portfolio=domain_org, portfolio=domain_org,
@ -1638,6 +1640,7 @@ class PortfolioInvitationAdmin(BaseInvitationAdmin):
portfolio = obj.portfolio portfolio = obj.portfolio
requested_email = obj.email requested_email = obj.email
requestor = request.user requestor = request.user
is_admin_invitation = UserPortfolioRoleChoices.ORGANIZATION_ADMIN in obj.roles
# Look up a user with that email # Look up a user with that email
requested_user = get_requested_user(requested_email) requested_user = get_requested_user(requested_email)
@ -1647,7 +1650,15 @@ class PortfolioInvitationAdmin(BaseInvitationAdmin):
try: try:
if not permission_exists: if not permission_exists:
# if permission does not exist for a user with requested_email, send email # if permission does not exist for a user with requested_email, send email
send_portfolio_invitation_email(email=requested_email, requestor=requestor, portfolio=portfolio) if not send_portfolio_invitation_email(
email=requested_email,
requestor=requestor,
portfolio=portfolio,
is_admin_invitation=is_admin_invitation,
):
messages.warning(
self.request, "Could not send email notification to existing organization admins."
)
# if user exists for email, immediately retrieve portfolio invitation upon creation # if user exists for email, immediately retrieve portfolio invitation upon creation
if requested_user is not None: if requested_user is not None:
obj.retrieve() obj.retrieve()

View file

@ -16,7 +16,7 @@ class DomainInvitationEmail(unittest.TestCase):
@patch("registrar.utility.email_invitations.send_templated_email") @patch("registrar.utility.email_invitations.send_templated_email")
@patch("registrar.utility.email_invitations.UserDomainRole.objects.filter") @patch("registrar.utility.email_invitations.UserDomainRole.objects.filter")
@patch("registrar.utility.email_invitations._validate_invitation") @patch("registrar.utility.email_invitations._validate_invitation")
@patch("registrar.utility.email_invitations.get_requestor_email") @patch("registrar.utility.email_invitations._get_requestor_email")
@patch("registrar.utility.email_invitations.send_invitation_email") @patch("registrar.utility.email_invitations.send_invitation_email")
@patch("registrar.utility.email_invitations.normalize_domains") @patch("registrar.utility.email_invitations.normalize_domains")
def test_send_domain_invitation_email( def test_send_domain_invitation_email(
@ -81,7 +81,7 @@ class DomainInvitationEmail(unittest.TestCase):
@patch("registrar.utility.email_invitations.send_templated_email") @patch("registrar.utility.email_invitations.send_templated_email")
@patch("registrar.utility.email_invitations.UserDomainRole.objects.filter") @patch("registrar.utility.email_invitations.UserDomainRole.objects.filter")
@patch("registrar.utility.email_invitations._validate_invitation") @patch("registrar.utility.email_invitations._validate_invitation")
@patch("registrar.utility.email_invitations.get_requestor_email") @patch("registrar.utility.email_invitations._get_requestor_email")
@patch("registrar.utility.email_invitations.send_invitation_email") @patch("registrar.utility.email_invitations.send_invitation_email")
@patch("registrar.utility.email_invitations.normalize_domains") @patch("registrar.utility.email_invitations.normalize_domains")
def test_send_domain_invitation_email_multiple_domains( def test_send_domain_invitation_email_multiple_domains(
@ -197,7 +197,7 @@ class DomainInvitationEmail(unittest.TestCase):
mock_validate_invitation.assert_called_once() mock_validate_invitation.assert_called_once()
@less_console_noise_decorator @less_console_noise_decorator
@patch("registrar.utility.email_invitations.get_requestor_email") @patch("registrar.utility.email_invitations._get_requestor_email")
def test_send_domain_invitation_email_raises_get_requestor_email_exception(self, mock_get_requestor_email): def test_send_domain_invitation_email_raises_get_requestor_email_exception(self, mock_get_requestor_email):
"""Test sending domain invitation email for one domain and assert exception """Test sending domain invitation email for one domain and assert exception
when get_requestor_email fails. when get_requestor_email fails.
@ -217,7 +217,7 @@ class DomainInvitationEmail(unittest.TestCase):
@less_console_noise_decorator @less_console_noise_decorator
@patch("registrar.utility.email_invitations._validate_invitation") @patch("registrar.utility.email_invitations._validate_invitation")
@patch("registrar.utility.email_invitations.get_requestor_email") @patch("registrar.utility.email_invitations._get_requestor_email")
@patch("registrar.utility.email_invitations.send_invitation_email") @patch("registrar.utility.email_invitations.send_invitation_email")
@patch("registrar.utility.email_invitations.normalize_domains") @patch("registrar.utility.email_invitations.normalize_domains")
def test_send_domain_invitation_email_raises_sending_email_exception( def test_send_domain_invitation_email_raises_sending_email_exception(
@ -267,7 +267,7 @@ class DomainInvitationEmail(unittest.TestCase):
@less_console_noise_decorator @less_console_noise_decorator
@patch("registrar.utility.email_invitations.send_emails_to_domain_managers") @patch("registrar.utility.email_invitations.send_emails_to_domain_managers")
@patch("registrar.utility.email_invitations._validate_invitation") @patch("registrar.utility.email_invitations._validate_invitation")
@patch("registrar.utility.email_invitations.get_requestor_email") @patch("registrar.utility.email_invitations._get_requestor_email")
@patch("registrar.utility.email_invitations.send_invitation_email") @patch("registrar.utility.email_invitations.send_invitation_email")
@patch("registrar.utility.email_invitations.normalize_domains") @patch("registrar.utility.email_invitations.normalize_domains")
def test_send_domain_invitation_email_manager_emails_send_mail_exception( def test_send_domain_invitation_email_manager_emails_send_mail_exception(

View file

@ -1,6 +1,7 @@
from datetime import date from datetime import date
from django.conf import settings from django.conf import settings
from registrar.models import Domain, DomainInvitation, UserDomainRole from registrar.models import Domain, DomainInvitation, UserDomainRole
from registrar.models.portfolio import Portfolio
from registrar.models.user_portfolio_permission import UserPortfolioPermission from registrar.models.user_portfolio_permission import UserPortfolioPermission
from registrar.models.utility.portfolio_helper import UserPortfolioRoleChoices from registrar.models.utility.portfolio_helper import UserPortfolioRoleChoices
from registrar.utility.errors import ( from registrar.utility.errors import (
@ -40,7 +41,7 @@ def send_domain_invitation_email(
EmailSendingError: If there is an error while sending the email. EmailSendingError: If there is an error while sending the email.
""" """
domains = normalize_domains(domains) domains = normalize_domains(domains)
requestor_email = get_requestor_email(requestor, domains=domains) requestor_email = _get_requestor_email(requestor, domains=domains)
_validate_invitation(email, requested_user, domains, requestor, is_member_of_different_org) _validate_invitation(email, requested_user, domains, requestor, is_member_of_different_org)
@ -99,7 +100,7 @@ def normalize_domains(domains: Domain | list[Domain]) -> list[Domain]:
return [domains] if isinstance(domains, Domain) else domains return [domains] if isinstance(domains, Domain) else domains
def get_requestor_email(requestor, domains=None, portfolio=None): def _get_requestor_email(requestor, domains=None, portfolio=None):
"""Get the requestor's email or raise an error if it's missing. """Get the requestor's email or raise an error if it's missing.
If the requestor is staff, default email is returned. If the requestor is staff, default email is returned.
@ -196,7 +197,7 @@ def send_portfolio_invitation_email(email: str, requestor, portfolio, is_admin_i
EmailSendingError: If there is an error while sending the email. EmailSendingError: If there is an error while sending the email.
""" """
requestor_email = get_requestor_email(requestor, portfolio=portfolio) requestor_email = _get_requestor_email(requestor, portfolio=portfolio)
try: try:
send_templated_email( send_templated_email(
@ -217,18 +218,29 @@ def send_portfolio_invitation_email(email: str, requestor, portfolio, is_admin_i
all_admin_emails_sent = True all_admin_emails_sent = True
# send emails to portfolio admins # send emails to portfolio admins
if is_admin_invitation: if is_admin_invitation:
all_admin_emails_sent = send_portfolio_admin_addition_emails_to_portfolio_admins( all_admin_emails_sent = _send_portfolio_admin_addition_emails_to_portfolio_admins(
email=email, email=email,
requestor_email=requestor_email, requestor_email=requestor_email,
portfolio=portfolio, portfolio=portfolio,
requested_user=None,
) )
return all_admin_emails_sent return all_admin_emails_sent
def send_portfolio_admin_addition_emails_to_portfolio_admins( def send_portfolio_admin_addition_emails(email: str, requestor, portfolio: Portfolio):
email: str, requestor_email, portfolio: Domain, requested_user=None """
): Notifies all portfolio admins of the provided portfolio of a newly invited portfolio admin
Returns:
Boolean indicating if all messages were sent successfully.
Raises:
MissingEmailError
"""
requestor_email = _get_requestor_email(requestor, portfolio=portfolio)
return _send_portfolio_admin_addition_emails_to_portfolio_admins(email, requestor_email, portfolio)
def _send_portfolio_admin_addition_emails_to_portfolio_admins(email: str, requestor_email, portfolio: Portfolio):
""" """
Notifies all portfolio admins of the provided portfolio of a newly invited portfolio admin Notifies all portfolio admins of the provided portfolio of a newly invited portfolio admin

View file

@ -1206,7 +1206,9 @@ class DomainAddUserView(DomainFormBaseView):
and requestor_can_update_portfolio and requestor_can_update_portfolio
and not member_of_this_org and not member_of_this_org
): ):
send_portfolio_invitation_email(email=requested_email, requestor=requestor, portfolio=domain_org) send_portfolio_invitation_email(
email=requested_email, requestor=requestor, portfolio=domain_org, is_admin_invitation=False
)
portfolio_invitation, _ = PortfolioInvitation.objects.get_or_create( portfolio_invitation, _ = PortfolioInvitation.objects.get_or_create(
email=requested_email, portfolio=domain_org, roles=[UserPortfolioRoleChoices.ORGANIZATION_MEMBER] email=requested_email, portfolio=domain_org, roles=[UserPortfolioRoleChoices.ORGANIZATION_MEMBER]
) )

View file

@ -15,7 +15,11 @@ from registrar.models.user_domain_role import UserDomainRole
from registrar.models.user_portfolio_permission import UserPortfolioPermission from registrar.models.user_portfolio_permission import UserPortfolioPermission
from registrar.models.utility.portfolio_helper import UserPortfolioPermissionChoices, UserPortfolioRoleChoices from registrar.models.utility.portfolio_helper import UserPortfolioPermissionChoices, UserPortfolioRoleChoices
from registrar.utility.email import EmailSendingError from registrar.utility.email import EmailSendingError
from registrar.utility.email_invitations import send_domain_invitation_email, send_portfolio_admin_addition_emails, send_portfolio_invitation_email from registrar.utility.email_invitations import (
send_domain_invitation_email,
send_portfolio_admin_addition_emails,
send_portfolio_invitation_email,
)
from registrar.utility.errors import MissingEmailError from registrar.utility.errors import MissingEmailError
from registrar.utility.enums import DefaultUserValues from registrar.utility.enums import DefaultUserValues
from registrar.views.utility.mixins import PortfolioMemberPermission from registrar.views.utility.mixins import PortfolioMemberPermission
@ -418,9 +422,11 @@ class PortfolioInvitedMemberEditView(PortfolioMemberEditPermissionView, View):
if not send_portfolio_admin_addition_emails( if not send_portfolio_admin_addition_emails(
email=portfolio_invitation.email, email=portfolio_invitation.email,
requestor=request.user, requestor=request.user,
portfolio=portfolio_invitation.portfolio portfolio=portfolio_invitation.portfolio,
): ):
messages.warning(self.request, "Could not send email notification to existing organization admins.") messages.warning(
self.request, "Could not send email notification to existing organization admins."
)
elif form.is_change_from_admin_to_member(): elif form.is_change_from_admin_to_member():
# NOTE: need to add portfolio_admin_removal_emails when ready # NOTE: need to add portfolio_admin_removal_emails when ready
pass pass