Commit a4226471 by Clinton Blackburn Committed by Clinton Blackburn

Corrected create permissions for ExperimentData create endpoint

parent e71f1afd
...@@ -10,5 +10,5 @@ class ExperimentDataFactory(factory.DjangoModelFactory): ...@@ -10,5 +10,5 @@ class ExperimentDataFactory(factory.DjangoModelFactory):
user = factory.SubFactory(UserFactory) user = factory.SubFactory(UserFactory)
experiment_id = factory.fuzzy.FuzzyInteger(0) experiment_id = factory.fuzzy.FuzzyInteger(0)
key = factory.Faker('word') key = factory.Sequence(lambda n: n)
value = factory.Faker('word') value = factory.Faker('word')
...@@ -8,5 +8,12 @@ class IsStaffOrOwner(permissions.IsStaffOrOwner): ...@@ -8,5 +8,12 @@ class IsStaffOrOwner(permissions.IsStaffOrOwner):
""" """
def has_permission(self, request, view): def has_permission(self, request, view):
# Staff users can create data for anyone.
# Non-staff users can only create data for themselves.
if view.action == 'create':
username = request.user.username
return super(IsStaffOrOwner, self).has_permission(request, view) or (
username == request.data.get('user', username))
# The view will handle filtering for the current user # The view will handle filtering for the current user
return True return True
from django.contrib.auth import get_user_model
from rest_framework import serializers from rest_framework import serializers
from .models import ExperimentData from .models import ExperimentData
User = get_user_model() # pylint:disable=invalid-name
class ExperimentDataSerializer(serializers.ModelSerializer):
user = serializers.SlugRelatedField(read_only=True, slug_field='username', default=serializers.CurrentUserDefault()) class ExperimentDataCreateSerializer(serializers.ModelSerializer):
user = serializers.SlugRelatedField(slug_field='username', default=serializers.CurrentUserDefault(), required=False,
queryset=User.objects.all())
class Meta(object): class Meta(object):
model = ExperimentData model = ExperimentData
fields = ('id', 'experiment_id', 'user', 'key', 'value', 'created', 'modified',) fields = ('id', 'experiment_id', 'user', 'key', 'value', 'created', 'modified',)
class ExperimentDataSerializer(serializers.ModelSerializer):
user = serializers.SlugRelatedField(read_only=True, slug_field='username', default=serializers.CurrentUserDefault())
class Meta(ExperimentDataCreateSerializer.Meta):
read_only_fields = ('user',) read_only_fields = ('user',)
...@@ -96,8 +96,32 @@ class ExperimentDataViewSetTests(APITestCase): ...@@ -96,8 +96,32 @@ class ExperimentDataViewSetTests(APITestCase):
response = self.client.post(url, {}) response = self.client.post(url, {})
self.assertEqual(response.status_code, 401) self.assertEqual(response.status_code, 401)
self.assert_data_created_for_user(UserFactory()) user = UserFactory()
self.assert_data_created_for_user(UserFactory()) data = {
'experiment_id': 1,
'key': 'foo',
'value': 'bar',
}
self.client.login(username=user.username, password=UserFactory._DEFAULT_PASSWORD)
# Users can create data for themselves
response = self.client.post(url, data)
self.assertEqual(response.status_code, 201)
ExperimentData.objects.get(user=user)
# A non-staff user cannot create data for another user
other_user = UserFactory()
data['user'] = other_user.username
response = self.client.post(url, data)
self.assertEqual(response.status_code, 403)
self.assertFalse(ExperimentData.objects.filter(user=other_user).exists())
# A staff user can create data for other users
user.is_staff = True
user.save()
response = self.client.post(url, data)
self.assertEqual(response.status_code, 201)
ExperimentData.objects.get(user=other_user)
def test_put_as_create(self): def test_put_as_create(self):
""" Users should be able to use PUT to create new data. """ """ Users should be able to use PUT to create new data. """
......
...@@ -5,7 +5,7 @@ from rest_framework.filters import DjangoFilterBackend ...@@ -5,7 +5,7 @@ from rest_framework.filters import DjangoFilterBackend
from experiments import filters from experiments import filters
from experiments.models import ExperimentData from experiments.models import ExperimentData
from experiments.permissions import IsStaffOrOwner from experiments.permissions import IsStaffOrOwner
from experiments.serializers import ExperimentDataSerializer from experiments.serializers import ExperimentDataCreateSerializer, ExperimentDataSerializer
from openedx.core.lib.api.authentication import SessionAuthenticationAllowInactiveUser from openedx.core.lib.api.authentication import SessionAuthenticationAllowInactiveUser
...@@ -21,6 +21,11 @@ class ExperimentDataViewSet(viewsets.ModelViewSet): ...@@ -21,6 +21,11 @@ class ExperimentDataViewSet(viewsets.ModelViewSet):
queryset = queryset.filter(user=self.request.user) queryset = queryset.filter(user=self.request.user)
return super(ExperimentDataViewSet, self).filter_queryset(queryset) return super(ExperimentDataViewSet, self).filter_queryset(queryset)
def get_serializer_class(self):
if self.action == 'create':
return ExperimentDataCreateSerializer
return ExperimentDataSerializer
def create_or_update(self, request, *args, **kwargs): def create_or_update(self, request, *args, **kwargs):
# If we have a primary key, treat this as a regular update request # If we have a primary key, treat this as a regular update request
if self.kwargs.get('pk'): if self.kwargs.get('pk'):
...@@ -40,4 +45,5 @@ class ExperimentDataViewSet(viewsets.ModelViewSet): ...@@ -40,4 +45,5 @@ class ExperimentDataViewSet(viewsets.ModelViewSet):
except ExperimentData.DoesNotExist: except ExperimentData.DoesNotExist:
pass pass
self.action = 'create'
return self.create(request, *args, **kwargs) return self.create(request, *args, **kwargs)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment