Port submit to new schema, adding a set of tests and fixing some bugs

- Legacy-Id: 3436
This commit is contained in:
Ole Laursen 2011-09-21 19:29:50 +00:00
parent 95ef2adfcd
commit 6f10d2f3f7
21 changed files with 924 additions and 192 deletions

View file

@ -1,3 +1,4 @@
from django.core.urlresolvers import reverse as urlreverse
from django.contrib import admin
from ietf.submit.models import *
@ -9,7 +10,16 @@ class IdSubmissionDetailAdmin(admin.ModelAdmin):
list_display = ['submission_id', 'filename', 'status_link', 'submission_date', 'last_updated_date',]
ordering = [ '-submission_date' ]
search_fields = ['filename', ]
admin.site.register(IdSubmissionDetail, IdSubmissionDetailAdmin)
raw_id_fields = ['group_acronym']
def status_link(self, instance):
url = urlreverse('draft_status_by_hash',
kwargs=dict(submission_id=instance.submission_id,
submission_hash=instance.get_hash()))
return '<a href="%s">%s</a>' % (url, instance.status)
status_link.allow_tags = True
admin.site.register(IdSubmissionDetail, IdSubmissionDetailAdmin)
class IdApprovedDetailAdmin(admin.ModelAdmin):
pass
@ -17,5 +27,5 @@ admin.site.register(IdApprovedDetail, IdApprovedDetailAdmin)
class TempIdAuthorsAdmin(admin.ModelAdmin):
ordering = ["-id"]
pass
admin.site.register(TempIdAuthors, TempIdAuthorsAdmin)
admin.site.register(TempIdAuthors, TempIdAuthorsAdmin)

View file

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<django-objects version="1.0">
<object pk="-4" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Cancelled</field>
</object>
<object pk="-3" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Dead</field>
</object>
<object pk="-2" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Posted by the Secretariat</field>
</object>
<object pk="-1" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Posted</field>
</object>
<object pk="0" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Ready To Post</field>
</object>
<object pk="1" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Uploaded</field>
</object>
<object pk="2" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">ID NITS Passed</field>
</object>
<object pk="3" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Initial Version Approval Required</field>
</object>
<object pk="4" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Submitter Authentication Required</field>
</object>
<object pk="5" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Manual Post Requested</field>
</object>
<object pk="6" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">External Meta-Data Required</field>
</object>
<object pk="7" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Internal Database Has Been Updated</field>
</object>
<object pk="8" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">ID Announcement Scheduled</field>
</object>
<object pk="9" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">ID Tracker Notification Scheduled</field>
</object>
<object pk="10" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Initial Version Approval Requested</field>
</object>
<object pk="101" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Error - Plain text version does not exist</field>
</object>
<object pk="102" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">File size is larger than 20 MB</field>
</object>
<object pk="103" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Duplicate Internet-Draft submission is currently in process.</field>
</object>
<object pk="104" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Error - Simultaneous submission from the same IP address</field>
</object>
<object pk="105" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Error - Auth key does not match</field>
</object>
<object pk="106" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Error - No such Internet-Draft is currently in process</field>
</object>
<object pk="107" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Error - Draft is not in an appropriate status for the requested page</field>
</object>
<object pk="108" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Error - Unknown Request</field>
</object>
<object pk="109" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Error - Invalid Email Address</field>
</object>
<object pk="110" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Error - Direct Access is prohibited</field>
</object>
<object pk="201" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Error - Invalid version number</field>
</object>
<object pk="202" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Error - Invalid filename</field>
</object>
<object pk="203" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Error - The document failed idnits verification</field>
</object>
<object pk="204" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Creation Date must be within 3 days of the submission date.</field>
</object>
<object pk="205" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Error Not a valid submitter</field>
</object>
<object pk="206" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Incorrect Meta-Data</field>
</object>
<object pk="111" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">The document does not contain a legitimate filename that start with draft-*.</field>
</object>
<object pk="11" model="submit.idsubmissionstatus">
<field type="CharField" name="status_value">Initial Version Approved</field>
</object>
</django-objects>

View file

