Decode guid using base64 if prefixed by rta: in search API
This supports the "Return to AMO" feature from bug 1468680.
This commit is contained in:
Родитель
196795c046
Коммит
4be0ca4973
|
@ -50,7 +50,7 @@ This endpoint allows you to search through public add-ons.
|
||||||
:query boolean featured: Filter to only featured add-ons. Only ``featured=true`` is supported.
|
:query boolean featured: Filter to only featured add-ons. Only ``featured=true`` is supported.
|
||||||
If ``app`` is provided as a parameter then only featured collections targeted to that application are taken into account.
|
If ``app`` is provided as a parameter then only featured collections targeted to that application are taken into account.
|
||||||
If ``lang`` is provided then only featured collections targeted to that language, (and collections for all languages), are taken into account. Both ``app`` and ``lang`` can be provided to filter to addons that are featured in collections that application and for that language, (and for all languages).
|
If ``lang`` is provided then only featured collections targeted to that language, (and collections for all languages), are taken into account. Both ``app`` and ``lang`` can be provided to filter to addons that are featured in collections that application and for that language, (and for all languages).
|
||||||
:query string guid: Filter by exact add-on guid. Multiple guids can be specified, separated by comma(s), in which case any add-ons matching any of the guids will be returned. As guids are unique there should be at most one add-on result per guid specified.
|
:query string guid: Filter by exact add-on guid. Multiple guids can be specified, separated by comma(s), in which case any add-ons matching any of the guids will be returned. As guids are unique there should be at most one add-on result per guid specified. For usage with Firefox, instead of separating multiple guids by comma(s), a single guid can be passed in base64url format, prefixed by the ``rta:`` string.
|
||||||
:query string lang: Activate translations in the specific language for that query. (See :ref:`translated fields <api-overview-translations>`)
|
:query string lang: Activate translations in the specific language for that query. (See :ref:`translated fields <api-overview-translations>`)
|
||||||
:query int page: 1-based page number. Defaults to 1.
|
:query int page: 1-based page number. Defaults to 1.
|
||||||
:query int page_size: Maximum number of results to return for the requested page. Defaults to 25.
|
:query int page_size: Maximum number of results to return for the requested page. Defaults to 25.
|
||||||
|
|
|
@ -7,7 +7,7 @@ from django.conf import settings
|
||||||
from django.core import mail
|
from django.core import mail
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
from django.test.client import Client
|
from django.test.client import Client
|
||||||
from django.utils.http import urlunquote
|
from django.utils.http import urlsafe_base64_encode, urlunquote
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -2864,6 +2864,42 @@ class TestAddonSearchView(ESTestCase):
|
||||||
assert data['results'][0]['id'] == addon.pk
|
assert data['results'][0]['id'] == addon.pk
|
||||||
assert data['results'][1]['id'] == addon2.pk
|
assert data['results'][1]['id'] == addon2.pk
|
||||||
|
|
||||||
|
def test_filter_by_guid_return_to_amo(self):
|
||||||
|
addon = addon_factory(slug='my-addon', name=u'My Addôn',
|
||||||
|
guid='random@guid', weekly_downloads=999)
|
||||||
|
addon_factory()
|
||||||
|
self.reindex(Addon)
|
||||||
|
|
||||||
|
param = 'rta:%s' % urlsafe_base64_encode(addon.guid)
|
||||||
|
|
||||||
|
data = self.perform_search(self.url, {'guid': param})
|
||||||
|
assert data['count'] == 1
|
||||||
|
assert len(data['results']) == 1
|
||||||
|
|
||||||
|
result = data['results'][0]
|
||||||
|
assert result['id'] == addon.pk
|
||||||
|
assert result['slug'] == addon.slug
|
||||||
|
|
||||||
|
def test_filter_by_guid_return_to_amo_wrong_format(self):
|
||||||
|
param = 'rta:%s' % urlsafe_base64_encode('foo@bar')[:-1]
|
||||||
|
|
||||||
|
data = self.perform_search(
|
||||||
|
self.url, {'guid': param}, expected_status=400)
|
||||||
|
assert data == [u'Invalid RTA guid (not base64url?)']
|
||||||
|
|
||||||
|
@override_settings(RETURN_TO_AMO=False)
|
||||||
|
def test_filter_by_guid_return_to_amo_feature_disabled(self):
|
||||||
|
addon = addon_factory(slug='my-addon', name=u'My Addôn',
|
||||||
|
guid='random@guid', weekly_downloads=999)
|
||||||
|
addon_factory()
|
||||||
|
self.reindex(Addon)
|
||||||
|
|
||||||
|
param = 'rta:%s' % urlsafe_base64_encode(addon.guid)
|
||||||
|
|
||||||
|
data = self.perform_search(
|
||||||
|
self.url, {'guid': param}, expected_status=400)
|
||||||
|
assert data == [u'RTA is currently disabled']
|
||||||
|
|
||||||
def test_find_addon_default_non_en_us(self):
|
def test_find_addon_default_non_en_us(self):
|
||||||
with self.activate('en-GB'):
|
with self.activate('en-GB'):
|
||||||
addon = addon_factory(
|
addon = addon_factory(
|
||||||
|
|
|
@ -1788,6 +1788,12 @@ DRF_API_GATES = {
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Return to AMO (https://bugzilla.mozilla.org/show_bug.cgi?id=1468680)
|
||||||
|
# kill switch. RETURN_TO_AMO=0 env variable deactivates it, causing the API to
|
||||||
|
# return 400s when the feature is used.
|
||||||
|
RETURN_TO_AMO = env('RETURN_TO_AMO', default=True)
|
||||||
|
|
||||||
|
|
||||||
# Change this to deactivate API throttling for views using a throttling class
|
# Change this to deactivate API throttling for views using a throttling class
|
||||||
# depending on the one defined in olympia.api.throttling.
|
# depending on the one defined in olympia.api.throttling.
|
||||||
API_THROTTLING = True
|
API_THROTTLING = True
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
from django.conf import settings
|
||||||
from django.utils import translation
|
from django.utils import translation
|
||||||
|
from django.utils.http import urlsafe_base64_decode
|
||||||
from django.utils.translation import ugettext
|
from django.utils.translation import ugettext
|
||||||
|
|
||||||
import colorgram
|
import colorgram
|
||||||
|
@ -135,7 +137,23 @@ class AddonGuidQueryParam(AddonQueryParam):
|
||||||
es_field = 'guid'
|
es_field = 'guid'
|
||||||
|
|
||||||
def get_value(self):
|
def get_value(self):
|
||||||
value = self.request.GET.get(self.query_param)
|
value = self.request.GET.get(self.query_param, '')
|
||||||
|
|
||||||
|
# Hack for Firefox 'return to AMO' feature (which, sadly, does not use
|
||||||
|
# a specific API but rather encodes the guid and adds a prefix to it,
|
||||||
|
# only in the search API): if the guid param matches this format, and
|
||||||
|
# the feature is enabled through a setting, then we decode it and
|
||||||
|
# proceed. A 400 is returned if the format is recognized but the
|
||||||
|
# feature is disabled through the setting, acting as a kill-switch.
|
||||||
|
if value.startswith('rta:') and '@' not in value:
|
||||||
|
if settings.RETURN_TO_AMO is not True:
|
||||||
|
raise ValueError('RTA is currently disabled')
|
||||||
|
# Any ValueError will trigger a 400.
|
||||||
|
try:
|
||||||
|
value = urlsafe_base64_decode(value[4:])
|
||||||
|
except TypeError:
|
||||||
|
raise ValueError('Invalid RTA guid (not base64url?)')
|
||||||
|
|
||||||
return value.split(',') if value else []
|
return value.split(',') if value else []
|
||||||
|
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче