Improve UniFi Protect unauth handling (#75269)
parent
bccdb29edc
commit
3a2beb2212
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue