From 2c0c386ba7ba5b0451d6a7c876c5edfcae0513a3 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Fri, 3 Feb 2023 03:13:53 +0100 Subject: [PATCH] Reduce required permissions for fritzbox_callmonitor (#87089) * Test new FritzAuthorizationError * Reduce required permissions --- .../fritzbox_callmonitor/config_flow.py | 7 ++- .../components/fritzbox_callmonitor/const.py | 2 +- .../fritzbox_callmonitor/test_config_flow.py | 45 +++++++++++++------ 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/homeassistant/components/fritzbox_callmonitor/config_flow.py b/homeassistant/components/fritzbox_callmonitor/config_flow.py index 982d888d22a..f7ce25c2ebe 100644 --- a/homeassistant/components/fritzbox_callmonitor/config_flow.py +++ b/homeassistant/components/fritzbox_callmonitor/config_flow.py @@ -5,7 +5,6 @@ from typing import Any, cast from fritzconnection import FritzConnection from fritzconnection.core.exceptions import FritzConnectionException, FritzSecurityError -from fritzconnection.lib.fritzstatus import FritzStatus from requests.exceptions import ConnectionError as RequestsConnectionError import voluptuous as vol @@ -31,6 +30,7 @@ from .const import ( DEFAULT_USERNAME, DOMAIN, FRITZ_ATTR_NAME, + FRITZ_ATTR_SERIAL_NUMBER, SERIAL_NUMBER, ) @@ -102,9 +102,8 @@ class FritzBoxCallMonitorConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): fritz_connection = FritzConnection( address=self._host, user=self._username, password=self._password ) - fritz_status = FritzStatus(fc=fritz_connection) - device_info = fritz_status.get_device_info() - self._serial_number = device_info.serial_number + info = fritz_connection.updatecheck + self._serial_number = info[FRITZ_ATTR_SERIAL_NUMBER] return ConnectResult.SUCCESS except RequestsConnectionError: diff --git a/homeassistant/components/fritzbox_callmonitor/const.py b/homeassistant/components/fritzbox_callmonitor/const.py index ccc5a45e61f..4f224660ae9 100644 --- a/homeassistant/components/fritzbox_callmonitor/const.py +++ b/homeassistant/components/fritzbox_callmonitor/const.py @@ -19,7 +19,7 @@ ICON_PHONE: Final = "mdi:phone" ATTR_PREFIXES = "prefixes" FRITZ_ATTR_NAME = "name" -FRITZ_ATTR_SERIAL_NUMBER = "NewSerialNumber" +FRITZ_ATTR_SERIAL_NUMBER = "Serial" UNKNOWN_NAME = "unknown" SERIAL_NUMBER = "serial_number" diff --git a/tests/components/fritzbox_callmonitor/test_config_flow.py b/tests/components/fritzbox_callmonitor/test_config_flow.py index 2aa68af0758..386151c31b1 100644 --- a/tests/components/fritzbox_callmonitor/test_config_flow.py +++ b/tests/components/fritzbox_callmonitor/test_config_flow.py @@ -1,8 +1,14 @@ """Tests for fritzbox_callmonitor config flow.""" +from __future__ import annotations + from unittest.mock import PropertyMock -from fritzconnection.core.exceptions import FritzConnectionException, FritzSecurityError -from fritzconnection.lib.fritztools import ArgumentNamespace +from fritzconnection.core.exceptions import ( + FritzAuthorizationError, + FritzConnectionException, + FritzSecurityError, +) +import pytest from requests.exceptions import ConnectionError as RequestsConnectionError from homeassistant.components.fritzbox_callmonitor.config_flow import ConnectResult @@ -11,7 +17,6 @@ from homeassistant.components.fritzbox_callmonitor.const import ( CONF_PREFIXES, DOMAIN, FRITZ_ATTR_NAME, - FRITZ_ATTR_SERIAL_NUMBER, SERIAL_NUMBER, ) from homeassistant.config_entries import SOURCE_USER @@ -59,7 +64,20 @@ MOCK_YAML_CONFIG = { CONF_PHONEBOOK: MOCK_PHONEBOOK_ID, CONF_NAME: MOCK_NAME, } -MOCK_DEVICE_INFO = ArgumentNamespace({FRITZ_ATTR_SERIAL_NUMBER: MOCK_SERIAL_NUMBER}) +MOCK_DEVICE_INFO = { + "Name": "FRITZ!Box 7590", + "HW": "226", + "Version": "100.01.01", + "Revision": "10000", + "Serial": MOCK_SERIAL_NUMBER, + "OEM": "avm", + "Lang": "de", + "Annex": "B", + "Lab": None, + "Country": "049", + "Flag": "mesh_master", + "UpdateConfig": "2", +} MOCK_PHONEBOOK_INFO_1 = {FRITZ_ATTR_NAME: MOCK_PHONEBOOK_NAME_1} MOCK_PHONEBOOK_INFO_2 = {FRITZ_ATTR_NAME: MOCK_PHONEBOOK_NAME_2} MOCK_UNIQUE_ID = f"{MOCK_SERIAL_NUMBER}-{MOCK_PHONEBOOK_ID}" @@ -91,10 +109,8 @@ async def test_setup_one_phonebook(hass: HomeAssistant) -> None: "homeassistant.components.fritzbox_callmonitor.config_flow.FritzConnection.__init__", return_value=None, ), patch( - "homeassistant.components.fritzbox_callmonitor.config_flow.FritzStatus.__init__", - return_value=None, - ), patch( - "homeassistant.components.fritzbox_callmonitor.config_flow.FritzStatus.get_device_info", + "homeassistant.components.fritzbox_callmonitor.config_flow.FritzConnection.updatecheck", + new_callable=PropertyMock, return_value=MOCK_DEVICE_INFO, ), patch( "homeassistant.components.fritzbox_callmonitor.async_setup_entry", @@ -130,10 +146,8 @@ async def test_setup_multiple_phonebooks(hass: HomeAssistant) -> None: "homeassistant.components.fritzbox_callmonitor.config_flow.FritzConnection.__init__", return_value=None, ), patch( - "homeassistant.components.fritzbox_callmonitor.config_flow.FritzStatus.__init__", - return_value=None, - ), patch( - "homeassistant.components.fritzbox_callmonitor.config_flow.FritzStatus.get_device_info", + "homeassistant.components.fritzbox_callmonitor.config_flow.FritzConnection.updatecheck", + new_callable=PropertyMock, return_value=MOCK_DEVICE_INFO, ), patch( "homeassistant.components.fritzbox_callmonitor.base.FritzPhonebook.phonebook_info", @@ -210,7 +224,10 @@ async def test_setup_insufficient_permissions(hass: HomeAssistant) -> None: assert result["reason"] == ConnectResult.INSUFFICIENT_PERMISSIONS -async def test_setup_invalid_auth(hass: HomeAssistant) -> None: +@pytest.mark.parametrize("error", [FritzAuthorizationError, FritzConnectionException]) +async def test_setup_invalid_auth( + hass: HomeAssistant, error: FritzConnectionException +) -> None: """Test we handle invalid auth.""" result = await hass.config_entries.flow.async_init( DOMAIN, @@ -219,7 +236,7 @@ async def test_setup_invalid_auth(hass: HomeAssistant) -> None: with patch( "homeassistant.components.fritzbox_callmonitor.base.FritzPhonebook.__init__", - side_effect=FritzConnectionException, + side_effect=error, ): result = await hass.config_entries.flow.async_configure( result["flow_id"], user_input=MOCK_USER_DATA