Fixes autoupdate bug for a user without user.can_see_name permission.

This commit is contained in:
Norman Jäckel 2017-04-28 22:10:18 +02:00 committed by Emanuel Schütze
parent 074559ba23
commit ea50971ae6
10 changed files with 58 additions and 13 deletions

View File

@ -46,7 +46,8 @@ Core:
- Fixing error when clearing empty chat [#3199].
- Added notify system [#3212].
- Enhanced performance esp. for server restart and first connection of all
clients by refactorting autoupdate, Collection and AccessPermission [#3223].
clients by refactoring autoupdate, Collection and AccessPermission [#3223].
- Fixes autoupdate bug for a user without user.can_see_name permission [#3233].
Mediafiles:
- Fixed reloading of PDF on page change [#3274]

View File

@ -103,6 +103,10 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
raise ValidationError({'detail': str(e)})
message = _('User %s was successfully added to the list of speakers.') % user
# Send new speaker via autoupdate because users without permission
# to see users may not have it but can get it now.
inform_changed_data([user])
else:
# request.method == 'DELETE'
speaker_ids = request.data.get('speaker')

View File

@ -79,6 +79,9 @@ class AssignmentViewSet(ModelViewSet):
self.permission_denied(request)
# If the request.user is already a candidate he can nominate himself nevertheless.
assignment.set_candidate(request.user)
# Send new candidate via autoupdate because users without permission
# to see users may not have it but can get it now.
inform_changed_data([request.user])
return _('You were nominated successfully.')
def withdraw_self(self, request, assignment):
@ -140,6 +143,9 @@ class AssignmentViewSet(ModelViewSet):
if assignment.is_candidate(user):
raise ValidationError({'detail': _('User %s is already nominated.') % user})
assignment.set_candidate(user)
# Send new candidate via autoupdate because users without permission
# to see users may not have it but can get it now.
inform_changed_data(user)
return _('User %s was nominated successfully.') % user
def delete_other(self, request, user, assignment):

View File

@ -723,6 +723,9 @@ class ChatMessageViewSet(ModelViewSet):
method so that the request.user can be saved into the model field.
"""
serializer.save(user=self.request.user)
# Send chatter via autoupdate because users without permission
# to see users may not have it but can get it now.
inform_changed_data([self.request.user])
@list_route(methods=['post'])
def clear(self, request):

View File

@ -2,6 +2,7 @@ from django.conf import settings
from django.db import models
from django.utils.translation import ugettext as _
from ..utils.autoupdate import inform_changed_data
from ..utils.models import RESTModelMixin
from .access_permissions import MediafileAccessPermissions
@ -52,6 +53,16 @@ class Mediafile(RESTModelMixin, models.Model):
"""
return self.title
def save(self, *args, **kwargs):
"""
Saves mediafile (mainly on create and update requests).
"""
result = super().save(*args, **kwargs)
# Send uploader via autoupdate because users without permission
# to see users may not have it but can get it now.
inform_changed_data(self.uploader)
return result
def get_filesize(self):
"""
Transforms bytes to kilobytes or megabytes. Returns the size as string.

View File

@ -1,8 +1,8 @@
from django.db import transaction
from django.utils.translation import ugettext as _
from openslides.poll.serializers import default_votes_validator
from openslides.utils.rest_api import (
from ..poll.serializers import default_votes_validator
from ..utils.rest_api import (
CharField,
DictField,
Field,
@ -12,8 +12,7 @@ from openslides.utils.rest_api import (
SerializerMethodField,
ValidationError,
)
from openslides.utils.validate import validate_html
from ..utils.validate import validate_html
from .models import (
Category,
Motion,

View File

@ -137,6 +137,13 @@ class MotionViewSet(ModelViewSet):
# Write the log message and initiate response.
motion.write_log([ugettext_noop('Motion created')], request.user)
# Send new submitters and supporters via autoupdate because users
# without permission to see users may not have them but can get it now.
new_users = list(motion.submitters.all())
new_users.extend(motion.supporters.all())
inform_changed_data(new_users)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
@ -198,6 +205,13 @@ class MotionViewSet(ModelViewSet):
not has_perm(request.user, 'motions.can_manage')):
updated_motion.supporters.clear()
updated_motion.write_log([ugettext_noop('All supporters removed')], request.user)
# Send new submitters and supporters via autoupdate because users
# without permission to see users may not have them but can get it now.
new_users = list(updated_motion.submitters.all())
new_users.extend(updated_motion.supporters.all())
inform_changed_data(new_users)
return Response(serializer.data)
@detail_route(methods=['put', 'delete'])
@ -265,6 +279,9 @@ class MotionViewSet(ModelViewSet):
raise ValidationError({'detail': _('You can not support this motion.')})
motion.supporters.add(request.user)
motion.write_log([ugettext_noop('Motion supported')], request.user)
# Send new supporter via autoupdate because users without permission
# to see users may not have it but can get it now.
inform_changed_data([request.user])
message = _('You have supported this motion successfully.')
else:
# Unsupport motion.

View File

@ -102,13 +102,13 @@ class CollectionElement:
"""
from .autoupdate import format_for_autoupdate
# TODO: Revert this after get_projector_data is also enhanced like get_restricted_data.
# TODO: Revert this after get_projector_data is also enhanced like get_restricted_data. See also #3282.
if method == 'get_restricted_data':
container = self
elif not self.is_deleted():
container = self.get_full_data()
else:
# TODO: Find a better solution for this hotfix, see issue #3282.
if not self.is_deleted():
container = self.get_full_data()
container = None
# End of hack
if not self.is_deleted():

View File

@ -15,9 +15,10 @@ class ItemViewSetManageSpeaker(TestCase):
self.view_instance.get_object = get_object_mock = MagicMock()
get_object_mock.return_value = self.mock_item = MagicMock()
@patch('openslides.agenda.views.inform_changed_data')
@patch('openslides.agenda.views.has_perm')
@patch('openslides.agenda.views.Speaker')
def test_add_oneself_as_speaker(self, mock_speaker, mock_has_perm):
def test_add_oneself_as_speaker(self, mock_speaker, mock_has_perm, mock_icd):
self.request.method = 'POST'
self.request.user = 1
mock_has_perm.return_value = True
@ -28,10 +29,11 @@ class ItemViewSetManageSpeaker(TestCase):
mock_speaker.objects.add.assert_called_with(self.request.user, self.mock_item)
@patch('openslides.agenda.views.inform_changed_data')
@patch('openslides.agenda.views.has_perm')
@patch('openslides.agenda.views.get_user_model')
@patch('openslides.agenda.views.Speaker')
def test_add_someone_else_as_speaker(self, mock_speaker, mock_get_user_model, mock_has_perm):
def test_add_someone_else_as_speaker(self, mock_speaker, mock_get_user_model, mock_has_perm, mock_icd):
self.request.method = 'POST'
self.request.user = 1
self.request.data = {'user': '2'} # It is assumed that the request user has pk!=2.

View File

@ -17,9 +17,10 @@ class MotionViewSetCreate(TestCase):
self.view_instance.get_serializer = get_serializer_mock = MagicMock()
get_serializer_mock.return_value = self.mock_serializer = MagicMock()
@patch('openslides.motions.views.inform_changed_data')
@patch('openslides.motions.views.has_perm')
@patch('openslides.motions.views.config')
def test_simple_create(self, mock_config, mock_has_perm):
def test_simple_create(self, mock_config, mock_has_perm, mock_icd):
self.request.user = 1
mock_has_perm.return_value = True
@ -41,9 +42,10 @@ class MotionViewSetUpdate(TestCase):
self.view_instance.get_serializer = get_serializer_mock = MagicMock()
get_serializer_mock.return_value = self.mock_serializer = MagicMock()
@patch('openslides.motions.views.inform_changed_data')
@patch('openslides.motions.views.has_perm')
@patch('openslides.motions.views.config')
def test_simple_update(self, mock_config, mock_has_perm):
def test_simple_update(self, mock_config, mock_has_perm, mock_icd):
self.request.user = 1
self.request.data.get.return_value = versioning_mock = MagicMock()
mock_has_perm.return_value = True