コード例 #1
0
ファイル: api.py プロジェクト: zamanafzal/edx-platform
def _get_thread_and_context(request, thread_id, retrieve_kwargs=None):
    """
    Retrieve the given thread and build a serializer context for it, returning
    both. This function also enforces access control for the thread (checking
    both the user's access to the course and to the thread's cohort if
    applicable). Raises ThreadNotFoundError if the thread does not exist or the
    user cannot access it.
    """
    retrieve_kwargs = retrieve_kwargs or {}
    try:
        if "with_responses" not in retrieve_kwargs:
            retrieve_kwargs["with_responses"] = False
        if "mark_as_read" not in retrieve_kwargs:
            retrieve_kwargs["mark_as_read"] = False
        cc_thread = Thread(id=thread_id).retrieve(**retrieve_kwargs)
        course_key = CourseKey.from_string(cc_thread["course_id"])
        course = _get_course(course_key, request.user)
        context = get_context(course, request, cc_thread)
        course_discussion_settings = get_course_discussion_settings(course_key)
        if (not context["is_requester_privileged"]
                and cc_thread["group_id"] and is_commentable_divided(
                    course.id, cc_thread["commentable_id"],
                    course_discussion_settings)):
            requester_group_id = get_group_id_for_user(
                request.user, course_discussion_settings)
            if requester_group_id is not None and cc_thread[
                    "group_id"] != requester_group_id:
                raise ThreadNotFoundError("Thread not found.")
        return cc_thread, context
    except CommentClientRequestError:
        # params are validated at a higher level, so the only possible request
        # error is if the thread doesn't exist
        raise ThreadNotFoundError("Thread not found.")
コード例 #2
0
ファイル: api.py プロジェクト: mrstephencollins/edx-platform
def get_thread_list(request, course_key, page, page_size, topic_id_list=None, text_search=None, following=False):
    """
    Return the list of all discussion threads pertaining to the given course

    Parameters:

    request: The django request objects used for build_absolute_uri
    course_key: The key of the course to get discussion threads for
    page: The page number (1-indexed) to retrieve
    page_size: The number of threads to retrieve per page
    topic_id_list: The list of topic_ids to get the discussion threads for
    text_search A text search query string to match
    following: If true, retrieve only threads the requester is following

    Note that topic_id_list, text_search, and following are mutually exclusive.

    Returns:

    A paginated result containing a list of threads; see
    discussion_api.views.ThreadViewSet for more detail.

    Raises:

    ValueError: if more than one of the mutually exclusive parameters is
      provided
    Http404: if the requesting user does not have access to the requested course
      or a page beyond the last is requested
    """
    exclusive_param_count = sum(1 for param in [topic_id_list, text_search, following] if param)
    if exclusive_param_count > 1:  # pragma: no cover
        raise ValueError("More than one mutually exclusive param passed to get_thread_list")

    course = _get_course_or_404(course_key, request.user)
    context = get_context(course, request)
    query_params = {
        "group_id": (None if context["is_requester_privileged"] else get_cohort_id(request.user, course.id)),
        "sort_key": "date",
        "sort_order": "desc",
        "page": page,
        "per_page": page_size,
        "text": text_search,
    }
    text_search_rewrite = None
    if following:
        threads, result_page, num_pages = context["cc_requester"].subscribed_threads(query_params)
    else:
        query_params["course_id"] = unicode(course.id)
        query_params["commentable_ids"] = ",".join(topic_id_list) if topic_id_list else None
        query_params["text"] = text_search
        threads, result_page, num_pages, text_search_rewrite = Thread.search(query_params)
    # The comments service returns the last page of results if the requested
    # page is beyond the last page, but we want be consistent with DRF's general
    # behavior and return a 404 in that case
    if result_page != page:
        raise Http404

    results = [ThreadSerializer(thread, context=context).data for thread in threads]
    ret = get_paginated_data(request, results, page, num_pages)
    ret["text_search_rewrite"] = text_search_rewrite
    return ret
コード例 #3
0
 def setUp(self):
     super(ThreadSerializerDeserializationTest, self).setUp()
     httpretty.reset()
     httpretty.enable()
     self.addCleanup(httpretty.reset)
     self.addCleanup(httpretty.disable)
     self.user = UserFactory.create()
     self.register_get_user_response(self.user)
     self.request = RequestFactory().get("/dummy")
     self.request.user = self.user
     self.minimal_data = {
         "course_id": unicode(self.course.id),
         "topic_id": "test_topic",
         "type": "discussion",
         "title": "Test Title",
         "raw_body": "Test body",
     }
     self.existing_thread = Thread(
         **make_minimal_cs_thread({
             "id": "existing_thread",
             "course_id": unicode(self.course.id),
             "commentable_id": "original_topic",
             "thread_type": "discussion",
             "title": "Original Title",
             "body": "Original body",
             "user_id": str(self.user.id),
             "username": self.user.username,
             "read": "False",
             "endorsed": "False"
         }))
コード例 #4
0
ファイル: serializers.py プロジェクト: lydia-lee/edx-platform
 def restore_object(self, attrs, instance=None):
     if instance:
         for key, val in attrs.items():
             instance[key] = val
         return instance
     else:
         return Thread(user_id=self.context["cc_requester"]["id"], **attrs)
コード例 #5
0
ファイル: test_permissions.py プロジェクト: gopinath81/vmss
 def test_comment(self, is_author, is_thread_author, is_privileged):
     comment = Comment(user_id="5" if is_author else "6")
     context = _get_context(
         requester_id="5",
         is_requester_privileged=is_privileged,
         thread=Thread(user_id="5" if is_thread_author else "6"))
     self.assertEqual(can_delete(comment, context), is_author
                      or is_privileged)
コード例 #6
0
 def test_thread(self, is_author, is_privileged):
     thread = Thread(user_id="5" if is_author else "6", type="thread")
     context = _get_context(requester_id="5",
                            is_requester_privileged=is_privileged)
     actual = get_editable_fields(thread, context)
     expected = {"abuse_flagged", "following", "voted"}
     if is_author or is_privileged:
         expected |= {"topic_id", "type", "title", "raw_body"}
     self.assertEqual(actual, expected)
コード例 #7
0
ファイル: api.py プロジェクト: happymark001/edx-platform
def get_thread_list(request, course, page, page_size):
    """
    Return the list of all discussion threads pertaining to the given course

    Parameters:

    request: The django request objects used for build_absolute_uri
    course: The course to get discussion threads for
    page: The page number (1-indexed) to retrieve
    page_size: The number of threads to retrieve per page

    Returns:

    A paginated result containing a list of threads; see
    discussion_api.views.ThreadViewSet for more detail.
    """
    user_is_privileged = Role.objects.filter(
        course_id=course.id,
        name__in=[FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA],
        users=request.user
    ).exists()
    cc_user = User.from_django_user(request.user).retrieve()
    threads, result_page, num_pages, _ = Thread.search({
        "course_id": unicode(course.id),
        "group_id": None if user_is_privileged else get_cohort_id(request.user, course.id),
        "sort_key": "date",
        "sort_order": "desc",
        "page": page,
        "per_page": page_size,
    })
    # The comments service returns the last page of results if the requested
    # page is beyond the last page, but we want be consistent with DRF's general
    # behavior and return a 404 in that case
    if result_page != page:
        raise Http404
    # TODO: cache staff_user_ids and ta_user_ids if we need to improve perf
    staff_user_ids = {
        user.id
        for role in Role.objects.filter(
            name__in=[FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR],
            course_id=course.id
        )
        for user in role.users.all()
    }
    ta_user_ids = {
        user.id
        for role in Role.objects.filter(name=FORUM_ROLE_COMMUNITY_TA, course_id=course.id)
        for user in role.users.all()
    }
    # For now, the only groups are cohorts
    group_ids_to_names = get_cohort_names(course)

    results = [
        _cc_thread_to_api_thread(thread, cc_user, staff_user_ids, ta_user_ids, group_ids_to_names)
        for thread in threads
    ]
    return get_paginated_data(request, results, page, num_pages)
コード例 #8
0
def get_initializable_thread_fields(context):
    """
    Return the set of fields that the requester can initialize for a thread

    Any field that is editable by the author should also be initializable.
    """
    ret = get_editable_fields(
        Thread(user_id=context["cc_requester"]["id"], type="thread"), context)
    ret |= NON_UPDATABLE_THREAD_FIELDS
    return ret
コード例 #9
0
 def test_pinned_missing(self):
     """
     Make sure that older threads in the comments service without the pinned
     field do not break serialization
     """
     thread_data = self.make_cs_content({})
     del thread_data["pinned"]
     self.register_get_thread_response(thread_data)
     serialized = self.serialize(Thread(id=thread_data["id"]))
     self.assertEqual(serialized["pinned"], False)
