feat(homeassistant): an admin signs in to Home Assistant, with nothing added to it (#6355)
Replaces the read-only token and the webhook automation, which every install would have had to paste into its own Home Assistant. Connect now goes to Home Assistant's own sign-in page, and Steward keeps the refresh token that comes back, encrypted, and calls backup.create_automatic and update.install directly. The connection page warns that the stored credential has the same access as the user who signed in, and recommends a service account so Steward's actions are easy to tell apart in Home Assistant's logs. A user who isn't an administrator gets the status page and no Install. Those actions answer only when finished, so a request cut off once sent counts as sent and the outcome is read from the entities. Removing the connection, or signing in again, ends the old sign-in on Home Assistant. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,6 @@ from typing import TYPE_CHECKING
|
||||
|
||||
from sqlalchemy import select
|
||||
|
||||
from steward.core.crypto import decrypt_secret
|
||||
from steward.core.scheduler import ScheduledTask
|
||||
|
||||
from . import client
|
||||
@@ -65,9 +64,9 @@ async def poll(app: "Quart", transport=None) -> None:
|
||||
connection = (await session.execute(select(HomeAssistantConnection))).scalars().first()
|
||||
if connection is None or not is_due(connection, now):
|
||||
return
|
||||
token = decrypt_secret(connection.token, context="Home Assistant token")
|
||||
snapshot, error, refused = None, None, False
|
||||
try:
|
||||
token = await client.access_token(connection, transport)
|
||||
snapshot = read_snapshot(await client.read_states(connection.url, token, connection.verify_tls, transport))
|
||||
except client.Refused as exc:
|
||||
error, refused = str(exc), True
|
||||
@@ -84,7 +83,7 @@ async def poll(app: "Quart", transport=None) -> None:
|
||||
batch.add(source_module=SOURCE, resource_name=RESOURCE, metric_name="is_up", value=0.0, recorded_at=now)
|
||||
else:
|
||||
row.last_ok_at = now
|
||||
row.updates, row.backup, row.automation = snapshot["updates"], snapshot["backup"], snapshot["automation"]
|
||||
row.updates, row.backup = snapshot["updates"], snapshot["backup"]
|
||||
batch.add(source_module=SOURCE, resource_name=RESOURCE, metric_name="is_up", value=1.0, recorded_at=now)
|
||||
batch.add(source_module=SOURCE, resource_name=RESOURCE, metric_name="updates_waiting",
|
||||
value=len(installable(row)), recorded_at=now)
|
||||
|
||||
Reference in New Issue
Block a user