Updated REST API for group create, update and delete.
This commit is contained in:
parent
7f8ad4bfcc
commit
fd34055611
@ -4,7 +4,7 @@ from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
|
||||
from openslides.utils.rest_api import ModelSerializer, PrimaryKeyRelatedField, RelatedField, ValidationError
|
||||
|
||||
from .models import Group, User
|
||||
from .models import Group, Permission, User
|
||||
|
||||
|
||||
class UserShortSerializer(ModelSerializer):
|
||||
@ -122,18 +122,40 @@ class PermissionRelatedField(RelatedField):
|
||||
"""
|
||||
A custom field to use for the permission relationship.
|
||||
"""
|
||||
default_error_messages = {
|
||||
'incorrect_value': ugettext_lazy('Incorrect value "{value}". Expected app_label.codename string.'),
|
||||
'does_not_exist': ugettext_lazy('Invalid permission "{value}". Object does not exist.')}
|
||||
|
||||
def to_representation(self, value):
|
||||
"""
|
||||
Returns the permission name (app_label.codename).
|
||||
Returns the permission code string (app_label.codename).
|
||||
"""
|
||||
return '.'.join((value.content_type.app_label, value.codename,))
|
||||
|
||||
def to_internal_value(self, data):
|
||||
"""
|
||||
Returns the permission object represented by data. The argument data is
|
||||
what is sent by the client. This method expects permission code strings
|
||||
(app_label.codename) like to_representation() returns.
|
||||
"""
|
||||
try:
|
||||
app_label, codename = data.split('.')
|
||||
except ValueError:
|
||||
self.fail('incorrect_value', value=data)
|
||||
try:
|
||||
permission = Permission.objects.get(content_type__app_label=app_label, codename=codename)
|
||||
except Permission.DoesNotExist:
|
||||
self.fail('does_not_exist', value=data)
|
||||
return permission
|
||||
|
||||
|
||||
class GroupSerializer(ModelSerializer):
|
||||
"""
|
||||
Serializer for django.contrib.auth.models.Group objects.
|
||||
"""
|
||||
permissions = PermissionRelatedField(many=True, read_only=True)
|
||||
permissions = PermissionRelatedField(
|
||||
many=True,
|
||||
queryset=Permission.objects.all())
|
||||
|
||||
class Meta:
|
||||
model = Group
|
||||
|
@ -4,8 +4,9 @@ from django.contrib.auth import logout as auth_logout
|
||||
from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import activate, ugettext_lazy
|
||||
from rest_framework import status
|
||||
|
||||
from openslides.utils.rest_api import ModelViewSet
|
||||
from openslides.utils.rest_api import ModelViewSet, Response
|
||||
from openslides.utils.views import (
|
||||
CSVImportView,
|
||||
FormView,
|
||||
@ -121,6 +122,19 @@ class GroupViewSet(ModelViewSet):
|
||||
request.user.has_perm('users.can_see_extra_data')))):
|
||||
self.permission_denied(request)
|
||||
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
"""
|
||||
Protects builtin groups 'Anonymous' (pk=1) and 'Registered' (pk=2)
|
||||
from being deleted.
|
||||
"""
|
||||
instance = self.get_object()
|
||||
if instance.pk in (1, 2,):
|
||||
self.permission_denied(request)
|
||||
else:
|
||||
self.perform_destroy(instance)
|
||||
response = Response(status=status.HTTP_204_NO_CONTENT)
|
||||
return response
|
||||
|
||||
|
||||
class UserSettingsView(LoginMixin, UpdateView):
|
||||
required_permission = None
|
||||
|
@ -2,11 +2,11 @@ from django.core.urlresolvers import reverse
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
from openslides.users.models import User
|
||||
from openslides.users.models import Group, User
|
||||
from openslides.utils.test import TestCase
|
||||
|
||||
|
||||
class UserCreation(TestCase):
|
||||
class UserCreate(TestCase):
|
||||
"""
|
||||
Tests creation of users via REST API.
|
||||
"""
|
||||
@ -22,26 +22,31 @@ class UserCreation(TestCase):
|
||||
|
||||
def test_creation_with_group(self):
|
||||
self.client.login(username='admin', password='admin')
|
||||
# These are the builtin groups 'Delegates' and 'Staff'. The pks are valid.
|
||||
group_pks = (3, 4,)
|
||||
|
||||
self.client.post(
|
||||
reverse('user-list'),
|
||||
{'last_name': 'Test name aedah1iequoof0Ashed4',
|
||||
'groups': ['3', '4']})
|
||||
'groups': group_pks})
|
||||
|
||||
user = User.objects.get(username='Test name aedah1iequoof0Ashed4')
|
||||
self.assertTrue(user.groups.filter(pk=3).exists())
|
||||
self.assertTrue(user.groups.filter(pk=4).exists())
|
||||
self.assertTrue(user.groups.filter(pk=group_pks[0]).exists())
|
||||
self.assertTrue(user.groups.filter(pk=group_pks[1]).exists())
|
||||
|
||||
def test_creation_with_anonymous_or_registered_group(self):
|
||||
self.client.login(username='admin', password='admin')
|
||||
# These are the builtin groups 'Anonymous' and 'Registered'.
|
||||
# The pks are valid. But these groups can not be added to users.
|
||||
group_pks = (1, 2,)
|
||||
|
||||
response = self.client.post(
|
||||
reverse('user-list'),
|
||||
{'last_name': 'Test name aedah1iequoof0Ashed4',
|
||||
'groups': ['1', '2']})
|
||||
'groups': group_pks})
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertEqual(response.data, {'groups': ["Invalid pk '1' - object does not exist."]})
|
||||
self.assertEqual(response.data, {'groups': ["Invalid pk '%d' - object does not exist." % group_pks[0]]})
|
||||
|
||||
|
||||
class UserUpdate(TestCase):
|
||||
@ -51,22 +56,26 @@ class UserUpdate(TestCase):
|
||||
def test_simple_update_via_patch(self):
|
||||
admin_client = APIClient()
|
||||
admin_client.login(username='admin', password='admin')
|
||||
# This is the builtin user 'Administrator' with username 'admin'. The pk is valid.
|
||||
user_pk = 1
|
||||
|
||||
response = admin_client.patch(
|
||||
reverse('user-detail', args=['1']),
|
||||
reverse('user-detail', args=[user_pk]),
|
||||
{'last_name': 'New name tu3ooh5Iez5Aec2laefo'})
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
user = User.objects.get(pk=1)
|
||||
user = User.objects.get(pk=user_pk)
|
||||
self.assertEqual(user.last_name, 'New name tu3ooh5Iez5Aec2laefo')
|
||||
self.assertEqual(user.username, 'admin')
|
||||
|
||||
def test_simple_update_via_put(self):
|
||||
admin_client = APIClient()
|
||||
admin_client.login(username='admin', password='admin')
|
||||
# This is the builtin user 'Administrator'. The pk is valid.
|
||||
user_pk = 1
|
||||
|
||||
response = admin_client.put(
|
||||
reverse('user-detail', args=['1']),
|
||||
reverse('user-detail', args=[user_pk]),
|
||||
{'last_name': 'New name Ohy4eeyei5Sahzah0Os2'})
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
@ -81,9 +90,120 @@ class UserDelete(TestCase):
|
||||
admin_client = APIClient()
|
||||
admin_client.login(username='admin', password='admin')
|
||||
User.objects.create(username='Test name bo3zieT3iefahng0ahqu')
|
||||
self.assertTrue(User.objects.filter(username='Test name bo3zieT3iefahng0ahqu').exists())
|
||||
|
||||
response = admin_client.delete(reverse('user-detail', args=['2']))
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||
self.assertFalse(User.objects.filter(username='Test name bo3zieT3iefahng0ahqu').exists())
|
||||
|
||||
|
||||
class GroupCreate(TestCase):
|
||||
"""
|
||||
Tests creation of groups via REST API.
|
||||
"""
|
||||
def test_creation(self):
|
||||
self.client.login(username='admin', password='admin')
|
||||
# This contains two valid permissions of the users app.
|
||||
permissions = ('users.can_see_name', 'users.can_see_extra_data')
|
||||
|
||||
response = self.client.post(
|
||||
reverse('group-list'),
|
||||
{'name': 'Test name la8eephu9vaecheiKeif',
|
||||
'permissions': permissions})
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
group = Group.objects.get(name='Test name la8eephu9vaecheiKeif')
|
||||
for permission in permissions:
|
||||
app_label, codename = permission.split('.')
|
||||
self.assertTrue(group.permissions.get(content_type__app_label=app_label, codename=codename))
|
||||
|
||||
def test_failed_creation_invalid_value(self):
|
||||
self.client.login(username='admin', password='admin')
|
||||
permissions = ('invalid_permission',)
|
||||
|
||||
response = self.client.post(
|
||||
reverse('group-list'),
|
||||
{'name': 'Test name ool5aeb6Rai2aiLaith1',
|
||||
'permissions': permissions})
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertEqual(
|
||||
response.data,
|
||||
{'permissions': ['Incorrect value "invalid_permission". Expected app_label.codename string.']})
|
||||
|
||||
def test_failed_creation_invalid_permission(self):
|
||||
self.client.login(username='admin', password='admin')
|
||||
permissions = ('invalid_app.invalid_permission',)
|
||||
|
||||
response = self.client.post(
|
||||
reverse('group-list'),
|
||||
{'name': 'Test name wei2go2aiV3eophi9Ohg',
|
||||
'permissions': permissions})
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertEqual(
|
||||
response.data,
|
||||
{'permissions': ['Invalid permission "invalid_app.invalid_permission". Object does not exist.']})
|
||||
|
||||
|
||||
class GroupUpdate(TestCase):
|
||||
"""
|
||||
Tests update of groups via REST API.
|
||||
"""
|
||||
def test_simple_update_via_patch(self):
|
||||
admin_client = APIClient()
|
||||
admin_client.login(username='admin', password='admin')
|
||||
# This is the builtin group 'Delegates'. The pk is valid.
|
||||
group_pk = 3
|
||||
# This contains one valid permission of the users app.
|
||||
permissions = ('users.can_see_name',)
|
||||
|
||||
response = admin_client.patch(
|
||||
reverse('group-detail', args=[group_pk]),
|
||||
{'permissions': permissions})
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
group = Group.objects.get(pk=group_pk)
|
||||
for permission in permissions:
|
||||
app_label, codename = permission.split('.')
|
||||
self.assertTrue(group.permissions.get(content_type__app_label=app_label, codename=codename))
|
||||
|
||||
def test_simple_update_via_put(self):
|
||||
admin_client = APIClient()
|
||||
admin_client.login(username='admin', password='admin')
|
||||
# This is the builtin group 'Delegates'. The pk is valid.
|
||||
group_pk = 3
|
||||
# This contains one valid permission of the users app.
|
||||
permissions = ('users.can_see_name',)
|
||||
|
||||
response = admin_client.put(
|
||||
reverse('group-detail', args=[group_pk]),
|
||||
{'permissions': permissions})
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertEqual(response.data, {'name': ['This field is required.']})
|
||||
|
||||
|
||||
class GroupDelete(TestCase):
|
||||
"""
|
||||
Tests delete of groups via REST API.
|
||||
"""
|
||||
def test_delete(self):
|
||||
admin_client = APIClient()
|
||||
admin_client.login(username='admin', password='admin')
|
||||
group = Group.objects.create(name='Test name Koh4lohlaewoog9Ahsh5')
|
||||
|
||||
response = admin_client.delete(reverse('group-detail', args=[group.pk]))
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||
self.assertFalse(Group.objects.filter(name='Test name Koh4lohlaewoog9Ahsh5').exists())
|
||||
|
||||
def test_delete_builtin_groups(self):
|
||||
admin_client = APIClient()
|
||||
admin_client.login(username='admin', password='admin')
|
||||
# The pks of builtin groups 'Anonymous' and 'Registered'
|
||||
group_pks = (1, 2,)
|
||||
|
||||
for group_pk in group_pks:
|
||||
response = admin_client.delete(reverse('group-detail', args=[group_pk]))
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
Loading…
Reference in New Issue
Block a user