Skip to content

Commit 1a7cd21

Browse files
committed
Search & Reviewer Search API cleanup and documentation (bug 899232)
1 parent 7c53e39 commit 1a7cd21

File tree

6 files changed

+89
-57
lines changed

6 files changed

+89
-57
lines changed

docs/api/topics/reviewers.rst

+67
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,73 @@ Reviewer API provides access to the reviewer tools.
99
Reviewing
1010
=========
1111

12+
.. note:: Requires authentication and permission to review apps.
13+
14+
.. http:get:: /api/v1/reviewers/search/
15+
16+
Performs a search just like the regular Search API, but customized with
17+
extra parameters and different (smaller) apps objects returned, containing
18+
only the information that is required for reviewer tools.
19+
20+
**Response**:
21+
22+
:param meta: :ref:`meta-response-label`.
23+
:type meta: object
24+
:param objects: A :ref:`listing <objects-response-label>` of :ref:`apps <reviewers-app-response-label>`.
25+
:type objects: array
26+
27+
:status 200: successfully completed.
28+
29+
.. _reviewers-app-response-label:
30+
31+
Each app in the response will contain the following:
32+
33+
:param device_types: a list of the device types at least one of:
34+
`desktop`, `mobile`, `tablet`, `firefoxos`. `mobile` and `tablet` both
35+
refer to Android mobile and tablet. As opposed to Firefox OS.
36+
:type device_types: array
37+
:param id: the app's id.
38+
:type id: int
39+
:param is_escalated: a boolean indicating whether this app is currently
40+
in the escalation queue or not.
41+
:type is_escalated: boolean
42+
:param is_packaged: a boolean indicating whether the app is packaged or
43+
not.
44+
:type is_packaged: boolean
45+
:param latest_version: an array containing the following information about
46+
the app's latest version:
47+
:type latest_version: object
48+
:param latest_version.has_editor_comment: a boolean indicathing whether
49+
that version contains comments from a reviewer.
50+
:type latest_version.has_editor_comment: boolean
51+
:param latest_version.has_info_request: a boolean indicathing whether that
52+
version contains an information request from a reviewer.
53+
:type latest_version.has_info_request: boolean
54+
:param latest_version.is_privileged: a boolean indicating whether this
55+
version is a privileged app or not.
56+
:type latest_version.is_privileged: boolean
57+
:param latest_version.status: an int representing the version status. Can
58+
be different from the app status, since the latest_version can be
59+
different from the latest public one.
60+
:type latest_version.status: int
61+
:param name: the name of the app
62+
:type name: string
63+
:param premium_type: one of ``free``, ``premium``, ``free-inapp``,
64+
``premium-inapp``. If ``premium`` or ``premium-inapp`` the app should
65+
be bought, check the ``price`` field to determine if it can.
66+
:type premium_type: string
67+
:param price: If it is a paid app this will be a string representing
68+
the price in the currency calculated for the request. If ``0.00`` then
69+
no payment is required, but the app requires a receipt. If ``null``, a
70+
price cannot be calculated for the region and cannot be bought.
71+
Example: 1.00
72+
:type price: string|null
73+
:param name: the URL slug for the app
74+
:type name: string
75+
:param status: an int representing the version status.
76+
:type latest_version.status: int
77+
78+
1279
.. note:: Requires authentication and permission to review apps.
1380

1481
.. warning:: Not available through CORS.

docs/api/topics/search.rst

-10
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,6 @@ Search
4747
'price', 'created', separated by commas. Sorts by relevance by default.
4848
:type sort: string
4949

50-
The following parameters requires an OAuth token by a user with App
51-
Reviewer privileges:
52-
53-
:param optional status: Filters by app status. Default is 'public'. One
54-
of 'pending', 'public', 'disabled', 'rejected', 'waiting'.
55-
:type status: string
56-
:param optional is_privileged: Filters by whether the latest version of the
57-
app is privileged or not.
58-
:type is_privileged: boolean
59-
6050
**Response**
6151

6252
:param meta: :ref:`meta-response-label`.

mkt/api/resources.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
from mkt.submit.forms import AppDetailsBasicForm
4646
from mkt.webapps.models import get_excluded_in
4747
from mkt.webapps.tasks import _update_manifest
48-
from mkt.webapps.utils import app_to_dict, update_with_reviewer_data
48+
from mkt.webapps.utils import app_to_dict
4949

5050
log = commonware.log.getLogger('z.api')
5151

@@ -244,16 +244,13 @@ def dehydrate(self, bundle):
244244
bundle.data['privacy_policy'] = (
245245
PrivacyPolicyResource().get_resource_uri(bundle))
246246

247-
# Add extra data for reviewers. Used in reviewer tool search.
248-
bundle = update_with_reviewer_data(bundle, using_es=False)
249247
self.dehydrate_extra(bundle)
250248
return bundle
251249

252250
def dehydrate_extra(self, bundle):
253251
if bundle.obj.upsold:
254252
bundle.data['upsold'] = self.get_resource_uri(bundle.obj.upsold.free)
255253

256-
257254
def hydrate_premium_type(self, bundle):
258255
typ = amo.ADDON_PREMIUM_API_LOOKUP.get(bundle.data['premium_type'],
259256
None)

mkt/reviewers/api.py

+14-7
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
from mkt.reviewers.forms import ApiReviewersSearchForm
1515
from mkt.search.api import SearchResource
1616
from mkt.search.views import _get_query
17-
from mkt.webapps.utils import update_with_reviewer_data
1817

1918

2019
class Wrapper(object):
@@ -45,8 +44,9 @@ class ReviewersSearchResource(SearchResource):
4544
class Meta(SearchResource.Meta):
4645
resource_name = 'search'
4746
authorization = PermissionAuthorization('Apps', 'Review')
48-
fields = ['device_types', 'id', 'is_packaged', 'latest_version',
49-
'name', 'premium_type', 'price', 'slug', 'status']
47+
fields = ['device_types', 'id', 'is_escalated', 'is_packaged',
48+
'latest_version', 'name', 'premium_type', 'price', 'slug',
49+
'status']
5050

5151
def get_search_data(self, request):
5252
form = ApiReviewersSearchForm(request.GET if request else None)
@@ -88,8 +88,15 @@ def get_query(self, request, base_filters=None):
8888

8989
def dehydrate(self, bundle):
9090
bundle = super(ReviewersSearchResource, self).dehydrate(bundle)
91-
bundle = update_with_reviewer_data(bundle, using_es=True)
92-
# Filter out anything not present in Meta fields.
93-
bundle.data = dict(((k, v) for k, v in bundle.data.items()
94-
if k in self._meta.fields))
91+
92+
# Add reviewer-specific stuff that's not in the standard dehydrate.
93+
bundle.data['latest_version'] = bundle.obj.latest_version
94+
bundle.data['is_escalated'] = bundle.obj.is_escalated
95+
96+
# Throw away anything not in _meta.fields.
97+
filtered_data = {}
98+
for k in self._meta.fields:
99+
filtered_data[k] = bundle.data[k]
100+
bundle.data = filtered_data
101+
95102
return bundle

mkt/reviewers/tests/test_api.py

+7
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from mkt.api.base import get_url, list_url
2020
from mkt.api.models import Access, generate
2121
from mkt.constants.features import FeatureProfile
22+
from mkt.reviewers.api import ReviewersSearchResource
2223
from mkt.reviewers.utils import AppsReviewing
2324
from mkt.site.fixtures import fixture
2425
from mkt.webapps.models import Webapp
@@ -90,6 +91,12 @@ def setUp(self, api_name='reviewers'):
9091
self.webapp.update(status=amo.STATUS_PENDING)
9192
self.refresh('webapp')
9293

94+
def test_fields(self):
95+
res = self.client.get(self.url)
96+
eq_(res.status_code, 200)
97+
obj = res.json['objects'][0]
98+
self.assertSetEqual(obj.keys(), ReviewersSearchResource._meta.fields)
99+
93100
def test_anonymous_access(self):
94101
res = self.anon.get(self.url)
95102
eq_(res.status_code, 401)

mkt/webapps/utils.py

-36
Original file line numberDiff line numberDiff line change
@@ -251,39 +251,3 @@ def es_app_to_dict(obj, region=None, profile=None, request=None):
251251
}
252252

253253
return data
254-
255-
256-
def update_with_reviewer_data(bundle, using_es=False):
257-
"""Adds reviewer specific data to app response bundle."""
258-
# TODO: Reviewer flags in ES (bug 848446)
259-
from editors.models import EscalationQueue
260-
261-
if acl.action_allowed(bundle.request, 'Apps', 'Review'):
262-
# Try bundle.obj._id first if it's coming from elasticsearch.
263-
# Fallback to database results using `.id`.
264-
addon_id = getattr(bundle.obj, '_id', bundle.obj.id)
265-
266-
if using_es and hasattr(bundle.obj, 'latest_version'):
267-
# If we know we are using elasticsearch and we have latest_version,
268-
# then we can directly return it in the results.
269-
bundle.data['latest_version'] = bundle.obj.latest_version
270-
else:
271-
version = Version.objects.filter(addon_id=addon_id).latest()
272-
try:
273-
latest_version_status = version.statuses[0][1]
274-
except IndexError:
275-
latest_version_status = None
276-
bundle.data['latest_version'] = {
277-
'status': latest_version_status,
278-
'is_privileged': version.is_privileged,
279-
'has_editor_comment': version.has_editor_comment,
280-
'has_info_request': version.has_info_request,
281-
}
282-
if using_es and hasattr(bundle.obj, 'is_escalated'):
283-
bundle.data['is_escalated'] = bundle.obj.is_escalated
284-
else:
285-
escalated = EscalationQueue.objects.filter(
286-
addon_id=addon_id).exists()
287-
bundle.data['is_escalated'] = escalated
288-
289-
return bundle

0 commit comments

Comments
 (0)