mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
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:
parent
879967bed2
commit
b3e60df82a
@ -18,6 +18,7 @@
|
|||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"data": {
|
"data": {
|
||||||
|
"authorization_code": "Authorization Code (required for manual authentication)",
|
||||||
"email": "E-Mail Address",
|
"email": "E-Mail Address",
|
||||||
"password": "Password"
|
"password": "Password"
|
||||||
},
|
},
|
||||||
|
@ -19,7 +19,7 @@ from .const import (
|
|||||||
MESSAGE_SCHEMA, SERVICE_RECONNECT, SERVICE_SEND_MESSAGE, SERVICE_UPDATE,
|
MESSAGE_SCHEMA, SERVICE_RECONNECT, SERVICE_SEND_MESSAGE, SERVICE_UPDATE,
|
||||||
TARGETS_SCHEMA)
|
TARGETS_SCHEMA)
|
||||||
|
|
||||||
REQUIREMENTS = ['hangups==0.4.6']
|
REQUIREMENTS = ['hangups==0.4.9']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
"""Config flow to configure Google Hangouts."""
|
"""Config flow to configure Google Hangouts."""
|
||||||
|
import functools
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
|
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
|
||||||
from homeassistant.core import callback
|
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
|
@callback
|
||||||
@ -41,13 +44,24 @@ class HangoutsFlowHandler(config_entries.ConfigFlow):
|
|||||||
from .hangups_utils import (HangoutsCredentials,
|
from .hangups_utils import (HangoutsCredentials,
|
||||||
HangoutsRefreshToken,
|
HangoutsRefreshToken,
|
||||||
GoogleAuthError, Google2FAError)
|
GoogleAuthError, Google2FAError)
|
||||||
self._credentials = HangoutsCredentials(user_input[CONF_EMAIL],
|
user_email = user_input[CONF_EMAIL]
|
||||||
user_input[CONF_PASSWORD])
|
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)
|
self._refresh_token = HangoutsRefreshToken(None)
|
||||||
try:
|
try:
|
||||||
await self.hass.async_add_executor_job(get_auth,
|
await self.hass.async_add_executor_job(
|
||||||
self._credentials,
|
functools.partial(get_auth,
|
||||||
self._refresh_token)
|
self._credentials,
|
||||||
|
self._refresh_token,
|
||||||
|
manual_login=manual_login)
|
||||||
|
)
|
||||||
|
|
||||||
return await self.async_step_final()
|
return await self.async_step_final()
|
||||||
except GoogleAuthError as err:
|
except GoogleAuthError as err:
|
||||||
@ -63,7 +77,8 @@ class HangoutsFlowHandler(config_entries.ConfigFlow):
|
|||||||
step_id='user',
|
step_id='user',
|
||||||
data_schema=vol.Schema({
|
data_schema=vol.Schema({
|
||||||
vol.Required(CONF_EMAIL): str,
|
vol.Required(CONF_EMAIL): str,
|
||||||
vol.Required(CONF_PASSWORD): str
|
vol.Required(CONF_PASSWORD): str,
|
||||||
|
vol.Optional(CONF_AUTH_CODE): str
|
||||||
}),
|
}),
|
||||||
errors=errors
|
errors=errors
|
||||||
)
|
)
|
||||||
|
@ -13,6 +13,7 @@ _LOGGER = logging.getLogger('.')
|
|||||||
DOMAIN = 'hangouts'
|
DOMAIN = 'hangouts'
|
||||||
|
|
||||||
CONF_2FA = '2fa'
|
CONF_2FA = '2fa'
|
||||||
|
CONF_AUTH_CODE = 'authorization_code'
|
||||||
CONF_REFRESH_TOKEN = 'refresh_token'
|
CONF_REFRESH_TOKEN = 'refresh_token'
|
||||||
CONF_BOT = 'bot'
|
CONF_BOT = 'bot'
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ class HangoutsCredentials(CredentialsPrompt):
|
|||||||
This implementation gets the user data as params.
|
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.
|
"""Google account credentials.
|
||||||
|
|
||||||
:param email: Google account email address.
|
:param email: Google account email address.
|
||||||
@ -23,6 +23,7 @@ class HangoutsCredentials(CredentialsPrompt):
|
|||||||
self._email = email
|
self._email = email
|
||||||
self._password = password
|
self._password = password
|
||||||
self._pin = pin
|
self._pin = pin
|
||||||
|
self._auth_code = auth_code
|
||||||
|
|
||||||
def get_email(self):
|
def get_email(self):
|
||||||
"""Return email.
|
"""Return email.
|
||||||
@ -54,6 +55,20 @@ class HangoutsCredentials(CredentialsPrompt):
|
|||||||
"""
|
"""
|
||||||
self._pin = pin
|
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):
|
class HangoutsRefreshToken(RefreshTokenCache):
|
||||||
"""Memory-based cache for refresh token."""
|
"""Memory-based cache for refresh token."""
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
"user": {
|
"user": {
|
||||||
"data": {
|
"data": {
|
||||||
"email": "E-Mail Address",
|
"email": "E-Mail Address",
|
||||||
"password": "Password"
|
"password": "Password",
|
||||||
|
"authorization_code": "Authorization Code (required for manual authentication)"
|
||||||
},
|
},
|
||||||
"title": "Google Hangouts Login"
|
"title": "Google Hangouts Login"
|
||||||
},
|
},
|
||||||
|
@ -19,6 +19,20 @@ async def test_flow_works(hass, aioclient_mock):
|
|||||||
assert result['title'] == 'test@test.com'
|
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):
|
async def test_flow_works_with_2fa(hass, aioclient_mock):
|
||||||
"""Test config flow with 2fa."""
|
"""Test config flow with 2fa."""
|
||||||
from homeassistant.components.hangouts.hangups_utils import Google2FAError
|
from homeassistant.components.hangouts.hangups_utils import Google2FAError
|
||||||
|
Loading…
x
Reference in New Issue
Block a user