fix: Don't allow ADs to set docs to -sent states (#6445)

This commit is contained in:
Paul Selkirk 2023-10-10 11:09:04 -04:00 committed by GitHub
parent f19d1047c4
commit 72fef7bc69
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 71 additions and 8 deletions

View file

@ -168,6 +168,21 @@ class ConflictReviewTests(TestCase):
self.assertTrue(review_doc.active_ballot())
self.assertEqual(review_doc.latest_event(BallotPositionDocEvent, type="changed_ballot_position").pos_id,'yes')
# try to change to an AD-forbidden state
appr_noprob_sent_pk = str(State.objects.get(used=True, slug='appr-noprob-sent',type__slug='conflrev').pk)
r = self.client.post(url,dict(review_state=appr_noprob_sent_pk,comment='xyzzy'))
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(q('form .invalid-feedback'))
# try again as secretariat
self.client.logout()
login_testing_unauthorized(self, 'secretary', url)
r = self.client.post(url,dict(review_state=appr_noprob_sent_pk,comment='xyzzy'))
self.assertEqual(r.status_code, 302)
review_doc = Document.objects.get(name='conflict-review-imaginary-irtf-submission')
self.assertEqual(review_doc.get_state('conflrev').slug, 'appr-noprob-sent')
def test_edit_notices(self):
doc = Document.objects.get(name='conflict-review-imaginary-irtf-submission')

View file

