From 1111a8074e59c1b3587f34e04885af111ecba5cd Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Fri, 1 Feb 2019 00:13:56 +0100 Subject: [PATCH] fix restricted_data_cache for elements that exists, but a user is not allowed to see them --- openslides/utils/cache.py | 26 ++++++++++++++++++-------- tests/unit/utils/test_cache.py | 25 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/openslides/utils/cache.py b/openslides/utils/cache.py index 34280f444..87b4945aa 100644 --- a/openslides/utils/cache.py +++ b/openslides/utils/cache.py @@ -286,19 +286,26 @@ class ElementCache: # The user_change_id is lower then the lowest change_id in the cache. # The whole restricted_data for that user has to be recreated. full_data_elements = await self.get_all_full_data() + deleted_elements = [] await self.cache_provider.del_restricted_data(user_id) - else: - # Remove deleted elements - if deleted_elements: - await self.cache_provider.del_elements( - deleted_elements, user_id - ) mapping = {} for collection_string, full_data in full_data_elements.items(): restricter = self.cachables[collection_string].restrict_elements - elements = await restricter(user_id, full_data) - for element in elements: + restricted_elements = await restricter(user_id, full_data) + + # find all elements the user can not see at all + full_data_ids = set(element["id"] for element in full_data) + restricted_data_ids = set( + element["id"] for element in restricted_elements + ) + for item_id in full_data_ids - restricted_data_ids: + deleted_elements.append( + get_element_id(collection_string, item_id) + ) + + for element in restricted_elements: + # The user can see the element mapping.update( { get_element_id( @@ -308,6 +315,9 @@ class ElementCache: ) mapping["_config:change_id"] = str(change_id) await self.cache_provider.update_restricted_data(user_id, mapping) + # Remove deleted elements + if deleted_elements: + await self.cache_provider.del_elements(deleted_elements, user_id) # Unset the lock await self.cache_provider.del_lock(lock_name) future.set_result(1) diff --git a/tests/unit/utils/test_cache.py b/tests/unit/utils/test_cache.py index f9f08e947..b88a5c358 100644 --- a/tests/unit/utils/test_cache.py +++ b/tests/unit/utils/test_cache.py @@ -1,6 +1,7 @@ import asyncio import json from typing import Any, Dict, List +from unittest.mock import patch import pytest @@ -309,6 +310,30 @@ async def test_update_restricted_data(element_cache): assert element_cache.restricted_data_cache_updater[0].done() +@pytest.mark.asyncio +async def test_update_restricted_data_full_restricted_elements(element_cache): + """ + Tests that elements in the restricted_data cache, that are later hidden from + a user, gets deleted for this user. + """ + element_cache.use_restricted_data_cache = True + await element_cache.update_restricted_data(0) + element_cache.cache_provider.change_id_data = { + 1: {"app/collection1:1", "app/collection1:3"} + } + + with patch("tests.unit.utils.cache_provider.restrict_elements", lambda x: []): + await element_cache.update_restricted_data(0) + + assert decode_dict(element_cache.cache_provider.restricted_data[0]) == decode_dict( + {"_config:change_id": "1"} + ) + # Make sure the lock is deleted + assert not await element_cache.cache_provider.get_lock("restricted_data_0") + # And the future is done + assert element_cache.restricted_data_cache_updater[0].done() + + @pytest.mark.asyncio async def test_update_restricted_data_disabled_restricted_data(element_cache): element_cache.use_restricted_data_cache = False