mirror of
https://github.com/home-assistant/core.git
synced 2025-04-26 10:17:51 +00:00
Bump reolink-aio to 0.12.3 (#140789)
* Add password length restriction * Bump reolink-aio to 0.12.3 * Add repair issue for too long password * finish password too long repair issue * add test
This commit is contained in:
parent
d3c40939f6
commit
a20601a1f0
@ -67,9 +67,7 @@ async def async_setup_entry(
|
|||||||
hass: HomeAssistant, config_entry: ReolinkConfigEntry
|
hass: HomeAssistant, config_entry: ReolinkConfigEntry
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Set up Reolink from a config entry."""
|
"""Set up Reolink from a config entry."""
|
||||||
host = ReolinkHost(
|
host = ReolinkHost(hass, config_entry.data, config_entry.options, config_entry)
|
||||||
hass, config_entry.data, config_entry.options, config_entry.entry_id
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await host.async_init()
|
await host.async_init()
|
||||||
|
@ -41,7 +41,7 @@ from .exceptions import (
|
|||||||
ReolinkWebhookException,
|
ReolinkWebhookException,
|
||||||
UserNotAdmin,
|
UserNotAdmin,
|
||||||
)
|
)
|
||||||
from .util import get_store
|
from .util import ReolinkConfigEntry, get_store
|
||||||
|
|
||||||
DEFAULT_TIMEOUT = 30
|
DEFAULT_TIMEOUT = 30
|
||||||
FIRST_TCP_PUSH_TIMEOUT = 10
|
FIRST_TCP_PUSH_TIMEOUT = 10
|
||||||
@ -67,11 +67,11 @@ class ReolinkHost:
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config: Mapping[str, Any],
|
config: Mapping[str, Any],
|
||||||
options: Mapping[str, Any],
|
options: Mapping[str, Any],
|
||||||
config_entry_id: str | None = None,
|
config_entry: ReolinkConfigEntry | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize Reolink Host. Could be either NVR, or Camera."""
|
"""Initialize Reolink Host. Could be either NVR, or Camera."""
|
||||||
self._hass: HomeAssistant = hass
|
self._hass: HomeAssistant = hass
|
||||||
self._config_entry_id = config_entry_id
|
self._config_entry = config_entry
|
||||||
self._config = config
|
self._config = config
|
||||||
self._unique_id: str = ""
|
self._unique_id: str = ""
|
||||||
|
|
||||||
@ -151,15 +151,33 @@ class ReolinkHost:
|
|||||||
async def async_init(self) -> None:
|
async def async_init(self) -> None:
|
||||||
"""Connect to Reolink host."""
|
"""Connect to Reolink host."""
|
||||||
if not self._api.valid_password():
|
if not self._api.valid_password():
|
||||||
|
if (
|
||||||
|
len(self._config[CONF_PASSWORD]) >= 32
|
||||||
|
and self._config_entry is not None
|
||||||
|
):
|
||||||
|
ir.async_create_issue(
|
||||||
|
self._hass,
|
||||||
|
DOMAIN,
|
||||||
|
f"password_too_long_{self._config_entry.entry_id}",
|
||||||
|
is_fixable=True,
|
||||||
|
severity=ir.IssueSeverity.ERROR,
|
||||||
|
translation_key="password_too_long",
|
||||||
|
translation_placeholders={"name": self._config_entry.title},
|
||||||
|
)
|
||||||
|
|
||||||
raise PasswordIncompatible(
|
raise PasswordIncompatible(
|
||||||
"Reolink password contains incompatible special character, "
|
"Reolink password contains incompatible special character or "
|
||||||
"please change the password to only contain characters: "
|
"is too long, please change the password to only contain characters: "
|
||||||
f"a-z, A-Z, 0-9 or {ALLOWED_SPECIAL_CHARS}"
|
f"a-z, A-Z, 0-9 or {ALLOWED_SPECIAL_CHARS} "
|
||||||
|
"and not be longer than 31 characters"
|
||||||
)
|
)
|
||||||
|
|
||||||
store: Store[str] | None = None
|
store: Store[str] | None = None
|
||||||
if self._config_entry_id is not None:
|
if self._config_entry is not None:
|
||||||
store = get_store(self._hass, self._config_entry_id)
|
ir.async_delete_issue(
|
||||||
|
self._hass, DOMAIN, f"password_too_long_{self._config_entry.entry_id}"
|
||||||
|
)
|
||||||
|
store = get_store(self._hass, self._config_entry.entry_id)
|
||||||
if self._config.get(CONF_SUPPORTS_PRIVACY_MODE) and (
|
if self._config.get(CONF_SUPPORTS_PRIVACY_MODE) and (
|
||||||
data := await store.async_load()
|
data := await store.async_load()
|
||||||
):
|
):
|
||||||
|
@ -19,5 +19,5 @@
|
|||||||
"iot_class": "local_push",
|
"iot_class": "local_push",
|
||||||
"loggers": ["reolink_aio"],
|
"loggers": ["reolink_aio"],
|
||||||
"quality_scale": "platinum",
|
"quality_scale": "platinum",
|
||||||
"requirements": ["reolink-aio==0.12.3b1"]
|
"requirements": ["reolink-aio==0.12.3"]
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
"cannot_connect": "Failed to connect, check the IP address of the camera",
|
"cannot_connect": "Failed to connect, check the IP address of the camera",
|
||||||
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
|
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
|
||||||
"not_admin": "User needs to be admin, user \"{username}\" has authorisation level \"{userlevel}\"",
|
"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}",
|
"password_incompatible": "Password contains incompatible special character or is too long, maximum 31 characters and only these characters are allowed: a-z, A-Z, 0-9 or {special_chars}",
|
||||||
"unknown": "[%key:common::config_flow::error::unknown%]",
|
"unknown": "[%key:common::config_flow::error::unknown%]",
|
||||||
"update_needed": "Failed to login because of outdated firmware, please update the firmware to version {needed_firmware} using the Reolink Download Center: {download_center_url}, currently version {current_firmware} is installed",
|
"update_needed": "Failed to login because of outdated firmware, please update the firmware to version {needed_firmware} using the Reolink Download Center: {download_center_url}, currently version {current_firmware} is installed",
|
||||||
"webhook_exception": "Home Assistant URL is not available, go to Settings > System > Network > Home Assistant URL and correct the URLs, see {more_info}"
|
"webhook_exception": "Home Assistant URL is not available, go to Settings > System > Network > Home Assistant URL and correct the URLs, see {more_info}"
|
||||||
@ -129,6 +129,10 @@
|
|||||||
"hub_switch_deprecated": {
|
"hub_switch_deprecated": {
|
||||||
"title": "Reolink Home Hub switches deprecated",
|
"title": "Reolink Home Hub switches deprecated",
|
||||||
"description": "The redundant 'Record', 'Email on event', 'FTP upload', 'Push notifications', and 'Buzzer on event' switches on the Reolink Home Hub are deprecated since the new firmware no longer supports these. Please use the equally named switches under each of the camera devices connected to the Home Hub instead. To remove this issue, please adjust automations accordingly and disable the switch entities mentioned."
|
"description": "The redundant 'Record', 'Email on event', 'FTP upload', 'Push notifications', and 'Buzzer on event' switches on the Reolink Home Hub are deprecated since the new firmware no longer supports these. Please use the equally named switches under each of the camera devices connected to the Home Hub instead. To remove this issue, please adjust automations accordingly and disable the switch entities mentioned."
|
||||||
|
},
|
||||||
|
"password_too_long": {
|
||||||
|
"title": "Reolink password too long",
|
||||||
|
"description": "The password for \"{name}\" is more than 31 characters long, this is no longer compatible with the Reolink API. Please change the password using the Reolink app/client to a password with is shorter than 32 characters. After changing the password, fill in the new password in the Reolink Re-authentication flow to continue using this integration. The latest version of the Reolink app/client also has a password limit of 31 characters."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"services": {
|
"services": {
|
||||||
|
2
requirements_all.txt
generated
2
requirements_all.txt
generated
@ -2622,7 +2622,7 @@ renault-api==0.2.9
|
|||||||
renson-endura-delta==1.7.2
|
renson-endura-delta==1.7.2
|
||||||
|
|
||||||
# homeassistant.components.reolink
|
# homeassistant.components.reolink
|
||||||
reolink-aio==0.12.3b1
|
reolink-aio==0.12.3
|
||||||
|
|
||||||
# homeassistant.components.idteck_prox
|
# homeassistant.components.idteck_prox
|
||||||
rfk101py==0.0.1
|
rfk101py==0.0.1
|
||||||
|
2
requirements_test_all.txt
generated
2
requirements_test_all.txt
generated
@ -2122,7 +2122,7 @@ renault-api==0.2.9
|
|||||||
renson-endura-delta==1.7.2
|
renson-endura-delta==1.7.2
|
||||||
|
|
||||||
# homeassistant.components.reolink
|
# homeassistant.components.reolink
|
||||||
reolink-aio==0.12.3b1
|
reolink-aio==0.12.3
|
||||||
|
|
||||||
# homeassistant.components.rflink
|
# homeassistant.components.rflink
|
||||||
rflink==0.0.66
|
rflink==0.0.66
|
||||||
|
@ -22,7 +22,11 @@ from homeassistant.components.reolink import (
|
|||||||
from homeassistant.components.reolink.const import CONF_BC_PORT, DOMAIN
|
from homeassistant.components.reolink.const import CONF_BC_PORT, DOMAIN
|
||||||
from homeassistant.config_entries import ConfigEntryState
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
|
CONF_HOST,
|
||||||
|
CONF_PASSWORD,
|
||||||
CONF_PORT,
|
CONF_PORT,
|
||||||
|
CONF_PROTOCOL,
|
||||||
|
CONF_USERNAME,
|
||||||
STATE_OFF,
|
STATE_OFF,
|
||||||
STATE_ON,
|
STATE_ON,
|
||||||
STATE_UNAVAILABLE,
|
STATE_UNAVAILABLE,
|
||||||
@ -35,17 +39,25 @@ from homeassistant.helpers import (
|
|||||||
entity_registry as er,
|
entity_registry as er,
|
||||||
issue_registry as ir,
|
issue_registry as ir,
|
||||||
)
|
)
|
||||||
|
from homeassistant.helpers.device_registry import format_mac
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from .conftest import (
|
from .conftest import (
|
||||||
|
CONF_SUPPORTS_PRIVACY_MODE,
|
||||||
|
CONF_USE_HTTPS,
|
||||||
|
DEFAULT_PROTOCOL,
|
||||||
TEST_BC_PORT,
|
TEST_BC_PORT,
|
||||||
TEST_CAM_MODEL,
|
TEST_CAM_MODEL,
|
||||||
|
TEST_HOST,
|
||||||
TEST_HOST_MODEL,
|
TEST_HOST_MODEL,
|
||||||
TEST_MAC,
|
TEST_MAC,
|
||||||
TEST_NVR_NAME,
|
TEST_NVR_NAME,
|
||||||
TEST_PORT,
|
TEST_PORT,
|
||||||
|
TEST_PRIVACY,
|
||||||
TEST_UID,
|
TEST_UID,
|
||||||
TEST_UID_CAM,
|
TEST_UID_CAM,
|
||||||
|
TEST_USE_HTTPS,
|
||||||
|
TEST_USERNAME,
|
||||||
)
|
)
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||||
@ -723,6 +735,41 @@ async def test_firmware_repair_issue(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert (DOMAIN, "firmware_update_host") in issue_registry.issues
|
assert (DOMAIN, "firmware_update_host") in issue_registry.issues
|
||||||
|
reolink_connect.camera_sw_version_update_required.return_value = False
|
||||||
|
|
||||||
|
|
||||||
|
async def test_password_too_long_repair_issue(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
reolink_connect: MagicMock,
|
||||||
|
issue_registry: ir.IssueRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test password too long issue is raised."""
|
||||||
|
reolink_connect.valid_password.return_value = False
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
unique_id=format_mac(TEST_MAC),
|
||||||
|
data={
|
||||||
|
CONF_HOST: TEST_HOST,
|
||||||
|
CONF_USERNAME: TEST_USERNAME,
|
||||||
|
CONF_PASSWORD: "too_longgggggggggggggggggggggggggggggggggggggggggggggggggg",
|
||||||
|
CONF_PORT: TEST_PORT,
|
||||||
|
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||||
|
CONF_SUPPORTS_PRIVACY_MODE: TEST_PRIVACY,
|
||||||
|
},
|
||||||
|
options={
|
||||||
|
CONF_PROTOCOL: DEFAULT_PROTOCOL,
|
||||||
|
},
|
||||||
|
title=TEST_NVR_NAME,
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
assert not await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert (
|
||||||
|
DOMAIN,
|
||||||
|
f"password_too_long_{config_entry.entry_id}",
|
||||||
|
) in issue_registry.issues
|
||||||
|
reolink_connect.valid_password.return_value = True
|
||||||
|
|
||||||
|
|
||||||
async def test_new_device_discovered(
|
async def test_new_device_discovered(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user