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 commitf9d614528b
Note: SVN reference [8320] has been migrated to Git commitfaa6469e27
This commit is contained in:
commit
f3afb556c2
|
@ -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)
|
||||
|
|
|
@ -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']
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -133,4 +133,4 @@ class SessionForm(forms.Form):
|
|||
|
||||
class ToolStatusForm(forms.Form):
|
||||
message = forms.CharField(widget=forms.Textarea(attrs={'rows':'3','cols':'80'}))
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 -->
|
||||
|
||||
|
|
|
@ -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 %}
|
||||
|
|
Loading…
Reference in a new issue