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):
user = factory.SubFactory(UserFactory)
experiment_id = factory.fuzzy.FuzzyInteger(0)
key = factory.Faker('word')
key = factory.Sequence(lambda n: n)
value = factory.Faker('word')
......@@ -8,5 +8,12 @@ class IsStaffOrOwner(permissions.IsStaffOrOwner):
"""
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
return True
from django.contrib.auth import get_user_model
from rest_framework import serializers
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):
model = ExperimentData
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',)
......@@ -96,8 +96,32 @@ class ExperimentDataViewSetTests(APITestCase):
response = self.client.post(url, {})
self.assertEqual(response.status_code, 401)
self.assert_data_created_for_user(UserFactory())
self.assert_data_created_for_user(UserFactory())
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):
""" Users should be able to use PUT to create new data. """
......
......@@ -5,7 +5,7 @@ from rest_framework.filters import DjangoFilterBackend
from experiments import filters
from experiments.models import ExperimentData
from experiments.permissions import IsStaffOrOwner
from experiments.serializers import ExperimentDataSerializer
from experiments.serializers import ExperimentDataCreateSerializer, ExperimentDataSerializer
from openedx.core.lib.api.authentication import SessionAuthenticationAllowInactiveUser
......@@ -21,6 +21,11 @@ class ExperimentDataViewSet(viewsets.ModelViewSet):
queryset = queryset.filter(user=self.request.user)
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):
# If we have a primary key, treat this as a regular update request
if self.kwargs.get('pk'):
......@@ -40,4 +45,5 @@ class ExperimentDataViewSet(viewsets.ModelViewSet):
except ExperimentData.DoesNotExist:
pass
self.action = 'create'
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