Handle missing application credentials in Tesla Fleet (#134237)

* Handle missing application credentials

* Add tests

* Test reauth starts

* Only catch ValueError
This commit is contained in:
Brett Adams 2024-12-30 16:21:18 +10:00 committed by GitHub
parent 249d93574a
commit 810689ce66
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 37 additions and 3 deletions

View File

@ -64,6 +64,15 @@ CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
async def async_setup_entry(hass: HomeAssistant, entry: TeslaFleetConfigEntry) -> bool:
"""Set up TeslaFleet config."""
try:
implementation = await async_get_config_entry_implementation(hass, entry)
except ValueError as e:
# Remove invalid implementation from config entry then raise AuthFailed
hass.config_entries.async_update_entry(
entry, data={"auth_implementation": None}
)
raise ConfigEntryAuthFailed from e
access_token = entry.data[CONF_TOKEN][CONF_ACCESS_TOKEN]
session = async_get_clientsession(hass)
@ -71,7 +80,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: TeslaFleetConfigEntry) -
scopes: list[Scope] = [Scope(s) for s in token["scp"]]
region: str = token["ou_code"].lower()
implementation = await async_get_config_entry_implementation(hass, entry)
oauth_session = OAuth2Session(hass, entry, implementation)
refresh_lock = asyncio.Lock()

View File

@ -33,7 +33,9 @@ def mock_expires_at() -> int:
return time.time() + 3600
def create_config_entry(expires_at: int, scopes: list[Scope]) -> MockConfigEntry:
def create_config_entry(
expires_at: int, scopes: list[Scope], implementation: str = DOMAIN
) -> MockConfigEntry:
"""Create Tesla Fleet entry in Home Assistant."""
access_token = jwt.encode(
{
@ -51,7 +53,7 @@ def create_config_entry(expires_at: int, scopes: list[Scope]) -> MockConfigEntry
title=UID,
unique_id=UID,
data={
"auth_implementation": DOMAIN,
"auth_implementation": implementation,
"token": {
"status": 0,
"userid": UID,
@ -90,6 +92,12 @@ def readonly_config_entry(expires_at: int) -> MockConfigEntry:
)
@pytest.fixture
def bad_config_entry(expires_at: int) -> MockConfigEntry:
"""Create Tesla Fleet entry in Home Assistant."""
return create_config_entry(expires_at, SCOPES, "bad")
@pytest.fixture(autouse=True)
def mock_products() -> Generator[AsyncMock]:
"""Mock Tesla Fleet Api products method."""

View File

@ -30,6 +30,7 @@ from homeassistant.components.tesla_fleet.coordinator import (
from homeassistant.components.tesla_fleet.models import TeslaFleetData
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers import device_registry as dr
from . import setup_platform
@ -424,3 +425,20 @@ async def test_signing(
) as mock_get_private_key:
await setup_platform(hass, normal_config_entry)
mock_get_private_key.assert_called_once()
async def test_bad_implementation(
hass: HomeAssistant,
bad_config_entry: MockConfigEntry,
) -> None:
"""Test handling of a bad authentication implementation."""
await setup_platform(hass, bad_config_entry)
assert bad_config_entry.state is ConfigEntryState.SETUP_ERROR
# Ensure reauth flow starts
assert any(bad_config_entry.async_get_active_flows(hass, {"reauth"}))
result = await bad_config_entry.start_reauth_flow(hass)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "reauth_confirm"
assert not result["errors"]