Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 18 additions & 13 deletions ietf/group/forms.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright The IETF Trust 2017-2020, All Rights Reserved
# Copyright The IETF Trust 2017-2023, All Rights Reserved
# -*- coding: utf-8 -*-


Expand Down Expand Up @@ -103,6 +103,8 @@ def __init__(self, *args, **kwargs):
else:
field = None

self.hide_parent = kwargs.pop('hide_parent', False)

super(self.__class__, self).__init__(*args, **kwargs)

if not group_features or group_features.has_chartering_process:
Expand Down Expand Up @@ -138,18 +140,21 @@ def __init__(self, *args, **kwargs):
self.fields['acronym'].widget.attrs['readonly'] = ""

# Sort out parent options
self.fields['parent'].queryset = self.fields['parent'].queryset.filter(type__in=parent_types)
if need_parent:
self.fields['parent'].required = True
self.fields['parent'].empty_label = None
# if this is a new group, fill in the default parent, if any
if self.group is None or (not hasattr(self.group, 'pk')):
self.fields['parent'].initial = self.fields['parent'].queryset.filter(
acronym=default_parent
).first()
# label the parent field as 'IETF Area' if appropriate, for consistency with past behavior
if parent_types.count() == 1 and parent_types.first().pk == 'area':
self.fields['parent'].label = "IETF Area"
if self.hide_parent:
self.fields.pop('parent')
else:
self.fields['parent'].queryset = self.fields['parent'].queryset.filter(type__in=parent_types)
if need_parent:
self.fields['parent'].required = True
self.fields['parent'].empty_label = None
# if this is a new group, fill in the default parent, if any
if self.group is None or (not hasattr(self.group, 'pk')):
self.fields['parent'].initial = self.fields['parent'].queryset.filter(
acronym=default_parent
).first()
# label the parent field as 'IETF Area' if appropriate, for consistency with past behavior
if parent_types.count() == 1 and parent_types.first().pk == 'area':
self.fields['parent'].label = "IETF Area"

if field:
keys = list(self.fields.keys())
Expand Down
82 changes: 80 additions & 2 deletions ietf/group/tests_info.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright The IETF Trust 2009-2022, All Rights Reserved
# Copyright The IETF Trust 2009-2023, All Rights Reserved
# -*- coding: utf-8 -*-


Expand Down Expand Up @@ -946,10 +946,88 @@ def test_edit_description_field(self):
r = self.client.post(url, {
'description': 'Ignored description',
})
self.assertEqual(r.status_code, 302)
self.assertEqual(r.status_code, 403)
group = Group.objects.get(pk=group.pk) # refresh
self.assertEqual(group.description, 'Updated description')

def test_edit_parent(self):
group = GroupFactory.create(type_id='wg', parent=GroupFactory.create(type_id='area'))
chair = RoleFactory(group=group, name_id='chair').person
url = urlreverse('ietf.group.views.edit', kwargs=dict(group_type=group.type_id, acronym=group.acronym, action='edit'))

# parent is not shown to group chair
login_testing_unauthorized(self, chair.user.username, url)
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertEqual(len(q('form select[name=parent]')), 0)

# view ignores attempt to change parent
old_parent = group.parent
new_parent = GroupFactory(type_id='area')
self.assertNotEqual(new_parent.acronym, group.parent.acronym)
r = self.client.post(url, dict(
name=group.name,
acronym=group.acronym,
state=group.state_id,
parent=new_parent.pk))
self.assertEqual(r.status_code, 302)
group = Group.objects.get(pk=group.pk)
self.assertNotEqual(group.parent, new_parent)
self.assertEqual(group.parent, old_parent)

# parent is shown to AD and Secretariat
for priv_user in ('ad', 'secretary'):
self.client.logout()
login_testing_unauthorized(self, priv_user, url)
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertEqual(len(q('form select[name=parent]')), 1)

new_parent = GroupFactory(type_id='area')
self.assertNotEqual(new_parent.acronym, group.parent.acronym)
r = self.client.post(url, dict(
name=group.name,
acronym=group.acronym,
state=group.state_id,
parent=new_parent.pk))
self.assertEqual(r.status_code, 302)
group = Group.objects.get(pk=group.pk)
self.assertEqual(group.parent, new_parent)

def test_edit_parent_field(self):
group = GroupFactory.create(type_id='wg', parent=GroupFactory.create(type_id='area'))
chair = RoleFactory(group=group, name_id='chair').person
url = urlreverse('ietf.group.views.edit', kwargs=dict(group_type=group.type_id, acronym=group.acronym, action='edit', field='parent'))

# parent is not shown to group chair
login_testing_unauthorized(self, chair.user.username, url)
r = self.client.get(url)
self.assertEqual(r.status_code, 403)

# chair is not allowed to change parent
new_parent = GroupFactory(type_id='area')
self.assertNotEqual(new_parent.acronym, group.parent.acronym)
r = self.client.post(url, dict(parent=new_parent.pk))
self.assertEqual(r.status_code, 403)

# parent is shown to AD and Secretariat
for priv_user in ('ad', 'secretary'):
self.client.logout()
login_testing_unauthorized(self, priv_user, url)
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertEqual(len(q('form select[name=parent]')), 1)

new_parent = GroupFactory(type_id='area')
self.assertNotEqual(new_parent.acronym, group.parent.acronym)
r = self.client.post(url, dict(parent=new_parent.pk))
self.assertEqual(r.status_code, 302)
group = Group.objects.get(pk=group.pk)
self.assertEqual(group.parent, new_parent)

def test_conclude(self):
group = GroupFactory(acronym="mars")

Expand Down
11 changes: 8 additions & 3 deletions ietf/group/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -945,14 +945,17 @@ def diff(attr, name):
if not (can_manage_group(request.user, group)
or group.has_role(request.user, group.features.groupman_roles)):
permission_denied(request, "You don't have permission to access this view")
hide_parent = not has_role(request.user, ("Secretariat", "Area Director", "IRTF Chair"))
else:
# This allows ADs to create RG and the IRTF Chair to create WG, but we trust them not to
if not has_role(request.user, ("Secretariat", "Area Director", "IRTF Chair")):
permission_denied(request, "You don't have permission to access this view")
hide_parent = False

if request.method == 'POST':
form = GroupForm(request.POST, group=group, group_type=group_type, field=field)
form = GroupForm(request.POST, group=group, group_type=group_type, field=field, hide_parent=hide_parent)
if field and not form.fields:
permission_denied(request, "You don't have permission to edit this field")
if form.is_valid():
clean = form.cleaned_data
if new_group:
Expand Down Expand Up @@ -1114,7 +1117,9 @@ def diff(attr, name):

else:
init = dict()
form = GroupForm(initial=init, group=group, group_type=group_type, field=field)
form = GroupForm(initial=init, group=group, group_type=group_type, field=field, hide_parent=hide_parent)
if field and not form.fields:
permission_denied(request, "You don't have permission to edit this field")

return render(request, 'group/edit.html',
dict(group=group,
Expand Down
4 changes: 3 additions & 1 deletion ietf/name/fixtures/names.json
Original file line number Diff line number Diff line change
Expand Up @@ -3034,7 +3034,9 @@
"material_types": "[\n \"slides\"\n]",
"matman_roles": "[\n \"chair\"\n]",
"need_parent": false,
"parent_types": [],
"parent_types": [
"rfcedtyp"
],
"req_subm_approval": true,
"role_order": "[\n \"chair\"\n]",
"session_purposes": "[\n \"regular\"\n]",
Expand Down