Skip to content

Commit 95433fa

Browse files
committed
Make project serializer return subset of fields to authenticated users
Admin users will get an extended list of fields, for use in the build instances. Normal users get a different project serializer with limited fields.
1 parent 1b2c965 commit 95433fa

File tree

3 files changed

+36
-6
lines changed

3 files changed

+36
-6
lines changed

readthedocs/restapi/serializers.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,16 @@ class Meta(object):
2424
'users',
2525
'canonical_url',
2626
)
27-
# Fields needed for properly passing data to the builds
28-
build_extra = (
27+
28+
29+
class ProjectSerializerFull(ProjectSerializer):
30+
31+
"""Serializer to return all Project fields, for use by builder instances"""
32+
33+
class Meta(object):
34+
model = Project
35+
# The following fields are required by builder processes
36+
fields = ProjectSerializer.Meta.fields + (
2937
'enable_epub_build',
3038
'enable_pdf_build',
3139
'conf_py_file',
@@ -41,7 +49,6 @@ class Meta(object):
4149
'requirements_file',
4250
'python_interpreter',
4351
)
44-
fields += build_extra
4552

4653

4754
class VersionSerializer(serializers.ModelSerializer):

readthedocs/restapi/views/model_views.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
RelatedProjectIsOwner, IsOwner)
2424
from ..serializers import (BuildSerializerFull, BuildSerializer,
2525
BuildCommandSerializer, ProjectSerializer,
26-
VersionSerializer, DomainSerializer,
27-
RemoteOrganizationSerializer,
26+
ProjectSerializerFull, VersionSerializer,
27+
DomainSerializer, RemoteOrganizationSerializer,
2828
RemoteRepositorySerializer)
2929
from .. import utils as api_utils
3030

@@ -46,6 +46,11 @@ class ProjectViewSet(viewsets.ModelViewSet):
4646
def get_queryset(self):
4747
return self.model.objects.api(self.request.user)
4848

49+
def get_serializer_class(self):
50+
if self.request.user.is_staff:
51+
return ProjectSerializerFull
52+
return self.serializer_class
53+
4954
@decorators.detail_route()
5055
def valid_versions(self, request, **kwargs):
5156
"""Maintain state of versions that are wanted."""

readthedocs/rtd_tests/tests/test_api.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
from __future__ import absolute_import
2-
from builtins import str
2+
33
import json
44
import base64
55
import datetime
66

77
import mock
8+
from builtins import str
89
from django.test import TestCase
910
from django.contrib.auth.models import User
1011
from django_dynamic_fixture import get
@@ -168,6 +169,23 @@ def test_make_project(self):
168169
obj = json.loads(resp.content)
169170
self.assertEqual(obj['slug'], 'awesome-project')
170171

172+
def test_user_doesnt_get_full_api_return(self):
173+
user_normal = get(User, is_staff=False)
174+
user_admin = get(User, is_staff=True)
175+
project = get(Project, main_language_project=None, conf_py_file='foo')
176+
client = APIClient()
177+
178+
client.force_authenticate(user=user_normal)
179+
resp = client.get('/api/v2/project/%s/' % (project.pk))
180+
self.assertEqual(resp.status_code, 200)
181+
self.assertNotIn('conf_py_file', resp.data)
182+
183+
client.force_authenticate(user=user_admin)
184+
resp = client.get('/api/v2/project/%s/' % (project.pk))
185+
self.assertEqual(resp.status_code, 200)
186+
self.assertIn('conf_py_file', resp.data)
187+
self.assertEqual(resp.data['conf_py_file'], 'foo')
188+
171189
def test_invalid_make_project(self):
172190
"""
173191
Test that the authentication is turned on.

0 commit comments

Comments
 (0)