{"action":"created","comment":{"url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/comments/42373823","id":42373823,"diff_hunk":"@@ -0,0 +1,140 @@\n+from modularodm import Q\n+from modularodm.exceptions import NoResultsFound\n+from rest_framework import generics, permissions as drf_permissions\n+from rest_framework.exceptions import NotFound, ValidationError, PermissionDenied\n+from api.comments.serializers import CommentSerializer, CommentDetailSerializer, CommentReportsSerializer, CommentReportDetailSerializer, CommentReport\n+from api.base.exceptions import Gone\n+from api.base import permissions as base_permissions\n+from api.nodes.permissions import (\n+    ContributorOrPublicForComments\n+)\n+from framework.auth.oauth_scopes import CoreScopes\n+from website.project.model import Comment\n+\n+\n+class CommentMixin(object):\n+    \"\"\"Mixin with convenience methods for retrieving the current comment  based on the\n+    current URL. By default, fetches the comment based on the comment_id kwarg.\n+    \"\"\"\n+\n+    serializer_class = CommentSerializer\n+    comment_lookup_url_kwarg = 'comment_id'\n+\n+    def get_comment(self, check_permissions=True):\n+        pk = self.kwargs[self.comment_lookup_url_kwarg]\n+        query = Q('_id', 'eq', pk)\n+        try:\n+            comment = Comment.find_one(query)\n+        except NoResultsFound:\n+            raise NotFound\n+\n+        if check_permissions:\n+            # May raise a permission denied\n+            self.check_object_permissions(self.request, comment)\n+        return comment\n+\n+\n+class CommentRepliesList(generics.ListCreateAPIView, CommentMixin):\n+    \"\"\"Replies to a comment.\n+\n+    By default, a GET will return both deleted and not deleted replies. Comment replies may be\n+    filtered by their `deleted` field.\n+    \"\"\"\n+    permission_classes = (\n+        drf_permissions.IsAuthenticatedOrReadOnly,\n+        ContributorOrPublicForComments,\n+        base_permissions.TokenHasScope,\n+    )\n+\n+    required_read_scopes = [CoreScopes.NODE_COMMENTS_READ]\n+    required_write_scopes = [CoreScopes.NODE_COMMENTS_WRITE]\n+\n+    serializer_class = CommentSerializer\n+\n+    def get_queryset(self):\n+        return Comment.find(Q('target', 'eq', self.get_comment()))\n+\n+    # overrides ListCreateAPIView\n+    def perform_create(self, serializer):\n+        self.check_object_permissions(self.request, self.get_comment())","path":"api/comments/views.py","position":59,"original_position":59,"commit_id":"745cd550a03f17826d519e06fd19d2d78da6a633","original_commit_id":"745cd550a03f17826d519e06fd19d2d78da6a633","user":{"login":"abought","id":2957073,"avatar_url":"https://avatars.githubusercontent.com/u/2957073?v=3","gravatar_id":"","url":"https://api.github.com/users/abought","html_url":"https://github.com/abought","followers_url":"https://api.github.com/users/abought/followers","following_url":"https://api.github.com/users/abought/following{/other_user}","gists_url":"https://api.github.com/users/abought/gists{/gist_id}","starred_url":"https://api.github.com/users/abought/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abought/subscriptions","organizations_url":"https://api.github.com/users/abought/orgs","repos_url":"https://api.github.com/users/abought/repos","events_url":"https://api.github.com/users/abought/events{/privacy}","received_events_url":"https://api.github.com/users/abought/received_events","type":"User","site_admin":false},"body":"There is a flag that allows you to call `check_object_permissions` directly from `get_comment`. This can be simplified accordingly.","created_at":"2015-10-19T14:02:01Z","updated_at":"2015-10-19T14:02:01Z","html_url":"https://github.com/CenterForOpenScience/osf.io/pull/4419#discussion_r42373823","pull_request_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4419","_links":{"self":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/comments/42373823"},"html":{"href":"https://github.com/CenterForOpenScience/osf.io/pull/4419#discussion_r42373823"},"pull_request":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4419"}}},"pull_request":{"url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4419","id":47073609,"html_url":"https://github.com/CenterForOpenScience/osf.io/pull/4419","diff_url":"https://github.com/CenterForOpenScience/osf.io/pull/4419.diff","patch_url":"https://github.com/CenterForOpenScience/osf.io/pull/4419.patch","issue_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/4419","number":4419,"state":"open","locked":false,"title":"[Ready for Review] Create API v2 routes for comments","user":{"login":"samanehsan","id":6414394,"avatar_url":"https://avatars.githubusercontent.com/u/6414394?v=3","gravatar_id":"","url":"https://api.github.com/users/samanehsan","html_url":"https://github.com/samanehsan","followers_url":"https://api.github.com/users/samanehsan/followers","following_url":"https://api.github.com/users/samanehsan/following{/other_user}","gists_url":"https://api.github.com/users/samanehsan/gists{/gist_id}","starred_url":"https://api.github.com/users/samanehsan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/samanehsan/subscriptions","organizations_url":"https://api.github.com/users/samanehsan/orgs","repos_url":"https://api.github.com/users/samanehsan/repos","events_url":"https://api.github.com/users/samanehsan/events{/privacy}","received_events_url":"https://api.github.com/users/samanehsan/received_events","type":"User","site_admin":false},"body":"Add in endpoints to retrieve all of the comments on a project and to create/retrieve/update/delete comments. Specifically: \r\n\r\n- GET, POST /v2/nodes/{node_id}/comments/  (includes ability to filter on the `deleted` field)\r\n- GET, PUT /v2/comments/{cid}/\r\n- GET, POST /v2/comments/{cid}/replies/\r\n- GET, POST /v2/comments/{cid}/reports/\r\n- PUT, DELETE /v2/comments/{cid}/reports/{user_id}/\r\n\r\nI also added a linked field for comments to the node serializer, along with the number of unread comments.","created_at":"2015-10-07T19:52:42Z","updated_at":"2015-10-19T14:02:01Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2ba090eaf13d53b7bd67ada0ec1d065934e4b31a","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4419/commits","review_comments_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4419/comments","review_comment_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/comments{/number}","comments_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/4419/comments","statuses_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/statuses/745cd550a03f17826d519e06fd19d2d78da6a633","head":{"label":"samanehsan:feature/api-comments","ref":"feature/api-comments","sha":"745cd550a03f17826d519e06fd19d2d78da6a633","user":{"login":"samanehsan","id":6414394,"avatar_url":"https://avatars.githubusercontent.com/u/6414394?v=3","gravatar_id":"","url":"https://api.github.com/users/samanehsan","html_url":"https://github.com/samanehsan","followers_url":"https://api.github.com/users/samanehsan/followers","following_url":"https://api.github.com/users/samanehsan/following{/other_user}","gists_url":"https://api.github.com/users/samanehsan/gists{/gist_id}","starred_url":"https://api.github.com/users/samanehsan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/samanehsan/subscriptions","organizations_url":"https://api.github.com/users/samanehsan/orgs","repos_url":"https://api.github.com/users/samanehsan/repos","events_url":"https://api.github.com/users/samanehsan/events{/privacy}","received_events_url":"https://api.github.com/users/samanehsan/received_events","type":"User","site_admin":false},"repo":{"id":26921095,"name":"osf.io","full_name":"samanehsan/osf.io","owner":{"login":"samanehsan","id":6414394,"avatar_url":"https://avatars.githubusercontent.com/u/6414394?v=3","gravatar_id":"","url":"https://api.github.com/users/samanehsan","html_url":"https://github.com/samanehsan","followers_url":"https://api.github.com/users/samanehsan/followers","following_url":"https://api.github.com/users/samanehsan/following{/other_user}","gists_url":"https://api.github.com/users/samanehsan/gists{/gist_id}","starred_url":"https://api.github.com/users/samanehsan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/samanehsan/subscriptions","organizations_url":"https://api.github.com/users/samanehsan/orgs","repos_url":"https://api.github.com/users/samanehsan/repos","events_url":"https://api.github.com/users/samanehsan/events{/privacy}","received_events_url":"https://api.github.com/users/samanehsan/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/samanehsan/osf.io","description":"Facilitating Open Science","fork":true,"url":"https://api.github.com/repos/samanehsan/osf.io","forks_url":"https://api.github.com/repos/samanehsan/osf.io/forks","keys_url":"https://api.github.com/repos/samanehsan/osf.io/keys{/key_id}","collaborators_url":"https://api.github.com/repos/samanehsan/osf.io/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/samanehsan/osf.io/teams","hooks_url":"https://api.github.com/repos/samanehsan/osf.io/hooks","issue_events_url":"https://api.github.com/repos/samanehsan/osf.io/issues/events{/number}","events_url":"https://api.github.com/repos/samanehsan/osf.io/events","assignees_url":"https://api.github.com/repos/samanehsan/osf.io/assignees{/user}","branches_url":"https://api.github.com/repos/samanehsan/osf.io/branches{/branch}","tags_url":"https://api.github.com/repos/samanehsan/osf.io/tags","blobs_url":"https://api.github.com/repos/samanehsan/osf.io/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/samanehsan/osf.io/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/samanehsan/osf.io/git/refs{/sha}","trees_url":"https://api.github.com/repos/samanehsan/osf.io/git/trees{/sha}","statuses_url":"https://api.github.com/repos/samanehsan/osf.io/statuses/{sha}","languages_url":"https://api.github.com/repos/samanehsan/osf.io/languages","stargazers_url":"https://api.github.com/repos/samanehsan/osf.io/stargazers","contributors_url":"https://api.github.com/repos/samanehsan/osf.io/contributors","subscribers_url":"https://api.github.com/repos/samanehsan/osf.io/subscribers","subscription_url":"https://api.github.com/repos/samanehsan/osf.io/subscription","commits_url":"https://api.github.com/repos/samanehsan/osf.io/commits{/sha}","git_commits_url":"https://api.github.com/repos/samanehsan/osf.io/git/commits{/sha}","comments_url":"https://api.github.com/repos/samanehsan/osf.io/comments{/number}","issue_comment_url":"https://api.github.com/repos/samanehsan/osf.io/issues/comments{/number}","contents_url":"https://api.github.com/repos/samanehsan/osf.io/contents/{+path}","compare_url":"https://api.github.com/repos/samanehsan/osf.io/compare/{base}...{head}","merges_url":"https://api.github.com/repos/samanehsan/osf.io/merges","archive_url":"https://api.github.com/repos/samanehsan/osf.io/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/samanehsan/osf.io/downloads","issues_url":"https://api.github.com/repos/samanehsan/osf.io/issues{/number}","pulls_url":"https://api.github.com/repos/samanehsan/osf.io/pulls{/number}","milestones_url":"https://api.github.com/repos/samanehsan/osf.io/milestones{/number}","notifications_url":"https://api.github.com/repos/samanehsan/osf.io/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/samanehsan/osf.io/labels{/name}","releases_url":"https://api.github.com/repos/samanehsan/osf.io/releases{/id}","created_at":"2014-11-20T16:27:37Z","updated_at":"2015-06-24T13:47:24Z","pushed_at":"2015-10-07T21:00:30Z","git_url":"git://github.com/samanehsan/osf.io.git","ssh_url":"git@github.com:samanehsan/osf.io.git","clone_url":"https://github.com/samanehsan/osf.io.git","svn_url":"https://github.com/samanehsan/osf.io","homepage":"http://osf.io","size":105789,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"develop"}},"base":{"label":"CenterForOpenScience:develop","ref":"develop","sha":"3bedc2edf40126eec6bcfcd4edc1e829c11685a9","user":{"login":"CenterForOpenScience","id":3344584,"avatar_url":"https://avatars.githubusercontent.com/u/3344584?v=3","gravatar_id":"","url":"https://api.github.com/users/CenterForOpenScience","html_url":"https://github.com/CenterForOpenScience","followers_url":"https://api.github.com/users/CenterForOpenScience/followers","following_url":"https://api.github.com/users/CenterForOpenScience/following{/other_user}","gists_url":"https://api.github.com/users/CenterForOpenScience/gists{/gist_id}","starred_url":"https://api.github.com/users/CenterForOpenScience/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CenterForOpenScience/subscriptions","organizations_url":"https://api.github.com/users/CenterForOpenScience/orgs","repos_url":"https://api.github.com/users/CenterForOpenScience/repos","events_url":"https://api.github.com/users/CenterForOpenScience/events{/privacy}","received_events_url":"https://api.github.com/users/CenterForOpenScience/received_events","type":"Organization","site_admin":false},"repo":{"id":10199599,"name":"osf.io","full_name":"CenterForOpenScience/osf.io","owner":{"login":"CenterForOpenScience","id":3344584,"avatar_url":"https://avatars.githubusercontent.com/u/3344584?v=3","gravatar_id":"","url":"https://api.github.com/users/CenterForOpenScience","html_url":"https://github.com/CenterForOpenScience","followers_url":"https://api.github.com/users/CenterForOpenScience/followers","following_url":"https://api.github.com/users/CenterForOpenScience/following{/other_user}","gists_url":"https://api.github.com/users/CenterForOpenScience/gists{/gist_id}","starred_url":"https://api.github.com/users/CenterForOpenScience/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CenterForOpenScience/subscriptions","organizations_url":"https://api.github.com/users/CenterForOpenScience/orgs","repos_url":"https://api.github.com/users/CenterForOpenScience/repos","events_url":"https://api.github.com/users/CenterForOpenScience/events{/privacy}","received_events_url":"https://api.github.com/users/CenterForOpenScience/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/CenterForOpenScience/osf.io","description":"Facilitating Open Science","fork":false,"url":"https://api.github.com/repos/CenterForOpenScience/osf.io","forks_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/forks","keys_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/keys{/key_id}","collaborators_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/teams","hooks_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/hooks","issue_events_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/events{/number}","events_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/events","assignees_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/assignees{/user}","branches_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/branches{/branch}","tags_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/tags","blobs_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/git/refs{/sha}","trees_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/git/trees{/sha}","statuses_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/statuses/{sha}","languages_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/languages","stargazers_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/stargazers","contributors_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/contributors","subscribers_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/subscribers","subscription_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/subscription","commits_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/commits{/sha}","git_commits_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/git/commits{/sha}","comments_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/comments{/number}","issue_comment_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/comments{/number}","contents_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/contents/{+path}","compare_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/compare/{base}...{head}","merges_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/merges","archive_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/downloads","issues_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues{/number}","pulls_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls{/number}","milestones_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/milestones{/number}","notifications_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/labels{/name}","releases_url":"https://api.github.com/repos/CenterForOpenScience/osf.io/releases{/id}","created_at":"2013-05-21T15:53:37Z","updated_at":"2015-10-15T20:19:45Z","pushed_at":"2015-10-19T13:51:07Z","git_url":"git://github.com/CenterForOpenScience/osf.io.git","ssh_url":"git@github.com:CenterForOpenScience/osf.io.git","clone_url":"https://github.com/CenterForOpenScience/osf.io.git","svn_url":"https://github.com/CenterForOpenScience/osf.io","homepage":"http://osf.io","size":234391,"stargazers_count":146,"watchers_count":146,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":126,"mirror_url":null,"open_issues_count":440,"forks":126,"open_issues":440,"watchers":146,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4419"},"html":{"href":"https://github.com/CenterForOpenScience/osf.io/pull/4419"},"issue":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/4419"},"comments":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/issues/4419/comments"},"review_comments":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4419/comments"},"review_comment":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/pulls/4419/commits"},"statuses":{"href":"https://api.github.com/repos/CenterForOpenScience/osf.io/statuses/745cd550a03f17826d519e06fd19d2d78da6a633"}}}}