Copy group chairs on confirmation email when a new group document revision is submitted that changes the author set. Fixes . Commit ready for merge.

- Legacy-Id: 11877
This commit is contained in:
Robert Sparks 2016-08-25 15:52:51 +00:00
commit b988b86b1a
8 changed files with 124 additions and 20 deletions

View file

@ -32,6 +32,7 @@ from ietf.utils.history import find_history_active_at
from ietf.utils.mail import send_mail_preformatted
from ietf.utils.textupload import get_cleaned_text_file_content
from ietf.group.mails import email_admin_re_charter
from ietf.group.views import fill_in_charter_info
class ChangeStateForm(forms.Form):
charter_state = forms.ModelChoiceField(State.objects.filter(used=True, type="charter"), label="Charter state", empty_label=None, required=False)
@ -446,6 +447,7 @@ def submit(request, name, option=None):
except IOError:
pass
form = UploadForm(initial=init)
fill_in_charter_info(group)
return render(request, 'doc/charter/submit.html', {
'form': form,
'next_rev': next_rev,

View file

@ -190,7 +190,8 @@ class Recipient(models.Model):
def gather_submission_confirmers(self, **kwargs):
"""If a submitted document is revising an existing document, the confirmers
are the authors of that existing document. Otherwise, the confirmers
are the authors of that existing document, and the chairs if the document is
a working group document and the author list has changed. Otherwise, the confirmers
are the authors and submitter of the submitted document."""
addrs=[]
@ -198,7 +199,11 @@ class Recipient(models.Model):
submission = kwargs['submission']
doc=submission.existing_document()
if doc:
addrs.extend([i.author.formatted_email() for i in doc.documentauthor_set.all() if not i.author.invalid_address()])
old_authors = [i.author.formatted_email() for i in doc.documentauthor_set.all() if not i.author.invalid_address()]
new_authors = [u'"%s" <%s>' % (author["name"], author["email"]) for author in submission.authors_parsed() if author["email"]]
addrs.extend(old_authors)
if doc.group and set(old_authors)!=set(new_authors):
addrs.extend(Recipient.objects.get(slug='group_chairs').gather(**{'group':doc.group}))
else:
addrs.extend([u"%s <%s>" % (author["name"], author["email"]) for author in submission.authors_parsed() if author["email"]])
if submission.submitter_parsed()["email"]:

View file

@ -10,7 +10,7 @@ from ietf.message.models import Message
from ietf.utils.accesstoken import generate_access_token
from ietf.mailtrigger.utils import gather_address_lists
def send_submission_confirmation(request, submission):
def send_submission_confirmation(request, submission, chair_notice=False):
subject = 'Confirm submission of I-D %s' % submission.name
from_email = settings.IDSUBMIT_FROM_EMAIL
(to_email, cc) = gather_address_lists('sub_confirmation_requested',submission=submission)
@ -23,6 +23,7 @@ def send_submission_confirmation(request, submission):
'submission': submission,
'confirm_url': confirm_url,
'status_url': status_url,
'chair_notice': chair_notice,
},
cc=cc)

View file

@ -15,7 +15,7 @@ from ietf.utils.mail import outbox
from ietf.utils.test_utils import TestCase
from ietf.meeting.models import Meeting
from ietf.submit.utils import expirable_submissions, expire_submission, ensure_person_email_info_exists
from ietf.person.models import Person
from ietf.person.models import Person, Email
from ietf.group.models import Group
from ietf.doc.models import Document, DocAlias, DocEvent, State, BallotDocEvent, BallotPositionDocEvent, DocumentAuthor
from ietf.submit.models import Submission, Preapproval
@ -263,14 +263,19 @@ class SubmitTests(TestCase):
def text_submit_new_wg_txt_xml(self):
self.submit_new_wg(["txt", "xml"])
def submit_existing(self, formats):
def submit_existing(self, formats, change_authors=True):
# submit new revision of existing -> supply submitter info -> prev authors confirm
draft = make_test_data()
prev_author = draft.documentauthor_set.all()[0]
if not change_authors:
draft.documentauthor_set.all().delete()
ensure_person_email_info_exists('Author Name','author@example.com')
draft.documentauthor_set.create(author=Email.objects.get(address='author@example.com'))
else:
# Make it such that one of the previous authors has an invalid email address
bogus_email = ensure_person_email_info_exists('Bogus Person',None)
DocumentAuthor.objects.create(document=draft,author=bogus_email,order=draft.documentauthor_set.latest('order').order+1)
# Make it such that one of the previous authors has an invalid email address
bogus_email = ensure_person_email_info_exists('Bogus Person',None)
DocumentAuthor.objects.create(document=draft,author=bogus_email,order=draft.documentauthor_set.latest('order').order+1)
prev_author = draft.documentauthor_set.all()[0]
# pretend IANA reviewed it
draft.set_state(State.objects.get(used=True, type="draft-iana-review", slug="not-ok"))
@ -316,11 +321,18 @@ class SubmitTests(TestCase):
self.assertTrue("Confirm submission" in confirm_email["Subject"])
self.assertTrue(name in confirm_email["Subject"])
self.assertTrue(prev_author.author.address in confirm_email["To"])
# submitter and new author can't confirm
self.assertTrue("author@example.com" not in confirm_email["To"])
if change_authors:
self.assertTrue("author@example.com" not in confirm_email["To"])
self.assertTrue("submitter@example.com" not in confirm_email["To"])
# Verify that mail wasn't sent to know invalid addresses
self.assertTrue("unknown-email-" not in confirm_email["To"])
if change_authors:
# Since authors changed, ensure chairs are copied (and that the message says why)
self.assertTrue("chairs have been copied" in unicode(confirm_email))
self.assertTrue("mars-chairs@" in confirm_email["To"].lower())
else:
self.assertTrue("chairs have been copied" not in unicode(confirm_email))
self.assertTrue("mars-chairs@" not in confirm_email["To"].lower())
confirm_url = self.extract_confirm_url(confirm_email)
@ -373,6 +385,9 @@ class SubmitTests(TestCase):
def test_submit_existing_txt_xml(self):
self.submit_existing(["txt", "xml"])
def test_submit_existing_txt_preserve_authors(self):
self.submit_existing(["txt"],change_authors=False)
def submit_new_individual(self, formats):
# submit new -> supply submitter info -> confirm
draft = make_test_data()
@ -400,6 +415,7 @@ class SubmitTests(TestCase):
# both submitter and author get email
self.assertTrue("author@example.com" in confirm_email["To"])
self.assertTrue("submitter@example.com" in confirm_email["To"])
self.assertFalse("chairs have been copied" in unicode(confirm_email))
confirm_url = self.extract_confirm_url(outbox[-1])
@ -430,6 +446,8 @@ class SubmitTests(TestCase):
def test_submit_update_individual(self):
draft = make_test_data()
draft.group = None
draft.save_with_history([DocEvent.objects.create(doc=draft, type="added_comment", by=Person.objects.get(user__username="secretary"), desc="Test")])
replaces_count = draft.relateddocument_set.filter(relationship_id='replaces').count()
name = draft.name
rev = '%02d'%(int(draft.rev)+1)
@ -454,6 +472,7 @@ class SubmitTests(TestCase):
r = self.client.get(status_url)
self.assertEqual(len(outbox), mailbox_before + 1)
confirm_url = self.extract_confirm_url(outbox[-1])
self.assertFalse("chairs have been copied" in unicode(outbox[-1]))
mailbox_before = len(outbox)
r = self.client.post(confirm_url)
self.assertEqual(r.status_code, 302)

View file

@ -208,6 +208,13 @@ def submission_status(request, submission_id, access_token=None):
requires_prev_authors_approval = Document.objects.filter(name=submission.name)
group_authors_changed = False
doc = submission.existing_document()
if doc and doc.group:
old_authors = [i.author.formatted_email() for i in doc.documentauthor_set.all() if not i.author.invalid_address()]
new_authors = [u'"%s" <%s>' % (author["name"], author["email"]) for author in submission.authors_parsed() if author["email"]]
group_authors_changed = set(old_authors)!=set(new_authors)
message = None
if submission.state_id == "cancel":
@ -253,7 +260,7 @@ def submission_status(request, submission_id, access_token=None):
submission.state = DraftSubmissionStateName.objects.get(slug="auth")
submission.save()
sent_to = send_submission_confirmation(request, submission)
sent_to = send_submission_confirmation(request, submission, chair_notice=group_authors_changed)
if submission.state_id == "aut-appr":
desc = u"sent confirmation email to previous authors: %s" % u", ".join(sent_to)

View file

@ -10,9 +10,77 @@
{% block content %}
{% origin %}
<h1>Charter submission<br><small>{{ group.acronym }} {{ group.type.name }}</small></h1>
<h1>Charter submission</h1>
<p class="alert alert-info">The text will be submitted as <b>{{ name }}-{{ next_rev }}</b>.</p>
<table class="table table-condensed">
<tbody class="meta">
<tr>
<th>{{ group.type.name }}</th>
<th>Name</th>
<td>{{ group.name }}</td>
</tr>
<tr>
<td></td>
<th>Acronym</th>
<td>{{ group.acronym }}</td>
</tr>
<tr>
<td></td>
{% if group.parent and group.parent.type_id == "area" %}
<th>{{ group.parent.type.name }}</th>
<td>{{ group.parent.name }} ({{ group.parent.acronym }})</td>
{% else %}
<th></th><td></td>
{% endif %}
</tr>
<tr>
<td></td>
<th>State</th>
<td>
{{ group.state.name }}
{% if requested_close %}
<div class="label label-info">In the process of being closed</div>
{% endif %}
</td>
</tr>
</tbody>
<tbody class="meta">
{% for slug, label, roles in group.personnel %}
<tr>
{% if forloop.first %}
<th>Personnel</th>
{% else %}
<td></td>
{% endif %}
<th>{{ label }}</th>
<td>
{% for r in roles %}
<span class="fa fa-envelope-o"></span>
<a href="mailto:{{ r.email.address }}">{{ r.person.plain_name }}</a>
<br>
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
{% if group.list_email %}
<tbody class="meta">
<tr>
<th>Mailing list</th>
<th>Address</th><td>{{ group.list_email|urlize }}</td>
</tr>
<tr><td></td><th>To subscribe</th><td>{{ group.list_subscribe|urlize }}</td></tr>
<tr><td></td><th>Archive</th><td>{{ group.list_archive|urlize }}</td></tr>
</tbody>
{% endif %}
</table>
<p class="alert alert-info">The text will be submitted as <b>charter-ietf-{{ name }}-{{ next_rev }}</b>.</p>
<form enctype="multipart/form-data" method="post">
{% csrf_token %}

