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
parent
fb28665cfa
commit
59d401e7b7
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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%]"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in New Issue