Skip to content
Snippets Groups Projects
Commit 57d49b0a authored by Eric Fischer's avatar Eric Fischer
Browse files

Support filtering team membership

Adds tests and functionality to support filtering the results returned
from team_membership endpoint with optional course_id parameter. Will
return 400 Bad Request in the event that the given course_id does not
match up with the provided team_id (team.course_id does not match), or
if the user is not enrolled in the course given.

Documentation has been added to the relevant API page on the wiki:
https://openedx.atlassian.net/wiki/display/TNL/Team+API
parent f785ae46
No related branches found
No related tags found
No related merge requests found
......@@ -231,3 +231,4 @@ Vedran Karačić <vedran@edx.org>
William Ono <william.ono@ubc.ca>
Dongwook Yoon <dy252@cornell.edu>
Awais Qureshi <awais.qureshi@arbisoft.com>
Eric Fischer <efischer@edx.org>
......@@ -198,6 +198,14 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase):
topic_id='topic_6'
)
self.test_team_name_id_map = {team.name: team for team in (
self.test_team_1,
self.test_team_2,
self.test_team_3,
self.test_team_4,
self.test_team_5,
)}
for user, course in [('staff', self.test_course_1), ('course_staff', self.test_course_1)]:
CourseEnrollment.enroll(
self.users[user], course.id, check_access=True
......@@ -777,6 +785,40 @@ class TestListMembershipAPI(TeamAPITestCase):
else:
self.assertEqual(membership['count'], 0)
@ddt.data(
('student_enrolled_both_courses_other_team', 'TestX/TS101/Test_Course', 200, 'Nuclear Team'),
('student_enrolled_both_courses_other_team', 'MIT/6.002x/Circuits', 200, 'Another Team'),
('student_enrolled', 'TestX/TS101/Test_Course', 200, u'sólar team'),
('student_enrolled', 'MIT/6.002x/Circuits', 400, ''),
)
@ddt.unpack
def test_course_filter_with_username(self, user, course_id, status, team_name):
membership = self.get_membership_list(
status,
{
'username': self.users[user],
'course_id': course_id
},
user=user
)
if status == 200:
self.assertEqual(membership['count'], 1)
self.assertEqual(membership['results'][0]['team']['team_id'], self.test_team_name_id_map[team_name].team_id)
@ddt.data(
('TestX/TS101/Test_Course', 200),
('MIT/6.002x/Circuits', 400),
)
@ddt.unpack
def test_course_filter_with_team_id(self, course_id, status):
membership = self.get_membership_list(status, {'team_id': self.test_team_1.team_id, 'course_id': course_id})
if status == 200:
self.assertEqual(membership['count'], 1)
self.assertEqual(membership['results'][0]['team']['team_id'], self.test_team_1.team_id)
def test_bad_course_id(self):
self.get_membership_list(404, {'course_id': 'no_such_course'})
def test_no_username_or_team_id(self):
self.get_membership_list(400, {})
......
......@@ -793,8 +793,17 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView):
"""GET /api/team/v0/team_membership"""
specified_username_or_team = False
username = None
valid_courses = None
team_id = None
requested_course_id = None
requested_course_key = None
accessible_course_ids = None
if 'course_id' in request.QUERY_PARAMS:
requested_course_id = request.QUERY_PARAMS['course_id']
try:
requested_course_key = CourseKey.from_string(requested_course_id)
except InvalidKeyError:
return Response(status=status.HTTP_404_NOT_FOUND)
if 'team_id' in request.QUERY_PARAMS:
specified_username_or_team = True
......@@ -803,6 +812,8 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView):
team = CourseTeam.objects.get(team_id=team_id)
except CourseTeam.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if requested_course_key is not None and requested_course_key != team.course_id:
return Response(status=status.HTTP_400_BAD_REQUEST)
if not has_team_api_access(request.user, team.course_id):
return Response(status=status.HTTP_404_NOT_FOUND)
......@@ -816,11 +827,9 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView):
staff_courses = (
CourseAccessRole.objects.filter(user=request.user, role='staff').values_list('course_id', flat=True)
)
valid_courses = [
CourseKey.from_string(course_key_string)
for course_list in [enrolled_courses, staff_courses]
for course_key_string in course_list
]
accessible_course_ids = [item for sublist in (enrolled_courses, staff_courses) for item in sublist]
if requested_course_id is not None and requested_course_id not in accessible_course_ids:
return Response(status=status.HTTP_400_BAD_REQUEST)
if not specified_username_or_team:
return Response(
......@@ -828,7 +837,13 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView):
status=status.HTTP_400_BAD_REQUEST
)
queryset = CourseTeamMembership.get_memberships(username, valid_courses, team_id)
course_keys = None
if requested_course_key is not None:
course_keys = [requested_course_key]
elif accessible_course_ids is not None:
course_keys = [CourseKey.from_string(course_string) for course_string in accessible_course_ids]
queryset = CourseTeamMembership.get_memberships(username, course_keys, team_id)
page = self.paginate_queryset(queryset)
serializer = self.get_pagination_serializer(page)
return Response(serializer.data) # pylint: disable=maybe-no-member
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment