diff --git a/openslides/users/models.py b/openslides/users/models.py index 5c4a3c0c4..1e9592a8f 100644 --- a/openslides/users/models.py +++ b/openslides/users/models.py @@ -1,5 +1,4 @@ import smtplib - from random import choice from django.contrib.auth.hashers import make_password diff --git a/openslides/utils/autoupdate.py b/openslides/utils/autoupdate.py index 8926e9400..65aed3244 100644 --- a/openslides/utils/autoupdate.py +++ b/openslides/utils/autoupdate.py @@ -3,7 +3,7 @@ import threading import time import warnings from collections import OrderedDict, defaultdict -from typing import Any, Dict, Generator, Iterable, List, Tuple, Union +from typing import Any, Dict, Generator, Iterable, List, Optional, Tuple, Union from channels import Channel, Group from channels.asgi import get_channel_layer @@ -100,7 +100,7 @@ def ws_add_site(message: Any) -> None: output.append(formatted_data) # Cache restricted data for user - restricted_data_cache.update_element( + restricted_data_cache.add_element( user_id, collection.collection_string, data['id'], @@ -317,12 +317,12 @@ def send_data_site(message: ChannelMessageFormat) -> None: send_or_wait(Channel(channel_name).send, {'text': json.dumps(output)}) -def to_ordered_dict(d): +def to_ordered_dict(d: Optional[Dict]) -> Optional[OrderedDict]: """ Little helper to hash information dict in inform_*_data. """ if isinstance(d, dict): - result = OrderedDict([(key, to_ordered_dict(d[key])) for key in sorted(d.keys())]) + result = OrderedDict([(key, to_ordered_dict(d[key])) for key in sorted(d.keys())]) # type: Optional[OrderedDict] else: result = d return result @@ -404,11 +404,11 @@ class AutoupdateBundleMiddleware: """ Middleware to handle autoupdate bundling. """ - def __init__(self, get_response): + def __init__(self, get_response: Any) -> None: self.get_response = get_response # One-time configuration and initialization. - def __call__(self, request): + def __call__(self, request: Any) -> Any: thread_id = threading.get_ident() autoupdate_bundle[thread_id] = {} diff --git a/openslides/utils/cache.py b/openslides/utils/cache.py index 1cb16d31f..9e2e6ebc4 100644 --- a/openslides/utils/cache.py +++ b/openslides/utils/cache.py @@ -396,6 +396,34 @@ class RestrictedDataCache: self.get_cache_key(user_id), "{}/{}".format(collection_string, id)) + def del_user(self, user_id: int) -> None: + """ + Removes all elements for one user from the cache. + """ + redis = get_redis_connection() + redis.delete(self.get_cache_key(user_id)) + + def del_all(self) -> None: + """ + Deletes all elements from the cache. + + This method uses the redis command SCAN. See + https://redis.io/commands/scan#scan-guarantees for its limitations. If + an element is added to the cache while del_all() is in process, it is + possible, that it is not deleted. + """ + redis = get_redis_connection() + + # Get all keys that start with self.base_cache_key and delete them + match = cache.make_key('{}:*'.format(self.base_cache_key)) + cursor = 0 + while True: + cursor, keys = redis.scan(cursor, match) + for key in keys: + redis.delete(key) + if cursor == 0: + return + def exists_for_user(self, user_id: int) -> bool: """ Returns True if the cache for the user exists, else False. diff --git a/openslides/utils/views.py b/openslides/utils/views.py index 932162202..dc8411ba5 100644 --- a/openslides/utils/views.py +++ b/openslides/utils/views.py @@ -85,6 +85,6 @@ class BinaryTemplateView(TemplateView): """ Loads the specified binary template and encode it with base64. """ - def load_template(self): + def load_template(self) -> str: with open(finders.find(self.template_name), 'rb') as template: - return base64.b64encode(template.read()) + return base64.b64encode(template.read()).decode() diff --git a/setup.cfg b/setup.cfg index a07430750..86bcf93e6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,10 +20,10 @@ strict_optional = true check_untyped_defs = true [mypy-openslides.utils.*] -disallow_any = unannotated +disallow_untyped_defs = true [mypy-openslides.core.config] -disallow_any = unannotated +disallow_untyped_defs = true [mypy-tests.*] ignore_errors = true