mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Improve UniFi Protect unauth handling (#75269)
This commit is contained in:
parent
2f92c47fe3
commit
59c99e0d60
@ -72,6 +72,7 @@ class ProtectData:
|
|||||||
self._pending_camera_ids: set[str] = set()
|
self._pending_camera_ids: set[str] = set()
|
||||||
self._unsub_interval: CALLBACK_TYPE | None = None
|
self._unsub_interval: CALLBACK_TYPE | None = None
|
||||||
self._unsub_websocket: CALLBACK_TYPE | None = None
|
self._unsub_websocket: CALLBACK_TYPE | None = None
|
||||||
|
self._auth_failures = 0
|
||||||
|
|
||||||
self.last_update_success = False
|
self.last_update_success = False
|
||||||
self.api = protect
|
self.api = protect
|
||||||
@ -117,9 +118,13 @@ class ProtectData:
|
|||||||
try:
|
try:
|
||||||
updates = await self.api.update(force=force)
|
updates = await self.api.update(force=force)
|
||||||
except NotAuthorized:
|
except NotAuthorized:
|
||||||
await self.async_stop()
|
if self._auth_failures < 10:
|
||||||
_LOGGER.exception("Reauthentication required")
|
_LOGGER.exception("Auth error while updating")
|
||||||
self._entry.async_start_reauth(self._hass)
|
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
|
self.last_update_success = False
|
||||||
except ClientError:
|
except ClientError:
|
||||||
if self.last_update_success:
|
if self.last_update_success:
|
||||||
@ -129,6 +134,7 @@ class ProtectData:
|
|||||||
self._async_process_updates(self.api.bootstrap)
|
self._async_process_updates(self.api.bootstrap)
|
||||||
else:
|
else:
|
||||||
self.last_update_success = True
|
self.last_update_success = True
|
||||||
|
self._auth_failures = 0
|
||||||
self._async_process_updates(updates)
|
self._async_process_updates(updates)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@ -9,14 +9,18 @@ import aiohttp
|
|||||||
from pyunifiprotect import NotAuthorized, NvrError, ProtectApiClient
|
from pyunifiprotect import NotAuthorized, NvrError, ProtectApiClient
|
||||||
from pyunifiprotect.data import NVR, Bootstrap, Light
|
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.config_entries import ConfigEntry, ConfigEntryState
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from . import _patch_discovery
|
from . import _patch_discovery
|
||||||
from .utils import MockUFPFixture, init_entry
|
from .utils import MockUFPFixture, init_entry, time_changed
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
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):
|
async def test_setup_failed_update_reauth(hass: HomeAssistant, ufp: MockUFPFixture):
|
||||||
"""Test setup of unifiprotect entry with update that gives unauthroized error."""
|
"""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.config_entries.async_setup(ufp.entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert ufp.entry.state == ConfigEntryState.SETUP_RETRY
|
assert ufp.entry.state == ConfigEntryState.LOADED
|
||||||
assert ufp.api.update.called
|
|
||||||
|
# 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):
|
async def test_setup_failed_error(hass: HomeAssistant, ufp: MockUFPFixture):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user