Skip to content
This repository has been archived by the owner on Mar 15, 2018. It is now read-only.

Commit

Permalink
Expose 'installs_allowed_from' in API (bug 965964)
Browse files Browse the repository at this point in the history
  • Loading branch information
robhudson committed Nov 26, 2014
1 parent 2e7d968 commit bbff414
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 16 deletions.
2 changes: 2 additions & 0 deletions docs/api/topics/search.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ Search
exact match and should only return a single result if a match is
found.
:type manifest_url: string
:param installs_allowed_from: Filters apps by the manifest
'installs_allowed_from' field. The only supported value is '*'.
:param optional offline: Filters by whether the app works offline or not.
'True' to show offline-capable apps; 'False' to show apps requiring
online support; any other value will show all apps unfiltered by
Expand Down
4 changes: 4 additions & 0 deletions mkt/search/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ class ApiSearchForm(forms.Form):
required=False, choices=APP_TYPE_CHOICES,
widget=forms.CheckboxSelectMultiple(), label=_lazy(u'App type'))
manifest_url = forms.CharField(required=False, label=_lazy('Manifest URL'))
# TODO: If we ever want to allow any string here change to a `CharField`.
installs_allowed_from = forms.ChoiceField(
required=False, label=_lazy('Installs allowed from'),
choices=[('*', _lazy('Everywhere'))])
offline = forms.NullBooleanField(required=False,
label=_lazy('Works offline'))
languages = forms.CharField(required=False,
Expand Down
26 changes: 13 additions & 13 deletions mkt/search/tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
from mkt.regions import set_region
from mkt.reviewers.forms import ApiReviewersSearchForm
from mkt.search.forms import ApiSearchForm, TARAKO_CATEGORIES_MAPPING
from mkt.search.views import _sort_search, DEFAULT_SORTING
from mkt.search.views import (_sort_search, DEFAULT_SORTING,
search_form_to_es_fields)
from mkt.site.fixtures import fixture
from mkt.webapps.indexers import WebappIndexer

Expand All @@ -38,18 +39,8 @@ def _filter(self, req, filters, **kwargs):
form = self.form_class(filters)
if form.is_valid():
form_data = form.cleaned_data
sq = WebappIndexer.get_app_filter(self.req, {
'app_type': form_data['app_type'],
'author.raw': form_data['author'],
'category': form_data['cat'],
'device': form_data['device'],
'is_offline': form_data['offline'],
'manifest_url': form_data['manifest_url'],
'q': form_data['q'],
'premium_type': form_data['premium_types'],
'supported_locales': form_data['languages'],
'tags': form_data['tag'],
})
sq = WebappIndexer.get_app_filter(
self.req, search_form_to_es_fields(form_data))
return _sort_search(self.req, sq, form_data).to_dict()
else:
return form.errors.copy()
Expand Down Expand Up @@ -193,6 +184,15 @@ def test_author(self):
ok_({'term': {'author.raw': u'mozilla labs'}}
in qs['query']['filtered']['filter']['bool']['must'])

def test_installs_allowed_from(self):
qs = self._filter(self.req, {'installs_allowed_from': '*'})
ok_({'term': {'installs_allowed_from': u'*'}}
in qs['query']['filtered']['filter']['bool']['must'])
# Test that we don't filter by this field if not provided.
qs = self._filter(self.req, {})
ok_('installs_allowed_from' not in json.dumps(qs),
"Unexpected 'installs_allowed_from' in query")

def test_region_exclusions(self):
self.req.REGION = regions.CO
qs = self._filter(self.req, {'q': 'search terms'})
Expand Down
21 changes: 20 additions & 1 deletion mkt/search/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ def test_sort(self):

def test_multiple_sort(self):
res = self.anon.get(self.url, [('sort', 'rating'),
('sort', 'created')])
('sort', 'created')])
eq_(res.status_code, 200)

def test_right_category(self):
Expand Down Expand Up @@ -633,6 +633,25 @@ def test_app_type_privileged(self):
obj = res.json['objects'][0]
eq_(obj['slug'], self.webapp.app_slug)

def test_installs_allowed_from_anywhere(self):
res = self.anon.get(self.url, data={'installs_allowed_from': '*'})
eq_(res.status_code, 200)
eq_(len(res.json['objects']), 1)

def test_installs_allowed_from_strict(self):
self.webapp.current_version.manifest_json.update(
manifest=json.dumps({'installs_allowed_from': 'http://a.com'}))
self.reindex(Webapp, 'webapp')
res = self.anon.get(self.url, data={'installs_allowed_from': '*'})
eq_(res.status_code, 200)
eq_(len(res.json['objects']), 0)

def test_installs_allowed_from_invalid(self):
res = self.anon.get(
self.url, data={'installs_allowed_from': 'http://a.com'})
eq_(res.status_code, 400)
ok_('installs_allowed_from' in res.json['detail'])

def test_status_value_packaged(self):
# When packaged and not a reviewer we exclude latest version status.
self.webapp.update(is_packaged=True)
Expand Down
1 change: 1 addition & 0 deletions mkt/search/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def search_form_to_es_fields(form_data):
'device': form_data['device'],
'is_offline': form_data['offline'],
'manifest_url': form_data['manifest_url'],
'installs_allowed_from': form_data['installs_allowed_from'],
'premium_type': form_data['premium_types'],
'q': form_data['q'],
'supported_locales': form_data['languages'],
Expand Down
9 changes: 7 additions & 2 deletions mkt/webapps/indexers.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ def _locale_field_mapping(field, analyzer):
'has_public_stats': {'type': 'boolean'},
'icon_hash': cls.string_not_indexed(),
'interactive_elements': cls.string_not_indexed(),
'installs_allowed_from': cls.string_not_analyzed(),
'is_disabled': {'type': 'boolean'},
'is_escalated': {'type': 'boolean'},
'is_offline': {'type': 'boolean'},
Expand Down Expand Up @@ -282,6 +283,9 @@ def extract_document(cls, pk=None, obj=None):
d['interactive_elements'] = obj.rating_interactives.to_keys()
except RatingInteractives.DoesNotExist:
d['interactive_elements'] = []
d['installs_allowed_from'] = (
version.manifest.get('installs_allowed_from', ['*'])
if version else ['*'])
d['is_escalated'] = obj.escalationqueue_set.exists()
d['is_offline'] = getattr(obj, 'is_offline', False)
d['is_priority'] = obj.priority_review
Expand Down Expand Up @@ -466,6 +470,7 @@ def get_app_filter(cls, request, additional_data=None, sq=None,
'category': None, # Slug.
'device': None, # ID.
'gaia': getattr(request, 'GAIA', False),
'installs_allowed_from': None,
'is_offline': None,
'manifest_url': '',
'mobile': getattr(request, 'MOBILE', False),
Expand All @@ -481,8 +486,8 @@ def get_app_filter(cls, request, additional_data=None, sq=None,
data.update(additional_data)

# Fields that will be filtered with a term query.
term_fields = ('author.raw', 'device', 'manifest_url', 'status',
'tags')
term_fields = ('author.raw', 'device', 'installs_allowed_from',
'manifest_url', 'status', 'tags')
# Fields that will be filtered with a terms query.
terms_fields = ('category', 'premium_type', 'app_type',
'supported_locales')
Expand Down
19 changes: 19 additions & 0 deletions mkt/webapps/tests/test_indexers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
import json
from nose.tools import eq_, ok_

import amo.tests
Expand Down Expand Up @@ -175,6 +176,24 @@ def test_extract_release_notes(self):
eq_(doc['release_notes_translations'][1],
{'lang': 'fr', 'string': release_notes['fr']})

def test_extract_installs_allowed_from(self):
# Test 'installs_allowed_from' empty defaults to ['*'].
self.app.current_version.manifest_json.update(manifest=json.dumps({}))
obj, doc = self._get_doc()
eq_(doc['installs_allowed_from'], ['*'])

# Test single value.
self.app.current_version.manifest_json.update(manifest=json.dumps({
'installs_allowed_from': ['http://a.com']}))
obj, doc = self._get_doc()
eq_(doc['installs_allowed_from'], ['http://a.com'])

# Test multiple value.
self.app.current_version.manifest_json.update(manifest=json.dumps({
'installs_allowed_from': ['http://a.com', 'http://b.com']}))
obj, doc = self._get_doc()
eq_(doc['installs_allowed_from'], ['http://a.com', 'http://b.com'])


class TestAppFilter(amo.tests.ESTestCase):

Expand Down

0 comments on commit bbff414

Please sign in to comment.