mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 01:38:02 +00:00
Check for incompatible special chars in Reolink password (#122461)
This commit is contained in:
parent
156a2427ff
commit
b46b74df90
@ -19,7 +19,7 @@ from homeassistant.helpers.device_registry import format_mac
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
from .const import DOMAIN
|
||||
from .exceptions import ReolinkException, UserNotAdmin
|
||||
from .exceptions import PasswordIncompatible, ReolinkException, UserNotAdmin
|
||||
from .host import ReolinkHost
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -56,7 +56,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
||||
|
||||
try:
|
||||
await host.async_init()
|
||||
except (UserNotAdmin, CredentialsInvalidError) as err:
|
||||
except (UserNotAdmin, CredentialsInvalidError, PasswordIncompatible) as err:
|
||||
await host.stop()
|
||||
raise ConfigEntryAuthFailed(err) from err
|
||||
except (
|
||||
|
@ -6,6 +6,7 @@ from collections.abc import Mapping
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from reolink_aio.api import ALLOWED_SPECIAL_CHARS
|
||||
from reolink_aio.exceptions import ApiError, CredentialsInvalidError, ReolinkError
|
||||
import voluptuous as vol
|
||||
|
||||
@ -29,7 +30,12 @@ from homeassistant.helpers import config_validation as cv, selector
|
||||
from homeassistant.helpers.device_registry import format_mac
|
||||
|
||||
from .const import CONF_USE_HTTPS, DOMAIN
|
||||
from .exceptions import ReolinkException, ReolinkWebhookException, UserNotAdmin
|
||||
from .exceptions import (
|
||||
PasswordIncompatible,
|
||||
ReolinkException,
|
||||
ReolinkWebhookException,
|
||||
UserNotAdmin,
|
||||
)
|
||||
from .host import ReolinkHost
|
||||
from .util import is_connected
|
||||
|
||||
@ -206,8 +212,11 @@ class ReolinkFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
errors[CONF_USERNAME] = "not_admin"
|
||||
placeholders["username"] = host.api.username
|
||||
placeholders["userlevel"] = host.api.user_level
|
||||
except PasswordIncompatible:
|
||||
errors[CONF_PASSWORD] = "password_incompatible"
|
||||
placeholders["special_chars"] = ALLOWED_SPECIAL_CHARS
|
||||
except CredentialsInvalidError:
|
||||
errors[CONF_HOST] = "invalid_auth"
|
||||
errors[CONF_PASSWORD] = "invalid_auth"
|
||||
except ApiError as err:
|
||||
placeholders["error"] = str(err)
|
||||
errors[CONF_HOST] = "api_error"
|
||||
|
@ -17,3 +17,7 @@ class ReolinkWebhookException(ReolinkException):
|
||||
|
||||
class UserNotAdmin(ReolinkException):
|
||||
"""Raised when user is not admin."""
|
||||
|
||||
|
||||
class PasswordIncompatible(ReolinkException):
|
||||
"""Raised when the password contains special chars that are incompatible."""
|
||||
|
@ -11,7 +11,7 @@ from typing import Any, Literal
|
||||
|
||||
import aiohttp
|
||||
from aiohttp.web import Request
|
||||
from reolink_aio.api import Host
|
||||
from reolink_aio.api import ALLOWED_SPECIAL_CHARS, Host
|
||||
from reolink_aio.enums import SubType
|
||||
from reolink_aio.exceptions import NotSupportedError, ReolinkError, SubscriptionError
|
||||
|
||||
@ -31,7 +31,12 @@ from homeassistant.helpers.event import async_call_later
|
||||
from homeassistant.helpers.network import NoURLAvailableError, get_url
|
||||
|
||||
from .const import CONF_USE_HTTPS, DOMAIN
|
||||
from .exceptions import ReolinkSetupException, ReolinkWebhookException, UserNotAdmin
|
||||
from .exceptions import (
|
||||
PasswordIncompatible,
|
||||
ReolinkSetupException,
|
||||
ReolinkWebhookException,
|
||||
UserNotAdmin,
|
||||
)
|
||||
|
||||
DEFAULT_TIMEOUT = 30
|
||||
FIRST_ONVIF_TIMEOUT = 10
|
||||
@ -123,6 +128,13 @@ class ReolinkHost:
|
||||
|
||||
async def async_init(self) -> None:
|
||||
"""Connect to Reolink host."""
|
||||
if not self._api.valid_password():
|
||||
raise PasswordIncompatible(
|
||||
"Reolink password contains incompatible special character, "
|
||||
"please change the password to only contain characters: "
|
||||
f"a-z, A-Z, 0-9 or {ALLOWED_SPECIAL_CHARS}"
|
||||
)
|
||||
|
||||
await self._api.get_host_data()
|
||||
|
||||
if self._api.mac_address is None:
|
||||
|
@ -29,6 +29,7 @@
|
||||
"cannot_connect": "Failed to connect, check the IP address of the camera",
|
||||
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
|
||||
"not_admin": "User needs to be admin, user \"{username}\" has authorisation level \"{userlevel}\"",
|
||||
"password_incompatible": "Password contains incompatible special character, only these characters are allowed: a-z, A-Z, 0-9 or {special_chars}",
|
||||
"unknown": "[%key:common::config_flow::error::unknown%]",
|
||||
"webhook_exception": "Home Assistant URL is not available, go to Settings > System > Network > Home Assistant URL and correct the URLs, see {more_info}"
|
||||
},
|
||||
|
@ -166,8 +166,23 @@ async def test_config_flow_errors(
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {CONF_HOST: "invalid_auth"}
|
||||
assert result["errors"] == {CONF_PASSWORD: "invalid_auth"}
|
||||
|
||||
reolink_connect.valid_password.return_value = False
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_USERNAME: TEST_USERNAME,
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
CONF_HOST: TEST_HOST,
|
||||
},
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {CONF_PASSWORD: "password_incompatible"}
|
||||
|
||||
reolink_connect.valid_password.return_value = True
|
||||
reolink_connect.get_host_data.side_effect = ApiError("Test error")
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
|
Loading…
x
Reference in New Issue
Block a user