diff --git a/homeassistant/components/hangouts/.translations/en.json b/homeassistant/components/hangouts/.translations/en.json index f526bec4f34..31e5f9894f9 100644 --- a/homeassistant/components/hangouts/.translations/en.json +++ b/homeassistant/components/hangouts/.translations/en.json @@ -18,6 +18,7 @@ }, "user": { "data": { + "authorization_code": "Authorization Code (required for manual authentication)", "email": "E-Mail Address", "password": "Password" }, diff --git a/homeassistant/components/hangouts/__init__.py b/homeassistant/components/hangouts/__init__.py index 2d36de8b769..29cdc29e5ad 100644 --- a/homeassistant/components/hangouts/__init__.py +++ b/homeassistant/components/hangouts/__init__.py @@ -19,7 +19,7 @@ from .const import ( MESSAGE_SCHEMA, SERVICE_RECONNECT, SERVICE_SEND_MESSAGE, SERVICE_UPDATE, TARGETS_SCHEMA) -REQUIREMENTS = ['hangups==0.4.6'] +REQUIREMENTS = ['hangups==0.4.9'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/hangouts/config_flow.py b/homeassistant/components/hangouts/config_flow.py index 5eecc24d45e..743c49abfdf 100644 --- a/homeassistant/components/hangouts/config_flow.py +++ b/homeassistant/components/hangouts/config_flow.py @@ -1,11 +1,14 @@ """Config flow to configure Google Hangouts.""" +import functools import voluptuous as vol + from homeassistant import config_entries from homeassistant.const import CONF_EMAIL, CONF_PASSWORD from homeassistant.core import callback -from .const import CONF_2FA, CONF_REFRESH_TOKEN, DOMAIN as HANGOUTS_DOMAIN +from .const import CONF_2FA, CONF_REFRESH_TOKEN, CONF_AUTH_CODE, \ + DOMAIN as HANGOUTS_DOMAIN @callback @@ -41,13 +44,24 @@ class HangoutsFlowHandler(config_entries.ConfigFlow): from .hangups_utils import (HangoutsCredentials, HangoutsRefreshToken, GoogleAuthError, Google2FAError) - self._credentials = HangoutsCredentials(user_input[CONF_EMAIL], - user_input[CONF_PASSWORD]) + user_email = user_input[CONF_EMAIL] + user_password = user_input[CONF_PASSWORD] + user_auth_code = user_input.get(CONF_AUTH_CODE) + manual_login = user_auth_code is not None + + user_pin = None + self._credentials = HangoutsCredentials(user_email, + user_password, + user_pin, + user_auth_code) self._refresh_token = HangoutsRefreshToken(None) try: - await self.hass.async_add_executor_job(get_auth, - self._credentials, - self._refresh_token) + await self.hass.async_add_executor_job( + functools.partial(get_auth, + self._credentials, + self._refresh_token, + manual_login=manual_login) + ) return await self.async_step_final() except GoogleAuthError as err: @@ -63,7 +77,8 @@ class HangoutsFlowHandler(config_entries.ConfigFlow): step_id='user', data_schema=vol.Schema({ vol.Required(CONF_EMAIL): str, - vol.Required(CONF_PASSWORD): str + vol.Required(CONF_PASSWORD): str, + vol.Optional(CONF_AUTH_CODE): str }), errors=errors ) diff --git a/homeassistant/components/hangouts/const.py b/homeassistant/components/hangouts/const.py index 38b238292b3..f664e769b9f 100644 --- a/homeassistant/components/hangouts/const.py +++ b/homeassistant/components/hangouts/const.py @@ -13,6 +13,7 @@ _LOGGER = logging.getLogger('.') DOMAIN = 'hangouts' CONF_2FA = '2fa' +CONF_AUTH_CODE = 'authorization_code' CONF_REFRESH_TOKEN = 'refresh_token' CONF_BOT = 'bot' diff --git a/homeassistant/components/hangouts/hangups_utils.py b/homeassistant/components/hangouts/hangups_utils.py index 9aff7730201..d2556ac15a0 100644 --- a/homeassistant/components/hangouts/hangups_utils.py +++ b/homeassistant/components/hangouts/hangups_utils.py @@ -13,7 +13,7 @@ class HangoutsCredentials(CredentialsPrompt): This implementation gets the user data as params. """ - def __init__(self, email, password, pin=None): + def __init__(self, email, password, pin=None, auth_code=None): """Google account credentials. :param email: Google account email address. @@ -23,6 +23,7 @@ class HangoutsCredentials(CredentialsPrompt): self._email = email self._password = password self._pin = pin + self._auth_code = auth_code def get_email(self): """Return email. @@ -54,6 +55,20 @@ class HangoutsCredentials(CredentialsPrompt): """ self._pin = pin + def get_authorization_code(self): + """Return the oauth authorization code. + + :return: Google oauth code. + """ + return self._auth_code + + def set_authorization_code(self, code): + """Set the google oauth authorization code. + + :param code: Oauth code returned after authentication with google. + """ + self._auth_code = code + class HangoutsRefreshToken(RefreshTokenCache): """Memory-based cache for refresh token.""" diff --git a/homeassistant/components/hangouts/strings.json b/homeassistant/components/hangouts/strings.json index c83a0ae0876..8c155784ebe 100644 --- a/homeassistant/components/hangouts/strings.json +++ b/homeassistant/components/hangouts/strings.json @@ -13,7 +13,8 @@ "user": { "data": { "email": "E-Mail Address", - "password": "Password" + "password": "Password", + "authorization_code": "Authorization Code (required for manual authentication)" }, "title": "Google Hangouts Login" }, diff --git a/tests/components/hangouts/test_config_flow.py b/tests/components/hangouts/test_config_flow.py index af9bb018919..becb981d68d 100644 --- a/tests/components/hangouts/test_config_flow.py +++ b/tests/components/hangouts/test_config_flow.py @@ -19,6 +19,20 @@ async def test_flow_works(hass, aioclient_mock): assert result['title'] == 'test@test.com' +async def test_flow_works_with_authcode(hass, aioclient_mock): + """Test config flow without 2fa.""" + flow = config_flow.HangoutsFlowHandler() + + flow.hass = hass + + with patch('hangups.get_auth'): + result = await flow.async_step_user( + {'email': 'test@test.com', 'password': '1232456', + 'authorization_code': 'c29tZXJhbmRvbXN0cmluZw=='}) + assert result['type'] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY + assert result['title'] == 'test@test.com' + + async def test_flow_works_with_2fa(hass, aioclient_mock): """Test config flow with 2fa.""" from homeassistant.components.hangouts.hangups_utils import Google2FAError