Do not treat nexia http not found as invalid auth (#39484)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>pull/39654/head
parent
55040cfde5
commit
ebc31c0f08
|
@ -9,18 +9,14 @@ from requests.exceptions import ConnectTimeout, HTTPError
|
|||
import voluptuous as vol
|
||||
|
||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
||||
from homeassistant.const import (
|
||||
CONF_PASSWORD,
|
||||
CONF_USERNAME,
|
||||
HTTP_BAD_REQUEST,
|
||||
HTTP_INTERNAL_SERVER_ERROR,
|
||||
)
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
|
||||
from .const import DOMAIN, NEXIA_DEVICE, PLATFORMS, UPDATE_COORDINATOR
|
||||
from .util import is_invalid_auth_code
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -81,10 +77,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||
_LOGGER.error("Unable to connect to Nexia service: %s", ex)
|
||||
raise ConfigEntryNotReady from ex
|
||||
except HTTPError as http_ex:
|
||||
if (
|
||||
http_ex.response.status_code >= HTTP_BAD_REQUEST
|
||||
and http_ex.response.status_code < HTTP_INTERNAL_SERVER_ERROR
|
||||
):
|
||||
if is_invalid_auth_code(http_ex.response.status_code):
|
||||
_LOGGER.error(
|
||||
"Access error from Nexia service, please check credentials: %s", http_ex
|
||||
)
|
||||
|
|
|
@ -6,14 +6,10 @@ from requests.exceptions import ConnectTimeout, HTTPError
|
|||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries, core, exceptions
|
||||
from homeassistant.const import (
|
||||
CONF_PASSWORD,
|
||||
CONF_USERNAME,
|
||||
HTTP_BAD_REQUEST,
|
||||
HTTP_INTERNAL_SERVER_ERROR,
|
||||
)
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
|
||||
|
||||
from .const import DOMAIN # pylint:disable=unused-import
|
||||
from .util import is_invalid_auth_code
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -42,10 +38,7 @@ async def validate_input(hass: core.HomeAssistant, data):
|
|||
raise CannotConnect from ex
|
||||
except HTTPError as http_ex:
|
||||
_LOGGER.error("HTTP error from Nexia service: %s", http_ex)
|
||||
if (
|
||||
http_ex.response.status_code >= HTTP_BAD_REQUEST
|
||||
and http_ex.response.status_code < HTTP_INTERNAL_SERVER_ERROR
|
||||
):
|
||||
if is_invalid_auth_code(http_ex.response.status_code):
|
||||
raise InvalidAuth from http_ex
|
||||
raise CannotConnect from http_ex
|
||||
|
||||
|
|
|
@ -1,5 +1,15 @@
|
|||
"""Utils for Nexia / Trane XL Thermostats."""
|
||||
|
||||
from homeassistant.const import HTTP_FORBIDDEN, HTTP_UNAUTHORIZED
|
||||
|
||||
|
||||
def is_invalid_auth_code(http_status_code):
|
||||
"""HTTP status codes that mean invalid auth."""
|
||||
if http_status_code in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def percent_conv(val):
|
||||
"""Convert an actual percentage (0.0-1.0) to 0-100 scale."""
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
"""Test the nexia config flow."""
|
||||
from requests.exceptions import ConnectTimeout
|
||||
from requests.exceptions import ConnectTimeout, HTTPError
|
||||
|
||||
from homeassistant import config_entries, setup
|
||||
from homeassistant.components.nexia.const import DOMAIN
|
||||
|
@ -80,6 +80,67 @@ async def test_form_cannot_connect(hass):
|
|||
assert result2["errors"] == {"base": "cannot_connect"}
|
||||
|
||||
|
||||
async def test_form_invalid_auth_http_401(hass):
|
||||
"""Test we handle invalid auth error from http 401."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
response_mock = MagicMock()
|
||||
type(response_mock).status_code = 401
|
||||
with patch(
|
||||
"homeassistant.components.nexia.config_flow.NexiaHome.login",
|
||||
side_effect=HTTPError(response=response_mock),
|
||||
):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{CONF_USERNAME: "username", CONF_PASSWORD: "password"},
|
||||
)
|
||||
|
||||
assert result2["type"] == "form"
|
||||
assert result2["errors"] == {"base": "invalid_auth"}
|
||||
|
||||
|
||||
async def test_form_cannot_connect_not_found(hass):
|
||||
"""Test we handle cannot connect from an http not found error."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
response_mock = MagicMock()
|
||||
type(response_mock).status_code = 404
|
||||
with patch(
|
||||
"homeassistant.components.nexia.config_flow.NexiaHome.login",
|
||||
side_effect=HTTPError(response=response_mock),
|
||||
):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{CONF_USERNAME: "username", CONF_PASSWORD: "password"},
|
||||
)
|
||||
|
||||
assert result2["type"] == "form"
|
||||
assert result2["errors"] == {"base": "cannot_connect"}
|
||||
|
||||
|
||||
async def test_form_broad_exception(hass):
|
||||
"""Test we handle invalid auth error."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.nexia.config_flow.NexiaHome.login",
|
||||
side_effect=ValueError,
|
||||
):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{CONF_USERNAME: "username", CONF_PASSWORD: "password"},
|
||||
)
|
||||
|
||||
assert result2["type"] == "form"
|
||||
assert result2["errors"] == {"base": "unknown"}
|
||||
|
||||
|
||||
async def test_form_import(hass):
|
||||
"""Test we get the form with import source."""
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
"""The sensor tests for the nexia platform."""
|
||||
|
||||
|
||||
from homeassistant.components.nexia import util
|
||||
from homeassistant.const import HTTP_FORBIDDEN, HTTP_NOT_FOUND, HTTP_UNAUTHORIZED
|
||||
|
||||
|
||||
async def test_is_invalid_auth_code():
|
||||
"""Test for invalid auth."""
|
||||
|
||||
assert util.is_invalid_auth_code(HTTP_UNAUTHORIZED) is True
|
||||
assert util.is_invalid_auth_code(HTTP_FORBIDDEN) is True
|
||||
assert util.is_invalid_auth_code(HTTP_NOT_FOUND) is False
|
||||
|
||||
|
||||
async def test_percent_conv():
|
||||
"""Test percentage conversion."""
|
||||
|
||||
assert util.percent_conv(0.12) == 12.0
|
||||
assert util.percent_conv(0.123) == 12.3
|
Loading…
Reference in New Issue