diff --git a/homeassistant/components/reolink/host.py b/homeassistant/components/reolink/host.py index 983ab293f69..73c0e70812c 100644 --- a/homeassistant/components/reolink/host.py +++ b/homeassistant/components/reolink/host.py @@ -14,6 +14,7 @@ from reolink_aio.exceptions import ReolinkError, SubscriptionError from homeassistant.components import webhook from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME from homeassistant.core import HomeAssistant +from homeassistant.helpers import issue_registry as ir from homeassistant.helpers.device_registry import format_mac from homeassistant.helpers.dispatcher import async_dispatcher_send from homeassistant.helpers.network import NoURLAvailableError, get_url @@ -273,6 +274,22 @@ class ReolinkHost: webhook_path = webhook.async_generate_path(event_id) self._webhook_url = f"{base_url}{webhook_path}" + if base_url.startswith("https"): + ir.async_create_issue( + self._hass, + DOMAIN, + "https_webhook", + is_fixable=False, + severity=ir.IssueSeverity.WARNING, + translation_key="https_webhook", + translation_placeholders={ + "base_url": base_url, + "network_link": "https://my.home-assistant.io/redirect/network/", + }, + ) + else: + ir.async_delete_issue(self._hass, DOMAIN, "https_webhook") + _LOGGER.debug("Registered webhook: %s", event_id) def unregister_webhook(self): diff --git a/homeassistant/components/reolink/strings.json b/homeassistant/components/reolink/strings.json index 8cd78e2ed7b..cc609488762 100644 --- a/homeassistant/components/reolink/strings.json +++ b/homeassistant/components/reolink/strings.json @@ -37,5 +37,11 @@ } } } + }, + "issues": { + "https_webhook": { + "title": "Reolink webhook URL uses HTTPS (SSL)", + "description": "Reolink products can not push motion events to an HTTPS address (SSL), please configure a (local) HTTP address under \"Home Assistant URL\" in the [network settings]({network_link}). The current (local) address is: `{base_url}`" + } } } diff --git a/tests/components/reolink/test_config_flow.py b/tests/components/reolink/test_config_flow.py index fb40463057a..10391c32067 100644 --- a/tests/components/reolink/test_config_flow.py +++ b/tests/components/reolink/test_config_flow.py @@ -9,8 +9,10 @@ from homeassistant import config_entries, data_entry_flow from homeassistant.components import dhcp from homeassistant.components.reolink import const from homeassistant.components.reolink.config_flow import DEFAULT_PROTOCOL +from homeassistant.config import async_process_ha_core_config from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME from homeassistant.core import HomeAssistant +from homeassistant.helpers import issue_registry as ir from homeassistant.helpers.device_registry import format_mac from tests.common import MockConfigEntry @@ -45,6 +47,9 @@ def get_mock_info(error=None, user_level="admin"): host_mock.use_https = TEST_USE_HTTPS host_mock.is_admin = user_level == "admin" host_mock.user_level = user_level + host_mock.timeout = 60 + host_mock.renewtimer = 600 + host_mock.get_states = AsyncMock(return_value=None) return host_mock @@ -52,8 +57,9 @@ def get_mock_info(error=None, user_level="admin"): def reolink_connect_fixture(mock_get_source_ip): """Mock reolink connection and entry setup.""" with patch( - "homeassistant.components.reolink.async_setup_entry", return_value=True - ), patch( + "homeassistant.components.reolink.host.webhook.async_register", + return_value=True, + ), patch("homeassistant.components.reolink.PLATFORMS", return_value=[]), patch( "homeassistant.components.reolink.host.Host", return_value=get_mock_info() ): yield @@ -415,3 +421,63 @@ async def test_dhcp_abort_flow(hass: HomeAssistant) -> None: assert result["type"] is data_entry_flow.FlowResultType.ABORT assert result["reason"] == "already_configured" + + +async def test_http_no_repair_issue(hass: HomeAssistant) -> None: + """Test no repairs issue is raised when http local url is used.""" + config_entry = MockConfigEntry( + domain=const.DOMAIN, + unique_id=format_mac(TEST_MAC), + data={ + CONF_HOST: TEST_HOST, + CONF_USERNAME: TEST_USERNAME, + CONF_PASSWORD: TEST_PASSWORD, + CONF_PORT: TEST_PORT, + const.CONF_USE_HTTPS: TEST_USE_HTTPS, + }, + options={ + const.CONF_PROTOCOL: DEFAULT_PROTOCOL, + }, + title=TEST_NVR_NAME, + ) + config_entry.add_to_hass(hass) + + await async_process_ha_core_config( + hass, {"country": "GB", "internal_url": "http://test_homeassistant_address"} + ) + + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + issue_registry = ir.async_get(hass) + assert len(issue_registry.issues) == 0 + + +async def test_https_repair_issue(hass: HomeAssistant) -> None: + """Test repairs issue is raised when https local url is used.""" + config_entry = MockConfigEntry( + domain=const.DOMAIN, + unique_id=format_mac(TEST_MAC), + data={ + CONF_HOST: TEST_HOST, + CONF_USERNAME: TEST_USERNAME, + CONF_PASSWORD: TEST_PASSWORD, + CONF_PORT: TEST_PORT, + const.CONF_USE_HTTPS: TEST_USE_HTTPS, + }, + options={ + const.CONF_PROTOCOL: DEFAULT_PROTOCOL, + }, + title=TEST_NVR_NAME, + ) + config_entry.add_to_hass(hass) + + await async_process_ha_core_config( + hass, {"country": "GB", "internal_url": "https://test_homeassistant_address"} + ) + + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + issue_registry = ir.async_get(hass) + assert len(issue_registry.issues) == 1