From 1abccf53994204fc4fa7c4633ef0798f359c086e Mon Sep 17 00:00:00 2001 From: Andy McKay Date: Fri, 28 Oct 2011 16:20:57 -0700 Subject: [PATCH] allow authors to download premium addons, watermarked from the details page (bug 694183) --- .../templates/addons/impala/details.html | 5 ++- apps/addons/tests/test_views.py | 33 +++++++++++--- apps/files/tests/test_views.py | 12 +++++ apps/versions/urls.py | 2 +- apps/versions/views.py | 45 ++++++++++--------- 5 files changed, 68 insertions(+), 29 deletions(-) diff --git a/apps/addons/templates/addons/impala/details.html b/apps/addons/templates/addons/impala/details.html index 372054e942..f1b89316d7 100644 --- a/apps/addons/templates/addons/impala/details.html +++ b/apps/addons/templates/addons/impala/details.html @@ -45,7 +45,10 @@ {{ sharing_widget(addon) }} {% if request.check_ownership(addon, require_owner=False) %} - {{ _('Manage') }} +

{{ _('Manage') }}

+ {% if waffle.switch('marketplace') and addon.is_premium() and not addon.is_webapp() %} +

{{ _('Download') }}

+ {% endif %} {% endif %} diff --git a/apps/addons/tests/test_views.py b/apps/addons/tests/test_views.py index c509d915a6..697a1e320b 100644 --- a/apps/addons/tests/test_views.py +++ b/apps/addons/tests/test_views.py @@ -427,6 +427,13 @@ class TestPurchaseEmbedded(amo.tests.TestCase): assert 'chains' in get_paykey.call_args_list[0][0][0].keys() +def setup_premium(addon): + price = Price.objects.create(price='0.99') + AddonPremium.objects.create(addon=addon, price=price) + addon.update(premium_type=amo.ADDON_PREMIUM) + return addon, price + + # TODO: remove when the marketplace is live. @patch.object(waffle, 'switch_is_active', lambda x: True) # TODO: figure out why this is being set @@ -442,12 +449,8 @@ class TestPaypalStart(amo.tests.TestCase): self.data = {'username': 'jbalogh@mozilla.com', 'password': 'foo'} self.addon = Addon.objects.all()[0] - self.url = addon_url('addons.purchase.start', self.addon) - - self.price = Price.objects.create(price='0.99') - AddonPremium.objects.create(addon=self.addon, price=self.price) - self.addon.update(premium_type=amo.ADDON_PREMIUM) + self.addon, self.price = setup_premium(self.addon) def test_loggedout_purchased(self): # "Buy" the add-on @@ -1160,6 +1163,26 @@ class TestImpalaDetailPage(amo.tests.TestCase): def test_other_addons_none(self): eq_(self.get_more_pq()('#author-addons').length, 0) + # TODO: remove when the marketplace is live. + @patch.object(waffle, 'switch_is_active', lambda x: True) + def test_author_watermarked(self): + # Test that an author can get a watermarked addon. + self.addon, self.price = setup_premium(self.addon) + assert self.client.login(username=self.addon.authors.all()[0].email, + password='password') + res = self.client.get(self.url) + eq_(pq(res.content)('.prominent').eq(1).attr('href'), + reverse('downloads.latest', args=[self.addon.slug])) + + @patch.object(waffle, 'switch_is_active', lambda x: True) + def test_not_author(self): + # A non-author should not see the download link. + self.addon, self.price = setup_premium(self.addon) + assert self.client.login(username='regular@mozilla.com', + password='password') + res = self.client.get(self.url) + eq_(len(pq(res.content)('.prominent')), 1) + class TestStatus(amo.tests.TestCase): fixtures = ['base/apps', 'base/addon_3615'] diff --git a/apps/files/tests/test_views.py b/apps/files/tests/test_views.py index e7eb42d4fe..385fd5a68b 100644 --- a/apps/files/tests/test_views.py +++ b/apps/files/tests/test_views.py @@ -489,6 +489,7 @@ class TestWatermarkedFile(amo.tests.TestCase, amo.tests.AMOPaths): self.xpi_copy_over(self.file, 'firefm') self.url = reverse('downloads.watermarked', args=[self.file.pk]) self.user = UserProfile.objects.get(pk=999) + self.author = self.addon.authors.all()[0] self.purchase = AddonPurchase.objects.create(addon=self.addon, user=self.user) self.client.login(username='regular@mozilla.com', password='password') @@ -550,3 +551,14 @@ class TestWatermarkedFile(amo.tests.TestCase, amo.tests.AMOPaths): self.purchase.delete() res = self.client.get(self.url) eq_(res.status_code, 403) + + def test_watermark_latest_redirects(self): + url = reverse('downloads.latest', args=[self.addon.slug]) + res = self.client.get(url, follow=False) + self.assertRedirects(res, '%s/%s' % (self.url, self.file.filename)) + + def test_author_can_get(self): + self.client.logout() + self.client.login(username=self.author.email, password='password') + res = self.client.get(self.url) + assert os.path.exists(res['X-SENDFILE']) diff --git a/apps/versions/urls.py b/apps/versions/urls.py index 4b4c6ea8de..afefc246fe 100644 --- a/apps/versions/urls.py +++ b/apps/versions/urls.py @@ -24,6 +24,6 @@ download_patterns = patterns('', '(?:platform:(?P\d+)/)?.*' % ADDON_ID, views.download_latest, name='downloads.latest'), - url('^watermarked/(?P\d+)', + url('^watermarked/(?P\d+)?(?:/.*)?', views.download_watermarked, name='downloads.watermarked'), ) diff --git a/apps/versions/views.py b/apps/versions/views.py index 681cee2f7a..8b480a45f8 100644 --- a/apps/versions/views.py +++ b/apps/versions/views.py @@ -80,28 +80,30 @@ def download_watermarked(request, file_id): file = get_object_or_404(File.objects, pk=file_id) addon = get_object_or_404(Addon.objects, pk=file.version.addon_id) - - if (not addon.is_premium() or addon.is_disabled - or file.status == amo.STATUS_DISABLED): - raise http.Http404() - + author = request.check_ownership(addon, require_owner=False) user = request.amo_user - if request.user.is_anonymous(): - log.debug('Anonymous user, checking hash: %s' % file_id) - email = request.GET.get(amo.WATERMARK_KEY, None) - hsh = request.GET.get(amo.WATERMARK_KEY_HASH, None) - user = addon.get_user_from_hash(email, hsh) - if not user: - log.debug('Watermarking denied, no user: %s, %s, %s' - % (file_id, email, hsh)) + if not author: + if (not addon.is_premium() or addon.is_disabled + or file.status == amo.STATUS_DISABLED): + raise http.Http404() + + if request.user.is_anonymous(): + log.debug('Anonymous user, checking hash: %s' % file_id) + email = request.GET.get(amo.WATERMARK_KEY, None) + hsh = request.GET.get(amo.WATERMARK_KEY_HASH, None) + + user = addon.get_user_from_hash(email, hsh) + if not user: + log.debug('Watermarking denied, no user: %s, %s, %s' + % (file_id, email, hsh)) + return http.HttpResponseForbidden() + + if not addon.has_purchased(user): + log.debug('Watermarking denied, not purchased: %s, %s' + % (file_id, user.id)) return http.HttpResponseForbidden() - if not addon.has_purchased(user): - log.debug('Watermarking denied, not purchased: %s, %s' - % (file_id, user.id)) - return http.HttpResponseForbidden() - dest = file.watermark(user) if not dest: # TODO(andym): the watermarking is already in progress and we've @@ -144,9 +146,6 @@ guard = lambda: Addon.objects.filter(_current_version__isnull=False) @addon_view_factory(guard) def download_latest(request, addon, type='xpi', platform=None): - if addon.is_premium(): - return http.HttpResponseForbidden() - platforms = [amo.PLATFORM_ALL.id] if platform is not None and int(platform) in amo.PLATFORMS: platforms.append(int(platform)) @@ -158,7 +157,9 @@ def download_latest(request, addon, type='xpi', platform=None): except IndexError: raise http.Http404() args = [file.id, type] if type else [file.id] - url = posixpath.join(reverse('downloads.file', args=args), file.filename) + pattern = ('downloads.watermarked' if addon.is_premium() + else 'downloads.file') + url = posixpath.join(reverse(pattern, args=args), file.filename) if request.GET: url += '?' + request.GET.urlencode() return redirect(url)