Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#3019: Portfolio and domain invitation emails [AD] #3252

Merged
merged 36 commits into from
Jan 3, 2025

Conversation

dave-kennedy-ecs
Copy link
Contributor

@dave-kennedy-ecs dave-kennedy-ecs commented Dec 19, 2024

Ticket

Resolves #3019

Changes

  • On (Portfolio) Add New Member, sends an email when creating a PortfolioInvitation.
  • In this ticket, completed the PortfolioAddNewMember view and form. Refactored the view to properly handle email sending exceptions.
  • Refactored 3 forms to inherit from BasePortfolioMemberForm, and for BasePortfolioMemberForm to inherit ModelForm.
  • On (Domain) Add Domain Manager, streamlined view to properly handle exceptions in one flow. When appropriate, sends PortfolioInvitation email to the newly added Domain Manager.
  • In Django Admin, addition of PortfolioInvitation sends email to invited email address. In the event of email sending error, new Portfolio Invitation is not saved.
  • Refactored email sending methods for portfolio invitation email and domain manager email into a separate utility file so that they can be executed from multiple views.

Context for reviewers

Setup

Code Review Verification Steps

As the original developer, I have

Satisfied acceptance criteria and met development standards

  • Met the acceptance criteria, or will meet them in a subsequent PR
  • Created/modified automated tests
  • Update documentation in READMEs and/or onboarding guide

Ensured code standards are met (Original Developer)

  • If any updated dependencies on Pipfile, also update dependencies in requirements.txt.
  • Interactions with external systems are wrapped in try/except
  • Error handling exists for unusual or missing values

Validated user-facing changes (if applicable)

  • Tag @dotgov-designers in this PR's Reviewers for design review. If code is not user-facing, delete design reviewer checklist
  • Verify new pages have been added to .pa11yci file so that they will be tested with our automated accessibility testing
  • Checked keyboard navigability
  • Tested general usability, landmarks, page header structure, and links with a screen reader (such as Voiceover or ANDI)

As a code reviewer, I have

Reviewed, tested, and left feedback about the changes

  • Pulled this branch locally and tested it
  • Verified code meets all checks above. Address any checks that are not satisfied
  • Reviewed this code and left comments. Indicate if comments must be addressed before code is merged
  • Checked that all code is adequately covered by tests
  • Verify migrations are valid and do not conflict with existing migrations

Validated user-facing changes as a developer

Note: Multiple code reviewers can share the checklists above, a second reviewer should not make a duplicate checklist. All checks should be checked before approving, even those labeled N/A.

  • New pages have been added to .pa11yci file so that they will be tested with our automated accessibility testing
  • Checked keyboard navigability
  • Meets all designs and user flows provided by design/product
  • Tested general usability, landmarks, page header structure, and links with a screen reader (such as Voiceover or ANDI)
  • (Rarely needed) Tested as both an analyst and applicant user

As a designer reviewer, I have

Verified that the changes match the design intention

  • Checked that the design translated visually
  • Checked behavior. Comment any found issues or broken flows.
  • Checked different states (empty, one, some, error)
  • Checked for landmarks, page heading structure, and links

Validated user-facing changes as a designer

  • Checked keyboard navigability
  • Tested general usability, landmarks, page header structure, and links with a screen reader (such as Voiceover or ANDI)
  • Tested with multiple browsers (check off which ones were used)
    • Chrome
    • Microsoft Edge
    • FireFox
    • Safari
  • (Rarely needed) Tested as both an analyst and applicant user

References

Screenshots

@dave-kennedy-ecs dave-kennedy-ecs changed the title [DRAFT] #3019: Portfolio and domain invitation emails [DRAFT] #3019: Portfolio and domain invitation emails [BOB] Dec 19, 2024
Copy link

🥳 Successfully deployed to developer sandbox bob.

Copy link

🥳 Successfully deployed to developer sandbox bob.

Copy link

🥳 Successfully deployed to developer sandbox bob.

Copy link

🥳 Successfully deployed to developer sandbox bob.

Copy link

🥳 Successfully deployed to developer sandbox bob.

Copy link

🥳 Successfully deployed to developer sandbox bob.

Copy link

🥳 Successfully deployed to developer sandbox bob.

Copy link

🥳 Successfully deployed to developer sandbox bob.

@CocoByte CocoByte self-assigned this Dec 30, 2024
src/registrar/admin.py Show resolved Hide resolved
src/registrar/tests/test_admin.py Outdated Show resolved Hide resolved
src/registrar/tests/test_forms.py Outdated Show resolved Hide resolved
Copy link
Contributor

@CocoByte CocoByte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am running into issues with portfolio invitation emails not getting sent (I am able to send domain request invitation emails). This happens for both existing and non-existing user e-mails.

