The secretariat and the Team Chair can now edit team groups. In addition, if the team in within the IETF, Area Directors can edit it. And, if the team is within the IRTF, the IRTF Chair can edit it. Fixes #1915.
- Legacy-Id: 11064
This commit is contained in:
parent
9f90441aa6
commit
1c509cd64c
|
@ -16,7 +16,7 @@ from ietf.doc.utils import get_tags_for_stream_id
|
|||
from ietf.doc.utils_charter import charter_name_for_group
|
||||
from ietf.group.models import ( Group, Role, GroupEvent, GroupHistory, GroupStateName,
|
||||
GroupStateTransitions, GroupTypeName, GroupURL, ChangeStateGroupEvent )
|
||||
from ietf.group.utils import save_group_in_history, can_manage_group_type
|
||||
from ietf.group.utils import save_group_in_history, can_manage_group_type, can_manage_team_group
|
||||
from ietf.group.utils import get_group_or_404
|
||||
from ietf.ietfauth.utils import has_role
|
||||
from ietf.person.fields import SearchableEmailsField
|
||||
|
@ -199,11 +199,19 @@ def submit_initial_charter(request, group_type=None, acronym=None):
|
|||
def edit(request, group_type=None, acronym=None, action="edit"):
|
||||
"""Edit or create a group, notifying parties as
|
||||
necessary and logging changes as group events."""
|
||||
if not can_manage_group_type(request.user, group_type):
|
||||
group = get_group_or_404(acronym, group_type)
|
||||
if not group_type and group:
|
||||
group_type = group.type_id
|
||||
|
||||
if group_type == "team":
|
||||
can_edit = can_manage_team_group(request.user, group) or group.has_role(request.user, "chair")
|
||||
else:
|
||||
can_edit = can_manage_group_type(request.user, group_type)
|
||||
|
||||
if not can_edit:
|
||||
return HttpResponseForbidden("You don't have permission to access this view")
|
||||
|
||||
if action == "edit":
|
||||
group = get_object_or_404(Group, acronym=acronym)
|
||||
new_group = False
|
||||
elif action in ("create","charter"):
|
||||
group = None
|
||||
|
@ -211,9 +219,6 @@ def edit(request, group_type=None, acronym=None, action="edit"):
|
|||
else:
|
||||
raise Http404
|
||||
|
||||
if not group_type and group:
|
||||
group_type = group.type_id
|
||||
|
||||
if request.method == 'POST':
|
||||
form = GroupForm(request.POST, group=group, group_type=group_type)
|
||||
if form.is_valid():
|
||||
|
|
|
@ -55,7 +55,7 @@ from ietf.doc.utils import get_chartering_type
|
|||
from ietf.doc.templatetags.ietf_filters import clean_whitespace
|
||||
from ietf.group.models import Group, Role, ChangeStateGroupEvent
|
||||
from ietf.name.models import GroupTypeName
|
||||
from ietf.group.utils import get_charter_text, can_manage_group_type, milestone_reviewer_for_group_type, can_provide_status_update
|
||||
from ietf.group.utils import get_charter_text, can_manage_group_type, can_manage_team_group, milestone_reviewer_for_group_type, can_provide_status_update
|
||||
from ietf.group.utils import can_manage_materials, get_group_or_404
|
||||
from ietf.utils.pipe import pipe
|
||||
from ietf.utils.textupload import get_cleaned_text_file_content
|
||||
|
@ -366,6 +366,8 @@ def construct_group_menu_context(request, group, selected, group_type, others):
|
|||
|
||||
is_chair = group.has_role(request.user, "chair")
|
||||
can_manage = can_manage_group_type(request.user, group.type_id)
|
||||
if group.type_id == "team":
|
||||
can_manage = can_manage_team_group(request.user, group)
|
||||
|
||||
if group.features.has_milestones:
|
||||
if group.state_id != "proposed" and (is_chair or can_manage):
|
||||
|
@ -374,7 +376,7 @@ def construct_group_menu_context(request, group, selected, group_type, others):
|
|||
if group.features.has_materials and can_manage_materials(request.user, group):
|
||||
actions.append((u"Upload material", urlreverse("ietf.doc.views_material.choose_material_type", kwargs=kwargs)))
|
||||
|
||||
if group.type_id in ("rg", "wg") and group.state_id != "conclude" and can_manage:
|
||||
if group.state_id != "conclude" and (is_chair or can_manage):
|
||||
actions.append((u"Edit group", urlreverse("group_edit", kwargs=kwargs)))
|
||||
|
||||
if group.features.customize_workflow and (is_chair or can_manage):
|
||||
|
|
|
@ -80,6 +80,14 @@ class Group(GroupInfo):
|
|||
role_names = [role_names]
|
||||
return user.is_authenticated() and self.role_set.filter(name__in=role_names, person__user=user).exists()
|
||||
|
||||
def is_decendant_of(self, sought_parent):
|
||||
p = self.parent
|
||||
while (p != None):
|
||||
if p.acronym == sought_parent:
|
||||
return True
|
||||
p = p.parent
|
||||
return False
|
||||
|
||||
def is_bof(self):
|
||||
return (self.state.slug in ["bof", "bof-conc"])
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ from ietf.name.models import DocTagName, GroupStateName, GroupTypeName
|
|||
from ietf.person.models import Person, Email
|
||||
from ietf.utils.test_utils import TestCase, unicontent
|
||||
from ietf.utils.mail import outbox, empty_outbox
|
||||
from ietf.utils.test_data import make_test_data
|
||||
from ietf.utils.test_data import make_test_data, create_person
|
||||
from ietf.utils.test_utils import login_testing_unauthorized
|
||||
from ietf.group.factories import GroupFactory, RoleFactory, GroupEventFactory
|
||||
from ietf.meeting.factories import SessionFactory
|
||||
|
@ -240,6 +240,17 @@ class GroupPagesTests(TestCase):
|
|||
self.assertTrue(milestone.docs.all()[0].name in unicontent(r))
|
||||
|
||||
def test_group_about(self):
|
||||
|
||||
def verify_cannot_edit_group(username):
|
||||
self.client.login(username=username, password=username+"+password")
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 403)
|
||||
|
||||
def verify_can_edit_group(username):
|
||||
self.client.login(username=username, password=username+"+password")
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
make_test_data()
|
||||
group = Group.objects.create(
|
||||
type_id="team",
|
||||
|
@ -247,7 +258,9 @@ class GroupPagesTests(TestCase):
|
|||
name="Test Team",
|
||||
description="The test team is testing.",
|
||||
state_id="active",
|
||||
parent = Group.objects.get(acronym="farfut"),
|
||||
)
|
||||
create_person(group, "chair", name="Testteam Chairman", username="teamchairman")
|
||||
|
||||
for url in [group.about_url(),
|
||||
urlreverse('ietf.group.info.group_about',kwargs=dict(acronym=group.acronym)),
|
||||
|
@ -260,6 +273,14 @@ class GroupPagesTests(TestCase):
|
|||
self.assertTrue(group.acronym in unicontent(r))
|
||||
self.assertTrue(group.description in unicontent(r))
|
||||
|
||||
url = urlreverse('ietf.group.edit.edit', kwargs=dict(acronym=group.acronym))
|
||||
|
||||
for username in ['plain','iana','iab chair','irtf chair','marschairman']:
|
||||
verify_cannot_edit_group(username)
|
||||
|
||||
for username in ['secretary','teamchairman','ad']:
|
||||
verify_can_edit_group(username)
|
||||
|
||||
def test_materials(self):
|
||||
make_test_data()
|
||||
group = Group.objects.create(type_id="team", acronym="testteam", name="Test Team", state_id="active")
|
||||
|
|
|
@ -91,6 +91,15 @@ def can_manage_group_type(user, group_type):
|
|||
|
||||
return has_role(user, 'Secretariat')
|
||||
|
||||
def can_manage_team_group(user, group):
|
||||
if group.type_id != "team":
|
||||
return False
|
||||
elif group.is_decendant_of("ietf") and has_role(user, ('Area Director', 'Secretariat')):
|
||||
return True
|
||||
elif group.is_decendant_of("irtf") and has_role(user, ('IRTF Chair', 'Secretariat')):
|
||||
return True
|
||||
return has_role(user, ('Secretariat'))
|
||||
|
||||
def milestone_reviewer_for_group_type(group_type):
|
||||
if group_type == "rg":
|
||||
return "IRTF Chair"
|
||||
|
|
Loading…
Reference in a new issue