Improve UniFi Protect unauth handling (#75269)

pull/75528/head
Christopher Bailey 2022-07-16 18:28:17 -04:00 committed by Franck Nijhof
parent bccdb29edc
commit 3a2beb2212
No known key found for this signature in database
GPG Key ID: D62583BA8AB11CA3
2 changed files with 30 additions and 9 deletions

View File

@ -72,6 +72,7 @@ class ProtectData:
self._pending_camera_ids: set[str] = set()
self._unsub_interval: CALLBACK_TYPE | None = None
self._unsub_websocket: CALLBACK_TYPE | None = None
self._auth_failures = 0
self.last_update_success = False
self.api = protect
@ -117,9 +118,13 @@ class ProtectData:
try:
updates = await self.api.update(force=force)
except NotAuthorized:
await self.async_stop()
_LOGGER.exception("Reauthentication required")
self._entry.async_start_reauth(self._hass)
if self._auth_failures < 10:
_LOGGER.exception("Auth error while updating")
self._auth_failures += 1
else:
await self.async_stop()
_LOGGER.exception("Reauthentication required")
self._entry.async_start_reauth(self._hass)
self.last_update_success = False
except ClientError:
if self.last_update_success:
@ -129,6 +134,7 @@ class ProtectData:
self._async_process_updates(self.api.bootstrap)
else:
self.last_update_success = True
self._auth_failures = 0
self._async_process_updates(updates)
@callback

View File

@ -9,14 +9,18 @@ import aiohttp
from pyunifiprotect import NotAuthorized, NvrError, ProtectApiClient
from pyunifiprotect.data import NVR, Bootstrap, Light
from homeassistant.components.unifiprotect.const import CONF_DISABLE_RTSP, DOMAIN
from homeassistant.components.unifiprotect.const import (
CONF_DISABLE_RTSP,
DEFAULT_SCAN_INTERVAL,
DOMAIN,
)
from homeassistant.config_entries import ConfigEntry, ConfigEntryState
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.setup import async_setup_component
from . import _patch_discovery
from .utils import MockUFPFixture, init_entry
from .utils import MockUFPFixture, init_entry, time_changed
from tests.common import MockConfigEntry
@ -145,12 +149,23 @@ async def test_setup_failed_update(hass: HomeAssistant, ufp: MockUFPFixture):
async def test_setup_failed_update_reauth(hass: HomeAssistant, ufp: MockUFPFixture):
"""Test setup of unifiprotect entry with update that gives unauthroized error."""
ufp.api.update = AsyncMock(side_effect=NotAuthorized)
await hass.config_entries.async_setup(ufp.entry.entry_id)
await hass.async_block_till_done()
assert ufp.entry.state == ConfigEntryState.SETUP_RETRY
assert ufp.api.update.called
assert ufp.entry.state == ConfigEntryState.LOADED
# reauth should not be triggered until there are 10 auth failures in a row
# to verify it is not transient
ufp.api.update = AsyncMock(side_effect=NotAuthorized)
for _ in range(10):
await time_changed(hass, DEFAULT_SCAN_INTERVAL)
assert len(hass.config_entries.flow._progress) == 0
assert ufp.api.update.call_count == 10
assert ufp.entry.state == ConfigEntryState.LOADED
await time_changed(hass, DEFAULT_SCAN_INTERVAL)
assert ufp.api.update.call_count == 11
assert len(hass.config_entries.flow._progress) == 1
async def test_setup_failed_error(hass: HomeAssistant, ufp: MockUFPFixture):