Exemplo n.º 1
0
    def get(self, request):
        """GET /api/team/v0/teams/"""
        result_filter = {'is_active': True}

        if 'course_id' in request.QUERY_PARAMS:
            course_id_string = request.QUERY_PARAMS['course_id']
            try:
                course_key = CourseKey.from_string(course_id_string)
                # Ensure the course exists
                if not modulestore().has_course(course_key):
                    return Response(status=status.HTTP_404_NOT_FOUND)
                result_filter.update({'course_id': course_key})
            except InvalidKeyError:
                error = build_api_error(
                    ugettext_noop(
                        "The supplied course id {course_id} is not valid."),
                    course_id=course_id_string,
                )
                return Response(error, status=status.HTTP_400_BAD_REQUEST)

            if not has_team_api_access(request.user, course_key):
                return Response(status=status.HTTP_403_FORBIDDEN)
        else:
            return Response(build_api_error(
                ugettext_noop("course_id must be provided")),
                            status=status.HTTP_400_BAD_REQUEST)

        if 'topic_id' in request.QUERY_PARAMS:
            result_filter.update(
                {'topic_id': request.QUERY_PARAMS['topic_id']})
        if 'include_inactive' in request.QUERY_PARAMS and request.QUERY_PARAMS[
                'include_inactive'].lower() == 'true':
            del result_filter['is_active']
        if 'text_search' in request.QUERY_PARAMS:
            return Response(build_api_error(
                ugettext_noop("text_search is not yet supported.")),
                            status=status.HTTP_400_BAD_REQUEST)

        queryset = CourseTeam.objects.filter(**result_filter)

        order_by_input = request.QUERY_PARAMS.get('order_by', 'name')
        if order_by_input == 'name':
            queryset = queryset.extra(select={'lower_name': "lower(name)"})
            order_by_field = 'lower_name'
        elif order_by_input == 'open_slots':
            queryset = queryset.annotate(team_size=Count('users'))
            order_by_field = 'team_size'
        elif order_by_input == 'last_activity':
            return Response(build_api_error(
                ugettext_noop("last_activity is not yet supported")),
                            status=status.HTTP_400_BAD_REQUEST)

        queryset = queryset.order_by(order_by_field)

        if not queryset:
            return Response(status=status.HTTP_404_NOT_FOUND)

        page = self.paginate_queryset(queryset)
        serializer = self.get_pagination_serializer(page)
        return Response(serializer.data)  # pylint: disable=maybe-no-member
Exemplo n.º 2
0
    def post(self, request):
        """POST /api/team/v0/team_membership"""
        field_errors = {}

        if 'username' not in request.DATA:
            field_errors['username'] = build_api_error(
                ugettext_noop("Username is required."))

        if 'team_id' not in request.DATA:
            field_errors['team_id'] = build_api_error(
                ugettext_noop("Team id is required."))

        if field_errors:
            return Response({
                'field_errors': field_errors,
            },
                            status=status.HTTP_400_BAD_REQUEST)

        try:
            team = CourseTeam.objects.get(team_id=request.DATA['team_id'])
        except CourseTeam.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        username = request.DATA['username']
        if not has_team_api_access(
                request.user, team.course_id, access_username=username):
            return Response(status=status.HTTP_404_NOT_FOUND)

        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        course_module = modulestore().get_course(team.course_id)
        if course_module.teams_max_size is not None and team.users.count(
        ) >= course_module.teams_max_size:
            return Response(build_api_error(
                ugettext_noop("This team is already full.")),
                            status=status.HTTP_400_BAD_REQUEST)

        try:
            membership = team.add_user(user)
        except AlreadyOnTeamInCourse:
            return Response(build_api_error(ugettext_noop(
                "The user {username} is already a member of a team in this course."
            ),
                                            username=username),
                            status=status.HTTP_400_BAD_REQUEST)
        except NotEnrolledInCourseForTeam:
            return Response(build_api_error(ugettext_noop(
                "The user {username} is not enrolled in the course associated with this team."
            ),
                                            username=username),
                            status=status.HTTP_400_BAD_REQUEST)

        serializer = self.get_serializer(instance=membership)
        return Response(serializer.data)
