Merged in [13722] and [13712] from rcross@amsl.com:

Remove all use of request.session from secretariat apps.  Add tests for affected views.  Fixes #1455.
 - Legacy-Id: 13724
Note: SVN reference [13712] has been migrated to Git commit 915b445bcffcd4687fb1677230b98282d22dd9a0

Note: SVN reference [13722] has been migrated to Git commit 3a2cb9d3d846168f75d9796b4e5383bdf10b1f60
This commit is contained in:
Henrik Levkowetz 2017-06-28 14:55:10 +00:00
parent 3b7f320c29
commit 2070bbfed6
24 changed files with 571 additions and 327 deletions

View file

@ -138,6 +138,10 @@ class AnnounceForm(forms.ModelForm):
fields = ('nomcom', 'to','to_custom','frm','cc','bcc','reply_to','subject','body')
def __init__(self, *args, **kwargs):
if 'hidden' in kwargs:
self.hidden = kwargs.pop('hidden')
else:
self.hidden = False
user = kwargs.pop('user')
person = user.person
super(AnnounceForm, self).__init__(*args, **kwargs)
@ -154,6 +158,10 @@ class AnnounceForm(forms.ModelForm):
if not nomcom_roles and not secr_roles:
self.fields['nomcom'].widget = forms.HiddenInput()
self.initial['reply_to'] = 'ietf@ietf.org'
if self.hidden:
for key in self.fields.keys():
self.fields[key].widget = forms.HiddenInput()
def clean(self):
super(AnnounceForm, self).clean()

View file

@ -4,9 +4,12 @@ from django.urls import reverse
from pyquery import PyQuery
from ietf.utils.test_utils import TestCase
from ietf.group.models import Group
from ietf.message.models import Message
from ietf.nomcom.test_data import nomcom_test_data
from ietf.person.models import Person
from ietf.utils.test_data import make_test_data
from ietf.utils.mail import outbox, empty_outbox
SECR_USER='secretary'
WG_USER=''
@ -41,7 +44,6 @@ class SubmitAnnouncementCase(TestCase):
make_test_data()
url = reverse('ietf.secr.announcement.views.main')
post_data = {'id_subject':''}
#self.client.login(username='rcross', password='rcross+password")
self.client.login(username="secretary", password="secretary+password")
r = self.client.post(url,post_data)
self.assertEqual(r.status_code, 200)
@ -51,17 +53,26 @@ class SubmitAnnouncementCase(TestCase):
def test_valid_submit(self):
"Valid Submit"
make_test_data()
#ietf.utils.mail.test_mode = True
nomcom_test_data()
empty_outbox()
url = reverse('ietf.secr.announcement.views.main')
redirect = reverse('ietf.secr.announcement.views.confirm')
post_data = {'to':'Other...',
confirm_url = reverse('ietf.secr.announcement.views.confirm')
nomcom = Group.objects.get(type='nomcom')
post_data = {'nomcom': nomcom.pk,
'to':'Other...',
'to_custom':'rcross@amsl.com',
'frm':'IETF Secretariat <ietf-secretariat@ietf.org>',
'subject':'Test Subject',
'body':'This is a test.'}
self.client.login(username="secretary", password="secretary+password")
r = self.client.post(url,post_data,follow=True)
self.assertRedirects(r, redirect)
# good enough if we get to confirm page
#self.assertEqual(len(outbox), 1)
#self.assertTrue(len(outbox) > mailbox_before)
response = self.client.post(url,post_data)
self.assertEqual(response.status_code, 200)
self.assertTrue('Confirm Announcement' in response.content)
response = self.client.post(confirm_url,post_data,follow=True)
self.assertRedirects(response, url)
self.assertEqual(len(outbox),1)
self.assertEqual(outbox[0]['subject'],'Test Subject')
self.assertEqual(outbox[0]['to'],'<rcross@amsl.com>')
message = Message.objects.last()
self.assertEqual(message.subject,'Test Subject')
self.assertTrue(nomcom in message.related_groups.all())

View file

@ -6,7 +6,7 @@ from django.shortcuts import render, redirect
from ietf.group.models import Role
from ietf.ietfauth.utils import has_role
from ietf.secr.announcement.forms import AnnounceForm
from ietf.secr.utils.decorators import check_for_cancel, clear_non_auth
from ietf.secr.utils.decorators import check_for_cancel
from ietf.utils.mail import send_mail_text
# -------------------------------------------------
@ -59,13 +59,18 @@ def main(request):
form = AnnounceForm(request.POST or None,user=request.user)
if form.is_valid():
# nomcom is a ModelChoice, store pk, not Group object
data = form.cleaned_data
if data['nomcom']:
data['nomcom'] = data['nomcom'].pk
request.session['data'] = data
# recast as hidden form for next page of process
form = AnnounceForm(request.POST, user=request.user, hidden=True)
if form.data['to'] == 'Other...':
to = form.data['to_custom']
else:
to = form.data['to']
return redirect('ietf.secr.announcement.views.confirm')
return render(request, 'announcement/confirm.html', {
'message': form.data,
'to': to,
'form': form},
)
return render(request, 'announcement/main.html', { 'form': form} )
@ -73,37 +78,26 @@ def main(request):
@check_for_cancel('../')
def confirm(request):
if request.session.get('data',None):
data = request.session['data']
else:
messages.error(request, 'No session data. Your session may have expired or cookies are disallowed.')
return redirect('ietf.secr.announcement.views.main')
if not check_access(request.user):
return HttpResponseForbidden('Restricted to: Secretariat, IAD, or chair of IETF, IAB, RSOC, RSE, IAOC, ISOC, NomCom.')
if request.method == 'POST':
form = AnnounceForm(data, user=request.user)
message = form.save(user=request.user,commit=True)
extra = {'Reply-To':message.reply_to}
send_mail_text(None,
message.to,
message.frm,
message.subject,
message.body,
cc=message.cc,
bcc=message.bcc,
extra=extra)
form = AnnounceForm(request.POST, user=request.user)
if request.method == 'POST':
message = form.save(user=request.user,commit=True)
extra = {'Reply-To':message.reply_to}
send_mail_text(None,
message.to,
message.frm,
message.subject,
message.body,
cc=message.cc,
bcc=message.bcc,
extra=extra)
messages.success(request, 'The announcement was sent.')
return redirect('ietf.secr.announcement.views.main')
# clear session
clear_non_auth(request.session)
messages.success(request, 'The announcement was sent.')
return redirect('ietf.secr.announcement.views.main')
if data['to'] == 'Other...':
to = ','.join(data['to_custom'])
else:
to = data['to']
return render(request, 'announcement/confirm.html', {
'message': data,
'to': to},
)

View file

@ -170,7 +170,7 @@ def get_fullcc_list(draft):
return ','.join(result_list)
def get_email_initial(draft, type=None, input=None):
def get_email_initial(draft, action=None, input=None):
"""
Takes a draft object, a string representing the email type:
(extend,new,replace,resurrect,revision,update,withdraw) and
@ -182,7 +182,6 @@ def get_email_initial(draft, type=None, input=None):
It appears datatracker abbreviates the list with "et al". Datatracker scheduled_announcement
entries have "Action" in subject whereas this app uses "ACTION"
"""
# assert False, (draft, type, input)
expiration_date = (datetime.date.today() + datetime.timedelta(185)).strftime('%B %d, %Y')
new_revision = str(int(draft.rev)+1).zfill(2)
new_filename = draft.name + '-' + new_revision + '.txt'
@ -190,12 +189,15 @@ def get_email_initial(draft, type=None, input=None):
data = {}
data['cc'] = get_fullcc_list(draft)
data['to'] = ''
if type == 'extend':
data['action'] = action
if action == 'extend':
context = {'doc':curr_filename,'expire_date':input['expiration_date']}
data['subject'] = 'Extension of Expiration Date for %s' % (curr_filename)
data['body'] = render_to_string('drafts/message_extend.txt', context)
data['expiration_date'] = input['expiration_date']
elif type == 'new':
elif action == 'new':
# if the ID belongs to a group other than "none" add line to message body
if draft.group.type.slug == 'wg':
wg_message = 'This draft is a work item of the %s Working Group of the IETF.' % draft.group.name
@ -211,37 +213,43 @@ def get_email_initial(draft, type=None, input=None):
data['subject'] = 'I-D ACTION:%s' % (curr_filename)
data['body'] = render_to_string('drafts/message_new.txt', context)
elif type == 'replace':
elif action == 'replace':
'''
input['replaced'] is a DocAlias
input['replaced_by'] is a Document
'''
context = {'doc':input['replaced'].name,'replaced_by':input['replaced_by'].name}
data['subject'] = 'Replacement of %s with %s' % (input['replaced'].name,input['replaced_by'].name)
context = {'doc':input['replaced'],'replaced_by':input['replaced_by']}
data['subject'] = 'Replacement of %s with %s' % (input['replaced'],input['replaced_by'])
data['body'] = render_to_string('drafts/message_replace.txt', context)
elif type == 'resurrect':
data['replaced'] = input['replaced']
data['replaced_by'] = input['replaced_by']
elif action == 'resurrect':
last_revision = get_last_revision(draft.name)
last_filename = draft.name + '-' + last_revision + '.txt'
context = {'doc':last_filename,'expire_date':expiration_date}
data['subject'] = 'Resurrection of %s' % (last_filename)
data['body'] = render_to_string('drafts/message_resurrect.txt', context)
data['action'] = action
elif type == 'revision':
elif action == 'revision':
context = {'rev':new_revision,'doc':new_filename,'doc_base':new_filename[:-4]}
data['to'] = get_revision_emails(draft)
data['cc'] = ''
data['subject'] = 'New Version Notification - %s' % (new_filename)
data['body'] = render_to_string('drafts/message_revision.txt', context)
elif type == 'update':
elif action == 'update':
context = {'doc':input['filename'],'expire_date':expiration_date}
data['subject'] = 'Posting of %s' % (input['filename'])
data['body'] = render_to_string('drafts/message_update.txt', context)
elif type == 'withdraw':
context = {'doc':curr_filename,'by':input['type']}
data['action'] = action
elif action == 'withdraw':
context = {'doc':curr_filename,'by':input['withdraw_type']}
data['subject'] = 'Withdrawl of %s' % (curr_filename)
data['body'] = render_to_string('drafts/message_withdraw.txt', context)
data['action'] = action
data['withdraw_type'] = input['withdraw_type']
return data

View file

@ -213,12 +213,30 @@ class EditModelForm(forms.ModelForm):
class EmailForm(forms.Form):
# max_lengths come from db limits, cc is not limited
action = forms.CharField(max_length=255, widget=forms.HiddenInput(), required=False)
expiration_date = forms.CharField(max_length=255, widget=forms.HiddenInput(), required=False)
withdraw_type = forms.CharField(max_length=255, widget=forms.HiddenInput(), required=False)
replaced = forms.CharField(max_length=255, widget=forms.HiddenInput(), required=False)
replaced_by = forms.CharField(max_length=255, widget=forms.HiddenInput(), required=False)
filename = forms.CharField(max_length=255, widget=forms.HiddenInput(), required=False)
to = forms.CharField(max_length=255)
cc = forms.CharField(required=False)
subject = forms.CharField(max_length=255)
body = forms.CharField(widget=forms.Textarea(), strip=False)
def __init__(self, *args, **kwargs):
if 'hidden' in kwargs:
self.hidden = kwargs.pop('hidden')
else:
self.hidden = False
super(EmailForm, self).__init__(*args, **kwargs)
if self.hidden:
for key in self.fields.keys():
self.fields[key].widget = forms.HiddenInput()
class ExtendForm(forms.Form):
action = forms.CharField(max_length=255, widget=forms.HiddenInput(),initial='extend')
expiration_date = forms.DateField()
class ReplaceForm(forms.Form):
@ -369,5 +387,5 @@ class UploadForm(forms.Form):
return self.cleaned_data
class WithdrawForm(forms.Form):
type = forms.CharField(widget=forms.Select(choices=WITHDRAW_CHOICES),help_text='Select which type of withdraw to perform.')
withdraw_type = forms.CharField(widget=forms.Select(choices=WITHDRAW_CHOICES),help_text='Select which type of withdraw to perform.')

View file

@ -1,19 +1,24 @@
import datetime
import os
import shutil
from StringIO import StringIO
from django.conf import settings
from django.urls import reverse as urlreverse
from django.utils.http import urlencode
import debug # pyflakes:ignore
from ietf.doc.models import State
from ietf.doc.expire import expire_draft
from ietf.doc.models import State, Document
from ietf.person.models import Person
from ietf.submit.models import Preapproval
from ietf.submit.tests import submission_file
from ietf.utils.test_utils import TestCase
from ietf.utils.test_data import make_test_data
from ietf.utils.mail import empty_outbox
from ietf.secr.drafts.email import get_email_initial
from pyquery import PyQuery
SECR_USER='secretary'
@ -100,13 +105,34 @@ class SecrDraftsTestCase(TestCase):
draft = make_test_data()
state = State.objects.get(type='draft-iesg',slug='rfcqueue')
draft.set_state(state)
data = get_email_initial(draft,type='revision')
data = get_email_initial(draft,action='revision')
self.assertTrue('rfc-editor@rfc-editor.org' in data['to'])
def test_revision(self):
draft = make_test_data()
url = urlreverse('ietf.secr.drafts.views.revision', kwargs={'id':draft.name})
view_url = urlreverse('ietf.secr.drafts.views.view', kwargs={'id':draft.name})
self.client.login(username="secretary", password="secretary+password")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
post_data = {
'title': draft.title,
'pages': str(draft.pages),
'abstract': draft.abstract,
}
files = {}
files['txt'] = submission_file(draft.name, '02', draft.group, 'txt', "test_submission.txt")
post_data.update(files)
response = self.client.post(url, post_data)
self.assertRedirects(response, view_url)
draft = Document.objects.get(name=draft.name)
self.assertEqual(draft.rev, '02')
def test_revision_rfcqueue(self):
# Makes sure that a manual posting by the Secretariat of an I-D that is
# in the RFC Editor Queue will result in notification of the RFC Editor
draft = make_test_data()
empty_outbox()
state = State.objects.get(type='draft-iesg',slug='rfcqueue')
draft.set_state(state)
url = urlreverse('ietf.secr.drafts.views.revision', kwargs={'id':draft.name})
@ -117,9 +143,9 @@ class SecrDraftsTestCase(TestCase):
post = {'title':'The Title','pages':'10','txt':file}
response = self.client.post(url,post,follow=True)
self.assertEqual(response.status_code, 200)
q = PyQuery(response.content)
self.assertTrue('rfc-editor@rfc-editor.org' in q("#draft-confirm-email tr:first-child td").html())
# addresses = ','.join([ m['To'] for m in outbox ])
# self.assertTrue('rfc-editor@rfc-editor.org' in addresses)
def test_makerfc(self):
draft = make_test_data()
url = urlreverse('ietf.secr.drafts.views.edit', kwargs={'id':draft.name})
@ -142,11 +168,48 @@ class SecrDraftsTestCase(TestCase):
def test_update(self):
draft = make_test_data()
path = os.path.join(self.repository_dir, draft.filename_with_rev())
with open(path, 'w') as file:
file.write('test')
expire_draft(draft)
url = urlreverse('ietf.secr.drafts.views.update', kwargs={'id':draft.name})
email_url = urlreverse('ietf.secr.drafts.views.email', kwargs={'id':draft.name})
confirm_url = urlreverse('ietf.secr.drafts.views.confirm', kwargs={'id':draft.name})
do_action_url = urlreverse('ietf.secr.drafts.views.do_action', kwargs={'id':draft.name})
view_url = urlreverse('ietf.secr.drafts.views.view', kwargs={'id':draft.name})
self.client.login(username="secretary", password="secretary+password")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
post_data = {
'title': draft.title,
'pages': str(draft.pages),
'abstract': draft.abstract,
}
formats = ['txt',]
files = {}
for format in formats:
files[format] = submission_file(draft.name, '02', draft.group, format, "test_submission.%s" % format)
post_data.update(files)
response = self.client.post(url, post_data)
self.assertRedirects(response, email_url + '?action=update&filename=%s-02' % (draft.name))
post_data = {
'action': 'update',
'to': 'john@example.com',
'cc': 'joe@example.com',
'subject': 'test',
'body': 'text',
'submit': 'Save'
}
response = self.client.post(email_url + '?action=update&filename=%s-02' % (draft.name), post_data)
response = self.client.post(confirm_url, post_data)
response = self.client.post(do_action_url, post_data)
self.assertRedirects(response, view_url)
draft = Document.objects.get(name=draft.name)
expires = datetime.datetime.now() + datetime.timedelta(settings.INTERNET_DRAFT_DAYS_TO_EXPIRE)
self.assertTrue(draft.get_state_slug('draft') == 'active')
self.assertEqual(draft.rev, '02')
self.assertEqual(draft.expires.replace(second=0,microsecond=0), expires.replace(second=0,microsecond=0))
def test_view(self):
draft = make_test_data()
url = urlreverse('ietf.secr.drafts.views.view', kwargs={'id':draft.name})
@ -167,3 +230,129 @@ class SecrDraftsTestCase(TestCase):
self.assertRedirects(response, redirect_url)
self.assertFalse(draft.documentauthor_set.filter(id=id))
def test_resurrect(self):
draft = make_test_data()
path = os.path.join(self.repository_dir, draft.filename_with_rev())
with open(path, 'w') as file:
file.write('test')
expire_draft(draft)
email_url = urlreverse('ietf.secr.drafts.views.email', kwargs={'id':draft.name}) + "?action=resurrect"
confirm_url = urlreverse('ietf.secr.drafts.views.confirm', kwargs={'id':draft.name})
do_action_url = urlreverse('ietf.secr.drafts.views.do_action', kwargs={'id':draft.name})
view_url = urlreverse('ietf.secr.drafts.views.view', kwargs={'id':draft.name})
self.client.login(username="secretary", password="secretary+password")
response = self.client.get(email_url)
self.assertEqual(response.status_code, 200)
post_data = {
'action': 'resurrect',
'to': 'john@example.com',
'cc': 'joe@example.com',
'subject': 'test',
'body': 'draft resurrected',
'submit': 'Save'
}
response = self.client.post(email_url, post_data)
response = self.client.post(confirm_url, post_data)
response = self.client.post(do_action_url, post_data)
self.assertRedirects(response, view_url)
draft = Document.objects.get(name=draft.name)
self.assertTrue(draft.get_state_slug('draft') == 'active')
def test_extend(self):
draft = make_test_data()
url = urlreverse('ietf.secr.drafts.views.extend', kwargs={'id':draft.name})
email_url = urlreverse('ietf.secr.drafts.views.email', kwargs={'id':draft.name})
confirm_url = urlreverse('ietf.secr.drafts.views.confirm', kwargs={'id':draft.name})
do_action_url = urlreverse('ietf.secr.drafts.views.do_action', kwargs={'id':draft.name})
view_url = urlreverse('ietf.secr.drafts.views.view', kwargs={'id':draft.name})
expiration = datetime.datetime.today() + datetime.timedelta(days=180)
expiration = expiration.replace(hour=0,minute=0,second=0,microsecond=0)
self.client.login(username="secretary", password="secretary+password")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
get_data = {
'action': 'extend',
'expiration_date': expiration.strftime('%Y-%m-%d'),
}
post_data = {
'action': 'extend',
'expiration_date': expiration.strftime('%Y-%m-%d'),
'to': 'john@example.com',
'cc': 'joe@example.com',
'subject': 'test',
'body': 'draft resurrected',
'submit': 'Save'
}
response = self.client.get(email_url + '?' + urlencode(get_data))
self.assertEqual(response.status_code, 200)
response = self.client.post(confirm_url, post_data)
response = self.client.post(do_action_url, post_data)
self.assertRedirects(response, view_url)
draft = Document.objects.get(name=draft.name)
self.assertTrue(draft.expires == expiration)
def test_withdraw(self):
draft = make_test_data()
url = urlreverse('ietf.secr.drafts.views.withdraw', kwargs={'id':draft.name})
email_url = urlreverse('ietf.secr.drafts.views.email', kwargs={'id':draft.name})
confirm_url = urlreverse('ietf.secr.drafts.views.confirm', kwargs={'id':draft.name})
do_action_url = urlreverse('ietf.secr.drafts.views.do_action', kwargs={'id':draft.name})
view_url = urlreverse('ietf.secr.drafts.views.view', kwargs={'id':draft.name})
self.client.login(username="secretary", password="secretary+password")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
get_data = {
'action': 'withdraw',
'withdraw_type': 'ietf',
}
post_data = {
'action': 'withdraw',
'withdraw_type': 'ietf',
'to': 'john@example.com',
'cc': 'joe@example.com',
'subject': 'test',
'body': 'draft resurrected',
'submit': 'Save'
}
response = self.client.get(email_url + '?' + urlencode(get_data))
self.assertEqual(response.status_code, 200)
response = self.client.post(confirm_url, post_data)
response = self.client.post(do_action_url, post_data)
self.assertRedirects(response, view_url)
draft = Document.objects.get(name=draft.name)
self.assertTrue(draft.get_state_slug('draft') == 'ietf-rm')
def test_replace(self):
draft = make_test_data()
other_draft = Document.objects.filter(type='draft').exclude(name=draft.name).first()
url = urlreverse('ietf.secr.drafts.views.replace', kwargs={'id':draft.name})
email_url = urlreverse('ietf.secr.drafts.views.email', kwargs={'id':draft.name})
confirm_url = urlreverse('ietf.secr.drafts.views.confirm', kwargs={'id':draft.name})
do_action_url = urlreverse('ietf.secr.drafts.views.do_action', kwargs={'id':draft.name})
view_url = urlreverse('ietf.secr.drafts.views.view', kwargs={'id':draft.name})
self.client.login(username="secretary", password="secretary+password")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
get_data = {
'action': 'replace',
'replaced': draft.name,
'replaced_by': other_draft.name,
}
post_data = {
'action': 'replace',
'replaced': draft.name,
'replaced_by': other_draft.name,
'to': 'john@example.com',
'cc': 'joe@example.com',
'subject': 'test',
'body': 'draft resurrected',
'submit': 'Save'
}
response = self.client.get(email_url + '?' + urlencode(get_data))
self.assertEqual(response.status_code, 200)
response = self.client.post(confirm_url, post_data)
response = self.client.post(do_action_url, post_data)
self.assertRedirects(response, view_url)
draft = Document.objects.get(name=draft.name)
self.assertTrue(draft.get_state_slug('draft') == 'repl')

View file

@ -14,12 +14,12 @@ urlpatterns = [
url(r'^(?P<id>[A-Za-z0-9._\-\+]+)/authors/$', views.authors),
url(r'^(?P<id>[A-Za-z0-9._\-\+]+)/author_delete/(?P<oid>\d{1,6})$', views.author_delete),
url(r'^(?P<id>[A-Za-z0-9._\-\+]+)/confirm/$', views.confirm),
url(r'^(?P<id>[A-Za-z0-9._\-\+]+)/do_action/$', views.do_action),
url(r'^(?P<id>[A-Za-z0-9._\-\+]+)/edit/$', views.edit),
url(r'^(?P<id>[A-Za-z0-9._\-\+]+)/extend/$', views.extend),
url(r'^(?P<id>[A-Za-z0-9._\-\+]+)/email/$', views.email),
url(r'^(?P<id>[A-Za-z0-9._\-\+]+)/makerfc/$', views.makerfc),
url(r'^(?P<id>[A-Za-z0-9._\-\+]+)/replace/$', views.replace),
url(r'^(?P<id>[A-Za-z0-9._\-\+]+)/resurrect/$', views.resurrect),
url(r'^(?P<id>[A-Za-z0-9._\-\+]+)/revision/$', views.revision),
url(r'^(?P<id>[A-Za-z0-9._\-\+]+)/update/$', views.update),
url(r'^(?P<id>[A-Za-z0-9._\-\+]+)/withdraw/$', views.withdraw),

View file

@ -2,12 +2,15 @@ import datetime
import glob
import os
import shutil
from dateutil.parser import parse
from django.conf import settings
from django.contrib import messages
from django.db.models import Max
from django.forms.formsets import formset_factory
from django.shortcuts import render, get_object_or_404, redirect
from django.urls import reverse
from django.utils.http import urlencode
from ietf.doc.models import Document, DocumentAuthor, DocAlias, DocRelationshipName, RelatedDocument, State
from ietf.doc.models import DocEvent, NewRevisionDocEvent
@ -21,9 +24,9 @@ from ietf.secr.drafts.forms import ( AddModelForm, AuthorForm, BaseRevisionModel
EmailForm, ExtendForm, ReplaceForm, RevisionModelForm, RfcModelForm,
RfcObsoletesForm, SearchForm, UploadForm, WithdrawForm )
from ietf.secr.utils.ams_utils import get_base
from ietf.secr.utils.decorators import clear_non_auth
from ietf.secr.utils.document import get_rfc_num, get_start_date
from ietf.submit.models import Submission, Preapproval, DraftSubmissionStateName, SubmissionEvent
from ietf.submit.mail import announce_new_version, announce_to_lists, announce_to_authors
from ietf.utils.draft import Draft
@ -41,19 +44,21 @@ def archive_draft_files(filename):
shutil.move(file,settings.INTERNET_DRAFT_ARCHIVE_DIR)
return
def get_action_details(draft, session):
def get_action_details(draft, request):
'''
This function takes a draft object and session object and returns a list of dictionaries
This function takes a draft object and request object and returns a list of dictionaries
with keys: label, value to be used in displaying information on the confirmation
page.
'''
result = []
if session['action'] == 'revision':
m = {'label':'New Revision','value':session['revision']}
data = request.POST
if data['action'] == 'revision':
m = {'label':'New Revision','value':data['revision']}
result.append(m)
if session['action'] == 'replace':
m = {'label':'Replaced By:','value':session['data']['replaced_by']}
if data['action'] == 'replace':
m = {'label':'Replaced By:','value':data['replaced_by']}
result.append(m)
return result
@ -93,31 +98,28 @@ def process_files(request,draft):
the files by calling handle_file_upload() and returns
the basename, revision number and a list of file types. Basename and revision
are assumed to be the same for all because this is part of the validation process.
It also creates the Submission record WITHOUT saving, and places it in the
session for saving in the final action step.
'''
files = request.FILES
file = files[files.keys()[0]]
filename = os.path.splitext(file.name)[0]
revision = os.path.splitext(file.name)[0][-2:]
basename = get_base(filename)
file_type_list = []
for file in files.values():
extension = os.path.splitext(file.name)[1]
file_type_list.append(extension)
if extension == '.txt':
txt_size = file.size
wrapper = Draft(file.read().decode('utf8'),file.name)
handle_uploaded_file(file)
# create Submission record, leaved unsaved
idsub = Submission(
name=basename,
return (filename,revision,file_type_list)
def post_submission(request, draft):
with open(draft.get_file_name()) as file:
wrapper = Draft(file.read().decode('utf8'), file.name)
submission = Submission(
name=draft.name,
title=draft.title,
rev=revision,
rev=draft.rev,
pages=draft.pages,
file_size=txt_size,
file_size=os.path.getsize(draft.get_file_name()),
document_date=wrapper.get_creation_date(),
submission_date=datetime.date.today(),
group_id=draft.group.id,
@ -125,14 +127,8 @@ def process_files(request,draft):
first_two_pages=''.join(wrapper.pages[:2]),
state=DraftSubmissionStateName.objects.get(slug="posted"),
abstract=draft.abstract,
file_types=','.join(file_type_list),
file_types=','.join(file_types_for_draft(draft)),
)
request.session['idsub'] = idsub
return (filename,revision,file_type_list)
def post_submission(request):
submission = request.session['idsub']
submission.save()
SubmissionEvent.objects.create(
@ -140,6 +136,18 @@ def post_submission(request):
by=request.user.person,
desc="Submitted and posted manually")
return submission
def file_types_for_draft(draft):
'''Returns list of file extensions that exist for this draft'''
basename, ext = os.path.splitext(draft.get_file_name())
files = glob.glob(basename + '.*')
file_types = []
for filename in files:
base, ext = os.path.splitext(filename)
if ext:
file_types.append(ext)
return file_types
def promote_files(draft, types):
'''
@ -160,7 +168,6 @@ moving files, etc. Generally speaking the action buttons trigger a multi-page
sequence where information may be gathered using a custom form, an email
may be produced and presented to the user to edit, and only then when confirmation
is given will the action work take place. That's when these functions are called.
The details of the action are stored in request.session.
'''
def do_extend(draft, request):
@ -178,19 +185,20 @@ def do_extend(draft, request):
time=draft.time,
desc='Extended expiry',
)
draft.expires = request.session['data']['expiration_date']
draft.expires = parse(request.POST.get('expiration_date'))
draft.save_with_history([e])
# save scheduled announcement
announcement_from_form(request.session['email'],by=request.user.person)
form = EmailForm(request.POST)
announcement_from_form(form.data,by=request.user.person)
return
def do_replace(draft, request):
'Perform document replace'
replaced = request.session['data']['replaced'] # a DocAlias
replaced_by = request.session['data']['replaced_by'] # a Document
replaced = DocAlias.objects.get(name=request.POST.get('replaced')) # a DocAlias
replaced_by = Document.objects.get(name=request.POST.get('replaced_by')) # a Document
# create relationship
RelatedDocument.objects.create(source=replaced_by,
@ -207,7 +215,7 @@ def do_replace(draft, request):
doc=replaced_by,
rev=replaced_by.rev,
time=draft.time,
desc='This document now replaces <b>%s</b>' % request.session['data']['replaced'],
desc='This document now replaces <b>%s</b>' % replaced,
)
draft.save_with_history([e])
@ -216,7 +224,8 @@ def do_replace(draft, request):
archive_draft_files(replaced.document.name + '-' + replaced.document.rev)
# send announcement
announcement_from_form(request.session['email'],by=request.user.person)
form = EmailForm(request.POST)
announcement_from_form(form.data,by=request.user.person)
return
@ -252,11 +261,12 @@ def do_resurrect(draft, request):
draft.save_with_history([e])
# send announcement
announcement_from_form(request.session['email'],by=request.user.person)
form = EmailForm(request.POST)
announcement_from_form(form.data,by=request.user.person)
return
def do_revision(draft, request):
def do_revision(draft, request, filename, file_type_list):
'''
This function handles adding a new revision of an existing Internet-Draft.
Prerequisites: draft must be active
@ -277,7 +287,7 @@ def do_revision(draft, request):
archive_draft_files(draft.name + '-' + draft.rev)
# save form data
form = BaseRevisionModelForm(request.session['data'],instance=draft)
form = BaseRevisionModelForm(request.POST,instance=draft)
if form.is_valid():
new_draft = form.save(commit=False)
else:
@ -285,7 +295,7 @@ def do_revision(draft, request):
raise Exception('Problem with input data %s' % form.data)
# set revision and expires
new_draft.rev = request.session['filename'][-2:]
new_draft.rev = filename[-2:]
new_draft.expires = datetime.datetime.now() + datetime.timedelta(settings.INTERNET_DRAFT_DAYS_TO_EXPIRE)
# create DocEvent
@ -301,18 +311,18 @@ def do_revision(draft, request):
handle_substate(new_draft)
# move uploaded files to production directory
promote_files(new_draft, request.session['file_type'])
promote_files(new_draft, file_type_list)
# save the submission record
post_submission(request)
# send announcement if we are in IESG process
if new_draft.get_state('draft-iesg'):
announcement_from_form(request.session['email'],by=request.user.person)
submission = post_submission(request, new_draft)
announce_to_lists(request, submission)
announce_new_version(request, submission, draft, '')
announce_to_authors(request, submission)
return
def do_update(draft,request):
def do_update(draft,request,filename,file_type_list):
'''
Actions
- increment revision #
@ -322,7 +332,7 @@ def do_update(draft,request):
- change state to Active
'''
# save form data
form = BaseRevisionModelForm(request.session['data'],instance=draft)
form = BaseRevisionModelForm(request.POST,instance=draft)
if form.is_valid():
new_draft = form.save(commit=False)
else:
@ -331,7 +341,7 @@ def do_update(draft,request):
handle_substate(new_draft)
# update draft record
new_draft.rev = os.path.splitext(request.session['data']['filename'])[0][-2:]
new_draft.rev = os.path.splitext(filename)[0][-2:]
new_draft.expires = datetime.datetime.now() + datetime.timedelta(settings.INTERNET_DRAFT_DAYS_TO_EXPIRE)
new_draft.set_state(State.objects.get(type="draft", slug="active"))
@ -347,13 +357,15 @@ def do_update(draft,request):
new_draft.save_with_history([e])
# move uploaded files to production directory
promote_files(new_draft, request.session['file_type'])
promote_files(new_draft, file_type_list)
# save the submission record
post_submission(request)
post_submission(request, new_draft)
def do_update_announce(draft, request):
# send announcement
announcement_from_form(request.session['email'],by=request.user.person)
form = EmailForm(request.POST)
announcement_from_form(form.data,by=request.user.person)
return
@ -363,7 +375,7 @@ def do_withdraw(draft,request):
- change state to withdrawn
- TODO move file to archive
'''
withdraw_type = request.session['data']['type']
withdraw_type = request.POST.get('withdraw_type')
prev_state = draft.get_state("draft")
new_state = None
@ -382,7 +394,8 @@ def do_withdraw(draft,request):
draft.save_with_history([e])
# send announcement
announcement_from_form(request.session['email'],by=request.user.person)
form = EmailForm(request.POST)
announcement_from_form(form.data,by=request.user.person)
return
@ -421,8 +434,7 @@ def add(request):
* form
'''
clear_non_auth(request.session)
if request.method == 'POST':
button_text = request.POST.get('submit', '')
if button_text == 'Cancel':
@ -482,12 +494,13 @@ def add(request):
promote_files(draft, file_type_list)
# save the submission record
post_submission(request)
request.session['action'] = 'add'
post_submission(request, draft)
messages.success(request, 'New draft added successfully!')
return redirect('ietf.secr.drafts.views.authors', id=draft.name)
params = dict(action='add')
url = reverse('ietf.secr.drafts.views.authors', kwargs={'id':draft.pk})
url = url + '?' + urlencode(params)
return redirect(url)
else:
form = AddModelForm()
@ -513,7 +526,7 @@ def announce(request, id):
'''
draft = get_object_or_404(Document, name=id)
email_form = EmailForm(get_email_initial(draft,type='new'))
email_form = EmailForm(get_email_initial(draft,action='new'))
announcement_from_form(email_form.data,
by=request.user.person,
@ -566,16 +579,14 @@ def authors(request, id):
'''
draft = get_object_or_404(Document, name=id)
action = request.GET.get('action')
if request.method == 'POST':
form = AuthorForm(request.POST)
button_text = request.POST.get('submit', '')
if button_text == 'Done':
action = request.session.get('action','')
if action == 'add':
del request.session['action']
return redirect('ietf.secr.drafts.views.announce', id=id)
return redirect('ietf.secr.drafts.views.view', id=id)
if form.is_valid():
@ -604,22 +615,50 @@ def authors(request, id):
@role_required('Secretariat')
def confirm(request, id):
'''
This view displays changes that will be made and calls appropriate
function if the user elects to proceed. If the user cancels then
the session data is cleared and view page is returned.
'''
draft = get_object_or_404(Document, name=id)
if request.method == 'POST':
button_text = request.POST.get('submit', '')
if button_text == 'Cancel':
# TODO do cancel functions from session (ie remove uploaded files?)
# clear session data
clear_non_auth(request.session)
return redirect('ietf.secr.drafts.views.view', id=id)
action = request.session['action']
action = request.POST.get('action','')
form = EmailForm(request.POST)
if form.is_valid():
email = form.data
details = get_action_details(draft, request)
hidden_form = EmailForm(request.POST, hidden=True)
return render(request, 'drafts/confirm.html', {
'details': details,
'email': email,
'action': action,
'draft': draft,
'form': hidden_form},
)
else:
return render(request, 'drafts/email.html', {
'form': form,
'draft': draft,
'action': action},
)
@role_required('Secretariat')
def do_action(request, id):
'''
This view displays changes that will be made and calls appropriate
function if the user elects to proceed. If the user cancels then
the view page is returned.
'''
draft = get_object_or_404(Document, name=id)
if request.method == 'POST':
button_text = request.POST.get('submit', '')
if button_text == 'Cancel':
return redirect('ietf.secr.drafts.views.view', id=id)
action = request.POST.get('action')
if action == 'revision':
func = do_revision
elif action == 'resurrect':
@ -627,31 +666,17 @@ def confirm(request, id):
elif action == 'replace':
func = do_replace
elif action == 'update':
func = do_update
func = do_update_announce
elif action == 'extend':
func = do_extend
elif action == 'withdraw':
func = do_withdraw
func(draft,request)
# clear session data
clear_non_auth(request.session)
messages.success(request, '%s action performed successfully!' % action)
return redirect('ietf.secr.drafts.views.view', id=id)
details = get_action_details(draft, request.session)
email = request.session.get('email','')
action = request.session.get('action','')
return render(request, 'drafts/confirm.html', {
'details': details,
'email': email,
'action': action,
'draft': draft},
)
@role_required('Secretariat')
def dates(request):
'''
@ -726,45 +751,25 @@ def email(request, id):
'''
This function displays the notification message and allows the
user to make changes before continuing to confirmation page.
One exception is the "revision" action, save email data and go
directly to confirm page.
'''
draft = get_object_or_404(Document, name=id)
if request.method == 'POST':
button_text = request.POST.get('submit', '')
if button_text == 'Cancel':
# clear session data
clear_non_auth(request.session)
return redirect('ietf.secr.drafts.views.view', id=id)
action = request.GET.get('action')
data = request.GET
form = EmailForm(request.POST)
if form.is_valid():
request.session['email'] = form.data
return redirect('ietf.secr.drafts.views.confirm', id=id)
else:
# the resurrect email body references the last revision number, handle
# exception if no last revision found
# if this exception was handled closer to the source it would be easier to debug
# other problems with get_email_initial
try:
form = EmailForm(initial=get_email_initial(
draft,
type=request.session['action'],
input=request.session.get('data', None)))
except Exception, e:
return render(request, 'drafts/error.html', { 'error': e},)
# for "revision" action skip email page and go directly to confirm
if request.session['action'] == 'revision':
request.session['email'] = form.initial
return redirect('ietf.secr.drafts.views.confirm', id=id)
# the resurrect email body references the last revision number, handle
# exception if no last revision found
# if this exception was handled closer to the source it would be easier to debug
# other problems with get_email_initial
try:
form = EmailForm(initial=get_email_initial(draft,action=action,input=data))
except Exception, e:
return render(request, 'drafts/error.html', { 'error': e},)
return render(request, 'drafts/email.html', {
'form': form,
'draft': draft},
)
'draft': draft,
'action': action,
})
@role_required('Secretariat')
def extend(request, id):
@ -785,9 +790,11 @@ def extend(request, id):
form = ExtendForm(request.POST)
if form.is_valid():
request.session['data'] = form.cleaned_data
request.session['action'] = 'extend'
return redirect('ietf.secr.drafts.views.email', id=id)
params = form.cleaned_data
params['action'] = 'extend'
url = reverse('ietf.secr.drafts.views.email', kwargs={'id':id})
url = url + '?' + urlencode(params)
return redirect(url)
else:
form = ExtendForm(initial={'revision_date':datetime.date.today().isoformat()})
@ -906,9 +913,14 @@ def replace(request, id):
form = ReplaceForm(request.POST, draft=draft)
if form.is_valid():
request.session['data'] = form.cleaned_data
request.session['action'] = 'replace'
return redirect('ietf.secr.drafts.views.email', id=id)
#params = form.cleaned_data
params = {}
params['replaced'] = form.data['replaced']
params['replaced_by'] = form.data['replaced_by']
params['action'] = 'replace'
url = reverse('ietf.secr.drafts.views.email', kwargs={'id':id})
url = url + '?' + urlencode(params)
return redirect(url)
else:
form = ReplaceForm(draft=draft)
@ -918,22 +930,11 @@ def replace(request, id):
'draft': draft},
)
@role_required('Secretariat')
def resurrect(request, id):
'''
This view handles resurrection of an Internet-Draft
Prerequisites: draft must be expired
Input: none
'''
request.session['action'] = 'resurrect'
return redirect('ietf.secr.drafts.views.email', id=id)
@role_required('Secretariat')
def revision(request, id):
'''
This function presents the input form for the New Revision action. If submitted
form is valid state is saved in the session and the email page is returned.
This function presents the input form for the New Revision action.
on POST, updates draft to new revision and sends notification.
'''
draft = get_object_or_404(Document, name=id)
@ -949,14 +950,10 @@ def revision(request, id):
# process files
filename,revision,file_type_list = process_files(request,draft)
# save info in session and proceed to email page
request.session['data'] = form.cleaned_data
request.session['action'] = 'revision'
request.session['filename'] = filename
request.session['revision'] = revision
request.session['file_type'] = file_type_list
return redirect('ietf.secr.drafts.views.email', id=id)
do_revision(draft, request, filename, file_type_list)
messages.success(request, 'New Revision successful!')
return redirect('ietf.secr.drafts.views.view', id=id)
else:
form = RevisionModelForm(instance=draft,initial={'revision_date':datetime.date.today().isoformat()})
@ -983,7 +980,6 @@ def search(request):
'''
results = []
clear_non_auth(request.session)
if request.method == 'POST':
form = SearchForm(request.POST)
@ -1019,7 +1015,6 @@ def search(request):
kwargs['docevent__time__lte'] = revision_date_end
# perform query
#assert False, kwargs
if kwargs:
qs = Document.objects.filter(**kwargs)
else:
@ -1061,14 +1056,13 @@ def update(request, id):
# process files
filename,revision,file_type_list = process_files(request,draft)
# save state in session and proceed to email page
request.session['data'] = form.data
request.session['action'] = 'update'
request.session['revision'] = revision
request.session['data']['filename'] = filename
request.session['file_type'] = file_type_list
return redirect('ietf.secr.drafts.views.email', id=id)
do_update(draft, request, filename, file_type_list)
params = dict(action='update')
params['filename'] = filename
url = reverse('ietf.secr.drafts.views.email', kwargs={'id':id})
url = url + '?' + urlencode(params)
return redirect(url)
else:
form = RevisionModelForm(instance=draft,initial={'revision_date':datetime.date.today().isoformat()})
@ -1094,7 +1088,6 @@ def view(request, id):
* draft, area, id_tracker_state
'''
draft = get_object_or_404(Document, name=id)
#clear_non_auth(request.session)
# TODO fix in Django 1.2
# some boolean state variables for use in the view.html template to manage display
@ -1157,11 +1150,11 @@ def withdraw(request, id):
form = WithdrawForm(request.POST)
if form.is_valid():
# save state in session and proceed to email page
request.session['data'] = form.data
request.session['action'] = 'withdraw'
return redirect('ietf.secr.drafts.views.email', id=id)
params = form.cleaned_data
params['action'] = 'withdraw'
url = reverse('ietf.secr.drafts.views.email', kwargs={'id':id})
url = url + '?' + urlencode(params)
return redirect(url)
else:
form = WithdrawForm()

View file

@ -52,16 +52,6 @@ class EditPersonForm(forms.ModelForm):
else:
return None
"""
def save(self, force_insert=False, force_update=False, commit=True):
obj = super(EditPersonForm, self).save(commit=False)
user = self.cleaned_data['user']
self.user = User.objects.get(username=user)
if commit:
obj.save()
return obj
"""
# ------------------------------------------------------
# Forms for addition of new contacts
# These sublcass the regular forms, with additional
@ -100,9 +90,6 @@ class NewPersonForm(forms.ModelForm):
class Meta:
model = Person
exclude = ('time','user')
#def __init__(self, *args, **kwargs):
# super(NewPersonForm, self).__init__(*args, **kwargs)
def clean_email(self):
email = self.cleaned_data['email']

View file

@ -24,4 +24,26 @@ class RolodexTestCase(TestCase):
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
def test_add(self):
make_test_data()
url = reverse('ietf.secr.rolodex.views.add')
add_proceed_url = reverse('ietf.secr.rolodex.views.add_proceed') + '?name=Joe+Smith'
self.client.login(username="secretary", password="secretary+password")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
response = self.client.post(url, {'name':'Joe Smith'})
self.assertRedirects(response, add_proceed_url)
post_data = {
'name': 'Joe Smith',
'ascii': 'Joe Smith',
'ascii_short': 'Joe S',
'affiliation': 'IETF',
'address': '100 First Ave',
'email': 'joes@exanple.com',
'submit': 'Submit',
}
response = self.client.post(add_proceed_url, post_data)
person = Person.objects.get(name='Joe Smith')
view_url = reverse('ietf.secr.rolodex.views.view', kwargs={'id':person.pk})
self.assertRedirects(response, view_url)

View file

@ -2,8 +2,9 @@ from django.contrib import messages
from django.contrib.auth.models import User
from django.db import IntegrityError
from django.forms.models import inlineformset_factory
from django.http import HttpResponseRedirect
from django.shortcuts import render, get_object_or_404, redirect
from django.utils.http import urlencode
from django.urls import reverse
from ietf.ietfauth.utils import role_required
from ietf.person.models import Person, Email, Alias
@ -35,13 +36,14 @@ def add(request):
if request.method == 'POST':
form = NameForm(request.POST)
if form.is_valid():
request.session['post_data'] = request.POST
# search to see if contact already exists
name = form.cleaned_data['name']
results = Alias.objects.filter(name=name)
if not results:
return HttpResponseRedirect('../add-proceed/')
params = dict(name=name)
url = reverse('ietf.secr.rolodex.views.add_proceed')
url = url + '?' + urlencode(params)
return redirect(url)
else:
form = NameForm()
@ -67,16 +69,14 @@ def add_proceed(request):
* form
"""
# if we get to this page from the add page, as expected, the session will have post_data.
if request.session['post_data']:
post_data = request.session['post_data']
if 'name' in request.GET:
name = request.GET.get('name')
elif 'name' in request.POST:
name = request.POST.get('name')
else:
messages.error('ERROR: unable to save session data (enable cookies)') # pylint: disable=no-value-for-parameter
return redirect('ietf.secr.rolodex.views.add')
name = ''
name = post_data['name']
if request.method == 'POST':
if request.method == 'POST' and request.POST.get('submit') == 'Submit':
form = NewPersonForm(request.POST)
if form.is_valid():
email = form.cleaned_data['email']

View file

@ -72,6 +72,10 @@ class SessionForm(forms.Form):
bethere = SearchablePersonsField(label="Must be present", required=False)
def __init__(self, *args, **kwargs):
if 'hidden' in kwargs:
self.hidden = kwargs.pop('hidden')
else:
self.hidden = False
super(SessionForm, self).__init__(*args, **kwargs)
self.fields['num_session'].widget.attrs['onChange'] = "stat_ls(this.selectedIndex);"
self.fields['length_session1'].widget.attrs['onClick'] = "if (check_num_session(1)) this.disabled=true;"
@ -92,6 +96,11 @@ class SessionForm(forms.Form):
if self.initial['length_session3'] != '0' and self.initial['length_session3'] != None:
self.fields['third_session'].initial = True
if self.hidden:
for key in self.fields.keys():
self.fields[key].widget = forms.HiddenInput()
self.fields['resources'].widget = forms.MultipleHiddenInput()
def clean_conflict1(self):
conflict = self.cleaned_data['conflict1']
check_conflict(conflict)

View file

@ -4,6 +4,7 @@ import debug # pyflakes:ignore
from ietf.utils.test_utils import TestCase, unicontent
from ietf.group.models import Group
from ietf.meeting.helpers import get_meeting
from ietf.meeting.models import Meeting, Session, ResourceAssociation
from ietf.meeting.test_data import make_meeting_test_data
from ietf.utils.mail import outbox, empty_outbox
@ -44,16 +45,26 @@ class SessionRequestTestCase(TestCase):
class SubmitRequestCase(TestCase):
def test_submit_request(self):
make_test_data()
meeting = get_meeting()
group = Group.objects.get(acronym='mars')
session_count_before = Session.objects.filter(meeting=meeting, group=group).count()
url = reverse('ietf.secr.sreq.views.new',kwargs={'acronym':group.acronym})
confirm_url = reverse('ietf.secr.sreq.views.confirm',kwargs={'acronym':group.acronym})
main_url = reverse('ietf.secr.sreq.views.main')
post_data = {'num_session':'1',
'length_session1':'3600',
'attendees':'10',
'conflict1':'',
'comments':'need projector'}
'comments':'need projector',
'submit': 'Continue'}
self.client.login(username="secretary", password="secretary+password")
r = self.client.post(url,post_data)
self.assertRedirects(r, reverse('ietf.secr.sreq.views.confirm', kwargs={'acronym':group.acronym}))
self.assertEqual(r.status_code, 200)
post_data['submit'] = 'Submit'
r = self.client.post(confirm_url,post_data)
self.assertRedirects(r, main_url)
session_count_after = Session.objects.filter(meeting=meeting, group=group).count()
self.assertTrue(session_count_after == session_count_before + 1)
def test_submit_request_invalid(self):
make_test_data()
@ -89,13 +100,17 @@ class SubmitRequestCase(TestCase):
'bethere':str(ad.pk),
'conflict1':'',
'comments':'',
'resources': resource.pk}
'resources': resource.pk,
'submit': 'Continue'}
self.client.login(username="ameschairman", password="ameschairman+password")
# submit
r = self.client.post(url,post_data)
self.assertRedirects(r, confirm_url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue('Confirm' in unicode(q("title")))
# confirm
r = self.client.post(confirm_url,{'submit':'Submit'})
post_data['submit'] = 'Submit'
r = self.client.post(confirm_url,post_data)
self.assertRedirects(r, reverse('ietf.secr.sreq.views.main'))
self.assertEqual(len(outbox),len_before+1)
notification = outbox[-1]

View file

@ -3,7 +3,6 @@ import datetime
from django.conf import settings
from django.contrib import messages
from django.db.models import Q
from django.http import Http404
from django.shortcuts import render, get_object_or_404, redirect
import debug # pyflakes:ignore
@ -224,28 +223,24 @@ def confirm(request, acronym):
to confirm for submission.
'''
# FIXME: this should be using form.is_valid/form.cleaned_data - invalid input will make it crash
querydict = request.session.get('session_form',None)
if not querydict:
raise Http404
form = querydict.copy()
if 'resources' in form:
form['resources'] = [ ResourceAssociation.objects.get(pk=pk) for pk in form['resources'].split(',')]
if 'bethere' in form:
person_id_list = [ id for id in form['bethere'].split(',') if id ]
form['bethere'] = Person.objects.filter(pk__in=person_id_list)
form = SessionForm(request.POST, hidden=True)
form.is_valid()
meeting = get_meeting()
group = get_object_or_404(Group,acronym=acronym)
login = request.user.person
if request.method == 'POST':
# clear http session data
del request.session['session_form']
button_text = request.POST.get('submit', '')
if button_text == 'Cancel':
messages.success(request, 'Session Request has been canceled')
return redirect('ietf.secr.sreq.views.main')
session_data = form.data.copy()
if 'bethere' in session_data:
person_id_list = [ id for id in form.data['bethere'].split(',') if id ]
session_data['bethere'] = Person.objects.filter(pk__in=person_id_list)
session_data['resources'] = [ ResourceAssociation.objects.get(pk=pk) for pk in request.POST.getlist('resources') ]
button_text = request.POST.get('submit', '')
if button_text == 'Cancel':
messages.success(request, 'Session Request has been canceled')
return redirect('ietf.secr.sreq.views.main')
if request.method == 'POST' and button_text == 'Submit':
# delete any existing session records with status = canceled or notmeet
Session.objects.filter(group=group,meeting=meeting,status__in=('canceled','notmeet')).delete()
@ -253,53 +248,50 @@ def confirm(request, acronym):
count = 0
# lenth_session2 and length_session3 fields might be disabled by javascript and so
# wouldn't appear in form data
for duration in (form.get('length_session1',None),form.get('length_session2',None),form.get('length_session3',None)):
for duration in (form.data.get('length_session1',None),form.data.get('length_session2',None),form.data.get('length_session3',None)):
count += 1
if duration:
slug = 'apprw' if count == 3 else 'schedw'
new_session = Session(meeting=meeting,
group=group,
attendees=form['attendees'],
attendees=form.data['attendees'],
requested=datetime.datetime.now(),
requested_by=login,
requested_duration=datetime.timedelta(0,int(duration)),
comments=form['comments'],
comments=form.data['comments'],
status=SessionStatusName.objects.get(slug=slug),
type_id='session',
)
session_save(new_session)
if 'resources' in form:
new_session.resources = form['resources']
if 'resources' in form.data:
new_session.resources = session_data['resources']
# write constraint records
save_conflicts(group,meeting,form.get('conflict1',''),'conflict')
save_conflicts(group,meeting,form.get('conflict2',''),'conflic2')
save_conflicts(group,meeting,form.get('conflict3',''),'conflic3')
save_conflicts(group,meeting,form.data.get('conflict1',''),'conflict')
save_conflicts(group,meeting,form.data.get('conflict2',''),'conflic2')
save_conflicts(group,meeting,form.data.get('conflict3',''),'conflic3')
if 'bethere' in form:
if 'bethere' in form.data:
bethere_cn = ConstraintName.objects.get(slug='bethere')
for p in form.get('bethere', []):
for p in session_data['bethere']:
Constraint.objects.create(name=bethere_cn, source=group, person=p, meeting=new_session.meeting)
# deprecated in new schema
# log activity
#add_session_activity(group,'New session was requested',meeting,user)
# clear not meeting
Session.objects.filter(group=group,meeting=meeting,status='notmeet').delete()
# send notification
send_notification(group,meeting,login,form,'new')
send_notification(group,meeting,login,session_data,'new')
status_text = 'IETF Agenda to be scheduled'
messages.success(request, 'Your request has been sent to %s' % status_text)
return redirect('ietf.secr.sreq.views.main')
# GET logic
# POST from request submission
session_conflicts = session_conflicts_as_string(group, meeting)
return render(request, 'sreq/confirm.html', {
'session': form,
'form': form,
'session': session_data,
'group': group,
'session_conflicts': session_conflicts},
)
@ -539,10 +531,7 @@ def new(request, acronym):
if Session.objects.filter(group=group,meeting=meeting).exclude(status__in=('deleted','notmeet')):
messages.warning(request, 'Sessions for working group %s have already been requested once.' % group.acronym)
return redirect('ietf.secr.sreq.views.main')
# save in user session
request.session['session_form'] = form.data
return redirect('ietf.secr.sreq.views.confirm',acronym=acronym)
return confirm(request, acronym)
# the "previous" querystring causes the form to be returned
# pre-populated with data from last meeeting's session request

View file

@ -14,9 +14,9 @@
{% block content %}
<div class="module">
<h2>Announcement</h2>
<h2>Confirm Announcement</h2>
<form action="" method="post">{% csrf_token %}
<form action="{% url "ietf.secr.announcement.views.confirm" %}" method="post">{% csrf_token %}
<pre id="announce-confirm">
To: {{ to }}
@ -29,6 +29,7 @@ Subject: {{ message.subject }}
{{ message.body }}
</pre>
{{ form }}
<div class="button-group">
<ul id="announcement-button-list">
<li><button type="submit" name="submit" value="Send">Send</button></li>

View file

@ -23,8 +23,8 @@
</table>
<div class="button-group">
<ul id="announcement-button-list">
<li><button type="submit" name="submit" value="submit">Submit</button></li>
<li><button type="submit" name="submit" value="Cancel">Cancel</button></li>
<li><button type="submit" name="submit" value="Continue">Continue</button></li>
<li><button onclick="window.location='../'" value="Cancel">Cancel</button></li>
</ul>
</div> <!-- button-group -->

View file

@ -17,7 +17,7 @@
<div class="module draft-container">
<h2>Draft - Confirm</h2>
<form enctype="multipart/form-data" action="" method="post">{% csrf_token %}
<form enctype="multipart/form-data" action="{% url "ietf.secr.drafts.views.do_action" id=draft.name %}" method="post">{% csrf_token %}
<table>
<tr><th>Action Selected:</th><td>{{ action }}</td></tr>
@ -39,6 +39,8 @@
</div>
{% endif %}
{{ form }}
{% include "includes/buttons_save_cancel.html" %}
</form>

View file

@ -17,7 +17,7 @@
<div class="module draft-container">
<h2>Draft - Email</h2>
<form enctype="multipart/form-data" action="" method="post">{% csrf_token %}
<form enctype="multipart/form-data" action="{% url "ietf.secr.drafts.views.confirm" id=draft.name %}" method="post">{% csrf_token %}
<table id="draft-email-table" class="full-width">
{{ form.as_table }}
</table>

View file

@ -82,7 +82,7 @@
<ul>
<li><button {% if is_active %}{% else %}disabled="disabled"{% endif %}onclick="window.location='revision/'">New Revision</button></li>
<li><button {% if is_expired %}{% else %}disabled="disabled"{% endif %}onclick="window.location='update/'">Update Expired</button></li>
<li><button {% if is_expired or is_withdrawn %}{% else %}disabled="disabled"{% endif %}onclick="window.location='resurrect/'">Resurrect</button></li>
<li><button {% if is_expired or is_withdrawn %}{% else %}disabled="disabled"{% endif %}onclick="window.location='{% url "ietf.secr.drafts.views.email" id=draft.name %}?action=resurrect'">Resurrect</button></li>
<li><button {% if is_active or is_expired %}{% else %}disabled="disabled"{% endif %}onclick="window.location='replace/'">Replace</button></li>
<li><button {% if is_active %}{% else %}disabled="disabled"{% endif %}onclick="window.location='extend/'">Extend Expiry</button></li>
<li><button {% if is_active %}{% else %}disabled="disabled"{% endif %}onclick="window.location='withdraw/'">Withdraw</button></li>

View file

@ -64,7 +64,7 @@
<div class="button-group">
<ul>
<li><button type="submit" name="submit" value="Save"{% if is_locked %} disabled{% endif %}>Save</button></li>
<li><button type="submit" name="submit" value="Continue"{% if is_locked %} disabled{% endif %}>Continue</button></li>
<li><button type="submit" name="submit" value="Cancel">Cancel</button></li>
</ul>
</div> <!-- button-group -->

View file

@ -21,14 +21,17 @@
<div class="module">
<h2>Adding {{ name }} </h2>
{% include "includes/search_results_table.html" %}
<form id="rolodex-add-form" enctype="multipart/form-data" action="{% url "ietf.secr.rolodex.views.add_proceed" %}" method="post">{% csrf_token %}
<div>{{ form.as_p }}</div>
{% include "includes/search_results_table.html" %}
<div class="button-group">
<ul>
<li><button onclick="history.go(-1);return true">Back</button></li>
<li><button onclick="window.location='../add-proceed/'">Proceed</button></li>
</ul>
</div> <!-- button-group -->
<div class="button-group">
<ul>
<li><button onclick="history.go(-1);return true">Back</button></li>
<li><button type="submit" name="submit" value="Continue">Continue</button></li>
</ul>
</div> <!-- button-group -->
</form>
</div> <!-- module -->
{% else %}

View file

@ -1,7 +1,7 @@
{% extends "base_site.html" %}
{% load staticfiles %}
{% block title %}Sessions - View{% endblock %}
{% block title %}Sessions - Confirm{% endblock %}
{% block extrahead %}{{ block.super }}
<script type="text/javascript" src="{% static 'secr/js/utils.js' %}"></script>
@ -28,7 +28,8 @@
<br>
{% endif %}
<form action="" method="post">{% csrf_token %}
<form action="{% url "ietf.secr.sreq.views.confirm" acronym=group.acronym %}" method="post">{% csrf_token %}
{{ form }}
{% include "includes/buttons_submit_cancel.html" %}
</form>

View file

@ -13,13 +13,6 @@ from ietf.group.models import Group, Role
from ietf.meeting.models import Session
from ietf.secr.utils.meeting import get_timeslot
def clear_non_auth(session):
"""
Clears non authentication related keys from the session object
"""
for key in session.keys():
if not key.startswith('_auth'):
del session[key]
def check_for_cancel(redirect_url):
"""
@ -30,7 +23,6 @@ def check_for_cancel(redirect_url):
@wraps(func)
def inner(request, *args, **kwargs):
if request.method == 'POST' and request.POST.get('submit',None) == 'Cancel':
clear_non_auth(request.session)
return HttpResponseRedirect(redirect_url)
return func(request, *args, **kwargs)
return inner

View file

@ -37,6 +37,8 @@ def log(msg):
"Uses syslog by preference. Logs the given calling point and message."
if settings.SERVER_MODE == 'test':
return
elif settings.DEBUG == True:
logfunc = debug.say
if isinstance(msg, unicode):
msg = msg.encode('unicode_escape')
try: