Merged in [17234] from rjsparks@nostrum.com:

Restrict the ability to change whether a group uses milestone dates to the ADs and the secretariat. Fixes #2869.
 - Legacy-Id: 17236
Note: SVN reference [17234] has been migrated to Git commit b4ac9f83f1
This commit is contained in:
Henrik Levkowetz 2020-01-16 22:57:09 +00:00
commit 68174ba501
4 changed files with 53 additions and 24 deletions

View file

@ -6,6 +6,7 @@ import calendar
from django import forms from django import forms
from django.contrib import messages from django.contrib import messages
from django.core.exceptions import PermissionDenied
from django.http import HttpResponseForbidden, HttpResponseBadRequest, HttpResponseRedirect, Http404 from django.http import HttpResponseForbidden, HttpResponseBadRequest, HttpResponseRedirect, Http404
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
@ -107,8 +108,10 @@ def edit_milestones(request, acronym, group_type=None, milestone_set="current"):
needs_review = False needs_review = False
if can_manage_group(request.user, group): if can_manage_group(request.user, group):
can_change_uses_milestone_dates = True
if not can_manage_group_type(request.user, group): if not can_manage_group_type(request.user, group):
# The user is chair or similar, not AD: # The user is chair or similar, not AD:
can_change_uses_milestone_dates = False
if milestone_set == "current": if milestone_set == "current":
needs_review = True needs_review = True
else: else:
@ -299,17 +302,20 @@ def edit_milestones(request, acronym, group_type=None, milestone_set="current"):
action = request.POST.get("action", "review") action = request.POST.get("action", "review")
if action == "switch": if action == "switch":
if group.uses_milestone_dates: if can_change_uses_milestone_dates:
group.uses_milestone_dates=False if group.uses_milestone_dates:
group.save() group.uses_milestone_dates=False
for order, milestone in enumerate(group.groupmilestone_set.filter(state_id='active').order_by('due','id')): group.save()
milestone.order = order for order, milestone in enumerate(group.groupmilestone_set.filter(state_id='active').order_by('due','id')):
milestone.save() milestone.order = order
milestone.save()
else:
group.uses_milestone_dates=True
group.save()
for m in milestones:
forms.append(MilestoneForm(needs_review, reviewer, instance=m, uses_dates=group.uses_milestone_dates))
else: else:
group.uses_milestone_dates=True raise PermissionDenied
group.save()
for m in milestones:
forms.append(MilestoneForm(needs_review, reviewer, instance=m, uses_dates=group.uses_milestone_dates))
else: else:
# parse out individual milestone forms # parse out individual milestone forms
for prefix in request.POST.getlist("prefix"): for prefix in request.POST.getlist("prefix"):
@ -383,7 +389,8 @@ def edit_milestones(request, acronym, group_type=None, milestone_set="current"):
milestone_set=milestone_set, milestone_set=milestone_set,
needs_review=needs_review, needs_review=needs_review,
reviewer=reviewer, reviewer=reviewer,
can_reset=can_reset)) can_reset=can_reset,
can_change_uses_milestone_dates=can_change_uses_milestone_dates))
@login_required @login_required
def reset_charter_milestones(request, group_type, acronym): def reset_charter_milestones(request, group_type, acronym):

View file

@ -1063,7 +1063,9 @@ class MilestoneTests(TestCase):
class DatelessMilestoneTests(TestCase): class DatelessMilestoneTests(TestCase):
def test_switch_to_dateless(self): def test_switch_to_dateless(self):
ms = DatedGroupMilestoneFactory() ad_role = RoleFactory(group__type_id='area',name_id='ad')
ms = DatedGroupMilestoneFactory(group__parent=ad_role.group)
ad = ad_role.person
chair = RoleFactory(group=ms.group,name_id='chair').person chair = RoleFactory(group=ms.group,name_id='chair').person
url = urlreverse('ietf.group.milestones.edit_milestones;current', kwargs=dict(acronym=ms.group.acronym)) url = urlreverse('ietf.group.milestones.edit_milestones;current', kwargs=dict(acronym=ms.group.acronym))
@ -1072,6 +1074,18 @@ class DatelessMilestoneTests(TestCase):
r = self.client.get(url) r = self.client.get(url)
self.assertEqual(r.status_code, 200) self.assertEqual(r.status_code, 200)
q = PyQuery(r.content) q = PyQuery(r.content)
self.assertEqual(len(q('#switch-date-use-form')),0)
r = self.client.post(url, dict(action="switch"))
self.assertEqual(r.status_code, 403)
self.client.logout()
self.client.login(username=ad.user.username, password='%s+password' % ad.user.username)
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertEqual(len(q('#switch-date-use-form')),1)
self.assertEqual(len(q('#uses_milestone_dates')),1) self.assertEqual(len(q('#uses_milestone_dates')),1)
r = self.client.post(url, dict(action="switch")) r = self.client.post(url, dict(action="switch"))
@ -1085,11 +1099,12 @@ class DatelessMilestoneTests(TestCase):
self.assertEqual(len(q('#uses_milestone_dates')),0) self.assertEqual(len(q('#uses_milestone_dates')),0)
def test_switch_to_dated(self): def test_switch_to_dated(self):
ms = DatelessGroupMilestoneFactory() ad_role = RoleFactory(group__type_id='area',name_id='ad')
chair = RoleFactory(group=ms.group,name_id='chair').person ms = DatelessGroupMilestoneFactory(group__parent=ad_role.group)
ad = ad_role.person
url = urlreverse('ietf.group.milestones.edit_milestones;current', kwargs=dict(acronym=ms.group.acronym)) url = urlreverse('ietf.group.milestones.edit_milestones;current', kwargs=dict(acronym=ms.group.acronym))
login_testing_unauthorized(self, chair.user.username, url) login_testing_unauthorized(self, ad.user.username, url)
r = self.client.get(url) r = self.client.get(url)
self.assertEqual(r.status_code, 200) self.assertEqual(r.status_code, 200)

View file

@ -3,6 +3,7 @@ $(document).ready(function () {
var milestonesForm = $('#milestones-form'); var milestonesForm = $('#milestones-form');
var group_uses_milestone_dates = ( $('#uses_milestone_dates').length > 0 ); var group_uses_milestone_dates = ( $('#uses_milestone_dates').length > 0 );
var milestone_order_has_changed = false; var milestone_order_has_changed = false;
var switch_date_use_form = $("#switch-date-use-form")
// make sure we got the lowest number for idCounter // make sure we got the lowest number for idCounter
milestonesForm.find('.edit-milestone input[name$="-id"]').each(function () { milestonesForm.find('.edit-milestone input[name$="-id"]').each(function () {
@ -14,7 +15,9 @@ $(document).ready(function () {
function setChanged() { function setChanged() {
$(this).closest(".edit-milestone").addClass("changed"); $(this).closest(".edit-milestone").addClass("changed");
setSubmitButtonState(); setSubmitButtonState();
$("#switch-date-use-form").hide(); if (switch_date_use_form) {
switch_date_use_form.hide();
}
} }
milestonesForm.on("change", '.edit-milestone select,.edit-milestone input,.edit-milestone textarea', setChanged); milestonesForm.on("change", '.edit-milestone select,.edit-milestone input,.edit-milestone textarea', setChanged);
@ -166,7 +169,9 @@ $(document).ready(function () {
milestone_order_has_changed = true; milestone_order_has_changed = true;
setSubmitButtonState(); setSubmitButtonState();
setOrderControlValue(); setOrderControlValue();
$("#switch-date-use-form").hide(); if (switch_date_use_form) {
switch_date_use_form.hide();
}
} }

View file

@ -26,13 +26,15 @@
</p> </p>
<div class="container-fluid"> <div class="container-fluid">
<div class="col-sm-12"> {% if can_change_uses_milestone_dates %}
<form method="post" id="switch-date-use-form">{% csrf_token %} <div class="col-sm-12">
<button class="btn btn-default" type="submit" name="action" value="switch"{% if milestone_set == 'charter' %} style="display:none;"{% endif %}> <form method="post" id="switch-date-use-form">{% csrf_token %}
{% if group.uses_milestone_dates %}Stop{% else %}Start{% endif %} using milestone dates <button class="btn btn-default" type="submit" name="action" value="switch"{% if milestone_set == 'charter' %} style="display:none;"{% endif %}>
</button> {% if group.uses_milestone_dates %}Stop{% else %}Start{% endif %} using milestone dates
</form> </button>
</div> </form>
</div>
{% endif %}
<div class="col-sm-12"> <div class="col-sm-12">