コード例 #1
0
ファイル: forms.py プロジェクト: zu83/kitsune
    def save(self, user, locale, product, product_config, *args, **kwargs):
        self.instance.creator = user
        self.instance.locale = locale
        self.instance.product = product

        category_config = product_config["categories"][self.cleaned_data["category"]]
        if category_config:
            t = category_config.get("topic")
            if t:
                self.instance.topic = Topic.objects.get(slug=t, product=product)

        question = super(NewQuestionForm, self).save(*args, **kwargs)

        if self.cleaned_data.get("notifications", False):
            QuestionReplyEvent.notify(question.creator, question)

        user_ct = ContentType.objects.get_for_model(user)
        qst_ct = ContentType.objects.get_for_model(question)
        # Move over to the question all of the images I added to the reply form
        up_images = ImageAttachment.objects.filter(creator=user, content_type=user_ct)
        up_images.update(content_type=qst_ct, object_id=question.id)

        # User successfully submitted a new question
        question.add_metadata(**self.cleaned_metadata)

        if product_config:
            # TODO: This add_metadata call should be removed once we are
            # fully IA-driven (sync isn't special case anymore).
            question.add_metadata(product=product_config["key"])

        # The first time a question is saved, automatically apply some tags:
        question.auto_tag()

        return question
コード例 #2
0
    def setUp(self):
        p = profile()
        p.save()
        self.user = p.user
        self.client.login(username=self.user.username, password='******')

        self.question = question(creator=self.user, save=True)
        QuestionReplyEvent.notify(self.user, self.question)
コード例 #3
0
ファイル: test_templates.py プロジェクト: bachileha/kitsune
    def setUp(self):
        p = profile()
        p.save()
        self.user = p.user
        self.client.login(username=self.user.username, password='******')

        self.question = question(creator=self.user, save=True)
        QuestionReplyEvent.notify(self.user, self.question)
コード例 #4
0
def reply(request, question_id):
    """Post a new answer to a question."""
    question = get_object_or_404(Question, pk=question_id, is_spam=False)
    answer_preview = None

    if not question.allows_new_answer(request.user):
        raise PermissionDenied

    form = AnswerForm(request.POST, **{"user": request.user, "question": question})

    # NOJS: delete images
    if "delete_images" in request.POST:
        for image_id in request.POST.getlist("delete_image"):
            ImageAttachment.objects.get(pk=image_id).delete()

        return question_details(request, question_id=question_id, form=form)

    # NOJS: upload image
    if "upload_image" in request.POST:
        upload_imageattachment(request, request.user)
        return question_details(request, question_id=question_id, form=form)

    if form.is_valid() and not request.limited:
        answer = Answer(
            question=question,
            creator=request.user,
            content=form.cleaned_data["content"],
        )
        if "preview" in request.POST:
            answer_preview = answer
        else:
            if form.cleaned_data.get("is_spam"):
                _add_to_moderation_queue(request, answer)
            else:
                answer.save()

            ans_ct = ContentType.objects.get_for_model(answer)
            # Move over to the answer all of the images I added to the
            # reply form
            user_ct = ContentType.objects.get_for_model(request.user)
            up_images = ImageAttachment.objects.filter(creator=request.user, content_type=user_ct)
            up_images.update(content_type=ans_ct, object_id=answer.id)

            # Handle needsinfo tag
            if "needsinfo" in request.POST:
                question.set_needs_info()
            elif "clear_needsinfo" in request.POST:
                question.unset_needs_info()

            if Setting.get_for_user(request.user, "questions_watch_after_reply"):
                QuestionReplyEvent.notify(request.user, question)

            return HttpResponseRedirect(answer.get_absolute_url())

    return question_details(
        request, question_id=question_id, form=form, answer_preview=answer_preview
    )
コード例 #5
0
    def test_notify_arbitrary_reply_to(self):
        """
        Test that notifications to the asker have a correct reply to field.
        """
        watcher = user(save=True)
        QuestionReplyEvent.notify(watcher, self.question)
        self.makeAnswer()

        notification = [m for m in mail.outbox if m.to == [watcher.email]][0]
        # Headers should be compared case-insensitively.
        headers = dict((k.lower(), v) for k, v in notification.extra_headers.items())
        eq_("*****@*****.**", headers["reply-to"])
コード例 #6
0
    def test_notify_anonymous_reply_to(self):
        """
        Test that notifications to the asker have a correct reply to field.
        """
        ANON_EMAIL = "*****@*****.**"
        QuestionReplyEvent.notify(ANON_EMAIL, self.question)
        self.makeAnswer()

        notification = [m for m in mail.outbox if m.to == [ANON_EMAIL]][0]
        # Headers should be compared case-insensitively.
        headers = dict((k.lower(), v) for k, v in notification.extra_headers.items())
        eq_("*****@*****.**", headers["reply-to"])
コード例 #7
0
ファイル: test_notifications.py プロジェクト: zctyhj/kitsune
    def test_notify_arbitrary_reply_to(self):
        """
        Test that notifications to the asker have a correct reply to field.
        """
        watcher = user(save=True)
        QuestionReplyEvent.notify(watcher, self.question)
        self.makeAnswer()

        notification = [m for m in mail.outbox if m.to == [watcher.email]][0]
        # Headers should be compared case-insensitively.
        headers = dict((k.lower(), v)
                       for k, v in notification.extra_headers.items())
        eq_('*****@*****.**', headers['reply-to'])
コード例 #8
0
ファイル: test_notifications.py プロジェクト: zctyhj/kitsune
    def test_notify_anonymous_reply_to(self):
        """
        Test that notifications to the asker have a correct reply to field.
        """
        ANON_EMAIL = '*****@*****.**'
        QuestionReplyEvent.notify(ANON_EMAIL, self.question)
        self.makeAnswer()

        notification = [m for m in mail.outbox if m.to == [ANON_EMAIL]][0]
        # Headers should be compared case-insensitively.
        headers = dict((k.lower(), v)
                       for k, v in notification.extra_headers.items())
        eq_('*****@*****.**', headers['reply-to'])
コード例 #9
0
ファイル: test_notifications.py プロジェクト: 1234-/kitsune
    def test_notify_arbitrary(self):
        """Test that arbitrary users are notified of new answers."""
        watcher = UserFactory()
        QuestionReplyEvent.notify(watcher, self.question)
        self.makeAnswer()

        # One for the asker's email, and one for the watcher's email.
        eq_(2, len(mail.outbox))
        notification = [m for m in mail.outbox if m.to == [watcher.email]][0]

        eq_([watcher.email], notification.to)
        eq_(u'Re: {0}'.format(self.question.title), notification.subject)

        body = re.sub(r'auth=[a-zA-Z0-9%_-]+', 'auth=AUTH', notification.body)
        starts_with(body, ANSWER_EMAIL.format(to_user=display_name(watcher), **self.format_args()))
コード例 #10
0
ファイル: test_notifications.py プロジェクト: zctyhj/kitsune
    def test_notify_arbitrary(self):
        """Test that arbitrary users are notified of new answers."""
        watcher = user(save=True)
        QuestionReplyEvent.notify(watcher, self.question)
        self.makeAnswer()

        # One for the asker's email, and one for the watcher's email.
        eq_(2, len(mail.outbox))
        notification = [m for m in mail.outbox if m.to == [watcher.email]][0]

        eq_([watcher.email], notification.to)
        eq_("Re: {0}".format(self.question.title), notification.subject)

        body = re.sub(r'auth=[a-zA-Z0-9%_-]+', 'auth=AUTH', notification.body)
        starts_with(body, ANSWER_EMAIL.format(to_user=display_name(watcher), **self.format_args()))
コード例 #11
0
    def test_notify_anonymous(self):
        """Test that anonymous users are notified of new answers."""
        ANON_EMAIL = "*****@*****.**"
        QuestionReplyEvent.notify(ANON_EMAIL, self.question)
        self.makeAnswer()

        # One for the asker's email, and one for the anonymous email.
        eq_(2, len(mail.outbox))
        notification = [m for m in mail.outbox if m.to == [ANON_EMAIL]][0]

        eq_([ANON_EMAIL], notification.to)
        eq_("Re: {0}".format(self.question.title), notification.subject)

        body = re.sub(r"auth=[a-zA-Z0-9%_-]+", "auth=AUTH", notification.body)
        starts_with(body, ANSWER_EMAIL_TO_ANONYMOUS.format(**self.format_args()))
コード例 #12
0
    def test_notify_arbitrary(self):
        """Test that arbitrary users are notified of new answers."""
        watcher = user(save=True)
        QuestionReplyEvent.notify(watcher, self.question)
        self.makeAnswer()

        # One for the asker's email, and one for the watcher's email.
        eq_(2, len(mail.outbox))
        notification = [m for m in mail.outbox if m.to == [watcher.email]][0]

        eq_([watcher.email], notification.to)
        eq_("Re: {0}".format(self.question.title), notification.subject)

        body = re.sub(r"auth=[a-zA-Z0-9%_-]+", "auth=AUTH", notification.body)
        starts_with(body, ANSWER_EMAIL.format(to_user=watcher.username, **self.format_args()))
コード例 #13
0
    def save(self, update=False, *args, **kwargs):
        """Override save method to take care of updated if requested."""
        new = not self.id

        if not new:
            self.clear_cached_html()
            if update:
                self.updated = datetime.now()

        super(Question, self).save(*args, **kwargs)

        if new:
            # Avoid circular import, events.py imports Question
            from kitsune.questions.events import QuestionReplyEvent
            # Authors should automatically watch their own questions.
            QuestionReplyEvent.notify(self.creator, self)
コード例 #14
0
ファイル: models.py プロジェクト: GVRV/kitsune
    def save(self, update=False, *args, **kwargs):
        """Override save method to take care of updated if requested."""
        new = not self.id

        if not new:
            self.clear_cached_html()
            if update:
                self.updated = datetime.now()

        super(Question, self).save(*args, **kwargs)

        if new:
            # Avoid circular import, events.py imports Question
            from kitsune.questions.events import QuestionReplyEvent
            # Authors should automatically watch their own questions.
            QuestionReplyEvent.notify(self.creator, self)
コード例 #15
0
ファイル: test_notifications.py プロジェクト: zctyhj/kitsune
    def test_notify_anonymous(self):
        """Test that anonymous users are notified of new answers."""
        ANON_EMAIL = '*****@*****.**'
        QuestionReplyEvent.notify(ANON_EMAIL, self.question)
        self.makeAnswer()

        # One for the asker's email, and one for the anonymous email.
        eq_(2, len(mail.outbox))
        notification = [m for m in mail.outbox if m.to == [ANON_EMAIL]][0]

        eq_([ANON_EMAIL], notification.to)
        eq_("Re: {0}".format(self.question.title), notification.subject)

        body = re.sub(r'auth=[a-zA-Z0-9%_-]+', 'auth=AUTH', notification.body)
        starts_with(body, ANSWER_EMAIL_TO_ANONYMOUS
                    .format(**self.format_args()))
コード例 #16
0
ファイル: views.py プロジェクト: willoughbyrm/kitsune
def watch_question(request, question_id):
    """Start watching a question for replies or solution."""

    question = get_object_or_404(Question, pk=question_id, is_spam=False)
    form = WatchQuestionForm(request.user, request.POST)

    # Process the form
    msg = None
    if form.is_valid():
        user_or_email = (request.user if request.user.is_authenticated else
                         form.cleaned_data["email"])
        try:
            if form.cleaned_data["event_type"] == "reply":
                QuestionReplyEvent.notify(user_or_email, question)
            else:
                QuestionSolvedEvent.notify(user_or_email, question)
        except ActivationRequestFailed:
            msg = _("Could not send a message to that email address.")

    # Respond to ajax request
    if request.is_ajax():
        if form.is_valid():
            msg = msg or (_("You will be notified of updates by email.")
                          if request.user.is_authenticated else _(
                              "You should receive an email shortly "
                              "to confirm your subscription."))
            return HttpResponse(json.dumps({"message": msg}))

        if request.POST.get("from_vote"):
            tmpl = "questions/includes/question_vote_thanks.html"
        else:
            tmpl = "questions/includes/email_subscribe.html"

        html = render_to_string(tmpl,
                                context={
                                    "question": question,
                                    "watch_form": form
                                },
                                request=request)
        return HttpResponse(json.dumps({"html": html}))

    if msg:
        messages.add_message(request, messages.ERROR, msg)

    return HttpResponseRedirect(question.get_absolute_url())
コード例 #17
0
ファイル: test_notifications.py プロジェクト: Puddo/kitsune
    def test_notify_anonymous(self):
        """Test that anonymous users are notified of new answers."""
        ANON_EMAIL = '*****@*****.**'
        QuestionReplyEvent.notify(ANON_EMAIL, self.question)
        self.makeAnswer()

        # One for the asker's email, and one for the anonymous email.
        eq_(2, len(mail.outbox))
        notification = [m for m in mail.outbox if m.to == [ANON_EMAIL]][0]

        eq_([ANON_EMAIL], notification.to)
        eq_("{0} commented on a Firefox question you're watching"
            .format(self.answer.creator.username),
            notification.subject)

        body = re.sub(r'auth=[a-zA-Z0-9%_-]+', 'auth=AUTH', notification.body)
        starts_with(body, ANSWER_EMAIL_TO_ANONYMOUS
                    .format(**self.format_args()))
コード例 #18
0
ファイル: test_notifications.py プロジェクト: ziegeer/kitsune
    def test_notify_unique_auth_tokens(self, email_mock):
        """Test that arbitrary users get unique auth tokens."""
        auth_backend = TokenLoginBackend()
        auth_re = re.compile(r'auth=([a-zA-Z0-9%_-]+)')
        watcher = UserFactory()
        QuestionReplyEvent.notify(watcher, self.question)
        asker_id = self.question.creator.id
        self.makeAnswer()

        def get_auth_token(ctx):
            return auth_re.search(ctx['answer_url']).group(1).replace('%3D', '=')

        eq_(email_mock.call_count, 2)
        all_calls = email_mock.call_args_list
        for call in all_calls:
            ctx = call[1]['context_vars']
            user = ctx['to_user']
            if user.id == asker_id:
                auth = get_auth_token(ctx)
                eq_(user, auth_backend.authenticate(auth))
            else:
                assert auth_re.search(ctx['answer_url']) is None
コード例 #19
0
ファイル: test_notifications.py プロジェクト: MikkCZ/kitsune
    def test_notify_unique_auth_tokens(self, email_mock):
        """Test that arbitrary users get unique auth tokens."""
        auth_backend = TokenLoginBackend()
        auth_re = re.compile(r'auth=([a-zA-Z0-9%_-]+)')
        watcher = UserFactory()
        QuestionReplyEvent.notify(watcher, self.question)
        asker_id = self.question.creator.id
        self.makeAnswer()

        def get_auth_token(ctx):
            return auth_re.search(ctx['answer_url']).group(1).replace('%3D', '=')

        eq_(email_mock.call_count, 2)
        all_calls = email_mock.call_args_list
        for call in all_calls:
            ctx = call[1]['context_vars']
            user = ctx['to_user']
            if user.id == asker_id:
                auth = get_auth_token(ctx)
                eq_(user, auth_backend.authenticate(auth))
            else:
                assert auth_re.search(ctx['answer_url']) is None
コード例 #20
0
 def setUp(self):
     super(TestAnswerNotifications, self).setUp()
     self._get_current_mock = mock.patch.object(Site.objects, 'get_current')
     self._get_current_mock.start().return_value.domain = 'testserver'
     self.question = QuestionFactory()
     QuestionReplyEvent.notify(self.question.creator, self.question)
コード例 #21
0
ファイル: test_templates.py プロジェクト: 1234-/kitsune
    def setUp(self):
        self.user = UserFactory()
        self.client.login(username=self.user.username, password='******')

        self.question = QuestionFactory(creator=self.user)
        QuestionReplyEvent.notify(self.user, self.question)
コード例 #22
0
    def test_answer_notification(self, get_current):
        """Assert that hitting the watch toggle toggles and that proper mails
        are sent to anonymous users, registered users, and the question
        asker."""
        # TODO: This test is way too monolithic, and the fixtures encode
        # assumptions that aren't obvious here. Split this test into about 5,
        # each of which tests just 1 thing. Consider using instantiation
        # helpers.
        get_current.return_value.domain = 'testserver'

        # An arbitrary registered user watches:
        watcher = user(save=True)
        q = self._toggle_watch_question('reply', watcher, turn_on=True)

        # An anonymous user watches:
        QuestionReplyEvent.notify('*****@*****.**', q)

        # The question asker watches:
        QuestionReplyEvent.notify(q.creator, q)

        # Post a reply
        replier = user(save=True)
        self.client.login(username=replier.username, password='******')
        post(self.client, 'questions.reply', {'content': 'an answer'},
             args=[q.id])

        a = Answer.uncached.filter().order_by('-id')[0]

        # Order of emails is not important.
        eq_(3, len(mail.outbox))

        emails_to = [m.to[0] for m in mail.outbox]

        i = emails_to.index(watcher.email)
        attrs_eq(mail.outbox[i], to=[watcher.email],
                 subject='%s commented on a Firefox question '
                         "you're watching" % a.creator.username)
        body = mail.outbox[i].body
        body = re.sub(r'auth=[a-zA-Z0-9%_-]+', r'auth=AUTH', body)
        starts_with(body, ANSWER_EMAIL.format(
            to_user=watcher.username,
            title=q.title,
            content=a.content,
            replier=replier.username,
            question_id=q.id,
            answer_id=a.id))

        i = emails_to.index(q.creator.email)
        attrs_eq(mail.outbox[i], to=[q.creator.email],
                 subject='%s posted an answer to your question "%s"' %
                         (a.creator.username, q.title))
        body = mail.outbox[i].body
        body = re.sub(r'auth=[a-zA-Z0-9%_-]+', r'auth=AUTH', body)
        starts_with(body, ANSWER_EMAIL_TO_ASKER.format(
            asker=q.creator.username,
            title=q.title,
            content=a.content,
            replier=replier.username,
            question_id=q.id,
            answer_id=a.id))

        i = emails_to.index('*****@*****.**')
        attrs_eq(mail.outbox[i], to=['*****@*****.**'],
                 subject="%s commented on a Firefox question you're watching" %
                         a.creator.username)
        body = mail.outbox[i].body
        body = re.sub(r'auth=[a-zA-Z0-9%_-]+', r'auth=AUTH', body)
        starts_with(body, ANSWER_EMAIL_TO_ANONYMOUS.format(
            title=q.title,
            content=a.content,
            replier=replier.username,
            question_id=q.id,
            answer_id=a.id))
コード例 #23
0
ファイル: test_templates.py プロジェクト: wrg2020/kitsune
    def setUp(self):
        self.user = UserFactory()
        self.client.login(username=self.user.username, password='******')

        self.question = QuestionFactory(creator=self.user)
        QuestionReplyEvent.notify(self.user, self.question)
コード例 #24
0
    def test_answer_notification(self, get_current):
        """Assert that hitting the watch toggle toggles and that proper mails
        are sent to anonymous users, registered users, and the question
        asker."""
        # TODO: This test is way too monolithic, and the fixtures encode
        # assumptions that aren't obvious here. Split this test into about 5,
        # each of which tests just 1 thing. Consider using instantiation
        # helpers.
        get_current.return_value.domain = 'testserver'

        # An arbitrary registered user watches:
        watcher = user(save=True)
        q = self._toggle_watch_question('reply', watcher, turn_on=True)

        # An anonymous user watches:
        QuestionReplyEvent.notify('*****@*****.**', q)

        # The question asker watches:
        QuestionReplyEvent.notify(q.creator, q)

        # Post a reply
        replier = user(save=True)
        self.client.login(username=replier.username, password='******')
        post(self.client,
             'questions.reply', {'content': 'an answer'},
             args=[q.id])

        a = Answer.uncached.filter().order_by('-id')[0]

        # Order of emails is not important.
        eq_(3, len(mail.outbox))

        emails_to = [m.to[0] for m in mail.outbox]

        i = emails_to.index(watcher.email)
        attrs_eq(mail.outbox[i],
                 to=[watcher.email],
                 subject='%s commented on a Firefox question '
                 "you're watching" % a.creator.username)
        starts_with(
            mail.outbox[i].body,
            ANSWER_EMAIL.format(to_user=watcher.username,
                                title=q.title,
                                content=a.content,
                                replier=replier.username,
                                question_id=q.id,
                                answer_id=a.id))

        i = emails_to.index(q.creator.email)
        attrs_eq(mail.outbox[i],
                 to=[q.creator.email],
                 subject='%s posted an answer to your question "%s"' %
                 (a.creator.username, q.title))
        starts_with(
            mail.outbox[i].body,
            ANSWER_EMAIL_TO_ASKER.format(asker=q.creator.username,
                                         title=q.title,
                                         content=a.content,
                                         replier=replier.username,
                                         question_id=q.id,
                                         answer_id=a.id))

        i = emails_to.index('*****@*****.**')
        attrs_eq(mail.outbox[i],
                 to=['*****@*****.**'],
                 subject="%s commented on a Firefox question you're watching" %
                 a.creator.username)
        starts_with(
            mail.outbox[i].body,
            ANSWER_EMAIL_TO_ANONYMOUS.format(title=q.title,
                                             content=a.content,
                                             replier=replier.username,
                                             question_id=q.id,
                                             answer_id=a.id))