コード例 #10
0
ファイル: test_permissions.py プロジェクト: gopinath81/vmss
 def test_comment(self, is_thread_author, thread_type, is_privileged):
     context = _get_context(requester_id="5",
                            is_requester_privileged=is_privileged,
                            thread=Thread(
                                user_id="5" if is_thread_author else "6",
                                thread_type=thread_type))
     actual = get_initializable_comment_fields(context)
     expected = {
         "abuse_flagged", "parent_id", "raw_body", "thread_id", "voted"
     }
     if (is_thread_author and thread_type == "question") or is_privileged:
         expected |= {"endorsed"}
     self.assertEqual(actual, expected)
コード例 #11
0
ファイル: api.py プロジェクト: yiakwy/edx-platform
def get_thread_list(request, course_key, page, page_size):
    """
    Return the list of all discussion threads pertaining to the given course

    Parameters:

    request: The django request objects used for build_absolute_uri
    course_key: The key of the course to get discussion threads for
    page: The page number (1-indexed) to retrieve
    page_size: The number of threads to retrieve per page

    Returns:

    A paginated result containing a list of threads; see
    discussion_api.views.ThreadViewSet for more detail.
    """
    user_is_privileged = Role.objects.filter(course_id=course_key,
                                             name__in=[
                                                 FORUM_ROLE_ADMINISTRATOR,
                                                 FORUM_ROLE_MODERATOR,
                                                 FORUM_ROLE_COMMUNITY_TA
                                             ],
                                             users=request.user).exists()
    threads, result_page, num_pages, _ = Thread.search({
        "course_id":
        unicode(course_key),
        "group_id":
        None
        if user_is_privileged else get_cohort_id(request.user, course_key),
        "sort_key":
        "date",
        "sort_order":
        "desc",
        "page":
        page,
        "per_page":
        page_size,
    })
    # The comments service returns the last page of results if the requested
    # page is beyond the last page, but we want be consistent with DRF's general
    # behavior and return a 404 in that case
    if result_page != page:
        raise Http404

    results = [_cc_thread_to_api_thread(thread) for thread in threads]
    return get_paginated_data(request, results, page, num_pages)
コード例 #12
0
ファイル: api.py プロジェクト: AnshitMehrotra/edx-platform-1
def get_thread_list(request, course_key, page, page_size):
    """
    Return the list of all discussion threads pertaining to the given course

    Parameters:

    request: The django request objects used for build_absolute_uri
    course_key: The key of the course to get discussion threads for
    page: The page number (1-indexed) to retrieve
    page_size: The number of threads to retrieve per page

    Returns:

    A paginated result containing a list of threads; see
    discussion_api.views.ThreadViewSet for more detail.
    """
    course = _get_course_or_404(course_key, request.user)
    context = get_context(course, request)
    threads, result_page, num_pages, _ = Thread.search({
        "course_id":
        unicode(course.id),
        "group_id":
        (None if context["is_requester_privileged"] else get_cohort_id(
            request.user, course.id)),
        "sort_key":
        "date",
        "sort_order":
        "desc",
        "page":
        page,
        "per_page":
        page_size,
    })
    # The comments service returns the last page of results if the requested
    # page is beyond the last page, but we want be consistent with DRF's general
    # behavior and return a 404 in that case
    if result_page != page:
        raise Http404

    results = [
        ThreadSerializer(thread, context=context).data for thread in threads
    ]
    return get_paginated_data(request, results, page, num_pages)
コード例 #13
0
def get_section_list(request,course_id,student_id):
    section_id_dict = {}
    commentable_id_list = []
    try:
        course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    except Exception as e:
        return Resposne(
            data={
            "Error": e.message
        })

    course = get_course_by_id(course_key)
    with modulestore().bulk_operations(course.id):
        course_module = get_module_for_descriptor(
            request.user, request, course, None, course.id, course=course
        )
        if course_module is None:
            return Response(
                data={
                "Error":"User is not allowed to do the operation"
            })

    student = User.objects.get(id=student_id)
    query_params = {
    "course_id":course_id,
    "user_id": student.id,
    }
    threads = Thread.search(query_params).collection

    for chapter in course_module.get_children():
        for section in chapter.get_children():
            for unit in section.get_children():
                for vertical in unit.get_children():
                    if vertical.category == 'discussion':
                        participated = False
                        for thread in threads:
                            if thread['commentable_id'] == vertical.discussion_id:
                                participated = thread['username'] == student.username
                        section_id_dict.update({chapter.url_name: participated})

    return section_id_dict
コード例 #14
0
ファイル: api.py プロジェクト: mtorrisi/edx-platform
def get_thread_list(request, course_key, page, page_size, topic_id_list=None):
    """
    Return the list of all discussion threads pertaining to the given course

    Parameters:

    request: The django request objects used for build_absolute_uri
    course_key: The key of the course to get discussion threads for
    page: The page number (1-indexed) to retrieve
    page_size: The number of threads to retrieve per page
    topic_id_list: The list of topic_ids to get the discussion threads for

    Returns:

    A paginated result containing a list of threads; see
    discussion_api.views.ThreadViewSet for more detail.
    """
    course = _get_course_or_404(course_key, request.user)
    context = get_context(course, request)
    topic_ids_csv = ",".join(topic_id_list) if topic_id_list else None
    threads, result_page, num_pages, _ = Thread.search({
        "course_id": unicode(course.id),
        "group_id": (
            None if context["is_requester_privileged"] else
            get_cohort_id(request.user, course.id)
        ),
        "sort_key": "date",
        "sort_order": "desc",
        "page": page,
        "per_page": page_size,
        "commentable_ids": topic_ids_csv,
    })
    # The comments service returns the last page of results if the requested
    # page is beyond the last page, but we want be consistent with DRF's general
    # behavior and return a 404 in that case
    if result_page != page:
        raise Http404

    results = [ThreadSerializer(thread, context=context).data for thread in threads]
    return get_paginated_data(request, results, page, num_pages)
コード例 #15
0
ファイル: api.py プロジェクト: unicri/edx-platform
def get_thread_list(request, course_key, page, page_size):
    """
    Return the list of all discussion threads pertaining to the given course

    Parameters:

    request: The django request objects used for build_absolute_uri
    course_key: The key of the course to get discussion threads for
    page: The page number (1-indexed) to retrieve
    page_size: The number of threads to retrieve per page

    Returns:

    A paginated result containing a list of threads; see
    discussion_api.views.ThreadViewSet for more detail.
    """
    user_is_privileged = Role.objects.filter(
        course_id=course_key,
        name__in=[FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA],
        users=request.user
    ).exists()
    threads, result_page, num_pages, _ = Thread.search({
        "course_id": unicode(course_key),
        "group_id": None if user_is_privileged else get_cohort_id(request.user, course_key),
        "sort_key": "date",
        "sort_order": "desc",
        "page": page,
        "per_page": page_size,
    })
    # The comments service returns the last page of results if the requested
    # page is beyond the last page, but we want be consistent with DRF's general
    # behavior and return a 404 in that case
    if result_page != page:
        raise Http404

    results = [_cc_thread_to_api_thread(thread) for thread in threads]
    return get_paginated_data(request, results, page, num_pages)
コード例 #16
0
ファイル: serializers.py プロジェクト: Qubad786/edx-platform
 def create(self, validated_data):
     thread = Thread(user_id=self.context["cc_requester"]["id"], **validated_data)
     thread.save()
     return thread
コード例 #17
0
ファイル: api.py プロジェクト: singhularity/edx-platform
def get_thread_list(
        request,
        course_key,
        page,
        page_size,
        topic_id_list=None,
        text_search=None,
        following=False,
        view=None,
        order_by="last_activity_at",
        order_direction="desc",
):
    """
    Return the list of all discussion threads pertaining to the given course

    Parameters:

    request: The django request objects used for build_absolute_uri
    course_key: The key of the course to get discussion threads for
    page: The page number (1-indexed) to retrieve
    page_size: The number of threads to retrieve per page
    topic_id_list: The list of topic_ids to get the discussion threads for
    text_search A text search query string to match
    following: If true, retrieve only threads the requester is following
    view: filters for either "unread" or "unanswered" threads
    order_by: The key in which to sort the threads by. The only values are
        "last_activity_at", "comment_count", and "vote_count". The default is
        "last_activity_at".
    order_direction: The direction in which to sort the threads by. The only
        values are "asc" or "desc". The default is "desc".

    Note that topic_id_list, text_search, and following are mutually exclusive.

    Returns:

    A paginated result containing a list of threads; see
    discussion_api.views.ThreadViewSet for more detail.

    Raises:

    ValidationError: if an invalid value is passed for a field.
    ValueError: if more than one of the mutually exclusive parameters is
      provided
    Http404: if the requesting user does not have access to the requested course
      or a page beyond the last is requested
    """
    exclusive_param_count = sum(1 for param in [topic_id_list, text_search, following] if param)
    if exclusive_param_count > 1:  # pragma: no cover
        raise ValueError("More than one mutually exclusive param passed to get_thread_list")

    cc_map = {"last_activity_at": "date", "comment_count": "comments", "vote_count": "votes"}
    if order_by not in cc_map:
        raise ValidationError({
            "order_by":
                ["Invalid value. '{}' must be 'last_activity_at', 'comment_count', or 'vote_count'".format(order_by)]
        })
    if order_direction not in ["asc", "desc"]:
        raise ValidationError({
            "order_direction": ["Invalid value. '{}' must be 'asc' or 'desc'".format(order_direction)]
        })

    course = _get_course_or_404(course_key, request.user)
    context = get_context(course, request)

    query_params = {
        "user_id": unicode(request.user.id),
        "group_id": (
            None if context["is_requester_privileged"] else
            get_cohort_id(request.user, course.id)
        ),
        "page": page,
        "per_page": page_size,
        "text": text_search,
        "sort_key": cc_map.get(order_by),
        "sort_order": order_direction,
    }

    text_search_rewrite = None

    if view:
        if view in ["unread", "unanswered"]:
            query_params[view] = "true"
        else:
            ValidationError({
                "view": ["Invalid value. '{}' must be 'unread' or 'unanswered'".format(view)]
            })

    if following:
        threads, result_page, num_pages = context["cc_requester"].subscribed_threads(query_params)
    else:
        query_params["course_id"] = unicode(course.id)
        query_params["commentable_ids"] = ",".join(topic_id_list) if topic_id_list else None
        query_params["text"] = text_search
        threads, result_page, num_pages, text_search_rewrite = Thread.search(query_params)
    # The comments service returns the last page of results if the requested
    # page is beyond the last page, but we want be consistent with DRF's general
    # behavior and return a 404 in that case
    if result_page != page:
        raise Http404

    results = [ThreadSerializer(thread, context=context).data for thread in threads]
    ret = get_paginated_data(request, results, page, num_pages)
    ret["text_search_rewrite"] = text_search_rewrite
    return ret
コード例 #18
0
ファイル: api.py プロジェクト: gopinath81/vmss
def get_thread_list(
    request,
    course_key,
    page,
    page_size,
    topic_id_list=None,
    text_search=None,
    following=False,
    view=None,
    order_by="last_activity_at",
    order_direction="desc",
    requested_fields=None,
):
    """
    Return the list of all discussion threads pertaining to the given course

    Parameters:

    request: The django request objects used for build_absolute_uri
    course_key: The key of the course to get discussion threads for
    page: The page number (1-indexed) to retrieve
    page_size: The number of threads to retrieve per page
    topic_id_list: The list of topic_ids to get the discussion threads for
    text_search A text search query string to match
    following: If true, retrieve only threads the requester is following
    view: filters for either "unread" or "unanswered" threads
    order_by: The key in which to sort the threads by. The only values are
        "last_activity_at", "comment_count", and "vote_count". The default is
        "last_activity_at".
    order_direction: The direction in which to sort the threads by. The default
        and only value is "desc". This will be removed in a future major
        version.
    requested_fields: Indicates which additional fields to return
        for each thread. (i.e. ['profile_image'])

    Note that topic_id_list, text_search, and following are mutually exclusive.

    Returns:

    A paginated result containing a list of threads; see
    discussion_api.views.ThreadViewSet for more detail.

    Raises:

    ValidationError: if an invalid value is passed for a field.
    ValueError: if more than one of the mutually exclusive parameters is
      provided
    CourseNotFoundError: if the requesting user does not have access to the requested course
    PageNotFoundError: if page requested is beyond the last
    """
    exclusive_param_count = sum(
        1 for param in [topic_id_list, text_search, following] if param)
    if exclusive_param_count > 1:  # pragma: no cover
        raise ValueError(
            "More than one mutually exclusive param passed to get_thread_list")

    cc_map = {
        "last_activity_at": "activity",
        "comment_count": "comments",
        "vote_count": "votes"
    }
    if order_by not in cc_map:
        raise ValidationError({
            "order_by": [
                "Invalid value. '{}' must be 'last_activity_at', 'comment_count', or 'vote_count'"
                .format(order_by)
            ]
        })
    if order_direction != "desc":
        raise ValidationError({
            "order_direction":
            ["Invalid value. '{}' must be 'desc'".format(order_direction)]
        })

    course = _get_course(course_key, request.user)
    context = get_context(course, request)

    query_params = {
        "user_id":
        unicode(request.user.id),
        "group_id":
        (None if context["is_requester_privileged"] else get_cohort_id(
            request.user, course.id)),
        "page":
        page,
        "per_page":
        page_size,
        "text":
        text_search,
        "sort_key":
        cc_map.get(order_by),
    }

    if view:
        if view in ["unread", "unanswered"]:
            query_params[view] = "true"
        else:
            ValidationError({
                "view": [
                    "Invalid value. '{}' must be 'unread' or 'unanswered'".
                    format(view)
                ]
            })

    if following:
        paginated_results = context["cc_requester"].subscribed_threads(
            query_params)
    else:
        query_params["course_id"] = unicode(course.id)
        query_params["commentable_ids"] = ",".join(
            topic_id_list) if topic_id_list else None
        query_params["text"] = text_search
        paginated_results = Thread.search(query_params)
    # The comments service returns the last page of results if the requested
    # page is beyond the last page, but we want be consistent with DRF's general
    # behavior and return a PageNotFoundError in that case
    if paginated_results.page != page:
        raise PageNotFoundError("Page not found (No results on this page).")

    results = _serialize_discussion_entities(request, context,
                                             paginated_results.collection,
                                             requested_fields,
                                             DiscussionEntity.thread)

    paginator = DiscussionAPIPagination(request, paginated_results.page,
                                        paginated_results.num_pages,
                                        paginated_results.thread_count)
    return paginator.get_paginated_response({
        "results":
        results,
        "text_search_rewrite":
        paginated_results.corrected_text,
    })
