Merged in [8156] and [8320] from rcross@amsl.com:

Do not allow editing or submitting new session requests when the tool is locked.  Fixes Ticket #1443.
 - Legacy-Id: 8391
Note: SVN reference [8156] has been migrated to Git commit f9d614528b

Note: SVN reference [8320] has been migrated to Git commit faa6469e27
This commit is contained in:
Henrik Levkowetz 2014-10-12 19:17:51 +00:00
commit f3afb556c2
10 changed files with 102 additions and 38 deletions

View file

@ -61,7 +61,8 @@ class Meeting(models.Model):
reg_area = models.CharField(blank=True, max_length=255)
agenda_note = models.TextField(blank=True, help_text="Text in this field will be placed at the top of the html agenda page for the meeting. HTML can be used, but will not validated.")
agenda = models.ForeignKey('Schedule',null=True,blank=True, related_name='+')
session_request_lock_message = models.CharField(blank=True,max_length=255) # locked if not empty
def __unicode__(self):
if self.type_id == "ietf":
return "IETF-%s" % (self.number)

View file

@ -90,7 +90,7 @@ class TimeChoiceField(forms.ChoiceField):
class MeetingModelForm(forms.ModelForm):
class Meta:
model = Meeting
exclude = ('type', 'agenda')
exclude = ('type', 'agenda', 'session_request_lock_message')
def clean_number(self):
number = self.cleaned_data['number']

View file

@ -4,7 +4,7 @@ from ietf.utils.test_utils import TestCase
from ietf.person.models import Person
from ietf.group.models import Group, GroupEvent
from ietf.meeting.models import Meeting, Schedule, Room, TimeSlot, ScheduledSession
from ietf.meeting.models import Meeting, Room, TimeSlot, ScheduledSession
from ietf.utils.mail import outbox
from ietf.meeting.test_data import make_meeting_test_data
@ -43,15 +43,17 @@ class MainTestCase(TestCase):
def test_add_meeting(self):
"Add Meeting"
meeting = make_meeting_test_data()
number = int(meeting.number) + 1
count = Meeting.objects.count()
url = reverse('meetings_add')
post_data = dict(number=1,city='Toronto',date='2014-07-20',country='CA',
post_data = dict(number=number,city='Toronto',date='2014-07-20',country='CA',
time_zone='America/New_York',venue_name='Hilton',
venue_addr='100 First Ave')
self.client.login(username='secretary', password='secretary+password')
response = self.client.post(url, post_data, follow=True)
self.assertEqual(response.status_code, 200)
self.assertEqual(Meeting.objects.count(),1)
self.assertEqual(Schedule.objects.count(),1)
self.assertEqual(Meeting.objects.count(),count + 1)
def test_edit_meeting(self):
"Edit Meeting"

View file

@ -13,6 +13,7 @@ from django.template import RequestContext
from django.utils.functional import curry
from ietf.utils.mail import send_mail
from ietf.meeting.helpers import get_meeting
from ietf.meeting.models import Meeting, Session, Room, TimeSlot, ScheduledSession, Schedule
from ietf.group.models import Group, GroupEvent
from ietf.person.models import Person
@ -27,8 +28,6 @@ from ietf.secr.utils.mail import get_cc_list
from ietf.secr.utils.meeting import get_session, get_timeslot
# prep for agenda changes
# --------------------------------------------------
# Helper Functions
@ -295,6 +294,10 @@ def add(request):
visible = True,
public = True)
meeting.agenda = schedule
# we want to carry session request lock status over from previous meeting
previous_meeting = get_meeting( int(meeting.number) - 1 )
meeting.session_request_lock_message = previous_meeting.session_request_lock_message
meeting.save()
#Create Physical new meeting directory and subdirectories

View file

@ -133,4 +133,4 @@ class SessionForm(forms.Form):
class ToolStatusForm(forms.Form):
message = forms.CharField(widget=forms.Textarea(attrs={'rows':'3','cols':'80'}))

View file

