Skip to content

Commit 818bffd

Browse files
committed
first app for merge, sreq
- Legacy-Id: 5173
1 parent af9a442 commit 818bffd

108 files changed

Lines changed: 7791 additions & 1 deletion

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ietf/secr/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
__version__ = "1.33"
2+
3+
__date__ = "$Date: 2011/07/26 14:29:17 $"
4+
5+
__rev__ = "$Rev: 3113 $"
6+
7+
__id__ = "$Id: __init__.py,v 1.5 2011/07/26 14:29:17 rcross Exp $"
8+

ietf/secr/context_processors.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright The IETF Trust 2007, All Rights Reserved
2+
3+
from django.conf import settings
4+
from ietf.secr import __date__, __rev__, __version__, __id__
5+
6+
def server_mode(request):
7+
return {'server_mode': settings.SERVER_MODE}
8+
9+
def secr_revision_info(request):
10+
return {'secr_revision_time': __date__[7:32], 'secr_revision_date': __date__[7:17], 'secr_revision_num': __rev__[6:-2], "secr_revision_id": __id__[5:-2], "secr_version_num": __version__ }

ietf/secr/middleware/__init__.py

Whitespace-only changes.

ietf/secr/middleware/secauth.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from django.conf import settings
2+
from django.http import HttpResponseForbidden
3+
from django.shortcuts import render_to_response
4+
5+
from ietf.ietfauth.decorators import has_role
6+
7+
import re
8+
9+
class SecAuthMiddleware(object):
10+
"""
11+
Middleware component that performs custom auth check for every
12+
request except those excluded by SEC_AUTH_UNRESTRICTED_URLS.
13+
14+
Since authentication is performed externally at the apache level
15+
REMOTE_USER should contain the name of the authenticated
16+
user. If the user is a secretariat than access is granted.
17+
Otherwise return a 401 error page.
18+
19+
To use, add the class to MIDDLEWARE_CLASSES and define
20+
SEC_AUTH_UNRESTRCITED_URLS in your settings.py.
21+
22+
The following example allows access to anything under "/interim/"
23+
to non-secretariat users:
24+
25+
SEC_AUTH_UNRESTRCITED_URLS = (
26+
(r'^/interim/'),
27+
28+
Also sets custom request attributes:
29+
user_is_secretariat
30+
user_is_chair
31+
user_is_ad
32+
)
33+
34+
"""
35+
36+
def __init__(self):
37+
self.unrestricted = [re.compile(pattern) for pattern in
38+
settings.SEC_AUTH_UNRESTRICTED_URLS]
39+
40+
def process_view(self, request, view_func, view_args, view_kwargs):
41+
# need to initialize user, it doesn't get set when running tests for example
42+
user = ''
43+
request.user_is_secretariat = False
44+
45+
if 'REMOTE_USER' in request.META:
46+
# do custom auth
47+
if has_role(request.user,'Secretariat'):
48+
request.user_is_secretariat = True
49+
50+
return None
51+

ietf/secr/sreq/__init__.py

Whitespace-only changes.

ietf/secr/sreq/forms.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
from django import forms
2+
3+
from ietf.group.models import Group
4+
import os
5+
6+
# -------------------------------------------------
7+
# Globals
8+
# -------------------------------------------------
9+
10+
NUM_SESSION_CHOICES = (('','--Please select'),('1','1'),('2','2'))
11+
LENGTH_SESSION_CHOICES = (('','--Please select'),('1800','30 minutes'),('3600','1 hour'),('5400','1.5 hours'), ('7200','2 hours'),('9000','2.5 hours'))
12+
WG_CHOICES = list( Group.objects.filter(type__in=('wg','rg','ag'),state__in=('bof','proposed','active')).values_list('acronym','acronym').order_by('acronym'))
13+
WG_CHOICES.insert(0,('','--Select WG(s)'))
14+
15+
# -------------------------------------------------
16+
# Helper Functions
17+
# -------------------------------------------------
18+
def check_conflict(groups):
19+
'''
20+
Takes a string which is a list of group acronyms. Checks that they are all active groups
21+
'''
22+
# convert to python list (allow space or comma separated lists)
23+
items = groups.replace(',',' ').split()
24+
active_groups = Group.objects.filter(type__in=('wg','ag','rg'), state__in=('bof','proposed','active'))
25+
for group in items:
26+
if not active_groups.filter(acronym=group):
27+
raise forms.ValidationError("Invalid or inactive group acronym: %s" % group)
28+
29+
def join_conflicts(data):
30+
'''
31+
Takes a dictionary (ie. data dict from a form) and concatenates all
32+
conflict fields into one list
33+
'''
34+
conflicts = []
35+
for groups in (data['conflict1'],data['conflict2'],data['conflict3']):
36+
# convert to python list (allow space or comma separated lists)
37+
items = groups.replace(',',' ').split()
38+
conflicts.extend(items)
39+
return conflicts
40+
41+
# -------------------------------------------------
42+
# Forms
43+
# -------------------------------------------------
44+
45+
class GroupSelectForm(forms.Form):
46+
group = forms.ChoiceField()
47+
48+
def __init__(self,*args,**kwargs):
49+
choices = kwargs.pop('choices')
50+
super(GroupSelectForm, self).__init__(*args,**kwargs)
51+
self.fields['group'].widget.choices = choices
52+
53+
54+
class SessionForm(forms.Form):
55+
num_session = forms.ChoiceField(choices=NUM_SESSION_CHOICES)
56+
length_session1 = forms.ChoiceField(choices=LENGTH_SESSION_CHOICES)
57+
length_session2 = forms.ChoiceField(choices=LENGTH_SESSION_CHOICES,required=False)
58+
length_session3 = forms.ChoiceField(choices=LENGTH_SESSION_CHOICES,required=False)
59+
attendees = forms.IntegerField()
60+
conflict1 = forms.CharField(max_length=255,required=False)
61+
conflict2 = forms.CharField(max_length=255,required=False)
62+
conflict3 = forms.CharField(max_length=255,required=False)
63+
comments = forms.CharField(max_length=200,required=False)
64+
wg_selector1 = forms.ChoiceField(choices=WG_CHOICES,required=False)
65+
wg_selector2 = forms.ChoiceField(choices=WG_CHOICES,required=False)
66+
wg_selector3 = forms.ChoiceField(choices=WG_CHOICES,required=False)
67+
third_session = forms.BooleanField(required=False)
68+
69+
def __init__(self, *args, **kwargs):
70+
super(SessionForm, self).__init__(*args, **kwargs)
71+
self.fields['num_session'].widget.attrs['onChange'] = "stat_ls(this.selectedIndex);"
72+
self.fields['length_session1'].widget.attrs['onClick'] = "if (check_num_session(1)) this.disabled=true;"
73+
self.fields['length_session2'].widget.attrs['onClick'] = "if (check_num_session(2)) this.disabled=true;"
74+
self.fields['length_session3'].widget.attrs['onClick'] = "if (check_third_session()) { this.disabled=true;}"
75+
self.fields['comments'].widget = forms.Textarea(attrs={'rows':'6','cols':'65'})
76+
self.fields['wg_selector1'].widget.attrs['onChange'] = "document.form_post.conflict1.value=document.form_post.conflict1.value + ' ' + this.options[this.selectedIndex].value; return handleconflictfield(1);"
77+
self.fields['wg_selector2'].widget.attrs['onChange'] = "document.form_post.conflict2.value=document.form_post.conflict2.value + ' ' + this.options[this.selectedIndex].value; return handleconflictfield(2);"
78+
self.fields['wg_selector2'].widget.attrs['onClick'] = "return check_prior_conflict(2);"
79+
self.fields['wg_selector3'].widget.attrs['onChange'] = "document.form_post.conflict3.value=document.form_post.conflict3.value + ' ' + this.options[this.selectedIndex].value; return handleconflictfield(3);"
80+
self.fields['wg_selector3'].widget.attrs['onClick'] = "return check_prior_conflict(3);"
81+
self.fields['third_session'].widget.attrs['onClick'] = "if (document.form_post.num_session.selectedIndex < 2) { alert('Cannot use this field - Number of Session is not set to 2'); return false; } else { if (this.checked==true) { document.form_post.length_session3.disabled=false; } else { document.form_post.length_session3.value=0;document.form_post.length_session3.disabled=true; } }"
82+
83+
# check third_session checkbox if instance and length_session3
84+
# assert False, (self.instance, self.fields['length_session3'].initial)
85+
if self.initial and 'length_session3' in self.initial:
86+
if self.initial['length_session3'] != '0' and self.initial['length_session3'] != None:
87+
self.fields['third_session'].initial = True
88+
89+
def clean_conflict1(self):
90+
conflict = self.cleaned_data['conflict1']
91+
check_conflict(conflict)
92+
return conflict
93+
94+
def clean_conflict2(self):
95+
conflict = self.cleaned_data['conflict2']
96+
check_conflict(conflict)
97+
return conflict
98+
99+
def clean_conflict3(self):
100+
conflict = self.cleaned_data['conflict3']
101+
check_conflict(conflict)
102+
return conflict
103+
104+
def clean(self):
105+
super(SessionForm, self).clean()
106+
data = self.cleaned_data
107+
if self.errors:
108+
return self.cleaned_data
109+
110+
# error if conflits contain dupes
111+
all_conflicts = join_conflicts(data)
112+
temp = []
113+
for c in all_conflicts:
114+
if c not in temp:
115+
temp.append(c)
116+
else:
117+
raise forms.ValidationError('%s appears in conflicts more than once' % c)
118+
119+
# verify session_length and num_session correspond
120+
# if default (empty) option is selected, cleaned_data won't include num_session key
121+
if data.get('num_session','') == 2:
122+
if not data['length_session2']:
123+
raise forms.ValidationError('You must enter a length for session 2')
124+
125+
if data.get('third_session',False):
126+
if not data.get('length_session3',None):
127+
raise forms.ValidationError('Length of third session not selected')
128+
129+
return data
130+
131+
class ToolStatusForm(forms.Form):
132+
message = forms.CharField(widget=forms.Textarea(attrs={'rows':'3','cols':'80'}))
133+

