Example #1
0
    def test_reviewer_reply(self, send_mail_mock):
        # One from the reviewer.
        self._create(amo.LOG.REJECT_VERSION, self.reviewer)
        # One from the developer.
        self._create(amo.LOG.DEVELOPER_REPLY_VERSION, self.developer)
        action = amo.LOG.REVIEWER_REPLY_VERSION
        comments = u'Thîs ïs a revïewer replyîng'
        log_and_notify(action, comments, self.reviewer, self.version)

        logs = ActivityLog.objects.filter(action=action.id)
        assert len(logs) == 1
        assert logs[0].details['comments'] == u'Thîs ïs a revïewer replyîng'

        assert send_mail_mock.call_count == 2  # Both authors.
        sender = '%s <notifications@%s>' % (
            self.reviewer.name, settings.INBOUND_EMAIL_DOMAIN)
        assert sender == send_mail_mock.call_args_list[0][1]['from_email']
        recipients = self._recipients(send_mail_mock)
        assert len(recipients) == 2
        assert self.developer.email in recipients
        assert self.developer2.email in recipients
        # The reviewer who sent it doesn't get their email back.
        assert self.reviewer.email not in recipients

        self._check_email(send_mail_mock.call_args_list[0],
                          absolutify(self.addon.get_dev_url('versions')),
                          'Reviewer Reply',
                          'you are an author of this add-on.')
        self._check_email(send_mail_mock.call_args_list[1],
                          absolutify(self.addon.get_dev_url('versions')),
                          'Reviewer Reply',
                          'you are an author of this add-on.')
Example #2
0
    def test_review_url_listed(self, send_mail_mock):
        # One from the reviewer.
        self._create(amo.LOG.REJECT_VERSION, self.reviewer)
        # One from the developer.  So the developer is on the 'thread'
        self._create(amo.LOG.DEVELOPER_REPLY_VERSION, self.developer)
        action = amo.LOG.DEVELOPER_REPLY_VERSION
        comments = u'Thïs is á reply'
        log_and_notify(action, comments, self.developer, self.version)

        logs = ActivityLog.objects.filter(action=action.id)
        assert len(logs) == 2  # We added one above.
        assert logs[0].details['comments'] == u'Thïs is á reply'

        assert send_mail_mock.call_count == 2  # One author, one reviewer.
        recipients = self._recipients(send_mail_mock)
        assert len(recipients) == 2
        assert self.reviewer.email in recipients
        assert self.developer2.email in recipients
        # The developer who sent it doesn't get their email back.
        assert self.developer.email not in recipients

        self._check_email(send_mail_mock.call_args_list[0],
                          absolutify(self.addon.get_dev_url('versions')),
                          'Developer Reply',
                          'you are an author of this add-on.')
        review_url = absolutify(
            reverse('editors.review', add_prefix=False,
                    kwargs={'channel': 'listed', 'addon_id': self.addon.pk}))
        self._check_email(send_mail_mock.call_args_list[1],
                          review_url, 'Developer Reply',
                          'you reviewed this add-on.')
Example #3
0
    def test_developer_reply(self, send_mail_mock):
        # One from the reviewer.
        self._create(amo.LOG.REJECT_VERSION, self.reviewer)
        # One from the developer.  So the developer is on the 'thread'
        self._create(amo.LOG.DEVELOPER_REPLY_VERSION, self.developer)
        action = amo.LOG.DEVELOPER_REPLY_VERSION
        comments = u'Thïs is á reply'
        log_and_notify(action, comments, self.developer, self.version)

        logs = ActivityLog.objects.filter(action=action.id)
        assert len(logs) == 2  # We added one above.
        assert logs[0].details['comments'] == u'Thïs is á reply'

        assert send_mail_mock.call_count == 2  # One author, one reviewer.
        recipients = self._recipients(send_mail_mock)
        assert len(recipients) == 2
        assert self.reviewer.email in recipients
        assert self.developer2.email in recipients
        # The developer who sent it doesn't get their email back.
        assert self.developer.email not in recipients

        self._check_email(send_mail_mock.call_args_list[0],
                          absolutify(self.addon.get_dev_url('versions')))
        review_url = absolutify(
            reverse('editors.review', args=[self.addon.pk], add_prefix=False))
        self._check_email(send_mail_mock.call_args_list[1],
                          review_url)
    def _test_version(self, version, data):
        assert data['id'] == version.pk

        assert data['compatibility']
        assert len(data['compatibility']) == len(version.compatible_apps)
        for app, compat in version.compatible_apps.items():
            assert data['compatibility'][app.short] == {
                'min': compat.min.version,
                'max': compat.max.version
            }
        assert data['files']
        assert len(data['files']) == 1

        result_file = data['files'][0]
        file_ = version.files.latest('pk')
        assert result_file['id'] == file_.pk
        assert result_file['created'] == (
            file_.created.replace(microsecond=0).isoformat() + 'Z')
        assert result_file['hash'] == file_.hash
        assert result_file['platform'] == (
            amo.PLATFORM_CHOICES_API[file_.platform])
        assert result_file['size'] == file_.size
        assert result_file['status'] == amo.STATUS_CHOICES_API[file_.status]
        assert result_file['url'] == file_.get_url_path(src='')
        assert result_file['permissions'] == file_.webext_permissions_list

        assert data['edit_url'] == absolutify(
            self.addon.get_dev_url('versions.edit',
                                   args=[version.pk],
                                   prefix_only=True))
        assert data['reviewed'] == version.reviewed
        assert data['version'] == version.version
        assert data['url'] == absolutify(version.get_url_path())
Example #5
0
 def send_notification_email(self):
     if self.reply_to:
         # It's a reply.
         reply_url = helpers.url("addons.reviews.detail", self.addon.slug, self.reply_to.pk, add_prefix=False)
         data = {
             "name": self.addon.name,
             "reply_title": self.title,
             "reply": self.body,
             "reply_url": helpers.absolutify(reply_url),
         }
         recipients = [self.reply_to.user.email]
         subject = u"Mozilla Add-on Developer Reply: %s" % self.addon.name
         template = "reviews/emails/reply_review.ltxt"
         perm_setting = "reply"
     else:
         # It's a new review.
         reply_url = helpers.url("addons.reviews.reply", self.addon.slug, self.pk, add_prefix=False)
         data = {
             "name": self.addon.name,
             "rating": "%s out of 5 stars" % self.rating,
             "review": self.body,
             "reply_url": helpers.absolutify(reply_url),
         }
         recipients = [author.email for author in self.addon.authors.all()]
         subject = u"Mozilla Add-on User Review: %s" % self.addon.name
         template = "reviews/emails/add_review.ltxt"
         perm_setting = "new_review"
     send_mail_jinja(subject, template, Context(data), recipient_list=recipients, perm_setting=perm_setting)
Example #6
0
 def send_notification_email(self):
     if self.reply_to:
         # It's a reply.
         reply_url = helpers.url('addons.reviews.detail', self.addon.slug,
                                 self.reply_to.pk, add_prefix=False)
         data = {
             'name': self.addon.name,
             'reply_title': self.title,
             'reply': self.body,
             'reply_url': helpers.absolutify(reply_url)
         }
         recipients = [self.reply_to.user.email]
         subject = u'Mozilla Add-on Developer Reply: %s' % self.addon.name
         template = 'reviews/emails/reply_review.ltxt'
         perm_setting = 'reply'
     else:
         # It's a new review.
         reply_url = helpers.url('addons.reviews.reply', self.addon.slug,
                                 self.pk, add_prefix=False)
         data = {
             'name': self.addon.name,
             'rating': '%s out of 5 stars' % self.rating,
             'review': self.body,
             'reply_url': helpers.absolutify(reply_url)
         }
         recipients = [author.email for author in self.addon.authors.all()]
         subject = u'Mozilla Add-on User Review: %s' % self.addon.name
         template = 'reviews/emails/add_review.ltxt'
         perm_setting = 'new_review'
     send_mail_jinja(
         subject, template, Context(data),
         recipient_list=recipients, perm_setting=perm_setting)
    def _test_version(self, version, data):
        assert data['id'] == version.pk

        assert data['compatibility']
        assert len(data['compatibility']) == len(version.compatible_apps)
        for app, compat in version.compatible_apps.items():
            assert data['compatibility'][app.short] == {
                'min': compat.min.version,
                'max': compat.max.version
            }
        assert data['files']
        assert len(data['files']) == 1

        result_file = data['files'][0]
        file_ = version.files.latest('pk')
        assert result_file['id'] == file_.pk
        assert result_file['created'] == file_.created.isoformat()
        assert result_file['hash'] == file_.hash
        assert result_file['platform'] == (
            amo.PLATFORM_CHOICES_API[file_.platform])
        assert result_file['size'] == file_.size
        assert result_file['status'] == amo.STATUS_CHOICES_API[file_.status]
        assert result_file['url'] == file_.get_url_path(src='')

        assert data['edit_url'] == absolutify(
            self.addon.get_dev_url(
                'versions.edit', args=[version.pk], prefix_only=True))
        assert data['reviewed'] == version.reviewed
        assert data['version'] == version.version
        assert data['url'] == absolutify(version.get_url_path())
Example #8
0
 def get_context_data(self):
     addon_url = self.addon.get_url_path(add_prefix=False)
     dev_ver_url = self.addon.get_dev_url('versions')
     # We need to display the name in some language that is relevant to the
     # recipient(s) instead of using the reviewer's. addon.default_locale
     # should work.
     if self.addon.name.locale != self.addon.default_locale:
         lang = to_language(self.addon.default_locale)
         with translation.override(lang):
             addon = Addon.unfiltered.get(pk=self.addon.pk)
     else:
         addon = self.addon
     return {
         'name':
         addon.name,
         'number':
         self.version.version if self.version else '',
         'reviewer':
         self.user.display_name,
         'addon_url':
         absolutify(addon_url),
         'dev_versions_url':
         absolutify(dev_ver_url),
         'review_url':
         absolutify(
             reverse('editors.review',
                     args=[self.addon.pk],
                     add_prefix=False)),
         'comments':
         self.data.get('comments'),
         'SITE_URL':
         settings.SITE_URL
     }
Example #9
0
 def send_notification(self, version):
     user_log.info('Sending addon update notice to %s for %s' %
                   (self.user.email, self.addon.pk))
     context = Context({
         'name':
         self.addon.name,
         'url':
         absolutify(
             reverse('addons.detail',
                     args=[self.addon.pk],
                     add_prefix=False)),
         'number':
         version.version,
         'review':
         absolutify(
             reverse('editors.review',
                     args=[self.addon.pk],
                     add_prefix=False)),
         'SITE_URL':
         settings.SITE_URL,
     })
     # Not being localised because we don't know the editors locale.
     subject = 'Mozilla Add-ons: %s Updated' % self.addon.name
     template = loader.get_template('editors/emails/notify_update.ltxt')
     send_mail(subject,
               template.render(Context(context)),
               recipient_list=[self.user.email],
               from_email=settings.EDITORS_EMAIL,
               use_deny_list=False)
Example #10
0
    def test_reviewer_reply(self, send_mail_mock):
        # One from the reviewer.
        self._create(amo.LOG.REJECT_VERSION, self.reviewer)
        # One from the developer.
        self._create(amo.LOG.DEVELOPER_REPLY_VERSION, self.developer)
        action = amo.LOG.REVIEWER_REPLY_VERSION
        comments = u'Thîs ïs a revïewer replyîng'
        log_and_notify(action, comments, self.reviewer, self.version)

        logs = ActivityLog.objects.filter(action=action.id)
        assert len(logs) == 1
        assert logs[0].details['comments'] == u'Thîs ïs a revïewer replyîng'

        assert send_mail_mock.call_count == 2  # Both authors.
        recipients = self._recipients(send_mail_mock)
        assert len(recipients) == 2
        assert self.developer.email in recipients
        assert self.developer2.email in recipients
        # The reviewer who sent it doesn't get their email back.
        assert self.reviewer.email not in recipients

        self._check_email(send_mail_mock.call_args_list[0],
                          absolutify(self.addon.get_dev_url('versions')))
        self._check_email(send_mail_mock.call_args_list[1],
                          absolutify(self.addon.get_dev_url('versions')))
Example #11
0
    def test_review_url_correct_channel(self):
        # Listed email
        self.helper.set_data(self.get_data())
        self.helper.handler.notify_email('super_review',
                                         'Sample subject %s, %s')
        assert len(mail.outbox) == 1
        listed_review_url = absolutify(
            reverse('editors.review', args=[self.addon.pk], add_prefix=False))
        assert listed_review_url in mail.outbox[0].body
        mail.outbox = []

        # Unlisted email
        self.version.update(channel=amo.RELEASE_CHANNEL_UNLISTED)
        self.helper.set_data(self.get_data())
        self.helper.handler.notify_email('super_review',
                                         'Sample subject %s, %s')
        assert len(mail.outbox) == 1
        unlisted_review_url = absolutify(
            reverse('editors.review',
                    kwargs={
                        'addon_id': self.addon.pk,
                        'channel': 'unlisted'
                    },
                    add_prefix=False))
        assert unlisted_review_url in mail.outbox[0].body
Example #12
0
 def get_context_data(self):
     addon_url = self.addon.get_url_path(add_prefix=False)
     dev_ver_url = self.addon.get_dev_url('versions')
     # We need to display the name in some language that is relevant to the
     # recipient(s) instead of using the reviewer's. addon.default_locale
     # should work.
     if self.addon.name.locale != self.addon.default_locale:
         lang = to_language(self.addon.default_locale)
         with translation.override(lang):
             addon = Addon.unfiltered.get(pk=self.addon.pk)
     else:
         addon = self.addon
     review_url_kw = {'addon_id': self.addon.pk}
     if (self.version and
             self.version.channel == amo.RELEASE_CHANNEL_UNLISTED):
         review_url_kw['channel'] = 'unlisted'
     return {'name': addon.name,
             'number': self.version.version if self.version else '',
             'reviewer': self.user.display_name,
             'addon_url': absolutify(addon_url),
             'dev_versions_url': absolutify(dev_ver_url),
             'review_url': absolutify(reverse('editors.review',
                                              kwargs=review_url_kw,
                                              add_prefix=False)),
             'comments': self.data.get('comments'),
             'SITE_URL': settings.SITE_URL,
             'legacy_addon': (
                 not self.version.all_files[0].is_webextension
                 if self.version else False)}
Example #13
0
def log_and_notify(action, comments, note_creator, version):
    log_kwargs = {
        'user': note_creator,
        'created': datetime.datetime.now(),
    }
    if comments:
        log_kwargs['details'] = {
            'comments': comments,
            'version': version.version}
    else:
        # Just use the name of the action if no comments provided.  Alas we
        # can't know the locale of recipient, and our templates are English
        # only so prevent language jumble by forcing into en-US.
        with no_translation():
            comments = '%s' % action.short
    note = amo.log(action, version.addon, version, **log_kwargs)

    # Collect reviewers involved with this version.
    review_perm = ('Review' if version.channel == amo.RELEASE_CHANNEL_LISTED
                   else 'ReviewUnlisted')
    log_users = {
        alog.user for alog in ActivityLog.objects.for_version(version) if
        acl.action_allowed_user(alog.user, 'Addons', review_perm)}
    # Collect add-on authors (excl. the person who sent the email.)
    addon_authors = set(version.addon.authors.all()) - {note_creator}
    # Collect staff that want a copy of the email
    staff_cc = set(
        UserProfile.objects.filter(groups__name=ACTIVITY_MAIL_GROUP))
    # If task_user doesn't exist that's no big issue (i.e. in tests)
    try:
        task_user = {get_task_user()}
    except UserProfile.DoesNotExist:
        task_user = set()
    # Collect reviewers on the thread (excl. the email sender and task user for
    # automated messages).
    reviewers = ((log_users | staff_cc) - addon_authors - task_user -
                 {note_creator})
    author_context_dict = {
        'name': version.addon.name,
        'number': version.version,
        'author': note_creator.name,
        'comments': comments,
        'url': absolutify(version.addon.get_dev_url('versions')),
        'SITE_URL': settings.SITE_URL,
    }
    reviewer_context_dict = author_context_dict.copy()
    reviewer_context_dict['url'] = absolutify(
        reverse('editors.review', args=[version.addon.pk], add_prefix=False))

    # Not being localised because we don't know the recipients locale.
    subject = 'Mozilla Add-ons: %s Updated' % version.addon.name
    template = loader.get_template('activity/emails/developer.txt')
    send_activity_mail(
        subject, template.render(Context(author_context_dict)), version,
        addon_authors, settings.EDITORS_EMAIL)
    send_activity_mail(
        subject, template.render(Context(reviewer_context_dict)), version,
        reviewers, settings.EDITORS_EMAIL)
    return note
Example #14
0
    def test_dev_versions_url_in_context(self):
        self.helper.set_data(self.get_data())
        context_data = self.helper.handler.get_context_data()
        assert context_data['dev_versions_url'] == absolutify(
            self.addon.get_dev_url('versions'))

        self.version.update(channel=amo.RELEASE_CHANNEL_UNLISTED)
        context_data = self.helper.handler.get_context_data()
        assert context_data['dev_versions_url'] == absolutify(
            reverse('devhub.addons.versions', args=[self.addon.id]))
Example #15
0
 def get_context_data(self):
     addon_url = self.addon.get_url_path(add_prefix=False)
     dev_ver_url = self.addon.get_dev_url('versions')
     return {'name': self.addon.name,
             'number': self.version.version if self.version else '',
             'reviewer': self.user.display_name,
             'addon_url': absolutify(addon_url),
             'dev_versions_url': absolutify(dev_ver_url),
             'review_url': absolutify(reverse('editors.review',
                                              args=[self.addon.pk],
                                              add_prefix=False)),
             'comments': self.data.get('comments'),
             'SITE_URL': settings.SITE_URL}
Example #16
0
 def get_context_data(self):
     addon_url = self.addon.get_url_path(add_prefix=False)
     dev_ver_url = self.addon.get_dev_url('versions')
     return {'name': self.addon.name,
             'number': self.version.version if self.version else '',
             'reviewer': self.user.display_name,
             'addon_url': absolutify(addon_url),
             'dev_versions_url': absolutify(dev_ver_url),
             'review_url': absolutify(reverse('editors.review',
                                              args=[self.addon.pk],
                                              add_prefix=False)),
             'comments': self.data.get('comments'),
             'SITE_URL': settings.SITE_URL}
Example #17
0
def get_paykey(data):
    """
    Gets a paykey from Paypal. Need to pass in the following in data:
    pattern: the reverse pattern to resolve
    email: who the money is going to (required)
    amount: the amount of money (required)
    ip: ip address of end user (required)
    uuid: contribution_uuid (required)
    memo: any nice message (optional)
    qs: anything you want to append to the complete or cancel (optional)
    currency: valid paypal currency, defaults to USD (optional)

    API Docs from Paypal are at :
    https://developer.paypal.com/docs/classic/api/adaptive-payments/ ("Pay").
    """
    if data['pattern']:
        complete = reverse(data['pattern'], args=[data['slug'], 'complete'])
        cancel = reverse(data['pattern'], args=[data['slug'], 'cancel'])
    else:
        # If there's no pattern given, just fake some urls.
        complete = cancel = settings.SITE_URL + '/paypal/dummy/'

    qs = {'uuid': data['uuid']}
    if 'qs' in data:
        qs.update(data['qs'])
    uuid_qs = urllib.urlencode(qs)

    paypal_data = {
        'actionType': 'PAY',
        'currencyCode': data.get('currency', 'USD'),
        'cancelUrl': absolutify('%s?%s' % (cancel, uuid_qs)),
        'returnUrl': absolutify('%s?%s' % (complete, uuid_qs)),
        'trackingId': data['uuid'],
        'ipnNotificationUrl': absolutify(reverse('amo.paypal')),
        'receiverList.receiver(0).email': data['email'],
        'receiverList.receiver(0).amount': data['amount'],
        'receiverList.receiver(0).invoiceID': 'mozilla-%s' % data['uuid'],
        'receiverList.receiver(0).paymentType': 'DIGITALGOODS',
        'requestEnvelope.errorLanguage': 'US'
    }

    if data.get('memo'):
        paypal_data['memo'] = data['memo']

    with statsd.timer('paypal.paykey.retrieval'):
        response = _call(settings.PAYPAL_PAY_URL + 'Pay',
                         paypal_data,
                         ip=data['ip'])

    return response['payKey'], response['paymentExecStatus']
Example #18
0
def get_context(addon, version, job, results, fileob=None):
    result_links = (absolutify(reverse('devhub.bulk_compat_result',
                                       args=[addon.slug, r.pk]))
                    for r in results)
    addon_name = addon.name
    if fileob and fileob.platform != amo.PLATFORM_ALL.id:
        addon_name = u'%s (%s)' % (addon_name, fileob.get_platform_display())
    return Context({
        'ADDON_NAME': addon_name,
        'ADDON_VERSION': version.version,
        'APPLICATION': str(job.application),
        'COMPAT_LINK': absolutify(reverse('devhub.versions.edit',
                                          args=[addon.pk, version.pk])),
        'RESULT_LINKS': ' '.join(result_links),
        'VERSION': job.target_version.version})
