mirror of
https://github.com/home-assistant/core.git
synced 2026-05-08 17:49:37 +01:00
Add support for multiple entries to Xbox integration (#155771)
This commit is contained in:
@@ -38,10 +38,6 @@ class OAuth2FlowHandler(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle a flow start."""
|
||||
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
|
||||
return await super().async_step_user(user_input)
|
||||
|
||||
async def async_oauth_create_entry(self, data: dict) -> ConfigFlowResult:
|
||||
@@ -57,4 +53,5 @@ class OAuth2FlowHandler(
|
||||
me = await client.people.get_friends_by_xuid(client.xuid)
|
||||
|
||||
await self.async_set_unique_id(client.xuid)
|
||||
self._abort_if_unique_id_configured()
|
||||
return self.async_create_entry(title=me.people[0].gamertag, data=data)
|
||||
|
||||
@@ -199,8 +199,13 @@ class XboxUpdateCoordinator(DataUpdateCoordinator[XboxData]):
|
||||
) from e
|
||||
else:
|
||||
presence_data = {self.client.xuid: batch.people[0]}
|
||||
configured_xuids = self.configured_as_entry()
|
||||
presence_data.update(
|
||||
{friend.xuid: friend for friend in friends.people if friend.is_favorite}
|
||||
{
|
||||
friend.xuid: friend
|
||||
for friend in friends.people
|
||||
if friend.is_favorite and friend.xuid not in configured_xuids
|
||||
}
|
||||
)
|
||||
|
||||
# retrieve title details
|
||||
@@ -252,9 +257,11 @@ class XboxUpdateCoordinator(DataUpdateCoordinator[XboxData]):
|
||||
"""Remove stale devices from registry."""
|
||||
|
||||
device_reg = dr.async_get(self.hass)
|
||||
identifiers = {(DOMAIN, xuid) for xuid in xuids} | {
|
||||
(DOMAIN, console.id) for console in self.consoles.result
|
||||
}
|
||||
identifiers = (
|
||||
{(DOMAIN, xuid) for xuid in xuids}
|
||||
| {(DOMAIN, console.id) for console in self.consoles.result}
|
||||
| self.configured_as_entry()
|
||||
)
|
||||
|
||||
for device in dr.async_entries_for_config_entry(
|
||||
device_reg, self.config_entry.entry_id
|
||||
@@ -264,3 +271,12 @@ class XboxUpdateCoordinator(DataUpdateCoordinator[XboxData]):
|
||||
device_reg.async_update_device(
|
||||
device.id, remove_config_entry_id=self.config_entry.entry_id
|
||||
)
|
||||
|
||||
def configured_as_entry(self) -> set[str]:
|
||||
"""Get xuids of configured entries."""
|
||||
|
||||
return {
|
||||
entry.unique_id
|
||||
for entry in self.hass.config_entries.async_entries(DOMAIN)
|
||||
if entry.unique_id is not None
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_account%]",
|
||||
"authorize_url_timeout": "[%key:common::config_flow::abort::oauth2_authorize_url_timeout%]",
|
||||
"missing_configuration": "[%key:common::config_flow::abort::oauth2_missing_configuration%]",
|
||||
"oauth_error": "[%key:common::config_flow::abort::oauth2_error%]",
|
||||
"oauth_failed": "[%key:common::config_flow::abort::oauth2_failed%]",
|
||||
"oauth_timeout": "[%key:common::config_flow::abort::oauth2_timeout%]",
|
||||
"oauth_unauthorized": "[%key:common::config_flow::abort::oauth2_unauthorized%]",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
"oauth_unauthorized": "[%key:common::config_flow::abort::oauth2_unauthorized%]"
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "[%key:common::config_flow::create_entry::authenticated%]"
|
||||
|
||||
@@ -67,6 +67,7 @@ def mock_config_entry() -> MockConfigEntry:
|
||||
"user_id": "AAAAAAAAAAAAAAAAAAAAA",
|
||||
},
|
||||
},
|
||||
unique_id="271958441785640",
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -18,17 +18,6 @@ from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
from tests.typing import ClientSessionGenerator
|
||||
|
||||
|
||||
async def test_abort_if_existing_entry(hass: HomeAssistant) -> None:
|
||||
"""Check flow abort when an entry already exist."""
|
||||
MockConfigEntry(domain=DOMAIN).add_to_hass(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
"xbox", context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "single_instance_allowed"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
"current_request_with_host",
|
||||
"xbox_live_client",
|
||||
@@ -90,6 +79,58 @@ async def test_full_flow(
|
||||
assert len(mock_setup.mock_calls) == 1
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
"current_request_with_host",
|
||||
"xbox_live_client",
|
||||
"authentication_manager",
|
||||
)
|
||||
async def test_form_already_configured(
|
||||
hass: HomeAssistant,
|
||||
hass_client_no_auth: ClientSessionGenerator,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test we abort flow when entry is already configured."""
|
||||
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
state = config_entry_oauth2_flow._encode_jwt(
|
||||
hass,
|
||||
{
|
||||
"flow_id": result["flow_id"],
|
||||
"redirect_uri": "https://example.com/auth/external/callback",
|
||||
},
|
||||
)
|
||||
|
||||
client = await hass_client_no_auth()
|
||||
resp = await client.get(f"/auth/external/callback?code=abcd&state={state}")
|
||||
assert resp.status == HTTPStatus.OK
|
||||
assert resp.headers["content-type"] == "text/html; charset=utf-8"
|
||||
|
||||
aioclient_mock.post(
|
||||
OAUTH2_TOKEN,
|
||||
json={
|
||||
"refresh_token": "mock-refresh-token",
|
||||
"access_token": "mock-access-token",
|
||||
"type": "Bearer",
|
||||
"expires_in": 60,
|
||||
"scope": "XboxLive.signin XboxLive.offline_access",
|
||||
"service": "xbox",
|
||||
"token_type": "bearer",
|
||||
"user_id": "AAAAAAAAAAAAAAAAAAAAA",
|
||||
},
|
||||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("xbox_live_client")
|
||||
async def test_unique_id_migration(
|
||||
hass: HomeAssistant,
|
||||
|
||||
Reference in New Issue
Block a user