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_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(
email=requested_email,
portfolio=domain_org,
@ -1638,6 +1640,7 @@ class PortfolioInvitationAdmin(BaseInvitationAdmin):
portfolio = obj.portfolio
requested_email = obj.email
requestor = request.user
is_admin_invitation = UserPortfolioRoleChoices.ORGANIZATION_ADMIN in obj.roles
# Look up a user with that email
requested_user = get_requested_user(requested_email)
@ -1647,7 +1650,15 @@ class PortfolioInvitationAdmin(BaseInvitationAdmin):
try:
if not permission_exists:
# 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 requested_user is not None:
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.UserDomainRole.objects.filter")
@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.normalize_domains")
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.UserDomainRole.objects.filter")
@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.normalize_domains")
def test_send_domain_invitation_email_multiple_domains(
@ -197,7 +197,7 @@ class DomainInvitationEmail(unittest.TestCase):
mock_validate_invitation.assert_called_once()
@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):
"""Test sending domain invitation email for one domain and assert exception
when get_requestor_email fails.
@ -217,7 +217,7 @@ class DomainInvitationEmail(unittest.TestCase):
@less_console_noise_decorator
@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.normalize_domains")
def test_send_domain_invitation_email_raises_sending_email_exception(
@ -267,7 +267,7 @@ class DomainInvitationEmail(unittest.TestCase):
@less_console_noise_decorator
@patch("registrar.utility.email_invitations.send_emails_to_domain_managers")
@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.normalize_domains")
def test_send_domain_invitation_email_manager_emails_send_mail_exception(

View file

@ -1,6 +1,7 @@
from datetime import date
from django.conf import settings
from registrar.models import Domain, DomainInvitation, UserDomainRole
from registrar.models.portfolio import Portfolio
from registrar.models.user_portfolio_permission import UserPortfolioPermission
from registrar.models.utility.portfolio_helper import UserPortfolioRoleChoices
from registrar.utility.errors import (
@ -40,7 +41,7 @@ def send_domain_invitation_email(
EmailSendingError: If there is an error while sending the email.
"""
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)
@ -99,7 +100,7 @@ def normalize_domains(domains: Domain | list[Domain]) -> list[Domain]:
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.
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.
"""
requestor_email = get_requestor_email(requestor, portfolio=portfolio)
requestor_email = _get_requestor_email(requestor, portfolio=portfolio)
try:
send_templated_email(
@ -217,18 +218,29 @@ def send_portfolio_invitation_email(email: str, requestor, portfolio, is_admin_i
all_admin_emails_sent = True
# send emails to portfolio admins
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,
requestor_email=requestor_email,
portfolio=portfolio,
requested_user=None,
)
return all_admin_emails_sent
def send_portfolio_admin_addition_emails_to_portfolio_admins(
email: str, requestor_email, portfolio: Domain, requested_user=None
):
def send_portfolio_admin_addition_emails(email: str, requestor, portfolio: Portfolio):
"""
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

View file

@ -1206,7 +1206,9 @@ class DomainAddUserView(DomainFormBaseView):
and requestor_can_update_portfolio
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(
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.utility.portfolio_helper import UserPortfolioPermissionChoices, UserPortfolioRoleChoices
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.enums import DefaultUserValues
from registrar.views.utility.mixins import PortfolioMemberPermission
@ -418,9 +422,11 @@ class PortfolioInvitedMemberEditView(PortfolioMemberEditPermissionView, View):
if not send_portfolio_admin_addition_emails(
email=portfolio_invitation.email,
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():
# NOTE: need to add portfolio_admin_removal_emails when ready
pass