@ -2,10 +2,11 @@ from django.core.urlresolvers import reverse
from ietf.utils.test_utils import TestCase
from ietf.group.models import Group
#from ietf.meeting.models import Session
#from ietf.utils.test_data import make_test_data
from ietf.meeting.test_data import make_meeting_test_data as make_test_data
#from pyquery import PyQuery
from pyquery import PyQuery
SECR_USER='secretary'
@ -59,6 +60,42 @@ class SubmitRequestCase(TestCase):
r = self.client.get(url)
assert False, r.content
"""
class LockAppTestCase(TestCase):
def test_edit_request(self):
meeting = make_test_data()
meeting.session_request_lock_message='locked'
meeting.save()
group = Group.objects.get(acronym='mars')
url = reverse('sessions_edit',kwargs={'acronym':group.acronym})
self.client.login(username="secretary", password="secretary+password")
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertEqual(len(q(':disabled[name="submit"]')), 1)
def test_view_request(self):
meeting = make_test_data()
meeting.session_request_lock_message='locked'
meeting.save()
group = Group.objects.get(acronym='mars')
url = reverse('sessions_view',kwargs={'acronym':group.acronym})
self.client.login(username="secretary", password="secretary+password")
r = self.client.get(url,follow=True)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertEqual(len(q(':disabled[name="edit"]')), 1)
def test_new_request(self):
meeting = make_test_data()
meeting.session_request_lock_message='locked'
meeting.save()
group = Group.objects.get(acronym='mars')
url = reverse('sessions_new',kwargs={'acronym':group.acronym})
self.client.login(username="secretary", password="secretary+password")
r = self.client.get(url)
self.assertEqual(r.status_code, 302)
class EditRequestCase(TestCase):
pass
@ -73,4 +110,4 @@ class RetrievePreviousCase(TestCase):
# test error if already scheduled
# test get previous exists/doesn't exist
# test that groups scheduled and unscheduled add up to total groups
# test locking function, access by unauthorized
# test access by unauthorized

View file

@ -1,7 +1,5 @@
import datetime
import os
from django.conf import settings
from django.contrib import messages
from django.db.models import Q
from django.http import Http404
@ -24,16 +22,18 @@ from ietf.person.models import Email
# Globals
# -------------------------------------------------
SESSION_REQUEST_EMAIL = 'session-request@ietf.org'
LOCKFILE = os.path.join(settings.SECR_PROCEEDINGS_DIR,'session_request.lock')
# -------------------------------------------------
# Helper Functions
# -------------------------------------------------
def check_app_locked():
def check_app_locked(meeting=None):
'''
This function returns True if the application is locked to non-secretariat users.
'''
return os.path.exists(LOCKFILE)
if not meeting:
meeting = get_meeting()
return bool(meeting.session_request_lock_message)
def get_initial_session(sessions):
'''
@ -75,17 +75,13 @@ def get_initial_session(sessions):
initial['bethere'] = bethere_email
return initial
def get_lock_message():
def get_lock_message(meeting=None):
'''
Returns the message to display to non-secretariat users when the tool is locked.
'''
try:
f = open(LOCKFILE,'r')
message = f.read()
f.close()
except IOError:
message = "This application is currently locked."
return message
if not meeting:
meeting = get_meeting()
return meeting.session_request_lock_message
def get_requester_text(person,group):
'''
@ -355,6 +351,11 @@ def edit_mtg(request, num, acronym):
if 'resources' in initial:
initial['resources'] = [x.pk for x in initial['resources']]
# check if app is locked
is_locked = check_app_locked(meeting=meeting)
if is_locked:
messages.warning(request, "The Session Request Tool is closed")
session_conflicts = session_conflicts_as_string(group, meeting)
login = request.user.person
@ -467,6 +468,7 @@ def edit_mtg(request, num, acronym):
form = SessionForm(initial=initial)
return render_to_response('sreq/edit.html', {
'is_locked': is_locked,
'meeting': meeting,
'form': form,
'group': group,
@ -541,11 +543,16 @@ def new(request, acronym):
This view gathers details for a new session request. The user proceeds to confirm()
to create the request.
'''
group = get_object_or_404(Group, acronym=acronym)
meeting = get_meeting()
session_conflicts = session_conflicts_as_string(group, meeting)
# check if app is locked
is_locked = check_app_locked()
if is_locked:
messages.warning(request, "The Session Request Tool is closed")
return redirect('sessions')
if request.method == 'POST':
button_text = request.POST.get('submit', '')
if button_text == 'Cancel':
@ -643,27 +650,26 @@ def tool_status(request):
'''
This view handles locking and unlocking of the tool to the public.
'''
is_locked = check_app_locked()
meeting = get_meeting()
is_locked = check_app_locked(meeting=meeting)
if request.method == 'POST':
button_text = request.POST.get('submit', '')
if button_text == 'Done':
if button_text == 'Back':
return redirect('sessions')
form = ToolStatusForm(request.POST)
if button_text == 'Lock':
if form.is_valid():
f = open(LOCKFILE,'w')
f.write(form.cleaned_data['message'])
f.close()
meeting.session_request_lock_message = form.cleaned_data['message']
meeting.save()
messages.success(request, 'Session Request Tool is now Locked')
return redirect('sessions')
elif button_text == 'Unlock':
os.remove(LOCKFILE)
meeting.session_request_lock_message = ''
meeting.save()
messages.success(request, 'Session Request Tool is now Unlocked')
return redirect('sessions')
@ -689,9 +695,17 @@ def view(request, acronym, num = None):
group = get_object_or_404(Group, acronym=acronym)
sessions = Session.objects.filter(~Q(status__in=('canceled','notmeet','deleted')),meeting=meeting,group=group).order_by('id')
# check if app is locked
is_locked = check_app_locked()
if is_locked:
messages.warning(request, "The Session Request Tool is closed")
# if there are no session requests yet, redirect to new session request page
if not sessions:
return redirect('sessions_new', acronym=acronym)
if is_locked:
return redirect('sessions')
else:
return redirect('sessions_new', acronym=acronym)
# TODO simulate activity records
activities = [{'act_date':sessions[0].requested.strftime('%b %d, %Y'),
@ -718,6 +732,7 @@ def view(request, acronym, num = None):
session = get_initial_session(sessions)
return render_to_response('sreq/view.html', {
'is_locked': is_locked,
'session': session,
'activities': activities,
'meeting': meeting,

View file

@ -62,6 +62,12 @@
</tr>
</table>
{% include "includes/buttons_save_cancel.html" %}
<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="Cancel">Cancel</button></li>
</ul>
</div> <!-- button-group -->
</form>

View file

@ -27,7 +27,7 @@
{% else %}
<li><button type="submit" name="submit" value="Lock">Lock</button></li>
{% endif %}
<li><button type="submit" name="submit" value="Done">Done</button></li>
<li><button type="submit" name="submit" value="Back">Back</button></li>
</ul>
</div> <!-- button-group -->

View file

@ -28,7 +28,7 @@
<div class="button-group">
<ul>
<li><button onclick="window.location='edit/'">Edit</button></li>
<li><button name="edit" onclick="window.location='edit/'"{% if is_locked %} disabled{% endif %}>Edit</button></li>
{% if show_approve_button %}
<li><button onclick="window.location='approve/'">Approve Third Session</button></li>
{% endif %}