Example #19
0
 def _check_disco_addon(self, result, item):
     addon = self.addons[item.addon_id]
     assert result['addon']['id'] == item.addon_id == addon.pk
     assert result['addon']['name'] == unicode(addon.name)
     assert result['addon']['slug'] == addon.slug
     assert result['addon']['icon_url'] == absolutify(
         addon.get_icon_url(64))
     assert (result['addon']['current_version']['files'][0]['id'] ==
             addon.current_version.all_files[0].pk)
     assert '<a href="{0}">{1}</a>'.format(
         absolutify(addon.get_url_path()),
         unicode(addon.name)) in result['heading']
     assert '<span>' in result['heading']
     assert '</span>' in result['heading']
     assert result['description']
Example #20
0
 def _check_disco_addon(self, result, item):
     addon = self.addons[item.addon_id]
     assert result['addon']['id'] == item.addon_id == addon.pk
     assert result['addon']['name'] == unicode(addon.name)
     assert result['addon']['slug'] == addon.slug
     assert result['addon']['icon_url'] == absolutify(
         addon.get_icon_url(64))
     assert (result['addon']['current_version']['files'][0]['id'] ==
             addon.current_version.all_files[0].pk)
     assert u'<a href="{0}">{1}</a>'.format(
         absolutify(addon.get_url_path()),
         unicode(addon.name)) in result['heading']
     assert '<span>' in result['heading']
     assert '</span>' in result['heading']
     assert result['description']
Example #21
0
def get_context(addon, version, job, results, fileob=None):
    result_links = (absolutify(reverse('devhub.bulk_compat_result',
                                       args=[addon.slug, r.pk]))
                    for r in results)
    addon_name = addon.name
    if fileob and fileob.platform != amo.PLATFORM_ALL.id:
        addon_name = u'%s (%s)' % (addon_name, fileob.get_platform_display())
    return Context({
        'ADDON_NAME': addon_name,
        'ADDON_VERSION': version.version,
        'APPLICATION': str(job.application),
        'COMPAT_LINK': absolutify(reverse('devhub.versions.edit',
                                          args=[addon.pk, version.pk])),
        'RESULT_LINKS': ' '.join(result_links),
        'VERSION': job.target_version.version})
Example #22
0
    def test_basic(self):
        addon = addon_factory()
        self.review = Review.objects.create(
            addon=addon, user=self.user, rating=4,
            version=addon.current_version, body=u'This is my rëview. Like ît?',
            title=u'My Review Titlé')

        result = self.serialize()

        assert result['id'] == self.review.pk
        assert result['addon'] == {'id': addon.pk}
        assert result['body'] == unicode(self.review.body)
        assert result['created'] == (
            self.review.created.replace(microsecond=0).isoformat() + 'Z')
        assert result['title'] == unicode(self.review.title)
        assert result['previous_count'] == int(self.review.previous_count)
        assert result['is_latest'] == self.review.is_latest
        assert result['rating'] == int(self.review.rating)
        assert result['reply'] is None
        assert result['user'] == {
            'id': self.user.pk,
            'name': unicode(self.user.name),
            'url': absolutify(self.user.get_url_path()),
        }
        assert result['version'] == {
            'id': self.review.version.id,
            'version': self.review.version.version
        }

        self.review.update(version=None)
        result = self.serialize()
        assert result['version'] is None
Example #23
0
    def _check_feed(self, browse_url, rss_url, sort='featured'):
        """
        Check RSS feed URLs and that the results on the listing pages match
        those for their respective RSS feeds.
        """
        # Check URLs.
        r = self.client.get(browse_url, follow=True)
        doc = pq(r.content)
        rss_url += '?sort=%s' % sort
        assert doc('link[type="application/rss+xml"]').attr('href') == rss_url
        assert doc('#subscribe').attr('href') == rss_url

        # Ensure that the RSS items match those on the browse listing pages.
        r = self.client.get(rss_url)
        rss_doc = pq(r.content)
        pg_items = doc('.items .item')
        rss_items = rss_doc('item')

        # We have to set `parser=xml` because of
        # https://github.com/gawel/pyquery/issues/93
        items_urls = zip(
            sorted((absolutify(pq(x).find('h3 a').attr('href')), pq(x))
                   for x in pg_items),
            sorted((pq(x).find('link').text(), pq(x, parser='xml'))
                   for x in rss_items))
        for (pg_url, pg_item), (rss_url, rss_item) in items_urls:
            abs_url = pg_url.split('?')[0]
            assert rss_url.endswith(abs_url), 'Unexpected URL: %s' % abs_url
            if sort in ('added', 'updated'):
                # Check timestamps.
                pg_ts = pg_item.find('.updated').text().strip('Added Updated')
                rss_ts = rss_item.find('pubDate').text()
                # Look at YMD, since we don't have h:m on listing pages.
                assert parse_dt(pg_ts).isocalendar() == (
                    parse_dt(rss_ts).isocalendar())
Example #24
0
    def test_creation_triggers_email_and_logging(self):
        addon = Addon.objects.get(pk=4)
        addon_author = user_factory()
        addon.addonuser_set.create(user=addon_author)
        review_user = user_factory()
        review = Review.objects.create(user=review_user,
                                       addon=addon,
                                       body=u'Rêviiiiiiew',
                                       user_responsible=review_user)

        activity_log = ActivityLog.objects.latest('pk')
        assert activity_log.user == review_user
        assert activity_log.arguments == [addon, review]
        assert activity_log.action == amo.LOG.ADD_REVIEW.id

        assert len(mail.outbox) == 1
        email = mail.outbox[0]
        reply_url = helpers.absolutify(
            helpers.url('addons.reviews.reply',
                        addon.slug,
                        review.pk,
                        add_prefix=False))
        assert email.subject == 'Mozilla Add-on User Review: my addon name'
        assert 'A user has left a review for your add-on,' in email.body
        assert 'my addon name' in email.body
        assert reply_url in email.body
        assert email.to == [addon_author.email]
        assert email.from_email == 'Mozilla Add-ons <*****@*****.**>'
Example #25
0
    def test_with_reply(self):
        addon = addon_factory()
        reply_user = user_factory()
        self.review = Review.objects.create(
            addon=addon, user=self.user, version=addon.current_version,
            body=u'This is my rëview. Like ît ?', title=u'My Review Titlé')
        reply = Review.objects.create(
            addon=addon, user=reply_user, version=addon.current_version,
            body=u'Thîs is a reply.', title=u'My rèply', reply_to=self.review)

        result = self.serialize()

        assert result['reply']
        assert 'rating' not in result['reply']
        assert 'reply' not in result['reply']
        assert result['reply']['id'] == reply.pk
        assert result['reply']['body'] == unicode(reply.body)
        assert result['reply']['created'] == (
            reply.created.replace(microsecond=0).isoformat() + 'Z')
        assert result['reply']['title'] == unicode(reply.title)
        assert result['reply']['user'] == {
            'id': reply_user.pk,
            'name': unicode(reply_user.name),
            'url': absolutify(reply_user.get_url_path()),
        }
