addons-server/apps/versions/views.py

134 строки
4.8 KiB
Python

import posixpath
from django import http
from django.shortcuts import get_object_or_404, redirect
from django.views.decorators.cache import never_cache
import caching.base as caching
import commonware.log
import jingo
from mobility.decorators import mobile_template
import waffle
import amo
from amo.decorators import login_required
from amo.urlresolvers import reverse
from amo.utils import urlparams, HttpResponseSendFile
from access import acl
from addons.decorators import addon_view_factory
from addons.models import Addon
from files.models import File
from versions.models import Version
# The version detail page redirects to the version within pagination, so we
# need to enforce the number of versions per page.
PER_PAGE = 30
addon_view = addon_view_factory(Addon.objects.valid)
log = commonware.log.getLogger('z.versions')
@addon_view
@mobile_template('versions/{mobile/}version_list.html')
def version_list(request, addon, template):
qs = (addon.versions.filter(files__status__in=amo.VALID_STATUSES)
.distinct().order_by('-created'))
versions = amo.utils.paginate(request, qs, PER_PAGE)
versions.object_list = list(versions.object_list)
Version.transformer(versions.object_list)
return jingo.render(request, template,
{'addon': addon, 'versions': versions})
@addon_view
def version_detail(request, addon, version_num):
qs = (addon.versions.filter(files__status__in=amo.VALID_STATUSES)
.distinct().order_by('-created'))
# Use cached_with since values_list won't be cached.
f = lambda: _find_version_page(qs, addon, version_num)
return caching.cached_with(qs, f, 'vd:%s:%s' % (addon.id, version_num))
def _find_version_page(qs, addon, version_num):
ids = list(qs.values_list('version', flat=True))
url = reverse('addons.versions', args=[addon.slug])
if version_num in ids:
page = 1 + ids.index(version_num) / PER_PAGE
return redirect(urlparams(url, 'version-%s' % version_num, page=page))
else:
raise http.Http404()
@never_cache
@login_required
def download_watermarked(request, file_id):
if not waffle.switch_is_active('marketplace'):
raise http.Http404()
file = get_object_or_404(File.objects, pk=file_id)
addon = get_object_or_404(Addon.objects, pk=file.version.addon_id)
# TODO(andym): assert payment went through here?
if (not addon.is_premium() or addon.is_disabled
or file.status == amo.STATUS_DISABLED):
raise http.Http404()
dest = file.watermark(request.amo_user)
if not dest:
# TODO(andym): the watermarking is already in progress and we've
# got multiple requests from the same users for the same file
# perhaps this should go into a loop.
log.debug('Watermark already in progress: %s' % file_id)
raise http.Http404()
log.debug('Serving watermarked file for: %s' % file_id)
return HttpResponseSendFile(request, dest,
content_type='application/xp-install')
# Should accept junk at the end for filename goodness.
def download_file(request, file_id, type=None):
file = get_object_or_404(File.objects, pk=file_id)
addon = get_object_or_404(Addon.objects, pk=file.version.addon_id)
if addon.is_premium():
return http.HttpResponseForbidden()
if addon.is_disabled or file.status == amo.STATUS_DISABLED:
if acl.check_addon_ownership(request, addon, viewer=True, ignore_disabled=True):
return HttpResponseSendFile(request, file.guarded_file_path,
content_type='application/xp-install')
else:
raise http.Http404()
attachment = (type == 'attachment' or not request.APP.browser)
loc = file.get_mirror(addon, attachment=attachment)
response = http.HttpResponseRedirect(loc)
response['X-Target-Digest'] = file.hash
return response
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))
files = File.objects.filter(platform__in=platforms,
version=addon._current_version_id)
try:
# If there's a file matching our platform, it'll float to the end.
file = sorted(files, key=lambda f: f.platform_id == platforms[-1])[-1]
except IndexError:
raise http.Http404()
args = [file.id, type] if type else [file.id]
url = posixpath.join(reverse('downloads.file', args=args), file.filename)
if request.GET:
url += '?' + request.GET.urlencode()
return redirect(url)