@ -1,4 +1,4 @@
import sha
import hashlib
import random
import os
import subprocess
@ -10,6 +10,7 @@ from django.conf import settings
from django.contrib.sites.models import Site
from django.template.loader import render_to_string
from django.utils.html import mark_safe
from django.core.urlresolvers import reverse as urlreverse
from ietf.idtracker.models import InternetDraft, IETFWG
from ietf.proceedings.models import Meeting
@ -51,11 +52,8 @@ class UploadForm(forms.Form):
def read_dates(self):
now = datetime.datetime.utcnow()
first_cut_off = Meeting.get_first_cut_off()
print "first_cut_off:", first_cut_off
second_cut_off = Meeting.get_second_cut_off()
print "second_cut_off:", second_cut_off
ietf_monday = Meeting.get_ietf_monday()
print "ietf_monday:", ietf_monday
if now.date() >= first_cut_off and now.date() < second_cut_off: # We are in the first_cut_off
if now.date() == first_cut_off and now.hour < settings.CUTOFF_HOUR:
@ -252,7 +250,10 @@ class UploadForm(forms.Form):
document_id = 0
existing_draft = InternetDraft.objects.filter(filename=draft.filename)
if existing_draft:
document_id = existing_draft[0].id_document_tag
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
document_id = -1
else:
document_id = existing_draft[0].id_document_tag
detail = IdSubmissionDetail.objects.create(
id_document_name=draft.get_title(),
filename=draft.filename,
@ -274,22 +275,34 @@ class UploadForm(forms.Form):
for author in draft.get_author_info():
full_name, first_name, middle_initial, last_name, name_suffix, email = author
order += 1
TempIdAuthors.objects.create(
id_document_tag=document_id,
first_name=first_name,
middle_initial=middle_initial,
last_name=last_name,
name_suffix=name_suffix,
email_address=email,
author_order=order,
submission=detail)
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
# save full name
TempIdAuthors.objects.create(
id_document_tag=document_id,
first_name=full_name.strip(),
email_address=email,
author_order=order,
submission=detail)
else:
TempIdAuthors.objects.create(
id_document_tag=document_id,
first_name=first_name,
middle_initial=middle_initial,
last_name=last_name,
name_suffix=name_suffix,
email_address=email,
author_order=order,
submission=detail)
return detail
class AutoPostForm(forms.Form):
first_name = forms.CharField(label=u'Given name', required=True)
last_name = forms.CharField(label=u'Last name', required=True)
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
name = forms.CharField(required=True)
else:
first_name = forms.CharField(label=u'Given name', required=True)
last_name = forms.CharField(label=u'Last name', required=True)
email = forms.EmailField(label=u'Email address', required=True)
def __init__(self, *args, **kwargs):
@ -298,10 +311,21 @@ class AutoPostForm(forms.Form):
super(AutoPostForm, self).__init__(*args, **kwargs)
def get_author_buttons(self):
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
buttons = []
for i in self.validation.authors:
buttons.append('<input type="button" data-name="%(name)s" data-email="%(email)s" value="%(name)s" />'
% dict(name=i.get_full_name(),
email=i.email()[1] or ''))
return "".join(buttons)
# this should be moved to a Javascript file and attributes like data-first-name ...
button_template = '<input type="button" onclick="jQuery(\'#id_first_name\').val(\'%(first_name)s\');jQuery(\'#id_last_name\').val(\'%(last_name)s\');jQuery(\'#id_email\').val(\'%(email)s\');" value="%(full_name)s" />'
buttons = []
for i in self.validation.authors:
full_name = '%s. %s' % (i.first_name[0], i.last_name)
full_name = u'%s. %s' % (i.first_name[0], i.last_name)
buttons.append(button_template % {'first_name': i.first_name,
'last_name': i.last_name,
'email': i.email()[1] or '',
@ -317,10 +341,22 @@ class AutoPostForm(forms.Form):
subject = 'Confirmation for Auto-Post of I-D %s' % self.draft.filename
from_email = settings.IDSUBMIT_FROM_EMAIL
to_email = self.cleaned_data['email']
confirm_url = settings.IDTRACKER_BASE_URL + urlreverse('draft_confirm', kwargs=dict(submission_id=self.draft.submission_id, auth_key=self.draft.auth_key))
status_url = settings.IDTRACKER_BASE_URL + urlreverse('draft_status_by_hash', kwargs=dict(submission_id=self.draft.submission_id, submission_hash=self.draft.get_hash()))
send_mail(request, to_email, from_email, subject, 'submit/confirm_autopost.txt',
{'draft': self.draft, 'domain': Site.objects.get_current().domain })
{ 'draft': self.draft, 'confirm_url': confirm_url, 'status_url': status_url })
def save_submitter_info(self):
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
return TempIdAuthors.objects.create(
id_document_tag=self.draft.temp_id_document_tag,
first_name=self.cleaned_data['name'],
email_address=self.cleaned_data['email'],
author_order=0,
submission=self.draft)
return TempIdAuthors.objects.create(
id_document_tag=self.draft.temp_id_document_tag,
first_name=self.cleaned_data['first_name'],
@ -330,8 +366,8 @@ class AutoPostForm(forms.Form):
submission=self.draft)
def save_new_draft_info(self):
salt = sha.new(str(random.random())).hexdigest()[:5]
self.draft.auth_key = sha.new(salt+self.cleaned_data['email']).hexdigest()
salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
self.draft.auth_key = hashlib.sha1(salt+self.cleaned_data['email']).hexdigest()
self.draft.status_id = WAITING_AUTHENTICATION
self.draft.save()
@ -343,11 +379,18 @@ class MetaDataForm(AutoPostForm):
creation_date = forms.DateField(label=u'Creation date', required=True)
pages = forms.IntegerField(label=u'Pages', required=True)
abstract = forms.CharField(label=u'Abstract', widget=forms.Textarea, required=True)
first_name = forms.CharField(label=u'Given name', required=True)
last_name = forms.CharField(label=u'Last name', required=True)
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
name = forms.CharField(required=True)
else:
first_name = forms.CharField(label=u'Given name', required=True)
last_name = forms.CharField(label=u'Last name', required=True)
email = forms.EmailField(label=u'Email address', required=True)
comments = forms.CharField(label=u'Comments to the secretariat', widget=forms.Textarea, required=False)
fields = ['title', 'version', 'creation_date', 'pages', 'abstract', 'first_name', 'last_name', 'email', 'comments']
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
fields = ['title', 'version', 'creation_date', 'pages', 'abstract', 'name', 'email', 'comments']
else:
fields = ['title', 'version', 'creation_date', 'pages', 'abstract', 'first_name', 'last_name', 'email', 'comments']
def __init__(self, *args, **kwargs):
super(MetaDataForm, self).__init__(*args, **kwargs)
@ -358,26 +401,44 @@ class MetaDataForm(AutoPostForm):
authors=[]
if self.is_bound:
for key, value in self.data.items():
if key.startswith('first_name_'):
author = {'errors': {}}
index = key.replace('first_name_', '')
first_name = value.strip()
if not first_name:
author['errors']['first_name'] = 'This field is required'
last_name = self.data.get('last_name_%s' % index, '').strip()
if not last_name:
author['errors']['last_name'] = 'This field is required'
email = self.data.get('email_%s' % index, '').strip()
if email and not email_re.search(email):
author['errors']['email'] = 'Enter a valid e-mail address'
if first_name or last_name or email:
author.update({'first_name': first_name,
'last_name': last_name,
'email': ('%s %s' % (first_name, last_name), email),
'index': index,
})
authors.append(author)
authors.sort(lambda x,y: cmp(int(x['index']), int(y['index'])))
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
if key.startswith('name_'):
author = {'errors': {}}
index = key.replace('name_', '')
name = value.strip()
if not name:
author['errors']['name'] = 'This field is required'
email = self.data.get('email_%s' % index, '').strip()
if email and not email_re.search(email):
author['errors']['email'] = 'Enter a valid e-mail address'
if name or email:
author.update({'get_full_name': name,
'email': (name, email),
'index': index,
})
authors.append(author)
else:
if key.startswith('first_name_'):
author = {'errors': {}}
index = key.replace('first_name_', '')
first_name = value.strip()
if not first_name:
author['errors']['first_name'] = 'This field is required'
last_name = self.data.get('last_name_%s' % index, '').strip()
if not last_name:
author['errors']['last_name'] = 'This field is required'
email = self.data.get('email_%s' % index, '').strip()
if email and not email_re.search(email):
author['errors']['email'] = 'Enter a valid e-mail address'
if first_name or last_name or email:
author.update({'first_name': first_name,
'last_name': last_name,
'email': ('%s %s' % (first_name, last_name), email),
'index': index,
})
authors.append(author)
authors.sort(key=lambda x: x['index'])
return authors
def set_initials(self):
@ -437,7 +498,7 @@ class MetaDataForm(AutoPostForm):
def save_new_draft_info(self):
draft = self.draft
draft.id_documen_name = self.cleaned_data['title']
draft.id_document_name = self.cleaned_data['title']
if draft.revision != self.cleaned_data['version']:
self.move_docs(draft, self.cleaned_data['version'])
draft.revision = self.cleaned_data['version']
@ -447,7 +508,21 @@ class MetaDataForm(AutoPostForm):
draft.comment_to_sec = self.cleaned_data['comments']
draft.status_id = MANUAL_POST_REQUESTED
draft.save()
self.save_submitter_info()
# sync authors
draft.tempidauthors_set.all().delete()
self.save_submitter_info() # submitter is author 0
for i, author in enumerate(self.authors):
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
# save full name
TempIdAuthors.objects.create(
id_document_tag=draft.temp_id_document_tag,
first_name=author["get_full_name"],
email_address=author["email"][1],
author_order=i + 1,
submission=draft)
def save(self, request):
self.save_new_draft_info()
@ -462,5 +537,11 @@ class MetaDataForm(AutoPostForm):
if self.draft.group_acronym:
cc += [i.person.email()[1] for i in self.draft.group_acronym.wgchair_set.all()]
cc = list(set(cc))
send_mail(request, to_email, from_email, subject, 'submit/manual_post_mail.txt',
{'form': self, 'draft': self.draft, 'domain': Site.objects.get_current().domain }, cc=cc)
submitter = self.draft.tempidauthors_set.get(author_order=0)
send_mail(request, to_email, from_email, subject, 'submit/manual_post_mail.txt', {
'form': self,
'draft': self.draft,
'url': settings.IDTRACKER_BASE_URL + urlreverse('draft_status', kwargs=dict(submission_id=self.draft.submission_id)),
'submitter': submitter
},
cc=cc)

View file

@ -0,0 +1,34 @@
#!/usr/bin/python
# boiler plate
import os, sys
ietf_path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../ietf'))
sys.path.insert(0, ietf_path)
from django.core.management import setup_environ
import settings
setup_environ(settings)
# script
from django.core.serializers import serialize
from django.db.models import Q
def output(name, qs):
try:
f = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "fixtures/%s.xml" % name), 'w')
f.write(serialize("xml", qs, indent=4))
f.close()
except:
from django.db import connection
from pprint import pprint
pprint(connection.queries)
raise
# pick all name models directly out of the module
names = []
from ietf.submit.models import IdSubmissionStatus
output("idsubmissionstatus", IdSubmissionStatus.objects.all())

