From eaebeb8f06777e3255e4039fcfd5694b55d5ce67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Tue, 13 Jun 2017 21:44:45 +0200 Subject: [PATCH] Fixed get_projector_data impementation. Closed #3282. --- openslides/agenda/access_permissions.py | 31 +++++++++++--- openslides/assignments/access_permissions.py | 27 +++++++++--- openslides/motions/access_permissions.py | 44 ++++++++++++++------ openslides/users/access_permissions.py | 33 +++++++++++---- openslides/utils/access_permissions.py | 4 +- openslides/utils/collection.py | 11 +---- tests/unit/users/test_access_permissions.py | 39 +++++++++++++++++ 7 files changed, 147 insertions(+), 42 deletions(-) create mode 100644 tests/unit/users/test_access_permissions.py diff --git a/openslides/agenda/access_permissions.py b/openslides/agenda/access_permissions.py index c6f34ce3e..2bd281c80 100644 --- a/openslides/agenda/access_permissions.py +++ b/openslides/agenda/access_permissions.py @@ -89,13 +89,32 @@ class ItemAccessPermissions(BaseAccessPermissions): return restricted_data - def get_projector_data(self, full_data): + def get_projector_data(self, container): """ Returns the restricted serialized data for the instance prepared for the projector. Removes field 'comment'. """ - data = {} - for key in full_data.keys(): - if key != 'comment': - data[key] = full_data[key] - return data + def filtered_data(full_data, blocked_keys): + """ + Returns a new dict like full_data but with all blocked_keys removed. + """ + whitelist = full_data.keys() - blocked_keys + return {key: full_data[key] for key in whitelist} + + # Expand full_data to a list if it is not one. + full_data = container.get_full_data() if isinstance(container, Collection) else [container.get_full_data()] + + # Parse data. + blocked_keys = ('comment',) + data = [filtered_data(full, blocked_keys) for full in full_data] + + # Reduce result to a single item or None if it was not a collection at + # the beginning of the method. + if isinstance(container, Collection): + projector_data = data + elif data: + projector_data = data[0] + else: + projector_data = None + + return projector_data diff --git a/openslides/assignments/access_permissions.py b/openslides/assignments/access_permissions.py index 74bec1a7c..56f5f2afc 100644 --- a/openslides/assignments/access_permissions.py +++ b/openslides/assignments/access_permissions.py @@ -58,11 +58,28 @@ class AssignmentAccessPermissions(BaseAccessPermissions): return restricted_data - def get_projector_data(self, full_data): + def get_projector_data(self, container): """ Returns the restricted serialized data for the instance prepared - for the projector. Removes several fields. + for the projector. Removes unpublished polls. """ - data = full_data.copy() - data['polls'] = [poll for poll in data['polls'] if poll['published']] - return data + # Expand full_data to a list if it is not one. + full_data = container.get_full_data() if isinstance(container, Collection) else [container.get_full_data()] + + # Parse data. Exclude unpublished polls. + data = [] + for full in full_data: + full_copy = full.copy() + full_copy['polls'] = [poll for poll in full['polls'] if poll['published']] + data.append(full_copy) + + # Reduce result to a single item or None if it was not a collection at + # the beginning of the method. + if isinstance(container, Collection): + projector_data = data + elif data: + projector_data = data[0] + else: + projector_data = None + + return projector_data diff --git a/openslides/motions/access_permissions.py b/openslides/motions/access_permissions.py index 473133b0f..3e6037224 100644 --- a/openslides/motions/access_permissions.py +++ b/openslides/motions/access_permissions.py @@ -96,21 +96,41 @@ class MotionAccessPermissions(BaseAccessPermissions): return restricted_data - def get_projector_data(self, full_data): + def get_projector_data(self, container): """ Returns the restricted serialized data for the instance prepared - for the projector. Removes several fields. + for the projector. Removes several comment fields. """ - data = full_data.copy() - if data.get('comments') is not None: - for i, field in enumerate(config['motions_comments']): - if not field.get('public'): - try: - data['comments'][i] = None - except IndexError: - # No data in range. Just do nothing. - pass - return data + # Expand full_data to a list if it is not one. + full_data = container.get_full_data() if isinstance(container, Collection) else [container.get_full_data()] + + # Parse data. + data = [] + for full in full_data: + # Set private comment fields to None. + if full.get('comments') is not None: + full_copy = deepcopy(full) + for i, field in enumerate(config['motions_comments']): + if not field.get('public'): + try: + full_copy['comments'][i] = None + except IndexError: + # No data in range. Just do nothing. + pass + data.append(full_copy) + else: + data.append(full) + + # Reduce result to a single item or None if it was not a collection at + # the beginning of the method. + if isinstance(container, Collection): + projector_data = data + elif data: + projector_data = data[0] + else: + projector_data = None + + return projector_data class MotionChangeRecommendationAccessPermissions(BaseAccessPermissions): diff --git a/openslides/users/access_permissions.py b/openslides/users/access_permissions.py index 246aceb28..5da7ee0fc 100644 --- a/openslides/users/access_permissions.py +++ b/openslides/users/access_permissions.py @@ -102,19 +102,38 @@ class UserAccessPermissions(BaseAccessPermissions): return restricted_data - def get_projector_data(self, full_data): + def get_projector_data(self, container): """ Returns the restricted serialized data for the instance prepared for the projector. Removes several fields. """ from .serializers import USERCANSEESERIALIZER_FIELDS - # Let only some fields pass this method. - data = {} - for key in full_data.keys(): - if key in USERCANSEESERIALIZER_FIELDS: - data[key] = full_data[key] - return data + def filtered_data(full_data, whitelist): + """ + Returns a new dict like full_data but only with whitelisted keys. + """ + return {key: full_data[key] for key in whitelist} + + # Expand full_data to a list if it is not one. + full_data = container.get_full_data() if isinstance(container, Collection) else [container.get_full_data()] + + # Parse data. + litte_data_fields = set(USERCANSEESERIALIZER_FIELDS) + litte_data_fields.add('groups_id') + litte_data_fields.discard('groups') + data = [filtered_data(full, litte_data_fields) for full in full_data] + + # Reduce result to a single item or None if it was not a collection at + # the beginning of the method. + if isinstance(container, Collection): + projector_data = data + elif data: + projector_data = data[0] + else: + projector_data = None + + return projector_data class GroupAccessPermissions(BaseAccessPermissions): diff --git a/openslides/utils/access_permissions.py b/openslides/utils/access_permissions.py index 9c5b17dd0..61a1e5d5c 100644 --- a/openslides/utils/access_permissions.py +++ b/openslides/utils/access_permissions.py @@ -82,10 +82,10 @@ class BaseAccessPermissions(object, metaclass=SignalConnectMetaClass): data = None return data - def get_projector_data(self, full_data): + def get_projector_data(self, container): """ Returns the serialized data for the projector. Returns None if the user has no access to this specific data. Returns reduced data if the user has limited access. Default: Returns full data. """ - return full_data + return container.get_full_data() diff --git a/openslides/utils/collection.py b/openslides/utils/collection.py index f23426362..ab50036cd 100644 --- a/openslides/utils/collection.py +++ b/openslides/utils/collection.py @@ -102,18 +102,9 @@ class CollectionElement: """ from .autoupdate import format_for_autoupdate - # 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: - container = None - # End of hack - if not self.is_deleted(): data = getattr(self.get_access_permissions(), method)( - container, + self, *args) else: data = None diff --git a/tests/unit/users/test_access_permissions.py b/tests/unit/users/test_access_permissions.py new file mode 100644 index 000000000..abaf628cf --- /dev/null +++ b/tests/unit/users/test_access_permissions.py @@ -0,0 +1,39 @@ +from unittest import TestCase + +from openslides.users.access_permissions import UserAccessPermissions +from openslides.utils.collection import CollectionElement + + +class UserGetProjectorDataTest(TestCase): + def test_get_projector_data_with_collection(self): + """ + This test ensures that comment field is removed. + """ + container = CollectionElement.from_values('users/user', 42, full_data={ + 'id': 42, + 'username': 'username_ai3Oofu7eit0eeyu1sie', + 'title': '', + 'first_name': 'first_name_iu8toShae0oolie8aevo', + 'last_name': 'last_name_OhZ4beezohY0doNoh2th', + 'structure_level': '', + 'number': '', + 'about_me': '', + 'groups_id': [], + 'is_present': False, + 'is_committee': False, + 'comment': 'comment_gah7aipeJohv9xethoku', + }) + data = UserAccessPermissions().get_projector_data(container) + self.assertEqual(data, { + 'id': 42, + 'username': 'username_ai3Oofu7eit0eeyu1sie', + 'title': '', + 'first_name': 'first_name_iu8toShae0oolie8aevo', + 'last_name': 'last_name_OhZ4beezohY0doNoh2th', + 'structure_level': '', + 'number': '', + 'about_me': '', + 'groups_id': [], + 'is_present': False, + 'is_committee': False, + })