Use live remote domain for the cloud remote UI URL (#183284)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Paulus Schoutsen
2026-09-28 04:42:10 -04:00
committed by GitHub
co-authored by Claude
parent cc999c32a9
commit 1f57f170da
4 changed files with 81 additions and 5 deletions
+10 -3
View File
@@ -287,10 +287,16 @@ def async_remote_ui_url(hass: HomeAssistant) -> str:
if not async_is_logged_in(hass):
raise CloudNotAvailable
if not hass.data[DATA_CLOUD].client.prefs.remote_enabled:
cloud = hass.data[DATA_CLOUD]
if not cloud.client.prefs.remote_enabled:
raise CloudNotAvailable
if not (remote_domain := hass.data[DATA_CLOUD].client.prefs.remote_domain):
# Fall back to the domain in the preferences while the remote backend is
# not loaded.
if not (
remote_domain := cloud.remote.instance_domain
or cloud.client.prefs.remote_domain
):
raise CloudNotAvailable
return f"https://{remote_domain}"
@@ -375,7 +381,8 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
async def _on_initialized() -> None:
"""Update preferences."""
await prefs.async_update(remote_domain=cloud.remote.instance_domain)
if (remote_domain := cloud.remote.instance_domain) != prefs.remote_domain:
await prefs.async_update(remote_domain=remote_domain)
hass.data[DATA_PENDING_AUTO_LOGIN] = None
+9
View File
@@ -10,6 +10,7 @@ from typing import Any, Literal, override
import aiohttp
from hass_nabucasa.client import CloudClient as Interface, RemoteActivationNotAllowed
from hass_nabucasa.const import DISPATCH_REMOTE_BACKEND_UP
from webrtc_models import RTCIceServer
from homeassistant.components import google_assistant, persistent_notification, webhook
@@ -309,6 +310,14 @@ class CloudClient(Interface):
@override
def dispatcher_message(self, identifier: str, data: Any = None) -> None:
"""Match cloud notification to dispatcher."""
if (
identifier == DISPATCH_REMOTE_BACKEND_UP
and (remote_domain := self.cloud.remote.instance_domain)
!= self._prefs.remote_domain
):
self._hass.async_create_task(
self._prefs.async_update(remote_domain=remote_domain)
)
if identifier.startswith("remote_"):
async_dispatcher_send(self._hass, DISPATCHER_REMOTE_UPDATE, data)
+28 -1
View File
@@ -3,7 +3,7 @@
from collections.abc import Callable, Coroutine
from datetime import timedelta
from typing import Any
from unittest.mock import AsyncMock, MagicMock, Mock, PropertyMock, patch
from unittest.mock import AsyncMock, MagicMock, Mock, PropertyMock, call, patch
import aiohttp
from aiohttp import web
@@ -634,6 +634,33 @@ async def test_remote_enable(hass: HomeAssistant) -> None:
prefs.async_update.assert_called_once_with(remote_enabled=True)
@pytest.mark.parametrize(
("stored_domain", "expected_calls"),
[
pytest.param(None, 1, id="changed"),
pytest.param("example.ui.nabu.casa", 0, id="unchanged"),
],
)
async def test_remote_backend_up_updates_remote_domain(
hass: HomeAssistant, stored_domain: str | None, expected_calls: int
) -> None:
"""Test the remote domain preference is synced when the backend is up."""
prefs = MagicMock(
async_update=AsyncMock(return_value=None), remote_domain=stored_domain
)
client = CloudClient(hass, prefs, None, {}, {})
client.cloud = MagicMock()
client.cloud.remote.instance_domain = "example.ui.nabu.casa"
client.dispatcher_message("remote_backend_up")
await hass.async_block_till_done()
assert (
prefs.async_update.call_args_list
== [call(remote_domain="example.ui.nabu.casa")] * expected_calls
)
async def test_remote_enable_not_allowed(hass: HomeAssistant) -> None:
"""Test enabling remote UI."""
prefs = MagicMock(
+34 -1
View File
@@ -2,7 +2,7 @@
from collections.abc import Callable, Coroutine
from typing import Any
from unittest.mock import MagicMock, patch
from unittest.mock import MagicMock, call, patch
from hass_nabucasa import (
AutoLoginController,
@@ -278,6 +278,39 @@ async def test_remote_ui_url(hass: HomeAssistant) -> None:
assert async_remote_ui_url(hass) == "https://example.com"
# Remote backend loaded after a login, stored domain not refreshed
cl.client.prefs._prefs["remote_domain"] = None
with patch.object(cl.remote, "_instance_domain", "live.example.com"):
assert async_remote_ui_url(hass) == "https://live.example.com"
@pytest.mark.parametrize(
("stored_domain", "expected_calls"),
[
pytest.param(None, 1, id="changed"),
pytest.param("example.ui.nabu.casa", 0, id="unchanged"),
],
)
@pytest.mark.usefixtures("mock_cloud_fixture")
async def test_on_initialized_updates_remote_domain(
hass: HomeAssistant, stored_domain: str | None, expected_calls: int
) -> None:
"""Test the remote domain preference is synced when cloud is initialized."""
cl = hass.data[DATA_CLOUD]
cl.client.prefs._prefs["remote_domain"] = stored_domain
(on_initialized,) = cl._on_initialized
with (
patch.object(cl.remote, "_instance_domain", "example.ui.nabu.casa"),
patch.object(cl.client.prefs, "async_update") as mock_update,
):
await on_initialized()
assert (
mock_update.call_args_list
== [call(remote_domain="example.ui.nabu.casa")] * expected_calls
)
async def test_async_get_or_create_cloudhook(
hass: HomeAssistant,