def test_notify_comment_followers(self):
     # send a couple of comments to the article with followup=True and check
     # that when the second comment is confirmed a followup notification
     # email is sent to the user who sent the first comment
     self.assertEqual(self.mock_mailer.call_count, 1)
     confirm_comment_url(self.key)
     # no comment followers yet:
     self.assertEqual(self.mock_mailer.call_count, 1)
     # send 2nd comment
     self.form = get_form()(self.article)
     data = {"name": "Alice", "email": "*****@*****.**",
             "followup": True, "reply_to": 0, "level": 1, "order": 1,
             "comment": "Es war einmal eine kleine..."}
     data.update(self.form.initial)
     response = post_article_comment(data, article=self.article)
     self.assertEqual(response.status_code, 302)
     self.assertTrue(response.url.startswith('/comments/posted/?c='))
     self.assertEqual(self.mock_mailer.call_count, 2)
     self.key = re.search(r'http://.+/confirm/(?P<key>[\S]+)/',
                          self.mock_mailer.call_args[0][1]).group("key")
     confirm_comment_url(self.key)
     self.assertEqual(self.mock_mailer.call_count, 3)
     self.assertTrue(self.mock_mailer.call_args[0][3] == ["*****@*****.**"])
     self.assertTrue(self.mock_mailer.call_args[0][1].find(
         "There is a new comment following up yours.") > -1)
 def setUp(self):
     patcher = patch('django_comments_tree.views.comments.send_mail')
     self.mock_mailer = patcher.start()
     self.article = Article.objects.create(
         title="October", slug="october", body="What I did on October...")
     self.form = get_form()(self.article)
     self.factory = RequestFactory()
     self.user = AnonymousUser()
    def test_notify_followers_dupes(self):
        # first of all confirm Bob's comment otherwise it doesn't reach DB
        confirm_comment_url(self.key)
        # then put in play pull-request-15's assert...
        # https://github.com/sharpertool/django-comments-tree/pull/15
        diary = Diary.objects.create(
            body='Lorem ipsum',
            allow_comments=True
        )
        self.assertEqual(diary.pk, self.article.pk)

        self.form = get_form()(diary)
        data = {"name": "Charlie", "email": "*****@*****.**",
                "followup": True, "reply_to": 0, "level": 1, "order": 1,
                "comment": "Es war einmal eine kleine..."}
        data.update(self.form.initial)
        response = post_diary_comment(data, diary_entry=diary)
        self.assertEqual(response.status_code, 302)
        self.assertTrue(response.url.startswith('/comments/posted/?c='))
        self.key = str(re.search(r'http://.+/confirm/(?P<key>[\S]+)/',
                                 self.mock_mailer.call_args[0][1]).group("key"))
        # 1) confirmation for Bob (sent in `setUp()`)
        # 2) confirmation for Charlie
        self.assertEqual(self.mock_mailer.call_count, 2)
        response = confirm_comment_url(self.key)
        self.assertEqual(response.status_code, 302)
        self.assertTrue(response.url.startswith('/comments/cr/'))
        self.assertEqual(self.mock_mailer.call_count, 2)

        self.form = get_form()(self.article)
        data = {"name": "Alice", "email": "*****@*****.**",
                "followup": True, "reply_to": 0, "level": 1, "order": 1,
                "comment": "Es war einmal iene kleine..."}
        data.update(self.form.initial)
        response = post_article_comment(data, article=self.article)
        self.assertEqual(response.status_code, 302)
        self.assertTrue(response.url.startswith('/comments/posted/?c='))
        self.assertEqual(self.mock_mailer.call_count, 3)
        self.key = re.search(r'http://.+/confirm/(?P<key>[\S]+)/',
                             self.mock_mailer.call_args[0][1]).group("key")
        confirm_comment_url(self.key)
        self.assertEqual(self.mock_mailer.call_count, 4)
        self.assertTrue(self.mock_mailer.call_args[0][3] == ["*****@*****.**"])
        self.assertTrue(self.mock_mailer.call_args[0][1].find(
            "There is a new comment following up yours.") > -1)
