Merge pull request #3233 from normanjaeckel/FixFreeUserAgenda
Fixes autoupdate bug for a user without user.can_see_name permission …
This commit is contained in:
commit
fb56215a26
@ -46,7 +46,8 @@ Core:
|
|||||||
- Fixing error when clearing empty chat [#3199].
|
- Fixing error when clearing empty chat [#3199].
|
||||||
- Added notify system [#3212].
|
- Added notify system [#3212].
|
||||||
- Enhanced performance esp. for server restart and first connection of all
|
- 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:
|
Mediafiles:
|
||||||
- Fixed reloading of PDF on page change [#3274]
|
- Fixed reloading of PDF on page change [#3274]
|
||||||
|
@ -103,6 +103,10 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
raise ValidationError({'detail': str(e)})
|
raise ValidationError({'detail': str(e)})
|
||||||
message = _('User %s was successfully added to the list of speakers.') % user
|
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:
|
else:
|
||||||
# request.method == 'DELETE'
|
# request.method == 'DELETE'
|
||||||
speaker_ids = request.data.get('speaker')
|
speaker_ids = request.data.get('speaker')
|
||||||
|
@ -79,6 +79,9 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
# If the request.user is already a candidate he can nominate himself nevertheless.
|
# If the request.user is already a candidate he can nominate himself nevertheless.
|
||||||
assignment.set_candidate(request.user)
|
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.')
|
return _('You were nominated successfully.')
|
||||||
|
|
||||||
def withdraw_self(self, request, assignment):
|
def withdraw_self(self, request, assignment):
|
||||||
@ -140,6 +143,9 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
if assignment.is_candidate(user):
|
if assignment.is_candidate(user):
|
||||||
raise ValidationError({'detail': _('User %s is already nominated.') % user})
|
raise ValidationError({'detail': _('User %s is already nominated.') % user})
|
||||||
assignment.set_candidate(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
|
return _('User %s was nominated successfully.') % user
|
||||||
|
|
||||||
def delete_other(self, request, user, assignment):
|
def delete_other(self, request, user, assignment):
|
||||||
|
@ -723,6 +723,9 @@ class ChatMessageViewSet(ModelViewSet):
|
|||||||
method so that the request.user can be saved into the model field.
|
method so that the request.user can be saved into the model field.
|
||||||
"""
|
"""
|
||||||
serializer.save(user=self.request.user)
|
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'])
|
@list_route(methods=['post'])
|
||||||
def clear(self, request):
|
def clear(self, request):
|
||||||
|
@ -2,6 +2,7 @@ from django.conf import settings
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
|
from ..utils.autoupdate import inform_changed_data
|
||||||
from ..utils.models import RESTModelMixin
|
from ..utils.models import RESTModelMixin
|
||||||
from .access_permissions import MediafileAccessPermissions
|
from .access_permissions import MediafileAccessPermissions
|
||||||
|
|
||||||
@ -52,6 +53,16 @@ class Mediafile(RESTModelMixin, models.Model):
|
|||||||
"""
|
"""
|
||||||
return self.title
|
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):
|
def get_filesize(self):
|
||||||
"""
|
"""
|
||||||
Transforms bytes to kilobytes or megabytes. Returns the size as string.
|
Transforms bytes to kilobytes or megabytes. Returns the size as string.
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from openslides.poll.serializers import default_votes_validator
|
from ..poll.serializers import default_votes_validator
|
||||||
from openslides.utils.rest_api import (
|
from ..utils.rest_api import (
|
||||||
CharField,
|
CharField,
|
||||||
DictField,
|
DictField,
|
||||||
Field,
|
Field,
|
||||||
@ -12,8 +12,7 @@ from openslides.utils.rest_api import (
|
|||||||
SerializerMethodField,
|
SerializerMethodField,
|
||||||
ValidationError,
|
ValidationError,
|
||||||
)
|
)
|
||||||
from openslides.utils.validate import validate_html
|
from ..utils.validate import validate_html
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Category,
|
Category,
|
||||||
Motion,
|
Motion,
|
||||||
|
@ -137,6 +137,13 @@ class MotionViewSet(ModelViewSet):
|
|||||||
|
|
||||||
# Write the log message and initiate response.
|
# Write the log message and initiate response.
|
||||||
motion.write_log([ugettext_noop('Motion created')], request.user)
|
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)
|
headers = self.get_success_headers(serializer.data)
|
||||||
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
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')):
|
not has_perm(request.user, 'motions.can_manage')):
|
||||||
updated_motion.supporters.clear()
|
updated_motion.supporters.clear()
|
||||||
updated_motion.write_log([ugettext_noop('All supporters removed')], request.user)
|
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)
|
return Response(serializer.data)
|
||||||
|
|
||||||
@detail_route(methods=['put', 'delete'])
|
@detail_route(methods=['put', 'delete'])
|
||||||
@ -265,6 +279,9 @@ class MotionViewSet(ModelViewSet):
|
|||||||
raise ValidationError({'detail': _('You can not support this motion.')})
|
raise ValidationError({'detail': _('You can not support this motion.')})
|
||||||
motion.supporters.add(request.user)
|
motion.supporters.add(request.user)
|
||||||
motion.write_log([ugettext_noop('Motion supported')], 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.')
|
message = _('You have supported this motion successfully.')
|
||||||
else:
|
else:
|
||||||
# Unsupport motion.
|
# Unsupport motion.
|
||||||
|
@ -102,13 +102,13 @@ class CollectionElement:
|
|||||||
"""
|
"""
|
||||||
from .autoupdate import format_for_autoupdate
|
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':
|
if method == 'get_restricted_data':
|
||||||
container = self
|
container = self
|
||||||
|
elif not self.is_deleted():
|
||||||
|
container = self.get_full_data()
|
||||||
else:
|
else:
|
||||||
# TODO: Find a better solution for this hotfix, see issue #3282.
|
container = None
|
||||||
if not self.is_deleted():
|
|
||||||
container = self.get_full_data()
|
|
||||||
# End of hack
|
# End of hack
|
||||||
|
|
||||||
if not self.is_deleted():
|
if not self.is_deleted():
|
||||||
|
@ -15,9 +15,10 @@ class ItemViewSetManageSpeaker(TestCase):
|
|||||||
self.view_instance.get_object = get_object_mock = MagicMock()
|
self.view_instance.get_object = get_object_mock = MagicMock()
|
||||||
get_object_mock.return_value = self.mock_item = 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.has_perm')
|
||||||
@patch('openslides.agenda.views.Speaker')
|
@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.method = 'POST'
|
||||||
self.request.user = 1
|
self.request.user = 1
|
||||||
mock_has_perm.return_value = True
|
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)
|
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.has_perm')
|
||||||
@patch('openslides.agenda.views.get_user_model')
|
@patch('openslides.agenda.views.get_user_model')
|
||||||
@patch('openslides.agenda.views.Speaker')
|
@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.method = 'POST'
|
||||||
self.request.user = 1
|
self.request.user = 1
|
||||||
self.request.data = {'user': '2'} # It is assumed that the request user has pk!=2.
|
self.request.data = {'user': '2'} # It is assumed that the request user has pk!=2.
|
||||||
|
@ -17,9 +17,10 @@ class MotionViewSetCreate(TestCase):
|
|||||||
self.view_instance.get_serializer = get_serializer_mock = MagicMock()
|
self.view_instance.get_serializer = get_serializer_mock = MagicMock()
|
||||||
get_serializer_mock.return_value = self.mock_serializer = 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.has_perm')
|
||||||
@patch('openslides.motions.views.config')
|
@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
|
self.request.user = 1
|
||||||
mock_has_perm.return_value = True
|
mock_has_perm.return_value = True
|
||||||
|
|
||||||
@ -41,9 +42,10 @@ class MotionViewSetUpdate(TestCase):
|
|||||||
self.view_instance.get_serializer = get_serializer_mock = MagicMock()
|
self.view_instance.get_serializer = get_serializer_mock = MagicMock()
|
||||||
get_serializer_mock.return_value = self.mock_serializer = 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.has_perm')
|
||||||
@patch('openslides.motions.views.config')
|
@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.user = 1
|
||||||
self.request.data.get.return_value = versioning_mock = MagicMock()
|
self.request.data.get.return_value = versioning_mock = MagicMock()
|
||||||
mock_has_perm.return_value = True
|
mock_has_perm.return_value = True
|
||||||
|
Loading…
Reference in New Issue
Block a user