ietf/secr/sreq/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from django.db import models

ietf/secr/sreq/templatetags/__init__.py

Whitespace-only changes.

ietf/secr/sreq/tests.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
from django.core.urlresolvers import reverse
2+
from django.test import TestCase
3+
from django.contrib.auth.models import User
4+
5+
from ietf.group.models import Group
6+
from ietf.ietfauth.decorators import has_role
7+
8+
from pyquery import PyQuery
9+
10+
SEC_USER='rcross'
11+
WG_USER=''
12+
AD_USER=''
13+
14+
class MainTestCase(TestCase):
15+
fixtures = ['names',
16+
'test-meeting',
17+
'test-group',
18+
'test-person',
19+
'test-user',
20+
'test-email',
21+
'test-role']
22+
23+
# ------- Test View -------- #
24+
def test_main(self):
25+
url = reverse('sessions')
26+
r = self.client.get(url,REMOTE_USER=SEC_USER)
27+
self.assertEquals(r.status_code, 200)
28+
#assert False, (r.context)
29+
sched = r.context['scheduled_groups']
30+
unsched = r.context['unscheduled_groups']
31+
self.failUnless(len(sched) == 0)
32+
self.failUnless(len(unsched) == 5)
33+
#ancp = Group.objects.get(acronym='ancp')
34+
paws = Group.objects.get(acronym='paws')
35+
#self.failUnless(ancp in sched)
36+
self.failUnless(paws in unsched)
37+
#assert False, r.content
38+
#user = User.objects.get(username='rcross')
39+
#self.failUnless(has_role(user,'Secretariat'))
40+
41+
class SubmitRequestCase(TestCase):
42+
fixtures = ['names',
43+
'test-meeting',
44+
'test-group',
45+
'test-person',
46+
'test-user',
47+
'test-email',
48+
'test-role']
49+
50+
def test_submit_request(self):
51+
url = reverse('sessions_new',kwargs={'acronym':'ancp'})
52+
post_data = {'id_num_session':'1',
53+
'id_length_session1':'3600',
54+
'id_attendees':'10',
55+
'id_conflict1':'core',
56+
'id_comments':'need projector'}
57+
self.client.login(remote_user='rcross')
58+
r = self.client.post(url,post_data)
59+
self.assertEquals(r.status_code, 200)
60+
#assert False, self.client.session..__dict__
61+
62+
url = reverse('sessions_confirm',kwargs={'acronym':'ancp'})
63+
#s = self.client.session
64+
#s['session_form'] = post_data
65+
r = self.client.get(url)
66+
assert False, r.content
67+
68+
class EditRequestCase(TestCase):
69+
pass
70+
71+
class NotMeetingCase(TestCase):
72+
pass
73+
74+
class RetrievePreviousCase(TestCase):
75+
pass
76+
77+
78+
79+
# test error if already scheduled
80+
# test get previous exists/doesn't exist
81+
# test that groups scheduled and unscheduled add up to total groups
82+
# test locking function, access by unauthorized

ietf/secr/sreq/urls.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from django.conf.urls.defaults import *
2+
3+
urlpatterns = patterns('sec.sreq.views',
4+
url(r'^$', 'main', name='sessions'),
5+
url(r'^status/$', 'tool_status', name='sessions_tool_status'),
6+
url(r'^(?P<acronym>[A-Za-z0-9_\-\+]+)/$', 'view', name='sessions_view'),
7+
url(r'^(?P<acronym>[A-Za-z0-9_\-\+]+)/approve/$', 'approve', name='sessions_approve'),
8+
url(r'^(?P<acronym>[A-Za-z0-9_\-\+]+)/cancel/$', 'cancel', name='sessions_cancel'),
9+
url(r'^(?P<acronym>[A-Za-z0-9_\-\+]+)/confirm/$', 'confirm', name='sessions_confirm'),
10+
url(r'^(?P<acronym>[A-Za-z0-9_\-\+]+)/edit/$', 'edit', name='sessions_edit'),
11+
url(r'^(?P<acronym>[A-Za-z0-9_\-\+]+)/new/$', 'new', name='sessions_new'),
12+
url(r'^(?P<acronym>[A-Za-z0-9_\-\+]+)/no_session/$', 'no_session', name='sessions_no_session'),
13+
)

0 commit comments

Comments
 (0)