From eb23846cfe5a0c92ef11f9bca28426d1492b4bb3 Mon Sep 17 00:00:00 2001 From: Quentame Date: Mon, 18 Nov 2019 16:47:30 +0100 Subject: [PATCH] Move imports in owntracks component (#27780) * Move imports in owntracks component * Fix nacl import * Fix nacl import 2 * Fix nacl import 3 * Add helper.supports_encryption tests * Fix tests helper 1 * Fix tests 2 * Add not_supports_encryption + get_cipher_error tests * Code cov * Fix nacl_not_imported test --- .../components/owntracks/config_flow.py | 11 +----- homeassistant/components/owntracks/helper.py | 10 ++++++ .../components/owntracks/messages.py | 12 +++++-- .../owntracks/test_device_tracker.py | 35 +++++++++++++++++++ tests/components/owntracks/test_helper.py | 29 +++++++++++++++ 5 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 homeassistant/components/owntracks/helper.py create mode 100644 tests/components/owntracks/test_helper.py diff --git a/homeassistant/components/owntracks/config_flow.py b/homeassistant/components/owntracks/config_flow.py index 5034114293f..ff4a649e0ce 100644 --- a/homeassistant/components/owntracks/config_flow.py +++ b/homeassistant/components/owntracks/config_flow.py @@ -4,21 +4,12 @@ from homeassistant.const import CONF_WEBHOOK_ID from homeassistant.auth.util import generate_secret from .const import DOMAIN # noqa pylint: disable=unused-import +from .helper import supports_encryption CONF_SECRET = "secret" CONF_CLOUDHOOK = "cloudhook" -def supports_encryption(): - """Test if we support encryption.""" - try: - import nacl # noqa: F401 pylint: disable=unused-import - - return True - except OSError: - return False - - class OwnTracksFlow(config_entries.ConfigFlow, domain=DOMAIN): """Set up OwnTracks.""" diff --git a/homeassistant/components/owntracks/helper.py b/homeassistant/components/owntracks/helper.py new file mode 100644 index 00000000000..b6ed307112c --- /dev/null +++ b/homeassistant/components/owntracks/helper.py @@ -0,0 +1,10 @@ +"""Helper for OwnTracks.""" +try: + import nacl +except ImportError: + nacl = None + + +def supports_encryption() -> bool: + """Test if we support encryption.""" + return nacl is not None diff --git a/homeassistant/components/owntracks/messages.py b/homeassistant/components/owntracks/messages.py index 0cb65c774b5..7c388f9eb17 100644 --- a/homeassistant/components/owntracks/messages.py +++ b/homeassistant/components/owntracks/messages.py @@ -2,6 +2,9 @@ import json import logging +from nacl.secret import SecretBox +from nacl.encoding import Base64Encoder + from homeassistant.components import zone as zone_comp from homeassistant.components.device_tracker import ( SOURCE_TYPE_GPS, @@ -11,6 +14,7 @@ from homeassistant.components.device_tracker import ( from homeassistant.const import STATE_HOME from homeassistant.util import decorator, slugify +from .helper import supports_encryption _LOGGER = logging.getLogger(__name__) @@ -22,8 +26,6 @@ def get_cipher(): Async friendly. """ - from nacl.secret import SecretBox - from nacl.encoding import Base64Encoder def decrypt(ciphertext, key): """Decrypt ciphertext using key.""" @@ -105,7 +107,11 @@ def _set_gps_from_zone(kwargs, location, zone): def _decrypt_payload(secret, topic, ciphertext): """Decrypt encrypted payload.""" try: - keylen, decrypt = get_cipher() + if supports_encryption(): + keylen, decrypt = get_cipher() + else: + _LOGGER.warning("Ignoring encrypted payload because nacl not installed") + return None except OSError: _LOGGER.warning("Ignoring encrypted payload because nacl not installed") return None diff --git a/tests/components/owntracks/test_device_tracker.py b/tests/components/owntracks/test_device_tracker.py index 5ba68474513..daef624f9c2 100644 --- a/tests/components/owntracks/test_device_tracker.py +++ b/tests/components/owntracks/test_device_tracker.py @@ -1406,6 +1406,25 @@ def config_context(hass, setup_comp): patch_save.stop() +@pytest.fixture(name="not_supports_encryption") +def mock_not_supports_encryption(): + """Mock non successful nacl import.""" + with patch( + "homeassistant.components.owntracks.messages.supports_encryption", + return_value=False, + ): + yield + + +@pytest.fixture(name="get_cipher_error") +def mock_get_cipher_error(): + """Mock non successful cipher.""" + with patch( + "homeassistant.components.owntracks.messages.get_cipher", side_effect=OSError() + ): + yield + + @patch("homeassistant.components.owntracks.messages.get_cipher", mock_cipher) async def test_encrypted_payload(hass, setup_comp): """Test encrypted payload.""" @@ -1422,6 +1441,22 @@ async def test_encrypted_payload_topic_key(hass, setup_comp): assert_location_latitude(hass, LOCATION_MESSAGE["lat"]) +async def test_encrypted_payload_not_supports_encryption( + hass, setup_comp, not_supports_encryption +): + """Test encrypted payload with no supported encryption.""" + await setup_owntracks(hass, {CONF_SECRET: TEST_SECRET_KEY}) + await send_message(hass, LOCATION_TOPIC, MOCK_ENCRYPTED_LOCATION_MESSAGE) + assert hass.states.get(DEVICE_TRACKER_STATE) is None + + +async def test_encrypted_payload_get_cipher_error(hass, setup_comp, get_cipher_error): + """Test encrypted payload with no supported encryption.""" + await setup_owntracks(hass, {CONF_SECRET: TEST_SECRET_KEY}) + await send_message(hass, LOCATION_TOPIC, MOCK_ENCRYPTED_LOCATION_MESSAGE) + assert hass.states.get(DEVICE_TRACKER_STATE) is None + + @patch("homeassistant.components.owntracks.messages.get_cipher", mock_cipher) async def test_encrypted_payload_no_key(hass, setup_comp): """Test encrypted payload with no key, .""" diff --git a/tests/components/owntracks/test_helper.py b/tests/components/owntracks/test_helper.py new file mode 100644 index 00000000000..f870ce82dd3 --- /dev/null +++ b/tests/components/owntracks/test_helper.py @@ -0,0 +1,29 @@ +"""Test the owntracks_http platform.""" +from unittest.mock import patch +import pytest + +from homeassistant.components.owntracks import helper + + +@pytest.fixture(name="nacl_imported") +def mock_nacl_imported(): + """Mock a successful import.""" + with patch("homeassistant.components.owntracks.helper.nacl"): + yield + + +@pytest.fixture(name="nacl_not_imported") +def mock_nacl_not_imported(): + """Mock non successful import.""" + with patch("homeassistant.components.owntracks.helper.nacl", new=None): + yield + + +def test_supports_encryption(nacl_imported): + """Test if env supports encryption.""" + assert helper.supports_encryption() + + +def test_supports_encryption_failed(nacl_not_imported): + """Test if env does not support encryption.""" + assert not helper.supports_encryption()