Beispiel #1
0
def add(request, addon, template=None):
    if addon.has_author(request.user):
        raise PermissionDenied
    form = forms.ReviewForm(request.POST or None)
    if (request.method == 'POST' and form.is_valid() and
        not request.POST.get('detailed')):
        details = _review_details(request, addon, form)
        review = Review.objects.create(**details)
        if 'flag' in form.cleaned_data and form.cleaned_data['flag']:
            rf = ReviewFlag(review=review,
                        user_id=request.user.id,
                        flag=ReviewFlag.OTHER,
                        note='URLs')
            rf.save()

        amo.log(amo.LOG.ADD_REVIEW, addon, review)
        log.debug('New review: %s' % review.id)

        reply_url = shared_url('reviews.reply', addon, review.id,
                               add_prefix=False)
        data = {'name': addon.name,
                'rating': '%s out of 5 stars' % details['rating'],
                'review': details['body'],
                'reply_url': absolutify(reply_url)}

        emails = [a.email for a in addon.authors.all()]
        send_mail('reviews/emails/add_review.ltxt',
                  u'Mozilla Add-on User Review: %s' % addon.name,
                  emails, Context(data), 'new_review')

        return redirect(shared_url('reviews.list', addon))
    return render(request, template, dict(addon=addon, form=form))
Beispiel #2
0
def reply(request, addon, review_id):
    is_admin = acl.action_allowed(request, "Addons", "Edit")
    is_author = acl.check_addon_ownership(request, addon, dev=True)
    if not (is_admin or is_author):
        raise PermissionDenied

    review = get_object_or_404(Review.objects, pk=review_id, addon=addon)
    form = forms.ReviewReplyForm(request.POST or None)
    if request.method == "POST" and form.is_valid():
        d = dict(reply_to=review, addon=addon, defaults=dict(user=request.amo_user))
        reply, new = Review.objects.get_or_create(**d)
        for key, val in _review_details(request, addon, form).items():
            setattr(reply, key, val)
        reply.save()
        action = "New" if new else "Edited"
        log.debug("%s reply to %s: %s" % (action, review_id, reply.id))

        if new:
            reply_url = shared_url("reviews.detail", addon, review.id, add_prefix=False)
            data = {
                "name": addon.name,
                "reply_title": reply.title,
                "reply": reply.body,
                "reply_url": absolutify(reply_url),
            }
            emails = [review.user.email]
            sub = u"Mozilla Add-on Developer Reply: %s" % addon.name
            send_mail("reviews/emails/reply_review.ltxt", sub, emails, Context(data), "reply")

        return redirect(shared_url("reviews.detail", addon, review_id))
    ctx = dict(review=review, form=form, addon=addon)
    return render(request, "reviews/reply.html", ctx)
Beispiel #3
0
 def test_addonurl(self):
     expected = "/en-US/firefox/addon/addon/"
     eq_(helpers.shared_url("addons.detail", self.addon), expected)
     eq_(helpers.shared_url("apps.detail", self.addon), expected)
     eq_(helpers.shared_url("detail", self.addon), expected)
     eq_(helpers.shared_url("detail", self.addon, add_prefix=False), "/addon/addon/")
     eq_(helpers.shared_url("reviews.detail", self.addon, 1, add_prefix=False), "/addon/addon/reviews/1/")
Beispiel #4
0
def add(request, addon, template=None):
    if addon.has_author(request.user):
        raise PermissionDenied
    form = forms.ReviewForm(request.POST or None)
    if request.method == "POST" and form.is_valid() and not request.POST.get("detailed"):
        details = _review_details(request, addon, form)
        review = Review.objects.create(**details)
        if "flag" in form.cleaned_data and form.cleaned_data["flag"]:
            rf = ReviewFlag(review=review, user_id=request.user.id, flag=ReviewFlag.OTHER, note="URLs")
            rf.save()

        amo.log(amo.LOG.ADD_REVIEW, addon, review)
        log.debug("New review: %s" % review.id)

        reply_url = shared_url("reviews.reply", addon, review.id, add_prefix=False)
        data = {
            "name": addon.name,
            "rating": "%s out of 5 stars" % details["rating"],
            "review": details["body"],
            "reply_url": absolutify(reply_url),
        }

        emails = [a.email for a in addon.authors.all()]
        send_mail(
            "reviews/emails/add_review.ltxt",
            u"Mozilla Add-on User Review: %s" % addon.name,
            emails,
            Context(data),
            "new_review",
        )

        return redirect(shared_url("reviews.list", addon))
    return render(request, template, dict(addon=addon, form=form))
Beispiel #5
0
def reply(request, addon, review_id):
    is_admin = acl.action_allowed(request, 'Addons', 'Edit')
    is_author = acl.check_addon_ownership(request, addon, dev=True)
    if not (is_admin or is_author):
        return http.HttpResponseForbidden()

    review = get_object_or_404(Review.objects, pk=review_id, addon=addon)
    form = forms.ReviewReplyForm(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        d = dict(reply_to=review, addon=addon,
                 defaults=dict(user=request.amo_user))
        reply, new = Review.objects.get_or_create(**d)
        for key, val in _review_details(request, addon, form).items():
            setattr(reply, key, val)
        reply.save()
        action = 'New' if new else 'Edited'
        log.debug('%s reply to %s: %s' % (action, review_id, reply.id))

        if new:
            reply_url = shared_url('reviews.detail', addon, review.id,
                                   add_prefix=False)
            data = {'name': addon.name,
                    'reply_title': reply.title,
                    'reply': reply.body,
                    'reply_url': absolutify(reply_url)}
            emails = [review.user.email]
            sub = u'Mozilla Add-on Developer Reply: %s' % addon.name
            send_mail('reviews/emails/reply_review.ltxt',
                      sub, emails, Context(data), 'reply')

        return redirect(shared_url('reviews.detail', addon, review_id))
    ctx = dict(review=review, form=form, addon=addon)
    return jingo.render(request, 'reviews/reply.html', ctx)
Beispiel #6
0
 def test_addonurl(self):
     expected = '/en-US/firefox/addon/addon/'
     eq_(helpers.shared_url('addons.detail', self.addon), expected)
     eq_(helpers.shared_url('apps.detail', self.addon), expected)
     eq_(helpers.shared_url('detail', self.addon), expected)
     eq_(helpers.shared_url('detail', self.addon, add_prefix=False),
         '/addon/addon/')
Beispiel #7
0
def add(request, addon, template=None):
    if addon.has_author(request.user):
        return http.HttpResponseForbidden()
    form = forms.ReviewForm(request.POST or None)
    if (request.method == 'POST' and form.is_valid()
            and not request.POST.get('detailed')):
        details = _review_details(request, addon, form)
        review = Review.objects.create(**details)
        amo.log(amo.LOG.ADD_REVIEW, addon, review)
        log.debug('New review: %s' % review.id)

        reply_url = shared_url('reviews.reply',
                               addon,
                               review.id,
                               add_prefix=False)
        data = {
            'name': addon.name,
            'rating': '%s out of 5 stars' % details['rating'],
            'review': details['body'],
            'reply_url': absolutify(reply_url)
        }

        emails = [a.email for a in addon.authors.all()]
        send_mail('reviews/emails/add_review.ltxt',
                  u'Mozilla Add-on User Review: %s' % addon.name, emails,
                  Context(data), 'new_review')

        return redirect(shared_url('reviews.list', addon))
    return jingo.render(request, template, dict(addon=addon, form=form))
Beispiel #8
0
def add(request, addon, template=None):
    if addon.has_author(request.user):
        raise PermissionDenied
    form = forms.ReviewForm(request.POST or None)
    if (request.method == 'POST' and form.is_valid() and
        not request.POST.get('detailed')):
        details = _review_details(request, addon, form)
        review = Review.objects.create(**details)
        if 'flag' in form.cleaned_data and form.cleaned_data['flag']:
            rf = ReviewFlag(review=review,
                        user_id=request.user.id,
                        flag=ReviewFlag.OTHER,
                        note='URLs')
            rf.save()

        amo.log(amo.LOG.ADD_REVIEW, addon, review)
        log.debug('New review: %s' % review.id)

        reply_url = shared_url('reviews.reply', addon, review.id,
                               add_prefix=False)
        data = {'name': addon.name,
                'rating': '%s out of 5 stars' % details['rating'],
                'review': details['body'],
                'reply_url': absolutify(reply_url)}

        emails = [a.email for a in addon.authors.all()]
        send_mail('reviews/emails/add_review.ltxt',
                  u'Mozilla Add-on User Review: %s' % addon.name,
                  emails, Context(data), 'new_review')

        return redirect(shared_url('reviews.list', addon))
    return render(request, template, dict(addon=addon, form=form))
Beispiel #9
0
def reply(request, addon, review_id):
    is_admin = acl.action_allowed(request, 'Addons', 'Edit')
    is_author = acl.check_addon_ownership(request, addon, dev=True)
    if not (is_admin or is_author):
        raise PermissionDenied

    review = get_object_or_404(Review.objects, pk=review_id, addon=addon)
    form = forms.ReviewReplyForm(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        d = dict(reply_to=review, addon=addon,
                 defaults=dict(user=request.amo_user))
        reply, new = Review.objects.get_or_create(**d)
        for key, val in _review_details(request, addon, form).items():
            setattr(reply, key, val)
        reply.save()
        action = 'New' if new else 'Edited'
        log.debug('%s reply to %s: %s' % (action, review_id, reply.id))

        if new:
            reply_url = shared_url('reviews.detail', addon, review.id,
                                   add_prefix=False)
            data = {'name': addon.name,
                    'reply_title': reply.title,
                    'reply': reply.body,
                    'reply_url': absolutify(reply_url)}
            emails = [review.user.email]
            sub = u'Mozilla Add-on Developer Reply: %s' % addon.name
            send_mail('reviews/emails/reply_review.ltxt',
                      sub, emails, Context(data), 'reply')

        return redirect(shared_url('reviews.detail', addon, review_id))
    ctx = dict(review=review, form=form, addon=addon)
    return render(request, 'reviews/reply.html', ctx)
Beispiel #10
0
def add(request, addon, template=None):
    if addon.has_author(request.user):
        return http.HttpResponseForbidden()
    form = forms.ReviewForm(request.POST or None)
    if (request.method == 'POST' and form.is_valid() and
        not request.POST.get('detailed')):
        details = _review_details(request, addon, form)
        review = Review.objects.create(**details)
        amo.log(amo.LOG.ADD_REVIEW, addon, review)
        log.debug('New review: %s' % review.id)

        reply_url = shared_url('reviews.reply', addon, review.id,
                               add_prefix=False)
        data = {'name': addon.name,
                'rating': '%s out of 5 stars' % details['rating'],
                'review': details['body'],
                'reply_url': absolutify(reply_url)}

        emails = [a.email for a in addon.authors.all()]
        send_mail('reviews/emails/add_review.ltxt',
                  u'Mozilla Add-on User Review: %s' % addon.name,
                  emails, Context(data), 'new_review')

        # Update the ratings and counts for the add-on.
        addon_review_aggregates.delay(addon.id, using='default')

        return redirect(shared_url('reviews.list', addon))
    return jingo.render(request, template, dict(addon=addon, form=form))
Beispiel #11
0
 def test_double_reply(self):
     self.login_dev()
     url = shared_url("reviews.reply", self.addon, 218207)
     r = self.client.post(url, {"body": "unst unst"})
     self.assertRedirects(r, shared_url("reviews.detail", self.addon, 218207))
     eq_(self.qs.filter(reply_to=218207).count(), 1)
     review = Review.objects.get(id=218468)
     eq_("%s" % review.body, "unst unst")
Beispiel #12
0
 def setUp(self):
     super(TestCreate, self).setUp()
     self.add = shared_url("reviews.add", self.addon)
     self.client.login(username="******", password="******")
     self.user = UserProfile.objects.get(email="*****@*****.**")
     self.qs = Review.objects.filter(addon=1865)
     self.log_count = ActivityLog.objects.count
     self.more = self.addon.get_url_path(more=True)
     self.list = shared_url("reviews.list", self.addon)
Beispiel #13
0
 def test_double_reply(self):
     self.login_dev()
     url = shared_url('reviews.reply', self.addon, 218207)
     r = self.client.post(url, {'body': 'unst unst'})
     self.assertRedirects(r, shared_url('reviews.detail', self.addon,
                                        218207))
     eq_(self.qs.filter(reply_to=218207).count(), 1)
     review = Review.objects.get(id=218468)
     eq_('%s' % review.body, 'unst unst')
Beispiel #14
0
 def setUp(self):
     super(TestCreate, self).setUp()
     self.add = shared_url('reviews.add', self.addon)
     self.client.login(username='******', password='******')
     self.user = UserProfile.objects.get(email='*****@*****.**')
     self.qs = Review.objects.filter(addon=1865)
     self.log_count = ActivityLog.objects.count
     self.more = self.addon.get_url_path(more=True)
     self.list = shared_url('reviews.list', self.addon)
Beispiel #15
0
 def test_double_reply(self):
     self.login_dev()
     url = shared_url('reviews.reply', self.addon, 218207)
     r = self.client.post(url, {'body': 'unst unst'})
     self.assertRedirects(r,
         shared_url('reviews.detail', self.addon, 218207))
     eq_(self.qs.filter(reply_to=218207).count(), 1)
     review = Review.objects.get(id=218468)
     eq_('%s' % review.body, 'unst unst')
Beispiel #16
0
 def test_addonurl(self):
     expected = '/en-US/firefox/addon/addon/'
     eq_(helpers.shared_url('addons.detail', self.addon), expected)
     eq_(helpers.shared_url('apps.detail', self.addon), expected)
     eq_(helpers.shared_url('detail', self.addon), expected)
     eq_(helpers.shared_url('detail', self.addon, add_prefix=False),
         '/addon/addon/')
     eq_(helpers.shared_url('reviews.detail', self.addon, 1,
                            add_prefix=False),
         '/addon/addon/reviews/1/')
Beispiel #17
0
 def test_appurl(self):
     expected = '/en-US/apps/app/webapp/'
     eq_(helpers.shared_url('addons.detail', self.webapp), expected)
     eq_(helpers.shared_url('apps.detail', self.webapp), expected)
     eq_(helpers.shared_url('detail', self.webapp), expected)
     eq_(helpers.shared_url('detail', self.webapp, add_prefix=False),
         '/apps/app/webapp/')
     eq_(helpers.shared_url('reviews.detail', self.webapp, 1,
                            add_prefix=False),
         '/apps/app/webapp/reviews/1/')
Beispiel #18
0
    def test_new_reply(self):
        self.login_dev()
        Review.objects.filter(reply_to__isnull=False).delete()
        url = shared_url("reviews.reply", self.addon, 218207)
        r = self.client.post(url, {"body": "unst unst"})
        self.assertRedirects(r, shared_url("reviews.detail", self.addon, 218207))
        eq_(self.qs.filter(reply_to=218207).count(), 1)

        eq_(len(mail.outbox), 1)
        self.assertTemplateUsed(r, "reviews/emails/reply_review.ltxt")
Beispiel #19
0
    def test_new_reply(self):
        self.login_dev()
        Review.objects.filter(reply_to__isnull=False).delete()
        url = shared_url('reviews.reply', self.addon, 218207)
        r = self.client.post(url, {'body': 'unst unst'})
        self.assertRedirects(r, shared_url('reviews.detail', self.addon,
                                           218207))
        eq_(self.qs.filter(reply_to=218207).count(), 1)

        eq_(len(mail.outbox), 1)
        self.assertTemplateUsed(r, 'reviews/emails/reply_review.ltxt')
Beispiel #20
0
 def test_edit_reply(self):
     self.login_dev()
     url = shared_url("reviews.edit", self.addon, 218468)
     r = self.client.post(url, {"title": "fo", "body": "shizzle"}, X_REQUESTED_WITH="XMLHttpRequest")
     eq_(r.status_code, 200)
     review = Review.objects.get(id=218468)
     eq_("%s" % review.title, "fo")
     eq_("%s" % review.body, "shizzle")
Beispiel #21
0
 def test_unicode_call(self):
     review = Review.objects.create(addon=self.addon, user=self.user,
                                    title='or', body=u'héhé 3%')
     url = shared_url('reviews.translate', review.addon, review.id, 'fr')
     r = self.client.get(url)
     eq_(r.status_code, 302)
     eq_(r.get('Location'),
         'https://translate.google.com/#auto/fr/h%C3%A9h%C3%A9%203%25')
Beispiel #22
0
 def test_edit_not_owner(self):
     url = shared_url('reviews.edit', self.addon, 218468)
     r = self.client.post(url, {
         'rating': 2,
         'body': 'woo woo'
     },
                          X_REQUESTED_WITH='XMLHttpRequest')
     eq_(r.status_code, 403)
Beispiel #23
0
 def test_unicode_call(self):
     review = Review.objects.create(addon=self.addon, user=self.user,
                                    title='or', body=u'héhé 3%')
     url = shared_url('reviews.translate', review.addon, review.id, 'fr')
     r = self.client.get(url)
     eq_(r.status_code, 302)
     eq_(r.get('Location'),
         'https://translate.google.com/#auto/fr/h%C3%A9h%C3%A9%203%25')
Beispiel #24
0
 def test_add_link_dev(self):
     """Ensure developer cannot see Add Review links."""
     self.login_dev()
     r = self.client.get_ajax(self.more)
     eq_(pq(r.content)("#add-review").length, 0)
     r = self.client.get(shared_url("reviews.list", self.addon))
     doc = pq(r.content)
     eq_(doc("#add-review").length, 0)
     eq_(doc("#add-first-review").length, 0)
Beispiel #25
0
 def test_delete_own_review(self):
     self.client.logout()
     self.login_dev()
     url = shared_url('reviews.delete', self.addon, 218468)
     cnt = Review.objects.count()
     response = self.client.post(url)
     eq_(response.status_code, 200)
     eq_(Review.objects.count(), cnt - 1)
     eq_(Review.objects.filter(pk=218468).exists(), False)
Beispiel #26
0
 def test_add_link_dev(self):
     """Ensure developer cannot see Add Review links."""
     self.login_dev()
     r = self.client.get_ajax(self.more)
     eq_(pq(r.content)('#add-review').length, 0)
     r = self.client.get(shared_url('reviews.list', self.addon))
     doc = pq(r.content)
     eq_(doc('#add-review').length, 0)
     eq_(doc('#add-first-review').length, 0)
Beispiel #27
0
 def test_delete_own_review(self):
     self.client.logout()
     self.login_dev()
     url = shared_url("reviews.delete", self.addon, 218468)
     cnt = Review.objects.count()
     response = self.client.post(url)
     eq_(response.status_code, 200)
     eq_(Review.objects.count(), cnt - 1)
     eq_(Review.objects.filter(pk=218468).exists(), False)
Beispiel #28
0
 def test_edit(self):
     url = shared_url('reviews.edit', self.addon, 218207)
     r = self.client.post(url, {
         'rating': 2,
         'body': 'woo woo'
     },
                          X_REQUESTED_WITH='XMLHttpRequest')
     eq_(r.status_code, 200)
     eq_('%s' % Review.objects.get(id=218207).body, 'woo woo')
Beispiel #29
0
 def test_edit_reply(self):
     self.login_dev()
     url = shared_url('reviews.edit', self.addon, 218468)
     r = self.client.post(url, {'title': 'fo', 'body': 'shizzle'},
                          X_REQUESTED_WITH='XMLHttpRequest')
     eq_(r.status_code, 200)
     review = Review.objects.get(id=218468)
     eq_('%s' % review.title, 'fo')
     eq_('%s' % review.body, 'shizzle')
Beispiel #30
0
 def test_edit_reply(self):
     self.login_dev()
     url = shared_url('reviews.edit', self.addon, 218468)
     r = self.client.post(url, {'title': 'fo', 'body': 'shizzle'},
                          X_REQUESTED_WITH='XMLHttpRequest')
     eq_(r.status_code, 200)
     review = Review.objects.get(id=218468)
     eq_('%s' % review.title, 'fo')
     eq_('%s' % review.body, 'shizzle')
Beispiel #31
0
 def test_empty_list(self):
     Review.objects.all().delete()
     eq_(Review.objects.count(), 0)
     r = self.client.get(shared_url('reviews.list', self.addon))
     eq_(r.status_code, 200)
     doc = pq(r.content)
     eq_(doc('#reviews .item').length, 0)
     eq_(doc('#add-first-review').length, 1)
     eq_(doc('.secondary .average-rating').length, 0)
     eq_(doc('.secondary .no-rating').length, 1)
Beispiel #32
0
 def test_empty_list(self):
     Review.objects.all().delete()
     eq_(Review.objects.count(), 0)
     r = self.client.get(shared_url("reviews.list", self.addon))
     eq_(r.status_code, 200)
     doc = pq(r.content)
     eq_(doc("#reviews .item").length, 0)
     eq_(doc("#add-first-review").length, 1)
     eq_(doc(".secondary .average-rating").length, 0)
     eq_(doc(".secondary .no-rating").length, 1)
Beispiel #33
0
 def test_add_link_visitor(self):
     """
     Ensure non-logged user can see Add Review links on details page
     but not on Reviews listing page.
     """
     self.client.logout()
     r = self.client.get_ajax(self.more)
     eq_(pq(r.content)("#add-review").length, 1)
     r = self.client.get(shared_url("reviews.list", self.addon))
     doc = pq(r.content)
     eq_(doc("#add-review").length, 0)
     eq_(doc("#add-first-review").length, 0)
Beispiel #34
0
 def test_add_link_visitor(self):
     """
     Ensure non-logged user can see Add Review links on details page
     but not on Reviews listing page.
     """
     self.client.logout()
     r = self.client.get_ajax(self.more)
     eq_(pq(r.content)('#add-review').length, 1)
     r = self.client.get(shared_url('reviews.list', self.addon))
     doc = pq(r.content)
     eq_(doc('#add-review').length, 0)
     eq_(doc('#add-first-review').length, 0)
Beispiel #35
0
def purchase_complete(request, addon, status):
    result = ''
    if status == 'complete':
        uuid_ = request.GET.get('uuid')
        log.debug('Looking up contrib for uuid: %s' % uuid_)

        # The IPN may, or may not have come through. Which means looking for
        # a for pre or post IPN contributions. If both fail, then we've not
        # got a matching contribution.
        lookup = (Q(uuid=uuid_, type=amo.CONTRIB_PENDING)
                  | Q(transaction_id=uuid_, type=amo.CONTRIB_PURCHASE))
        con = get_object_or_404(Contribution, lookup)

        log.debug('Check purchase paypal addon: %s, user: %s, paykey: %s' %
                  (addon.pk, request.amo_user.pk, con.paykey[:10]))
        try:
            result = paypal.check_purchase(con.paykey)
            if result == 'ERROR':
                paypal.paypal_log_cef(
                    request, addon, uuid_, 'Purchase Fail', 'PURCHASEFAIL',
                    'Checking purchase state returned error')
                raise
        except:
            paypal.paypal_log_cef(
                request, addon, uuid_, 'Purchase Fail', 'PURCHASEFAIL',
                'There was an error checking purchase state')
            log.error('Check purchase paypal addon: %s, user: %s, paykey: %s' %
                      (addon.pk, request.amo_user.pk, con.paykey[:10]),
                      exc_info=True)
            result = 'ERROR'
            status = 'error'

        log.debug('Paypal returned: %s for paykey: %s' %
                  (result, con.paykey[:10]))
        if result == 'COMPLETED' and con.type == amo.CONTRIB_PENDING:
            con.update(type=amo.CONTRIB_PURCHASE)

    context = {
        'realurl': request.GET.get('realurl', ''),
        'status': status,
        'result': result
    }

    # For mobile, bounce back to the details page.
    if request.MOBILE:
        url = urlparams(shared_url('detail', addon), **context)
        return http.HttpResponseRedirect(url)

    context.update({'addon': addon})
    response = jingo.render(request, 'addons/paypal_result.html', context)
    response['x-frame-options'] = 'allow'
    return response
Beispiel #36
0
    def test_review_success(self):
        old_cnt = self.qs.count()
        log_count = self.log_count()
        r = self.client.post(self.add, {"body": "xx", "rating": 3})
        self.assertRedirects(r, shared_url("reviews.list", self.addon), status_code=302)
        eq_(self.qs.count(), old_cnt + 1)
        # We should have an ADD_REVIEW entry now.
        eq_(self.log_count(), log_count + 1)

        eq_(len(mail.outbox), 1)

        assert "3 out of 5" in mail.outbox[0].body, "Rating not included"
        self.assertTemplateUsed(r, "reviews/emails/add_review.ltxt")
Beispiel #37
0
    def test_review_success(self):
        old_cnt = self.qs.count()
        log_count = self.log_count()
        r = self.client.post(self.add, {'body': 'xx', 'rating': 3})
        self.assertRedirects(r, shared_url('reviews.list', self.addon),
                             status_code=302)
        eq_(self.qs.count(), old_cnt + 1)
        # We should have an ADD_REVIEW entry now.
        eq_(self.log_count(), log_count + 1)

        eq_(len(mail.outbox), 1)

        assert '3 out of 5' in mail.outbox[0].body, "Rating not included"
        self.assertTemplateUsed(r, 'reviews/emails/add_review.ltxt')
Beispiel #38
0
    def test_invalid_api_key(self, requests):
        # Mock requests.
        response = mock.Mock()
        response.status_code = 400
        response.json.return_value = {'error': {'code': 400, 'errors': [{
            'domain': 'usageLimits', 'message': 'Bad Request',
            'reason': 'keyInvalid'}], 'message': 'Bad Request'}}
        requests.get.return_value = response

        # Call translation.
        review = self.review
        url = shared_url('reviews.translate', review.addon, review.id, 'fr')
        r = self.client.get(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        eq_(r.status_code, 400)
Beispiel #39
0
    def test_invalid_api_key(self, requests):
        # Mock requests.
        response = mock.Mock()
        response.status_code = 400
        response.json.return_value = {'error': {'code': 400, 'errors': [{
            'domain': 'usageLimits', 'message': 'Bad Request',
            'reason': 'keyInvalid'}], 'message': 'Bad Request'}}
        requests.get.return_value = response

        # Call translation.
        review = self.review
        url = shared_url('reviews.translate', review.addon, review.id, 'fr')
        r = self.client.get(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        eq_(r.status_code, 400)
Beispiel #40
0
def purchase_complete(request, addon, status):
    result = ""
    if status == "complete":
        uuid_ = request.GET.get("uuid")
        log.debug("Looking up contrib for uuid: %s" % uuid_)

        # The IPN may, or may not have come through. Which means looking for
        # a for pre or post IPN contributions. If both fail, then we've not
        # got a matching contribution.
        lookup = Q(uuid=uuid_, type=amo.CONTRIB_PENDING) | Q(transaction_id=uuid_, type=amo.CONTRIB_PURCHASE)
        con = get_object_or_404(Contribution, lookup)

        log.debug(
            "Check purchase paypal addon: %s, user: %s, paykey: %s" % (addon.pk, request.amo_user.pk, con.paykey[:10])
        )
        try:
            result = paypal.check_purchase(con.paykey)
            if result == "ERROR":
                paypal.paypal_log_cef(
                    request, addon, uuid_, "Purchase Fail", "PURCHASEFAIL", "Checking purchase state returned error"
                )
                raise
        except:
            paypal.paypal_log_cef(
                request, addon, uuid_, "Purchase Fail", "PURCHASEFAIL", "There was an error checking purchase state"
            )
            log.error(
                "Check purchase paypal addon: %s, user: %s, paykey: %s"
                % (addon.pk, request.amo_user.pk, con.paykey[:10]),
                exc_info=True,
            )
            result = "ERROR"
            status = "error"

        log.debug("Paypal returned: %s for paykey: %s" % (result, con.paykey[:10]))
        if result == "COMPLETED" and con.type == amo.CONTRIB_PENDING:
            con.update(type=amo.CONTRIB_PURCHASE)

    context = {"realurl": request.GET.get("realurl", ""), "status": status, "result": result}

    # For mobile, bounce back to the details page.
    if request.MOBILE:
        url = urlparams(shared_url("detail", addon), **context)
        return redirect(url)

    context.update({"addon": addon})
    response = jingo.render(request, "addons/paypal_result.html", context)
    response["x-frame-options"] = "allow"
    return response
Beispiel #41
0
def purchase_complete(request, addon, status):
    result = ''
    if status == 'complete':
        uuid_ = request.GET.get('uuid')
        log.debug('Looking up contrib for uuid: %s' % uuid_)

        # The IPN may, or may not have come through. Which means looking for
        # a for pre or post IPN contributions. If both fail, then we've not
        # got a matching contribution.
        lookup = (Q(uuid=uuid_, type=amo.CONTRIB_PENDING) |
                  Q(transaction_id=uuid_, type=amo.CONTRIB_PURCHASE))
        con = get_object_or_404(Contribution, lookup)

        log.debug('Check purchase paypal addon: %s, user: %s, paykey: %s'
                  % (addon.pk, request.amo_user.pk, con.paykey[:10]))
        try:
            result = paypal.check_purchase(con.paykey)
            if result == 'ERROR':
                paypal.paypal_log_cef(request, addon, uuid_, 'Purchase Fail',
                                      'PURCHASEFAIL',
                                      'Checking purchase state returned error')
                raise
        except:
            paypal.paypal_log_cef(request, addon, uuid_, 'Purchase Fail',
                                  'PURCHASEFAIL',
                                  'There was an error checking purchase state')
            log.error('Check purchase paypal addon: %s, user: %s, paykey: %s'
                      % (addon.pk, request.amo_user.pk, con.paykey[:10]),
                      exc_info=True)
            result = 'ERROR'
            status = 'error'

        log.debug('Paypal returned: %s for paykey: %s'
                  % (result, con.paykey[:10]))
        if result == 'COMPLETED' and con.type == amo.CONTRIB_PENDING:
            con.update(type=amo.CONTRIB_PURCHASE)

    context = {'realurl': request.GET.get('realurl', ''),
               'status': status, 'result': result}

    # For mobile, bounce back to the details page.
    if request.MOBILE:
        url = urlparams(shared_url('detail', addon), **context)
        return http.HttpResponseRedirect(url)

    context.update({'addon': addon})
    response = jingo.render(request, 'addons/paypal_result.html', context)
    response['x-frame-options'] = 'allow'
    return response
Beispiel #42
0
    def test_ajax_call(self, requests):
        # Mock requests.
        response = mock.Mock()
        response.status_code = 200
        response.json.return_value = {
            u"data": {u"translations": [{u"translatedText": u"oui", u"detectedSourceLanguage": u"en"}]}
        }
        requests.get.return_value = response

        # Call translation.
        review = self.review
        url = shared_url("reviews.translate", review.addon, review.id, "fr")
        r = self.client.get(url, HTTP_X_REQUESTED_WITH="XMLHttpRequest")
        eq_(r.status_code, 200)
        eq_(r.content, "oui")
Beispiel #43
0
    def test_ajax_call(self, requests):
        # Mock requests.
        response = mock.Mock()
        response.status_code = 200
        response.json.return_value = {u'data': {u'translations': [{
            u'translatedText': u'oui',
            u'detectedSourceLanguage': u'en'
        }]}}
        requests.get.return_value = response

        # Call translation.
        review = self.review
        url = shared_url('reviews.translate', review.addon, review.id, 'fr')
        r = self.client.get(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        eq_(r.status_code, 200)
        eq_(r.content, '{"body": "oui", "title": "oui"}')
Beispiel #44
0
    def test_ajax_call(self, requests):
        # Mock requests.
        response = mock.Mock()
        response.status_code = 200
        response.json.return_value = {u'data': {u'translations': [{
            u'translatedText': u'oui',
            u'detectedSourceLanguage': u'en'
        }]}}
        requests.get.return_value = response

        # Call translation.
        review = self.review
        url = shared_url('reviews.translate', review.addon, review.id, 'fr')
        r = self.client.get(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        eq_(r.status_code, 200)
        eq_(r.content, '{"body": "oui", "title": "oui"}')
Beispiel #45
0
    def test_invalid_api_key(self, requests):
        # Mock requests.
        response = mock.Mock()
        response.status_code = 400
        response.json.return_value = {
            "error": {
                "code": 400,
                "errors": [{"domain": "usageLimits", "message": "Bad Request", "reason": "keyInvalid"}],
                "message": "Bad Request",
            }
        }
        requests.get.return_value = response

        # Call translation.
        review = self.review
        url = shared_url("reviews.translate", review.addon, review.id, "fr")
        r = self.client.get(url, HTTP_X_REQUESTED_WITH="XMLHttpRequest")
        eq_(r.status_code, 400)
Beispiel #46
0
    def test_list_item_actions(self):
        self.login_admin()
        self.make_it_my_review()
        r = self.client.get(shared_url("reviews.list", self.addon))
        reviews = pq(r.content)("#reviews .item")

        r = Review.objects.get(id=218207)
        item = reviews.filter("#review-218207")
        actions = item.find(".item-actions")
        eq_(actions.length, 1)
        classes = sorted(c.get("class") for c in actions.find("li a"))
        eq_(classes, ["delete-review", "flag-review"])

        r = Review.objects.get(id=218468)
        item = reviews.filter("#review-218468")
        actions = item.find(".item-actions")
        eq_(actions.length, 1)
        classes = sorted(c.get("class") for c in actions.find("li a"))
        eq_(classes, ["delete-review", "review-edit"])
Beispiel #47
0
    def test_list_item_actions(self):
        self.login_admin()
        self.make_it_my_review()
        r = self.client.get(shared_url('reviews.list', self.addon))
        reviews = pq(r.content)('#reviews .item')

        r = Review.objects.get(id=218207)
        item = reviews.filter('#review-218207')
        actions = item.find('.item-actions')
        eq_(actions.length, 1)
        classes = sorted(c.get('class') for c in actions.find('li a'))
        eq_(classes, ['delete-review', 'flag-review'])

        r = Review.objects.get(id=218468)
        item = reviews.filter('#review-218468')
        actions = item.find('.item-actions')
        eq_(actions.length, 1)
        classes = sorted(c.get('class') for c in actions.find('li a'))
        eq_(classes, ['delete-review', 'review-edit'])
Beispiel #48
0
    def test_list_item_actions(self):
        self.login_admin()
        self.make_it_my_review()
        r = self.client.get(shared_url('reviews.list', self.addon))
        reviews = pq(r.content)('#reviews .item')

        r = Review.objects.get(id=218207)
        item = reviews.filter('#review-218207')
        actions = item.find('.item-actions')
        eq_(actions.length, 1)
        classes = sorted(c.get('class') for c in actions.find('li a'))
        eq_(classes, ['delete-review', 'flag-review'])

        r = Review.objects.get(id=218468)
        item = reviews.filter('#review-218468')
        actions = item.find('.item-actions')
        eq_(actions.length, 1)
        classes = sorted(c.get('class') for c in actions.find('li a'))
        eq_(classes, ['delete-review', 'review-edit'])
Beispiel #49
0
    def test_list(self):
        r = self.client.get(shared_url('reviews.list', self.addon))
        eq_(r.status_code, 200)
        doc = pq(r.content)
        reviews = doc('#reviews .item')
        eq_(reviews.length, Review.objects.count())
        eq_(Review.objects.count(), 2)
        eq_(doc('.secondary .average-rating').length, 1)
        eq_(doc('.secondary .no-rating').length, 0)

        r = Review.objects.get(id=218207)
        item = reviews.filter('#review-218207')
        eq_(r.reply_to_id, None)
        eq_(item.hasClass('reply'), False)
        eq_(item.length, 1)
        eq_(item.attr('data-rating'), str(r.rating))

        r = Review.objects.get(id=218468)
        item = reviews.filter('#review-218468')
        eq_(item.length, 1)
        eq_(r.reply_to_id, 218207)
        eq_(item.hasClass('reply'), True)
        eq_(r.rating, None)
        eq_(item.attr('data-rating'), '')
Beispiel #50
0
    def test_list(self):
        r = self.client.get(shared_url("reviews.list", self.addon))
        eq_(r.status_code, 200)
        doc = pq(r.content)
        reviews = doc("#reviews .item")
        eq_(reviews.length, Review.objects.count())
        eq_(Review.objects.count(), 2)
        eq_(doc(".secondary .average-rating").length, 1)
        eq_(doc(".secondary .no-rating").length, 0)

        r = Review.objects.get(id=218207)
        item = reviews.filter("#review-218207")
        eq_(r.reply_to_id, None)
        eq_(item.hasClass("reply"), False)
        eq_(item.length, 1)
        eq_(item.attr("data-rating"), str(r.rating))

        r = Review.objects.get(id=218468)
        item = reviews.filter("#review-218468")
        eq_(item.length, 1)
        eq_(r.reply_to_id, 218207)
        eq_(item.hasClass("reply"), True)
        eq_(r.rating, None)
        eq_(item.attr("data-rating"), "")
Beispiel #51
0
 def test_dev_no_rss(self):
     url = shared_url('reviews.detail', self.addon, 218468)
     r = self.client.get(url)
     doc = pq(r.content)
     eq_(doc('link[title=RSS]').length, 0)
Beispiel #52
0
def _notify(redis, context):
    """
    Notify the admins or the developers what happened. Performing a sanity
    check in case something went wrong.
    """
    log.info('Completed run of paypal addon checks: %s' % context['checked'])

    if context['limit'] and context['rate'] > context['limit']:
        # This is too cope with something horrible going wrong like, paypal
        # goes into maintenance mode, or netops changes something and all of
        # a sudden all the apps start failing their paypal checks.
        #
        # It would really suck if one errant current job disabled every app
        # on the marketplace. So this is an attempt to sanity check this.
        log.info('Too many failed: %s%%, aborting.' % context['limit'])
        template = 'market/emails/check_error.txt'
        send_mail('Cron job error on checking addons',
                  env.get_template(template).render(context),
                  recipient_list=[settings.FLIGTAR],
                  from_email=settings.NOBODY_EMAIL)

    else:
        if not context['failed']:
            return

        failure_list = []
        for k in xrange(context['failed']):
            data = json.loads(redis.lindex(failures, k))
            addon = Addon.objects.get(pk=data[0])
            url = absolutify(shared_url('detail', addon))
            # Add this to a list so we can tell the admins who got disabled.
            failure_list.append(url)
            if not context['do_disable']:
                continue

            # Write to the developers log that it failed to pass and update
            # the status of the addon.
            amo.log(amo.LOG.PAYPAL_FAILED, addon, user=get_task_user())
            addon.update(status=amo.STATUS_DISABLED)

            authors = [u.email for u in addon.authors.all()]
            if addon.is_webapp():
                template = 'market/emails/check_developer_app.txt'
                subject = loc('App disabled on the Mozilla Market.')
            else:
                template = 'market/emails/check_developer_addon.txt'
                subject = loc('Add-on disabled on the Mozilla Market.')

            # Now email the developer and tell them the bad news.
            url = absolutify(shared_url('detail', addon))
            send_mail(subject,
                      env.get_template(template).render({
                          'addon': addon,
                          'errors': data[1:]
                      }),
                      recipient_list=authors,
                      from_email=settings.NOBODY_EMAIL)

        context['failure_list'] = failure_list
        # Now email the admins and tell them what happened.
        template = 'market/emails/check_summary.txt'
        send_mail('Cron job disabled %s add-ons' % context['failed'],
                  env.get_template(template).render(context),
                  recipient_list=[settings.FLIGTAR],
                  from_email=settings.NOBODY_EMAIL)
Beispiel #53
0
 def test_list_rss(self):
     r = self.client.get(shared_url('reviews.list', self.addon))
     doc = pq(r.content)
     eq_(doc('link[title=RSS]').length, 1)
Beispiel #54
0
 def test_edit_review_form(self):
     r = self.client.get(shared_url('reviews.list', self.addon))
     self.assertTemplateUsed(r, 'reviews/edit_review.html')
     r = self.client.get(shared_url('reviews.detail', self.addon, 218468))
     self.assertTemplateUsed(r, 'reviews/edit_review.html')
Beispiel #55
0
 def test_add_logged_out(self):
     self.client.logout()
     self.mobile_init()
     r = self.client.get(shared_url('reviews.add', self.addon))
     eq_(r.status_code, 302)
Beispiel #56
0
 def test_feed(self):
     url = shared_url('reviews.list.rss', self.addon)
     r = self.client.get(url)
     eq_(r.status_code, 200)
Beispiel #57
0
 def setUp(self):
     self.addon = Addon.objects.get(id=1865)
     self.user = UserProfile.objects.get(email='*****@*****.**')
     self.login_regular()
     self.add = shared_url('reviews.add', self.addon)
     self.list = shared_url('reviews.list', self.addon)
Beispiel #58
0
 def test_404_user_page(self):
     url = shared_url('reviews.user', self.addon, 233452342)
     r = self.client.get(url)
     eq_(r.status_code, 404)
Beispiel #59
0
 def test_regular_call(self):
     review = self.review
     url = shared_url('reviews.translate', review.addon, review.id, 'fr')
     r = self.client.get(url)
     eq_(r.status_code, 302)
     eq_(r.get('Location'), 'https://translate.google.com/#auto/fr/yes')