mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 00:37:53 +00:00
Refresh the august access token when needed (#31735)
* Refresh the august access token when needed. Currently august will stop working when the token expires about every six month. This resolves issue #23788 * Make refresh_access_token_if_needed private since we do not want additional callers * Add init
This commit is contained in:
parent
891f13eefe
commit
f5be9ef7fb
@ -35,6 +35,7 @@ homeassistant/components/arest/* @fabaff
|
||||
homeassistant/components/asuswrt/* @kennedyshead
|
||||
homeassistant/components/aten_pe/* @mtdcr
|
||||
homeassistant/components/atome/* @baqs
|
||||
homeassistant/components/august/* @bdraco
|
||||
homeassistant/components/aurora_abb_powerone/* @davet2001
|
||||
homeassistant/components/auth/* @home-assistant/core
|
||||
homeassistant/components/automatic/* @armills
|
||||
|
@ -136,7 +136,7 @@ def setup_august(hass, config, api, authenticator):
|
||||
if DOMAIN in _CONFIGURING:
|
||||
hass.components.configurator.request_done(_CONFIGURING.pop(DOMAIN))
|
||||
|
||||
hass.data[DATA_AUGUST] = AugustData(hass, api, authentication.access_token)
|
||||
hass.data[DATA_AUGUST] = AugustData(hass, api, authentication, authenticator)
|
||||
|
||||
for component in AUGUST_COMPONENTS:
|
||||
discovery.load_platform(hass, component, DOMAIN, {}, config)
|
||||
@ -193,11 +193,14 @@ def setup(hass, config):
|
||||
class AugustData:
|
||||
"""August data object."""
|
||||
|
||||
def __init__(self, hass, api, access_token):
|
||||
def __init__(self, hass, api, authentication, authenticator):
|
||||
"""Init August data object."""
|
||||
self._hass = hass
|
||||
self._api = api
|
||||
self._access_token = access_token
|
||||
self._authenticator = authenticator
|
||||
self._access_token = authentication.access_token
|
||||
self._access_token_expires = authentication.access_token_expires
|
||||
|
||||
self._doorbells = self._api.get_doorbells(self._access_token) or []
|
||||
self._locks = self._api.get_operable_locks(self._access_token) or []
|
||||
self._house_ids = set()
|
||||
@ -227,6 +230,21 @@ class AugustData:
|
||||
"""Return a list of locks."""
|
||||
return self._locks
|
||||
|
||||
def _refresh_access_token_if_needed(self):
|
||||
"""Refresh the august access token if needed."""
|
||||
|
||||
if self._authenticator.should_refresh():
|
||||
refreshed_authentication = self._authenticator.refresh_access_token(
|
||||
force=False
|
||||
)
|
||||
_LOGGER.info(
|
||||
"Refreshed august access token. The old token expired at %s, and the new token expires at %s",
|
||||
self._access_token_expires,
|
||||
refreshed_authentication.access_token_expires,
|
||||
)
|
||||
self._access_token = refreshed_authentication.access_token
|
||||
self._access_token_expires = refreshed_authentication.access_token_expires
|
||||
|
||||
def get_device_activities(self, device_id, *activity_types):
|
||||
"""Return a list of activities."""
|
||||
_LOGGER.debug("Getting device activities")
|
||||
@ -245,6 +263,17 @@ class AugustData:
|
||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||
def _update_device_activities(self, limit=ACTIVITY_FETCH_LIMIT):
|
||||
"""Update data object with latest from August API."""
|
||||
|
||||
# This is the only place we refresh the api token
|
||||
# in order to avoid multiple threads from doing it at the same time
|
||||
# since there will only be one activity refresh at a time
|
||||
#
|
||||
# In the future when this module is converted to async we should
|
||||
# use a lock to prevent all api calls while the token
|
||||
# is being refreshed as this is a better solution
|
||||
#
|
||||
self._refresh_access_token_if_needed()
|
||||
|
||||
_LOGGER.debug("Start retrieving device activities")
|
||||
for house_id in self.house_ids:
|
||||
_LOGGER.debug("Updating device activity for house id %s", house_id)
|
||||
|
@ -4,5 +4,5 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/august",
|
||||
"requirements": ["py-august==0.11.0"],
|
||||
"dependencies": ["configurator"],
|
||||
"codeowners": []
|
||||
"codeowners": ["@bdraco"]
|
||||
}
|
||||
|
@ -389,6 +389,9 @@ pure-python-adb==0.2.2.dev0
|
||||
# homeassistant.components.pushbullet
|
||||
pushbullet.py==0.11.0
|
||||
|
||||
# homeassistant.components.august
|
||||
py-august==0.11.0
|
||||
|
||||
# homeassistant.components.canary
|
||||
py-canary==0.5.0
|
||||
|
||||
|
1
tests/components/august/__init__.py
Normal file
1
tests/components/august/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""Tests for the august component."""
|
44
tests/components/august/test_init.py
Normal file
44
tests/components/august/test_init.py
Normal file
@ -0,0 +1,44 @@
|
||||
"""The tests for the august platform."""
|
||||
from unittest.mock import MagicMock, PropertyMock
|
||||
|
||||
from homeassistant.components import august
|
||||
|
||||
|
||||
def _mock_august_authenticator():
|
||||
authenticator = MagicMock(name="august.authenticator")
|
||||
authenticator.should_refresh = MagicMock(
|
||||
name="august.authenticator.should_refresh", return_value=0
|
||||
)
|
||||
authenticator.refresh_access_token = MagicMock(
|
||||
name="august.authenticator.refresh_access_token"
|
||||
)
|
||||
return authenticator
|
||||
|
||||
|
||||
def _mock_august_authentication(token_text, token_timestamp):
|
||||
authentication = MagicMock(name="august.authentication")
|
||||
type(authentication).access_token = PropertyMock(return_value=token_text)
|
||||
type(authentication).access_token_expires = PropertyMock(
|
||||
return_value=token_timestamp
|
||||
)
|
||||
return authentication
|
||||
|
||||
|
||||
def test__refresh_access_token():
|
||||
"""Set up things to be run when tests are started."""
|
||||
authentication = _mock_august_authentication("original_token", 1234)
|
||||
authenticator = _mock_august_authenticator()
|
||||
data = august.AugustData(
|
||||
MagicMock(name="hass"), MagicMock(name="api"), authentication, authenticator
|
||||
)
|
||||
data._refresh_access_token_if_needed()
|
||||
authenticator.refresh_access_token.assert_not_called()
|
||||
|
||||
authenticator.should_refresh.return_value = 1
|
||||
authenticator.refresh_access_token.return_value = _mock_august_authentication(
|
||||
"new_token", 5678
|
||||
)
|
||||
data._refresh_access_token_if_needed()
|
||||
authenticator.refresh_access_token.assert_called()
|
||||
assert data._access_token == "new_token"
|
||||
assert data._access_token_expires == 5678
|
Loading…
x
Reference in New Issue
Block a user