From 5c592e4a878656d9f530bf1290c75c63547f2bde Mon Sep 17 00:00:00 2001 From: Vito Sansevero Date: Wed, 7 Oct 2026 18:53:03 -0700 Subject: [PATCH] fix: saving LoRA settings without a key keeps the stored CivitAI key --- py/api/lora_integration.py | 15 ++++++++++++- tests/test_api_lora.py | 44 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/py/api/lora_integration.py b/py/api/lora_integration.py index 9630e78..e64f312 100644 --- a/py/api/lora_integration.py +++ b/py/api/lora_integration.py @@ -95,11 +95,24 @@ class LoraIntegrationMixin: enabled = data.get("enabled", False) path = data.get("path", "") trigger_words = data.get("trigger_words_enabled", False) - civitai_key = data.get("civitai_api_key", "") from ..config import IntegrationConfig, PromptManagerConfig from ..lora_utils import detect_lora_manager, get_trigger_cache + # The key is never echoed back to the UI, so a blank or absent + # field means "unchanged"; clearing is an explicit request. + civitai_key = IntegrationConfig.CIVITAI_API_KEY + submitted_key = data.get("civitai_api_key") + if submitted_key is not None and not isinstance(submitted_key, str): + return web.json_response( + {"success": False, "error": "civitai_api_key must be a string"}, + status=400, + ) + if data.get("clear_civitai_api_key"): + civitai_key = "" + elif submitted_key and submitted_key.strip(): + civitai_key = submitted_key.strip() + # If enabling, validate the path if enabled: resolved = await self._run_in_executor(detect_lora_manager, path) diff --git a/tests/test_api_lora.py b/tests/test_api_lora.py index 2c170e8..b4ed354 100644 --- a/tests/test_api_lora.py +++ b/tests/test_api_lora.py @@ -267,6 +267,50 @@ class TestLoraEnableRoute(LoraAPITestCase): self.assertFalse(get_trigger_cache().is_loaded) self.assertFalse(IntegrationConfig.LORA_MANAGER_ENABLED) + async def test_empty_key_keeps_the_stored_key(self): + IntegrationConfig.CIVITAI_API_KEY = SECRET_KEY + + resp = await self._post_json( + "/prompt_manager/lora/enable", {"enabled": False, "civitai_api_key": ""} + ) + + self.assertEqual(resp.status, 200) + self.assertEqual(IntegrationConfig.CIVITAI_API_KEY, SECRET_KEY) + + async def test_absent_key_keeps_the_stored_key(self): + IntegrationConfig.CIVITAI_API_KEY = SECRET_KEY + + await self._post_json("/prompt_manager/lora/enable", {"enabled": False}) + + self.assertEqual(IntegrationConfig.CIVITAI_API_KEY, SECRET_KEY) + + async def test_new_key_replaces_the_stored_key(self): + IntegrationConfig.CIVITAI_API_KEY = SECRET_KEY + + await self._post_json( + "/prompt_manager/lora/enable", + {"enabled": False, "civitai_api_key": " new-key "}, + ) + + self.assertEqual(IntegrationConfig.CIVITAI_API_KEY, "new-key") + + async def test_clear_flag_removes_the_stored_key(self): + IntegrationConfig.CIVITAI_API_KEY = SECRET_KEY + + resp = await self._post_json( + "/prompt_manager/lora/enable", + {"enabled": False, "clear_civitai_api_key": True}, + ) + + self.assertEqual(resp.status, 200) + self.assertEqual(IntegrationConfig.CIVITAI_API_KEY, "") + + async def test_non_string_key_is_400(self): + resp = await self._post_json( + "/prompt_manager/lora/enable", {"enabled": False, "civitai_api_key": 123} + ) + self.assertEqual(resp.status, 400) + async def test_persist_failure_is_500(self): self.save_mock.side_effect = OSError("read-only") resp = await self._post_json("/prompt_manager/lora/enable", {"enabled": False})