From 1d717b768d4ce59ee03b904f093460626b50c3d4 Mon Sep 17 00:00:00 2001 From: Andrew Hayworth Date: Sun, 2 Dec 2018 04:14:46 -0600 Subject: [PATCH 01/12] bugfix: ensure the `google_assistant` component respects `allow_unlock` (#18874) The `Config` object specific to the `google_assistant` component had a default value for `allow_unlock`. We were not overriding this default when constructing the Config object during `google_assistant` component setup, whereas we do when setting up the `cloud` component. To fix, we thread the `allow_unlock` parameter down through http setup, and ensure that it's set correctly. Moreover, we also change the ordering of the `Config` parameters, and remove the default. Future refactoring should not miss it, as it is now a required parameter. --- homeassistant/components/cloud/__init__.py | 2 +- homeassistant/components/google_assistant/helpers.py | 4 ++-- homeassistant/components/google_assistant/http.py | 8 ++++++-- tests/components/google_assistant/test_smart_home.py | 2 ++ tests/components/google_assistant/test_trait.py | 1 + 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/cloud/__init__.py b/homeassistant/components/cloud/__init__.py index 4f4b0c582fc..ba5621b1f8d 100644 --- a/homeassistant/components/cloud/__init__.py +++ b/homeassistant/components/cloud/__init__.py @@ -186,9 +186,9 @@ class Cloud: self._gactions_config = ga_h.Config( should_expose=should_expose, + allow_unlock=self.prefs.google_allow_unlock, agent_user_id=self.claims['cognito:username'], entity_config=conf.get(CONF_ENTITY_CONFIG), - allow_unlock=self.prefs.google_allow_unlock, ) return self._gactions_config diff --git a/homeassistant/components/google_assistant/helpers.py b/homeassistant/components/google_assistant/helpers.py index e71756d9fee..f20a4106a16 100644 --- a/homeassistant/components/google_assistant/helpers.py +++ b/homeassistant/components/google_assistant/helpers.py @@ -16,8 +16,8 @@ class SmartHomeError(Exception): class Config: """Hold the configuration for Google Assistant.""" - def __init__(self, should_expose, agent_user_id, entity_config=None, - allow_unlock=False): + def __init__(self, should_expose, allow_unlock, agent_user_id, + entity_config=None): """Initialize the configuration.""" self.should_expose = should_expose self.agent_user_id = agent_user_id diff --git a/homeassistant/components/google_assistant/http.py b/homeassistant/components/google_assistant/http.py index f29e8bbae12..d688491fe89 100644 --- a/homeassistant/components/google_assistant/http.py +++ b/homeassistant/components/google_assistant/http.py @@ -15,6 +15,7 @@ from homeassistant.const import CLOUD_NEVER_EXPOSED_ENTITIES from .const import ( GOOGLE_ASSISTANT_API_ENDPOINT, + CONF_ALLOW_UNLOCK, CONF_EXPOSE_BY_DEFAULT, CONF_EXPOSED_DOMAINS, CONF_ENTITY_CONFIG, @@ -32,6 +33,7 @@ def async_register_http(hass, cfg): expose_by_default = cfg.get(CONF_EXPOSE_BY_DEFAULT) exposed_domains = cfg.get(CONF_EXPOSED_DOMAINS) entity_config = cfg.get(CONF_ENTITY_CONFIG) or {} + allow_unlock = cfg.get(CONF_ALLOW_UNLOCK, False) def is_exposed(entity) -> bool: """Determine if an entity should be exposed to Google Assistant.""" @@ -57,7 +59,7 @@ def async_register_http(hass, cfg): return is_default_exposed or explicit_expose hass.http.register_view( - GoogleAssistantView(is_exposed, entity_config)) + GoogleAssistantView(is_exposed, entity_config, allow_unlock)) class GoogleAssistantView(HomeAssistantView): @@ -67,15 +69,17 @@ class GoogleAssistantView(HomeAssistantView): name = 'api:google_assistant' requires_auth = True - def __init__(self, is_exposed, entity_config): + def __init__(self, is_exposed, entity_config, allow_unlock): """Initialize the Google Assistant request handler.""" self.is_exposed = is_exposed self.entity_config = entity_config + self.allow_unlock = allow_unlock async def post(self, request: Request) -> Response: """Handle Google Assistant requests.""" message = await request.json() # type: dict config = Config(self.is_exposed, + self.allow_unlock, request['hass_user'].id, self.entity_config) result = await async_handle_message( diff --git a/tests/components/google_assistant/test_smart_home.py b/tests/components/google_assistant/test_smart_home.py index 66e7747e06a..36971224f92 100644 --- a/tests/components/google_assistant/test_smart_home.py +++ b/tests/components/google_assistant/test_smart_home.py @@ -11,6 +11,7 @@ from homeassistant.components.light.demo import DemoLight BASIC_CONFIG = helpers.Config( should_expose=lambda state: True, + allow_unlock=False, agent_user_id='test-agent', ) REQ_ID = 'ff36a3cc-ec34-11e6-b1a0-64510650abcf' @@ -35,6 +36,7 @@ async def test_sync_message(hass): config = helpers.Config( should_expose=lambda state: state.entity_id != 'light.not_expose', + allow_unlock=False, agent_user_id='test-agent', entity_config={ 'light.demo_light': { diff --git a/tests/components/google_assistant/test_trait.py b/tests/components/google_assistant/test_trait.py index 42af1230eed..616c43464a6 100644 --- a/tests/components/google_assistant/test_trait.py +++ b/tests/components/google_assistant/test_trait.py @@ -25,6 +25,7 @@ from tests.common import async_mock_service BASIC_CONFIG = helpers.Config( should_expose=lambda state: True, + allow_unlock=False, agent_user_id='test-agent', ) From 6de0ed3f0a016e30c65e8404c21a7762ebc0a9f3 Mon Sep 17 00:00:00 2001 From: ludeeus Date: Sat, 1 Dec 2018 11:24:32 +0100 Subject: [PATCH 02/12] Fix stability issues with multiple units --- homeassistant/components/device_tracker/googlehome.py | 4 ++-- requirements_all.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/device_tracker/googlehome.py b/homeassistant/components/device_tracker/googlehome.py index 575d9688493..e700301d579 100644 --- a/homeassistant/components/device_tracker/googlehome.py +++ b/homeassistant/components/device_tracker/googlehome.py @@ -14,7 +14,7 @@ from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST -REQUIREMENTS = ['ghlocalapi==0.1.0'] +REQUIREMENTS = ['ghlocalapi==0.3.4'] _LOGGER = logging.getLogger(__name__) @@ -77,8 +77,8 @@ class GoogleHomeDeviceScanner(DeviceScanner): async def async_update_info(self): """Ensure the information from Google Home is up to date.""" _LOGGER.debug('Checking Devices...') - await self.scanner.scan_for_devices() await self.scanner.get_scan_result() + await self.scanner.scan_for_devices() ghname = self.deviceinfo.device_info['name'] devices = {} for device in self.scanner.devices: diff --git a/requirements_all.txt b/requirements_all.txt index e4020ca41e7..8f4f24f45ed 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -422,7 +422,7 @@ geojson_client==0.3 georss_client==0.4 # homeassistant.components.device_tracker.googlehome -ghlocalapi==0.1.0 +ghlocalapi==0.3.4 # homeassistant.components.sensor.gitter gitterpy==0.1.7 From 79a9c1af9ea1304ae987833220b79c6bee214da0 Mon Sep 17 00:00:00 2001 From: ludeeus Date: Sat, 1 Dec 2018 16:28:22 +0100 Subject: [PATCH 03/12] bump ghlocalapi to use clear_scan_result --- homeassistant/components/device_tracker/googlehome.py | 5 +++-- requirements_all.txt | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/device_tracker/googlehome.py b/homeassistant/components/device_tracker/googlehome.py index e700301d579..dabb92a0751 100644 --- a/homeassistant/components/device_tracker/googlehome.py +++ b/homeassistant/components/device_tracker/googlehome.py @@ -14,7 +14,7 @@ from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST -REQUIREMENTS = ['ghlocalapi==0.3.4'] +REQUIREMENTS = ['ghlocalapi==0.3.5'] _LOGGER = logging.getLogger(__name__) @@ -77,8 +77,8 @@ class GoogleHomeDeviceScanner(DeviceScanner): async def async_update_info(self): """Ensure the information from Google Home is up to date.""" _LOGGER.debug('Checking Devices...') - await self.scanner.get_scan_result() await self.scanner.scan_for_devices() + await self.scanner.get_scan_result() ghname = self.deviceinfo.device_info['name'] devices = {} for device in self.scanner.devices: @@ -89,4 +89,5 @@ class GoogleHomeDeviceScanner(DeviceScanner): devices[uuid]['btle_mac_address'] = device['mac_address'] devices[uuid]['ghname'] = ghname devices[uuid]['source_type'] = 'bluetooth' + await self.scanner.clear_scan_result() self.last_results = devices diff --git a/requirements_all.txt b/requirements_all.txt index 8f4f24f45ed..c016d4596ad 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -422,7 +422,7 @@ geojson_client==0.3 georss_client==0.4 # homeassistant.components.device_tracker.googlehome -ghlocalapi==0.3.4 +ghlocalapi==0.3.5 # homeassistant.components.sensor.gitter gitterpy==0.1.7 From f8218b5e01bc67ad1e8e01f032d7a9f7aba27ac3 Mon Sep 17 00:00:00 2001 From: ludeeus Date: Sat, 1 Dec 2018 13:02:15 +0100 Subject: [PATCH 04/12] Fix IndexError for home stats --- homeassistant/components/sensor/tautulli.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/sensor/tautulli.py b/homeassistant/components/sensor/tautulli.py index 7b0d8e491d2..419ef6a11a1 100644 --- a/homeassistant/components/sensor/tautulli.py +++ b/homeassistant/components/sensor/tautulli.py @@ -19,7 +19,7 @@ import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle -REQUIREMENTS = ['pytautulli==0.4.0'] +REQUIREMENTS = ['pytautulli==0.4.1'] _LOGGER = logging.getLogger(__name__) @@ -90,9 +90,9 @@ class TautulliSensor(Entity): await self.tautulli.async_update() self.home = self.tautulli.api.home_data self.sessions = self.tautulli.api.session_data - self._attributes['Top Movie'] = self.home[0]['rows'][0]['title'] - self._attributes['Top TV Show'] = self.home[3]['rows'][0]['title'] - self._attributes['Top User'] = self.home[7]['rows'][0]['user'] + self._attributes['Top Movie'] = self.home['movie'] + self._attributes['Top TV Show'] = self.home['tv'] + self._attributes['Top User'] = self.home['user'] for key in self.sessions: if 'sessions' not in key: self._attributes[key] = self.sessions[key] From 475be636d6d1fda3349dd444cb085f0000ea5b1a Mon Sep 17 00:00:00 2001 From: ludeeus Date: Sat, 1 Dec 2018 13:07:32 +0100 Subject: [PATCH 05/12] Fix requirements_all --- requirements_all.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_all.txt b/requirements_all.txt index c016d4596ad..50a81aa6c2c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1154,7 +1154,7 @@ pystride==0.1.7 pysyncthru==0.3.1 # homeassistant.components.sensor.tautulli -pytautulli==0.4.0 +pytautulli==0.4.1 # homeassistant.components.media_player.liveboxplaytv pyteleloisirs==3.4 From 82d89edb4f2cd82b785c955e03ccdd1d95c6073b Mon Sep 17 00:00:00 2001 From: ludeeus Date: Sat, 1 Dec 2018 21:32:31 +0100 Subject: [PATCH 06/12] Use dict.get('key') instead of dict['key'] --- homeassistant/components/sensor/tautulli.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/sensor/tautulli.py b/homeassistant/components/sensor/tautulli.py index 419ef6a11a1..29c11c934f9 100644 --- a/homeassistant/components/sensor/tautulli.py +++ b/homeassistant/components/sensor/tautulli.py @@ -90,9 +90,9 @@ class TautulliSensor(Entity): await self.tautulli.async_update() self.home = self.tautulli.api.home_data self.sessions = self.tautulli.api.session_data - self._attributes['Top Movie'] = self.home['movie'] - self._attributes['Top TV Show'] = self.home['tv'] - self._attributes['Top User'] = self.home['user'] + self._attributes['Top Movie'] = self.home.get('movie') + self._attributes['Top TV Show'] = self.home,get('tv') + self._attributes['Top User'] = self.home.get('user') for key in self.sessions: if 'sessions' not in key: self._attributes[key] = self.sessions[key] From ee1c29b392ac0734c4fd0d1ee15fa44547612893 Mon Sep 17 00:00:00 2001 From: ludeeus Date: Sat, 1 Dec 2018 21:34:31 +0100 Subject: [PATCH 07/12] corrects , -> . typo --- homeassistant/components/sensor/tautulli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/tautulli.py b/homeassistant/components/sensor/tautulli.py index 29c11c934f9..f47f0e5c382 100644 --- a/homeassistant/components/sensor/tautulli.py +++ b/homeassistant/components/sensor/tautulli.py @@ -91,7 +91,7 @@ class TautulliSensor(Entity): self.home = self.tautulli.api.home_data self.sessions = self.tautulli.api.session_data self._attributes['Top Movie'] = self.home.get('movie') - self._attributes['Top TV Show'] = self.home,get('tv') + self._attributes['Top TV Show'] = self.home.get('tv') self._attributes['Top User'] = self.home.get('user') for key in self.sessions: if 'sessions' not in key: From 3575c34f77aecaaacace741d66c33ba8201dd4a0 Mon Sep 17 00:00:00 2001 From: William Scanlon Date: Mon, 3 Dec 2018 05:34:22 -0500 Subject: [PATCH 08/12] Use capability of sensor if present to fix multisensor Wink devices (#18907) --- homeassistant/components/wink/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/homeassistant/components/wink/__init__.py b/homeassistant/components/wink/__init__.py index a94f8c3bdf2..c4cefa2c2d1 100644 --- a/homeassistant/components/wink/__init__.py +++ b/homeassistant/components/wink/__init__.py @@ -690,6 +690,10 @@ class WinkDevice(Entity): @property def unique_id(self): """Return the unique id of the Wink device.""" + if hasattr(self.wink, 'capability') and \ + self.wink.capability() is not None: + return "{}_{}".format(self.wink.object_id(), + self.wink.capability()) return self.wink.object_id() @property From 35690d5b29b1f54ac7cadf3ee9777de15ad23061 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 3 Dec 2018 11:34:01 +0100 Subject: [PATCH 09/12] Add users added via credentials to admin group too (#18922) * Add users added via credentials to admin group too * Update test_init.py --- homeassistant/auth/__init__.py | 1 + tests/auth/test_init.py | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/homeassistant/auth/__init__.py b/homeassistant/auth/__init__.py index 7d8ef13d2bb..49f01211e5a 100644 --- a/homeassistant/auth/__init__.py +++ b/homeassistant/auth/__init__.py @@ -190,6 +190,7 @@ class AuthManager: credentials=credentials, name=info.name, is_active=info.is_active, + group_ids=[GROUP_ID_ADMIN], ) self.hass.bus.async_fire(EVENT_USER_ADDED, { diff --git a/tests/auth/test_init.py b/tests/auth/test_init.py index 4357ba1b1de..e950230f10a 100644 --- a/tests/auth/test_init.py +++ b/tests/auth/test_init.py @@ -870,3 +870,28 @@ async def test_async_remove_user(hass): await hass.async_block_till_done() assert len(events) == 1 assert events[0].data['user_id'] == user.id + + +async def test_new_users_admin(mock_hass): + """Test newly created users are admin.""" + manager = await auth.auth_manager_from_config(mock_hass, [{ + 'type': 'insecure_example', + 'users': [{ + 'username': 'test-user', + 'password': 'test-pass', + 'name': 'Test Name' + }] + }], []) + ensure_auth_manager_loaded(manager) + + user = await manager.async_create_user('Hello') + assert user.is_admin + + user_cred = await manager.async_get_or_create_user(auth_models.Credentials( + id='mock-id', + auth_provider_type='insecure_example', + auth_provider_id=None, + data={'username': 'test-user'}, + is_new=True, + )) + assert user_cred.is_admin From f6a79059e5a240540f8185cd6c419135f8e5c90c Mon Sep 17 00:00:00 2001 From: kennedyshead Date: Tue, 27 Nov 2018 14:20:25 +0100 Subject: [PATCH 10/12] fix aioasuswrt sometimes return empty lists (#18742) * aioasuswrt sometimes return empty lists * Bumping aioasuswrt to 1.1.12 --- homeassistant/components/asuswrt.py | 2 +- homeassistant/components/sensor/asuswrt.py | 8 ++++---- requirements_all.txt | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/asuswrt.py b/homeassistant/components/asuswrt.py index c653c1d03fd..d72c8d77a2b 100644 --- a/homeassistant/components/asuswrt.py +++ b/homeassistant/components/asuswrt.py @@ -14,7 +14,7 @@ from homeassistant.const import ( from homeassistant.helpers import config_validation as cv from homeassistant.helpers.discovery import async_load_platform -REQUIREMENTS = ['aioasuswrt==1.1.11'] +REQUIREMENTS = ['aioasuswrt==1.1.12'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/sensor/asuswrt.py b/homeassistant/components/sensor/asuswrt.py index 4ca088fb1e2..876f0dfd559 100644 --- a/homeassistant/components/sensor/asuswrt.py +++ b/homeassistant/components/sensor/asuswrt.py @@ -68,7 +68,7 @@ class AsuswrtRXSensor(AsuswrtSensor): async def async_update(self): """Fetch new state data for the sensor.""" await super().async_update() - if self._speed is not None: + if self._speed: self._state = round(self._speed[0] / 125000, 2) @@ -86,7 +86,7 @@ class AsuswrtTXSensor(AsuswrtSensor): async def async_update(self): """Fetch new state data for the sensor.""" await super().async_update() - if self._speed is not None: + if self._speed: self._state = round(self._speed[1] / 125000, 2) @@ -104,7 +104,7 @@ class AsuswrtTotalRXSensor(AsuswrtSensor): async def async_update(self): """Fetch new state data for the sensor.""" await super().async_update() - if self._rates is not None: + if self._rates: self._state = round(self._rates[0] / 1000000000, 1) @@ -122,5 +122,5 @@ class AsuswrtTotalTXSensor(AsuswrtSensor): async def async_update(self): """Fetch new state data for the sensor.""" await super().async_update() - if self._rates is not None: + if self._rates: self._state = round(self._rates[1] / 1000000000, 1) diff --git a/requirements_all.txt b/requirements_all.txt index 50a81aa6c2c..e939f1e4646 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -86,7 +86,7 @@ abodepy==0.14.0 afsapi==0.0.4 # homeassistant.components.asuswrt -aioasuswrt==1.1.11 +aioasuswrt==1.1.12 # homeassistant.components.device_tracker.automatic aioautomatic==0.6.5 From 106cb63922955ef8af0ca64fbf8133e76a2e1483 Mon Sep 17 00:00:00 2001 From: kennedyshead Date: Mon, 3 Dec 2018 11:13:06 +0100 Subject: [PATCH 11/12] bump aioasuswrt version (#18955) --- homeassistant/components/asuswrt.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/asuswrt.py b/homeassistant/components/asuswrt.py index d72c8d77a2b..719e857c751 100644 --- a/homeassistant/components/asuswrt.py +++ b/homeassistant/components/asuswrt.py @@ -14,7 +14,7 @@ from homeassistant.const import ( from homeassistant.helpers import config_validation as cv from homeassistant.helpers.discovery import async_load_platform -REQUIREMENTS = ['aioasuswrt==1.1.12'] +REQUIREMENTS = ['aioasuswrt==1.1.13'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index e939f1e4646..169c54aa713 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -86,7 +86,7 @@ abodepy==0.14.0 afsapi==0.0.4 # homeassistant.components.asuswrt -aioasuswrt==1.1.12 +aioasuswrt==1.1.13 # homeassistant.components.device_tracker.automatic aioautomatic==0.6.5 From 4ef1bf21570f15fca37262ce76deb08d61627204 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 3 Dec 2018 11:42:49 +0100 Subject: [PATCH 12/12] Bumped version to 0.83.3 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 1a1d45396f0..63d4e9f00f5 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -2,7 +2,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 83 -PATCH_VERSION = '2' +PATCH_VERSION = '3' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 5, 3)