Skip to content

Commit b653e8f

Browse files
committed
Removed the description field from Position. Simplified the Position list and the Position edit form. Tweaked several places to make the pages more self documenting. Added a page to help nomcom chairs through setting up a new nomcom. Fixes ietf-tools#1867 and ietf-tools#1768.
- Legacy-Id: 10565
1 parent f566a83 commit b653e8f

15 files changed

Lines changed: 173 additions & 36 deletions

ietf/nomcom/factories.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ class Meta:
125125
model = Position
126126

127127
name = factory.Faker('sentence',nb_words=10)
128-
description = factory.Faker('paragraph',nb_sentences=4)
129128
is_open = True
130129

131130
class NomineeFactory(factory.DjangoModelFactory):

ietf/nomcom/forms.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
get_user_email, validate_private_key, validate_public_key,
1818
get_or_create_nominee, create_feedback_email)
1919
from ietf.person.models import Email
20-
from ietf.person.fields import SearchableEmailField
2120
from ietf.utils.fields import MultiEmailField
2221
from ietf.utils.mail import send_mail
2322
from ietf.mailtrigger.utils import gather_address_lists
@@ -566,13 +565,11 @@ class NomComTemplateForm(BaseNomcomForm, DBTemplateForm):
566565

567566
class PositionForm(BaseNomcomForm, forms.ModelForm):
568567

569-
fieldsets = [('Position', ('name', 'description', 'is_open' ))]
570-
571-
incumbent = SearchableEmailField(required=False)
568+
fieldsets = [('Position', ('name', 'is_open' ))]
572569

573570
class Meta:
574571
model = Position
575-
fields = ('name', 'description', 'is_open')
572+
fields = ('name', 'is_open')
576573

577574
def __init__(self, *args, **kwargs):
578575
self.nomcom = kwargs.pop('nomcom', None)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals
3+
4+
from django.db import models, migrations
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('nomcom', '0007_feedbacklastseen'),
11+
]
12+
13+
operations = [
14+
migrations.RemoveField(
15+
model_name='position',
16+
name='description',
17+
),
18+
migrations.AlterField(
19+
model_name='position',
20+
name='name',
21+
field=models.CharField(help_text=b'This short description will appear on the Nomination and Feedback pages. Be as descriptive as necessary. Past examples: "Transport AD", "IAB Member"', max_length=255, verbose_name=b'Name'),
22+
preserve_default=True,
23+
),
24+
]

ietf/nomcom/models.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,7 @@ def questionnaires(self):
164164

165165
class Position(models.Model):
166166
nomcom = models.ForeignKey('NomCom')
167-
name = models.CharField(verbose_name='Name', max_length=255)
168-
description = models.TextField(verbose_name='Description')
167+
name = models.CharField(verbose_name='Name', max_length=255, help_text='This short description will appear on the Nomination and Feedback pages. Be as descriptive as necessary. Past examples: "Transport AD", "IAB Member"')
169168
requirement = models.ForeignKey(DBTemplate, related_name='requirement', null=True, editable=False)
170169
questionnaire = models.ForeignKey(DBTemplate, related_name='questionnaire', null=True, editable=False)
171170
is_open = models.BooleanField(verbose_name='Is open', default=False)

ietf/nomcom/resources.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ class Meta:
3737
filtering = {
3838
"id": ALL,
3939
"name": ALL,
40-
"description": ALL,
4140
"is_open": ALL,
4241
"nomcom": ALL_WITH_RELATIONS,
4342
"requirement": ALL_WITH_RELATIONS,

ietf/nomcom/test_data.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,19 @@
2121
EMAIL_DOMAIN = '@example.com'
2222
NOMCOM_YEAR = "2013"
2323

24-
POSITIONS = {
25-
"GEN": "IETF Chair/Gen AD",
26-
"APP": "APP Area Director",
27-
"INT": "INT Area Director",
28-
"OAM": "OPS Area Director",
29-
"OPS": "OPS Area Director",
30-
"RAI": "RAI Area Director",
31-
"RTG": "RTG Area Director",
32-
"SEC": "SEC Area Director",
33-
"TSV": "TSV Area Director",
34-
"IAB": "IAB Member",
35-
"IAOC": "IAOC Member",
36-
}
24+
POSITIONS = [
25+
"GEN",
26+
"APP",
27+
"INT",
28+
"OAM",
29+
"OPS",
30+
"RAI",
31+
"RTG",
32+
"SEC",
33+
"TSV",
34+
"IAB",
35+
"IAOC"
36+
]
3737

3838

3939
def generate_cert():
@@ -127,10 +127,9 @@ def nomcom_test_data():
127127
nominee, _ = Nominee.objects.get_or_create(email=email, nomcom=nomcom)
128128

129129
# positions
130-
for name, description in POSITIONS.iteritems():
130+
for name in POSITIONS:
131131
position, created = Position.objects.get_or_create(nomcom=nomcom,
132132
name=name,
133-
description=description,
134133
is_open=True)
135134

136135
ChangeStateGroupEvent.objects.get_or_create(group=group,

ietf/nomcom/tests.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ def test_list_positions_add(self):
430430
nomcom = get_nomcom_by_year(self.year)
431431
count = nomcom.position_set.all().count()
432432
login_testing_unauthorized(self, CHAIR_USER, self.edit_position_url)
433-
test_data = {"action" : "add", "name": "testpos", "description": "test description"}
433+
test_data = {"action" : "add", "name": "testpos" }
434434
r = self.client.post(self.edit_position_url, test_data)
435435
self.assertEqual(r.status_code, 302)
436436
self.assertEqual(nomcom.position_set.all().count(), count+1)
@@ -1181,3 +1181,15 @@ def test_feedback_nominee_badges(self):
11811181
self.assertEqual(response.status_code,200)
11821182
q = PyQuery(response.content)
11831183
self.assertEqual( len(q('.label-success')), 0 )
1184+
1185+
class NewActiveNomComTests(TestCase):
1186+
1187+
def setUp(self):
1188+
self.nc = NomComFactory.create(**nomcom_kwargs_for_year(group__state_id='conclude'))
1189+
self.chair = self.nc.group.role_set.filter(name='chair').first().person
1190+
1191+
def test_help(self):
1192+
url = reverse('nomcom_chair_help',kwargs={'year':self.nc.year()})
1193+
login_testing_unauthorized(self, self.chair.user.username, url)
1194+
response = self.client.get(url)
1195+
self.assertEqual(response.status_code,200)

ietf/nomcom/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
url(r'^ann/$', 'announcements'),
88
url(r'^(?P<year>\d{4})/private/$', 'private_index', name='nomcom_private_index'),
99
url(r'^(?P<year>\d{4})/private/key/$', 'private_key', name='nomcom_private_key'),
10+
url(r'^(?P<year>\d{4})/private/help/$', 'configuration_help', name='nomcom_chair_help'),
1011
url(r'^(?P<year>\d{4})/private/nominate/$', 'private_nominate', name='nomcom_private_nominate'),
1112
url(r'^(?P<year>\d{4})/private/feedback/$', 'private_feedback', name='nomcom_private_feedback'),
1213
url(r'^(?P<year>\d{4})/private/feedback-email/$', 'private_feedback_email', name='nomcom_private_feedback_email'),

ietf/nomcom/views.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -874,7 +874,7 @@ def edit_template(request, year, template_id):
874874
@role_required("Nomcom Chair", "Nomcom Advisor")
875875
def list_positions(request, year):
876876
nomcom = get_nomcom_by_year(year)
877-
positions = nomcom.position_set.all()
877+
positions = nomcom.position_set.order_by('-is_open')
878878

879879
return render_to_response('nomcom/list_positions.html',
880880
{'positions': positions,
@@ -936,3 +936,7 @@ def edit_position(request, year, position_id=None):
936936
'nomcom': nomcom,
937937
'is_chair_task' : True,
938938
}, RequestContext(request))
939+
940+
@role_required("Nomcom Chair", "Nomcom Advisor")
941+
def configuration_help(request, year):
942+
return render(request,'nomcom/chair_help.html',{'year':year})
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
{% extends "nomcom/nomcom_private_base.html" %}
2+
{# Copyright The IETF Trust 2015, All Rights Reserved #}
3+
{% load origin %}
4+
5+
{% load bootstrap3 %}
6+
{% load ietf_filters %}
7+
8+
{% block bodyAttrs %}data-spy="scroll" data-target="#nav-instructions"{% endblock %}
9+
10+
{% block subtitle %} - Configuration Help {% endblock %}
11+
12+
{% block nomcom_content %}
13+
{% origin %}
14+
15+
{% comment %} Why isn't this part of the base templates? {% endcomment %}
16+
{% bootstrap_messages %}
17+
18+
<div class="col-sm-2 col-sm-offset-10 hidden-xs hidden-print bs-docs-sidebar" id="nav-instructions">
19+
<ul class="nav nav-pills nav-stacked small" data-spy="affix">
20+
<li><a href="#keys">Keypair</a></li>
21+
<li><a href="#configure">Configuration</a></li>
22+
<li><a href="#positions">Positions</a></li>
23+
<li><a href="#templates">Templates</a></li>
24+
</ul>
25+
</div>
26+
27+
<div id="instructions" class="col-sm-10">
28+
<h2>Help for Configuring a New NomCom</h2>
29+
30+
31+
32+
33+
<h3 class="anchor-target" id="keys">Generate a keypair for the nomcom</h3>
34+
35+
<p> The Datatracker uses a public/private keypair to encrypt any feedback entered by the community
36+
before storing it in the database. Only persons with the private key can view this feedback.
37+
The private key is provided by using a datatracker page to store a blowfish-encrypted cookie in a browser session.
38+
The blowfish-encrypted private key is sent to the server and used to decrypt feedback. The private key is never
39+
stored on the server, but if the server is compromised, it would be possible for an attacker to grab the private key
40+
by modifying the datatracker code. The NomCom chair generates the keypair for each NomCom and manages its secure
41+
distribution.
42+
</p>
43+
44+
<p>To generate the keypair:
45+
<ol>
46+
<li>
47+
Create a config file for openssl, named nomcom-config.cnf, with the following contents:
48+
<pre>[ req ]
49+
distinguished_name = req_distinguished_name
50+
string_mask = utf8only
51+
x509_extensions = ss_v3_ca
52+
53+
[ req_distinguished_name ]
54+
commonName = Common Name (e.g. NomComYY)
55+
commonName_default = NomCom{{year|slice:"2:"}}
56+
57+
[ ss_v3_ca ]
58+
59+
subjectKeyIdentifier = hash
60+
keyUsage = critical, digitalSignature, keyEncipherment, dataEncipherment
61+
basicConstraints = critical, CA:true
62+
subjectAltName = email:nomcom{{year|slice:"2:"}}@ietf.org
63+
extendedKeyUsage= emailProtection
64+
</pre></li>
65+
<li>Generate a private key and corresponding certificate:
66+
<pre>openssl req -config nomcom-config.cnf -x509 -new -newkey rsa:2048 -sha256 -days 730 -nodes -keyout privateKey-nomcom{{year|slice:"2:"}}.pem -out nomcom{{year|slice:"2:"}}.cert</pre>
67+
(Just press Enter when presented with "Common Name (e.g. NomComYY) [NomCom15]:")
68+
</li>
69+
</ol>
70+
<p>
71+
You will upload the certificate to the datatracker (and make it available to people wishing to send mail) in the steps below.
72+
</p>
73+
<p>Securely distribute privateKey-nomcom{{year|slice:"2:"}} to your NomCom advisor(s), liaisons, and members, as they become known.</p>
74+
75+
76+
<h3 class="anchor-target" id="configure">Configure the Datatracker NomCom</h3>
77+
78+
<p>Sign into the datatracker and go to the <a href="{% url 'nomcom_edit_nomcom' year %}">NomCom Configuration Page</a>.</p>
79+
<p>Use the Browse button to select the public nomcom{{year|slice:"2:"}}.cert file created above.</p>
80+
<p>Enter any special instructions you want to appear on the nomination entry form in the "Help text for nomination form" box. These will appear on the form immediately below the field labeled "Candidate's qualifications for the position".</p>
81+
<p>Choose whether to have the datatracker send questionnares, and whether to automatically remind people to accept nominations and return questionnaires, according to the instructions on the form.</p>
82+
<p>Press the save button.</p>
83+
<p>You can return to this page and change your mind on any of the settings, even towards the end of your nomcom cycle. However, be wary of uploading a new public key once one feedback has been received. That step should only be taken in the case of a compromised keypair. Old feedback will remain encrypted with the old key, and will not be accessible through the datatracker.</p>
84+
85+
<h3 class="anchor-target" id="positions">Configure the Positions to be filled</h3>
86+
<p>Add the positions this nomcom needs to fill.</p>
87+
<p>Only create one Position for those roles having multiple seats to fill,
88+
such as the IAB, or the IESG areas where multiple ADs in that area are at the end of their term. </p>
89+
90+
<p>Note the "Is open" checkbox. When this is set to True, the Position will appear on the Nomination and Feedback pages. You will set this to False when you do not want any more feedback (that is, the position is filled, or otherwise closed for some reason). It is a good idea to start with the "Is open" value set to False. After you edit the templates for the position and are ready for the community to provide nominations and feedback, set the "Is open" value to True.</p>
91+
<p>You might need to close some positions and open others as your nomcom progresses. For example, the 2014 Nomcom was called back after it had finished work on its usual selections to fill a IAOC position that had been vacated mid-term. Before making the call for nominations and feedback for this additional IAOC position, the chair would mark the already filled positions as not open, leaving only the new IAOC position open for consideration. At that point, only that IAOC position would be available on the Nomination and Feedback pages. </p>
92+
93+
<h3 class="anchor-target" id="templates">Customize the web-form and email templates</h3>
94+
95+
<p>Edit each of the templates at {% url 'nomcom_list_templates' year %}. The "Home page of group" template is where to put information about the current nomcom members and policies. It is also a good place to list incumbents in positions, and information about whether the incumbents will stand again. See the home page of past nomcoms for examples.</p>
96+
97+
<h3 class="anchor-target" id="test">Test the results</h3>
98+
<p> Before advertising that your nomcom pages are ready for the community to use, test your configuration. Create a dummy nominee for at least one position, and give it some feedback. You will be able to move this out of the way later. Once you've marked positions as open, ask your nomcom members to look over the expertise and questionnaires tab (which show rendered view of each of the templates for each position) to ensure they contain what you want the community to see. Please don't assume that everything is all right without looking. It's a good idea to give the secretariat and the tools team a heads up a few (preferably 3 to 5) days notice before announcing that your pages are ready for community use.
99+
</div>
100+
{% endblock %}
101+

0 commit comments

Comments
 (0)