diff --git a/ietf/doc/mails.py b/ietf/doc/mails.py index a78bb9d58..2dab704ee 100644 --- a/ietf/doc/mails.py +++ b/ietf/doc/mails.py @@ -28,7 +28,18 @@ def email_state_changed(request, doc, text, mailtrigger_id=None): dict(text=text, url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url()), cc=cc) - + +def email_ad_approved_doc(request, doc, text): + to = "iesg@iesg.org" + bcc = "iesg-secretary@ietf.org" + frm = request.user.person.formatted_email() + send_mail(request, to, frm, + "Approved: %s" % doc.filename_with_rev(), + "doc/mail/ad_approval_email.txt", + dict(text=text, + docname=doc.filename_with_rev()), + bcc=bcc) + def email_stream_changed(request, doc, old_stream, new_stream, text=""): """Email the change text to the notify group and to the stream chairs""" streams = [] diff --git a/ietf/doc/tests_draft.py b/ietf/doc/tests_draft.py index faf5bfe87..0ba88a7c2 100644 --- a/ietf/doc/tests_draft.py +++ b/ietf/doc/tests_draft.py @@ -26,6 +26,47 @@ from ietf.utils.test_utils import TestCase class ChangeStateTests(TestCase): + def test_ad_approved(self): + # get a draft in iesg evaluation, point raised + draft = make_test_data() + draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="iesg-eva")) + draft.tags.add("point") + + url = urlreverse('doc_change_state', kwargs=dict(name=draft.name)) + login_testing_unauthorized(self, "ad", url) + + # normal get + r = self.client.get(url) + self.assertEqual(r.status_code, 200) + q = PyQuery(r.content) + self.assertEqual(len(q('form select[name=state]')), 1) + + events_before = draft.docevent_set.count() + mailbox_before = len(outbox) + + # set it to approved with no substate + r = self.client.post(url, + dict(state=State.objects.get(used=True, type="draft-iesg", slug="approved").pk, + substate="", + comment="Test comment")) + self.assertEqual(r.status_code, 302) + + draft = Document.objects.get(name=draft.name) + + # should now be in approved with no substate + self.assertEqual(draft.get_state_slug("draft-iesg"), "approved") + self.assertTrue(not draft.tags.filter(slug="approved")) + self.assertFalse(draft.tags.exists()) + self.assertEqual(draft.docevent_set.count(), events_before + 2) + self.assertTrue("Test comment" in draft.docevent_set.all()[0].desc) + self.assertTrue("IESG state changed" in draft.docevent_set.all()[1].desc) + + # should have sent two emails, the second one to the iesg with approved message + self.assertEqual(len(outbox), mailbox_before + 2) + self.assertTrue("Approved: " in outbox[-1]['Subject']) + self.assertTrue(draft.name in outbox[-1]['Subject']) + self.assertTrue('iesg@' in outbox[-1]['To']) + def test_change_state(self): draft = make_test_data() draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="ad-eval")) diff --git a/ietf/doc/views_draft.py b/ietf/doc/views_draft.py index 9373cbc32..f196d1d72 100644 --- a/ietf/doc/views_draft.py +++ b/ietf/doc/views_draft.py @@ -22,7 +22,7 @@ from ietf.doc.mails import ( email_pulled_from_rfc_queue, email_resurrect_reques email_resurrection_completed, email_state_changed, email_stream_changed, email_stream_state_changed, email_stream_tags_changed, extra_automation_headers, generate_publication_request, email_adopted, email_intended_status_changed, - email_iesg_processing_document ) + email_iesg_processing_document, email_ad_approved_doc ) from ietf.doc.utils import ( add_state_change_event, can_adopt_draft, get_tags_for_stream_id, nice_consensus, update_reminder, update_telechat, make_notify_changed_event, get_initial_notify, @@ -69,6 +69,7 @@ def change_state(request, name): """Change IESG state of Internet Draft, notifying parties as necessary and logging the change as a comment.""" doc = get_object_or_404(Document, docalias__name=name) + if (not doc.latest_event(type="started_iesg_process")) or doc.get_state_slug() == "expired": raise Http404 @@ -77,6 +78,7 @@ def change_state(request, name): if request.method == 'POST': form = ChangeStateForm(request.POST) form.docname=name + if form.is_valid(): new_state = form.cleaned_data['state'] prev_state = doc.get_state("draft-iesg") @@ -84,6 +86,7 @@ def change_state(request, name): tag = form.cleaned_data['substate'] comment = form.cleaned_data['comment'].strip() + # tag handling is a bit awkward since the UI still works # as if IESG tags are a substate prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS) @@ -114,7 +117,9 @@ def change_state(request, name): doc.save() email_state_changed(request, doc, msg,'doc_state_edited') - + + if new_state.slug == "approved" and new_tags == [] and has_role(request.user, "Area Director"): + email_ad_approved_doc(request, doc, comment) if prev_state and prev_state.slug in ("ann", "rfcqueue") and new_state.slug not in ("rfcqueue", "pub"): email_pulled_from_rfc_queue(request, doc, comment, prev_state, new_state) diff --git a/ietf/templates/doc/mail/ad_approval_email.txt b/ietf/templates/doc/mail/ad_approval_email.txt new file mode 100644 index 000000000..7c7564708 --- /dev/null +++ b/ietf/templates/doc/mail/ad_approval_email.txt @@ -0,0 +1,10 @@ +{% load mail_filters %}{% autoescape off %} +{% filter wordwrap:73 %}Secretary (Bcc'ed): + +{{ docname }} has been approved. + +{{ text }} + +{% endfilter %} + +{% endautoescape%}