def create(self, validated_data): comment = Comment( course_id=self.context["thread"]["course_id"], user_id=self.context["cc_requester"]["id"], **validated_data ) comment.save() return comment
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)
def get_response_comments(request, comment_id, page, page_size, requested_fields=None): """ Return the list of comments for the given thread response. Arguments: request: The django request object used for build_absolute_uri and determining the requesting user. comment_id: The id of the comment/response to get child comments for. page: The page number (1-indexed) to retrieve page_size: The number of comments to retrieve per page requested_fields: Indicates which additional fields to return for each child comment. (i.e. ['profile_image']) Returns: A paginated result containing a list of comments """ try: cc_comment = Comment(id=comment_id).retrieve() cc_thread, context = _get_thread_and_context( request, cc_comment["thread_id"], retrieve_kwargs={ "with_responses": True, "recursive": True, } ) if cc_thread["thread_type"] == "question": thread_responses = itertools.chain(cc_thread["endorsed_responses"], cc_thread["non_endorsed_responses"]) else: thread_responses = cc_thread["children"] response_comments = [] for response in thread_responses: if response["id"] == comment_id: response_comments = response["children"] break response_skip = page_size * (page - 1) paged_response_comments = response_comments[response_skip:(response_skip + page_size)] if len(paged_response_comments) == 0 and page != 1: raise PageNotFoundError("Page not found (No results on this page).") results = _serialize_discussion_entities( request, context, paged_response_comments, requested_fields, DiscussionEntity.comment ) comments_count = len(response_comments) num_pages = (comments_count + page_size - 1) / page_size if comments_count else 1 paginator = DiscussionAPIPagination(request, page, num_pages, comments_count) return paginator.get_paginated_response(results) except CommentClientRequestError: raise CommentNotFoundError("Comment not found")
def get_initializable_comment_fields(context): # pylint: disable=invalid-name """ Return the set of fields that the requester can initialize for a comment Any field that is editable by the author should also be initializable. """ ret = get_editable_fields( Comment(user_id=context["cc_requester"]["id"], type="comment"), context) ret |= NON_UPDATABLE_COMMENT_FIELDS return ret
def get_response_comments(request, comment_id, page, page_size): """ Return the list of comments for the given thread response. Arguments: request: The django request object used for build_absolute_uri and determining the requesting user. comment_id: The id of the comment/response to get child comments for. 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 """ try: cc_comment = Comment(id=comment_id).retrieve() cc_thread, context = _get_thread_and_context(request, cc_comment["thread_id"], retrieve_kwargs={ "recursive": True, }) if cc_thread["thread_type"] == "question": thread_responses = itertools.chain( cc_thread["endorsed_responses"], cc_thread["non_endorsed_responses"]) else: thread_responses = cc_thread["children"] response_comments = [] for response in thread_responses: if response["id"] == comment_id: response_comments = response["children"] break response_skip = page_size * (page - 1) paged_response_comments = response_comments[response_skip:( response_skip + page_size)] results = [ CommentSerializer(comment, context=context).data for comment in paged_response_comments ] comments_count = len(response_comments) num_pages = (comments_count + page_size - 1) / page_size if comments_count else 1 return get_paginated_data(request, results, page, num_pages) except CommentClientRequestError: raise Http404
def _get_comment_and_context(request, comment_id): """ Retrieve the given comment and build a serializer context for it, returning both. This function also enforces access control for the comment (checking both the user's access to the course and to the comment's thread's cohort if applicable). Raises Http404 if the comment does not exist or the user cannot access it. """ try: cc_comment = Comment(id=comment_id).retrieve() _, context = _get_thread_and_context(request, cc_comment["thread_id"]) return cc_comment, context except CommentClientRequestError: raise Http404
def test_comment(self, is_author, is_thread_author, thread_type, is_privileged): comment = Comment(user_id="5" if is_author else "6", type="comment") 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_editable_fields(comment, context) expected = {"abuse_flagged", "voted"} if is_author or is_privileged: expected |= {"raw_body"} if (is_thread_author and thread_type == "question") or is_privileged: expected |= {"endorsed"} self.assertEqual(actual, expected)
def restore_object(self, attrs, instance=None): if instance: for key, val in attrs.items(): instance[key] = val # TODO: The comments service doesn't populate the endorsement # field on comment creation, so we only provide # endorsement_user_id on update if key == "endorsed": instance["endorsement_user_id"] = self.context[ "cc_requester"]["id"] return instance return Comment(course_id=self.context["thread"]["course_id"], user_id=self.context["cc_requester"]["id"], **attrs)
def validate(self, attrs): """ Ensure that parent_id identifies a comment that is actually in the thread identified by thread_id and does not violate the configured maximum depth. """ parent = None parent_id = attrs.get("parent_id") if parent_id: try: parent = Comment(id=parent_id).retrieve() except CommentClientRequestError: pass if not (parent and parent["thread_id"] == attrs["thread_id"]): raise ValidationError( "parent_id does not identify a comment in the thread identified by thread_id." ) if is_comment_too_deep(parent): raise ValidationError({"parent_id": ["Comment level is too deep."]}) return attrs
def setUp(self): super(CommentSerializerDeserializationTest, self).setUp() httpretty.reset() httpretty.enable() 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 = { "thread_id": "test_thread", "raw_body": "Test body", } self.existing_comment = Comment(**make_minimal_cs_comment({ "id": "existing_comment", "thread_id": "existing_thread", "body": "Original body", "user_id": str(self.user.id), "course_id": unicode(self.course.id), }))