Changed the draft submission form and views so that an email address is required for each author in order to complete self-service draft submission. It is possible to add these as metadata updates, but this will lead to submission through the secretariat (and the email addresses will still be required). Also updated related templates to make the handling of form section headings more consistent.
- Legacy-Id: 16745
This commit is contained in:
parent
1efd28752c
commit
78889979a1
5
PLAN
5
PLAN
|
@ -7,11 +7,6 @@ Updated: $Date$
|
|||
Planned work in rough order
|
||||
===========================
|
||||
|
||||
* Change the draft submission form so that an email address is required for
|
||||
each author in order to complete self-service draft submission. Missing
|
||||
email address(es) will lead to failure, and require submission via the
|
||||
secretariat (where email addresses for all will also be required).
|
||||
|
||||
* Simplify submission if submitter is logged into the datatracker, skipping the
|
||||
email verification step.
|
||||
|
||||
|
|
|
@ -403,7 +403,6 @@ class AuthorForm(NameEmailForm):
|
|||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AuthorForm, self).__init__(*args, **kwargs)
|
||||
self.fields["email"].required = False
|
||||
|
||||
class SubmitterForm(NameEmailForm):
|
||||
#Fields for secretariat only
|
||||
|
|
|
@ -53,7 +53,7 @@ def submission_file(name, rev, group, format, templatename, author=None, email=N
|
|||
if author is None:
|
||||
author = PersonFactory()
|
||||
if email is None:
|
||||
email = author.email().address.lower()
|
||||
email = author.email().address.lower() if author.email() else None
|
||||
if title is None:
|
||||
title = "Test Document"
|
||||
if year is None:
|
||||
|
@ -754,7 +754,7 @@ class SubmitTests(TestCase):
|
|||
"authors-1-name": "Person 2",
|
||||
"authors-1-email": "person2@example.com",
|
||||
"authors-2-name": "Person 3",
|
||||
"authors-2-email": "",
|
||||
"authors-2-email": "person3@example.com",
|
||||
"authors-prefix": ["authors-", "authors-0", "authors-1", "authors-2"],
|
||||
})
|
||||
self.assertNoFormPostErrors(r, ".has-error,.alert-danger")
|
||||
|
@ -776,7 +776,7 @@ class SubmitTests(TestCase):
|
|||
self.assertEqual(authors[1]["name"], "Person 2")
|
||||
self.assertEqual(authors[1]["email"], "person2@example.com")
|
||||
self.assertEqual(authors[2]["name"], "Person 3")
|
||||
self.assertEqual(authors[2]["email"], "")
|
||||
self.assertEqual(authors[2]["email"], "person3@example.com")
|
||||
|
||||
self.assertEqual(len(outbox), mailbox_before + 1)
|
||||
self.assertTrue("Manual Post Requested" in outbox[-1]["Subject"])
|
||||
|
@ -1038,20 +1038,62 @@ class SubmitTests(TestCase):
|
|||
|
||||
self.assertIn('The idnits check returned 1 warning', m)
|
||||
|
||||
def test_submit_missing_author_email(self):
|
||||
name = "draft-authorname-testing-noemail"
|
||||
rev = "00"
|
||||
group = None
|
||||
|
||||
author = PersonFactory()
|
||||
for e in author.email_set.all():
|
||||
e.delete()
|
||||
|
||||
files = {"txt": submission_file(name, rev, group, "txt", "test_submission.txt", author=author, ascii=False)[0] }
|
||||
|
||||
# submit
|
||||
url = urlreverse('ietf.submit.views.upload_submission')
|
||||
r = self.client.post(url, files)
|
||||
self.assertEqual(r.status_code, 302)
|
||||
status_url = r["Location"]
|
||||
r = self.client.get(status_url)
|
||||
q = PyQuery(r.content)
|
||||
m = q('p.text-danger').text()
|
||||
|
||||
self.assertIn('Author email error', m)
|
||||
self.assertIn('Found no email address.', m)
|
||||
|
||||
def test_submit_bad_author_email(self):
|
||||
name = "draft-authorname-testing-bademail"
|
||||
rev = "00"
|
||||
group = None
|
||||
|
||||
author = PersonFactory()
|
||||
email = author.email_set.first()
|
||||
email.address = '@bad.email'
|
||||
email.save()
|
||||
|
||||
files = {"xml": submission_file(name, rev, group, "xml", "test_submission.xml", author=author, ascii=False)[0] }
|
||||
|
||||
# submit
|
||||
url = urlreverse('ietf.submit.views.upload_submission')
|
||||
r = self.client.post(url, files)
|
||||
self.assertEqual(r.status_code, 302)
|
||||
status_url = r["Location"]
|
||||
r = self.client.get(status_url)
|
||||
q = PyQuery(r.content)
|
||||
m = q('p.text-danger').text()
|
||||
|
||||
self.assertIn('Author email error', m)
|
||||
self.assertIn('Invalid email address.', m)
|
||||
|
||||
def test_submit_invalid_yang(self):
|
||||
name = "draft-yang-testing-invalid"
|
||||
rev = "00"
|
||||
group = None
|
||||
|
||||
# get
|
||||
url = urlreverse('ietf.submit.views.upload_submission')
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
|
||||
# submit
|
||||
files = {"txt": submission_file(name, rev, group, "txt", "test_submission_invalid_yang.txt") }
|
||||
files = {"txt": submission_file(name, rev, group, "txt", "test_submission_invalid_yang.txt")[0] }
|
||||
|
||||
url = urlreverse('ietf.submit.views.upload_submission')
|
||||
r = self.client.post(url, files)
|
||||
self.assertEqual(r.status_code, 302)
|
||||
status_url = r["Location"]
|
||||
|
|
|
@ -72,6 +72,30 @@ def validate_submission(submission):
|
|||
if error:
|
||||
errors['document_date'] = error
|
||||
|
||||
# author email addresses
|
||||
author_error_count = 0
|
||||
seen = set()
|
||||
for author in submission.authors:
|
||||
email = author['email']
|
||||
author['errors'] = []
|
||||
if not email:
|
||||
author['errors'].append("Found no email address. A valid email address is required.")
|
||||
author_error_count += 1
|
||||
else:
|
||||
try:
|
||||
validate_email(email)
|
||||
except ValidationError:
|
||||
author['errors'].append("Invalid email address. A valid email address is required.")
|
||||
author_error_count += 1
|
||||
if email in seen:
|
||||
author['errors'].append("Duplicate email address. A unique email address is required.")
|
||||
author_error_count += 1
|
||||
else:
|
||||
seen.add(email)
|
||||
|
||||
if author_error_count:
|
||||
errors['authors'] = "Author email error (see below)" if author_error_count == 1 else "Author email errors (see below)"
|
||||
|
||||
return errors
|
||||
|
||||
def has_been_replaced_by(name):
|
||||
|
|
|
@ -70,7 +70,6 @@
|
|||
|
||||
{% bootstrap_form edit_form %}
|
||||
|
||||
<h3>Submitter</h3>
|
||||
{% include "submit/submitter_form.html" %}
|
||||
{% include "submit/replaces_form.html" %}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{% for field in replaces_form %}
|
||||
<h3>Replacement information</h3>
|
||||
<tr{% if field.errors %} class="error"{% endif %}>
|
||||
<th>{{ field.label_tag }}</th>
|
||||
<td>
|
||||
|
|
|
@ -235,7 +235,9 @@
|
|||
<br>
|
||||
<b class="text-warning">Unrecognized country: "{{ author.country }}"</b>: See <a href="{% url "ietf.stats.views.known_countries_list" %}">recognized country names</a>.
|
||||
{% endif %}
|
||||
|
||||
{% for auth_err in author.errors %}
|
||||
<p class="text-danger bg-danger"><b>{{ auth_err }}</b></p>
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@ -279,7 +281,7 @@
|
|||
</form>
|
||||
<p>Leads to manual post by the secretariat.</p>
|
||||
|
||||
{% if passes_checks and not errors %}
|
||||
{% if passes_checks and not errors and not submission.errors %}
|
||||
<h2>Please edit the following meta-data before posting:</h2>
|
||||
|
||||
<form class="idsubmit" method="post">
|
||||
|
@ -287,6 +289,7 @@
|
|||
{% include "submit/submitter_form.html" %}
|
||||
{% include "submit/replaces_form.html" %}
|
||||
<input type="hidden" name="action" value="autopost">
|
||||
<h3>Post submission</h3>
|
||||
<button class="btn btn-primary" type="submit">Post submission</button>
|
||||
</form>
|
||||
|
||||
|
@ -320,7 +323,7 @@
|
|||
{% endif %}
|
||||
|
||||
{% if can_cancel %}
|
||||
<h2>Cancel submission</h2>
|
||||
<h3>Cancel submission</h3>
|
||||
<form id="cancel-submission" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="action" value="cancel">
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{# Copyright The IETF Trust 2015, All Rights Reserved #}{% load origin %}{% origin %}
|
||||
{% load bootstrap3 %}
|
||||
|
||||
<h3>Submitter</h3>
|
||||
<p>
|
||||
If you are one of the authors, please click the button below
|
||||
with your name on it to automatically fill in the
|
||||
|
|
Loading…
Reference in a new issue