image

Copy link
Contributor

@abroddrick abroddrick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't do a full review, just briefly skimmed the code only. No major comments, looks good and I like the implementation, I'll trust Nicolle do the full review though of course as I see she already hit some snags

if has_errors:
# Re-render the change form if there are errors or warnings
# Prepare context for rendering the change form
opts = self.model._meta
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

non blocking question why "opts"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If confusing, can change. Was modeling code after super class, django.contrib.admin.options.ModelAdmin, in which many of their methods get the options from _meta.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dave-kennedy-ecs It looks like opts is being used on line 1673 after pulling from obj (its using obj._meta instead of self.model._meta). The value for the var definition here is never actually being used, only the _meta property from obj. Seems like a typo and makes it a bit hard to follow -- can you delete the opts definition on this line?

src/registrar/admin.py Show resolved Hide resolved
src/registrar/tests/test_forms.py Show resolved Hide resolved
src/registrar/views/portfolios.py Show resolved Hide resolved
Copy link

🥳 Successfully deployed to developer sandbox bob.

@dave-kennedy-ecs dave-kennedy-ecs changed the title #3019: Portfolio and domain invitation emails [BOB] #3019: Portfolio and domain invitation emails [AD] Dec 31, 2024
@dave-kennedy-ecs
Copy link
Contributor Author

dave-kennedy-ecs commented Dec 31, 2024

@CocoByte @abroddrick I have restaged this PR on AD sandbox. Email sending appears to be broken on BOB sandbox. I have now successfully tested this branch on multiple sandboxes so think the problem is not with the branch, but with the sandbox. Please evaluate the functionality on the AD sandbox, and I have opened a ticket to investigate email sending on BOB sandbox.

@zandercymatics zandercymatics self-assigned this Jan 2, 2025
Copy link
Contributor

@zandercymatics zandercymatics left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still verifying the functionality, but here is the initial code review. Great work! Most of my suggestions are nitpicks so keep that in mind, no need to address everything if you don't view it as worth the time investment

src/registrar/admin.py Show resolved Hide resolved
src/registrar/admin.py Outdated Show resolved Hide resolved
if has_errors:
# Re-render the change form if there are errors or warnings
# Prepare context for rendering the change form
opts = self.model._meta
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dave-kennedy-ecs It looks like opts is being used on line 1673 after pulling from obj (its using obj._meta instead of self.model._meta). The value for the var definition here is never actually being used, only the _meta property from obj. Seems like a typo and makes it a bit hard to follow -- can you delete the opts definition on this line?

Comment on lines +174 to +177
common_forbidden_perms = (
set.intersection(*[set(cls.FORBIDDEN_PORTFOLIO_ROLE_PERMISSIONS.get(role, [])) for role in roles])
if roles
else set()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding this check on roles. If you recall, how did you run into this issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe I had this error when attempting to save a userportfoliopermission through django admin without specifying a role. May have run into it in one of the views though. Can't remember if both scenarios.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah weird. Thanks

src/registrar/utility/email_invitations.py Show resolved Hide resolved
Comment on lines +1205 to +1208
# COMMENT: this code does not take into account multiple portfolios flag

# COMMENT: shouldn't this code be based on the organization of the domain, not the org
# of the requestor? requestor could have multiple portfolios
Copy link
Contributor

@zandercymatics zandercymatics Jan 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm reading the original logic right, I think we shouldn't actually be doing this check at all if the multiple portfolios flag is enabled. Its basically enforcing that rule by proxy (hence why its checking on org requestor). See image

image

src/registrar/views/domain.py Show resolved Hide resolved
src/registrar/views/domain.py Outdated Show resolved Hide resolved
domain=self.object,
is_member_of_different_org=member_of_different_org,
)
DomainInvitation.objects.get_or_create(email=email, domain=self.object)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be create?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be get_or_create to account for an existing, canceled DomainInvitation

Copy link

github-actions bot commented Jan 2, 2025

🥳 Successfully deployed to developer sandbox bob.

Copy link
Contributor

@zandercymatics zandercymatics left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM though note the comments above

Copy link

github-actions bot commented Jan 2, 2025

🥳 Successfully deployed to developer sandbox bob.

Copy link

github-actions bot commented Jan 3, 2025

🥳 Successfully deployed to developer sandbox bob.

Copy link

github-actions bot commented Jan 3, 2025

🥳 Successfully deployed to developer sandbox bob.

@dave-kennedy-ecs dave-kennedy-ecs merged commit 1745f6a into main Jan 3, 2025
10 checks passed
@dave-kennedy-ecs dave-kennedy-ecs deleted the bob/3019-portfolio-invitation-email branch January 3, 2025 01:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Dev: Send email when someone is invited to a portfolio
5 participants