From e9a70f456ca229a49331239d0e390c1b8faaad05 Mon Sep 17 00:00:00 2001
From: Geert Kapteijns <ghkapteijns@gmail.com>
Date: Sat, 25 Feb 2017 20:42:09 +0100
Subject: [PATCH] Extract submission comment logic to #new_comment

Fix bug that allows a forged post request to create a comment,
while the submission is not open for commenting.
---
 comments/templates/comments/new_comment.html  |  2 +-
 comments/test_views.py                        | 55 ++++++++++++++++++-
 comments/views.py                             | 19 +++++--
 submissions/factories.py                      |  2 +-
 .../submissions/submission_detail.html        | 33 +----------
 submissions/test_views.py                     | 18 ++++++
 submissions/views.py                          | 37 +------------
 theses/templates/theses/thesis_detail.html    |  2 +-
 8 files changed, 91 insertions(+), 77 deletions(-)

diff --git a/comments/templates/comments/new_comment.html b/comments/templates/comments/new_comment.html
index 572b9fd43..80f19afad 100644
--- a/comments/templates/comments/new_comment.html
+++ b/comments/templates/comments/new_comment.html
@@ -1,4 +1,4 @@
-{% if user.is_authenticated and thesislink.open_for_commenting and perms.scipost.can_submit_comments %}
+{% if user.is_authenticated and open_for_commenting and perms.scipost.can_submit_comments %}
 <hr />
 
 <div class="row">
diff --git a/comments/test_views.py b/comments/test_views.py
index 0f382843b..967c63d3b 100644
--- a/comments/test_views.py
+++ b/comments/test_views.py
@@ -1,9 +1,11 @@
 from django.test import TestCase, RequestFactory, Client
 from django.urls import reverse, reverse_lazy
 from django.contrib.auth.models import Group
+from django.core.exceptions import PermissionDenied
 
 from scipost.factories import ContributorFactory
 from theses.factories import ThesisLinkFactory
+from submissions.factories import EICassignedSubmissionFactory
 
 from .factories import CommentFactory
 from .forms import CommentForm
@@ -22,7 +24,7 @@ class TestNewComment(TestCase):
         contributor = ContributorFactory()
         thesislink = ThesisLinkFactory()
         valid_comment_data = model_form_data(CommentFactory.build(), CommentForm)
-        target = reverse('theses:thesis', kwargs={'thesislink_id': thesislink.id})
+        target = reverse('comments:new_comment', kwargs={'object_id': thesislink.id, 'type_of_object': 'thesislink'})
 
         comment_count = Comment.objects.filter(author=contributor).count()
         self.assertEqual(comment_count, 0)
@@ -35,4 +37,53 @@ class TestNewComment(TestCase):
         self.assertEqual(comment_count, 1)
 
         response.client = Client()
-        self.assertRedirects(response, reverse('theses:thesis', kwargs={"thesislink_id":thesislink.id}))
+        expected_redirect_link = reverse('theses:thesis', kwargs={'thesislink_id': thesislink.id})
+        self.assertRedirects(response, expected_redirect_link)
+
+    def test_submitting_comment_on_submission_creates_comment_and_redirects(self):
+        contributor = ContributorFactory()
+        submission = EICassignedSubmissionFactory()
+        submission.open_for_commenting = True
+        submission.save()
+        valid_comment_data = model_form_data(CommentFactory.build(), CommentForm)
+        target = reverse(
+            'comments:new_comment',
+            kwargs={'object_id': submission.id, 'type_of_object': 'submission'},
+        )
+
+        comment_count = Comment.objects.filter(author=contributor).count()
+        self.assertEqual(comment_count, 0)
+
+        request = RequestFactory().post(target, valid_comment_data)
+        request.user = contributor.user
+        response = new_comment(request, object_id=submission.id, type_of_object='submission')
+
+        comment_count = Comment.objects.filter(author=contributor).count()
+        self.assertEqual(comment_count, 1)
+
+        response.client = Client()
+        expected_redirect_link = reverse(
+            'submissions:submission',
+            kwargs={'arxiv_identifier_w_vn_nr': submission.arxiv_identifier_w_vn_nr}
+        )
+        self.assertRedirects(response, expected_redirect_link)
+
+
+    def test_submitting_comment_on_submission_that_is_not_open_for_commenting_should_be_impossible(self):
+        contributor = ContributorFactory()
+        submission = EICassignedSubmissionFactory()
+        submission.open_for_commenting = False
+        submission.save()
+        valid_comment_data = model_form_data(CommentFactory.build(), CommentForm)
+        target = reverse(
+            'comments:new_comment',
+            kwargs={'object_id': submission.id, 'type_of_object': 'submission'},
+        )
+
+        comment_count = Comment.objects.filter(author=contributor).count()
+        self.assertEqual(comment_count, 0)
+
+        request = RequestFactory().post(target, valid_comment_data)
+        request.user = contributor.user
+        with self.assertRaises(PermissionDenied):
+            response = new_comment(request, object_id=submission.id, type_of_object='submission')
diff --git a/comments/views.py b/comments/views.py
index f07ed6d76..4b32e734f 100644
--- a/comments/views.py
+++ b/comments/views.py
@@ -3,6 +3,7 @@ from django.shortcuts import get_object_or_404, render, redirect
 from django.contrib.auth.decorators import permission_required
 from django.core.mail import EmailMessage
 from django.core.urlresolvers import reverse
+from django.core.exceptions import PermissionDenied
 from django.http import HttpResponseRedirect, Http404
 
 from .models import Comment
@@ -11,7 +12,7 @@ from .forms import CommentForm, VetCommentForm, comment_refusal_dict
 from scipost.models import Contributor, title_dict
 from theses.models import ThesisLink
 from submissions.utils import SubmissionUtils
-from submissions.models import Report
+from submissions.models import Submission, Report
 
 @permission_required('scipost.can_submit_comments', raise_exception=True)
 def new_comment(request, **kwargs):
@@ -22,7 +23,6 @@ def new_comment(request, **kwargs):
             object_id = int(kwargs["object_id"])
             type_of_object = kwargs["type_of_object"]
             new_comment = Comment(
-                # thesislink=thesislink,
                 author=author,
                 is_rem=form.cleaned_data['is_rem'],
                 is_que=form.cleaned_data['is_que'],
@@ -39,9 +39,17 @@ def new_comment(request, **kwargs):
             if type_of_object == "thesislink":
                 thesislink = ThesisLink.objects.get(id=object_id)
                 new_comment.thesislink = thesislink
+                redirect_link = reverse('theses:thesis', kwargs={"thesislink_id":thesislink.id})
             elif type_of_object == "submission":
-                # TODO
-                1 + 1
+                submission = Submission.objects.get(id=object_id)
+                if not submission.open_for_commenting:
+                    raise PermissionDenied
+                    
+                new_comment.submission = submission
+                redirect_link = reverse(
+                    'submissions:submission',
+                    kwargs={"arxiv_identifier_w_vn_nr": submission.arxiv_identifier_w_vn_nr}
+                )
             elif type_of_object == "commentary":
                 # TODO
                 1 + 1
@@ -49,8 +57,7 @@ def new_comment(request, **kwargs):
             new_comment.save()
             author.nr_comments = Comment.objects.filter(author=author).count()
             author.save()
-            if type_of_object == "thesislink":
-                return redirect('theses:thesis', thesislink_id=object_id)
+            return redirect(redirect_link)
     else:
         # This view is only accessible by POST request
         raise Http404
diff --git a/submissions/factories.py b/submissions/factories.py
index 7f07c3052..ade2eba39 100644
--- a/submissions/factories.py
+++ b/submissions/factories.py
@@ -25,7 +25,7 @@ class SubmissionFactory(factory.django.DjangoModelFactory):
 class EICassignedSubmissionFactory(SubmissionFactory):
     status = 'EICassigned'
     editor_in_charge = factory.SubFactory(ContributorFactory)
-
+    open_for_commenting = True
 
 
 def random_arxiv_identifier_with_version_number():
diff --git a/submissions/templates/submissions/submission_detail.html b/submissions/templates/submissions/submission_detail.html
index 68750602f..3e793e6ce 100644
--- a/submissions/templates/submissions/submission_detail.html
+++ b/submissions/templates/submissions/submission_detail.html
@@ -205,7 +205,7 @@
 				    <p>
 				      <a target="_blank" href="{{ reply.file_attachment.url }}">
 					{% if reply.file_attachment|is_image %}
-					<img class="attachment attachment-comment" src="{{ reply.file_attachment.url }}">                                                                              
+					<img class="attachment attachment-comment" src="{{ reply.file_attachment.url }}">
 					{% else %}
 					{{ reply.file_attachment|filename }}<br><small>{{ reply.file_attachment.size|filesizeformat }}</small>
 					{% endif %}
@@ -304,37 +304,8 @@
 
 {% endif %}
 
-
-
 {% include 'scipost/comments_block.html' %}
 
-{% if user.is_authenticated and submission.open_for_commenting and perms.scipost.can_submit_comments %}
-<hr>
-<div id="contribute_comment">
-    <div class="row">
-        <div class="col-12">
-            <div class="panel">
-                <h2>Contribute a Comment:</h2>
-            </div>
-        </div>
-    </div>
-    <div class="row">
-        <div class="col-12">
-            <form enctype="multipart/form-data" action="{% url 'submissions:submission' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}" method="post">
-                {% csrf_token %}
-                {% load crispy_forms_tags %}
-                {% crispy form %}
-            </form>
-        </div>
-    </div>
-
-    <div class="row">
-        <div class="col-12">
-            <h3>Preview of your comment:</h3>
-            <p id="preview-comment_text"></p>
-        </div>
-    </div>
-</div>
-{% endif %}
+{% include 'comments/new_comment.html' with object_id=submission.id type_of_object='submission' open_for_commenting=submission.open_for_commenting %}
 
 {% endblock content %}
diff --git a/submissions/test_views.py b/submissions/test_views.py
index 5eef315b0..8cfec3410 100644
--- a/submissions/test_views.py
+++ b/submissions/test_views.py
@@ -3,6 +3,8 @@ from django.test import Client
 from submissions.views import *
 import django.core.urlresolvers
 
+from .factories import EICassignedSubmissionFactory
+
 
 class PrefillUsingIdentifierTest(TestCase):
     fixtures = ['permissions', 'groups', 'contributors']
@@ -45,3 +47,19 @@ class SubmitManuscriptTest(TestCase):
                                {**params, **extras})
 
         self.assertEqual(response.status_code, 200)
