Add Nanoleaf reauth flow (#55217)

Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
pull/55227/head
Milan Meulemans 2021-08-25 21:56:10 +02:00 committed by GitHub
parent fb28665cfa
commit 59d401e7b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 76 additions and 3 deletions

View File

@ -1,10 +1,10 @@
"""The Nanoleaf integration."""
from pynanoleaf.pynanoleaf import Nanoleaf, Unavailable
from pynanoleaf.pynanoleaf import InvalidToken, Nanoleaf, Unavailable
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_TOKEN
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from .const import DEVICE, DOMAIN, NAME, SERIAL_NO
from .util import pynanoleaf_get_info
@ -18,6 +18,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
info = await hass.async_add_executor_job(pynanoleaf_get_info, nanoleaf)
except Unavailable as err:
raise ConfigEntryNotReady from err
except InvalidToken as err:
raise ConfigEntryAuthFailed from err
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = {
DEVICE: nanoleaf,

View File

@ -32,6 +32,8 @@ USER_SCHEMA: Final = vol.Schema(
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Nanoleaf config flow."""
reauth_entry: config_entries.ConfigEntry | None = None
VERSION = 1
def __init__(self) -> None:
@ -73,6 +75,16 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
)
return await self.async_step_link()
async def async_step_reauth(self, data: dict[str, str]) -> FlowResult:
"""Handle Nanoleaf reauth flow if token is invalid."""
self.reauth_entry = cast(
config_entries.ConfigEntry,
self.hass.config_entries.async_get_entry(self.context["entry_id"]),
)
self.nanoleaf = Nanoleaf(data[CONF_HOST])
self.context["title_placeholders"] = {"name": self.reauth_entry.title}
return await self.async_step_link()
async def async_step_zeroconf(
self, discovery_info: DiscoveryInfoType
) -> FlowResult:
@ -135,6 +147,18 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unknown error authorizing Nanoleaf")
return self.async_show_form(step_id="link", errors={"base": "unknown"})
if self.reauth_entry is not None:
self.hass.config_entries.async_update_entry(
self.reauth_entry,
data={
**self.reauth_entry.data,
CONF_TOKEN: self.nanoleaf.token,
},
)
await self.hass.config_entries.async_reload(self.reauth_entry.entry_id)
return self.async_abort(reason="reauth_successful")
return await self.async_setup_finish()
async def async_step_import(self, config: dict[str, Any]) -> FlowResult:

View File

@ -21,6 +21,7 @@
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"invalid_token": "[%key:common::config_flow::error::invalid_access_token%]",
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
"unknown": "[%key:common::config_flow::error::unknown%]"
}
}

View File

@ -4,6 +4,7 @@
"already_configured": "Device is already configured",
"cannot_connect": "Failed to connect",
"invalid_token": "Invalid access token",
"reauth_successful": "Re-authentication was successful",
"unknown": "Unexpected error"
},
"error": {

View File

@ -1,7 +1,7 @@
"""Test the Nanoleaf config flow."""
from __future__ import annotations
from unittest.mock import patch
from unittest.mock import MagicMock, patch
from pynanoleaf import InvalidToken, NotAuthorizingNewTokens, Unavailable
from pynanoleaf.pynanoleaf import NanoleafError
@ -12,6 +12,8 @@ from homeassistant.components.nanoleaf.const import DOMAIN
from homeassistant.const import CONF_HOST, CONF_TOKEN
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
TEST_NAME = "Canvas ADF9"
TEST_HOST = "192.168.0.100"
TEST_OTHER_HOST = "192.168.0.200"
@ -283,6 +285,49 @@ async def test_discovery_link_unavailable(
assert result["reason"] == "cannot_connect"
async def test_reauth(hass: HomeAssistant) -> None:
"""Test Nanoleaf reauth flow."""
nanoleaf = MagicMock()
nanoleaf.host = TEST_HOST
nanoleaf.token = TEST_TOKEN
entry = MockConfigEntry(
domain=DOMAIN,
unique_id=TEST_NAME,
data={CONF_HOST: TEST_HOST, CONF_TOKEN: TEST_OTHER_TOKEN},
)
entry.add_to_hass(hass)
with patch(
"homeassistant.components.nanoleaf.config_flow.Nanoleaf",
return_value=nanoleaf,
), patch(
"homeassistant.components.nanoleaf.async_setup_entry",
return_value=True,
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={
"source": config_entries.SOURCE_REAUTH,
"entry_id": entry.entry_id,
"unique_id": entry.unique_id,
},
data=entry.data,
)
assert result["type"] == "form"
assert result["step_id"] == "link"
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{},
)
assert result2["type"] == "abort"
assert result2["reason"] == "reauth_successful"
assert entry.data[CONF_HOST] == TEST_HOST
assert entry.data[CONF_TOKEN] == TEST_TOKEN
async def test_import_config(hass: HomeAssistant) -> None:
"""Test configuration import."""
with patch(