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
This commit is contained in:
1
AUTHORS
1
AUTHORS
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user