+
+
+class SubmissionDetailTest(TestCase):
+    fixtures = ['permissions', 'groups', 'contributors']
+
+    def setUp(self):
+        self.client = Client()
+        self.submission = EICassignedSubmissionFactory()
+        self.target = reverse(
+            'submissions:submission',
+            kwargs={'arxiv_identifier_w_vn_nr': self.submission.arxiv_identifier_w_vn_nr}
+        )
+
+    def test_status_code_200(self):
+        response = self.client.get(self.target)
+        self.assertEqual(response.status_code, 200)
diff --git a/submissions/views.py b/submissions/views.py
index f69b23d8c..2681da5f9 100644
--- a/submissions/views.py
+++ b/submissions/views.py
@@ -285,41 +285,8 @@ def submission_detail(request, arxiv_identifier_w_vn_nr):
     other_versions = Submission.objects.filter(
         arxiv_identifier_wo_vn_nr=submission.arxiv_identifier_wo_vn_nr
     ).exclude(pk=submission.id)
-    if request.method == 'POST':
-        form = CommentForm(request.POST, request.FILES)
-        if form.is_valid():
-            author = Contributor.objects.get(user=request.user)
-            newcomment = Comment(
-                submission=submission,
-                author=author,
-                is_rem=form.cleaned_data['is_rem'],
-                is_que=form.cleaned_data['is_que'],
-                is_ans=form.cleaned_data['is_ans'],
-                is_obj=form.cleaned_data['is_obj'],
-                is_rep=form.cleaned_data['is_rep'],
-                is_val=form.cleaned_data['is_val'],
-                is_lit=form.cleaned_data['is_lit'],
-                is_sug=form.cleaned_data['is_sug'],
-                file_attachment=form.cleaned_data['file_attachment'],
-                comment_text=form.cleaned_data['comment_text'],
-                remarks_for_editors=form.cleaned_data['remarks_for_editors'],
-                date_submitted=timezone.now(),
-            )
-            newcomment.save()
-            author.nr_comments = Comment.objects.filter(author=author).count()
-            author.save()
-            context = {'ack_header': 'Thank you for contributing a Comment.',
-                       'ack_message': 'It will soon be vetted by an Editor.',
-                       'followup_message': 'Back to the ',
-                       'followup_link': reverse(
-                           'submissions:submission',
-                           kwargs={'arxiv_identifier_w_vn_nr': newcomment.submission.arxiv_identifier_w_vn_nr}
-                       ),
-                       'followup_link_label': ' Submission page you came from'
-                       }
-            return render(request, 'scipost/acknowledgement.html', context)
-    else:
-        form = CommentForm()
+
+    form = CommentForm()
 
     reports = submission.report_set.all()
     try:
diff --git a/theses/templates/theses/thesis_detail.html b/theses/templates/theses/thesis_detail.html
index 8bca24d3e..edde03144 100644
--- a/theses/templates/theses/thesis_detail.html
+++ b/theses/templates/theses/thesis_detail.html
@@ -50,6 +50,6 @@
 
 {% include 'scipost/comments_block.html' %}
 
-{% include 'comments/new_comment.html' with object_id=thesislink.id type_of_object='thesislink' %}
+{% include 'comments/new_comment.html' with object_id=thesislink.id type_of_object='thesislink' open_for_commenting=thesislink.open_for_commenting %}
 
 {% endblock content %}
-- 
GitLab