mirror of
https://github.com/home-assistant/core.git
synced 2025-07-09 14:27:07 +00:00
Add reauth flow for lyric (#47863)
This commit is contained in:
parent
ad967cfebb
commit
912d5c347c
@ -6,7 +6,9 @@ from datetime import timedelta
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from aiohttp.client_exceptions import ClientResponseError
|
||||||
from aiolyric import Lyric
|
from aiolyric import Lyric
|
||||||
|
from aiolyric.exceptions import LyricAuthenticationException, LyricException
|
||||||
from aiolyric.objects.device import LyricDevice
|
from aiolyric.objects.device import LyricDevice
|
||||||
from aiolyric.objects.location import LyricLocation
|
from aiolyric.objects.location import LyricLocation
|
||||||
import async_timeout
|
import async_timeout
|
||||||
@ -15,6 +17,7 @@ import voluptuous as vol
|
|||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
|
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import ConfigEntryAuthFailed
|
||||||
from homeassistant.helpers import (
|
from homeassistant.helpers import (
|
||||||
aiohttp_client,
|
aiohttp_client,
|
||||||
config_entry_oauth2_flow,
|
config_entry_oauth2_flow,
|
||||||
@ -29,7 +32,7 @@ from homeassistant.helpers.update_coordinator import (
|
|||||||
|
|
||||||
from .api import ConfigEntryLyricClient, LyricLocalOAuth2Implementation
|
from .api import ConfigEntryLyricClient, LyricLocalOAuth2Implementation
|
||||||
from .config_flow import OAuth2FlowHandler
|
from .config_flow import OAuth2FlowHandler
|
||||||
from .const import DOMAIN, LYRIC_EXCEPTIONS, OAUTH2_AUTHORIZE, OAUTH2_TOKEN
|
from .const import DOMAIN, OAUTH2_AUTHORIZE, OAUTH2_TOKEN
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema(
|
CONFIG_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
@ -94,7 +97,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
async with async_timeout.timeout(60):
|
async with async_timeout.timeout(60):
|
||||||
await lyric.get_locations()
|
await lyric.get_locations()
|
||||||
return lyric
|
return lyric
|
||||||
except LYRIC_EXCEPTIONS as exception:
|
except LyricAuthenticationException as exception:
|
||||||
|
raise ConfigEntryAuthFailed from exception
|
||||||
|
except (LyricException, ClientResponseError) as exception:
|
||||||
raise UpdateFailed(exception) from exception
|
raise UpdateFailed(exception) from exception
|
||||||
|
|
||||||
coordinator = DataUpdateCoordinator(
|
coordinator = DataUpdateCoordinator(
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
"""Config flow for Honeywell Lyric."""
|
"""Config flow for Honeywell Lyric."""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.helpers import config_entry_oauth2_flow
|
from homeassistant.helpers import config_entry_oauth2_flow
|
||||||
|
|
||||||
@ -21,3 +23,25 @@ class OAuth2FlowHandler(
|
|||||||
def logger(self) -> logging.Logger:
|
def logger(self) -> logging.Logger:
|
||||||
"""Return logger."""
|
"""Return logger."""
|
||||||
return logging.getLogger(__name__)
|
return logging.getLogger(__name__)
|
||||||
|
|
||||||
|
async def async_step_reauth(self, user_input=None):
|
||||||
|
"""Perform reauth upon an API authentication error."""
|
||||||
|
return await self.async_step_reauth_confirm()
|
||||||
|
|
||||||
|
async def async_step_reauth_confirm(self, user_input=None):
|
||||||
|
"""Dialog that informs the user that reauth is required."""
|
||||||
|
if user_input is None:
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id="reauth_confirm",
|
||||||
|
data_schema=vol.Schema({}),
|
||||||
|
)
|
||||||
|
return await self.async_step_user()
|
||||||
|
|
||||||
|
async def async_oauth_create_entry(self, data: dict) -> dict:
|
||||||
|
"""Create an oauth config entry or update existing entry for reauth."""
|
||||||
|
existing_entry = await self.async_set_unique_id(DOMAIN)
|
||||||
|
if existing_entry:
|
||||||
|
self.hass.config_entries.async_update_entry(existing_entry, data=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="Lyric", data=data)
|
||||||
|
@ -3,11 +3,16 @@
|
|||||||
"step": {
|
"step": {
|
||||||
"pick_implementation": {
|
"pick_implementation": {
|
||||||
"title": "[%key:common::config_flow::title::oauth2_pick_implementation%]"
|
"title": "[%key:common::config_flow::title::oauth2_pick_implementation%]"
|
||||||
|
},
|
||||||
|
"reauth_confirm": {
|
||||||
|
"title": "[%key:common::config_flow::title::reauth%]",
|
||||||
|
"description": "The Lyric integration needs to re-authenticate your account."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"abort": {
|
"abort": {
|
||||||
|
"authorize_url_timeout": "[%key:common::config_flow::abort::oauth2_authorize_url_timeout%]",
|
||||||
"missing_configuration": "[%key:common::config_flow::abort::oauth2_missing_configuration%]",
|
"missing_configuration": "[%key:common::config_flow::abort::oauth2_missing_configuration%]",
|
||||||
"authorize_url_timeout": "[%key:common::config_flow::abort::oauth2_authorize_url_timeout%]"
|
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
|
||||||
},
|
},
|
||||||
"create_entry": {
|
"create_entry": {
|
||||||
"default": "[%key:common::config_flow::create_entry::authenticated%]"
|
"default": "[%key:common::config_flow::create_entry::authenticated%]"
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"abort": {
|
"abort": {
|
||||||
"authorize_url_timeout": "Timeout generating authorize URL.",
|
"authorize_url_timeout": "Timeout generating authorize URL.",
|
||||||
"missing_configuration": "The component is not configured. Please follow the documentation."
|
"missing_configuration": "The component is not configured. Please follow the documentation.",
|
||||||
|
"reauth_successful": "Re-authentication was successful"
|
||||||
},
|
},
|
||||||
"create_entry": {
|
"create_entry": {
|
||||||
"default": "Successfully authenticated"
|
"default": "Successfully authenticated"
|
||||||
@ -10,6 +11,10 @@
|
|||||||
"step": {
|
"step": {
|
||||||
"pick_implementation": {
|
"pick_implementation": {
|
||||||
"title": "Pick Authentication Method"
|
"title": "Pick Authentication Method"
|
||||||
|
},
|
||||||
|
"reauth_confirm": {
|
||||||
|
"description": "The Lyric integration needs to re-authenticate your account.",
|
||||||
|
"title": "Reauthenticate Integration"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,8 @@ from homeassistant.components.lyric.const import DOMAIN, OAUTH2_AUTHORIZE, OAUTH
|
|||||||
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
|
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
|
||||||
from homeassistant.helpers import config_entry_oauth2_flow
|
from homeassistant.helpers import config_entry_oauth2_flow
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
CLIENT_ID = "1234"
|
CLIENT_ID = "1234"
|
||||||
CLIENT_SECRET = "5678"
|
CLIENT_SECRET = "5678"
|
||||||
|
|
||||||
@ -131,3 +133,69 @@ async def test_abort_if_authorization_timeout(
|
|||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||||
assert result["reason"] == "authorize_url_timeout"
|
assert result["reason"] == "authorize_url_timeout"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_reauthentication_flow(
|
||||||
|
hass, aiohttp_client, aioclient_mock, current_request_with_host
|
||||||
|
):
|
||||||
|
"""Test reauthentication flow."""
|
||||||
|
await setup.async_setup_component(
|
||||||
|
hass,
|
||||||
|
DOMAIN,
|
||||||
|
{
|
||||||
|
DOMAIN: {
|
||||||
|
CONF_CLIENT_ID: CLIENT_ID,
|
||||||
|
CONF_CLIENT_SECRET: CLIENT_SECRET,
|
||||||
|
},
|
||||||
|
DOMAIN_HTTP: {CONF_BASE_URL: "https://example.com"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
old_entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
unique_id=DOMAIN,
|
||||||
|
version=1,
|
||||||
|
data={"id": "timmo", "auth_implementation": DOMAIN},
|
||||||
|
)
|
||||||
|
old_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": "reauth"}, data=old_entry.data
|
||||||
|
)
|
||||||
|
|
||||||
|
flows = hass.config_entries.flow.async_progress()
|
||||||
|
assert len(flows) == 1
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(flows[0]["flow_id"], {})
|
||||||
|
|
||||||
|
# pylint: disable=protected-access
|
||||||
|
state = config_entry_oauth2_flow._encode_jwt(
|
||||||
|
hass,
|
||||||
|
{
|
||||||
|
"flow_id": result["flow_id"],
|
||||||
|
"redirect_uri": "https://example.com/auth/external/callback",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
client = await aiohttp_client(hass.http.app)
|
||||||
|
await client.get(f"/auth/external/callback?code=abcd&state={state}")
|
||||||
|
|
||||||
|
aioclient_mock.post(
|
||||||
|
OAUTH2_TOKEN,
|
||||||
|
json={
|
||||||
|
"refresh_token": "mock-refresh-token",
|
||||||
|
"access_token": "mock-access-token",
|
||||||
|
"type": "Bearer",
|
||||||
|
"expires_in": 60,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch("homeassistant.components.lyric.api.ConfigEntryLyricClient"):
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.lyric.async_setup_entry", return_value=True
|
||||||
|
) as mock_setup:
|
||||||
|
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||||
|
assert result["reason"] == "reauth_successful"
|
||||||
|
|
||||||
|
assert len(mock_setup.mock_calls) == 1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user