Example #26
0
 def link(self, category):
     """Link for the feed as a whole"""
     if self.category:
         base = url('browse.search-tools.rss', self.category.slug)
     else:
         base = url('browse.search-tools.rss')
     return absolutify(base + '?sort=' + self.sort)
Example #27
0
 def link(self, category):
     """Link for the feed as a whole"""
     if self.category:
         base = url('browse.search-tools.rss', self.category.slug)
     else:
         base = url('browse.search-tools.rss')
     return absolutify(base + '?sort=' + self.sort)
Example #28
0
    def test_staff_cc_group_get_mail(self, send_mail_mock):
        self.grant_permission(self.reviewer, 'None:None', ACTIVITY_MAIL_GROUP)
        action = amo.LOG.DEVELOPER_REPLY_VERSION
        comments = u'Thïs is á reply'
        log_and_notify(action, comments, self.developer, self.version)

        logs = ActivityLog.objects.filter(action=action.id)
        assert len(logs) == 1

        recipients = self._recipients(send_mail_mock)
        sender = '%s <notifications@%s>' % (
            self.developer.name, settings.INBOUND_EMAIL_DOMAIN)
        assert sender == send_mail_mock.call_args_list[0][1]['from_email']
        assert len(recipients) == 2
        # self.reviewers wasn't on the thread, but gets an email anyway.
        assert self.reviewer.email in recipients
        assert self.developer2.email in recipients
        review_url = absolutify(
            reverse('editors.review',
                    kwargs={'addon_id': self.version.addon.pk,
                            'channel': 'listed'},
                    add_prefix=False))
        self._check_email(send_mail_mock.call_args_list[1],
                          review_url, 'Developer Reply',
                          'you are member of the activity email cc group.')
Example #29
0
def tally_job_results(job_id, **kw):
    sql = """select sum(1),
                    sum(case when completed IS NOT NULL then 1 else 0 end)
             from validation_result
             where validation_job_id=%s"""

    with connection.cursor() as cursor:
        cursor.execute(sql, [job_id])
        total, completed = cursor.fetchone()

    if completed == total:
        # The job has finished.
        job = ValidationJob.objects.get(pk=job_id)
        job.update(completed=datetime.now())
        if job.finish_email:
            send_mail(
                u'Behold! Validation results for %s %s->%s' %
                (amo.APP_IDS[job.application].pretty,
                 job.curr_max_version.version, job.target_version.version),
                textwrap.dedent("""
                          Aww yeah
                          %s
                          """ % absolutify(reverse('zadmin.validation'))),
                from_email=settings.DEFAULT_FROM_EMAIL,
                recipient_list=[job.finish_email])
Example #30
0
    def test_with_deleted_reply_but_view_allowing_it_to_be_shown(self):
        addon = addon_factory()
        reply_user = user_factory()
        self.review = Review.objects.create(
            addon=addon,
            user=self.user,
            version=addon.current_version,
            body=u'This is my rëview. Like ît ?',
            title=u'My Review Titlé')
        reply = Review.objects.create(addon=addon,
                                      user=reply_user,
                                      version=addon.current_version,
                                      body=u'Thîs is a reply.',
                                      title=u'My rèply',
                                      reply_to=self.review)

        view = Mock(spec=[], should_access_deleted_reviews=True)
        view.should_access_deleted_reviews = True
        result = self.serialize(view=view)

        assert result['reply']
        assert 'rating' not in result['reply']
        assert 'reply' not in result['reply']
        assert result['reply']['id'] == reply.pk
        assert result['reply']['body'] == unicode(reply.body)
        assert result['reply']['created'] == reply.created.isoformat()
        assert result['reply']['title'] == unicode(reply.title)
        assert result['reply']['user'] == {
            'name': unicode(reply_user.name),
            'url': absolutify(reply_user.get_url_path()),
        }
Example #31
0
    def test_creation_triggers_email_and_logging(self):
        addon = Addon.objects.get(pk=4)
        addon_author = user_factory()
        addon.addonuser_set.create(user=addon_author)
        review_user = user_factory()
        review = Review.objects.create(
            user=review_user, addon=addon,
            body=u'Rêviiiiiiew', user_responsible=review_user)

        activity_log = ActivityLog.objects.latest('pk')
        assert activity_log.user == review_user
        assert activity_log.arguments == [addon, review]
        assert activity_log.action == amo.LOG.ADD_REVIEW.id

        assert len(mail.outbox) == 1
        email = mail.outbox[0]
        reply_url = helpers.absolutify(
            helpers.url('addons.reviews.reply', addon.slug,
                        review.pk, add_prefix=False))
        assert email.subject == 'Mozilla Add-on User Review: my addon name'
        assert 'A user has left a review for your add-on,' in email.body
        assert 'my addon name' in email.body
        assert reply_url in email.body
        assert email.to == [addon_author.email]
        assert email.from_email == 'Mozilla Add-ons <*****@*****.**>'
Example #32
0
    def test_basic(self):
        addon = addon_factory()
        self.review = Review.objects.create(
            addon=addon,
            user=self.user,
            rating=4,
            version=addon.current_version,
            body=u'This is my rëview. Like ît?',
            title=u'My Review Titlé')
        result = self.serialize()

        assert result['id'] == self.review.pk
        assert result['body'] == unicode(self.review.body)
        assert result['created'] == self.review.created.isoformat()
        assert result['title'] == unicode(self.review.title)
        assert result['previous_count'] == int(self.review.previous_count)
        assert result['is_latest'] == self.review.is_latest
        assert result['rating'] == int(self.review.rating)
        assert result['reply'] is None
        assert result['user'] == {
            'name': unicode(self.user.name),
            'url': absolutify(self.user.get_url_path()),
        }
        assert result['version'] == self.review.version.version

        self.review.update(version=None)
        result = self.serialize()
        assert result['version'] is None
