mirror of
https://github.com/home-assistant/core.git
synced 2025-07-07 21:37:07 +00:00
Ask for permission to disable Reolink privacy mode during config flow (#136511)
This commit is contained in:
parent
439a393816
commit
f1dfae6937
@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Mapping
|
||||
import logging
|
||||
from typing import Any
|
||||
@ -11,6 +12,7 @@ from reolink_aio.exceptions import (
|
||||
ApiError,
|
||||
CredentialsInvalidError,
|
||||
LoginFirmwareError,
|
||||
LoginPrivacyModeError,
|
||||
ReolinkError,
|
||||
)
|
||||
import voluptuous as vol
|
||||
@ -49,6 +51,7 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_PROTOCOL = "rtsp"
|
||||
DEFAULT_OPTIONS = {CONF_PROTOCOL: DEFAULT_PROTOCOL}
|
||||
API_STARTUP_TIME = 5
|
||||
|
||||
|
||||
class ReolinkOptionsFlowHandler(OptionsFlow):
|
||||
@ -101,6 +104,8 @@ class ReolinkFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
self._host: str | None = None
|
||||
self._username: str = "admin"
|
||||
self._password: str | None = None
|
||||
self._user_input: dict[str, Any] | None = None
|
||||
self._disable_privacy: bool = False
|
||||
|
||||
@staticmethod
|
||||
@callback
|
||||
@ -198,6 +203,21 @@ class ReolinkFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
self._host = discovery_info.ip
|
||||
return await self.async_step_user()
|
||||
|
||||
async def async_step_privacy(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
"""Ask permission to disable privacy mode."""
|
||||
if user_input is not None:
|
||||
self._disable_privacy = True
|
||||
return await self.async_step_user(self._user_input)
|
||||
|
||||
assert self._user_input is not None
|
||||
placeholders = {"host": self._user_input[CONF_HOST]}
|
||||
return self.async_show_form(
|
||||
step_id="privacy",
|
||||
description_placeholders=placeholders,
|
||||
)
|
||||
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
@ -219,6 +239,10 @@ class ReolinkFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
|
||||
host = ReolinkHost(self.hass, user_input, DEFAULT_OPTIONS)
|
||||
try:
|
||||
if self._disable_privacy:
|
||||
await host.api.baichuan.set_privacy_mode(enable=False)
|
||||
# give the camera some time to startup the HTTP API server
|
||||
await asyncio.sleep(API_STARTUP_TIME)
|
||||
await host.async_init()
|
||||
except UserNotAdmin:
|
||||
errors[CONF_USERNAME] = "not_admin"
|
||||
@ -227,6 +251,9 @@ class ReolinkFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
except PasswordIncompatible:
|
||||
errors[CONF_PASSWORD] = "password_incompatible"
|
||||
placeholders["special_chars"] = ALLOWED_SPECIAL_CHARS
|
||||
except LoginPrivacyModeError:
|
||||
self._user_input = user_input
|
||||
return await self.async_step_privacy()
|
||||
except CredentialsInvalidError:
|
||||
errors[CONF_PASSWORD] = "invalid_auth"
|
||||
except LoginFirmwareError:
|
||||
|
@ -18,6 +18,10 @@
|
||||
"username": "Username to login to the Reolink device itself. Not the Reolink cloud account.",
|
||||
"password": "Password to login to the Reolink device itself. Not the Reolink cloud account."
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Permission to disable Reolink privacy mode",
|
||||
"description": "Privacy mode is enabled on Reolink device {host}. By pressing SUBMIT, the privacy mode will be disabled to retrieve the necessary information from the Reolink device. You can abort the setup by pressing X and repeat the setup at a time in which privacy mode can be disabled. After this configuration, you are free to enable the privacy mode again using the privacy mode switch entity. During normal startup the privacy mode will not be disabled. Note however that all entities will be marked unavailable as long as the privacy mode is active."
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
import json
|
||||
from typing import Any
|
||||
from unittest.mock import ANY, AsyncMock, MagicMock, call
|
||||
from unittest.mock import ANY, AsyncMock, MagicMock, call, patch
|
||||
|
||||
from aiohttp import ClientSession
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
@ -11,6 +11,7 @@ from reolink_aio.exceptions import (
|
||||
ApiError,
|
||||
CredentialsInvalidError,
|
||||
LoginFirmwareError,
|
||||
LoginPrivacyModeError,
|
||||
ReolinkError,
|
||||
)
|
||||
|
||||
@ -88,6 +89,59 @@ async def test_config_flow_manual_success(
|
||||
assert result["result"].unique_id == TEST_MAC
|
||||
|
||||
|
||||
async def test_config_flow_privacy_success(
|
||||
hass: HomeAssistant, reolink_connect: MagicMock, mock_setup_entry: MagicMock
|
||||
) -> None:
|
||||
"""Successful flow when privacy mode is turned on."""
|
||||
reolink_connect.baichuan.privacy_mode.return_value = True
|
||||
reolink_connect.get_host_data.side_effect = LoginPrivacyModeError("Test error")
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {}
|
||||
|
||||
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"] == "privacy"
|
||||
assert result["errors"] is None
|
||||
|
||||
assert reolink_connect.baichuan.set_privacy_mode.call_count == 0
|
||||
reolink_connect.get_host_data.reset_mock(side_effect=True)
|
||||
|
||||
with patch("homeassistant.components.reolink.config_flow.API_STARTUP_TIME", new=0):
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
||||
|
||||
assert reolink_connect.baichuan.set_privacy_mode.call_count == 1
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == TEST_NVR_NAME
|
||||
assert result["data"] == {
|
||||
CONF_HOST: TEST_HOST,
|
||||
CONF_USERNAME: TEST_USERNAME,
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
CONF_PORT: TEST_PORT,
|
||||
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||
}
|
||||
assert result["options"] == {
|
||||
CONF_PROTOCOL: DEFAULT_PROTOCOL,
|
||||
}
|
||||
assert result["result"].unique_id == TEST_MAC
|
||||
|
||||
reolink_connect.baichuan.privacy_mode.return_value = False
|
||||
|
||||
|
||||
async def test_config_flow_errors(
|
||||
hass: HomeAssistant, reolink_connect: MagicMock, mock_setup_entry: MagicMock
|
||||
) -> None:
|
||||
|
Loading…
x
Reference in New Issue
Block a user