diff --git a/homeassistant/components/pushover/__init__.py b/homeassistant/components/pushover/__init__.py index fa9a9c5ebd9..3c0c92db044 100644 --- a/homeassistant/components/pushover/__init__.py +++ b/homeassistant/components/pushover/__init__.py @@ -25,6 +25,10 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up pushover from a config entry.""" + # remove unique_id for beta users + if entry.unique_id is not None: + hass.config_entries.async_update_entry(entry, unique_id=None) + pushover_api = PushoverAPI(entry.data[CONF_API_KEY]) try: await hass.async_add_executor_job( diff --git a/homeassistant/components/pushover/config_flow.py b/homeassistant/components/pushover/config_flow.py index 3f12446733e..ddb61d4bbc3 100644 --- a/homeassistant/components/pushover/config_flow.py +++ b/homeassistant/components/pushover/config_flow.py @@ -62,6 +62,12 @@ class PushBulletConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): errors = {} if user_input is not None and self._reauth_entry: user_input = {**self._reauth_entry.data, **user_input} + self._async_abort_entries_match( + { + CONF_USER_KEY: user_input[CONF_USER_KEY], + CONF_API_KEY: user_input[CONF_API_KEY], + } + ) errors = await validate_input(self.hass, user_input) if not errors: self.hass.config_entries.async_update_entry( @@ -87,9 +93,13 @@ class PushBulletConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): errors = {} if user_input is not None: - await self.async_set_unique_id(user_input[CONF_USER_KEY]) - self._abort_if_unique_id_configured() + self._async_abort_entries_match( + { + CONF_USER_KEY: user_input[CONF_USER_KEY], + CONF_API_KEY: user_input[CONF_API_KEY], + } + ) self._async_abort_entries_match({CONF_NAME: user_input[CONF_NAME]}) errors = await validate_input(self.hass, user_input) diff --git a/tests/components/pushover/test_config_flow.py b/tests/components/pushover/test_config_flow.py index 21c0bc3ab1e..1e919167c6a 100644 --- a/tests/components/pushover/test_config_flow.py +++ b/tests/components/pushover/test_config_flow.py @@ -48,12 +48,11 @@ async def test_flow_user(hass: HomeAssistant) -> None: assert result["data"] == MOCK_CONFIG -async def test_flow_user_key_already_configured(hass: HomeAssistant) -> None: - """Test user initialized flow with duplicate user key.""" +async def test_flow_user_key_api_key_exists(hass: HomeAssistant) -> None: + """Test user initialized flow with duplicate user key / api key pair.""" entry = MockConfigEntry( domain=DOMAIN, data=MOCK_CONFIG, - unique_id="MYUSERKEY", ) entry.add_to_hass(hass) @@ -171,7 +170,7 @@ async def test_reauth_success(hass: HomeAssistant) -> None: data=MOCK_CONFIG, ) - assert result["type"] == "form" + assert result["type"] == FlowResultType.FORM assert result["step_id"] == "reauth_confirm" result2 = await hass.config_entries.flow.async_configure( @@ -181,7 +180,7 @@ async def test_reauth_success(hass: HomeAssistant) -> None: }, ) - assert result2["type"] == "abort" + assert result2["type"] == FlowResultType.ABORT assert result2["reason"] == "reauth_successful" @@ -213,7 +212,47 @@ async def test_reauth_failed(hass: HomeAssistant, mock_pushover: MagicMock) -> N }, ) - assert result2["type"] == "form" + assert result2["type"] == FlowResultType.FORM assert result2["errors"] == { CONF_API_KEY: "invalid_api_key", } + + +async def test_reauth_with_existing_config(hass: HomeAssistant) -> None: + """Test reauth fails if the api key entered exists in another entry.""" + entry = MockConfigEntry( + domain=DOMAIN, + data=MOCK_CONFIG, + ) + entry.add_to_hass(hass) + + second_entry = MOCK_CONFIG.copy() + second_entry[CONF_API_KEY] = "MYAPIKEY2" + + entry2 = MockConfigEntry( + domain=DOMAIN, + data=second_entry, + ) + entry2.add_to_hass(hass) + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={ + "source": config_entries.SOURCE_REAUTH, + "entry_id": entry.entry_id, + }, + data=MOCK_CONFIG, + ) + + assert result["type"] == FlowResultType.FORM + assert result["step_id"] == "reauth_confirm" + + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_API_KEY: "MYAPIKEY2", + }, + ) + + assert result2["type"] == FlowResultType.ABORT + assert result2["reason"] == "already_configured" diff --git a/tests/components/pushover/test_init.py b/tests/components/pushover/test_init.py index 4d1ee3cae19..7a8b02c93a0 100644 --- a/tests/components/pushover/test_init.py +++ b/tests/components/pushover/test_init.py @@ -68,6 +68,16 @@ async def test_async_setup_entry_success(hass: HomeAssistant) -> None: assert entry.state == ConfigEntryState.LOADED +async def test_unique_id_updated(hass: HomeAssistant) -> None: + """Test updating unique_id to new format.""" + entry = MockConfigEntry(domain=DOMAIN, data=MOCK_CONFIG, unique_id="MYUSERKEY") + entry.add_to_hass(hass) + await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done() + assert entry.state == ConfigEntryState.LOADED + assert entry.unique_id is None + + async def test_async_setup_entry_failed_invalid_api_key( hass: HomeAssistant, mock_pushover: MagicMock ) -> None: