mirror of
https://github.com/home-assistant/core.git
synced 2026-10-06 22:38:02 -04:00
Show a hint when a Verisure password is longer than 30 characters (#184250)
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
e2d077e560
commit
c1e5561efe
@@ -26,6 +26,9 @@ from .const import (
|
||||
)
|
||||
from .coordinator import VerisureConfigEntry
|
||||
|
||||
# Observed on the Danish My Pages site, other countries may differ.
|
||||
MAX_PASSWORD_LENGTH = 30
|
||||
|
||||
|
||||
class VerisureConfigFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a config flow for Verisure."""
|
||||
@@ -90,7 +93,11 @@ class VerisureConfigFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
return await self.async_step_mfa()
|
||||
else:
|
||||
LOGGER.debug("Could not log in to Verisure, %s", ex)
|
||||
errors["base"] = "invalid_auth"
|
||||
errors["base"] = (
|
||||
"invalid_auth_password_too_long"
|
||||
if len(self.password) > MAX_PASSWORD_LENGTH
|
||||
else "invalid_auth"
|
||||
)
|
||||
except VerisureRateLimitError as ex:
|
||||
LOGGER.debug("Verisure rate limited during login, %s", ex)
|
||||
errors["base"] = "mfa_rate_limited"
|
||||
@@ -233,7 +240,11 @@ class VerisureConfigFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
return await self.async_step_reauth_mfa()
|
||||
else:
|
||||
LOGGER.debug("Could not log in to Verisure, %s", ex)
|
||||
errors["base"] = "invalid_auth"
|
||||
errors["base"] = (
|
||||
"invalid_auth_password_too_long"
|
||||
if len(self.password) > MAX_PASSWORD_LENGTH
|
||||
else "invalid_auth"
|
||||
)
|
||||
except VerisureRateLimitError as ex:
|
||||
LOGGER.debug("Verisure rate limited during reauth login, %s", ex)
|
||||
errors["base"] = "mfa_rate_limited"
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
|
||||
"invalid_auth_password_too_long": "Invalid authentication. Verisure may not accept passwords longer than 30 characters. Try changing yours to 30 characters or fewer.",
|
||||
"mfa_rate_limited": "Too many login attempts. Wait before trying again.",
|
||||
"unknown": "[%key:common::config_flow::error::unknown%]",
|
||||
"unknown_mfa": "Unknown error occurred during MFA setup"
|
||||
@@ -27,6 +28,9 @@
|
||||
"description": "Re-authenticate with your Verisure My Pages account.",
|
||||
"email": "[%key:common::config_flow::data::email%]",
|
||||
"password": "[%key:common::config_flow::data::password%]"
|
||||
},
|
||||
"data_description": {
|
||||
"password": "[%key:component::verisure::config::step::user::data_description::password%]"
|
||||
}
|
||||
},
|
||||
"reauth_mfa": {
|
||||
@@ -40,6 +44,9 @@
|
||||
"description": "Sign in with your Verisure My Pages account.",
|
||||
"email": "[%key:common::config_flow::data::email%]",
|
||||
"password": "[%key:common::config_flow::data::password%]"
|
||||
},
|
||||
"data_description": {
|
||||
"password": "Verisure may not accept passwords longer than 30 characters."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -539,6 +539,98 @@ async def test_reauth_flow_errors(
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("password", "error"),
|
||||
[
|
||||
pytest.param("a" * 30, "invalid_auth", id="at_limit"),
|
||||
pytest.param("a" * 31, "invalid_auth_password_too_long", id="over_limit"),
|
||||
],
|
||||
)
|
||||
async def test_user_flow_invalid_auth_password_length(
|
||||
hass: HomeAssistant,
|
||||
mock_setup_entry: AsyncMock,
|
||||
mock_verisure_config_flow: MagicMock,
|
||||
password: str,
|
||||
error: str,
|
||||
) -> None:
|
||||
"""Test a rejected login hints at the password length when it is too long."""
|
||||
mock_verisure_config_flow.get_installations.return_value = {
|
||||
k1: {k2: {k3: [v3[0]] for k3, v3 in v2.items()} for k2, v2 in v1.items()}
|
||||
for k1, v1 in mock_verisure_config_flow.get_installations.return_value.items()
|
||||
}
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
mock_verisure_config_flow.login.side_effect = VerisureLoginError("Login failed")
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{"email": "verisure_my_pages@example.com", "password": password},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result2.get("type") is FlowResultType.FORM
|
||||
assert result2.get("step_id") == "user"
|
||||
assert result2.get("errors") == {"base": error}
|
||||
|
||||
mock_verisure_config_flow.login.side_effect = None
|
||||
result3 = await hass.config_entries.flow.async_configure(
|
||||
result2["flow_id"],
|
||||
{"email": "verisure_my_pages@example.com", "password": "SuperS3cr3t!"},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result3.get("type") is FlowResultType.CREATE_ENTRY
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("password", "error"),
|
||||
[
|
||||
pytest.param("a" * 30, "invalid_auth", id="at_limit"),
|
||||
pytest.param("a" * 31, "invalid_auth_password_too_long", id="over_limit"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("mock_setup_entry")
|
||||
async def test_reauth_flow_invalid_auth_password_length(
|
||||
hass: HomeAssistant,
|
||||
mock_verisure_config_flow: MagicMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
password: str,
|
||||
error: str,
|
||||
) -> None:
|
||||
"""Test a rejected reauth login hints at the password length when too long."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
result = await mock_config_entry.start_reauth_flow(hass)
|
||||
|
||||
mock_verisure_config_flow.login.side_effect = VerisureLoginError("Login failed")
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{"email": "verisure_my_pages@example.com", "password": password},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result2.get("type") is FlowResultType.FORM
|
||||
assert result2.get("step_id") == "reauth_confirm"
|
||||
assert result2.get("errors") == {"base": error}
|
||||
|
||||
mock_verisure_config_flow.login.side_effect = None
|
||||
result3 = await hass.config_entries.flow.async_configure(
|
||||
result2["flow_id"],
|
||||
{"email": "verisure_my_pages@example.com", "password": "SuperS3cr3t!"},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result3.get("type") is FlowResultType.ABORT
|
||||
assert result3.get("reason") == "reauth_successful"
|
||||
assert mock_config_entry.data == {
|
||||
CONF_GIID: "12345",
|
||||
CONF_EMAIL: "verisure_my_pages@example.com",
|
||||
CONF_PASSWORD: "SuperS3cr3t!",
|
||||
}
|
||||
|
||||
|
||||
async def test_user_flow_mfa_rate_limited(
|
||||
hass: HomeAssistant,
|
||||
mock_verisure_config_flow: MagicMock,
|
||||
|
||||
Reference in New Issue
Block a user