From 29187795a8f03f4c1b5ad5f4943f760f98315b7e Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Tue, 26 Feb 2019 21:35:25 +0100 Subject: [PATCH] Fix ESPHome nodes being auto-added without user confirmation (#21444) --- .../components/esphome/config_flow.py | 47 ++++++++++++------- homeassistant/components/esphome/strings.json | 6 ++- tests/components/esphome/test_config_flow.py | 5 ++ 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/esphome/config_flow.py b/homeassistant/components/esphome/config_flow.py index e509455c12e..f6b8bb9abd7 100644 --- a/homeassistant/components/esphome/config_flow.py +++ b/homeassistant/components/esphome/config_flow.py @@ -26,18 +26,7 @@ class EsphomeFlowHandler(config_entries.ConfigFlow): error: Optional[str] = None): """Handle a flow initialized by the user.""" if user_input is not None: - self._host = user_input['host'] - self._port = user_input['port'] - error, device_info = await self.fetch_device_info() - if error is not None: - return await self.async_step_user(error=error) - self._name = device_info.name - - # Only show authentication step if device uses password - if device_info.uses_password: - return await self.async_step_authenticate() - - return self._async_get_entry() + return await self._async_authenticate_or_add(user_input) fields = OrderedDict() fields[vol.Required('host', default=self._host or vol.UNDEFINED)] = str @@ -53,6 +42,33 @@ class EsphomeFlowHandler(config_entries.ConfigFlow): errors=errors ) + async def _async_authenticate_or_add(self, user_input, + from_discovery=False): + self._host = user_input['host'] + self._port = user_input['port'] + error, device_info = await self.fetch_device_info() + if error is not None: + return await self.async_step_user(error=error) + self._name = device_info.name + # Only show authentication step if device uses password + if device_info.uses_password: + return await self.async_step_authenticate() + + if from_discovery: + # If from discovery, do not create entry immediately, + # First present user with message + return await self.async_step_discovery_confirm() + return self._async_get_entry() + + async def async_step_discovery_confirm(self, user_input=None): + """Handle user-confirmation of discovered node.""" + if user_input is not None: + return self._async_get_entry() + return self.async_show_form( + step_id='discovery_confirm', + description_placeholders={'name': self._name}, + ) + async def async_step_discovery(self, user_input: ConfigType): """Handle discovery.""" address = user_input['properties'].get( @@ -63,12 +79,10 @@ class EsphomeFlowHandler(config_entries.ConfigFlow): reason='already_configured' ) - # Prefer .local addresses (mDNS is available after all, otherwise - # we wouldn't have received the discovery message) - return await self.async_step_user(user_input={ + return await self._async_authenticate_or_add(user_input={ 'host': address, 'port': user_input['port'], - }) + }, from_discovery=True) def _async_get_entry(self): return self.async_create_entry( @@ -99,6 +113,7 @@ class EsphomeFlowHandler(config_entries.ConfigFlow): data_schema=vol.Schema({ vol.Required('password'): str }), + description_placeholders={'name': self._name}, errors=errors ) diff --git a/homeassistant/components/esphome/strings.json b/homeassistant/components/esphome/strings.json index 56eeed8ea41..8f691d9cb00 100644 --- a/homeassistant/components/esphome/strings.json +++ b/homeassistant/components/esphome/strings.json @@ -21,8 +21,12 @@ "data": { "password": "Password" }, - "description": "Please enter the password you set in your configuration.", + "description": "Please enter the password you set in your configuration for {name}.", "title": "Enter Password" + }, + "discovery_confirm": { + "description": "Do you want to add the ESPHome node `{name}` to Home Assistant?", + "title": "Discovered ESPHome node" } }, "title": "ESPHome" diff --git a/tests/components/esphome/test_config_flow.py b/tests/components/esphome/test_config_flow.py index 8c870c6ad73..076ec0066a6 100644 --- a/tests/components/esphome/test_config_flow.py +++ b/tests/components/esphome/test_config_flow.py @@ -203,6 +203,11 @@ async def test_discovery_initiation(hass, mock_client): MockDeviceInfo(False, "test8266")) result = await flow.async_step_discovery(user_input=service_info) + assert result['type'] == 'form' + assert result['step_id'] == 'discovery_confirm' + assert result['description_placeholders']['name'] == 'test8266' + + result = await flow.async_step_discovery_confirm(user_input={}) assert result['type'] == 'create_entry' assert result['title'] == 'test8266' assert result['data']['host'] == 'test8266.local'