Add view to edit nomcom
Merge public key edit view whith nomcom edit view Add view to delete nomcom Add hash url to accept o decline nominations Change new nominee template to include hash urls See #976 #977 - Legacy-Id: 5578
This commit is contained in:
parent
d3731ce77e
commit
a9c33ed9f1
|
@ -1,3 +1,5 @@
|
|||
import datetime
|
||||
|
||||
from django.conf import settings
|
||||
from django import forms
|
||||
from django.contrib.formtools.preview import FormPreview, AUTO_ID
|
||||
|
@ -8,6 +10,7 @@ from django.template.loader import render_to_string
|
|||
from django.utils.decorators import method_decorator
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template.context import RequestContext
|
||||
from django.contrib.sites.models import Site
|
||||
|
||||
from ietf.dbtemplate.forms import DBTemplateForm
|
||||
from ietf.utils import unaccent
|
||||
|
@ -22,7 +25,7 @@ from ietf.nomcom.models import NomCom, Nomination, Nominee, NomineePosition, \
|
|||
from ietf.nomcom.utils import QUESTIONNAIRE_TEMPLATE, NOMINATION_EMAIL_TEMPLATE, \
|
||||
INEXISTENT_PERSON_TEMPLATE, NOMINEE_EMAIL_TEMPLATE, \
|
||||
NOMINATION_RECEIPT_TEMPLATE, FEEDBACK_RECEIPT_TEMPLATE, \
|
||||
get_user_email
|
||||
get_user_email, get_hash_nominee_position, get_year_by_nomcom
|
||||
from ietf.nomcom.decorators import member_required
|
||||
|
||||
ROLODEX_URL = getattr(settings, 'ROLODEX_URL', None)
|
||||
|
@ -190,17 +193,13 @@ class EditChairFormPreview(FormPreview):
|
|||
return HttpResponseRedirect(reverse('nomcom_edit_chair', kwargs={'year': self.year}))
|
||||
|
||||
|
||||
class EditPublicKeyForm(BaseNomcomForm, forms.ModelForm):
|
||||
class EditNomcomForm(BaseNomcomForm, forms.ModelForm):
|
||||
|
||||
fieldsets = [('Public Key', ('public_key',))]
|
||||
fieldsets = [('Edit nomcom', ('public_key', 'send_questionnaire'))]
|
||||
|
||||
class Meta:
|
||||
model = NomCom
|
||||
fields = ('public_key',)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(EditPublicKeyForm, self).__init__(*args, **kwargs)
|
||||
self.fields['public_key'].required = True
|
||||
fields = ('public_key', 'send_questionnaire')
|
||||
|
||||
|
||||
class MergeForm(BaseNomcomForm, forms.Form):
|
||||
|
@ -393,8 +392,30 @@ class NominateForm(BaseNomcomForm, forms.ModelForm):
|
|||
subject = 'IETF Nomination Information'
|
||||
from_email = settings.NOMCOM_FROM_EMAIL
|
||||
to_email = email.address
|
||||
domain = Site.objects.get_current().domain
|
||||
today = datetime.date.today().strftime('%Y%m%d')
|
||||
hash = get_hash_nominee_position(today, nominee_position.id)
|
||||
accept_url = reverse('nomcom_process_nomination_status',
|
||||
None,
|
||||
args=(get_year_by_nomcom(self.nomcom),
|
||||
nominee_position.id,
|
||||
'accepted',
|
||||
today,
|
||||
hash))
|
||||
decline_url = reverse('nomcom_process_nomination_status',
|
||||
None,
|
||||
args=(get_year_by_nomcom(self.nomcom),
|
||||
nominee_position.id,
|
||||
'declined',
|
||||
today,
|
||||
hash))
|
||||
|
||||
context = {'nominee': email.person.name,
|
||||
'position': position.name}
|
||||
'position': position.name,
|
||||
'domain': domain,
|
||||
'accept_url': accept_url,
|
||||
'decline_url': decline_url}
|
||||
|
||||
path = nomcom_template_path + NOMINEE_EMAIL_TEMPLATE
|
||||
send_mail(None, to_email, from_email, subject, path, context)
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django.conf.urls.defaults import patterns, url
|
||||
from django.views.generic.simple import direct_to_template
|
||||
from ietf.nomcom.forms import EditChairForm, EditChairFormPreview, \
|
||||
EditMembersForm, EditMembersFormPreview
|
||||
|
||||
|
@ -14,7 +15,9 @@ urlpatterns = patterns('ietf.nomcom.views',
|
|||
url(r'^(?P<year>\d{4})/private/send-reminder-mail/$', 'send_reminder_mail', name='nomcom_send_reminder_mail'),
|
||||
url(r'^(?P<year>\d{4})/private/edit-members/$', EditMembersFormPreview(EditMembersForm), name='nomcom_edit_members'),
|
||||
url(r'^(?P<year>\d{4})/private/edit-chair/$', EditChairFormPreview(EditChairForm), name='nomcom_edit_chair'),
|
||||
url(r'^(?P<year>\d{4})/private/edit-publickey/$', 'edit_publickey', name='nomcom_edit_publickey'),
|
||||
url(r'^(?P<year>\d{4})/private/edit-nomcom/$', 'edit_nomcom', name='nomcom_edit_nomcom'),
|
||||
url(r'^(?P<year>\d{4})/private/delete-nomcom/$', 'delete_nomcom', name='nomcom_delete_nomcom'),
|
||||
url(r'^deleted/$', direct_to_template, {'template': 'nomcom/deleted.html'}, name='nomcom_deleted'),
|
||||
url(r'^(?P<year>\d{4})/private/chair/templates/$', 'list_templates', name='nomcom_list_templates'),
|
||||
url(r'^(?P<year>\d{4})/private/chair/templates/(?P<template_id>\d+)/$', 'edit_template', name='nomcom_edit_template'),
|
||||
url(r'^(?P<year>\d{4})/private/chair/position/$', 'list_positions', name='nomcom_list_positions'),
|
||||
|
@ -27,6 +30,7 @@ urlpatterns = patterns('ietf.nomcom.views',
|
|||
url(r'^(?P<year>\d{4})/questionnaires/$', 'questionnaires', name='nomcom_questionnaires'),
|
||||
url(r'^(?P<year>\d{4})/feedback/$', 'public_feedback', name='nomcom_public_feedback'),
|
||||
url(r'^(?P<year>\d{4})/nominate/$', 'public_nominate', name='nomcom_public_nominate'),
|
||||
url(r'^(?P<year>\d{4})/process-nomination-status/(?P<nominee_position_id>\d+)/(?P<state>[\w]+)/(?P<date>[\d]+)/(?P<hash>[a-f0-9]+)/$', 'process_nomination_status', name='nomcom_process_nomination_status'),
|
||||
url(r'^ajax/position-text/(?P<position_id>\d+)/$', 'ajax_position_text', name='nomcom_ajax_position_text'),
|
||||
|
||||
)
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import hashlib
|
||||
import re
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
@ -34,6 +37,12 @@ def get_nomcom_by_year(year):
|
|||
group__state__slug='active')
|
||||
|
||||
|
||||
def get_year_by_nomcom(nomcom):
|
||||
acronym = nomcom.group.acronym
|
||||
m = re.search('(?P<year>\d\d\d\d)', acronym)
|
||||
return m.group(0)
|
||||
|
||||
|
||||
def get_user_email(user):
|
||||
emails = Email.objects.filter(person__user=user)
|
||||
email = emails and emails[0] or None
|
||||
|
@ -52,6 +61,10 @@ def is_nomcom_chair(user, nomcom):
|
|||
raise PermissionDenied("Must be nomcom chair")
|
||||
|
||||
|
||||
def get_hash_nominee_position(date, nominee_position_id):
|
||||
return hashlib.md5('%s%s%s' % (settings.SECRET_KEY, date, nominee_position_id)).hexdigest()
|
||||
|
||||
|
||||
def initialize_templates_for_group(group):
|
||||
for template_name in DEFAULT_NOMCOM_TEMPLATES:
|
||||
template_path = MAIN_NOMCOM_TEMPLATE_PATH + template_name
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
|
||||
from django.views.generic.create_update import delete_object
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponse, Http404, HttpResponseRedirect
|
||||
from django.http import HttpResponse, Http404, HttpResponseRedirect, HttpResponseForbidden
|
||||
from django.shortcuts import render_to_response, get_object_or_404
|
||||
from django.template import RequestContext
|
||||
from django.template.loader import render_to_string
|
||||
|
@ -17,12 +20,14 @@ from ietf.dbtemplate.views import template_edit
|
|||
from ietf.name.models import NomineePositionState, FeedbackType
|
||||
|
||||
from ietf.nomcom.decorators import member_required, private_key_required
|
||||
from ietf.nomcom.forms import (EditPublicKeyForm, NominateForm, FeedbackForm, MergeForm,
|
||||
NomComTemplateForm, PositionForm, PrivateKeyForm)
|
||||
from ietf.nomcom.models import Position, NomineePosition, Nominee, Feedback
|
||||
from ietf.nomcom.forms import (NominateForm, FeedbackForm, MergeForm,
|
||||
NomComTemplateForm, PositionForm, PrivateKeyForm,
|
||||
EditNomcomForm)
|
||||
from ietf.nomcom.models import Position, NomineePosition, Nominee, Feedback, NomCom
|
||||
from ietf.nomcom.utils import (get_nomcom_by_year, HOME_TEMPLATE,
|
||||
retrieve_nomcom_private_key,
|
||||
store_nomcom_private_key, NOMINEE_REMINDER_TEMPLATE)
|
||||
store_nomcom_private_key, get_hash_nominee_position,
|
||||
NOMINEE_REMINDER_TEMPLATE)
|
||||
|
||||
|
||||
def index(request, year):
|
||||
|
@ -71,13 +76,13 @@ def private_index(request, year):
|
|||
nominations = all_nominee_positions.filter(id__in=nominations_to_modify)
|
||||
if action == "set_as_accepted":
|
||||
nominations.update(state='accepted')
|
||||
message = ('success', 'The selected nominations has been set as accepted')
|
||||
message = ('success', 'The selected nominations have been set as accepted')
|
||||
elif action == "set_as_declined":
|
||||
nominations.update(state='declined')
|
||||
message = ('success', 'The selected nominations has been set as declined')
|
||||
message = ('success', 'The selected nominations have been set as declined')
|
||||
elif action == "set_as_pending":
|
||||
nominations.update(state='pending')
|
||||
message = ('success', 'The selected nominations has been set as pending')
|
||||
message = ('success', 'The selected nominations have been set as pending')
|
||||
else:
|
||||
message = ('warning', "Please, select some nominations to work with")
|
||||
|
||||
|
@ -164,7 +169,7 @@ def private_merge(request, year):
|
|||
form = MergeForm(request.POST, nomcom=nomcom)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
message = ('success', 'The emails has been unified')
|
||||
message = ('success', 'The emails have been unified')
|
||||
else:
|
||||
form = MergeForm(nomcom=nomcom)
|
||||
|
||||
|
@ -251,6 +256,42 @@ def private_feedback(request, year):
|
|||
return feedback(request, year, False)
|
||||
|
||||
|
||||
def process_nomination_status(request, year, nominee_position_id, state, date, hash):
|
||||
valid = get_hash_nominee_position(date, nominee_position_id) == hash
|
||||
if not valid:
|
||||
return HttpResponseForbidden("Bad hash!")
|
||||
expiration_days = getattr(settings, 'DAYS_TO_EXPIRE_NOMINATION_LINK', None)
|
||||
if expiration_days:
|
||||
request_date = datetime.date(int(date[:4]), int(date[4:6]), int(date[6:]))
|
||||
if datetime.date.today() > (request_date + datetime.timedelta(days=settings.DAYS_TO_EXPIRE_REGISTRATION_LINK)):
|
||||
return HttpResponseForbidden("Link expired")
|
||||
|
||||
need_confirmation = True
|
||||
nomcom = get_nomcom_by_year(year)
|
||||
nominee_position = get_object_or_404(NomineePosition, id=nominee_position_id)
|
||||
if nominee_position.state.slug != "pending":
|
||||
return HttpResponseForbidden("The nomination already was %s" % nominee_position.state)
|
||||
|
||||
state = get_object_or_404(NomineePositionState, slug=state)
|
||||
message = ('warning', "Are you sure to change the nomination on %s as %s?" % (nominee_position.position.name,
|
||||
state.name))
|
||||
if request.method == 'POST':
|
||||
nominee_position.state = state
|
||||
nominee_position.save()
|
||||
need_confirmation = False
|
||||
message = message = ('success', 'Your nomination on %s has been set as %s' % (nominee_position.position.name,
|
||||
state.name))
|
||||
|
||||
return render_to_response('nomcom/process_nomination_status.html',
|
||||
{'message': message,
|
||||
'nomcom': nomcom,
|
||||
'year': year,
|
||||
'nominee_position': nominee_position,
|
||||
'state': state,
|
||||
'need_confirmation': need_confirmation,
|
||||
'selected': 'feedback'}, RequestContext(request))
|
||||
|
||||
|
||||
def feedback(request, year, public):
|
||||
nomcom = get_nomcom_by_year(year)
|
||||
has_publickey = nomcom.public_key and True or False
|
||||
|
@ -358,27 +399,42 @@ def view_feedback_nominee(request, year, nominee_id):
|
|||
|
||||
|
||||
@member_required(role='chair')
|
||||
def edit_publickey(request, year):
|
||||
def edit_nomcom(request, year):
|
||||
nomcom = get_nomcom_by_year(year)
|
||||
|
||||
message = ('warning', 'Previous data will remain encrypted with the old key')
|
||||
if request.method == 'POST':
|
||||
form = EditPublicKeyForm(request.POST,
|
||||
request.FILES,
|
||||
instance=nomcom,
|
||||
initial={'public_key': None})
|
||||
form = EditNomcomForm(request.POST,
|
||||
request.FILES,
|
||||
instance=nomcom)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
message = ('success', 'The public key has been changed')
|
||||
message = ('success', 'The nomcom has been changed')
|
||||
else:
|
||||
form = EditPublicKeyForm()
|
||||
form = EditNomcomForm(instance=nomcom)
|
||||
|
||||
return render_to_response('nomcom/edit_publickey.html',
|
||||
return render_to_response('nomcom/edit_nomcom.html',
|
||||
{'form': form,
|
||||
'group': nomcom.group,
|
||||
'nomcom': nomcom,
|
||||
'message': message,
|
||||
'year': year,
|
||||
'selected': 'edit_publickey'}, RequestContext(request))
|
||||
'selected': 'edit_nomcom'}, RequestContext(request))
|
||||
|
||||
|
||||
@member_required(role='chair')
|
||||
def delete_nomcom(request, year):
|
||||
nomcom = get_nomcom_by_year(year)
|
||||
post_delete_redirect = reverse('nomcom_deleted')
|
||||
extra_context = {'year': year,
|
||||
'selected': 'edit_nomcom',
|
||||
'nomcom': nomcom}
|
||||
|
||||
return delete_object(request,
|
||||
model=NomCom,
|
||||
object_id=nomcom.id,
|
||||
post_delete_redirect=post_delete_redirect,
|
||||
template_name='nomcom/delete_nomcom.html',
|
||||
extra_context=extra_context)
|
||||
|
||||
|
||||
@member_required(role='chair')
|
||||
|
|
15
ietf/templates/nomcom/delete_nomcom.html
Normal file
15
ietf/templates/nomcom/delete_nomcom.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
{% extends "nomcom/nomcom_private_base.html" %}
|
||||
|
||||
{% block subtitle %}- Delete Nomcom{% endblock %}
|
||||
|
||||
{% block nomcom_content %}
|
||||
|
||||
<p>Are you sure you want to delete all data about {{ nomcom.group.name }}?</p>
|
||||
<form action="" method="post">{% csrf_token %}
|
||||
<div>
|
||||
<input type="hidden" name="post" value="yes" />
|
||||
<input type="submit" value="Yes, I'm sure" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
7
ietf/templates/nomcom/deleted.html
Normal file
7
ietf/templates/nomcom/deleted.html
Normal file
|
@ -0,0 +1,7 @@
|
|||
{% extends "nomcom/nomcom_base.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="info-message-success">All data about the nomcom has been removed</div>
|
||||
|
||||
{% endblock %}
|
|
@ -1,9 +1,9 @@
|
|||
{% extends "nomcom/nomcom_private_base.html" %}
|
||||
|
||||
{% block subtitle %}- Edit public key{% endblock %}
|
||||
{% block subtitle %}- Edit Nomcom{% endblock %}
|
||||
|
||||
{% block nomcom_content %}
|
||||
<h2>Edit public key</h2>
|
||||
<h2>Edit Nomcom</h2>
|
||||
|
||||
{% if message %}
|
||||
<div class="info-message-{{ message.0 }}">{{ message.1 }}</div>
|
||||
|
@ -18,4 +18,8 @@
|
|||
<p><input type="submit" value="Save" /></p>
|
||||
</form>
|
||||
|
||||
<h2>Delete Nomcom</h2>
|
||||
|
||||
<p>To delete all data about {{ nomcom.group.name }}, <a href="{% url nomcom_delete_nomcom year %}" class="deletelink">click here</a></p>
|
||||
|
||||
{% endblock %}
|
|
@ -16,7 +16,7 @@
|
|||
{% if selected == "merge" %}<span class="selected">Merge nominee email addr</span>{% else %}<a href="{% url nomcom_private_merge year %}">Merge nominee email addr</a>{% endif %} |
|
||||
{% if selected == "send_reminder_mail" %}<span class="selected">Send Reminder Mail</span>{% else %}<a href="{% url nomcom_send_reminder_mail year %}">Send reminder mail</a>{% endif %} |
|
||||
{% if selected == "edit_members" %}<span class="selected">Nomcom members</span>{% else %}<a href="{% url nomcom_edit_members year %}">Nomcom members</a>{% endif %} |
|
||||
{% if selected == "edit_publickey" %}<span class="selected">Public key</span>{% else %}<a href="{% url nomcom_edit_publickey year %}">Public key</a>{% endif %} |
|
||||
{% if selected == "edit_nomcom" %}<span class="selected">Edit Nomcom</span>{% else %}<a href="{% url nomcom_edit_nomcom year %}">Edit Nomcom</a>{% endif %} |
|
||||
{% if selected == "edit_templates" %}<span class="selected">Templates</span>{% else %}<a href="{% url nomcom_list_templates year %}">Templates</a>{% endif %} |
|
||||
{% if selected == "edit_positions" %}<span class="selected">Positions</span>{% else %}<a href="{% url nomcom_list_positions year %}">Positions</a>{% endif %}
|
||||
{% endif %}
|
||||
|
|
22
ietf/templates/nomcom/process_nomination_status.html
Normal file
22
ietf/templates/nomcom/process_nomination_status.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
{% extends "nomcom/nomcom_public_base.html" %}
|
||||
|
||||
{% block subtitle %} - Change Nomination {% endblock %}
|
||||
|
||||
{% block nomcom_content %}
|
||||
|
||||
{% if message %}
|
||||
<div class="info-message-{{ message.0 }}">{{ message.1 }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% if need_confirmation %}
|
||||
<form action="" method="post">{% csrf_token %}
|
||||
{{ form }}
|
||||
|
||||
<div class="submitrow">
|
||||
<input type="submit" value="Save" name="save"/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
Loading…
Reference in a new issue