import json import logging from pathlib import Path from typing import Any from django.conf import settings from django.core.cache import cache from django.core.exceptions import BadRequest from django.utils.translation import gettext_lazy as _ from graphene import Context from rest_framework.request import Request logger = logging.getLogger(__name__) def is_safe_cache_key(key: str) -> bool: return key not in settings.UNSAFE_CACHE_KEYS def get_cached_value(user: Any, key: str, default: Any = None) -> Any: if user.is_staff or user.is_superuser: return cache.get(key, default) if is_safe_cache_key(key): return cache.get(key, default) return None def set_cached_value( user: Any, key: str, value: object, timeout: int = 3600 ) -> None | object: if user.is_staff or user.is_superuser: cache.set(key, value, timeout) return value return None def web_cache( request: Request | Context, key: str, data: dict[str, Any] | None, timeout: int | None, ) -> dict[str, Any]: if not data and not timeout: return {"data": get_cached_value(request.user, key)} # ty: ignore[possibly-missing-attribute] if (data and not timeout) or (timeout and not data): raise BadRequest(_("both data and timeout are required")) if timeout is None or not 0 < timeout < 216000: raise BadRequest( _("invalid timeout value, it must be between 0 and 216000 seconds") ) return {"data": set_cached_value(request.user, key, data, timeout)} # ty: ignore[possibly-missing-attribute] def set_default_cache() -> None: data_dir = Path(__file__).resolve().parent.parent / "data" for json_file in data_dir.glob("*.json"): with json_file.open("r", encoding="utf-8") as f: data = json.load(f) logger.info("Setting cache for %s", json_file.stem) cache.set(json_file.stem, data, timeout=28800)