예제 #4
0
 def setUp(self):
     patcher_app1 = patch(send_mail)
     patcher_app2 = patch('django_comments_tree.views.comments.send_mail')
     self.mailer_app1 = patcher_app1.start()
     self.mailer_app2 = patcher_app2.start()
     self.diary_entry = Diary.objects.create(body="What I did Yesterday...",
                                             allow_comments=True,
                                             publish=datetime.now() -
                                             timedelta(days=5))
     self.form = django_comments_tree.get_form()(self.diary_entry)
    def setUp(self):
        # Create an article and send a comment. Test method will chech headers
        # to see wheter messages has multiparts or not.
        patcher = patch('django_comments_tree.views.comments.send_mail')
        self.mock_mailer = patcher.start()
        self.article = Article.objects.create(
            title="September", slug="september", body="John's September")
        self.form = get_form()(self.article)

        # Bob sends 1st comment to the article with follow-up
        self.data = {"name": "Bob", "email": "*****@*****.**",
                     "followup": True, "reply_to": 0, "level": 1, "order": 1,
                     "comment": "Nice September you had..."}
        self.data.update(self.form.initial)
예제 #6
0
    def test_get_comment_create_data(self):
        # as it's used in django_comments.views.comments
        data = {"name": "Daniel",
                "email": "*****@*****.**",
                "followup": True,
                "reply_to": 0, "level": 1, "order": 1,
                "comment": "Es war einmal iene kleine..."}
        data.update(self.form.initial)
        form = django_comments_tree.get_form()(self.article, data)
        self.assertTrue(self.form.security_errors() == {})
        self.assertTrue(self.form.errors == {})
        comment = form.get_comment_object()

        # it does have the new field 'followup'
        self.assertTrue("followup" in comment)
예제 #7
0
 def setUp(self):
     diary_entry = Diary.objects.create(body="What I did on October...",
                                        allow_comments=True,
                                        publish=datetime.now())
     form = django_comments_tree.get_form()(diary_entry)
     self.user = User.objects.create_user("bob", "*****@*****.**", "pwd")
     data = {
         "name": "Bob",
         "email": "*****@*****.**",
         "followup": True,
         "reply_to": 0,
         "level": 1,
         "order": 1,
         "comment": "Es war einmal eine kleine..."
     }
     data.update(form.initial)
     post_diary_comment(data, diary_entry, auth_user=self.user)
 def setUp(self):
     patcher = patch('django_comments_tree.views.comments.send_mail')
     self.mock_mailer = patcher.start()
     # Create random string so that it's harder for zlib to compress
     content = ''.join(random.choice(string.printable) for _ in range(6096))
     self.article = Article.objects.create(title="September",
                                           slug="september",
                                           body="In September..." + content)
     self.form = get_form()(self.article)
     data = {"name": "Bob", "email": "*****@*****.**", "followup": True,
             "reply_to": 0, "level": 1, "order": 1,
             "comment": "Es war einmal iene kleine..."}
     data.update(self.form.initial)
     response = post_article_comment(data, self.article)
     self.assertTrue(self.mock_mailer.call_count == 1)
     self.key = str(re.search(r'http://.+/confirm/(?P<key>[\S]+)/',
                              self.mock_mailer.call_args[0][1]).group("key"))
     self.addCleanup(patcher.stop)
 def test_no_notification_for_same_user_email(self):
     # test that a follow-up user_email don't get a notification when
     # sending another email to the thread
     self.assertEqual(self.mock_mailer.call_count, 1)
     confirm_comment_url(self.key)  # confirm Bob's comment
     # no comment followers yet:
     self.assertEqual(self.mock_mailer.call_count, 1)
     # send Bob's 2nd comment
     self.form = get_form()(self.article)
     data = {"name": "Alice", "email": "*****@*****.**", "followup": True,
             "reply_to": 0, "level": 1, "order": 1,
             "comment": "Bob's comment he shouldn't get notified about"}
     data.update(self.form.initial)
     response = post_article_comment(data, self.article)
     self.assertEqual(self.mock_mailer.call_count, 2)
     self.key = re.search(r'http://.+/confirm/(?P<key>[\S]+)/',
                          self.mock_mailer.call_args[0][1]).group("key")
     confirm_comment_url(self.key)
     self.assertEqual(self.mock_mailer.call_count, 2)
예제 #10
0
    def setUp(self):
        # Creates an article and send two comments to the article with follow-up
        # notifications. First comment doesn't have to send any notification.
        # Second comment has to send one notification (to Bob).
        self.factory = RequestFactory()
        patcher = patch('django_comments_tree.views.comments.send_mail')
        self.mock_mailer = patcher.start()
        self.article = Article.objects.create(
            title="September", slug="september", body="John's September")
        self.form = get_form()(self.article)

        # Bob sends 1st comment to the article with follow-up
        data = {"name": "Bob", "email": "*****@*****.**", "followup": True,
                "reply_to": 0, "level": 1, "order": 1,
                "comment": "Nice September you had..."}
        data.update(self.form.initial)
        response = post_article_comment(data, self.article)
        self.assertEqual(response.status_code, 302)
        self.assertTrue(response.url.startswith('/comments/posted/?c='))
        self.assertTrue(self.mock_mailer.call_count == 1)
        bobkey = str(re.search(r'http://.+/confirm/(?P<key>[\S]+)/',
                               self.mock_mailer.call_args[0][1]).group("key"))
        confirm_comment_url(bobkey)  # confirm Bob's comment

        # Alice sends 2nd comment to the article with follow-up
        data = {"name": "Alice", "email": "*****@*****.**",
                "followup": True, "reply_to": 1, "level": 1, "order": 1,
                "comment": "Yeah, great photos"}
        data.update(self.form.initial)
        response = post_article_comment(data, self.article)
        self.assertEqual(response.status_code, 302)
        self.assertTrue(response.url.startswith('/comments/posted/?c='))
        self.assertTrue(self.mock_mailer.call_count == 2)
        alicekey = str(re.search(r'http://.+/confirm/(?P<key>[\S]+)/',
                                 self.mock_mailer.call_args[0][1]).group("key"))
        confirm_comment_url(alicekey)  # confirm Alice's comment

        # Bob receives a follow-up notification
        self.assertTrue(self.mock_mailer.call_count == 3)
        self.bobs_mutekey = str(re.search(
            r'http://.+/mute/(?P<key>[\S]+)/',
            self.mock_mailer.call_args[0][1]).group("key"))
        self.addCleanup(patcher.stop)
예제 #11
0
def reply(request, cid):
    try:
        comment = TreeComment.objects.get(pk=cid)
        if not comment.allow_thread():
            raise MaxThreadLevelExceededException(comment)
    except MaxThreadLevelExceededException as exc:
        return HttpResponseForbidden(exc)
    except TreeComment.DoesNotExist as exc:
        raise Http404(exc)

    form = get_form()(comment.content_object, comment=comment)
    next = request.GET.get("next", reverse("comments-tree-sent"))

    template_arg = [
        "django_comments_tree/%s/%s/reply.html" % (
            comment.content_type.app_label,
            comment.content_type.model),
        "django_comments_tree/%s/reply.html" % (
            comment.content_type.app_label,),
        "django_comments_tree/reply.html"
    ]
    return render(request, template_arg,
                  {"comment": comment, "form": form, "cid": cid, "next": next})
예제 #12
0
    def validate(self, data):
        ctype = data.get("content_type")
        object_id = data.get("object_id")
        if ctype is None or object_id is None:
            return serializers.ValidationError("Missing content_type or "
                                               "object_id field.")
        try:
            model = apps.get_model(*ctype.split(".", 1))
            target = model._default_manager.get(pk=object_id)
        except TypeError:
            return serializers.ValidationError(
                "Invalid content_type value: %r" % escape(ctype))
        except AttributeError:
            return serializers.ValidationError(
                "The given content-type %r does "
                "not resolve to a valid model." % escape(ctype))
        except model.ObjectDoesNotExist:
            return serializers.ValidationError(
                "No object matching content-type %r and object ID %r exists." %
                (escape(ctype), escape(object_id)))
        except (ValueError, serializers.ValidationError) as e:
            return serializers.ValidationError(
                "Attempting go get content-type %r and object ID %r exists "
                "raised %s" %
                (escape(ctype), escape(object_id), e.__class__.__name__))

        self.form = get_form()(target, data=data)

        # Check security information
        if self.form.security_errors():
            return serializers.ValidationError(
                "The comment form failed security verification: %s" %
                escape(str(self.form.security_errors())))
        if self.form.errors:
            return serializers.ValidationError(self.form.errors)
        return data
예제 #13
0
 def setUp(self):
     patcher = patch('django_comments_tree.views.comments.send_mail')
     self.mock_mailer = patcher.start()
     self.article = Article.objects.create(
         title="October", slug="october", body="What I did on October...")
     self.form = django_comments_tree.get_form()(self.article)
예제 #14
0
 def get_form(self, context):
     obj = self.get_object(context)
     if obj:
         return django_comments_tree.get_form()(obj)
     else:
         return None
예제 #15
0
 def setUp(self):
     self.article = Article.objects.create(title="September",
                                           slug="september",
                                           body="What I did on September...")
     self.form = django_comments_tree.get_form()(self.article)
예제 #16
0
 def test_get_form(self):
     # check function django_comments_tree.get_form retrieves the due class
     self.assertTrue(django_comments_tree.get_form() == TreeCommentForm)
예제 #17
0
    def post(self, request, next=None, using=None):
        """
        Post a comment.

        HTTP POST is required. If ``POST['submit'] == "preview"`` or if there are
        errors a preview template, ``comments/preview.html``, will be rendered.
        """
        # Fill out some initial data fields from an authenticated user, if present
        data = request.POST.copy()
        if request.user.is_authenticated:
            if not data.get('name', ''):
                data["name"] = request.user.get_full_name() or request.user.get_username()
            if not data.get('email', ''):
                data["email"] = request.user.email

        # Look up the object we're trying to comment about
        ctype = data.get("content_type")
        object_id = data.get("object_id")
        if ctype is None or object_id is None:
            return CommentPostBadRequest("Missing content_type or object_id field.")
        try:
            model = apps.get_model(*ctype.split(".", 1))
            target = model._default_manager.using(using).get(pk=object_id)
        except TypeError:
            return CommentPostBadRequest(
                "Invalid content_type value: %r" % escape(ctype))
        except AttributeError:
            return CommentPostBadRequest(
                "The given content-type %r does not resolve to a valid model." % escape(ctype))
        except ObjectDoesNotExist:
            return CommentPostBadRequest(
                "No object matching content-type %r and object PK %r exists." % (
                    escape(ctype), escape(object_id)))
        except (ValueError, ValidationError) as e:
            return CommentPostBadRequest(
                "Attempting go get content-type %r and object PK %r exists raised %s" % (
                    escape(ctype), escape(object_id), e.__class__.__name__))

        # Do we want to preview the comment?
        preview = "preview" in data

        # Construct the comment form
        form = get_form()(target, data=data)

        # Check security information
        if form.security_errors():
            return CommentPostBadRequest(
                f"The comment form failed security verification:"
                f" {escape(str(form.security_errors()))}")

        # If there are errors or if we requested a preview show the comment
        if form.errors or preview:
            app_lbl = model._meta.app_label
            nm = model._meta.model_name
            template_list = [
                # These first two exist for purely historical reasons.
                # Django v1.0 and v1.1 allowed the underscore format for
                # preview templates, so we have to preserve that format.
                f"comments/{app_lbl}_{nm}_preview.html",
                f"comments/{app_lbl}_preview.html",
                # Now the usual directory based template hierarchy.
                f"comments/{app_lbl}/{nm}/preview.html",
                f"comments/{app_lbl}/preview.html",
                "comments/preview.html",
            ]
            return render(request, template_list,
                          {
                              "comment": form.data.get("comment", ""),
                              "form": form,
                              "next": data.get("next", next),
                          },
                          )

        # Otherwise create the comment
        comment = form.get_comment_object(site_id=get_current_site(request).id)
        comment.ip_address = request.META.get("REMOTE_ADDR", None) or None
        if request.user.is_authenticated:
            comment.user = request.user

        # Signal that the comment is about to be saved
        responses = signals.comment_will_be_posted.send(
            sender=comment.__class__,
            comment=comment,
            request=request
        )

        for (receiver, response) in responses:
            if response is False:
                return CommentPostBadRequest(
                    "comment_will_be_posted receiver %r killed the comment" % receiver.__name__)

        # Save the comment and signal that it was saved
        comment.save()
        signals.comment_was_posted.send(
            sender=comment.__class__,
            comment=comment,
            request=request
        )

        return next_redirect(request, fallback=next or 'comments-comment-done',
                             c=comment._get_pk_val())