addons-server/apps/addons/decorators.py

108 строки
3.5 KiB
Python

import functools
from django import http
from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404
import waffle
from addons.models import Addon
import commonware.log
log = commonware.log.getLogger('mkt.purchase')
def addon_view(f, qs=Addon.objects.all):
@functools.wraps(f)
def wrapper(request, addon_id=None, app_slug=None, *args, **kw):
"""Provides an addon given either an addon_id or app_slug."""
assert addon_id or app_slug, 'Must provide addon_id or app_slug'
get = lambda **kw: get_object_or_404(qs(), **kw)
if addon_id and addon_id.isdigit():
addon = get(id=addon_id)
# Don't get in an infinite loop if addon.slug.isdigit().
if addon.slug != addon_id:
url = request.path.replace(addon_id, addon.slug)
if request.GET:
url += '?' + request.GET.urlencode()
return http.HttpResponsePermanentRedirect(url)
elif addon_id:
addon = get(slug=addon_id)
elif app_slug:
addon = get(app_slug=app_slug)
return f(request, addon, *args, **kw)
return wrapper
def addon_view_factory(qs):
# Don't evaluate qs or the locale will get stuck on whatever the server
# starts with. The addon_view() decorator will call qs with no arguments
# before doing anything, so lambdas are ok.
# GOOD: Addon.objects.valid
# GOOD: lambda: Addon.objects.valid().filter(type=1)
# BAD: Addon.objects.valid()
return functools.partial(addon_view, qs=qs)
def can_be_purchased(f):
"""
Check if it can be purchased, returns False if not premium.
Must be called after the addon_view decorator.
"""
@functools.wraps(f)
def wrapper(request, addon, *args, **kw):
if not waffle.switch_is_active('marketplace'):
log.error('Marketplace waffle switch is off')
raise http.Http404
if not addon.can_be_purchased():
raise PermissionDenied
return f(request, addon, *args, **kw)
return wrapper
def has_purchased(f):
"""
If the addon is premium, require a purchase.
Must be called after addon_view decorator.
"""
@functools.wraps(f)
def wrapper(request, addon, *args, **kw):
if addon.is_premium() and not addon.has_purchased(request.amo_user):
raise PermissionDenied
return f(request, addon, *args, **kw)
return wrapper
def has_purchased_or_refunded(f):
"""
If the addon is premium, require a purchase.
Must be called after addon_view decorator.
"""
@functools.wraps(f)
def wrapper(request, addon, *args, **kw):
if addon.is_premium() and not (addon.has_purchased(request.amo_user) or
addon.is_refunded(request.amo_user)):
raise PermissionDenied
return f(request, addon, *args, **kw)
return wrapper
def has_not_purchased(f):
""" The opposite of has_purchased. """
@functools.wraps(f)
def wrapper(request, addon, *args, **kw):
if addon.is_premium() and addon.has_purchased(request.amo_user):
raise PermissionDenied
return f(request, addon, *args, **kw)
return wrapper
def can_become_premium(f):
"""Check that the addon can become premium."""
@functools.wraps(f)
def wrapper(request, addon_id, addon, *args, **kw):
if not addon.can_become_premium():
raise PermissionDenied
return f(request, addon_id, addon, *args, **kw)
return wrapper