View file

@ -4,8 +4,10 @@ Hi,
The IETF datatracker draft submission service has received your draft
{{ submission.name }}-{{ submission.rev }}, and requires a
confirmation step in order to be able to complete the posting of
the draft.
the draft.{% if chair_notice %}
The chairs have been copied since this is a group document whose author list has changed.
{%endif%}
Please follow this link to the page where you can confirm the posting:
{{ confirm_url }}

View file

@ -17,7 +17,7 @@
<h3>Upload screen</h3>
<p>
The Upload screen is the first screen that a user will see when he or she starts the I-D submission process. A user can submit four different formats of an I-D, plain text, XML, PDF, and postscript, at the same time. Failure to submit a plain-text version will cause an error, and an error screen will be displayed.
The Upload screen is the first screen that a user will see when he or she starts the I-D submission process. A user can submit four different formats of an I-D, plain text, XML, PDF, and postscript, at the same time. Failure to submit at least one of a plain-text or xml version will cause an error, and an error screen will be displayed.
</p>
<p>
@ -26,7 +26,7 @@
<table class="table table-condensed table-striped">
<tr>
<th>.txt format</th>
<td>Button to select a plain-text file of an I-D from a user's local file system. A plain-text version is mandatory and leaving the field blank will cause an error.</td>
<td>Button to select a plain-text file of an I-D from a user's local file system.</td>
</tr>
<tr>
<th>.xml format</th>
@ -42,13 +42,13 @@
</tr>
<tr>
<th>Upload</th>
<td>Button to upload the document(s). The tool will begin parsing the plain-text document and validate the document. The parsed meta-data will be displayed for user confirmation along with the validation results.</td>
<td>Button to upload the document(s). The tool will begin parsing the plain-text document (or creating it from the xml if only xml is provided) and validate the document. The parsed meta-data will be displayed for user confirmation along with the validation results.</td>
</tr>
</table>
<h3>Validation screen</h3>
<p>
After a user uploads a plain-text version, or multiple versions of an I-D, the tool will parse the plain-text version, validate the I-D, and display the validation results with option(s) for next steps. The validation includes: checking for all IPR-related notices and I-D boilerplate described in <a href="https://www.ietf.org/ietf/1id-guidelines.html">Guidelines to Authors of Internet-Drafts</a>; the required sections described in <a href="https://www.ietf.org/ID-Checklist.html">the I-D Check List</a>; the version number; and the creation date.
After a user uploads the document(s), the tool will parse the plain-text version, validate the I-D, and display the validation results with option(s) for next steps. The validation includes: checking for all IPR-related notices and I-D boilerplate described in <a href="https://www.ietf.org/ietf/1id-guidelines.html">Guidelines to Authors of Internet-Drafts</a>; the required sections described in <a href="https://www.ietf.org/ID-Checklist.html">the I-D Check List</a>; the version number; and the creation date.
</p>
<p>
@ -83,7 +83,7 @@
<tr>
<th>Post now</th>
<td>
<p>Button to start the automated posting process with submitter authentication. Once clicked, an email message will be sent to the submitter whose email address was provided within the form. The submitter will need to open the email message via his or her email application, and click the link provided in the message body.</p>
<p>Button to start the automated posting process with submitter authentication. Once clicked, an email message will be sent to the parties who can verify the sybmission. For a new draft (-00), that will be the authors listed in the document. For -01 and subsequent drafts, the confirmation message is sent to the authors of the <b>previous</b> version. One of the recipients of the confirmation message will need to open the email message via his or her email application, and click the link provided in the message body.</p>
<p>Once a link in the email body is clicked, the document gets pushed to the IETF Web and FTP sites, a notification is sent to the authors of the document, and an I-D Action announcement will be sent out within the next 15 minutes.</p>
<p>If the document requires an additional approval from a chair of a working group, i.e., for submission of a 00 version of a working group document, then a message will be sent to the chairs of the working group for the approval. Once approved, the document will be immediately announced and available via the IETF Web and FTP sites.</p>
</td>