This exports person objects via the REST API. Security Constraints: * The API is read-only to authenticated users
Signed-off-by: Andy Doan <[email protected]> --- patchwork/rest_serializers.py | 19 ++++++++++++++- patchwork/tests/test_rest_api.py | 50 +++++++++++++++++++++++++++++++++++----- patchwork/views/rest_api.py | 12 +++++++++- 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/patchwork/rest_serializers.py b/patchwork/rest_serializers.py index 0d6c041..103280a 100644 --- a/patchwork/rest_serializers.py +++ b/patchwork/rest_serializers.py @@ -19,9 +19,26 @@ from django.contrib.auth.models import User +from rest_framework.relations import HyperlinkedRelatedField from rest_framework.serializers import HyperlinkedModelSerializer -from patchwork.models import Project +from patchwork.models import Person, Project + + +class URLSerializer(HyperlinkedModelSerializer): + """Just like parent but puts _url for fields""" + + def to_representation(self, instance): + data = super(URLSerializer, self).to_representation(instance) + for name, field in self.fields.items(): + if isinstance(field, HyperlinkedRelatedField) and name != 'url': + data[name + '_url'] = data.pop(name) + return data + + +class PersonSerializer(URLSerializer): + class Meta: + model = Person class UserSerializer(HyperlinkedModelSerializer): diff --git a/patchwork/tests/test_rest_api.py b/patchwork/tests/test_rest_api.py index 70743d6..3acf70c 100644 --- a/patchwork/tests/test_rest_api.py +++ b/patchwork/tests/test_rest_api.py @@ -121,14 +121,14 @@ class TestProjectAPI(APITestCase): @unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API') -class TestUserAPI(APITestCase): +class TestPersonAPI(APITestCase): fixtures = ['default_states'] @staticmethod def api_url(item=None): if item is None: - return reverse('api_1.0:user-list') - return reverse('api_1.0:user-detail', args=[item]) + return reverse('api_1.0:person-list') + return reverse('api_1.0:person-detail', args=[item]) def test_anonymous_list(self): """The API should reject anonymous users.""" @@ -142,9 +142,20 @@ class TestUserAPI(APITestCase): resp = self.client.get(self.api_url()) self.assertEqual(status.HTTP_200_OK, resp.status_code) self.assertEqual(1, len(resp.data)) - self.assertEqual(user.username, resp.data[0]['username']) - self.assertNotIn('password', resp.data[0]) - self.assertNotIn('is_superuser', resp.data[0]) + self.assertEqual(user.username, resp.data[0]['name']) + self.assertIn('users/%d/' % user.id, resp.data[0]['user_url']) + self.assertEqual(user.email, resp.data[0]['email']) + + def test_unlinked_user(self): + defaults.patch_author_person.save() + user = create_user() + self.client.force_authenticate(user=user) + resp = self.client.get(self.api_url()) + self.assertEqual(status.HTTP_200_OK, resp.status_code) + self.assertEqual(2, len(resp.data)) + self.assertEqual( + defaults.patch_author_person.name, resp.data[0]['name']) + self.assertEqual(None, resp.data[0]['user_url']) def test_readonly(self): defaults.project.save() @@ -161,3 +172,30 @@ class TestUserAPI(APITestCase): resp = self.client.post(self.api_url(), {'email': '[email protected]'}) self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code) + + [email protected](settings.ENABLE_REST_API, 'requires ENABLE_REST_API') +class TestUserAPI(APITestCase): + fixtures = ['default_states'] + + @staticmethod + def api_url(item=None): + if item is None: + return reverse('api_1.0:user-list') + return reverse('api_1.0:user-detail', args=[item]) + + def test_anonymous_list(self): + """The API should reject anonymous users.""" + resp = self.client.get(self.api_url()) + self.assertEqual(status.HTTP_403_FORBIDDEN, resp.status_code) + + def test_authenticated_list(self): + """This API requires authenticated users.""" + user = create_user() + self.client.force_authenticate(user=user) + resp = self.client.get(self.api_url()) + self.assertEqual(status.HTTP_200_OK, resp.status_code) + self.assertEqual(1, len(resp.data)) + self.assertEqual(user.username, resp.data[0]['username']) + self.assertNotIn('password', resp.data[0]) + self.assertNotIn('is_superuser', resp.data[0]) diff --git a/patchwork/views/rest_api.py b/patchwork/views/rest_api.py index 8cff44e..6e7f94e 100644 --- a/patchwork/views/rest_api.py +++ b/patchwork/views/rest_api.py @@ -20,7 +20,7 @@ from django.conf import settings from patchwork.rest_serializers import ( - ProjectSerializer, UserSerializer) + PersonSerializer, ProjectSerializer, UserSerializer) from rest_framework import permissions from rest_framework.pagination import PageNumberPagination @@ -85,11 +85,21 @@ class UserViewSet(PatchworkViewSet): serializer_class = UserSerializer +class PeopleViewSet(PatchworkViewSet): + permission_classes = (AuthenticatedReadOnly, ) + serializer_class = PersonSerializer + + def get_queryset(self): + qs = super(PeopleViewSet, self).get_queryset() + return qs.select_related('user__username') + + class ProjectViewSet(PatchworkViewSet): permission_classes = (PatchworkPermission, ) serializer_class = ProjectSerializer router = DefaultRouter() +router.register('people', PeopleViewSet, 'person') router.register('projects', ProjectViewSet, 'project') router.register('users', UserViewSet, 'user') -- 2.7.4 _______________________________________________ Patchwork mailing list [email protected] https://lists.ozlabs.org/listinfo/patchwork
