EDUCATOR-4920 Control permission to REST endpoint
EDUCATOR-4920 Control permission to REST endpoint CR1 EDUCATOR-4920 Control permission to REST endpoint CR1
This commit is contained in:
@@ -207,16 +207,30 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase):
|
||||
def setUpClass(cls):
|
||||
# pylint: disable=super-method-not-called
|
||||
with super(TeamAPITestCase, cls).setUpClassAndTestData():
|
||||
base_topics = [{
|
||||
'id': 'topic_{}'.format(i), 'name': name,
|
||||
'description': u'Description for topic {}.'.format(i)
|
||||
} for i, name in enumerate([u'Sólar power', 'Wind Power', 'Nuclear Power', 'Coal Power'])]
|
||||
base_topics.append(
|
||||
{
|
||||
'id': 'private_topic_1_id',
|
||||
'name': 'private_topic_1_name',
|
||||
'description': u'Description for topic private topic 1.',
|
||||
'type': u'private_managed'
|
||||
}
|
||||
)
|
||||
base_topics.append(
|
||||
{
|
||||
'id': 'private_topic_2_id',
|
||||
'name': 'private_topic_2_name',
|
||||
'description': u'Description for topic private topic 2.',
|
||||
'type': u'private_managed'
|
||||
}
|
||||
)
|
||||
teams_configuration_1 = TeamsConfig({
|
||||
'topics':
|
||||
[
|
||||
{
|
||||
'id': 'topic_{}'.format(i),
|
||||
'name': name,
|
||||
'description': u'Description for topic {}.'.format(i)
|
||||
} for i, name in enumerate([u'Sólar power', 'Wind Power', 'Nuclear Power', 'Coal Power'])
|
||||
]
|
||||
'topics': base_topics
|
||||
})
|
||||
|
||||
cls.test_course_1 = CourseFactory.create(
|
||||
org='TestX',
|
||||
course='TS101',
|
||||
@@ -255,12 +269,14 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(TeamAPITestCase, cls).setUpTestData()
|
||||
cls.topics_count = 4
|
||||
cls.topics_count = 6
|
||||
cls.users = {
|
||||
'staff': AdminFactory.create(password=cls.test_password),
|
||||
'course_staff': StaffFactory.create(course_key=cls.test_course_1.id, password=cls.test_password)
|
||||
}
|
||||
cls.create_and_enroll_student(username='student_enrolled')
|
||||
cls.create_and_enroll_student(username='student_on_team_1_private_set_1', mode=CourseMode.MASTERS)
|
||||
cls.create_and_enroll_student(username='student_not_member_of_private_teams', mode=CourseMode.MASTERS)
|
||||
cls.create_and_enroll_student(username='student_enrolled_not_on_team')
|
||||
cls.create_and_enroll_student(username='student_unenrolled', courses=[])
|
||||
|
||||
@@ -346,6 +362,36 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase):
|
||||
organization_protected=True
|
||||
)
|
||||
|
||||
cls.team_1_in_private_teamset_1 = CourseTeamFactory.create(
|
||||
name='team 1 in private teamset 1',
|
||||
description='team 1 in private teamset 1 desc',
|
||||
country='US',
|
||||
language='EN',
|
||||
course_id=cls.test_course_1.id,
|
||||
topic_id='private_topic_1_id',
|
||||
organization_protected=True
|
||||
)
|
||||
|
||||
cls.team_2_in_private_teamset_1 = CourseTeamFactory.create(
|
||||
name='team 2 in private teamset 1',
|
||||
description='team 2 in private teamset 1 desc',
|
||||
country='US',
|
||||
language='EN',
|
||||
course_id=cls.test_course_1.id,
|
||||
topic_id='private_topic_1_id',
|
||||
organization_protected=True
|
||||
)
|
||||
|
||||
cls.team_1_in_private_teamset_2 = CourseTeamFactory.create(
|
||||
name='team 1 in private teamset 2',
|
||||
description='team 1 in private teamset 2 desc',
|
||||
country='US',
|
||||
language='EN',
|
||||
course_id=cls.test_course_1.id,
|
||||
topic_id='private_topic_2_id',
|
||||
organization_protected=True
|
||||
)
|
||||
|
||||
cls.test_team_name_id_map = {team.name: team for team in (
|
||||
cls.solar_team,
|
||||
cls.wind_team,
|
||||
@@ -370,6 +416,7 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase):
|
||||
cls.another_team.add_user(cls.users['student_enrolled_both_courses_other_team'])
|
||||
cls.public_profile_team.add_user(cls.users['student_enrolled_public_profile'])
|
||||
cls.masters_only_team.add_user(cls.users['student_masters'])
|
||||
cls.team_1_in_private_teamset_1.add_user(cls.users['student_on_team_1_private_set_1'])
|
||||
|
||||
def build_membership_data_raw(self, username, team):
|
||||
"""Assembles a membership creation payload based on the raw values provided."""
|
||||
@@ -581,8 +628,8 @@ class TestListTeamsAPI(EventTestMixin, TeamAPITestCase):
|
||||
('student_inactive', 401),
|
||||
('student_unenrolled', 403),
|
||||
('student_enrolled', 200, 3),
|
||||
('staff', 200, 4),
|
||||
('course_staff', 200, 4),
|
||||
('staff', 200, 7),
|
||||
('course_staff', 200, 7),
|
||||
('community_ta', 200, 3),
|
||||
('student_masters', 200, 1)
|
||||
)
|
||||
@@ -662,6 +709,25 @@ class TestListTeamsAPI(EventTestMixin, TeamAPITestCase):
|
||||
result = self.get_teams_list(200, {'page_size': 2})
|
||||
self.assertEqual(2, result['num_pages'])
|
||||
|
||||
def test_non_member_trying_to_get_private_topic(self):
|
||||
"""
|
||||
Verifies that when a student that is enrolled in a course, but is NOT a member of
|
||||
a private team set, asks for information about that team set, an empty list is returned.
|
||||
"""
|
||||
result = self.get_teams_list(data={'topic_id': 'private_topic_1_id'})
|
||||
self.assertEqual([], result['results'])
|
||||
|
||||
def test_member_trying_to_get_private_topic(self):
|
||||
"""
|
||||
Verifies that when a student that is enrolled in a course, and IS a member of
|
||||
a private team set, asks for information about that team set, information about the teamset is returned.
|
||||
"""
|
||||
result = self.get_teams_list(data={'topic_id': 'private_topic_1_id'},
|
||||
user='student_on_team_1_private_set_1')
|
||||
self.assertEqual(1, len(result['results']))
|
||||
self.assertEqual('private_topic_1_id', result['results'][0]['topic_id'])
|
||||
self.assertNotEqual([], result['results'])
|
||||
|
||||
def test_page(self):
|
||||
result = self.get_teams_list(200, {'page_size': 1, 'page': 3})
|
||||
self.assertEqual(3, result['num_pages'])
|
||||
@@ -1141,11 +1207,14 @@ class TestListTopicsAPI(TeamAPITestCase):
|
||||
self.get_topics_list(400)
|
||||
|
||||
@ddt.data(
|
||||
(None, 200, ['Coal Power', 'Nuclear Power', u'Sólar power', 'Wind Power'], 'name'),
|
||||
('name', 200, ['Coal Power', 'Nuclear Power', u'Sólar power', 'Wind Power'], 'name'),
|
||||
(None, 200, ['Coal Power', 'Nuclear Power', 'private_topic_1_name', 'private_topic_2_name',
|
||||
u'Sólar power', 'Wind Power'], 'name'),
|
||||
('name', 200, ['Coal Power', 'Nuclear Power', 'private_topic_1_name', 'private_topic_2_name',
|
||||
u'Sólar power', 'Wind Power'], 'name'),
|
||||
# Note that "Nuclear Power" and "Solar power" both have 2 teams. "Coal Power" and "Window Power"
|
||||
# both have 0 teams. The secondary sort is alphabetical by name.
|
||||
('team_count', 200, ['Nuclear Power', u'Sólar power', 'Coal Power', 'Wind Power'], 'team_count'),
|
||||
('team_count', 200, ['Nuclear Power', u'Sólar power', 'Coal Power', 'private_topic_1_name',
|
||||
'private_topic_2_name', 'Wind Power'], 'team_count'),
|
||||
('no_such_field', 400, [], None),
|
||||
)
|
||||
@ddt.unpack
|
||||
|
||||
@@ -419,6 +419,9 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView):
|
||||
topic_id=topic_id
|
||||
)
|
||||
return Response(error, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
if course_module.teamsets_by_id[topic_id].is_private_managed:
|
||||
result_filter.update({'membership__user__username': request.user})
|
||||
result_filter.update({'topic_id': topic_id})
|
||||
|
||||
organization_protection_status = user_organization_protection_status(
|
||||
@@ -467,7 +470,19 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView):
|
||||
'open_slots': ('team_size', '-last_activity_at'),
|
||||
'last_activity_at': ('-last_activity_at', 'team_size'),
|
||||
}
|
||||
queryset = CourseTeam.objects.filter(**result_filter)
|
||||
|
||||
if not has_access(request.user, 'staff', course_key):
|
||||
# hide private_managed courses from non-admin users that aren't members of those teams
|
||||
private_topic_ids = [ts.teamset_id for ts in course_module.teamsets if
|
||||
ts.is_private_managed]
|
||||
public_teams = CourseTeam.objects.filter(**result_filter).exclude(
|
||||
topic_id__in=private_topic_ids)
|
||||
private_managed_teams_of_user = CourseTeam.objects.filter(topic_id__in=private_topic_ids,
|
||||
membership__user__username=request.user)
|
||||
queryset = public_teams | private_managed_teams_of_user
|
||||
else:
|
||||
queryset = CourseTeam.objects.filter(**result_filter)
|
||||
|
||||
order_by_input = request.query_params.get('order_by', 'name')
|
||||
if order_by_input not in ordering_schemes:
|
||||
return Response(
|
||||
|
||||
@@ -308,6 +308,13 @@ class TeamsetConfig(object):
|
||||
except (KeyError, ValueError):
|
||||
return TeamsetType.get_default()
|
||||
|
||||
@cached_property
|
||||
def is_private_managed(self):
|
||||
"""
|
||||
Returns true if teamsettype is private_managed
|
||||
"""
|
||||
return self.teamset_type == TeamsetType.private_managed
|
||||
|
||||
|
||||
class TeamsetType(Enum):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user