@ -98,7 +98,7 @@ class ChangeStateTests(TestCase):
draft.action_holders.add(ad)
url = urlreverse('ietf.doc.views_draft.change_state', kwargs=dict(name=draft.name))
login_testing_unauthorized(self, "secretary", url)
login_testing_unauthorized(self, "ad", url)
first_state = draft.get_state("draft-iesg")
next_states = first_state.next_states.all()
@ -154,6 +154,20 @@ class ChangeStateTests(TestCase):
q = PyQuery(r.content)
self.assertEqual(len(q('form [type=submit]:contains("%s")' % first_state.name)), 1)
# try to change to an AD-forbidden state
r = self.client.post(url, dict(state=State.objects.get(used=True, type='draft-iesg', slug='ann').pk, comment='Test comment'))
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(q('form .invalid-feedback'))
# try again as secretariat
self.client.logout()
login_testing_unauthorized(self, 'secretary', url)
r = self.client.post(url, dict(state=State.objects.get(used=True, type='draft-iesg', slug='ann').pk, comment='Test comment'))
self.assertEqual(r.status_code, 302)
draft = Document.objects.get(name=draft.name)
self.assertEqual(draft.get_state_slug('draft-iesg'), 'ann')
def test_pull_from_rfc_queue(self):
ad = Person.objects.get(user__username="ad")
draft = WgDraftFactory(

View file

@ -147,6 +147,21 @@ class StatusChangeTests(TestCase):
self.assertTrue(doc.active_ballot())
self.assertEqual(doc.latest_event(BallotPositionDocEvent, type="changed_ballot_position").pos_id,'yes')
# try to change to an AD-forbidden state
appr_sent_pk = str(State.objects.get(used=True, slug='appr-sent',type__slug='statchg').pk)
r = self.client.post(url, dict(new_state=appr_sent_pk, comment='xyzzy'))
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(q('form .invalid-feedback'))
# try again as secretariat
self.client.logout()
login_testing_unauthorized(self, 'secretary', url)
r = self.client.post(url, dict(new_state=appr_sent_pk, comment='xyzzy'))
self.assertEqual(r.status_code, 302)
doc = Document.objects.get(name='status-change-imaginary-mid-review')
self.assertEqual(doc.get_state('statchg').slug, 'appr-sent')
def test_edit_notices(self):
doc = Document.objects.get(name='status-change-imaginary-mid-review')
url = urlreverse('ietf.doc.views_doc.edit_notify;status-change',kwargs=dict(name=doc.name))

View file

@ -36,6 +36,12 @@ class ChangeStateForm(forms.Form):
review_state = forms.ModelChoiceField(State.objects.filter(used=True, type="conflrev"), label="Conflict review state", empty_label=None, required=True)
comment = forms.CharField(widget=forms.Textarea, help_text="Optional comment for the review history.", required=False, strip=False)
def __init__(self, *args, **kwargs):
user = kwargs.pop("user")
super(ChangeStateForm, self).__init__(*args, **kwargs)
if not has_role(user, "Secretariat"):
self.fields["review_state"].queryset = self.fields["review_state"].queryset.exclude(slug__in=("appr-reqnopub-sent","appr-noprob-sent"))
@role_required("Area Director", "Secretariat")
def change_state(request, name, option=None):
"""Change state of an IESG review for IETF conflicts in other stream's documents, notifying parties as necessary
@ -45,7 +51,7 @@ def change_state(request, name, option=None):
login = request.user.person
if request.method == 'POST':
form = ChangeStateForm(request.POST)
form = ChangeStateForm(request.POST, user=request.user)
if form.is_valid():
clean = form.cleaned_data
new_state = clean['review_state']
@ -100,7 +106,7 @@ def change_state(request, name, option=None):
else:
s = review.get_state()
init = dict(review_state=s.pk if s else None)
form = ChangeStateForm(initial=init)
form = ChangeStateForm(initial=init, user=request.user)
return render(request, 'doc/change_state.html',
dict(form=form,

View file

@ -1,4 +1,4 @@
# Copyright The IETF Trust 2010-2020, All Rights Reserved
# Copyright The IETF Trust 2010-2023, All Rights Reserved
# -*- coding: utf-8 -*-
@ -61,6 +61,12 @@ class ChangeStateForm(forms.Form):
substate = forms.ModelChoiceField(DocTagName.objects.filter(slug__in=IESG_SUBSTATE_TAGS), required=False)
comment = forms.CharField(widget=forms.Textarea, required=False, strip=False)
def __init__(self, *args, **kwargs):
user = kwargs.pop("user")
super(ChangeStateForm, self).__init__(*args, **kwargs)
if not has_role(user, "Secretariat"):
self.fields["state"].queryset = self.fields["state"].queryset.exclude(slug="ann")
def clean(self):
retclean = self.cleaned_data
state = self.cleaned_data.get('state', '(None)')
@ -94,7 +100,7 @@ def change_state(request, name):
login = request.user.person
if request.method == 'POST':
form = ChangeStateForm(request.POST)
form = ChangeStateForm(request.POST, user=request.user)
form.docname=name
if form.is_valid():
@ -175,7 +181,8 @@ def change_state(request, name):
state = doc.get_state("draft-iesg")
t = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
form = ChangeStateForm(initial=dict(state=state.pk if state else None,
substate=t[0].pk if t else None))
substate=t[0].pk if t else None),
user=request.user)
form.docname=name
state = doc.get_state("draft-iesg")

View file

@ -42,6 +42,12 @@ class ChangeStateForm(forms.Form):
new_state = forms.ModelChoiceField(State.objects.filter(type="statchg", used=True), label="Status Change Evaluation State", empty_label=None, required=True)
comment = forms.CharField(widget=forms.Textarea, help_text="Optional comment for the review history.", required=False, strip=False)
def __init__(self, *args, **kwargs):
user = kwargs.pop("user")
super(ChangeStateForm, self).__init__(*args, **kwargs)
if not has_role(user, "Secretariat"):
self.fields["new_state"].queryset = self.fields["new_state"].queryset.exclude(slug="appr-sent")
@role_required("Area Director", "Secretariat")
def change_state(request, name, option=None):
@ -52,7 +58,7 @@ def change_state(request, name, option=None):
login = request.user.person
if request.method == 'POST':
form = ChangeStateForm(request.POST)
form = ChangeStateForm(request.POST, user=request.user)
if form.is_valid():
clean = form.cleaned_data
new_state = clean['new_state']
@ -116,7 +122,7 @@ def change_state(request, name, option=None):
type='statchg',
label='Status Change Evaluation State',
)
form = ChangeStateForm(initial=init)
form = ChangeStateForm(initial=init, user=request.user)
return render(request, 'doc/change_state.html',
dict(form=form,