diff --git a/app/api/endpoints/manifest.py b/app/api/endpoints/manifest.py index a715015..0eb42e6 100644 --- a/app/api/endpoints/manifest.py +++ b/app/api/endpoints/manifest.py @@ -80,7 +80,7 @@ def get_config_id(catalog) -> str | None: async def _manifest_handler(response: Response, token: str): - response.headers["Cache-Control"] = "public, max-age=7200" + response.headers["Cache-Control"] = "no-cache" if not token: raise HTTPException(status_code=401, detail="Missing token. Please reconfigure the addon.") diff --git a/app/core/version.py b/app/core/version.py index 0b2f79d..c72e379 100644 --- a/app/core/version.py +++ b/app/core/version.py @@ -1 +1 @@ -__version__ = "1.1.3" +__version__ = "1.1.4" diff --git a/app/services/token_store.py b/app/services/token_store.py index 77946fb..e632383 100644 --- a/app/services/token_store.py +++ b/app/services/token_store.py @@ -37,7 +37,7 @@ def _ensure_secure_salt(self) -> None: if not settings.TOKEN_SALT or settings.TOKEN_SALT == "change-me": logger.error("Refusing to store credentials because TOKEN_SALT is unset or using the insecure default.") raise RuntimeError( - "Server misconfiguration: TOKEN_SALT must be set to a non-default value before storing credentials." + "Server misconfiguration: TOKEN_SALT must be set to a non-default value before storing" " credentials." ) def _get_cipher(self) -> Fernet: @@ -145,6 +145,20 @@ async def store_user_data(self, user_id: str, payload: dict[str, Any]) -> str: else: await client.set(key, json_str) + # Invalidate async LRU cache for fresh reads on subsequent requests + try: + # bound method supports targeted invalidation by argument(s) + self.get_user_data.cache_invalidate(token) + except KeyError: + # The token was not in the cache, no action needed. + pass + except Exception as e: + logger.warning(f"Targeted cache invalidation failed: {e}. Falling back to clearing cache.") + try: + self.get_user_data.cache_clear() + except Exception as e_clear: + logger.error(f"Error while clearing cache: {e_clear}") + # Ensure we remove from negative cache so new value is read next time try: if token in self._missing_tokens: @@ -194,6 +208,19 @@ async def delete_token(self, token: str = None, key: str = None) -> None: client = await self._get_client() await client.delete(key) + # Invalidate async LRU cache so future reads reflect deletion + try: + if token: + self.get_user_data.cache_invalidate(token) + else: + # If only key is provided, clear cache entirely to be safe + self.get_user_data.cache_clear() + except KeyError: + # The token was not in the cache, no action needed. + pass + except Exception as e: + logger.warning(f"Failed to invalidate user data cache during token deletion: {e}") + # Remove from negative cache as token is deleted try: if token and token in self._missing_tokens: