Add google hangouts manual authentication option (#22158)

* Added option to use manual authentication for google hangout component
See: https://hangups.readthedocs.io/en/latest/user_guide.html#logging-in for manual log in example

Bumped up version of hangups to 0.4.9

* Updated components/hangouts/strings.json and generated translation string by running script/translations_develop
Reduced verbosity of modifications to components/hangouts/config_flow.py

* Added option to use manual authentication for google hangout component
See: https://hangups.readthedocs.io/en/latest/user_guide.html#logging-in for manual log in example

Bumped up version of hangups to 0.4.9

* Updated components/hangouts/strings.json and generated translation string by running script/translations_develop
Reduced verbosity of modifications to components/hangouts/config_flow.py

* fixing missing rebase
This commit is contained in:
teliov 2019-04-05 19:11:04 +02:00 committed by Jason Hu
parent 879967bed2
commit b3e60df82a
7 changed files with 57 additions and 10 deletions

View file

@ -18,6 +18,7 @@
},
"user": {
"data": {
"authorization_code": "Authorization Code (required for manual authentication)",
"email": "E-Mail Address",
"password": "Password"
},

View file

@ -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__)

View file

@ -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
)

View file

@ -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'

View file

@ -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."""

View file

@ -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"
},

View file

@ -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