Add `show_permissions_for` support, with documentation

This commit is contained in:
Mathieu Pillard 2018-10-12 11:25:22 +02:00
Родитель 98602ec875
Коммит 500bd093a6
3 изменённых файлов: 79 добавлений и 19 удалений

Просмотреть файл

@ -27,6 +27,7 @@ user has already posted a rating for the current version of an add-on.
.. http:get:: /api/v4/ratings/rating/
:query string addon: The :ref:`add-on <addon-detail>` id, slug, or guid to fetch ratings from. When passed, the ratings shown will always be the latest posted by each user on this particular add-on (which means there should only be one rating per user in the results), unless the ``version`` parameter is also passed.
:query string show_permissions_for: The user id to show permissions for. If the request is made with an authenticated user matching this parameter value, and the ``addon`` parameter is also present, a ``can_reply`` property will be added to the response as described below.
:query string filter: The :ref:`filter(s) <rating-filtering-param>` to apply.
:query int user: The user id to fetch ratings from.
:query boolean show_grouped_ratings: Whether or not to show ratings aggregates for this add-on in the response (Use "true"/"1" as truthy values, "0"/"false" as falsy ones).
@ -38,7 +39,7 @@ user has already posted a rating for the current version of an add-on.
:>json string next: The URL of the next page of results.
:>json string previous: The URL of the previous page of results.
:>json array results: An array of :ref:`ratings <rating-detail-object>`.
:>json boolean can_reply: Only present if the ``addon`` query parameter is present. A boolean indicating if the user that made the ratings list request can reply to ratings in that list.
:>json boolean can_reply: Only present if the ``addon`` query parameter and ``show_permissions_for`` parameters are present. A boolean indicating if the user that made the ratings list request can reply to ratings in that list.
:>json object grouped_ratings: Only present if ``show_grouped_ratings`` query parameter is present. An object with 5 key-value pairs, the keys representing each possible rating (Though a number, it has to be converted to a string because of the JSON formatting) and the values being the number of times the corresponding rating has been posted for this add-on, e.g. ``{"1": 4, "2": 8, "3": 15, "4": 16: "5": 23}``.
.. _rating-filtering-param:

Просмотреть файл

@ -809,30 +809,71 @@ class TestRatingViewSetGet(TestCase):
assert len(data['results']) == 2
assert data['results'][0]['id'] == review2.pk
assert data['results'][1]['id'] == review1.pk
if 'expected_can_reply' in kwargs:
assert data['can_reply'] is kwargs['expected_can_reply']
if 'show_permissions_for' not in kwargs:
assert 'can_reply' not in data
if 'show_grouped_ratings' not in kwargs:
assert 'grouped_ratings' not in data
return data
def test_list_show_permission_for_anonymous(self):
response = self.client.get(
self.url, {'addon': self.addon.pk,
'show_permissions_for': 666})
assert response.status_code == 400
assert response.data['detail'] == (
'show_permissions_for parameter value should be equal to the user '
'id of the authenticated user')
def test_list_show_permission_for_not_int(self):
response = self.client.get(
self.url, {'addon': self.addon.pk,
'show_permissions_for': 'nope'})
assert response.status_code == 400
assert response.data['detail'] == (
'show_permissions_for parameter value should be equal to the user '
'id of the authenticated user')
def test_list_show_permission_for_not_right_user(self):
self.user = user_factory()
self.client.login_api(self.user)
response = self.client.get(
self.url, {'addon': self.addon.pk,
'show_permissions_for': self.user.pk + 42})
assert response.status_code == 400
assert response.data['detail'] == (
'show_permissions_for parameter value should be equal to the user '
'id of the authenticated user')
def test_list_show_permissions_for_without_addon(self):
self.user = user_factory()
self.client.login_api(self.user)
response = self.client.get(
self.url, {'user': self.user.pk,
'show_permissions_for': self.user.pk})
assert response.status_code == 400
assert response.data['detail'] == (
'show_permissions_for parameter is only valid if the addon '
'parameter is also present')
def test_list_can_reply(self):
self.user = user_factory()
self.client.login_api(self.user)
self.addon.addonuser_set.create(user=self.user, listed=False)
self.test_list_addon(expected_can_reply=True)
def test_list_can_not_reply_anonymous(self):
self.test_list_addon(expected_can_reply=False)
data = self.test_list_addon(show_permissions_for=self.user.pk)
assert data['can_reply'] is True
def test_list_can_not_reply(self):
self.user = user_factory()
self.client.login_api(self.user)
self.test_list_addon(expected_can_reply=False)
data = self.test_list_addon(show_permissions_for=self.user.pk)
assert data['can_reply'] is False
def test_list_can_reply_field_absent_in_v3(self):
self.user = user_factory()
self.client.login_api(self.user)
self.url = reverse_ns('rating-list', api_version='v3')
data = self.test_list_addon()
data = self.test_list_addon(show_permissions_for=self.user.pk)
assert 'can_reply' not in data
def test_list_addon_queries(self):

Просмотреть файл

@ -8,7 +8,8 @@ from django.utils.translation import ugettext
from rest_framework import serializers
from rest_framework.decorators import action
from rest_framework.exceptions import ParseError, PermissionDenied
from rest_framework.exceptions import (
NotAuthenticated, ParseError, PermissionDenied)
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.viewsets import ModelViewSet
@ -380,23 +381,40 @@ class RatingViewSet(AddonChildMixin, ModelViewSet):
return super(RatingViewSet, self).filter_queryset(qs)
def get_paginated_response(self, data):
response = super(RatingViewSet, self).get_paginated_response(data)
if 'show_grouped_ratings' in self.request.GET:
request = self.request
extra_data = {}
if 'show_grouped_ratings' in request.GET:
try:
show_grouped_ratings = (
serializers.BooleanField().to_internal_value(
self.request.GET['show_grouped_ratings']))
request.GET['show_grouped_ratings']))
except serializers.ValidationError:
raise ParseError(
'show_grouped_ratings parameter should be a boolean')
if show_grouped_ratings and self.get_addon_object():
response.data['grouped_ratings'] = dict(GroupedRating.get(
extra_data['grouped_ratings'] = dict(GroupedRating.get(
self.addon_object.id))
if 'addon' in self.request.GET and is_gate_active(
self.request, 'ratings-can_reply'):
response.data['can_reply'] = (
bool(self.request.user.is_authenticated) and
if ('show_permissions_for' in request.GET and
is_gate_active(self.request, 'ratings-can_reply')):
if 'addon' not in request.GET:
raise ParseError(
'show_permissions_for parameter is only valid if the '
'addon parameter is also present')
try:
show_permissions_for = (
serializers.IntegerField().to_internal_value(
request.GET['show_permissions_for']))
if show_permissions_for != request.user.pk:
raise serializers.ValidationError
except serializers.ValidationError:
raise ParseError(
'show_permissions_for parameter value should be equal to '
'the user id of the authenticated user')
extra_data['can_reply'] = (
self.check_can_reply_permission_for_ratings_list())
response = super(RatingViewSet, self).get_paginated_response(data)
if extra_data:
response.data.update(extra_data)
return response
def check_can_reply_permission_for_ratings_list(self):
@ -417,7 +435,7 @@ class RatingViewSet(AddonChildMixin, ModelViewSet):
viewset.check_permissions(self.request)
viewset.check_object_permissions(self.request, dummy_rating)
return True
except PermissionDenied:
except (PermissionDenied, NotAuthenticated):
return False
def get_queryset(self):