View file

@ -60,9 +60,6 @@ class IdSubmissionDetail(models.Model):
self.create_hash()
self.save()
return self.submission_hash
def status_link(self):
return '<a href="http://datatracker.ietf.org/submit/status/%s/%s/">%s</a>' % (self.submission_id, self.submission_hash, self.status)
status_link.allow_tags = True
def create_submission_hash(sender, instance, **kwargs):
@ -86,7 +83,7 @@ class IdApprovedDetail(models.Model):
class TempIdAuthors(models.Model):
id_document_tag = models.IntegerField()
first_name = models.CharField(blank=True, max_length=255)
first_name = models.CharField(blank=True, max_length=255) # with new schema, this contains the full name while the other name fields are empty to avoid loss of information
last_name = models.CharField(blank=True, max_length=255)
email_address = models.CharField(blank=True, max_length=255)
last_modified_date = models.DateField(null=True, blank=True)
@ -100,13 +97,11 @@ class TempIdAuthors(models.Model):
db_table = 'temp_id_authors'
def email(self):
return ('%s %s' % (self.first_name, self.last_name), self.email_address)
return (self.get_full_name(), self.email_address)
def get_full_name(self):
full_name = ('%s %s %s %s') % (self.first_name, self.middle_initial or '',
self.last_name, self.name_suffix or '')
full_name = re.sub(' +', ' ', full_name).strip()
return full_name
parts = (self.first_name or '', self.middle_initial or '', self.last_name or '', self.name_suffix or '')
return u" ".join(x.strip() for x in parts if x.strip())
def __unicode__(self):
return u"%s <%s>" % self.email()
return u"%s <%s>" % self.email()

View file

@ -65,23 +65,3 @@ class PlainParser(FileParser):
self.parsed_info.metadraft.filename = filename
return
self.parsed_info.add_error('The first page of the document does not contain a legitimate filename that start with draft-*')
def parse_wg(self):
filename = self.parsed_info.metadraft.filename
try:
existing_draft = InternetDraft.objects.get(filename=filename)
self.parsed_info.metadraft.wg = existing_draft.group
except InternetDraft.DoesNotExist:
if filename.startswith('draft-ietf-'):
# Extra check for WG that contains dashes
for group in IETFWG.objects.filter(group_acronym__acronym__contains='-'):
if filename.startswith('draft-ietf-%s-' % group.group_acronym.acronym):
self.parsed_info.metadraft.wg = group
return
group_acronym = filename.split('-')[2]
try:
self.parsed_info.metadraft.wg = IETFWG.objects.get(group_acronym__acronym=group_acronym)
except IETFWG.DoesNotExist:
self.parsed_info.add_error('Invalid WG ID: %s' % group_acronym)
else:
self.parsed_info.metadraft.wg = IETFWG.objects.get(pk=NONE_WG_PK)

View file

@ -17,9 +17,6 @@ def show_submission_files(context, submission):
'url': '%s%s-%s%s' % (settings.IDSUBMIT_STAGING_URL, submission.filename, submission.revision, ext)})
return {'files': result}
def show_two_pages(context, two_pages, validation):
result
@register.filter
def two_pages_decorated_with_validation(value, validation):

View file

@ -1,7 +1,7 @@
Informational Test Name
Internet-Draft Test Center Inc.
Intended status: Informational
Expires: %(expire)s %(date)s
Intended status: Informational %(date)s
Expires: %(expire)s
Testing tests
@ -15,9 +15,7 @@ Abstract
Status of this Memo
This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79. This document may not be modified,
and derivative works of it may not be created, and it may not be
published except as an Internet-Draft.
provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute
@ -41,73 +39,73 @@ Copyright Notice
(http://trustee.ietf.org/license-info) in effect on the date of
publication of this document. Please review these documents
carefully, as they describe your rights and restrictions with respect
to this document.
This Informational Internet Draft is submitted as an RFC Editor
to this document. Code Components extracted from this document must
Name Expires %(expire)s [Page 1]
Internet-Draft Testing tests %(month_year)s
Contribution and/or non-IETF Document (not as a Contribution, IETF
Contribution, nor IETF Document) in accordance with BCP 78 and BCP
79.
include Simplified BSD License text as described in Section 4.e of
the Trust Legal Provisions and are provided without warranty as
described in the Simplified BSD License.
This document may contain material from IETF Documents or IETF
Contributions published or made publicly available before November
10, 2008. The person(s) controlling the copyright in some of this
material may not have granted the IETF Trust the right to allow
modifications of such material outside the IETF Standards Process.
Without obtaining an adequate license from the person(s) controlling
the copyright in such materials, this document may not be modified
outside the IETF Standards Process, and derivative works of it may
not be created outside the IETF Standards Process, except to format
it for publication as an RFC or to translate it into languages other
than English.
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 4
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
2. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 4
3. Security Considerations . . . . . . . . . . . . . . . . . . . 4
Name Expires %(expire)s [Page 2]
Internet-Draft Testing tests %(month_year)s
1. Introduction
This document describes a protocol for testing tests.
Name Expires %(expire)s [Page 3]
Internet-Draft Testing tests %(month_year)s
2. Security Considerations
There are none.
3. IANA Considerations
No new registrations for IANA.
Authors' Addresses
Test Name
Test Center Inc.
Some way 42
Some Where, NY
Email: testname@example.com
Name Expires %(expire)s [Page 4]

View file

@ -13,56 +13,325 @@ from ietf.utils.test_data import make_test_data
from redesign.person.models import Person, Email
from redesign.group.models import Group, Role
from redesign.doc.models import Document
from redesign.doc.models import Document, BallotPositionDocEvent
from ietf.submit.models import IdSubmissionDetail
class SubmitTestCase(django.test.TestCase):
fixtures = ['names']
fixtures = ['names', 'idsubmissionstatus']
def setUp(self):
self.staging_dir = os.path.abspath("tmp-submit-staging-dir")
os.mkdir(self.staging_dir)
settings.IDSUBMIT_STAGING_PATH = self.staging_dir
self.repository_dir = os.path.abspath("tmp-submit-repository-dir")
os.mkdir(self.repository_dir)
settings.IDSUBMIT_REPOSITORY_PATH = self.repository_dir
def tearDown(self):
shutil.rmtree(self.staging_dir)
shutil.rmtree(self.repository_dir)
def test_submit(self):
def do_submission(self, name, rev):
# break early in case of missing configuration
self.assertTrue(os.path.exists(settings.IDSUBMIT_IDNITS_BINARY))
draft = make_test_data()
url = urlreverse('submit_index')
# get
url = urlreverse('submit_index')
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertEquals(len(q('input[type=file][name=txt]')), 1)
# submit text draft
filename = "draft-mars-testing-tests-00"
# construct appropriate text file
# construct appropriate text draft
f = open(os.path.join(settings.BASE_DIR, "submit", "test_submission.txt"))
template = f.read()
f.close()
submission_text = template % dict(
date=datetime.date.today().strftime("%Y-%m-%d"),
date=datetime.date.today().strftime("%d %B %Y"),
expire=(datetime.date.today() + datetime.timedelta(days=100)).strftime("%Y-%m-%d"),
year=datetime.date.today().strftime("%Y"),
month_year=datetime.date.today().strftime("%B, %Y"),
filename=filename,
filename="%s-%s" % (name, rev),
)
test_file = StringIO(submission_text)
test_file = StringIO(str(submission_text))
test_file.name = "somename.txt"
# submit
r = self.client.post(url,
dict(txt=test_file))
self.assertEquals(r.status_code, 302)
self.assertTrue(os.path.exists(os.path.join(self.staging_dir, filename + ".txt")))
supply_submitter_url = r["Location"]
self.assertTrue(os.path.exists(os.path.join(self.staging_dir, u"%s-%s.txt" % (name, rev))))
self.assertEquals(IdSubmissionDetail.objects.filter(filename=name).count(), 1)
submission = IdSubmissionDetail.objects.get(filename=name)
self.assertEquals(submission.group_acronym.acronym, "mars")
self.assertEquals(submission.tempidauthors_set.count(), 1)
author = submission.tempidauthors_set.all()[0]
self.assertEquals(author.first_name, "Test Name")
return supply_submitter_url
def supply_submitter(self, name, supply_submitter_url):
# check the page
r = self.client.get(supply_submitter_url)
q = PyQuery(r.content)
self.assertEquals(len(q('input[type=submit][name=autopost]')), 1)
# post submitter info
r = self.client.post(supply_submitter_url,
dict(autopost="1",
name="Test Name",
email="testname@example.com",
))
# submitter is saved as author order 0
submission = IdSubmissionDetail.objects.get(filename=name)
self.assertEquals(submission.tempidauthors_set.count(), 2)
self.assertEquals(submission.tempidauthors_set.get(author_order=0).first_name, "Test Name")
return r
def test_submit_new(self):
# submit new -> supply submitter info -> approve
draft = make_test_data()
name = "draft-ietf-mars-testing-tests"
rev = "00"
supply_submitter_url = self.do_submission(name, rev)
# supply submitter info, then draft should be in and ready for approval
mailbox_before = len(mail_outbox)
r = self.supply_submitter(name, supply_submitter_url)
self.assertEquals(r.status_code, 302)
status_url = r["Location"]
self.assertEquals(len(mail_outbox), mailbox_before + 1)
self.assertTrue("New draft waiting for approval" in mail_outbox[-1]["Subject"])
self.assertTrue(name in mail_outbox[-1]["Subject"])
# as chair of WG, we should see approval button
self.client.login(remote_user="marschairman")
r = self.client.get(status_url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
approve_submit = q('input[type=submit][value*="Approve"]')
self.assertEquals(len(approve_submit), 1)
# approve submission
mailbox_before = len(mail_outbox)
approve_url = approve_submit.parents("form").attr("action")
r = self.client.post(approve_url, dict())
self.assertEquals(r.status_code, 302)
draft = Document.objects.get(docalias__name=name)
self.assertEquals(draft.rev, rev)
new_revision = draft.latest_event()
self.assertEquals(new_revision.type, "new_revision")
self.assertEquals(new_revision.by.name, "Test Name")
self.assertTrue(not os.path.exists(os.path.join(self.staging_dir, u"%s-%s.txt" % (name, rev))))
self.assertTrue(os.path.exists(os.path.join(self.repository_dir, u"%s-%s.txt" % (name, rev))))
self.assertEquals(draft.authors.count(), 1)
self.assertEquals(draft.authors.all()[0].get_name(), "Test Name")
self.assertEquals(draft.authors.all()[0].address, "testname@example.com")
self.assertEquals(len(mail_outbox), mailbox_before + 2)
self.assertTrue((u"I-D Action: %s" % name) in mail_outbox[-2]["Subject"])
self.assertTrue("Test Name" in unicode(mail_outbox[-2]))
self.assertTrue("New Version Notification" in mail_outbox[-1]["Subject"])
self.assertTrue(name in unicode(mail_outbox[-1]))
self.assertTrue("mars" in unicode(mail_outbox[-1]))
def test_submit_existing(self):
# submit new revision of existing -> supply submitter info -> confirm
draft = make_test_data()
# make a discuss to see if the AD gets an email
ballot_position = BallotPositionDocEvent()
ballot_position.pos_id = "discuss"
ballot_position.type = "changed_ballot_position"
ballot_position.doc = draft
ballot_position.ad = ballot_position.by = Person.objects.get(user__username="ad2")
ballot_position.save()
name = draft.name
rev = "%02d" % (int(draft.rev) + 1)
supply_submitter_url = self.do_submission(name, rev)
# supply submitter info, then we get a confirmation email
mailbox_before = len(mail_outbox)
r = self.supply_submitter(name, supply_submitter_url)
self.assertEquals(r.status_code, 200)
self.assertTrue("Your submission is pending email authentication" in r.content)
self.assertEquals(len(mail_outbox), mailbox_before + 1)
confirmation = mail_outbox[-1]
self.assertTrue("Confirmation for" in confirmation["Subject"])
self.assertTrue(name in confirmation["Subject"])
# dig out confirmation link
msg = confirmation.get_payload(i=1).get_payload(i=0).get_payload(decode=True)
line_start = "I-D Submission Tool URL:"
self.assertTrue(line_start in msg)
confirm_url = None
for line in msg.split("\n"):
if line.startswith(line_start):
confirm_url = line[len(line_start):].strip()
# go to confirm page
r = self.client.get(confirm_url)
q = PyQuery(r.content)
self.assertEquals(len(q('input[type=submit][value=Auto-Post]')), 1)
# confirm
mailbox_before = len(mail_outbox)
r = self.client.post(confirm_url)
self.assertEquals(r.status_code, 200)
self.assertTrue('Authorization key accepted' in r.content)
draft = Document.objects.get(docalias__name=name)
self.assertEquals(draft.rev, rev)
new_revision = draft.latest_event()
self.assertEquals(new_revision.type, "new_revision")
self.assertEquals(new_revision.by.name, "Test Name")
self.assertTrue(not os.path.exists(os.path.join(self.staging_dir, u"%s-%s.txt" % (name, rev))))
self.assertTrue(os.path.exists(os.path.join(self.repository_dir, u"%s-%s.txt" % (name, rev))))
self.assertEquals(draft.authors.count(), 1)
self.assertEquals(draft.authors.all()[0].get_name(), "Test Name")
self.assertEquals(draft.authors.all()[0].address, "testname@example.com")
self.assertEquals(len(mail_outbox), mailbox_before + 3)
self.assertTrue((u"I-D Action: %s" % name) in mail_outbox[-3]["Subject"])
self.assertTrue("Test Name" in unicode(mail_outbox[-3]))
self.assertTrue("New Version Notification" in mail_outbox[-2]["Subject"])
self.assertTrue(name in unicode(mail_outbox[-2]))
self.assertTrue("mars" in unicode(mail_outbox[-2]))
self.assertTrue(draft.ad.email_address().address in unicode(mail_outbox[-2]))
self.assertTrue(ballot_position.ad.email_address().address in unicode(mail_outbox[-2]))
self.assertTrue("New Version Notification" in mail_outbox[-1]["Subject"])
self.assertTrue(name in unicode(mail_outbox[-1]))
self.assertTrue("mars" in unicode(mail_outbox[-1]))
def test_cancel_submission(self):
# submit -> cancel
draft = make_test_data()
name = "draft-ietf-mars-testing-tests"
rev = "00"
supply_submitter_url = self.do_submission(name, rev)
# check we got cancel button
r = self.client.get(supply_submitter_url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
cancel_submission = q('input[type=submit][value*="Cancel"]')
self.assertEquals(len(cancel_submission), 1)
cancel_url = cancel_submission.parents("form").attr("action")
# cancel
r = self.client.post(cancel_url)
self.assertTrue(not os.path.exists(os.path.join(self.staging_dir, u"%s-%s.txt" % (name, rev))))
def test_edit_submission(self):
# submit -> edit
draft = make_test_data()
name = "draft-ietf-mars-testing-tests"
rev = "00"
supply_submitter_url = self.do_submission(name, rev)
# check we got edit button
r = self.client.get(supply_submitter_url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertEquals(len(q('input[type=submit][value*="Adjust"]')), 1)
# go to edit, we do this by posting, slightly weird
r = self.client.post(supply_submitter_url)
self.assertEquals(r.status_code, 302)
edit_url = r['Location']
# check page
r = self.client.get(edit_url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertEquals(len(q('input[name=title]')), 1)
# edit
mailbox_before = len(mail_outbox)
creation_date = datetime.date.today() - datetime.timedelta(days=-3)
r = self.client.post(edit_url,
dict(title="some title",
version="00",
creation_date=creation_date.strftime("%Y-%m-%d"),
abstract="some abstract",
pages="123",
name="Some Random Test Person",
email="random@example.com",
comments="no comments",
name_0="Person 1",
email_0="person1@example.com",
name_1="Person 2",
email_1="person2@example.com",
))
self.assertEquals(r.status_code, 302)
submission = IdSubmissionDetail.objects.get(filename=name)
self.assertEquals(submission.id_document_name, "some title")
self.assertEquals(submission.creation_date, creation_date)
self.assertEquals(submission.abstract, "some abstract")
self.assertEquals(submission.txt_page_count, 123)
self.assertEquals(submission.comment_to_sec, "no comments")
authors = submission.tempidauthors_set
self.assertEquals(authors.count(), 3)
# first one is submitter
self.assertEquals(authors.get(author_order=0).first_name, "Some Random Test Person")
self.assertEquals(authors.get(author_order=0).email_address, "random@example.com")
self.assertEquals(authors.get(author_order=1).first_name, "Person 1")
self.assertEquals(authors.get(author_order=1).email_address, "person1@example.com")
self.assertEquals(authors.get(author_order=2).first_name, "Person 2")
self.assertEquals(authors.get(author_order=2).email_address, "person2@example.com")
self.assertEquals(len(mail_outbox), mailbox_before + 1)
self.assertTrue("Manual Post Requested" in mail_outbox[-1]["Subject"])
self.assertTrue(name in mail_outbox[-1]["Subject"])
def test_request_full_url(self):
# submit -> request full URL to be sent
draft = make_test_data()
name = "draft-ietf-mars-testing-tests"
rev = "00"
self.do_submission(name, rev)
submission = IdSubmissionDetail.objects.get(filename=name)
url = urlreverse('draft_status', kwargs=dict(submission_id=submission.submission_id))
# check we got request full URL button
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
request_button = q('input[type=submit][value*="Request full access"]')
self.assertEquals(len(request_button), 1)
request_url = request_button.parents("form").attr("action")
# request URL to be sent
mailbox_before = len(mail_outbox)
r = self.client.post(request_url)
self.assertEquals(r.status_code, 200)
self.assertEquals(len(mail_outbox), mailbox_before + 1)
self.assertTrue("Full URL for managing submission" in mail_outbox[-1]["Subject"])
self.assertTrue(name in mail_outbox[-1]["Subject"])
if not settings.USE_DB_REDESIGN_PROXY_CLASSES:

View file

@ -4,14 +4,20 @@ import datetime
from django.conf import settings
from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse as urlreverse
from ietf.idtracker.models import (InternetDraft, PersonOrOrgInfo, IETFWG,
IDAuthor, EmailAddress, IESGLogin, BallotInfo)
from ietf.submit.models import TempIdAuthors
from ietf.utils.mail import send_mail
from ietf.idrfc.utils import add_document_comment
from ietf.utils import unaccent
from redesign.doc.models import *
from redesign.person.models import Person, Alias, Email
from redesign.doc.utils import active_ballot_positions
# Some usefull states
# Some useful states
UPLOADED = 1
WAITING_AUTHENTICATION = 4
MANUAL_POST_REQUESTED = 5
@ -26,12 +32,15 @@ NONE_WG = 1027
def request_full_url(request, submission):
subject = 'Full url for managing submission of draft %s' % submission.filename
subject = 'Full URL for managing submission of draft %s' % submission.filename
from_email = settings.IDSUBMIT_FROM_EMAIL
to_email = ['%s <%s>' % i.email() for i in submission.tempidauthors_set.all()]
to_email = list(set(u'%s <%s>' % i.email() for i in submission.tempidauthors_set.all()))
url = settings.IDTRACKER_BASE_URL + urlreverse('draft_status_by_hash',
kwargs=dict(submission_id=submission.submission_id,
submission_hash=submission.get_hash()))
send_mail(request, to_email, from_email, subject, 'submit/request_full_url.txt',
{'submission': submission,
'domain': Site.objects.get_current().domain})
{'submission': submission,
'url': url})
def perform_post(submission):
@ -80,6 +89,72 @@ def perform_post(submission):
send_announcements(submission, draft, state_change_msg)
submission.save()
def perform_postREDESIGN(submission):
system = Person.objects.get(name="(System)")
group_id = submission.group_acronym_id or NONE_WG
try:
draft = Document.objects.get(name=submission.filename)
save_document_in_history(draft)
draft.tags.remove(DocInfoTagName.objects.get(slug="exp-tomb"))
except Document.DoesNotExist:
draft = Document(name=submission.filename)
draft.intended_std_level = None
draft.time = datetime.datetime.now()
draft.title = submission.id_document_name
draft.group_id = group_id
draft.rev = submission.revision
draft.pages = submission.txt_page_count
draft.abstract = submission.abstract
was_rfc = draft.state_id == "rfc"
draft.state_id = "active"
draft.save()
DocAlias.objects.get_or_create(name=submission.filename, document=draft)
update_authors(draft, submission)
# new revision event
try:
a = submission.tempidauthors_set.get(author_order=0)
submitter = ensure_person_email_info_exists(a).person
except TempIdAuthors.DoesNotExist:
submitter = system
e = NewRevisionDocEvent(type="new_revision", doc=draft, rev=draft.rev)
e.time = draft.time #submission.submission_date
e.by = submitter
e.desc = "New revision available"
e.save()
# automatic state changes
state_change_msg = ""
if not was_rfc and draft.tags.filter(slug="need-rev"):
draft.tags.remove("need-rev")
draft.tags.add("ad-f-up")
e = DocEvent(type="changed_document", doc=draft)
e.desc = "Sub state has been changed to <b>AD Followup</b> from <b>Revised ID Needed</b>"
e.by = system
e.save()
state_change_msg = e.desc
move_docs(submission)
submission.status_id = POSTED
announce_to_lists(submission)
if draft.iesg_state != None and not was_rfc:
announce_new_version(submission, draft, state_change_msg)
announce_to_authors(submission)
submission.save()
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
perform_post = perform_postREDESIGN
def send_announcements(submission, draft, state_change_msg):
announce_to_lists(submission)
@ -126,9 +201,29 @@ def announce_new_version(submission, draft, state_change_msg):
'msg': state_change_msg})
def announce_new_versionREDESIGN(submission, draft, state_change_msg):
to_email = []
if draft.notify:
to_email.append(draft.notify)
if draft.ad:
to_email.append(draft.ad.role_email("ad").address)
for ad, pos in active_ballot_positions(draft).iteritems():
if pos and pos.pos_id == "discuss":
to_email.append(ad.role_email("ad").address)
subject = 'New Version Notification - %s-%s.txt' % (submission.filename, submission.revision)
from_email = settings.IDSUBMIT_ANNOUNCE_FROM_EMAIL
send_mail(None, to_email, from_email, subject, 'submit/announce_new_version.txt',
{'submission': submission,
'msg': state_change_msg})
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
announce_new_version = announce_new_versionREDESIGN
def announce_to_authors(submission):
authors = submission.tempidauthors_set.order_by('author_order')
cc = list(set([i.email()[1] for i in authors]))
cc = list(set(i.email()[1] for i in authors if i.email() != authors[0].email()))
to_email = [authors[0].email()[1]] # First TempIdAuthor is submitter
from_email = settings.IDSUBMIT_ANNOUNCE_FROM_EMAIL
subject = 'New Version Notification for %s-%s.txt' % (submission.filename, submission.revision)
@ -202,6 +297,85 @@ def update_authors(draft, submission):
idauthor.save()
draft.authors.exclude(person__pk__in=person_pks).delete()
def get_person_from_author(author):
persons = None
# try email
if author.email_address:
persons = Person.objects.filter(email__address=author.email_address).distinct()
if len(persons) == 1:
return persons[0]
if not persons:
persons = Person.objects.all()
# try full name
p = persons.filter(alias__name=author.get_full_name()).distinct()
if p:
return p[0]
return None
def ensure_person_email_info_exists(author):
person = get_person_from_author(author)
# make sure we got a person
if not person:
person = Person()
person.name = author.get_full_name()
person.ascii = unaccent.asciify(person.name)
person.save()
Alias.objects.create(name=person.name, person=person)
if person.name != person.ascii:
Alias.objects.create(name=ascii, person=person)
# make sure we got an email address
if author.email_address:
addr = author.email_address.lower()
else:
# we're in trouble, use a fake one
addr = u"unknown-email-%s" % person.name.replace(" ", "-")
try:
email = person.email_set.get(address=addr)
except Email.DoesNotExist:
try:
# maybe it's pointing to someone else
email = Email.objects.get(address=addr)
except Email.DoesNotExist:
# most likely we just need to create it
email = Email(address=addr)
email.active = False
email.person = person
email.save()
return email
def update_authorsREDESIGN(draft, submission):
# order 0 is submitter
authors = []
for author in submission.tempidauthors_set.exclude(author_order=0).order_by('author_order'):
email = ensure_person_email_info_exists(author)
try:
a = DocumentAuthor.objects.get(document=draft, author=email)
except DocumentAuthor.DoesNotExist:
a = DocumentAuthor(document=draft, author=email)
a.order = author.author_order
a.save()
authors.append(email)
draft.documentauthor_set.exclude(author__in=authors).delete()
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
update_authors = update_authorsREDESIGN
def get_person_for_user(user):
try:
@ -215,6 +389,8 @@ def is_secretariat(user):
return False
return bool(user.groups.filter(name='Secretariat'))
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
from ietf.liaisons.accounts import is_secretariat, get_person_for_user
def move_docs(submission):
for ext in submission.file_type.split(','):
@ -274,7 +450,7 @@ class DraftValidation(object):
self.validate_wg()
def validate_wg(self):
if self.wg and not self.wg.status.pk == IETFWG.ACTIVE:
if self.wg and not self.wg.status_id == IETFWG.ACTIVE:
self.add_warning('group', 'Working Group exists but is not an active WG')
def validate_abstract(self):
@ -314,8 +490,7 @@ class DraftValidation(object):
self.add_warning('creation_date', 'Creation Date must be within 3 days of submission date')
def get_authors(self):
tmpauthors = self.draft.tempidauthors_set.exclude(author_order=0).order_by('author_order')
return tmpauthors
return self.draft.tempidauthors_set.exclude(author_order=0).order_by('author_order')
def get_submitter(self):
submitter = self.draft.tempidauthors_set.filter(author_order=0)

View file

@ -127,9 +127,9 @@ def draft_status(request, submission_id, submission_hash=None, message=None):
to_email += [i.person.email()[1] for i in detail.group_acronym.wgchair_set.all()]
to_email = list(set(to_email))
if to_email:
metadata_form = MetaDataForm(draft=detail, validation=validation)
authors = detail.tempidauthors_set.exclude(author_order=0).order_by('author_order')
send_mail(request, to_email, from_email, subject, 'submit/submission_approval.txt',
{'submitter': submitter, 'form': metadata_form,
{'submitter': submitter, 'authors': authors,
'draft': detail, 'domain': Site.objects.get_current().domain})
return HttpResponseRedirect(reverse(draft_status, None, kwargs={'submission_id': detail.submission_id}))
else:
@ -144,7 +144,11 @@ def draft_status(request, submission_id, submission_hash=None, message=None):
allow_edit = None
message = ('success', 'Your submission is pending email authentication. An email has been sent you with instructions.')
else:
return HttpResponseRedirect(reverse(draft_edit, None, kwargs={'submission_id': detail.submission_id, 'submission_hash': submission_hash}))
submission_hash = detail.get_hash()
if submission_hash:
return HttpResponseRedirect(reverse('draft_edit_by_hash', None, kwargs={'submission_id': detail.submission_id, 'submission_hash': submission_hash}))
else:
return HttpResponseRedirect(reverse(draft_edit, None, kwargs={'submission_id': detail.submission_id }))
else:
auto_post_form = AutoPostForm(draft=detail, validation=validation)
@ -207,6 +211,7 @@ def draft_edit(request, submission_id, submission_hash=None):
'detail': detail,
'validation': validation,
'form': form,
'settings': settings
},
context_instance=RequestContext(request))

View file

@ -1,6 +1,7 @@
Follow this link to confirm you Auto-Post of I-D {{ draft.filename }}-{{ draft.revision }}
Follow this link to confirm your Auto-Post of
I-D {{ draft.filename }}-{{ draft.revision }}:
I-D Submission Tool URL: http://{{ domain }}/submit/status/{{ draft.submission_id }}/confirm/{{ draft.auth_key }}/
I-D Submission Tool URL: {{ confirm_url|safe }}
Remember that you can cancel the submission from:
http://{{ domain }}/submit/status/{{ draft.submission_id }}/{{ draft.get_hash }}/
{{ status_url|safe }}

View file

@ -14,6 +14,7 @@ table.ietf-table span.field-error { display: block; color: red; }
{% block pagehead %}
{{ block.super }}
<script type="text/javascript" src="/js/draft-submit.js"></script>
<script type="text/javascript">
(function ($) {
@ -118,8 +119,12 @@ Please fix the following errors.
If you are one of the authors, then please click a button by your name to automatically fill in the submitter's information as requested below. Otherwise, Please manually enter your information.<br />
{{ form.get_author_buttons|safe }}
</td></tr>
{% if settings.USE_DB_REDESIGN_PROXY_CLASSES %}
<tr{% if form.errors.name %} class="warning"{% endif %}><th class="author">Name</th><td>{{ form.name }}{{ form.errors.name }}</td></tr>
{% else %}
<tr{% if form.errors.first_name %} class="warning"{% endif %}><th class="author">First name</th><td>{{ form.first_name }}{{ form.errors.first_name }}</td></tr>
<tr{% if form.errors.last_name %} class="warning"{% endif %}><th class="author">Last name</th><td>{{ form.last_name }}{{ form.errors.last_name }}</td></tr>
{% endif %}
<tr{% if form.errors.email %} class="warning"{% endif %}><th class="author">Email address</th><td>{{ form.email }}{{ form.errors.email }}</td></tr>
<tr{% if form.errors.comments %} class="warning"{% endif %}><th>Comments to the secretariat</th><td>{{ form.comments }}{{ form.errors.comments }}</td></tr>
</table>
@ -127,13 +132,25 @@ If you are one of the authors, then please click a button by your name to automa
<h3>Authors</h3>
<table class="author_list ietf-table" style="width: 100%;">
<thead>
<tr><th>First name</th><th>Last name</th><th>Email address</th></tr>
<tr>
{% if settings.USE_DB_REDESIGN_PROXY_CLASSES %}
<th>Name</th>
{% else %}
<th>First name</th>
<th>Last name</th>
{% endif %}
<th>Email address</th>
</tr>
</thead>
<tbody>
{% for author in form.get_authors %}
<tr class="editable {% cycle oddrow,evenrow %}{% if author.errors %} error{% endif %}">
{% if settings.USE_DB_REDESIGN_PROXY_CLASSES %}
<td name="name"><span class="fieldValue">{{ author.get_full_name|default:"" }}</span><span class="field-error">{{ author.errors.name }}</span></td>
{% else %}
<td name="first_name"><span class="fieldValue">{{ author.first_name|default:"" }}</span><span class="field-error">{{ author.errors.first_name }}</span></td>
<td name="last_name"><span class="fieldValue">{{ author.last_name|default:"" }}</span><span class="field-error">{{ author.errors.last_name }}</span></td>
{% endif %}
<td name="email"><span class="fieldValue">{{ author.email.1|default:"" }}</span><span class="field-error">{{ author.errors.email }}</span></td>
</tr>
{% endfor %}

View file

@ -21,6 +21,7 @@ pre.twopages { margin: 0px; }
{% block pagehead %}
<script type="text/javascript" src="/js/lib/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="/js/draft-submit.js"></script>
{% if can_cancel %}
<script type="text/javascript">
function confirmCancelation(){
@ -222,16 +223,16 @@ returned to the submitter.
{% if show_notify_button %}
<div class="metadata-errors">
<p>
You are not allowed to modify or cancel this submission. You only can modify or cancel this submission from the same url you were redirected after the submission.
You are not allowed to modify or cancel this submission. You only can modify or cancel this submission from the same URL you were redirected to after the submission.
</p>
<p>
If you are the submitter check your browser history to find this url. You can share it with any person you need.
</p>
<p>
If you are one of the authors you can request the url from wich you can modify or cancel this submission by clicking the next button. An email will be sent to the draft authors and to the submitter (if its email is available).
If you are one of the authors you can request the URL from wich you can modify or cancel this submission by clicking the next button. An email will be sent to the draft authors and to the submitter (if the submitter's email is available).
</p>
<form method="post" action="{% url full_url_request detail.submission_id %}">
<input type="submit" value="Request full access url" />
<input type="submit" value="Request full access URL" />
</form>
</div>
{% endif %}

View file

@ -1,6 +1,6 @@
{% autoescape off %}Manual posting has been requested for the following Internet-Draft:
I-D Submission Tool URL: http://{{ domain }}/submit/status/{{ draft.submission_id }}/
I-D Submission Tool URL: {{ url }}
File name: {{ draft.filename }}
Version: {{ draft.revision }}
@ -13,10 +13,10 @@ Abstract: {{ draft.abstract }}
Pages: {{ draft.txt_page_count }}
File size: {{ draft.filesize|filesizeformat }}
Submitter: {{ form.cleaned_data.first_name }} {{ form.cleaned_data.last_name }} <{{ form.cleaned_data.email }}>
Submitter: {{ submitter.get_full_name }} <{{ submitter.email.1 }}>
Author(s):
{% for author in form.get_authors %}{{ author.first_name }} {{ author.last_name }} <{{ author.email.1 }}>
Authors:
{% for author in form.get_authors %}{{ author.get_full_name }} <{{ author.email.1 }}>
{% endfor %}
{{ draft.comment_to_sec }}

View file

@ -1,3 +1,4 @@
Follow this link to get full access to the submission of I-D {{ submission.filename }}-{{ submission.revision }}
Follow this link to get full access to the submission of
I-D {{ submission.filename }}-{{ submission.revision }}:
http://{{ domain }}/submit/status/{{ submission.submission_id }}/{{ submission.get_hash }}/
{{ url|safe }}

View file

@ -1,4 +1,4 @@
WG chair approval is needed for posting of {{ draft.filename }}-{{ draft.revision }} draft
WG chair approval is needed for posting of {{ draft.filename }}-{{ draft.revision }} draft.
I-D Submission Tool URL: http://{{ domain }}/submit/status/{{ draft.submission_id }}/{{ draft.submission_hash }}/
@ -13,8 +13,8 @@ Abstract: {{ draft.abstract }}
Pages: {{ draft.txt_page_count }}
File size: {{ draft.filesize|filesizeformat }}
Submitter: {{ submitter.first_name }} {{ submitter.last_name }} <{{ submitter.email_address }}>
Submitter: {{ submitter.get_full_name }} <{{ submitter.email_address }}>
Author(s):
{% for author in form.get_authors %}{{ author.first_name }} {{ author.last_name }} <{{ author.email.1 }}>
Authors:
{% for author in authors %}{{ author.get_full_name }} <{{ author.email.1 }}>
{% endfor %}

View file

@ -142,7 +142,7 @@ def make_test_data():
# draft
draft = Document.objects.create(
name="draft-ietf-test",
name="draft-ietf-mars-test",
time=datetime.datetime.now(),
type_id="draft",
title="Optimizing Martian Network Topologies",

49
redesign/doc/utils.py Normal file
View file

@ -0,0 +1,49 @@
from redesign.doc.models import *
def get_state_types(doc):
res = []
if not doc:
return res
res.append(doc.type_id)
#if doc.type_id in ("agenda", "minutes", "slides", "liai-att"):
# res.append(doc.type_id)
if doc.type_id == "draft":
if doc.stream_id == "ietf":
wg_specific = doc.type_id + ":" + "wg" + ":" + doc.group.acronym
if State.objects.filter(type=wg_specific):
res.append(wg_specific)
else:
res.append(doc.type_id + ":" + "wg")
elif doc.stream_id == "irtf":
res.append(doc.type_id + ":" + "rg")
elif doc.stream_id == "iab":
res.append(doc.type_id + ":" + "iab")
elif doc.stream_id == "ise":
res.append(doc.type_id + ":" + "ise")
res.append(doc.type_id + ":" + "iesg")
res.append(doc.type_id + ":" + "iana")
res.append(doc.type_id + ":" + "rfc-editor")
return res
def active_ballot_positions(doc):
"""Return dict mapping each active AD to a current ballot position (or None if they haven't voted)."""
active_ads = list(Person.objects.filter(role__name="ad", role__group__state="active"))
res = {}
positions = BallotPositionDocEvent.objects.filter(doc=doc, type="changed_ballot_position", ad__in=active_ads).select_related('ad').order_by("-time", "-id")
for pos in positions:
if pos.ad not in res:
res[pos.ad] = pos
for ad in active_ads:
if ad not in res:
res[ad] = None
return res

View file

@ -28,10 +28,15 @@ class PersonInfo(models.Model):
else:
prefix, first, middle, last, suffix = self.ascii_parts()
return (first and first[0]+"." or "")+(middle or "")+" "+last+(suffix and " "+suffix or "")
def role_email(self, role_name, group):
e = Email.objects.filter(person=self, role__group=group, role__name=role_name)
if e:
return e[0]
def role_email(self, role_name, group=None):
if group:
e = Email.objects.filter(person=self, role__group=group, role__name=role_name)
if e:
return e[0]
else:
e = Email.objects.filter(person=self, role__group__state="active", role__name=role_name)
if e:
return e[0]
e = self.email_set.order_by("-active")
if e:
return e[0]

12
static/js/draft-submit.js Normal file
View file

@ -0,0 +1,12 @@
$(function (){
// fill in submitter info when an author button is clicked
$("input[type=button]").click(function () {
var name = $(this).data("name");
if (name == null) // backwards compatibility
return;
var email = $(this).data("email");
$(this).parents("form").find("input[name=name]").val(name || "");
$(this).parents("form").find("input[name=email]").val(email || "");
});
});