コード例 #19
0
 def create(self, validated_data):
     thread = Thread(user_id=self.context["cc_requester"]["id"],
                     **validated_data)
     thread.save()
     return thread
コード例 #20
0
    def get(self, request, course_id, section_id):
        try:
            course_key = SlashSeparatedCourseKey.from_deprecated_string(
                course_id)
        except Exception as e:
            return Resposne(data={"Error": e.message})

        course = get_course_by_id(course_key)
        with modulestore().bulk_operations(course.id):
            course_module = get_module_for_descriptor(request.user,
                                                      request,
                                                      course,
                                                      None,
                                                      course.id,
                                                      course=course)
            if course_module is None:
                return Response(
                    data={"Error": "User is not allowed to do the operation"})

        commentable_id_list = []
        for chapter in course_module.get_children():
            for section in chapter.get_children():
                if section_id == section.url_name:
                    for unit in section.get_children():
                        for vertical in unit.get_children():
                            if vertical.category == 'discussion':
                                commentable_id_list.append(
                                    vertical.discussion_id)
                    break

        count = 0
        for cid in commentable_id_list:
            query_params = {
                "course_id": course_id,
                "user_id": request.user.id,
                "commentable_id": cid
            }
            threads = Thread.search(query_params).collection
            for thread in threads:
                if thread['thread_type'] == "discussion":
                    request.GET = {'thread_id': thread['id']}
                elif thread['thread_type'] == "question":
                    request.GET = {
                        'thread_id': thread['id'],
                        'endorsed': False
                    }
                else:
                    pass
                if thread['username'] == request.user.username:
                    count = count + 1
                list_comments = CommentViewSet()
                comments = list_comments.list(request).data
                for comment in comments['results']:
                    if comment['author'] == request.user.username:
                        count = count + 1

                    if comment['child_count'] > 0:
                        child_comments = list_comments.retrieve(
                            request, comment_id=comment['id']).data
                        for child_comment in child_comments['results']:
                            if child_comment[
                                    'author'] == request.user.username:
                                count = count + 1
            return Response(
                data={
                    "Course_id": course_id,
                    "Section_id": section_id,
                    "User": request.user.username,
                    "Comment Count": count,
                })
        else:
            return Response(
                data={"Error": "No active discussion for given section_id"})
コード例 #21
0
ファイル: test_permissions.py プロジェクト: gopinath81/vmss
 def test_thread(self, is_author, is_privileged):
     thread = Thread(user_id="5" if is_author else "6")
     context = _get_context(requester_id="5",
                            is_requester_privileged=is_privileged)
     self.assertEqual(can_delete(thread, context), is_author
                      or is_privileged)
コード例 #22
0
 def test_response_count_missing(self):
     thread_data = self.make_cs_content({})
     del thread_data["resp_total"]
     self.register_get_thread_response(thread_data)
     serialized = self.serialize(Thread(id=thread_data["id"]))
     self.assertNotIn("response_count", serialized)
コード例 #23
0
 def test_response_count(self):
     thread_data = self.make_cs_content({"resp_total": 2})
     self.register_get_thread_response(thread_data)
     serialized = self.serialize(Thread(id=thread_data["id"]))
     self.assertEqual(serialized["response_count"], 2)
