Check for incompatible special chars in Reolink password (#122461)

This commit is contained in:
starkillerOG 2024-07-23 15:22:23 +02:00 committed by GitHub
parent 156a2427ff
commit b46b74df90
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 48 additions and 7 deletions

View File

@ -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 (

View File

@ -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"

View File

@ -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."""

View File

@ -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:

View File

@ -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}"
},

View File

@ -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"],