Skip to content

Commit 72fef7b

Browse files
authored
fix: Don't allow ADs to set docs to -sent states (ietf-tools#6445)
1 parent f19d104 commit 72fef7b

6 files changed

Lines changed: 71 additions & 8 deletions

File tree

ietf/doc/tests_conflict_review.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,21 @@ def test_change_state(self):
168168
self.assertTrue(review_doc.active_ballot())
169169
self.assertEqual(review_doc.latest_event(BallotPositionDocEvent, type="changed_ballot_position").pos_id,'yes')
170170

171+
# try to change to an AD-forbidden state
172+
appr_noprob_sent_pk = str(State.objects.get(used=True, slug='appr-noprob-sent',type__slug='conflrev').pk)
173+
r = self.client.post(url,dict(review_state=appr_noprob_sent_pk,comment='xyzzy'))
174+
self.assertEqual(r.status_code, 200)
175+
q = PyQuery(r.content)
176+
self.assertTrue(q('form .invalid-feedback'))
177+
178+
# try again as secretariat
179+
self.client.logout()
180+
login_testing_unauthorized(self, 'secretary', url)
181+
r = self.client.post(url,dict(review_state=appr_noprob_sent_pk,comment='xyzzy'))
182+
self.assertEqual(r.status_code, 302)
183+
review_doc = Document.objects.get(name='conflict-review-imaginary-irtf-submission')
184+
self.assertEqual(review_doc.get_state('conflrev').slug, 'appr-noprob-sent')
185+
171186

172187
def test_edit_notices(self):
173188
doc = Document.objects.get(name='conflict-review-imaginary-irtf-submission')

ietf/doc/tests_draft.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def test_change_state(self):
9898
draft.action_holders.add(ad)
9999

100100
url = urlreverse('ietf.doc.views_draft.change_state', kwargs=dict(name=draft.name))
101-
login_testing_unauthorized(self, "secretary", url)
101+
login_testing_unauthorized(self, "ad", url)
102102

103103
first_state = draft.get_state("draft-iesg")
104104
next_states = first_state.next_states.all()
@@ -154,6 +154,20 @@ def test_change_state(self):
154154
q = PyQuery(r.content)
155155
self.assertEqual(len(q('form [type=submit]:contains("%s")' % first_state.name)), 1)
156156

157+
# try to change to an AD-forbidden state
158+
r = self.client.post(url, dict(state=State.objects.get(used=True, type='draft-iesg', slug='ann').pk, comment='Test comment'))
159+
self.assertEqual(r.status_code, 200)
160+
q = PyQuery(r.content)
161+
self.assertTrue(q('form .invalid-feedback'))
162+
163+
# try again as secretariat
164+
self.client.logout()
165+
login_testing_unauthorized(self, 'secretary', url)
166+
r = self.client.post(url, dict(state=State.objects.get(used=True, type='draft-iesg', slug='ann').pk, comment='Test comment'))
167+
self.assertEqual(r.status_code, 302)
168+
draft = Document.objects.get(name=draft.name)
169+
self.assertEqual(draft.get_state_slug('draft-iesg'), 'ann')
170+
157171
def test_pull_from_rfc_queue(self):
158172
ad = Person.objects.get(user__username="ad")
159173
draft = WgDraftFactory(

ietf/doc/tests_status_change.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,21 @@ def test_change_state(self):
147147
self.assertTrue(doc.active_ballot())
148148
self.assertEqual(doc.latest_event(BallotPositionDocEvent, type="changed_ballot_position").pos_id,'yes')
149149

150+
# try to change to an AD-forbidden state
151+
appr_sent_pk = str(State.objects.get(used=True, slug='appr-sent',type__slug='statchg').pk)
152+
r = self.client.post(url, dict(new_state=appr_sent_pk, comment='xyzzy'))
153+
self.assertEqual(r.status_code, 200)
154+
q = PyQuery(r.content)
155+
self.assertTrue(q('form .invalid-feedback'))
156+
157+
# try again as secretariat
158+
self.client.logout()
159+
login_testing_unauthorized(self, 'secretary', url)
160+
r = self.client.post(url, dict(new_state=appr_sent_pk, comment='xyzzy'))
161+
self.assertEqual(r.status_code, 302)
162+
doc = Document.objects.get(name='status-change-imaginary-mid-review')
163+
self.assertEqual(doc.get_state('statchg').slug, 'appr-sent')
164+
150165
def test_edit_notices(self):
151166
doc = Document.objects.get(name='status-change-imaginary-mid-review')
152167
url = urlreverse('ietf.doc.views_doc.edit_notify;status-change',kwargs=dict(name=doc.name))

ietf/doc/views_conflict_review.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ class ChangeStateForm(forms.Form):
3636
review_state = forms.ModelChoiceField(State.objects.filter(used=True, type="conflrev"), label="Conflict review state", empty_label=None, required=True)
3737
comment = forms.CharField(widget=forms.Textarea, help_text="Optional comment for the review history.", required=False, strip=False)
3838

39+
def __init__(self, *args, **kwargs):
40+
user = kwargs.pop("user")
41+
super(ChangeStateForm, self).__init__(*args, **kwargs)
42+
if not has_role(user, "Secretariat"):
43+
self.fields["review_state"].queryset = self.fields["review_state"].queryset.exclude(slug__in=("appr-reqnopub-sent","appr-noprob-sent"))
44+
3945
@role_required("Area Director", "Secretariat")
4046
def change_state(request, name, option=None):
4147
"""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):
4551
login = request.user.person
4652

4753
if request.method == 'POST':
48-
form = ChangeStateForm(request.POST)
54+
form = ChangeStateForm(request.POST, user=request.user)
4955
if form.is_valid():
5056
clean = form.cleaned_data
5157
new_state = clean['review_state']
@@ -100,7 +106,7 @@ def change_state(request, name, option=None):
100106
else:
101107
s = review.get_state()
102108
init = dict(review_state=s.pk if s else None)
103-
form = ChangeStateForm(initial=init)
109+
form = ChangeStateForm(initial=init, user=request.user)
104110

105111
return render(request, 'doc/change_state.html',
106112
dict(form=form,

ietf/doc/views_draft.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright The IETF Trust 2010-2020, All Rights Reserved
1+
# Copyright The IETF Trust 2010-2023, All Rights Reserved
22
# -*- coding: utf-8 -*-
33

44

@@ -61,6 +61,12 @@ class ChangeStateForm(forms.Form):
6161
substate = forms.ModelChoiceField(DocTagName.objects.filter(slug__in=IESG_SUBSTATE_TAGS), required=False)
6262
comment = forms.CharField(widget=forms.Textarea, required=False, strip=False)
6363

64+
def __init__(self, *args, **kwargs):
65+
user = kwargs.pop("user")
66+
super(ChangeStateForm, self).__init__(*args, **kwargs)
67+
if not has_role(user, "Secretariat"):
68+
self.fields["state"].queryset = self.fields["state"].queryset.exclude(slug="ann")
69+
6470
def clean(self):
6571
retclean = self.cleaned_data
6672
state = self.cleaned_data.get('state', '(None)')
@@ -94,7 +100,7 @@ def change_state(request, name):
94100
login = request.user.person
95101

96102
if request.method == 'POST':
97-
form = ChangeStateForm(request.POST)
103+
form = ChangeStateForm(request.POST, user=request.user)
98104
form.docname=name
99105

100106
if form.is_valid():
@@ -175,7 +181,8 @@ def change_state(request, name):
175181
state = doc.get_state("draft-iesg")
176182
t = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
177183
form = ChangeStateForm(initial=dict(state=state.pk if state else None,
178-
substate=t[0].pk if t else None))
184+
substate=t[0].pk if t else None),
185+
user=request.user)
179186
form.docname=name
180187

181188
state = doc.get_state("draft-iesg")

ietf/doc/views_status_change.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ class ChangeStateForm(forms.Form):
4242
new_state = forms.ModelChoiceField(State.objects.filter(type="statchg", used=True), label="Status Change Evaluation State", empty_label=None, required=True)
4343
comment = forms.CharField(widget=forms.Textarea, help_text="Optional comment for the review history.", required=False, strip=False)
4444

45+
def __init__(self, *args, **kwargs):
46+
user = kwargs.pop("user")
47+
super(ChangeStateForm, self).__init__(*args, **kwargs)
48+
if not has_role(user, "Secretariat"):
49+
self.fields["new_state"].queryset = self.fields["new_state"].queryset.exclude(slug="appr-sent")
50+
4551

4652
@role_required("Area Director", "Secretariat")
4753
def change_state(request, name, option=None):
@@ -52,7 +58,7 @@ def change_state(request, name, option=None):
5258
login = request.user.person
5359

5460
if request.method == 'POST':
55-
form = ChangeStateForm(request.POST)
61+
form = ChangeStateForm(request.POST, user=request.user)
5662
if form.is_valid():
5763
clean = form.cleaned_data
5864
new_state = clean['new_state']
@@ -116,7 +122,7 @@ def change_state(request, name, option=None):
116122
type='statchg',
117123
label='Status Change Evaluation State',
118124
)
119-
form = ChangeStateForm(initial=init)
125+
form = ChangeStateForm(initial=init, user=request.user)
120126

121127
return render(request, 'doc/change_state.html',
122128
dict(form=form,

0 commit comments

Comments
 (0)