More explicitly call out special cases with SimpliSafe authorization code (#76232)
parent
8ca5b5d4a4
commit
b2dc810ea4
|
@ -81,17 +81,34 @@ class SimpliSafeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
description_placeholders={CONF_URL: self._oauth_values.auth_url},
|
||||
)
|
||||
|
||||
auth_code = user_input[CONF_AUTH_CODE]
|
||||
|
||||
if auth_code.startswith("="):
|
||||
# Sometimes, users may include the "=" from the URL query param; in that
|
||||
# case, strip it off and proceed:
|
||||
LOGGER.debug('Stripping "=" from the start of the authorization code')
|
||||
auth_code = auth_code[1:]
|
||||
|
||||
if len(auth_code) != 45:
|
||||
# SimpliSafe authorization codes are 45 characters in length; if the user
|
||||
# provides something different, stop them here:
|
||||
return self.async_show_form(
|
||||
step_id="user",
|
||||
data_schema=STEP_USER_SCHEMA,
|
||||
errors={CONF_AUTH_CODE: "invalid_auth_code_length"},
|
||||
description_placeholders={CONF_URL: self._oauth_values.auth_url},
|
||||
)
|
||||
|
||||
errors = {}
|
||||
session = aiohttp_client.async_get_clientsession(self.hass)
|
||||
|
||||
try:
|
||||
simplisafe = await API.async_from_auth(
|
||||
user_input[CONF_AUTH_CODE],
|
||||
auth_code,
|
||||
self._oauth_values.code_verifier,
|
||||
session=session,
|
||||
)
|
||||
except InvalidCredentialsError:
|
||||
errors = {"base": "invalid_auth"}
|
||||
errors = {CONF_AUTH_CODE: "invalid_auth"}
|
||||
except SimplipyError as err:
|
||||
LOGGER.error("Unknown error while logging into SimpliSafe: %s", err)
|
||||
errors = {"base": "unknown"}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"description": "SimpliSafe authenticates users via its web app. Due to technical limitations, there is a manual step at the end of this process; please ensure that you read the [documentation](http://home-assistant.io/integrations/simplisafe#getting-an-authorization-code) before starting.\n\nWhen you are ready, click [here]({url}) to open the SimpliSafe web app and input your credentials. When the process is complete, return here and input the authorization code from the SimpliSafe web app URL.",
|
||||
"description": "SimpliSafe authenticates users via its web app. Due to technical limitations, there is a manual step at the end of this process; please ensure that you read the [documentation](http://home-assistant.io/integrations/simplisafe#getting-an-authorization-code) before starting.\n\nWhen you are ready, click [here]({url}) to open the SimpliSafe web app and input your credentials. If you've already logged into SimpliSafe in your browser, you may want to open a new tab, then copy/paste the above URL into that tab.\n\nWhen the process is complete, return here and input the authorization code from the `com.simplisafe.mobile` URL.",
|
||||
"data": {
|
||||
"auth_code": "Authorization Code"
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
|||
"error": {
|
||||
"identifier_exists": "Account already registered",
|
||||
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
|
||||
"invalid_auth_code_length": "SimpliSafe authorization codes are 45 characters in length",
|
||||
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||
},
|
||||
"abort": {
|
||||
|
|
|
@ -2,39 +2,21 @@
|
|||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "This SimpliSafe account is already in use.",
|
||||
"email_2fa_timed_out": "Timed out while waiting for email-based two-factor authentication.",
|
||||
"reauth_successful": "Re-authentication was successful",
|
||||
"wrong_account": "The user credentials provided do not match this SimpliSafe account."
|
||||
},
|
||||
"error": {
|
||||
"identifier_exists": "Account already registered",
|
||||
"invalid_auth": "Invalid authentication",
|
||||
"invalid_auth_code_length": "SimpliSafe authorization codes are 45 characters in length",
|
||||
"unknown": "Unexpected error"
|
||||
},
|
||||
"progress": {
|
||||
"email_2fa": "Check your email for a verification link from Simplisafe."
|
||||
},
|
||||
"step": {
|
||||
"reauth_confirm": {
|
||||
"data": {
|
||||
"password": "Password"
|
||||
},
|
||||
"description": "Please re-enter the password for {username}.",
|
||||
"title": "Reauthenticate Integration"
|
||||
},
|
||||
"sms_2fa": {
|
||||
"data": {
|
||||
"code": "Code"
|
||||
},
|
||||
"description": "Input the two-factor authentication code sent to you via SMS."
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"auth_code": "Authorization Code",
|
||||
"password": "Password",
|
||||
"username": "Username"
|
||||
"auth_code": "Authorization Code"
|
||||
},
|
||||
"description": "SimpliSafe authenticates users via its web app. Due to technical limitations, there is a manual step at the end of this process; please ensure that you read the [documentation](http://home-assistant.io/integrations/simplisafe#getting-an-authorization-code) before starting.\n\nWhen you are ready, click [here]({url}) to open the SimpliSafe web app and input your credentials. When the process is complete, return here and input the authorization code from the SimpliSafe web app URL."
|
||||
"description": "SimpliSafe authenticates users via its web app. Due to technical limitations, there is a manual step at the end of this process; please ensure that you read the [documentation](http://home-assistant.io/integrations/simplisafe#getting-an-authorization-code) before starting.\n\nWhen you are ready, click [here]({url}) to open the SimpliSafe web app and input your credentials. If you've already logged into SimpliSafe in your browser, you may want to open a new tab, then copy/paste the above URL into that tab.\n\nWhen the process is complete, return here and input the authorization code from the `com.simplisafe.mobile` URL."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
"""Define tests for the SimpliSafe config flow."""
|
||||
import logging
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
@ -10,6 +11,8 @@ from homeassistant.components.simplisafe.config_flow import CONF_AUTH_CODE
|
|||
from homeassistant.config_entries import SOURCE_REAUTH, SOURCE_USER
|
||||
from homeassistant.const import CONF_CODE, CONF_TOKEN, CONF_USERNAME
|
||||
|
||||
VALID_AUTH_CODE = "code12345123451234512345123451234512345123451"
|
||||
|
||||
|
||||
async def test_duplicate_error(config_entry, hass, setup_simplisafe):
|
||||
"""Test that errors are shown when duplicates are added."""
|
||||
|
@ -23,12 +26,27 @@ async def test_duplicate_error(config_entry, hass, setup_simplisafe):
|
|||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={CONF_AUTH_CODE: "code123"}
|
||||
result["flow_id"], user_input={CONF_AUTH_CODE: VALID_AUTH_CODE}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_invalid_auth_code_length(hass):
|
||||
"""Test that an invalid auth code length show the correct error."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
assert result["step_id"] == "user"
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={CONF_AUTH_CODE: "too_short_code"}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["errors"] == {CONF_AUTH_CODE: "invalid_auth_code_length"}
|
||||
|
||||
|
||||
async def test_invalid_credentials(hass):
|
||||
"""Test that invalid credentials show the correct error."""
|
||||
with patch(
|
||||
|
@ -42,10 +60,11 @@ async def test_invalid_credentials(hass):
|
|||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={CONF_AUTH_CODE: "code123"}
|
||||
result["flow_id"],
|
||||
user_input={CONF_AUTH_CODE: VALID_AUTH_CODE},
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["errors"] == {"base": "invalid_auth"}
|
||||
assert result["errors"] == {CONF_AUTH_CODE: "invalid_auth"}
|
||||
|
||||
|
||||
async def test_options_flow(config_entry, hass):
|
||||
|
@ -80,7 +99,7 @@ async def test_step_reauth(config_entry, hass, setup_simplisafe):
|
|||
"homeassistant.components.simplisafe.async_setup_entry", return_value=True
|
||||
), patch("homeassistant.config_entries.ConfigEntries.async_reload"):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={CONF_AUTH_CODE: "code123"}
|
||||
result["flow_id"], user_input={CONF_AUTH_CODE: VALID_AUTH_CODE}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "reauth_successful"
|
||||
|
@ -104,14 +123,29 @@ async def test_step_reauth_wrong_account(config_entry, hass, setup_simplisafe):
|
|||
"homeassistant.components.simplisafe.async_setup_entry", return_value=True
|
||||
), patch("homeassistant.config_entries.ConfigEntries.async_reload"):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={CONF_AUTH_CODE: "code123"}
|
||||
result["flow_id"], user_input={CONF_AUTH_CODE: VALID_AUTH_CODE}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "wrong_account"
|
||||
|
||||
|
||||
async def test_step_user(hass, setup_simplisafe):
|
||||
"""Test the user step."""
|
||||
@pytest.mark.parametrize(
|
||||
"auth_code,log_statement",
|
||||
[
|
||||
(
|
||||
VALID_AUTH_CODE,
|
||||
None,
|
||||
),
|
||||
(
|
||||
f"={VALID_AUTH_CODE}",
|
||||
'Stripping "=" from the start of the authorization code',
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_step_user(auth_code, caplog, hass, log_statement, setup_simplisafe):
|
||||
"""Test successfully completion of the user step."""
|
||||
caplog.set_level = logging.DEBUG
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
|
@ -121,10 +155,13 @@ async def test_step_user(hass, setup_simplisafe):
|
|||
"homeassistant.components.simplisafe.async_setup_entry", return_value=True
|
||||
), patch("homeassistant.config_entries.ConfigEntries.async_reload"):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={CONF_AUTH_CODE: "code123"}
|
||||
result["flow_id"], user_input={CONF_AUTH_CODE: auth_code}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
|
||||
if log_statement:
|
||||
assert any(m for m in caplog.messages if log_statement in m)
|
||||
|
||||
assert len(hass.config_entries.async_entries()) == 1
|
||||
[config_entry] = hass.config_entries.async_entries(DOMAIN)
|
||||
assert config_entry.data == {CONF_USERNAME: "12345", CONF_TOKEN: "token123"}
|
||||
|
@ -143,7 +180,7 @@ async def test_unknown_error(hass, setup_simplisafe):
|
|||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={CONF_AUTH_CODE: "code123"}
|
||||
result["flow_id"], user_input={CONF_AUTH_CODE: VALID_AUTH_CODE}
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["errors"] == {"base": "unknown"}
|
||||
|
|
Loading…
Reference in New Issue