Example #33
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.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 = helpers.url('addons.reviews.detail', addon.slug,
                                    review.id, add_prefix=False)
            data = {'name': addon.name,
                    'reply_title': reply.title,
                    'reply': reply.body,
                    'reply_url': helpers.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(helpers.url('addons.reviews.detail', addon.slug,
                                    review_id))
    ctx = dict(review=review, form=form, addon=addon)
    return render(request, 'reviews/reply.html', ctx)
Example #34
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 = helpers.url('addons.reviews.reply', addon.slug, review.id,
                                add_prefix=False)
        data = {'name': addon.name,
                'rating': '%s out of 5 stars' % details['rating'],
                'review': details['body'],
                'reply_url': helpers.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(helpers.url('addons.reviews.list', addon.slug))
    return render(request, template, dict(addon=addon, form=form))
Example #35
0
 def get_url(self, instance):
     return absolutify(
         reverse('signing.version',
                 args=[
                     instance.addon.guid, instance.version,
                     instance.uuid.hex
                 ]))
Example #36
0
    def test_with_reply(self):
        addon = addon_factory()
        reply_user = user_factory()
        self.review = Review.objects.create(
            addon=addon,
            user=self.user,
            version=addon.current_version,
            body=u'This is my rëview. Like ît ?',
            title=u'My Review Titlé')
        reply = Review.objects.create(addon=addon,
                                      user=reply_user,
                                      version=addon.current_version,
                                      body=u'Thîs is a reply.',
                                      title=u'My rèply',
                                      reply_to=self.review)

        result = self.serialize()

        assert result['reply']
        assert 'rating' not in result['reply']
        assert 'reply' not in result['reply']
        assert result['reply']['id'] == reply.pk
        assert result['reply']['body'] == unicode(reply.body)
        assert result['reply']['created'] == reply.created.isoformat()
        assert result['reply']['title'] == unicode(reply.title)
        assert result['reply']['user'] == {
            'name': unicode(reply_user.name),
            'url': absolutify(reply_user.get_url_path()),
        }
Example #37
0
def get_paykey(data):
    """
    Gets a paykey from Paypal. Need to pass in the following in data:
    pattern: the reverse pattern to resolve
    email: who the money is going to (required)
    amount: the amount of money (required)
    ip: ip address of end user (required)
    uuid: contribution_uuid (required)
    memo: any nice message (optional)
    qs: anything you want to append to the complete or cancel (optional)
    currency: valid paypal currency, defaults to USD (optional)
    """
    if data['pattern']:
        complete = reverse(data['pattern'], args=[data['slug'], 'complete'])
        cancel = reverse(data['pattern'], args=[data['slug'], 'cancel'])
    else:
        # If there's no pattern given, just fake some urls.
        complete = cancel = settings.SITE_URL + '/paypal/dummy/'

    qs = {'uuid': data['uuid']}
    if 'qs' in data:
        qs.update(data['qs'])
    uuid_qs = urllib.urlencode(qs)

    paypal_data = {
        'actionType': 'PAY',
        'currencyCode': data.get('currency', 'USD'),
        'cancelUrl': absolutify('%s?%s' % (cancel, uuid_qs)),
        'returnUrl': absolutify('%s?%s' % (complete, uuid_qs)),
        'trackingId': data['uuid'],
        'ipnNotificationUrl': absolutify(reverse('amo.paypal')),
        'receiverList.receiver(0).email': data['email'],
        'receiverList.receiver(0).amount': data['amount'],
        'receiverList.receiver(0).invoiceID': 'mozilla-%s' % data['uuid'],
        'receiverList.receiver(0).primary': 'TRUE',
        'receiverList.receiver(0).paymentType': 'DIGITALGOODS',
        'requestEnvelope.errorLanguage': 'US'
    }

    if data.get('memo'):
        paypal_data['memo'] = data['memo']

    with statsd.timer('paypal.paykey.retrieval'):
        response = _call(settings.PAYPAL_PAY_URL + 'Pay', paypal_data,
                         ip=data['ip'])

    return response['payKey'], response['paymentExecStatus']
Example #38
0
    def _authenticate(self, token):
        url = absolutify('/api/whatever')
        prefix = api_settings.JWT_AUTH_HEADER_PREFIX
        request = self.factory.post(
            url, HTTP_HOST='testserver',
            HTTP_AUTHORIZATION='{0} {1}'.format(prefix, token))

        return self.auth.authenticate(request)
Example #39
0
    def _authenticate(self, token):
        url = absolutify('/api/v3/whatever/')
        prefix = WebTokenAuthentication.auth_header_prefix
        request = self.factory.post(
            url, HTTP_HOST='testserver',
            HTTP_AUTHORIZATION='{0} {1}'.format(prefix, token))

        return self.auth.authenticate(request)
    def test_basic(self):
        self.addon = addon_factory(
            description=u'My Addôn description',
            file_kw={
                'hash': 'fakehash',
                'size': 42,
            },
            guid='{%s}' % uuid.uuid4(),
            homepage=u'https://www.example.org/',
            name=u'My Addôn',
            public_stats=True,
            slug='my-addon',
            summary=u'My Addôn summary',
            support_email=u'*****@*****.**',
            support_url=u'https://support.example.org/support/my-addon/',
            tags=['some_tag', 'some_other_tag'],
        )

        result = self.serialize()
        version = self.addon.current_version
        file_ = version.files.latest('pk')

        assert result['id'] == self.addon.pk

        assert result['current_version']
        assert result['current_version']['id'] == version.pk
        assert result['current_version']['files']
        assert len(result['current_version']['files']) == 1

        result_file = result['current_version']['files'][0]
        assert result_file['id'] == file_.pk
        assert result_file['created'] == file_.created.isoformat()
        assert result_file['hash'] == file_.hash
        assert result_file['platform'] == file_.get_platform_display()
        assert result_file['size'] == file_.size
        assert result_file['status'] == file_.get_status_display()
        assert result_file['url'] == file_.get_url_path(src='')

        assert result['current_version']['reviewed'] == version.reviewed
        assert result['current_version']['version'] == version.version

        assert result['default_locale'] == self.addon.default_locale
        assert result['description'] == {'en-US': self.addon.description}
        assert result['guid'] == self.addon.guid
        assert result['homepage'] == {'en-US': self.addon.homepage}
        assert result['is_listed'] == self.addon.is_listed
        assert result['name'] == {'en-US': self.addon.name}
        assert result['last_updated'] == self.addon.last_updated.isoformat()
        assert result['public_stats'] == self.addon.public_stats
        assert result['slug'] == self.addon.slug
        assert result['status'] == self.addon.get_status_display()
        assert result['summary'] == {'en-US': self.addon.summary}
        assert result['support_email'] == {'en-US': self.addon.support_email}
        assert result['support_url'] == {'en-US': self.addon.support_url}
        assert set(result['tags']) == set(['some_tag', 'some_other_tag'])
        assert result['type'] == self.addon.get_type_display()
        assert result['url'] == absolutify(self.addon.get_url_path())
        return result
Example #41
0
    def test_basic(self):
        self.addon = addon_factory(
            description=u'My Addôn description',
            file_kw={
                'hash': 'fakehash',
                'size': 42,
            },
            guid='{%s}' % uuid.uuid4(),
            homepage=u'https://www.example.org/',
            name=u'My Addôn',
            public_stats=True,
            slug='my-addon',
            summary=u'My Addôn summary',
            support_email=u'*****@*****.**',
            support_url=u'https://support.example.org/support/my-addon/',
            tags=['some_tag', 'some_other_tag'],
        )

        result = self.serialize()
        version = self.addon.current_version
        file_ = version.files.latest('pk')

        assert result['id'] == self.addon.pk

        assert result['current_version']
        assert result['current_version']['id'] == version.pk
        assert result['current_version']['files']
        assert len(result['current_version']['files']) == 1

        result_file = result['current_version']['files'][0]
        assert result_file['id'] == file_.pk
        assert result_file['created'] == file_.created.isoformat()
        assert result_file['hash'] == file_.hash
        assert result_file['platform'] == file_.get_platform_display()
        assert result_file['size'] == file_.size
        assert result_file['status'] == file_.get_status_display()
        assert result_file['url'] == file_.get_url_path(src='')

        assert result['current_version']['reviewed'] == version.reviewed
        assert result['current_version']['version'] == version.version

        assert result['default_locale'] == self.addon.default_locale
        assert result['description'] == {'en-US': self.addon.description}
        assert result['guid'] == self.addon.guid
        assert result['homepage'] == {'en-US': self.addon.homepage}
        assert result['name'] == {'en-US': self.addon.name}
        assert result['last_updated'] == self.addon.last_updated.isoformat()
        assert result['public_stats'] == self.addon.public_stats
        assert result['slug'] == self.addon.slug
        assert result['status'] == self.addon.get_status_display()
        assert result['summary'] == {'en-US': self.addon.summary}
        assert result['support_email'] == {'en-US': self.addon.support_email}
        assert result['support_url'] == {'en-US': self.addon.support_url}
        assert set(result['tags']) == set(['some_tag', 'some_other_tag'])
        assert result['type'] == self.addon.get_type_display()
        assert result['url'] == absolutify(self.addon.get_url_path())
        return result
Example #42
0
def log_and_notify(action, comments, note_creator, version):
    log_kwargs = {
        'user': note_creator,
        'created': datetime.datetime.now(),
        'details': {
            'comments': comments,
            'version': version.version
        }
    }
    note = amo.log(action, version.addon, version, **log_kwargs)

    # Collect reviewers involved with this version.
    review_perm = ('Review' if version.channel == amo.RELEASE_CHANNEL_LISTED
                   else 'ReviewUnlisted')
    log_users = {
        alog.user
        for alog in ActivityLog.objects.for_version(version)
        if acl.action_allowed_user(alog.user, 'Addons', review_perm)
    }
    # Collect add-on authors (excl. the person who sent the email.)
    addon_authors = set(version.addon.authors.all()) - {note_creator}
    # Collect staff that want a copy of the email
    staff_cc = set(
        UserProfile.objects.filter(groups__name=ACTIVITY_MAIL_GROUP))
    # If task_user doesn't exist that's no big issue (i.e. in tests)
    try:
        task_user = {get_task_user()}
    except UserProfile.DoesNotExist:
        task_user = set()
    # Collect reviewers on the thread (excl. the email sender and task user for
    # automated messages).
    reviewers = ((log_users | staff_cc) - addon_authors - task_user -
                 {note_creator})
    author_context_dict = {
        'name': version.addon.name,
        'number': version.version,
        'author': note_creator.name,
        'comments': comments,
        'url': version.addon.get_dev_url('versions'),
        'SITE_URL': settings.SITE_URL,
    }
    reviewer_context_dict = author_context_dict.copy()
    reviewer_context_dict['url'] = absolutify(
        reverse('editors.review', args=[version.addon.pk], add_prefix=False))

    # Not being localised because we don't know the recipients locale.
    subject = 'Mozilla Add-ons: %s Updated' % version.addon.name
    template = loader.get_template('activity/emails/developer.txt')
    send_activity_mail(subject, template.render(Context(author_context_dict)),
                       version, addon_authors, settings.EDITORS_EMAIL)
    send_activity_mail(subject,
                       template.render(Context(reviewer_context_dict)),
                       version, reviewers, settings.EDITORS_EMAIL)
    return note
 def _check_disco_theme(self, result, item):
     addon = self.addons[item.addon_id]
     assert result['addon']['id'] == item.addon_id == addon.pk
     assert result['addon']['name'] == unicode(addon.name)
     assert result['addon']['slug'] == addon.slug
     assert u'{1} <span>by <a href="{0}">{2}</a></span>'.format(
         absolutify(addon.get_url_path()), unicode(addon.name), u', '.join(
             author.name
             for author in addon.listed_authors)) == result['heading']
     assert not result['description']
     assert result['addon']['theme_data'] == addon.persona.theme_data
Example #44
0
 def send_notification(self, version):
     user_log.info('Sending addon update notice to %s for %s' %
                   (self.user.email, self.addon.pk))
     context = Context({
         'name': self.addon.name,
         'url': absolutify(reverse('addons.detail', args=[self.addon.pk],
                                   add_prefix=False)),
         'number': version.version,
         'review': absolutify(reverse('editors.review',
                                      args=[self.addon.pk],
                                      add_prefix=False)),
         'SITE_URL': settings.SITE_URL,
     })
     # Not being localised because we don't know the editors locale.
     subject = 'Mozilla Add-ons: %s Updated' % self.addon.name
     template = loader.get_template('editors/emails/notify_update.ltxt')
     send_mail(subject, template.render(Context(context)),
               recipient_list=[self.user.email],
               from_email=settings.EDITORS_EMAIL,
               use_blacklist=False)
    def test_basic(self):
        result = self.serialize()

        assert result['id'] == self.entry.pk
        assert result['date'] == self.now.isoformat()
        assert result['action'] == 'rejected'
        assert result['action_label'] == 'Rejected'
        assert result['comments'] == u'Oh nôes!'
        assert result['user'] == {
            'name': self.user.name,
            'url': absolutify(self.user.get_url_path())}
Example #46
0
 def _check_disco_theme(self, result, item):
     addon = self.addons[item.addon_id]
     assert result['addon']['id'] == item.addon_id == addon.pk
     assert result['addon']['name'] == unicode(addon.name)
     assert result['addon']['slug'] == addon.slug
     assert '<a href="{0}">{1}</a>'.format(
         absolutify(addon.get_url_path()),
         unicode(addon.name)) == result['heading']
     assert '<span>' not in result['heading']
     assert '</span>' not in result['heading']
     assert not result['description']
     assert result['addon']['theme_data'] == addon.persona.theme_data
Example #47
0
 def _check_disco_theme(self, result, item):
     addon = self.addons[item.addon_id]
     assert result['addon']['id'] == item.addon_id == addon.pk
     assert result['addon']['name'] == unicode(addon.name)
     assert result['addon']['slug'] == addon.slug
     assert u'<a href="{0}">{1}</a>'.format(
         absolutify(addon.get_url_path()),
         unicode(addon.name)) == result['heading']
     assert '<span>' not in result['heading']
     assert '</span>' not in result['heading']
     assert not result['description']
     assert result['addon']['theme_data'] == addon.persona.theme_data
Example #48
0
    def test_basic(self):
        result = self.serialize()

        assert result['id'] == self.entry.pk
        assert result['date'] == self.now.isoformat() + 'Z'
        assert result['action'] == 'rejected'
        assert result['action_label'] == 'Rejected'
        assert result['comments'] == u'Oh nôes!'
        assert result['user'] == {
            'id': self.user.pk,
            'name': self.user.name,
            'url': absolutify(self.user.get_url_path())}
Example #49
0
 def _check_disco_theme(self, result, item):
     addon = self.addons[item.addon_id]
     assert result['addon']['id'] == item.addon_id == addon.pk
     assert result['addon']['name'] == unicode(addon.name)
     assert result['addon']['slug'] == addon.slug
     assert u'{1} <span>by <a href="{0}">{2}</a></span>'.format(
         absolutify(addon.get_url_path()),
         unicode(addon.name),
         u', '.join(author.name for author in addon.listed_authors)
     ) == result['heading']
     assert not result['description']
     assert result['addon']['theme_data'] == addon.persona.theme_data
Example #50
0
 def send_notification(self, version):
     user_log.info("Sending addon update notice to %s for %s" % (self.user.email, self.addon.pk))
     context = Context(
         {
             "name": self.addon.name,
             "url": absolutify(reverse("addons.detail", args=[self.addon.pk], add_prefix=False)),
             "number": version.version,
             "review": absolutify(reverse("editors.review", args=[self.addon.pk], add_prefix=False)),
             "SITE_URL": settings.SITE_URL,
         }
     )
     # Not being localised because we don't know the editors locale.
     subject = "Mozilla Add-ons: %s Updated" % self.addon.name
     template = loader.get_template("editors/emails/notify_update.ltxt")
     send_mail(
         subject,
         template.render(Context(context)),
         recipient_list=[self.user.email],
         from_email=settings.EDITORS_EMAIL,
         use_blacklist=False,
     )
    def test_icon_url_without_modified_date(self):
        self.addon = addon_factory(icon_type='image/png')
        self.addon.update(created=datetime(year=1970, day=1, month=1))

        obj = self.search()
        delattr(obj, 'modified')

        with self.assertNumQueries(0):
            serializer = ESAddonSerializer(context={'request': self.request})
            result = serializer.to_representation(obj)

        assert result['id'] == self.addon.pk

        # icon_url should differ, since the serialized result could not use
        # the modification date.
        assert result['icon_url'] != absolutify(self.addon.get_icon_url(64))

        # If we pretend the original add-on modification date is its creation
        # date, then icon_url should be the same, since that's what we do when
        # we don't have a modification date in the serializer.
        self.addon.modified = self.addon.created
        assert result['icon_url'] == absolutify(self.addon.get_icon_url(64))
Example #52
0
 def get_context_data(self):
     addon_url = self.addon.get_url_path(add_prefix=False)
     dev_ver_url = self.addon.get_dev_url('versions')
     # We need to display the name in some language that is relevant to the
     # recipient(s) instead of using the reviewer's. addon.default_locale
     # should work.
     if self.addon.name.locale != self.addon.default_locale:
         lang = to_language(self.addon.default_locale)
         with translation.override(lang):
             addon = Addon.unfiltered.get(pk=self.addon.pk)
     else:
         addon = self.addon
     return {'name': addon.name,
             'number': self.version.version if self.version else '',
             'reviewer': self.user.display_name,
             'addon_url': absolutify(addon_url),
             'dev_versions_url': absolutify(dev_ver_url),
             'review_url': absolutify(reverse('editors.review',
                                              args=[self.addon.pk],
                                              add_prefix=False)),
             'comments': self.data.get('comments'),
             'SITE_URL': settings.SITE_URL}
    def test_icon_url_without_modified_date(self):
        self.addon = addon_factory(icon_type='image/png')
        self.addon.update(created=datetime(year=1970, day=1, month=1))

        obj = self.search()
        delattr(obj, 'modified')

        with self.assertNumQueries(0):
            serializer = ESAddonSerializer(context={'request': self.request})
            result = serializer.to_representation(obj)

        assert result['id'] == self.addon.pk

        # icon_url should differ, since the serialized result could not use
        # the modification date.
        assert result['icon_url'] != absolutify(self.addon.get_icon_url(64))

        # If we pretend the original add-on modification date is its creation
        # date, then icon_url should be the same, since that's what we do when
        # we don't have a modification date in the serializer.
        self.addon.modified = self.addon.created
        assert result['icon_url'] == absolutify(self.addon.get_icon_url(64))
    def test_basic(self):
        now = self.days_ago(0)
        entry = self.log(u'Oh nôes!', amo.LOG.REJECT_VERSION, now)

        result = self.serialize(entry)

        assert result['id'] == entry.pk
        assert result['date'] == now.isoformat()
        assert result['action'] == 'rejected'
        assert result['action_label'] == 'Rejected'
        assert result['comments'] == u'Oh nôes!'
        assert result['user'] == {
            'name': self.user.name,
            'url': absolutify(self.user.get_url_path())}
Example #55
0
    def to_representation(self, instance):
        data = super(DiscoverySerializer, self).to_representation(instance)
        # Note: target and rel attrs are added in addons-frontend.
        addon_link = u'<a href="{0}">{1}</a>'.format(
            absolutify(instance.addon.get_url_path()),
            unicode(instance.addon.name))

        if data['heading'] is None:
            data['heading'] = addon_link
        else:
            data['heading'] = data['heading'].replace(
                '{start_sub_heading}', '<span>').replace(
                '{end_sub_heading}', '</span>').replace(
                '{addon_name}', addon_link)
        return data
Example #56
0
    def test_latest_unlisted_version_with_rights(self):
        self.serializer_class = self.serializer_class_with_unlisted_data

        self.addon = addon_factory()
        version_factory(
            addon=self.addon, channel=amo.RELEASE_CHANNEL_UNLISTED,
            version='1.1')
        assert self.addon.latest_unlisted_version

        result = self.serialize()
        # In this serializer latest_unlisted_version is present.
        assert result['latest_unlisted_version']
        self._test_version(
            self.addon.latest_unlisted_version,
            result['latest_unlisted_version'])
        assert result['latest_unlisted_version']['url'] == absolutify('')
Example #57
0
 def test_error_no_code_with_safe_path(self):
     request = self.make_request()
     assert len(get_messages(request)) == 0
     response = self.render_error(
         request, views.ERROR_NO_CODE, next_path='/over/here')
     assert response.status_code == 302
     messages = get_messages(request)
     assert len(messages) == 1
     assert 'could not be parsed' in next(iter(messages)).message
     assert_url_equal(response['location'], absolutify('/over/here'))
     response = self.render_error(
         request, views.ERROR_NO_CODE, next_path=None)
     assert response.status_code == 302
     messages = get_messages(request)
     assert len(messages) == 1
     assert 'could not be parsed' in next(iter(messages)).message
     assert_url_equal(response['location'], self.login_url())
Example #58
0
    def test_reply_triggers_email_but_no_logging(self):
        review = Review.objects.get(id=1)
        user = user_factory()
        Review.objects.create(
            reply_to=review, user=user, addon=review.addon,
            body=u'Rêply', user_responsible=user)

        assert not ActivityLog.objects.exists()
        assert len(mail.outbox) == 1
        email = mail.outbox[0]
        reply_url = helpers.absolutify(
            helpers.url('addons.reviews.detail', review.addon.slug,
                        review.pk, add_prefix=False))
        assert email.subject == 'Mozilla Add-on Developer Reply: my addon name'
        assert 'A developer has replied to your review' in email.body
        assert 'add-on my addon name' in email.body
        assert reply_url in email.body
        assert email.to == ['*****@*****.**']
        assert email.from_email == 'Mozilla Add-ons <*****@*****.**>'