Add support for incoming ADs with a new "pre-ad" role

- Legacy-Id: 3900
This commit is contained in:
Ole Laursen 2012-02-03 16:22:31 +00:00
parent 5c66a91c0e
commit d43159cd90
9 changed files with 57 additions and 16 deletions

View file

@ -500,6 +500,22 @@ class EditPositionTestCase(django.test.TestCase):
self.assertEquals(pos.discuss, "Test discuss text")
self.assertTrue("New position" in pos.desc)
self.assertTrue("by Sec" in pos.desc)
def test_cannot_edit_position_as_pre_ad(self):
draft = make_test_data()
url = urlreverse('doc_edit_position', kwargs=dict(name=draft.name))
# transform to pre-ad
ad_role = Role.objects.filter(name="ad")[0]
ad_role.name_id = "pre-ad"
ad_role.save()
# we can see
login_testing_unauthorized(self, ad_role.person.user.username, url)
# but not touch
r = self.client.post(url, dict(position="discuss", discuss="Test discuss text"))
self.assertEquals(r.status_code, 403)
def test_send_ballot_comment(self):
draft = make_test_data()

View file

@ -3,7 +3,7 @@
import re, os
from datetime import datetime, date, time, timedelta
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, Http404
from django.shortcuts import render_to_response, get_object_or_404
from django.core.urlresolvers import reverse as urlreverse
from django.template.loader import render_to_string
@ -15,7 +15,7 @@ from django.conf import settings
from ietf.utils.mail import send_mail_text, send_mail_preformatted
from ietf.ietfauth.decorators import group_required
from ietf.idtracker.templatetags.ietf_filters import in_group
from ietf.ietfauth.decorators import has_role
from ietf.ietfauth.decorators import has_role, role_required
from ietf.idtracker.models import *
from ietf.iesg.models import *
from ietf.ipr.models import IprDetail
@ -222,7 +222,7 @@ class EditPositionFormREDESIGN(forms.Form):
raise forms.ValidationError("You must enter a non-empty discuss")
return entered_discuss
@group_required('Area_Director','Secretariat')
@role_required('Area Director','Secretariat')
def edit_positionREDESIGN(request, name):
"""Vote and edit discuss and comment on Internet Draft as Area Director."""
doc = get_object_or_404(Document, docalias__name=name)
@ -238,7 +238,7 @@ def edit_positionREDESIGN(request, name):
return_to_url = doc.get_absolute_url()
# if we're in the Secretariat, we can select an AD to act as stand-in for
if not has_role(request.user, "Area Director"):
if has_role(request.user, "Secretariat"):
ad_id = request.GET.get('ad')
if not ad_id:
raise Http404()
@ -248,6 +248,10 @@ def edit_positionREDESIGN(request, name):
old_pos = doc.latest_event(BallotPositionDocEvent, type="changed_ballot_position", ad=ad, time__gte=started_process.time)
if request.method == 'POST':
if not has_role(request.user, "Secretariat") and not ad.role_set.filter(name="ad", group__type="area", group__state="active"):
# prevent pre-ADs from voting
return HttpResponseForbidden("Must be a proper Area Director in an active area to cast ballot")
form = EditPositionForm(request.POST)
if form.is_valid():

View file

@ -301,7 +301,9 @@ if settings.USE_DB_REDESIGN_PROXY_CLASSES:
active_ads = list(Person.objects.filter(role__name="ad",
role__group__type="area",
role__group__state="active").distinct())
inactive_ads = list(Person.objects.filter(pk__in=responsible)
inactive_ads = list((Person.objects.filter(pk__in=responsible) | Person.objects.filter(role__name="pre-ad",
role__group__type="area",
role__group__state="active"))
.exclude(pk__in=[x.pk for x in active_ads]))
extract_last_name = lambda x: x.name_parts()[3]
active_ads.sort(key=extract_last_name)
@ -568,10 +570,11 @@ def by_ad(request, name):
ad_name = None
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
responsible = Document.objects.values_list('ad', flat=True).distinct()
for p in Person.objects.filter(Q(role__name="ad",
for p in Person.objects.filter(Q(role__name__in=("pre-ad", "ad"),
role__group__type="area",
role__group__state="active")
| Q(pk__in=responsible)):
| Q(pk__in=responsible)).distinct():
print name, p.full_name_as_key()
if name == p.full_name_as_key():
ad_id = p.id
ad_name = p.plain_name()

View file

@ -436,7 +436,7 @@ def stable_dictsort(value, arg):
def ad_area(user):
if user and user.is_authenticated():
from ietf.group.models import Group
g = Group.objects.filter(role__name="ad", role__person__user=user)
g = Group.objects.filter(role__name__in=("pre-ad", "ad"), role__person__user=user)
if g:
return g[0].acronym
return None

View file

@ -79,7 +79,7 @@ def has_role(user, role_names):
return False
role_qs = {
"Area Director": Q(person=person, name="ad", group__type="area", group__state="active"),
"Area Director": Q(person=person, name__in=("pre-ad", "ad"), group__type="area", group__state="active"),
"Secretariat": Q(person=person, name="secr", group__acronym="secretariat"),
"IANA": Q(person=person, name="auth", group__acronym="iana"),
"WG Chair": Q(person=person,name="chair", group__type="wg", group__state="active"),
@ -97,7 +97,7 @@ def role_required(*role_names):
"""View decorator for checking that the user is logged in and
has one of the listed roles."""
return passes_test_decorator(lambda u: has_role(u, role_names),
"Restricted to role%s %s" % ("s" if len(role_names) != 1 else "", ",".join(role_names)))
"Restricted to role%s %s" % ("s" if len(role_names) != 1 else "", ", ".join(role_names)))
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
# overwrite group_required

View file

@ -58,7 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<p>Area Director{{ forloop.revcounter|pluralize }}:</p>
<table style="margin-left: 2em" class="ietf-wg-table">
{% endif %}
<tr><td><span class="square bgcolor{{forloop.counter}}">&nbsp;</span></td> <td><a href="mailto:{{ ad.address }}">{{ ad.person.plain_name }} &lt;{{ ad.address }}&gt;</a></td></tr>
<tr><td><span class="square bgcolor{{forloop.counter}}">&nbsp;</span></td> <td><a href="mailto:{{ ad.address }}">{{ ad.person.plain_name }} &lt;{{ ad.address }}&gt;</a>{% if ad.incoming %} (Incoming AD){% endif %}</td></tr>
{% if forloop.last %}
</table>
{% endif %}

View file

@ -11,7 +11,7 @@ def is_area_director_for_group(person, group):
return bool(group.area.area.areadirector_set.filter(person=person).count())
def is_area_director_for_groupREDESIGN(person, group):
return bool(Role.objects.filter(group=group.parent, person=person, name="ad"))
return bool(Role.objects.filter(group=group.parent, person=person, name=("ad", "pre-ad")))
def is_group_chair(person, group):

View file

@ -99,7 +99,16 @@ def wg_dirREDESIGN(request):
areas = Group.objects.filter(type="area", state="active").order_by("name")
for area in areas:
area.ads = sorted(Email.objects.filter(role__group=area, role__name="ad").select_related("person"), key=lambda e: e.person.name_parts()[3])
area.ads = []
for e in Email.objects.filter(role__group=area, role__name="ad").select_related("person"):
e.incoming = False
area.ads.append(e)
for e in Email.objects.filter(role__group=area, role__name="pre-ad").select_related("person"):
e.incoming = True
area.ads.append(e)
area.ads.sort(key=lambda e: (e.incoming, e.person.name_parts()[3]))
area.wgs = Group.objects.filter(parent=area, type="wg", state="active").order_by("acronym")
area.urls = area.groupurl_set.all().order_by("name")
for wg in area.wgs:

View file

@ -33,6 +33,7 @@ from ietf.utils.history import *
# SDOAuthorizedIndividual, WGDelegate
area_director_role = name(RoleName, "ad", "Area Director")
pre_area_director_role = name(RoleName, "pre-ad", "Incoming Area Director")
chair_role = name(RoleName, "chair", "Chair")
editor_role = name(RoleName, "editor", "Editor")
secretary_role = name(RoleName, "secr", "Secretary")
@ -237,14 +238,22 @@ for o in AreaDirector.objects.all():
area = Group.objects.get(acronym=o.area.area_acronym.acronym)
r = Role.objects.filter(name=area_director_role,
role_type = area_director_role
try:
if IESGLogin.objects.get(person=o.person).user_level == 4:
role_type = pre_area_director_role
except IESGLogin.DoesNotExist:
pass
r = Role.objects.filter(name=role_type,
person=email.person)
if r and r[0].group == "iesg":
r[0].group = area
r[0].name = area_director_role
r[0].name = role_type
r[0].save()
else:
Role.objects.get_or_create(name=area_director_role, group=area, person=email.person, email=email)
Role.objects.get_or_create(name=role_type, group=area, person=email.person, email=email)
# IESGHistory
emails_for_time = {}