Exemplo n.º 3
0
    def post(self, request):
        """POST /api/team/v0/team_membership"""
        field_errors = {}

        if 'username' not in request.DATA:
            field_errors['username'] = build_api_error(ugettext_noop("Username is required."))

        if 'team_id' not in request.DATA:
            field_errors['team_id'] = build_api_error(ugettext_noop("Team id is required."))

        if field_errors:
            return Response({
                'field_errors': field_errors,
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            team = CourseTeam.objects.get(team_id=request.DATA['team_id'])
        except CourseTeam.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        username = request.DATA['username']
        if not has_team_api_access(request.user, team.course_id, access_username=username):
            return Response(status=status.HTTP_404_NOT_FOUND)

        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        course_module = modulestore().get_course(team.course_id)
        if course_module.teams_max_size is not None and team.users.count() >= course_module.teams_max_size:
            return Response(
                build_api_error(ugettext_noop("This team is already full.")),
                status=status.HTTP_400_BAD_REQUEST
            )

        try:
            membership = team.add_user(user)
        except AlreadyOnTeamInCourse:
            return Response(
                build_api_error(
                    ugettext_noop("The user {username} is already a member of a team in this course."),
                    username=username
                ),
                status=status.HTTP_400_BAD_REQUEST
            )
        except NotEnrolledInCourseForTeam:
            return Response(
                build_api_error(
                    ugettext_noop("The user {username} is not enrolled in the course associated with this team."),
                    username=username
                ),
                status=status.HTTP_400_BAD_REQUEST
            )

        serializer = self.get_serializer(instance=membership)
        return Response(serializer.data)
Exemplo n.º 4
0
    def get(self, request):
        """GET /api/team/v0/teams/"""
        result_filter = {"is_active": True}

        if "course_id" in request.QUERY_PARAMS:
            course_id_string = request.QUERY_PARAMS["course_id"]
            try:
                course_key = CourseKey.from_string(course_id_string)
                # Ensure the course exists
                if not modulestore().has_course(course_key):
                    return Response(status=status.HTTP_404_NOT_FOUND)
                result_filter.update({"course_id": course_key})
            except InvalidKeyError:
                error = build_api_error(
                    ugettext_noop("The supplied course id {course_id} is not valid."), course_id=course_id_string
                )
                return Response(error, status=status.HTTP_400_BAD_REQUEST)

            if not has_team_api_access(request.user, course_key):
                return Response(status=status.HTTP_403_FORBIDDEN)
        else:
            return Response(
                build_api_error(ugettext_noop("course_id must be provided")), status=status.HTTP_400_BAD_REQUEST
            )

        if "topic_id" in request.QUERY_PARAMS:
            result_filter.update({"topic_id": request.QUERY_PARAMS["topic_id"]})
        if "include_inactive" in request.QUERY_PARAMS and request.QUERY_PARAMS["include_inactive"].lower() == "true":
            del result_filter["is_active"]
        if "text_search" in request.QUERY_PARAMS:
            return Response(
                build_api_error(ugettext_noop("text_search is not yet supported.")), status=status.HTTP_400_BAD_REQUEST
            )

        queryset = CourseTeam.objects.filter(**result_filter)

        order_by_input = request.QUERY_PARAMS.get("order_by", "name")
        if order_by_input == "name":
            queryset = queryset.extra(select={"lower_name": "lower(name)"})
            order_by_field = "lower_name"
        elif order_by_input == "open_slots":
            queryset = queryset.annotate(team_size=Count("users"))
            order_by_field = "team_size"
        elif order_by_input == "last_activity":
            return Response(
                build_api_error(ugettext_noop("last_activity is not yet supported")), status=status.HTTP_400_BAD_REQUEST
            )

        queryset = queryset.order_by(order_by_field)

        if not queryset:
            return Response(status=status.HTTP_404_NOT_FOUND)

        page = self.paginate_queryset(queryset)
        serializer = self.get_pagination_serializer(page)
        return Response(serializer.data)  # pylint: disable=maybe-no-member
Exemplo n.º 5
0
    def post(self, request):
        """POST /api/team/v0/teams/"""
        field_errors = {}
        course_key = None

        course_id = request.DATA.get('course_id')
        try:
            course_key = CourseKey.from_string(course_id)
            # Ensure the course exists
            if not modulestore().has_course(course_key):
                return Response(status=status.HTTP_404_NOT_FOUND)
        except InvalidKeyError:
            field_errors['course_id'] = build_api_error(ugettext_noop(
                'The supplied course_id {course_id} is not valid.'),
                                                        course_id=course_id)
            return Response({
                'field_errors': field_errors,
            },
                            status=status.HTTP_400_BAD_REQUEST)

        # Course and global staff, as well as discussion "privileged" users, will not automatically
        # be added to a team when they create it. They are allowed to create multiple teams.
        team_administrator = (has_access(request.user, 'staff', course_key)
                              or has_discussion_privileges(
                                  request.user, course_key))
        if not team_administrator and CourseTeamMembership.user_in_team_for_course(
                request.user, course_key):
            error_message = build_api_error(
                ugettext_noop('You are already in a team in this course.'),
                course_id=course_id)
            return Response(error_message, status=status.HTTP_400_BAD_REQUEST)

        if course_key and not has_team_api_access(request.user, course_key):
            return Response(status=status.HTTP_403_FORBIDDEN)

        data = request.DATA.copy()
        data['course_id'] = course_key

        serializer = CourseTeamCreationSerializer(data=data)
        add_serializer_errors(serializer, data, field_errors)

        if field_errors:
            return Response({
                'field_errors': field_errors,
            },
                            status=status.HTTP_400_BAD_REQUEST)
        else:
            team = serializer.save()
            if not team_administrator:
                # Add the creating user to the team.
                team.add_user(request.user)
            return Response(CourseTeamSerializer(team).data)
Exemplo n.º 6
0
    def post(self, request):
        """POST /api/team/v0/teams/"""
        field_errors = {}
        course_key = None

        course_id = request.DATA.get("course_id")
        try:
            course_key = CourseKey.from_string(course_id)
            # Ensure the course exists
            if not modulestore().has_course(course_key):
                return Response(status=status.HTTP_404_NOT_FOUND)
        except InvalidKeyError:
            field_errors["course_id"] = build_api_error(
                ugettext_noop("The supplied course_id {course_id} is not valid."), course_id=course_id
            )
            return Response({"field_errors": field_errors}, status=status.HTTP_400_BAD_REQUEST)

        # Course and global staff, as well as discussion "privileged" users, will not automatically
        # be added to a team when they create it. They are allowed to create multiple teams.
        team_administrator = has_access(request.user, "staff", course_key) or has_discussion_privileges(
            request.user, course_key
        )
        if not team_administrator and CourseTeamMembership.user_in_team_for_course(request.user, course_key):
            error_message = build_api_error(
                ugettext_noop("You are already in a team in this course."), course_id=course_id
            )
            return Response(error_message, status=status.HTTP_400_BAD_REQUEST)

        if course_key and not has_team_api_access(request.user, course_key):
            return Response(status=status.HTTP_403_FORBIDDEN)

        data = request.DATA.copy()
        data["course_id"] = course_key

        serializer = CourseTeamCreationSerializer(data=data)
        add_serializer_errors(serializer, data, field_errors)

        if field_errors:
            return Response({"field_errors": field_errors}, status=status.HTTP_400_BAD_REQUEST)
        else:
            team = serializer.save()
            emit_team_event("edx.team.created", course_key, {"team_id": team.team_id})
            if not team_administrator:
                # Add the creating user to the team.
                team.add_user(request.user)
                emit_team_event(
                    "edx.team.learner_added",
                    course_key,
                    {"team_id": team.team_id, "user_id": request.user.id, "add_method": "added_on_create"},
                )
            return Response(CourseTeamSerializer(team).data)
Exemplo n.º 7
0
    def post(self, request):
        """POST /api/team/v0/teams/"""
        field_errors = {}
        course_key = None

        course_id = request.DATA.get('course_id')
        try:
            course_key = CourseKey.from_string(course_id)
            # Ensure the course exists
            if not modulestore().has_course(course_key):
                return Response(status=status.HTTP_404_NOT_FOUND)
        except InvalidKeyError:
            field_errors['course_id'] = build_api_error(
                ugettext_noop('The supplied course_id {course_id} is not valid.'),
                course_id=course_id
            )
            return Response({
                'field_errors': field_errors,
            }, status=status.HTTP_400_BAD_REQUEST)

        if CourseTeamMembership.user_in_team_for_course(request.user, course_key):
            error_message = build_api_error(
                ugettext_noop('You are already in a team in this course.'),
                course_id=course_id
            )
            return Response({
                'error_message': error_message,
            }, status=status.HTTP_400_BAD_REQUEST)

        if course_key and not has_team_api_access(request.user, course_key):
            return Response(status=status.HTTP_403_FORBIDDEN)

        data = request.DATA.copy()
        data['course_id'] = course_key

        serializer = CourseTeamCreationSerializer(data=data)
        add_serializer_errors(serializer, data, field_errors)

        if field_errors:
            return Response({
                'field_errors': field_errors,
            }, status=status.HTTP_400_BAD_REQUEST)
        else:
            team = serializer.save()
            if not (has_access(request.user, 'staff', course_key)
                    or has_discussion_privileges(request.user, course_key)):
                # Add the creating user to the team.
                team.add_user(request.user)
            return Response(CourseTeamSerializer(team).data)
Exemplo n.º 8
0
    def post(self, request):
        """POST /api/team/v0/team_membership"""
        field_errors = {}

        if "username" not in request.DATA:
            field_errors["username"] = build_api_error(ugettext_noop("Username is required."))

        if "team_id" not in request.DATA:
            field_errors["team_id"] = build_api_error(ugettext_noop("Team id is required."))

        if field_errors:
            return Response({"field_errors": field_errors}, status=status.HTTP_400_BAD_REQUEST)

        try:
            team = CourseTeam.objects.get(team_id=request.DATA["team_id"])
        except CourseTeam.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        username = request.DATA["username"]
        if not has_team_api_access(request.user, team.course_id, access_username=username):
            return Response(status=status.HTTP_404_NOT_FOUND)

        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        try:
            membership = team.add_user(user)
        except AlreadyOnTeamInCourse:
            return Response(
                build_api_error(
                    ugettext_noop("The user {username} is already a member of a team in this course."),
                    username=username,
                ),
                status=status.HTTP_400_BAD_REQUEST,
            )
        except NotEnrolledInCourseForTeam:
            return Response(
                build_api_error(
                    ugettext_noop("The user {username} is not enrolled in the course associated with this team."),
                    username=username,
                ),
                status=status.HTTP_400_BAD_REQUEST,
            )

        serializer = self.get_serializer(instance=membership)
        return Response(serializer.data)
Exemplo n.º 9
0
    def post(self, request):
        """POST /api/team/v0/teams/"""
        field_errors = {}
        course_key = None

        course_id = request.DATA.get('course_id')
        try:
            course_key = CourseKey.from_string(course_id)
            # Ensure the course exists
            if not modulestore().has_course(course_key):
                return Response(status=status.HTTP_404_NOT_FOUND)
        except InvalidKeyError:
            field_errors['course_id'] = build_api_error(ugettext_noop(
                'The supplied course_id {course_id} is not valid.'),
                                                        course_id=course_id)

        if course_key and not has_team_api_access(request.user, course_key):
            return Response(status=status.HTTP_403_FORBIDDEN)

        data = request.DATA.copy()
        data['course_id'] = course_key

        serializer = CourseTeamCreationSerializer(data=data)
        add_serializer_errors(serializer, data, field_errors)

        if field_errors:
            return Response({
                'field_errors': field_errors,
            },
                            status=status.HTTP_400_BAD_REQUEST)
        else:
            team = serializer.save()
            return Response(CourseTeamSerializer(team).data)
Exemplo n.º 10
0
    def post(self, request):
        """POST /api/team/v0/teams/"""
        field_errors = {}
        course_key = None

        course_id = request.DATA.get('course_id')
        try:
            course_key = CourseKey.from_string(course_id)
            # Ensure the course exists
            if not modulestore().has_course(course_key):
                return Response(status=status.HTTP_404_NOT_FOUND)
        except InvalidKeyError:
            field_errors['course_id'] = build_api_error(
                ugettext_noop('The supplied course_id {course_id} is not valid.'),
                course_id=course_id
            )

        if course_key and not has_team_api_access(request.user, course_key):
            return Response(status=status.HTTP_403_FORBIDDEN)

        data = request.DATA.copy()
        data['course_id'] = course_key

        serializer = CourseTeamCreationSerializer(data=data)
        add_serializer_errors(serializer, data, field_errors)

        if field_errors:
            return Response({
                'field_errors': field_errors,
            }, status=status.HTTP_400_BAD_REQUEST)
        else:
            team = serializer.save()
            return Response(CourseTeamSerializer(team).data)
Exemplo n.º 11
0
    def get(self, request):
        """GET /api/team/v0/team_membership"""
        specified_username_or_team = False
        username = 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
            team_id = request.QUERY_PARAMS['team_id']
            try:
                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)

        if 'username' in request.QUERY_PARAMS:
            specified_username_or_team = True
            username = request.QUERY_PARAMS['username']
            if not request.user.is_staff:
                enrolled_courses = (
                    CourseEnrollment.enrollments_for_user(request.user).values_list('course_id', flat=True)
                )
                staff_courses = (
                    CourseAccessRole.objects.filter(user=request.user, role='staff').values_list('course_id', flat=True)
                )
                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(
                build_api_error(ugettext_noop("username or team_id must be specified.")),
                status=status.HTTP_400_BAD_REQUEST
            )

        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
Exemplo n.º 12
0
    def get(self, request):
        """GET /api/team/v0/topics/?course_id={course_id}"""
        course_id_string = request.QUERY_PARAMS.get('course_id', None)
        if course_id_string is None:
            return Response(
                {
                    'field_errors': {
                        'course_id':
                        build_api_error(ugettext_noop(
                            "The supplied course id {course_id} is not valid."
                        ),
                                        course_id=course_id_string)
                    }
                },
                status=status.HTTP_400_BAD_REQUEST)

        try:
            course_id = CourseKey.from_string(course_id_string)
        except InvalidKeyError:
            return Response(status=status.HTTP_404_NOT_FOUND)

        # Ensure the course exists
        course_module = modulestore().get_course(course_id)
        if course_module is None:  # course is None if not found
            return Response(status=status.HTTP_404_NOT_FOUND)

        if not has_team_api_access(request.user, course_id):
            return Response(status=status.HTTP_403_FORBIDDEN)

        ordering = request.QUERY_PARAMS.get('order_by', 'name')
        if ordering == 'name':
            topics = get_ordered_topics(course_module, ordering)
        else:
            return Response(
                {
                    'developer_message':
                    "unsupported order_by value {ordering}".format(
                        ordering=ordering),
                    # Translators: 'ordering' is a string describing a way
                    # of ordering a list. For example, {ordering} may be
                    # 'name', indicating that the user wants to sort the
                    # list by lower case name.
                    'user_message':
                    _(u"The ordering {ordering} is not supported").format(
                        ordering=ordering),
                },
                status=status.HTTP_400_BAD_REQUEST)

        page = self.paginate_queryset(topics)
        serializer = self.pagination_serializer_class(page,
                                                      context={
                                                          'course_id':
                                                          course_id,
                                                          'sort_order':
                                                          ordering
                                                      })
        return Response(serializer.data)
Exemplo n.º 13
0
    def get(self, request):
        """GET /api/team/v0/topics/?course_id={course_id}"""
        course_id_string = request.QUERY_PARAMS.get('course_id', None)
        if course_id_string is None:
            return Response({
                'field_errors': {
                    'course_id': build_api_error(
                        ugettext_noop("The supplied course id {course_id} is not valid."),
                        course_id=course_id_string
                    )
                }
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            course_id = CourseKey.from_string(course_id_string)
        except InvalidKeyError:
            return Response(status=status.HTTP_404_NOT_FOUND)

        # Ensure the course exists
        course_module = modulestore().get_course(course_id)
        if course_module is None:  # course is None if not found
            return Response(status=status.HTTP_404_NOT_FOUND)

        if not has_team_api_access(request.user, course_id):
            return Response(status=status.HTTP_403_FORBIDDEN)

        ordering = request.QUERY_PARAMS.get('order_by', 'name')
        if ordering not in ['name', 'team_count']:
            return Response({
                'developer_message': "unsupported order_by value {ordering}".format(ordering=ordering),
                # Translators: 'ordering' is a string describing a way
                # of ordering a list. For example, {ordering} may be
                # 'name', indicating that the user wants to sort the
                # list by lower case name.
                'user_message': _(u"The ordering {ordering} is not supported").format(ordering=ordering),
            }, status=status.HTTP_400_BAD_REQUEST)

        # Always sort alphabetically, as it will be used as secondary sort
        # in the case of "team_count".
        topics = get_alphabetical_topics(course_module)
        if ordering == 'team_count':
            add_team_count(topics, course_id)
            topics.sort(key=lambda t: t['team_count'], reverse=True)
            page = self.paginate_queryset(topics)
            # Since team_count has already been added to all the topics, use PaginatedTopicSerializer.
            # Even though sorting is done outside of the serializer, sort_order needs to be passed
            # to the serializer so that the paginated results indicate how they were sorted.
            serializer = PaginatedTopicSerializer(page, context={'course_id': course_id, 'sort_order': ordering})
        else:
            page = self.paginate_queryset(topics)
            # Use the serializer that adds team_count in a bulk operation per page.
            serializer = BulkTeamCountPaginatedTopicSerializer(
                page, context={'course_id': course_id, 'sort_order': ordering}
            )

        return Response(serializer.data)
Exemplo n.º 14
0
    def get(self, request):
        """GET /api/team/v0/topics/?course_id={course_id}"""
        course_id_string = request.QUERY_PARAMS.get("course_id", None)
        if course_id_string is None:
            return Response(
                {
                    "field_errors": {
                        "course_id": build_api_error(
                            ugettext_noop("The supplied course id {course_id} is not valid."),
                            course_id=course_id_string,
                        )
                    }
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        try:
            course_id = CourseKey.from_string(course_id_string)
        except InvalidKeyError:
            return Response(status=status.HTTP_404_NOT_FOUND)

        # Ensure the course exists
        course_module = modulestore().get_course(course_id)
        if course_module is None:  # course is None if not found
            return Response(status=status.HTTP_404_NOT_FOUND)

        if not has_team_api_access(request.user, course_id):
            return Response(status=status.HTTP_403_FORBIDDEN)

        topics = course_module.teams_topics

        ordering = request.QUERY_PARAMS.get("order_by", "name")
        if ordering == "name":
            topics = sorted(topics, key=lambda t: t["name"].lower())
        else:
            return Response(
                {
                    "developer_message": "unsupported order_by value {}".format(ordering),
                    "user_message": _(u"The ordering {} is not supported").format(ordering),
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        page = self.paginate_queryset(topics)
        serializer = self.get_pagination_serializer(page)
        return Response(serializer.data)  # pylint: disable=maybe-no-member
Exemplo n.º 15
0
    def get(self, request):
        """GET /api/team/v0/topics/?course_id={course_id}"""
        course_id_string = request.QUERY_PARAMS.get('course_id', None)
        if course_id_string is None:
            return Response(
                {
                    'field_errors': {
                        'course_id':
                        build_api_error(ugettext_noop(
                            "The supplied course id {course_id} is not valid."
                        ),
                                        course_id=course_id_string)
                    }
                },
                status=status.HTTP_400_BAD_REQUEST)

        try:
            course_id = CourseKey.from_string(course_id_string)
        except InvalidKeyError:
            return Response(status=status.HTTP_404_NOT_FOUND)

        # Ensure the course exists
        course_module = modulestore().get_course(course_id)
        if course_module is None:  # course is None if not found
            return Response(status=status.HTTP_404_NOT_FOUND)

        if not has_team_api_access(request.user, course_id):
            return Response(status=status.HTTP_403_FORBIDDEN)

        ordering = request.QUERY_PARAMS.get('order_by', 'name')
        if ordering == 'name':
            topics = get_ordered_topics(course_module, ordering)
        else:
            return Response(
                {
                    'developer_message':
                    "unsupported order_by value {}".format(ordering),
                    'user_message':
                    _(u"The ordering {} is not supported").format(ordering),
                },
                status=status.HTTP_400_BAD_REQUEST)

        page = self.paginate_queryset(topics)
        serializer = self.get_pagination_serializer(page)
        serializer.context = {'sort_order': ordering}
        return Response(serializer.data)  # pylint: disable=maybe-no-member
Exemplo n.º 16
0
    def get(self, request):
        """GET /api/team/v0/team_membership"""
        queryset = CourseTeamMembership.objects.all()

        specified_username_or_team = False

        if 'team_id' in request.QUERY_PARAMS:
            specified_username_or_team = True
            team_id = request.QUERY_PARAMS['team_id']
            try:
                team = CourseTeam.objects.get(team_id=team_id)
            except CourseTeam.DoesNotExist:
                return Response(status=status.HTTP_404_NOT_FOUND)
            if not has_team_api_access(request.user, team.course_id):
                return Response(status=status.HTTP_404_NOT_FOUND)
            queryset = queryset.filter(team__team_id=team_id)

        if 'username' in request.QUERY_PARAMS:
            specified_username_or_team = True
            if not request.user.is_staff:
                enrolled_courses = (
                    CourseEnrollment.enrollments_for_user(request.user).values_list('course_id', flat=True)
                )
                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
                ]
                queryset = queryset.filter(team__course_id__in=valid_courses)
            queryset = queryset.filter(user__username=request.QUERY_PARAMS['username'])

        if not specified_username_or_team:
            return Response(
                build_api_error(ugettext_noop("username or team_id must be specified.")),
                status=status.HTTP_400_BAD_REQUEST
            )

        page = self.paginate_queryset(queryset)
        serializer = self.get_pagination_serializer(page)
        return Response(serializer.data)  # pylint: disable=maybe-no-member
Exemplo n.º 17
0
    def get(self, request):
        """GET /api/team/v0/team_membership"""
        queryset = CourseTeamMembership.objects.all()

        specified_username_or_team = False

        if 'team_id' in request.QUERY_PARAMS:
            specified_username_or_team = True
            team_id = request.QUERY_PARAMS['team_id']
            try:
                team = CourseTeam.objects.get(team_id=team_id)
            except CourseTeam.DoesNotExist:
                return Response(status=status.HTTP_404_NOT_FOUND)
            if not has_team_api_access(request.user, team.course_id):
                return Response(status=status.HTTP_404_NOT_FOUND)
            queryset = queryset.filter(team__team_id=team_id)

        if 'username' in request.QUERY_PARAMS:
            specified_username_or_team = True
            if not request.user.is_staff:
                enrolled_courses = (
                    CourseEnrollment.enrollments_for_user(request.user).values_list('course_id', flat=True)
                )
                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
                ]
                queryset = queryset.filter(team__course_id__in=valid_courses)
            queryset = queryset.filter(user__username=request.QUERY_PARAMS['username'])

        if not specified_username_or_team:
            return Response(
                build_api_error(ugettext_noop("username or team_id must be specified.")),
                status=status.HTTP_400_BAD_REQUEST
            )

        page = self.paginate_queryset(queryset)
        serializer = self.get_pagination_serializer(page)
        return Response(serializer.data)  # pylint: disable=maybe-no-member
Exemplo n.º 18
0
    def get(self, request):
        """GET /api/team/v0/topics/?course_id={course_id}"""
        course_id_string = request.QUERY_PARAMS.get('course_id', None)
        if course_id_string is None:
            return Response({
                'field_errors': {
                    'course_id': build_api_error(
                        ugettext_noop("The supplied course id {course_id} is not valid."),
                        course_id=course_id_string
                    )
                }
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            course_id = CourseKey.from_string(course_id_string)
        except InvalidKeyError:
            return Response(status=status.HTTP_404_NOT_FOUND)

        # Ensure the course exists
        course_module = modulestore().get_course(course_id)
        if course_module is None:  # course is None if not found
            return Response(status=status.HTTP_404_NOT_FOUND)

        if not has_team_api_access(request.user, course_id):
            return Response(status=status.HTTP_403_FORBIDDEN)

        ordering = request.QUERY_PARAMS.get('order_by', 'name')
        if ordering == 'name':
            topics = get_ordered_topics(course_module, ordering)
        else:
            return Response({
                'developer_message': "unsupported order_by value {ordering}".format(ordering=ordering),
                # Translators: 'ordering' is a string describing a way
                # of ordering a list. For example, {ordering} may be
                # 'name', indicating that the user wants to sort the
                # list by lower case name.
                'user_message': _(u"The ordering {ordering} is not supported").format(ordering=ordering),
            }, status=status.HTTP_400_BAD_REQUEST)

        page = self.paginate_queryset(topics)
        serializer = self.pagination_serializer_class(page, context={'course_id': course_id, 'sort_order': ordering})
        return Response(serializer.data)  # pylint: disable=maybe-no-member
Exemplo n.º 19
0
    def get(self, request):
        """GET /api/team/v0/teams/"""
        result_filter = {}

        if 'course_id' in request.QUERY_PARAMS:
            course_id_string = request.QUERY_PARAMS['course_id']
            try:
                course_key = CourseKey.from_string(course_id_string)
                # Ensure the course exists
                course_module = modulestore().get_course(course_key)
                if course_module is None:
                    return Response(status=status.HTTP_404_NOT_FOUND)
                result_filter.update({'course_id': course_key})
            except InvalidKeyError:
                error = build_api_error(
                    ugettext_noop("The supplied course id {course_id} is not valid."),
                    course_id=course_id_string,
                )
                return Response(error, status=status.HTTP_400_BAD_REQUEST)

            if not has_team_api_access(request.user, course_key):
                return Response(status=status.HTTP_403_FORBIDDEN)
        else:
            return Response(
                build_api_error(ugettext_noop("course_id must be provided")),
                status=status.HTTP_400_BAD_REQUEST
            )

        text_search = request.QUERY_PARAMS.get('text_search', None)
        if text_search and request.QUERY_PARAMS.get('order_by', None):
            return Response(
                build_api_error(ugettext_noop("text_search and order_by cannot be provided together")),
                status=status.HTTP_400_BAD_REQUEST
            )

        topic_id = request.QUERY_PARAMS.get('topic_id', None)
        if topic_id is not None:
            if topic_id not in [topic['id'] for topic in course_module.teams_configuration['topics']]:
                error = build_api_error(
                    ugettext_noop('The supplied topic id {topic_id} is not valid'),
                    topic_id=topic_id
                )
                return Response(error, status=status.HTTP_400_BAD_REQUEST)
            result_filter.update({'topic_id': topic_id})
        if text_search and CourseTeamIndexer.search_is_enabled():
            try:
                search_engine = CourseTeamIndexer.engine()
            except ElasticSearchConnectionError:
                return Response(
                    build_api_error(ugettext_noop('Error connecting to elasticsearch')),
                    status=status.HTTP_400_BAD_REQUEST
                )
            result_filter.update({'course_id': course_id_string})

            search_results = search_engine.search(
                query_string=text_search.encode('utf-8'),
                field_dictionary=result_filter,
                size=MAXIMUM_SEARCH_SIZE,
            )

            paginated_results = paginate_search_results(
                CourseTeam,
                search_results,
                self.get_paginate_by(),
                self.get_page()
            )
            serializer = self.get_pagination_serializer(paginated_results)
            tracker.emit('edx.team.searched', {
                "number_of_results": search_results['total'],
                "search_text": text_search,
                "topic_id": topic_id,
                "course_id": course_id_string,
            })
        else:
            queryset = CourseTeam.objects.filter(**result_filter)
            order_by_input = request.QUERY_PARAMS.get('order_by', 'name')
            if order_by_input == 'name':
                # MySQL does case-insensitive order_by.
                queryset = queryset.order_by('name')
            elif order_by_input == 'open_slots':
                queryset = queryset.order_by('team_size', '-last_activity_at')
            elif order_by_input == 'last_activity_at':
                queryset = queryset.order_by('-last_activity_at', 'team_size')
            else:
                return Response({
                    'developer_message': "unsupported order_by value {ordering}".format(ordering=order_by_input),
                    # Translators: 'ordering' is a string describing a way
                    # of ordering a list. For example, {ordering} may be
                    # 'name', indicating that the user wants to sort the
                    # list by lower case name.
                    'user_message': _(u"The ordering {ordering} is not supported").format(ordering=order_by_input),
                }, status=status.HTTP_400_BAD_REQUEST)

            page = self.paginate_queryset(queryset)
            serializer = self.get_pagination_serializer(page)
            serializer.context.update({'sort_order': order_by_input})  # pylint: disable=maybe-no-member

        return Response(serializer.data)  # pylint: disable=maybe-no-member
Exemplo n.º 20
0
    def get(self, request):
        """GET /api/team/v0/teams/"""
        result_filter = {
            'is_active': True
        }

        if 'course_id' in request.QUERY_PARAMS:
            course_id_string = request.QUERY_PARAMS['course_id']
            try:
                course_key = CourseKey.from_string(course_id_string)
                # Ensure the course exists
                course_module = modulestore().get_course(course_key)
                if course_module is None:
                    return Response(status=status.HTTP_404_NOT_FOUND)
                result_filter.update({'course_id': course_key})
            except InvalidKeyError:
                error = build_api_error(
                    ugettext_noop("The supplied course id {course_id} is not valid."),
                    course_id=course_id_string,
                )
                return Response(error, status=status.HTTP_400_BAD_REQUEST)

            if not has_team_api_access(request.user, course_key):
                return Response(status=status.HTTP_403_FORBIDDEN)
        else:
            return Response(
                build_api_error(ugettext_noop("course_id must be provided")),
                status=status.HTTP_400_BAD_REQUEST
            )

        if 'topic_id' in request.QUERY_PARAMS:
            topic_id = request.QUERY_PARAMS['topic_id']
            if topic_id not in [topic['id'] for topic in course_module.teams_configuration['topics']]:
                error = build_api_error(
                    ugettext_noop('The supplied topic id {topic_id} is not valid'),
                    topic_id=topic_id
                )
                return Response(error, status=status.HTTP_400_BAD_REQUEST)
            result_filter.update({'topic_id': request.QUERY_PARAMS['topic_id']})
        if 'include_inactive' in request.QUERY_PARAMS and request.QUERY_PARAMS['include_inactive'].lower() == 'true':
            del result_filter['is_active']
        if 'text_search' in request.QUERY_PARAMS:
            return Response(
                build_api_error(ugettext_noop("text_search is not yet supported.")),
                status=status.HTTP_400_BAD_REQUEST
            )

        queryset = CourseTeam.objects.filter(**result_filter)

        order_by_input = request.QUERY_PARAMS.get('order_by', 'name')
        if order_by_input == 'name':
            queryset = queryset.extra(select={'lower_name': "lower(name)"})
            order_by_field = 'lower_name'
        elif order_by_input == 'open_slots':
            queryset = queryset.annotate(team_size=Count('users'))
            order_by_field = 'team_size'
        elif order_by_input == 'last_activity':
            return Response(
                build_api_error(ugettext_noop("last_activity is not yet supported")),
                status=status.HTTP_400_BAD_REQUEST
            )
        else:
            return Response({
                'developer_message': "unsupported order_by value {ordering}".format(ordering=order_by_input),
                # Translators: 'ordering' is a string describing a way
                # of ordering a list. For example, {ordering} may be
                # 'name', indicating that the user wants to sort the
                # list by lower case name.
                'user_message': _(u"The ordering {ordering} is not supported").format(ordering=order_by_input),
            }, status=status.HTTP_400_BAD_REQUEST)

        queryset = queryset.order_by(order_by_field)

        # TODO: Remove this on update to Django 1.8
        # Use the cached length of the queryset in order to avoid
        # making an extra database call to get the number of items in
        # the collection
        paginator = self.paginator_class(queryset, self.get_paginate_by())
        paginator._count = len(queryset)  # pylint: disable=protected-access
        page = paginator.page(int(request.QUERY_PARAMS.get('page', 1)))
        # end TODO
        serializer = self.get_pagination_serializer(page)
        serializer.context.update({'sort_order': order_by_input})  # pylint: disable=maybe-no-member
        return Response(serializer.data)  # pylint: disable=maybe-no-member
Exemplo n.º 21
0
    def get(self, request):
        """GET /api/team/v0/teams/"""
        result_filter = {
            'is_active': True
        }

        if 'course_id' in request.QUERY_PARAMS:
            course_id_string = request.QUERY_PARAMS['course_id']
            try:
                course_key = CourseKey.from_string(course_id_string)
                # Ensure the course exists
                course_module = modulestore().get_course(course_key)
                if course_module is None:
                    return Response(status=status.HTTP_404_NOT_FOUND)
                result_filter.update({'course_id': course_key})
            except InvalidKeyError:
                error = build_api_error(
                    ugettext_noop("The supplied course id {course_id} is not valid."),
                    course_id=course_id_string,
                )
                return Response(error, status=status.HTTP_400_BAD_REQUEST)

            if not has_team_api_access(request.user, course_key):
                return Response(status=status.HTTP_403_FORBIDDEN)
        else:
            return Response(
                build_api_error(ugettext_noop("course_id must be provided")),
                status=status.HTTP_400_BAD_REQUEST
            )

        if 'topic_id' in request.QUERY_PARAMS:
            topic_id = request.QUERY_PARAMS['topic_id']
            if topic_id not in [topic['id'] for topic in course_module.teams_configuration['topics']]:
                error = build_api_error(
                    ugettext_noop('The supplied topic id {topic_id} is not valid'),
                    topic_id=topic_id
                )
                return Response(error, status=status.HTTP_400_BAD_REQUEST)
            result_filter.update({'topic_id': request.QUERY_PARAMS['topic_id']})
        if 'include_inactive' in request.QUERY_PARAMS and request.QUERY_PARAMS['include_inactive'].lower() == 'true':
            del result_filter['is_active']
        if 'text_search' in request.QUERY_PARAMS:
            return Response(
                build_api_error(ugettext_noop("text_search is not yet supported.")),
                status=status.HTTP_400_BAD_REQUEST
            )

        queryset = CourseTeam.objects.filter(**result_filter)

        order_by_input = request.QUERY_PARAMS.get('order_by', 'name')
        if order_by_input == 'name':
            queryset = queryset.extra(select={'lower_name': "lower(name)"})
            order_by_field = 'lower_name'
        elif order_by_input == 'open_slots':
            queryset = queryset.annotate(team_size=Count('users'))
            order_by_field = 'team_size'
        elif order_by_input == 'last_activity':
            return Response(
                build_api_error(ugettext_noop("last_activity is not yet supported")),
                status=status.HTTP_400_BAD_REQUEST
            )
        else:
            return Response({
                'developer_message': "unsupported order_by value {}".format(order_by_input),
                'user_message': _(u"The ordering {} is not supported").format(order_by_input),
            }, status=status.HTTP_400_BAD_REQUEST)

        queryset = queryset.order_by(order_by_field)

        page = self.paginate_queryset(queryset)
        serializer = self.get_pagination_serializer(page)
        serializer.context.update({'sort_order': order_by_input})  # pylint: disable=maybe-no-member
        return Response(serializer.data)  # pylint: disable=maybe-no-member
Exemplo n.º 22
0
    def get(self, request):
        """GET /api/team/v0/team_membership"""
        specified_username_or_team = False
        username = 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
            team_id = request.QUERY_PARAMS['team_id']
            try:
                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)

        if 'username' in request.QUERY_PARAMS:
            specified_username_or_team = True
            username = request.QUERY_PARAMS['username']
            if not request.user.is_staff:
                enrolled_courses = (CourseEnrollment.enrollments_for_user(
                    request.user).values_list('course_id', flat=True))
                staff_courses = (CourseAccessRole.objects.filter(
                    user=request.user, role='staff').values_list('course_id',
                                                                 flat=True))
                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(build_api_error(
                ugettext_noop("username or team_id must be specified.")),
                            status=status.HTTP_400_BAD_REQUEST)

        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
Exemplo n.º 23
0
    def get(self, request):
        """GET /api/team/v0/topics/?course_id={course_id}"""
        course_id_string = request.QUERY_PARAMS.get('course_id', None)
        if course_id_string is None:
            return Response(
                {
                    'field_errors': {
                        'course_id':
                        build_api_error(ugettext_noop(
                            "The supplied course id {course_id} is not valid."
                        ),
                                        course_id=course_id_string)
                    }
                },
                status=status.HTTP_400_BAD_REQUEST)

        try:
            course_id = CourseKey.from_string(course_id_string)
        except InvalidKeyError:
            return Response(status=status.HTTP_404_NOT_FOUND)

        # Ensure the course exists
        course_module = modulestore().get_course(course_id)
        if course_module is None:  # course is None if not found
            return Response(status=status.HTTP_404_NOT_FOUND)

        if not has_team_api_access(request.user, course_id):
            return Response(status=status.HTTP_403_FORBIDDEN)

        ordering = request.QUERY_PARAMS.get('order_by', 'name')
        if ordering not in ['name', 'team_count']:
            return Response(
                {
                    'developer_message':
                    "unsupported order_by value {ordering}".format(
                        ordering=ordering),
                    # Translators: 'ordering' is a string describing a way
                    # of ordering a list. For example, {ordering} may be
                    # 'name', indicating that the user wants to sort the
                    # list by lower case name.
                    'user_message':
                    _(u"The ordering {ordering} is not supported").format(
                        ordering=ordering),
                },
                status=status.HTTP_400_BAD_REQUEST)

        # Always sort alphabetically, as it will be used as secondary sort
        # in the case of "team_count".
        topics = get_alphabetical_topics(course_module)
        if ordering == 'team_count':
            add_team_count(topics, course_id)
            topics.sort(key=lambda t: t['team_count'], reverse=True)
            page = self.paginate_queryset(topics)
            # Since team_count has already been added to all the topics, use PaginatedTopicSerializer.
            # Even though sorting is done outside of the serializer, sort_order needs to be passed
            # to the serializer so that the paginated results indicate how they were sorted.
            serializer = PaginatedTopicSerializer(page,
                                                  context={
                                                      'course_id': course_id,
                                                      'sort_order': ordering
                                                  })
        else:
            page = self.paginate_queryset(topics)
            # Use the serializer that adds team_count in a bulk operation per page.
            serializer = BulkTeamCountPaginatedTopicSerializer(
                page, context={
                    'course_id': course_id,
                    'sort_order': ordering
                })

        return Response(serializer.data)
Exemplo n.º 24
0
    def post(self, request):
        """POST /api/team/v0/team_membership"""
        field_errors = {}

        if "username" not in request.DATA:
            field_errors["username"] = build_api_error(ugettext_noop("Username is required."))

        if "team_id" not in request.DATA:
            field_errors["team_id"] = build_api_error(ugettext_noop("Team id is required."))

        if field_errors:
            return Response({"field_errors": field_errors}, status=status.HTTP_400_BAD_REQUEST)

        try:
            team = CourseTeam.objects.get(team_id=request.DATA["team_id"])
        except CourseTeam.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        username = request.DATA["username"]
        if not has_team_api_access(request.user, team.course_id, access_username=username):
            return Response(status=status.HTTP_404_NOT_FOUND)

        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        course_module = modulestore().get_course(team.course_id)
        if course_module.teams_max_size is not None and team.users.count() >= course_module.teams_max_size:
            return Response(
                build_api_error(ugettext_noop("This team is already full.")), status=status.HTTP_400_BAD_REQUEST
            )

        try:
            membership = team.add_user(user)
            emit_team_event(
                "edx.team.learner_added",
                team.course_id,
                {
                    "team_id": team.team_id,
                    "user_id": user.id,
                    "add_method": "joined_from_team_view" if user == request.user else "added_by_another_user",
                },
            )
        except AlreadyOnTeamInCourse:
            return Response(
                build_api_error(
                    ugettext_noop("The user {username} is already a member of a team in this course."),
                    username=username,
                ),
                status=status.HTTP_400_BAD_REQUEST,
            )
        except NotEnrolledInCourseForTeam:
            return Response(
                build_api_error(
                    ugettext_noop("The user {username} is not enrolled in the course associated with this team."),
                    username=username,
                ),
                status=status.HTTP_400_BAD_REQUEST,
            )

        serializer = self.get_serializer(instance=membership)
        return Response(serializer.data)
Exemplo n.º 25
0
    def get(self, request):
        """GET /api/team/v0/teams/"""
        result_filter = {'is_active': True}

        if 'course_id' in request.QUERY_PARAMS:
            course_id_string = request.QUERY_PARAMS['course_id']
            try:
                course_key = CourseKey.from_string(course_id_string)
                # Ensure the course exists
                course_module = modulestore().get_course(course_key)
                if course_module is None:
                    return Response(status=status.HTTP_404_NOT_FOUND)
                result_filter.update({'course_id': course_key})
            except InvalidKeyError:
                error = build_api_error(
                    ugettext_noop(
                        "The supplied course id {course_id} is not valid."),
                    course_id=course_id_string,
                )
                return Response(error, status=status.HTTP_400_BAD_REQUEST)

            if not has_team_api_access(request.user, course_key):
                return Response(status=status.HTTP_403_FORBIDDEN)
        else:
            return Response(build_api_error(
                ugettext_noop("course_id must be provided")),
                            status=status.HTTP_400_BAD_REQUEST)

        if 'text_search' in request.QUERY_PARAMS and 'order_by' in request.QUERY_PARAMS:
            return Response(build_api_error(
                ugettext_noop(
                    "text_search and order_by cannot be provided together")),
                            status=status.HTTP_400_BAD_REQUEST)

        if 'topic_id' in request.QUERY_PARAMS:
            topic_id = request.QUERY_PARAMS['topic_id']
            if topic_id not in [
                    topic['id']
                    for topic in course_module.teams_configuration['topics']
            ]:
                error = build_api_error(ugettext_noop(
                    'The supplied topic id {topic_id} is not valid'),
                                        topic_id=topic_id)
                return Response(error, status=status.HTTP_400_BAD_REQUEST)
            result_filter.update(
                {'topic_id': request.QUERY_PARAMS['topic_id']})
        if 'include_inactive' in request.QUERY_PARAMS and request.QUERY_PARAMS[
                'include_inactive'].lower() == 'true':
            del result_filter['is_active']

        if 'text_search' in request.QUERY_PARAMS and CourseTeamIndexer.search_is_enabled(
        ):
            search_engine = CourseTeamIndexer.engine()
            text_search = request.QUERY_PARAMS['text_search'].encode('utf-8')
            result_filter.update({'course_id': course_id_string})

            search_results = search_engine.search(
                query_string=text_search,
                field_dictionary=result_filter,
                size=MAXIMUM_SEARCH_SIZE,
            )

            paginated_results = paginate_search_results(
                CourseTeam, search_results, self.get_paginate_by(),
                self.get_page())

            serializer = self.get_pagination_serializer(paginated_results)
        else:
            queryset = CourseTeam.objects.filter(**result_filter)
            order_by_input = request.QUERY_PARAMS.get('order_by', 'name')
            if order_by_input == 'name':
                queryset = queryset.extra(select={'lower_name': "lower(name)"})
                queryset = queryset.order_by('lower_name')
            elif order_by_input == 'open_slots':
                queryset = queryset.annotate(team_size=Count('users'))
                queryset = queryset.order_by('team_size', '-last_activity_at')
            elif order_by_input == 'last_activity_at':
                queryset = queryset.annotate(team_size=Count('users'))
                queryset = queryset.order_by('-last_activity_at', 'team_size')
            else:
                return Response(
                    {
                        'developer_message':
                        "unsupported order_by value {ordering}".format(
                            ordering=order_by_input),
                        # Translators: 'ordering' is a string describing a way
                        # of ordering a list. For example, {ordering} may be
                        # 'name', indicating that the user wants to sort the
                        # list by lower case name.
                        'user_message':
                        _(u"The ordering {ordering} is not supported").format(
                            ordering=order_by_input),
                    },
                    status=status.HTTP_400_BAD_REQUEST)

            page = self.paginate_queryset(queryset)
            serializer = self.get_pagination_serializer(page)
            serializer.context.update({'sort_order': order_by_input})  # pylint: disable=maybe-no-member

        return Response(serializer.data)  # pylint: disable=maybe-no-member
Exemplo n.º 26
0
    def get(self, request):
        """GET /api/team/v0/teams/"""
        result_filter = {'is_active': True}

        if 'course_id' in request.QUERY_PARAMS:
            course_id_string = request.QUERY_PARAMS['course_id']
            try:
                course_key = CourseKey.from_string(course_id_string)
                # Ensure the course exists
                course_module = modulestore().get_course(course_key)
                if course_module is None:
                    return Response(status=status.HTTP_404_NOT_FOUND)
                result_filter.update({'course_id': course_key})
            except InvalidKeyError:
                error = build_api_error(
                    ugettext_noop(
                        "The supplied course id {course_id} is not valid."),
                    course_id=course_id_string,
                )
                return Response(error, status=status.HTTP_400_BAD_REQUEST)

            if not has_team_api_access(request.user, course_key):
                return Response(status=status.HTTP_403_FORBIDDEN)
        else:
            return Response(build_api_error(
                ugettext_noop("course_id must be provided")),
                            status=status.HTTP_400_BAD_REQUEST)

        if 'topic_id' in request.QUERY_PARAMS:
            topic_id = request.QUERY_PARAMS['topic_id']
            if topic_id not in [
                    topic['id']
                    for topic in course_module.teams_configuration['topics']
            ]:
                error = build_api_error(ugettext_noop(
                    'The supplied topic id {topic_id} is not valid'),
                                        topic_id=topic_id)
                return Response(error, status=status.HTTP_400_BAD_REQUEST)
            result_filter.update(
                {'topic_id': request.QUERY_PARAMS['topic_id']})
        if 'include_inactive' in request.QUERY_PARAMS and request.QUERY_PARAMS[
                'include_inactive'].lower() == 'true':
            del result_filter['is_active']
        if 'text_search' in request.QUERY_PARAMS:
            return Response(build_api_error(
                ugettext_noop("text_search is not yet supported.")),
                            status=status.HTTP_400_BAD_REQUEST)

        queryset = CourseTeam.objects.filter(**result_filter)

        order_by_input = request.QUERY_PARAMS.get('order_by', 'name')
        if order_by_input == 'name':
            queryset = queryset.extra(select={'lower_name': "lower(name)"})
            order_by_field = 'lower_name'
        elif order_by_input == 'open_slots':
            queryset = queryset.annotate(team_size=Count('users'))
            order_by_field = 'team_size'
        elif order_by_input == 'last_activity':
            return Response(build_api_error(
                ugettext_noop("last_activity is not yet supported")),
                            status=status.HTTP_400_BAD_REQUEST)
        else:
            return Response(
                {
                    'developer_message':
                    "unsupported order_by value {ordering}".format(
                        ordering=order_by_input),
                    # Translators: 'ordering' is a string describing a way
                    # of ordering a list. For example, {ordering} may be
                    # 'name', indicating that the user wants to sort the
                    # list by lower case name.
                    'user_message':
                    _(u"The ordering {ordering} is not supported").format(
                        ordering=order_by_input),
                },
                status=status.HTTP_400_BAD_REQUEST)

        queryset = queryset.order_by(order_by_field)

        # TODO: Remove this on update to Django 1.8
        # Use the cached length of the queryset in order to avoid
        # making an extra database call to get the number of items in
        # the collection
        paginator = self.paginator_class(queryset, self.get_paginate_by())
        paginator._count = len(queryset)  # pylint: disable=protected-access
        page = paginator.page(int(request.QUERY_PARAMS.get('page', 1)))
        # end TODO
        serializer = self.get_pagination_serializer(page)
        serializer.context.update({'sort_order': order_by_input})  # pylint: disable=maybe-no-member
        return Response(serializer.data)  # pylint: disable=maybe-no-member