diff --git a/AUTHORS b/AUTHORS index 390e932c4f83c601503e302e2d038f23159b2354..df8acfeedbb2436fafb28557b3bbc61f8b6c3c9b 100644 --- a/AUTHORS +++ b/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> diff --git a/lms/djangoapps/teams/tests/test_views.py b/lms/djangoapps/teams/tests/test_views.py index 93913211a4db56c6c4a1d2782ece248992411864..bd1daded4cf7cc2b1c6c04fe5b45b52e3036cca7 100644 --- a/lms/djangoapps/teams/tests/test_views.py +++ b/lms/djangoapps/teams/tests/test_views.py @@ -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, {}) diff --git a/lms/djangoapps/teams/views.py b/lms/djangoapps/teams/views.py index d767f5ac166aa90307128a04e70b35b24eda29a7..5df771309c8bd932c36f6d9c7c7658073e8257ef 100644 --- a/lms/djangoapps/teams/views.py +++ b/lms/djangoapps/teams/views.py @@ -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