From 514ab823d66b0f859d7e87426f7e40a3c949615d Mon Sep 17 00:00:00 2001 From: SchiZzA Date: Sun, 21 Jun 2026 19:10:31 +0200 Subject: [PATCH] feat(config-flow): mask secret fields with password selectors (Q7) API_KEY, WINDY_STATION_PWD and POCASI_CZ_API_KEY now use a password TextSelector so the values are masked in the UI. Field keys are unchanged, so stored options and the flow contract are unaffected. 308 passing, 100% coverage; ruff + basedpyright clean. Co-Authored-By: Claude Opus 4.8 (1M context) --- custom_components/sws12500/config_flow.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/custom_components/sws12500/config_flow.py b/custom_components/sws12500/config_flow.py index d13e3aa..f6439cd 100644 --- a/custom_components/sws12500/config_flow.py +++ b/custom_components/sws12500/config_flow.py @@ -11,6 +11,7 @@ from yarl import URL from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult, OptionsFlow from homeassistant.core import callback from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers import selector from homeassistant.helpers.network import get_url from .const import ( @@ -37,6 +38,9 @@ from .const import ( WSLINK_ADDON_PORT, ) +# Masked text input for secret fields (API keys / station passwords). +_PASSWORD_SELECTOR = selector.TextSelector(selector.TextSelectorConfig(type=selector.TextSelectorType.PASSWORD)) + class CannotConnect(HomeAssistantError): """We can not connect. - not used in push mechanism.""" @@ -79,7 +83,7 @@ class ConfigOptionsFlowHandler(OptionsFlow): self.user_data_schema = { vol.Optional(API_ID, default=self.user_data.get(API_ID, "")): str, - vol.Optional(API_KEY, default=self.user_data.get(API_KEY, "")): str, + vol.Optional(API_KEY, default=self.user_data.get(API_KEY, "")): _PASSWORD_SELECTOR, vol.Optional(WSLINK, default=self.user_data.get(WSLINK, False)): bool, vol.Optional(DEV_DBG, default=self.user_data.get(DEV_DBG, False)): bool, vol.Optional(LEGACY_ENABLED, default=self.user_data.get(LEGACY_ENABLED, True)): bool, @@ -105,7 +109,7 @@ class ConfigOptionsFlowHandler(OptionsFlow): vol.Optional( WINDY_STATION_PW, default=self.windy_data.get(WINDY_STATION_PW, ""), - ): str, + ): _PASSWORD_SELECTOR, vol.Optional(WINDY_ENABLED, default=self.windy_data[WINDY_ENABLED]): bool, vol.Optional( WINDY_LOGGER_ENABLED, @@ -123,7 +127,7 @@ class ConfigOptionsFlowHandler(OptionsFlow): self.pocasi_cz_schema = { vol.Required(POCASI_CZ_API_ID, default=self.pocasi_cz.get(POCASI_CZ_API_ID)): str, - vol.Required(POCASI_CZ_API_KEY, default=self.pocasi_cz.get(POCASI_CZ_API_KEY)): str, + vol.Required(POCASI_CZ_API_KEY, default=self.pocasi_cz.get(POCASI_CZ_API_KEY)): _PASSWORD_SELECTOR, vol.Required( POCASI_CZ_SEND_INTERVAL, default=self.pocasi_cz.get(POCASI_CZ_SEND_INTERVAL), @@ -330,7 +334,7 @@ class ConfigFlowHandler(ConfigFlow, domain=DOMAIN): pws_schema = { vol.Required(API_ID): str, - vol.Required(API_KEY): str, + vol.Required(API_KEY): _PASSWORD_SELECTOR, vol.Optional(WSLINK): bool, vol.Optional(DEV_DBG): bool, }