Added possibility to update your own user object. Hide default password for non admins.

This commit is contained in:
Norman Jäckel 2015-09-06 10:29:23 +02:00
parent 973d3fa653
commit c8bf754646
4 changed files with 98 additions and 5 deletions

View File

@ -104,7 +104,7 @@ class MotionViewSet(ModelViewSet):
# Check permission to send submitter and supporter data. # Check permission to send submitter and supporter data.
if (not request.user.has_perm('motions.can_manage') and if (not request.user.has_perm('motions.can_manage') and
(request.data.getlist('submitters') or request.data.getlist('supporters'))): (request.data.get('submitters_id') or request.data.get('supporters_id'))):
# Non-staff users are not allowed to send submitter or supporter data. # Non-staff users are not allowed to send submitter or supporter data.
self.permission_denied(request) self.permission_denied(request)

View File

@ -16,7 +16,7 @@ class UserShortSerializer(ModelSerializer):
""" """
Serializer for users.models.User objects. Serializer for users.models.User objects.
Serializes only name fields. Serializes only name fields and about me field.
""" """
class Meta: class Meta:
model = User model = User
@ -27,6 +27,7 @@ class UserShortSerializer(ModelSerializer):
'first_name', 'first_name',
'last_name', 'last_name',
'structure_level', 'structure_level',
'about_me',
'groups',) 'groups',)

View File

@ -33,9 +33,9 @@ class UserViewSet(ModelViewSet):
""" """
Returns True if the user has required permissions. Returns True if the user has required permissions.
""" """
if self.action in ('metadata', 'list', 'retrieve'): if self.action in ('metadata', 'list', 'retrieve', 'partial_update'):
result = self.request.user.has_perm('users.can_see_name') result = self.request.user.has_perm('users.can_see_name')
elif self.action in ('create', 'partial_update', 'update', 'destroy', 'reset_password'): elif self.action in ('create', 'update', 'destroy', 'reset_password'):
result = (self.request.user.has_perm('users.can_see_name') and result = (self.request.user.has_perm('users.can_see_name') and
self.request.user.has_perm('users.can_see_extra_data') and self.request.user.has_perm('users.can_see_extra_data') and
self.request.user.has_perm('users.can_manage')) self.request.user.has_perm('users.can_manage'))
@ -57,6 +57,79 @@ class UserViewSet(ModelViewSet):
serializer_class = UserShortSerializer serializer_class = UserShortSerializer
return serializer_class return serializer_class
def list(self, request, *args, **kwargs):
"""
Customized view endpoint to list all user.
Does only the default_password check.
"""
response = super().list(request, *args, **kwargs)
self.extract_default_password(response)
return response
def retrieve(self, request, *args, **kwargs):
"""
Customized view endpoint to retrieve a user.
Does only the default_password check.
"""
response = super().retrieve(request, *args, **kwargs)
self.extract_default_password(response)
return response
def extract_default_password(self, response):
"""
Checks if a user is not a manager. If yes, the default password is
extracted from the response.
"""
if not self.request.user.has_perm('users.can_manage'):
if isinstance(response.data, dict):
del response.data['default_password']
elif isinstance(response.data, list):
for user in response.data:
del user['default_password']
def update(self, request, *args, **kwargs):
"""
Customized view endpoint to update an user.
Checks also whether the requesting user can update the user. He
needs at least the permissions 'users.can_see_name' (see
self.check_view_permissions()). Also it is evaluated whether he
wants to update himself or is manager.
"""
# Check manager perms
if (request.user.has_perm('users.can_see_extra_data') and
request.user.has_perm('users.can_manage')):
response = super().update(request, *args, **kwargs)
else:
# Get user.
user = self.get_object()
# Check permissions only to update yourself.
if request.user != user:
self.permission_denied(request)
# Check permission to send only some data.
whitelist = (
'username',
'title',
'first_name',
'last_name',
'structure_level'
'about_me',)
for data in request.data.keys():
if data not in whitelist:
# Non-staff users are allowed to send only some data.
self.permission_denied(request)
# Validate data and update user.
serializer = self.get_serializer(
user,
data=request.data,
partial=kwargs.get('partial', False))
serializer.is_valid(raise_exception=True)
serializer.save()
response = Response(serializer.data)
return response
@detail_route(methods=['post']) @detail_route(methods=['post'])
def reset_password(self, request, pk=None): def reset_password(self, request, pk=None):
""" """

View File

@ -1,3 +1,5 @@
import json
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from rest_framework import status from rest_framework import status
@ -154,12 +156,29 @@ class UpdateMotion(TestCase):
password='test_password_XaeTe3aesh8ohg6Cohwo') password='test_password_XaeTe3aesh8ohg6Cohwo')
response = self.client.patch( response = self.client.patch(
reverse('motion-detail', args=[self.motion.pk]), reverse('motion-detail', args=[self.motion.pk]),
{'supporters_id': [supporter.pk]}) json.dumps({'supporters_id': [supporter.pk]}),
content_type='application/json')
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
motion = Motion.objects.get() motion = Motion.objects.get()
self.assertEqual(motion.title, 'test_title_aeng7ahChie3waiR8xoh') self.assertEqual(motion.title, 'test_title_aeng7ahChie3waiR8xoh')
self.assertEqual(motion.supporters.get().username, 'test_username_ieB9eicah0uqu6Phoovo') self.assertEqual(motion.supporters.get().username, 'test_username_ieB9eicah0uqu6Phoovo')
def test_patch_supporters_non_manager(self):
non_admin = get_user_model().objects.create_user(
username='test_username_uqu6PhoovieB9eicah0o',
password='test_password_Xaesh8ohg6CoheTe3awo')
self.client.login(
username='test_username_uqu6PhoovieB9eicah0o',
password='test_password_Xaesh8ohg6CoheTe3awo')
motion = Motion.objects.get()
motion.submitters.add(non_admin)
motion.supporters.clear()
response = self.client.patch(
reverse('motion-detail', args=[self.motion.pk]),
json.dumps({'supporters_id': [1]}),
content_type='application/json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
def test_removal_of_supporters(self): def test_removal_of_supporters(self):
admin = get_user_model().objects.get(username='admin') admin = get_user_model().objects.get(username='admin')
group_staff = admin.groups.get(name='Staff') group_staff = admin.groups.get(name='Staff')