Prompt to reauth when the august password is changed or token expires (#40103)
* Prompt to reauth when the august password is changed or token expires * augment missing config flow coverage * augment test coverage * Adjust test * Update homeassistant/components/august/__init__.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * block until patch complete Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
540b925659
commit
5ea04d64f6
9 changed files with 379 additions and 100 deletions
|
@ -4,7 +4,7 @@ import logging
|
|||
from august.authenticator import ValidationResult
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries, core
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_TIMEOUT, CONF_USERNAME
|
||||
|
||||
from .const import (
|
||||
|
@ -19,18 +19,8 @@ from .gateway import AugustGateway
|
|||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DATA_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_LOGIN_METHOD, default="phone"): vol.In(LOGIN_METHODS),
|
||||
vol.Required(CONF_USERNAME): str,
|
||||
vol.Required(CONF_PASSWORD): str,
|
||||
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): vol.Coerce(int),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def async_validate_input(
|
||||
hass: core.HomeAssistant,
|
||||
data,
|
||||
august_gateway,
|
||||
):
|
||||
|
@ -79,6 +69,7 @@ class AugustConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
"""Store an AugustGateway()."""
|
||||
self._august_gateway = None
|
||||
self.user_auth_details = {}
|
||||
self._needs_reset = False
|
||||
super().__init__()
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
|
@ -87,30 +78,45 @@ class AugustConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
self._august_gateway = AugustGateway(self.hass)
|
||||
errors = {}
|
||||
if user_input is not None:
|
||||
await self._august_gateway.async_setup(user_input)
|
||||
combined_inputs = {**self.user_auth_details, **user_input}
|
||||
await self._august_gateway.async_setup(combined_inputs)
|
||||
if self._needs_reset:
|
||||
self._needs_reset = False
|
||||
await self._august_gateway.async_reset_authentication()
|
||||
|
||||
try:
|
||||
info = await async_validate_input(
|
||||
self.hass,
|
||||
user_input,
|
||||
combined_inputs,
|
||||
self._august_gateway,
|
||||
)
|
||||
await self.async_set_unique_id(user_input[CONF_USERNAME])
|
||||
return self.async_create_entry(title=info["title"], data=info["data"])
|
||||
except CannotConnect:
|
||||
errors["base"] = "cannot_connect"
|
||||
except InvalidAuth:
|
||||
errors["base"] = "invalid_auth"
|
||||
except RequireValidation:
|
||||
self.user_auth_details = user_input
|
||||
self.user_auth_details.update(user_input)
|
||||
|
||||
return await self.async_step_validation()
|
||||
except Exception: # pylint: disable=broad-except
|
||||
_LOGGER.exception("Unexpected exception")
|
||||
errors["base"] = "unknown"
|
||||
|
||||
if not errors:
|
||||
self.user_auth_details.update(user_input)
|
||||
|
||||
existing_entry = await self.async_set_unique_id(
|
||||
combined_inputs[CONF_USERNAME]
|
||||
)
|
||||
if existing_entry:
|
||||
self.hass.config_entries.async_update_entry(
|
||||
existing_entry, data=info["data"]
|
||||
)
|
||||
await self.hass.config_entries.async_reload(existing_entry.entry_id)
|
||||
return self.async_abort(reason="reauth_successful")
|
||||
return self.async_create_entry(title=info["title"], data=info["data"])
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="user", data_schema=DATA_SCHEMA, errors=errors
|
||||
step_id="user", data_schema=self._async_build_schema(), errors=errors
|
||||
)
|
||||
|
||||
async def async_step_validation(self, user_input=None):
|
||||
|
@ -135,3 +141,23 @@ class AugustConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
self._abort_if_unique_id_configured()
|
||||
|
||||
return await self.async_step_user(user_input)
|
||||
|
||||
async def async_step_reauth(self, data):
|
||||
"""Handle configuration by re-auth."""
|
||||
self.user_auth_details = dict(data)
|
||||
self._needs_reset = True
|
||||
return await self.async_step_user()
|
||||
|
||||
def _async_build_schema(self):
|
||||
"""Generate the config flow schema."""
|
||||
base_schema = {
|
||||
vol.Required(CONF_LOGIN_METHOD, default="phone"): vol.In(LOGIN_METHODS),
|
||||
vol.Required(CONF_USERNAME): str,
|
||||
vol.Required(CONF_PASSWORD): str,
|
||||
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): vol.Coerce(int),
|
||||
}
|
||||
for key in self.user_auth_details:
|
||||
if key == CONF_PASSWORD or key not in base_schema:
|
||||
continue
|
||||
del base_schema[key]
|
||||
return vol.Schema(base_schema)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue