Skip to content

Commit 70380cb

Browse files
committed
Merged in [16672] from sasha@dashcare.nl:
Fix ietf-tools#2328 - Use mailtriggers to find destinations in review app As the review app has several conditionals that don't fit entirely well within mailtriggers, the templates use a bit of extra context to figure out who exactly to include. This also extends the tests for review, to check for correct recipients. It also adds a tiny feature to mailtrigger to entirely exclude certain addresses, as required by the review-generated mails. - Legacy-Id: 16793 Note: SVN reference [16672] has been migrated to Git commit 88b7b45
2 parents 632423a + 88b7b45 commit 70380cb

6 files changed

Lines changed: 272 additions & 117 deletions

File tree

ietf/doc/tests_review.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ def test_close_request(self):
223223
self.assertNotIn("review_request_close_comment", e.desc.lower())
224224

225225
self.assertEqual(len(outbox), 1)
226+
self.assertIn('<reviewer@example.com>', outbox[0]["To"])
227+
self.assertNotIn("<reviewsecretary@example.com>", outbox[0]["To"])
226228
mail_content = outbox[0].get_payload(decode=True).decode("utf-8").lower()
227229
self.assertIn("closed", mail_content)
228230
self.assertIn("review_request_close_comment", mail_content)
@@ -420,6 +422,7 @@ def test_assign_reviewer(self):
420422
self.assertEqual(assignment.reviewer, reviewer)
421423
self.assertEqual(assignment.state_id, "assigned")
422424
self.assertEqual(len(outbox), 1)
425+
self.assertEqual('"Some Reviewer" <reviewer@example.com>', outbox[0]["To"])
423426
self.assertTrue("assigned" in outbox[0].get_payload(decode=True).decode("utf-8"))
424427
self.assertEqual(NextReviewerInTeam.objects.get(team=review_req.team).next_reviewer, rotation_list[1])
425428

@@ -482,6 +485,8 @@ def test_reject_reviewer_assignment(self):
482485
self.assertEqual(e.type, "closed_review_assignment")
483486
self.assertTrue("rejected" in e.desc)
484487
self.assertEqual(len(outbox), 1)
488+
self.assertIn(assignment.reviewer.address, outbox[0]["To"])
489+
self.assertNotIn("<reviewsecretary@example.com>", outbox[0]["To"])
485490
self.assertTrue("Test message" in outbox[0].get_payload(decode=True).decode("utf-8"))
486491

487492
def make_test_mbox_tarball(self, review_req):
@@ -858,7 +863,8 @@ def test_partially_complete_review(self):
858863
self.assertTrue(assignment.review_request.doc.rev in assignment.review.name)
859864

860865
self.assertEqual(len(outbox), 2)
861-
self.assertTrue("reviewsecretary@example.com" in outbox[0]["To"])
866+
self.assertIn("<reviewsecretary@example.com>", outbox[0]["To"])
867+
self.assertNotIn(assignment.reviewer.address, outbox[0]["To"])
862868
self.assertTrue("partially" in outbox[0]["Subject"].lower())
863869

864870
self.assertTrue(assignment.review_request.team.list_email in outbox[1]["To"])
@@ -998,6 +1004,7 @@ def test_edit_deadline(self):
9981004
r = self.client.get(url)
9991005
self.assertEqual(r.status_code, 200)
10001006

1007+
empty_outbox()
10011008
old_deadline = review_req.deadline.date()
10021009
new_deadline = old_deadline + datetime.timedelta(days=1)
10031010
r = self.client.post(url, data={
@@ -1006,7 +1013,10 @@ def test_edit_deadline(self):
10061013
self.assertEqual(r.status_code, 302)
10071014
review_req = reload_db_objects(review_req)
10081015
self.assertEqual(review_req.deadline,new_deadline)
1009-
self.assertTrue('Deadline changed' in outbox[-1]['Subject'])
1016+
self.assertEqual(len(outbox), 1)
1017+
self.assertIn('<reviewsecretary@example.com>', outbox[0]["To"])
1018+
self.assertIn('<reviewer@example.com>', outbox[0]["To"])
1019+
self.assertIn('Deadline changed', outbox[0]['Subject'])
10101020

10111021
def test_mark_no_response(self):
10121022
assignment = ReviewAssignmentFactory()
@@ -1017,12 +1027,18 @@ def test_mark_no_response(self):
10171027
r = self.client.get(url)
10181028
self.assertEqual(r.status_code, 200)
10191029

1030+
empty_outbox()
10201031
r=self.client.post(url, data={"action":"noresponse"})
10211032
self.assertEqual(r.status_code, 302)
10221033

10231034
assignment = reload_db_objects(assignment)
10241035
self.assertEqual(assignment.state_id, 'no-response')
10251036

1037+
self.assertEqual(len(outbox), 1)
1038+
self.assertIn(assignment.reviewer.address, outbox[0]["To"])
1039+
self.assertNotIn('<reviewsecretary@example.com>', outbox[0]["To"])
1040+
self.assertIn('Reviewer assignment marked no-response', outbox[0]['Subject'])
1041+
10261042
def test_withdraw_assignment(self):
10271043
assignment = ReviewAssignmentFactory()
10281044
secr = RoleFactory(group=assignment.review_request.team,person__user__username='reviewsecretary',person__user__email='reviewsecretary@example.com',name_id='secr').person
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Copyright The IETF Trust 2019, All Rights Reserved
2+
# -*- coding: utf-8 -*-
3+
4+
from __future__ import absolute_import, print_function, unicode_literals
5+
6+
from django.db import migrations
7+
8+
def forward(apps, schema_editor):
9+
MailTrigger = apps.get_model('mailtrigger','MailTrigger')
10+
Recipient = apps.get_model('mailtrigger', 'Recipient')
11+
12+
review_assignment_reviewer = Recipient.objects.create(
13+
slug="review_assignment_reviewer",
14+
desc="The reviewer assigned to a review assignment",
15+
template="{% if not skip_review_reviewer %}{{review_assignment.reviewer.email_address}}{% endif %}",
16+
)
17+
review_assignment_review_req_by = Recipient.objects.create(
18+
slug="review_assignment_review_req_by",
19+
desc="The requester of an assigned review",
20+
template="{% if not skip_review_requested_by %}{{review_assignment.review_request.requested_by.email_address}}{% endif %}",
21+
)
22+
review_req_requested_by = Recipient.objects.create(
23+
slug="review_req_requested_by",
24+
desc="The requester of a review",
25+
template="{% if not skip_review_requested_by %}{{review_req.requested_by.email_address}}{% endif %}",
26+
)
27+
review_req_reviewers = Recipient.objects.create(
28+
slug="review_req_reviewers",
29+
desc="All reviewers assigned to a review request",
30+
template=None,
31+
)
32+
review_secretaries = Recipient.objects.create(
33+
slug="review_secretaries",
34+
desc="The secretaries of the review team of a review request or assignment",
35+
template=None,
36+
)
37+
Recipient.objects.create(
38+
slug="review_reviewer",
39+
desc="A single reviewer",
40+
template="{{reviewer.email_address}}",
41+
)
42+
43+
review_assignment_changed = MailTrigger.objects.create(
44+
slug="review_assignment_changed",
45+
desc="Recipients for a change to a review assignment",
46+
)
47+
review_assignment_changed.to.set([review_assignment_review_req_by, review_assignment_reviewer,
48+
review_secretaries])
49+
50+
review_req_changed = MailTrigger.objects.create(
51+
slug="review_req_changed",
52+
desc="Recipients for a change to a review request",
53+
)
54+
review_req_changed.to.set([review_req_requested_by, review_req_reviewers, review_secretaries])
55+
56+
review_availability_changed = MailTrigger.objects.create(
57+
slug="review_availability_changed",
58+
desc="Recipients for a change to a reviewer's availability",
59+
)
60+
review_availability_changed.to.set(
61+
Recipient.objects.filter(slug__in=['review_reviewer', 'group_secretaries'])
62+
)
63+
64+
65+
def reverse(apps, schema_editor):
66+
MailTrigger = apps.get_model('mailtrigger','MailTrigger')
67+
Recipient = apps.get_model('mailtrigger', 'Recipient')
68+
69+
MailTrigger.objects.filter(slug__in=[
70+
'review_assignment_changed', 'review_req_changed', 'review_availability_changed',
71+
]).delete()
72+
Recipient.objects.filter(slug__in=[
73+
'review_assignment_reviewer', 'review_assignment_review_req_by', 'review_req_requested_by',
74+
'review_req_reviewers', 'review_secretaries', 'review_reviewer',
75+
]).delete()
76+
77+
78+
class Migration(migrations.Migration):
79+
80+
dependencies = [
81+
('mailtrigger', '0006_sub_new_wg_00'),
82+
]
83+
84+
operations = [
85+
migrations.RunPython(forward, reverse)
86+
]

ietf/mailtrigger/models.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,20 @@ def gather_group_secretaries(self, **kwargs):
184184
else:
185185
addrs.extend(group.role_set.filter(name='secr').values_list('email__address',flat=True))
186186
return addrs
187-
187+
188+
def gather_review_req_reviewers(self, **kwargs):
189+
addrs = []
190+
if 'review_request' in kwargs:
191+
review_request = kwargs['review_request']
192+
for assignment in review_request.reviewassignment_set.all():
193+
addrs.append(assignment.reviewer.formatted_email())
194+
return addrs
195+
196+
def gather_review_secretaries(self, **kwargs):
197+
if not kwargs.get('skip_secretary'):
198+
return self.gather_group_secretaries(**kwargs)
199+
return []
200+
188201
def gather_doc_group_responsible_directors(self, **kwargs):
189202
addrs = []
190203
if 'doc' in kwargs:

ietf/mailtrigger/utils.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# Copyright The IETF Trust 2015-2019, All Rights Reserved
2+
13
from collections import namedtuple
24

35
import debug # pyflakes:ignore
@@ -17,18 +19,22 @@ def as_strings(self,compact=True):
1719

1820
return namedtuple('AddrListsAsStrings',['to','cc'])(to=to_string,cc=cc_string)
1921

20-
def gather_address_lists(slug, **kwargs):
22+
def gather_address_lists(slug, skipped_recipients=None, **kwargs):
2123
mailtrigger = MailTrigger.objects.get(slug=slug)
2224

2325
to = set()
2426
for recipient in mailtrigger.to.all():
2527
to.update(recipient.gather(**kwargs))
2628
to.discard('')
29+
if skipped_recipients:
30+
to -= set(skipped_recipients)
2731

2832
cc = set()
2933
for recipient in mailtrigger.cc.all():
3034
cc.update(recipient.gather(**kwargs))
3135
cc.discard('')
36+
if skipped_recipients:
37+
cc -= set(skipped_recipients)
3238

3339
return AddrLists(to=list(to),cc=list(cc))
3440

ietf/name/fixtures/names.json

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3956,6 +3956,19 @@
39563956
"model": "mailtrigger.mailtrigger",
39573957
"pk": "resurrection_requested"
39583958
},
3959+
{
3960+
"fields": {
3961+
"cc": [],
3962+
"desc": "Recipients for a change to a review assignment",
3963+
"to": [
3964+
"review_assignment_reviewer",
3965+
"review_assignment_review_req_by",
3966+
"review_secretaries"
3967+
]
3968+
},
3969+
"model": "mailtrigger.mailtrigger",
3970+
"pk": "review_assignment_changed"
3971+
},
39593972
{
39603973
"fields": {
39613974
"cc": [],
@@ -3967,6 +3980,18 @@
39673980
"model": "mailtrigger.mailtrigger",
39683981
"pk": "review_assignments_summarized"
39693982
},
3983+
{
3984+
"fields": {
3985+
"cc": [],
3986+
"desc": "Recipients for a change to a reviewer's availability",
3987+
"to": [
3988+
"review_reviewer",
3989+
"group_secretaries"
3990+
]
3991+
},
3992+
"model": "mailtrigger.mailtrigger",
3993+
"pk": "review_availability_changed"
3994+
},
39703995
{
39713996
"fields": {
39723997
"cc": [
@@ -3994,6 +4019,19 @@
39944019
"model": "mailtrigger.mailtrigger",
39954020
"pk": "review_notify_ad"
39964021
},
4022+
{
4023+
"fields": {
4024+
"cc": [],
4025+
"desc": "Recipients for a change to a review request",
4026+
"to": [
4027+
"review_req_requested_by",
4028+
"review_req_reviewers",
4029+
"review_secretaries"
4030+
]
4031+
},
4032+
"model": "mailtrigger.mailtrigger",
4033+
"pk": "review_req_changed"
4034+
},
39974035
{
39984036
"fields": {
39994037
"cc": [
@@ -4646,6 +4684,22 @@
46464684
"model": "mailtrigger.recipient",
46474685
"pk": "nominee"
46484686
},
4687+
{
4688+
"fields": {
4689+
"desc": "The requester of an assigned review",
4690+
"template": "{% if not skip_review_requested_by %}{{review_assignment.review_request.requested_by.email_address}}{% endif %}"
4691+
},
4692+
"model": "mailtrigger.recipient",
4693+
"pk": "review_assignment_review_req_by"
4694+
},
4695+
{
4696+
"fields": {
4697+
"desc": "The reviewer assigned to a review assignment",
4698+
"template": "{% if not skip_review_reviewer %}{{review_assignment.reviewer.email_address}}{% endif %}"
4699+
},
4700+
"model": "mailtrigger.recipient",
4701+
"pk": "review_assignment_reviewer"
4702+
},
46494703
{
46504704
"fields": {
46514705
"desc": "The reviewed document's responsible area director",
@@ -4670,6 +4724,38 @@
46704724
"model": "mailtrigger.recipient",
46714725
"pk": "review_doc_group_mail_list"
46724726
},
4727+
{
4728+
"fields": {
4729+
"desc": "The requester of a review",
4730+
"template": "{% if not skip_review_requested_by %}{{review_req.requested_by.email_address}}{% endif %}"
4731+
},
4732+
"model": "mailtrigger.recipient",
4733+
"pk": "review_req_requested_by"
4734+
},
4735+
{
4736+
"fields": {
4737+
"desc": "All reviewers assigned to a review request",
4738+
"template": null
4739+
},
4740+
"model": "mailtrigger.recipient",
4741+
"pk": "review_req_reviewers"
4742+
},
4743+
{
4744+
"fields": {
4745+
"desc": "A single reviewer",
4746+
"template": "{{reviewer.email_address}}"
4747+
},
4748+
"model": "mailtrigger.recipient",
4749+
"pk": "review_reviewer"
4750+
},
4751+
{
4752+
"fields": {
4753+
"desc": "The secretaries of the review team of a review request or assignment",
4754+
"template": null
4755+
},
4756+
"model": "mailtrigger.recipient",
4757+
"pk": "review_secretaries"
4758+
},
46734759
{
46744760
"fields": {
46754761
"desc": "The ADs of the team reviewing the document",

0 commit comments

Comments
 (0)