コード例 #24
0
ファイル: api.py プロジェクト: lydia-lee/edx-platform
def get_thread_list(request,
                    course_key,
                    page,
                    page_size,
                    topic_id_list=None,
                    text_search=None,
                    following=False):
    """
    Return the list of all discussion threads pertaining to the given course

    Parameters:

    request: The django request objects used for build_absolute_uri
    course_key: The key of the course to get discussion threads for
    page: The page number (1-indexed) to retrieve
    page_size: The number of threads to retrieve per page
    topic_id_list: The list of topic_ids to get the discussion threads for
    text_search A text search query string to match
    following: If true, retrieve only threads the requester is following

    Note that topic_id_list, text_search, and following are mutually exclusive.

    Returns:

    A paginated result containing a list of threads; see
    discussion_api.views.ThreadViewSet for more detail.

    Raises:

    ValueError: if more than one of the mutually exclusive parameters is
      provided
    Http404: if the requesting user does not have access to the requested course
      or a page beyond the last is requested
    """
    exclusive_param_count = sum(
        1 for param in [topic_id_list, text_search, following] if param)
    if exclusive_param_count > 1:  # pragma: no cover
        raise ValueError(
            "More than one mutually exclusive param passed to get_thread_list")

    course = _get_course_or_404(course_key, request.user)
    context = get_context(course, request)
    query_params = {
        "group_id":
        (None if context["is_requester_privileged"] else get_cohort_id(
            request.user, course.id)),
        "sort_key":
        "date",
        "sort_order":
        "desc",
        "page":
        page,
        "per_page":
        page_size,
        "text":
        text_search,
    }
    text_search_rewrite = None
    if following:
        threads, result_page, num_pages = context[
            "cc_requester"].subscribed_threads(query_params)
    else:
        query_params["course_id"] = unicode(course.id)
        query_params["commentable_ids"] = ",".join(
            topic_id_list) if topic_id_list else None
        query_params["text"] = text_search
        threads, result_page, num_pages, text_search_rewrite = Thread.search(
            query_params)
    # The comments service returns the last page of results if the requested
    # page is beyond the last page, but we want be consistent with DRF's general
    # behavior and return a 404 in that case
    if result_page != page:
        raise Http404

    results = [
        ThreadSerializer(thread, context=context).data for thread in threads
    ]
    ret = get_paginated_data(request, results, page, num_pages)
    ret["text_search_rewrite"] = text_search_rewrite
    return ret
コード例 #25
0
ファイル: serializers.py プロジェクト: fahadm507/edx-platform
 def restore_object(self, attrs, instance=None):
     if instance:
         raise ValueError("ThreadSerializer cannot be used for updates.")
     return Thread(user_id=self.context["cc_requester"]["id"], **attrs)
コード例 #26
0
ファイル: api.py プロジェクト: chrisndodge/edx-platform
def get_thread_list(
        request,
        course_key,
        page,
        page_size,
        topic_id_list=None,
        text_search=None,
        following=False,
        view=None,
        order_by="last_activity_at",
        order_direction="desc",
        requested_fields=None,
):
    """
    Return the list of all discussion threads pertaining to the given course

    Parameters:

    request: The django request objects used for build_absolute_uri
    course_key: The key of the course to get discussion threads for
    page: The page number (1-indexed) to retrieve
    page_size: The number of threads to retrieve per page
    topic_id_list: The list of topic_ids to get the discussion threads for
    text_search A text search query string to match
    following: If true, retrieve only threads the requester is following
    view: filters for either "unread" or "unanswered" threads
    order_by: The key in which to sort the threads by. The only values are
        "last_activity_at", "comment_count", and "vote_count". The default is
        "last_activity_at".
    order_direction: The direction in which to sort the threads by. The default
        and only value is "desc". This will be removed in a future major
        version.
    requested_fields: Indicates which additional fields to return
        for each thread. (i.e. ['profile_image'])

    Note that topic_id_list, text_search, and following are mutually exclusive.

    Returns:

    A paginated result containing a list of threads; see
    discussion_api.views.ThreadViewSet for more detail.

    Raises:

    ValidationError: if an invalid value is passed for a field.
    ValueError: if more than one of the mutually exclusive parameters is
      provided
    CourseNotFoundError: if the requesting user does not have access to the requested course
    PageNotFoundError: if page requested is beyond the last
    """
    exclusive_param_count = sum(1 for param in [topic_id_list, text_search, following] if param)
    if exclusive_param_count > 1:  # pragma: no cover
        raise ValueError("More than one mutually exclusive param passed to get_thread_list")

    cc_map = {"last_activity_at": "activity", "comment_count": "comments", "vote_count": "votes"}
    if order_by not in cc_map:
        raise ValidationError({
            "order_by":
                ["Invalid value. '{}' must be 'last_activity_at', 'comment_count', or 'vote_count'".format(order_by)]
        })
    if order_direction != "desc":
        raise ValidationError({
            "order_direction": ["Invalid value. '{}' must be 'desc'".format(order_direction)]
        })

    course = _get_course(course_key, request.user)
    context = get_context(course, request)

    query_params = {
        "user_id": unicode(request.user.id),
        "group_id": (
            None if context["is_requester_privileged"] else
            get_cohort_id(request.user, course.id)
        ),
        "page": page,
        "per_page": page_size,
        "text": text_search,
        "sort_key": cc_map.get(order_by),
    }

    if view:
        if view in ["unread", "unanswered"]:
            query_params[view] = "true"
        else:
            ValidationError({
                "view": ["Invalid value. '{}' must be 'unread' or 'unanswered'".format(view)]
            })

    if following:
        paginated_results = context["cc_requester"].subscribed_threads(query_params)
    else:
        query_params["course_id"] = unicode(course.id)
        query_params["commentable_ids"] = ",".join(topic_id_list) if topic_id_list else None
        query_params["text"] = text_search
        paginated_results = Thread.search(query_params)
    # The comments service returns the last page of results if the requested
    # page is beyond the last page, but we want be consistent with DRF's general
    # behavior and return a PageNotFoundError in that case
    if paginated_results.page != page:
        raise PageNotFoundError("Page not found (No results on this page).")

    results = _serialize_discussion_entities(
        request, context, paginated_results.collection, requested_fields, DiscussionEntity.thread
    )

    paginator = DiscussionAPIPagination(
        request,
        paginated_results.page,
        paginated_results.num_pages,
        paginated_results.thread_count
    )
    return paginator.get_paginated_response({
        "results": results,
        "text_search_rewrite": paginated_results.corrected_text,
    })
コード例 #27
0
def get_comment_list(request, thread_id, endorsed, page, page_size):
    """
    Return the list of comments in the given thread.

    Parameters:

        request: The django request object used for build_absolute_uri and
          determining the requesting user.

        thread_id: The id of the thread to get comments for.

        endorsed: Boolean indicating whether to get endorsed or non-endorsed
          comments (or None for all comments). Must be None for a discussion
          thread and non-None for a question thread.

        page: The page number (1-indexed) to retrieve

        page_size: The number of comments to retrieve per page

    Returns:

        A paginated result containing a list of comments; see
        discussion_api.views.CommentViewSet for more detail.
    """
    response_skip = page_size * (page - 1)
    try:
        cc_thread = Thread(id=thread_id).retrieve(
            recursive=True,
            user_id=request.user.id,
            mark_as_read=True,
            response_skip=response_skip,
            response_limit=page_size
        )
    except CommentClientRequestError:
        # page and page_size are validated at a higher level, so the only
        # possible request error is if the thread doesn't exist
        raise Http404

    course_key = CourseLocator.from_string(cc_thread["course_id"])
    course = _get_course_or_404(course_key, request.user)
    context = get_context(course, request, cc_thread)

    # Ensure user has access to the thread
    if not context["is_requester_privileged"] and cc_thread["group_id"]:
        requester_cohort = get_cohort_id(request.user, course_key)
        if requester_cohort is not None and cc_thread["group_id"] != requester_cohort:
            raise Http404

    # Responses to discussion threads cannot be separated by endorsed, but
    # responses to question threads must be separated by endorsed due to the
    # existing comments service interface
    if cc_thread["thread_type"] == "question":
        if endorsed is None:
            raise ValidationError({"endorsed": ["This field is required for question threads."]})
        elif endorsed:
            # CS does not apply resp_skip and resp_limit to endorsed responses
            # of a question post
            responses = cc_thread["endorsed_responses"][response_skip:(response_skip + page_size)]
            resp_total = len(cc_thread["endorsed_responses"])
        else:
            responses = cc_thread["non_endorsed_responses"]
            resp_total = cc_thread["non_endorsed_resp_total"]
    else:
        if endorsed is not None:
            raise ValidationError(
                {"endorsed": ["This field may not be specified for discussion threads."]}
            )
        responses = cc_thread["children"]
        resp_total = cc_thread["resp_total"]

    # The comments service returns the last page of results if the requested
    # page is beyond the last page, but we want be consistent with DRF's general
    # behavior and return a 404 in that case
    if not responses and page != 1:
        raise Http404
    num_pages = (resp_total + page_size - 1) / page_size if resp_total else 1

    results = [CommentSerializer(response, context=context).data for response in responses]
    return get_paginated_data(request, results, page, num_pages)