Skip to content

Commit

Permalink
Organization updated email notification (#12377)
Browse files Browse the repository at this point in the history
* Relabel "Organization {name => display name}"

* Templates for "organization-updated" email

* Define send_* for "organization-updated" email

* Call send_* for "organization-updated" email

* Disable changing org from Company to Community

* Redirect instead of 404 for inactive Company orgs

Co-authored-by: Ee Durbin <ewdurbin@gmail.com>
  • Loading branch information
divbzero and ewdurbin authored Oct 19, 2022
1 parent 1df08e9 commit 8eeae12
Show file tree
Hide file tree
Showing 13 changed files with 452 additions and 64 deletions.
84 changes: 84 additions & 0 deletions tests/unit/email/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -2579,6 +2579,90 @@ def test_send_role_changed_as_organization_email(
]


class TestOrganizationUpdateEmails:
@pytest.fixture
def organization_update(self, pyramid_user):
self.user = UserFactory.create()
EmailFactory.create(user=self.user, verified=True)
self.organization_name = "example"
self.organization_display_name = "Example"
self.organization_link_url = "https://www.example.com/"
self.organization_description = "An example organization for testing"
self.organization_orgtype = "Company"
self.previous_organization_display_name = "Example Group"
self.previous_organization_link_url = "https://www.example.com/group/"
self.previous_organization_description = "An example group for testing"
self.previous_organization_orgtype = "Community"

def test_send_organization_renamed_email(
self,
db_request,
organization_update,
make_email_renderers,
send_email,
):
subject_renderer, body_renderer, html_renderer = make_email_renderers(
"organization-updated"
)

result = email.send_organization_updated_email(
db_request,
self.user,
organization_name=self.organization_name,
organization_display_name=self.organization_display_name,
organization_link_url=self.organization_link_url,
organization_description=self.organization_description,
organization_orgtype=self.organization_orgtype,
previous_organization_display_name=self.previous_organization_display_name,
previous_organization_link_url=self.previous_organization_link_url,
previous_organization_description=self.previous_organization_description,
previous_organization_orgtype=self.previous_organization_orgtype,
)

assert result == {
"organization_name": self.organization_name,
"organization_display_name": self.organization_display_name,
"organization_link_url": self.organization_link_url,
"organization_description": self.organization_description,
"organization_orgtype": self.organization_orgtype,
"previous_organization_display_name": (
self.previous_organization_display_name
),
"previous_organization_link_url": self.previous_organization_link_url,
"previous_organization_description": self.previous_organization_description,
"previous_organization_orgtype": self.previous_organization_orgtype,
}
subject_renderer.assert_(**result)
body_renderer.assert_(**result)
html_renderer.assert_(**result)
assert db_request.task.calls == [pretend.call(send_email)]
assert send_email.delay.calls == [
pretend.call(
f"{self.user.name} <{self.user.email}>",
{
"subject": subject_renderer.string_response,
"body_text": body_renderer.string_response,
"body_html": (
f"<html>\n"
f"<head></head>\n"
f"<body><p>{html_renderer.string_response}</p></body>\n"
f"</html>\n"
),
},
{
"tag": "account:email:sent",
"user_id": self.user.id,
"additional": {
"from_": db_request.registry.settings["mail.sender"],
"to": self.user.email,
"subject": subject_renderer.string_response,
"redact_ip": True,
},
},
)
]


class TestOrganizationRenameEmails:
@pytest.fixture
def organization_rename(self, pyramid_user):
Expand Down
33 changes: 30 additions & 3 deletions tests/unit/manage/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2870,14 +2870,20 @@ def test_manage_organization(
link_url=organization.link_url,
description=organization.description,
orgtype=organization.orgtype,
organization_service=organization_service,
),
]

@pytest.mark.parametrize("orgtype", list(OrganizationType))
def test_save_organization(
self, db_request, organization_service, enable_organizations, monkeypatch
self,
db_request,
pyramid_user,
orgtype,
organization_service,
enable_organizations,
monkeypatch,
):
organization = OrganizationFactory.create()
organization = OrganizationFactory.create(orgtype=orgtype)
db_request.POST = {
"display_name": organization.display_name,
"link_url": organization.link_url,
Expand All @@ -2899,13 +2905,34 @@ def test_save_organization(
)
monkeypatch.setattr(views, "SaveOrganizationForm", save_organization_cls)

send_email = pretend.call_recorder(lambda *a, **kw: None)
monkeypatch.setattr(views, "send_organization_updated_email", send_email)
monkeypatch.setattr(
views, "organization_owners", lambda *a, **kw: [pyramid_user]
)

view = views.ManageOrganizationSettingsViews(organization, db_request)
result = view.save_organization()

assert isinstance(result, HTTPSeeOther)
assert organization_service.update_organization.calls == [
pretend.call(organization.id, **db_request.POST)
]
assert send_email.calls == [
pretend.call(
db_request,
{pyramid_user},
organization_name=organization.name,
organization_display_name=organization.display_name,
organization_link_url=organization.link_url,
organization_description=organization.description,
organization_orgtype=organization.orgtype,
previous_organization_display_name=organization.display_name,
previous_organization_link_url=organization.link_url,
previous_organization_description=organization.description,
previous_organization_orgtype=organization.orgtype,
),
]

def test_save_organization_validation_fails(
self, db_request, organization_service, enable_organizations, monkeypatch
Expand Down
19 changes: 17 additions & 2 deletions tests/unit/test_predicates.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import pytest

from pyramid.exceptions import ConfigurationError
from pyramid.httpexceptions import HTTPSeeOther

from warehouse.organizations.models import OrganizationType
from warehouse.predicates import (
Expand Down Expand Up @@ -151,9 +152,16 @@ def test_inactive_organization(
organization,
enable_organizations,
):
db_request.route_path = pretend.call_recorder(
lambda *a, **kw: "/manage/organizations/"
)

organization.is_active = False
predicate = ActiveOrganizationPredicate(True, None)
assert not predicate(organization, db_request)
with pytest.raises(HTTPSeeOther):
predicate(organization, db_request)

assert db_request.route_path.calls == [pretend.call("manage.organizations")]

def test_inactive_subscription(
self,
Expand All @@ -162,8 +170,15 @@ def test_inactive_subscription(
enable_organizations,
inactive_subscription,
):
db_request.route_path = pretend.call_recorder(
lambda *a, **kw: "/manage/organizations/"
)

predicate = ActiveOrganizationPredicate(True, None)
assert not predicate(organization, db_request)
with pytest.raises(HTTPSeeOther):
predicate(organization, db_request)

assert db_request.route_path.calls == [pretend.call("manage.organizations")]

def test_active_subscription(
self, db_request, organization, enable_organizations, active_subscription
Expand Down
28 changes: 28 additions & 0 deletions warehouse/email/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,34 @@ def send_role_changed_as_organization_member_email(
}


@_email("organization-updated")
def send_organization_updated_email(
request,
user,
*,
organization_name,
organization_display_name,
organization_link_url,
organization_description,
organization_orgtype,
previous_organization_display_name,
previous_organization_link_url,
previous_organization_description,
previous_organization_orgtype,
):
return {
"organization_name": organization_name,
"organization_display_name": organization_display_name,
"organization_link_url": organization_link_url,
"organization_description": organization_description,
"organization_orgtype": organization_orgtype,
"previous_organization_display_name": previous_organization_display_name,
"previous_organization_link_url": previous_organization_link_url,
"previous_organization_description": previous_organization_description,
"previous_organization_orgtype": previous_organization_orgtype,
}


@_email("organization-renamed")
def send_organization_renamed_email(
request, user, *, organization_name, previous_organization_name
Expand Down
Loading

0 comments on commit 8eeae12

Please sign in to comment.