mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 21:57:51 +00:00
Fix onvif reauth when device returns a http 401/403 error (#92690)
This commit is contained in:
parent
d66305ddd3
commit
d05724a42a
@ -1,5 +1,6 @@
|
|||||||
"""The ONVIF integration."""
|
"""The ONVIF integration."""
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from http import HTTPStatus
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from httpx import RequestError
|
from httpx import RequestError
|
||||||
@ -56,7 +57,20 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
except ONVIFError as err:
|
except ONVIFError as err:
|
||||||
await device.device.close()
|
await device.device.close()
|
||||||
raise ConfigEntryNotReady(
|
raise ConfigEntryNotReady(
|
||||||
f"Could not setup camera {device.device.host}:{device.device.port}: {err}"
|
f"Could not setup camera {device.device.host}:{device.device.port}: {stringify_onvif_error(err)}"
|
||||||
|
) from err
|
||||||
|
except TransportError as err:
|
||||||
|
await device.device.close()
|
||||||
|
stringified_onvif_error = stringify_onvif_error(err)
|
||||||
|
if err.status_code in (
|
||||||
|
HTTPStatus.UNAUTHORIZED.value,
|
||||||
|
HTTPStatus.FORBIDDEN.value,
|
||||||
|
):
|
||||||
|
raise ConfigEntryAuthFailed(
|
||||||
|
f"Auth Failed: {stringified_onvif_error}"
|
||||||
|
) from err
|
||||||
|
raise ConfigEntryNotReady(
|
||||||
|
f"Could not setup camera {device.device.host}:{device.device.port}: {stringified_onvif_error}"
|
||||||
) from err
|
) from err
|
||||||
except asyncio.CancelledError as err:
|
except asyncio.CancelledError as err:
|
||||||
# After https://github.com/agronholm/anyio/issues/374 is resolved
|
# After https://github.com/agronholm/anyio/issues/374 is resolved
|
||||||
|
@ -142,10 +142,14 @@ class OnvifFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
hass.async_create_task(hass.config_entries.async_reload(entry_id))
|
hass.async_create_task(hass.config_entries.async_reload(entry_id))
|
||||||
return self.async_abort(reason="reauth_successful")
|
return self.async_abort(reason="reauth_successful")
|
||||||
|
|
||||||
|
username = (user_input or {}).get(CONF_USERNAME) or entry.data[CONF_USERNAME]
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
step_id="reauth_confirm",
|
step_id="reauth_confirm",
|
||||||
data_schema=vol.Schema(
|
data_schema=vol.Schema(
|
||||||
{vol.Required(CONF_USERNAME): str, vol.Required(CONF_PASSWORD): str}
|
{
|
||||||
|
vol.Required(CONF_USERNAME, default=username): str,
|
||||||
|
vol.Required(CONF_PASSWORD): str,
|
||||||
|
}
|
||||||
),
|
),
|
||||||
errors=errors,
|
errors=errors,
|
||||||
description_placeholders=description_placeholders,
|
description_placeholders=description_placeholders,
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
},
|
},
|
||||||
"reauth_confirm": {
|
"reauth_confirm": {
|
||||||
"title": "Reauthenticate the ONVIF device",
|
"title": "Reauthenticate the ONVIF device",
|
||||||
|
"description": "Some devices will reject authentication if the time is out of sync by more than 5 seconds. If authentication is unsuccessful, verify the time on the device is correct and try again.",
|
||||||
"data": {
|
"data": {
|
||||||
"username": "[%key:common::config_flow::data::username%]",
|
"username": "[%key:common::config_flow::data::username%]",
|
||||||
"password": "[%key:common::config_flow::data::password%]"
|
"password": "[%key:common::config_flow::data::password%]"
|
||||||
|
@ -5,7 +5,7 @@ from homeassistant import config_entries, data_entry_flow
|
|||||||
from homeassistant.components import dhcp
|
from homeassistant.components import dhcp
|
||||||
from homeassistant.components.onvif import DOMAIN, config_flow
|
from homeassistant.components.onvif import DOMAIN, config_flow
|
||||||
from homeassistant.config_entries import SOURCE_DHCP
|
from homeassistant.config_entries import SOURCE_DHCP
|
||||||
from homeassistant.const import CONF_HOST
|
from homeassistant.const import CONF_HOST, CONF_USERNAME
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import FlowResultType
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
from homeassistant.helpers import device_registry as dr
|
from homeassistant.helpers import device_registry as dr
|
||||||
@ -710,6 +710,14 @@ async def test_discovered_by_dhcp_does_not_update_if_no_matching_entry(
|
|||||||
assert result["reason"] == "no_devices_found"
|
assert result["reason"] == "no_devices_found"
|
||||||
|
|
||||||
|
|
||||||
|
def _get_schema_default(schema, key_name):
|
||||||
|
"""Iterate schema to find a key."""
|
||||||
|
for schema_key in schema:
|
||||||
|
if schema_key == key_name:
|
||||||
|
return schema_key.default()
|
||||||
|
raise KeyError(f"{key_name} not found in schema")
|
||||||
|
|
||||||
|
|
||||||
async def test_form_reauth(hass: HomeAssistant) -> None:
|
async def test_form_reauth(hass: HomeAssistant) -> None:
|
||||||
"""Test reauthenticate."""
|
"""Test reauthenticate."""
|
||||||
entry, _, _ = await setup_onvif_integration(hass)
|
entry, _, _ = await setup_onvif_integration(hass)
|
||||||
@ -721,6 +729,10 @@ async def test_form_reauth(hass: HomeAssistant) -> None:
|
|||||||
)
|
)
|
||||||
assert result["type"] == FlowResultType.FORM
|
assert result["type"] == FlowResultType.FORM
|
||||||
assert result["step_id"] == "reauth_confirm"
|
assert result["step_id"] == "reauth_confirm"
|
||||||
|
assert (
|
||||||
|
_get_schema_default(result["data_schema"].schema, CONF_USERNAME)
|
||||||
|
== entry.data[CONF_USERNAME]
|
||||||
|
)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.onvif.config_flow.get_device"
|
"homeassistant.components.onvif.config_flow.get_device"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user