fix: surface all calendar sync failures, not just Google

CalDAV and Home Assistant sync failures were previously only logged
server-side, leaving clients unable to distinguish an empty calendar
from a broken sync. Unify error reporting across CalDAV, Home
Assistant, and Google into a single errors list on GET
/api/caldav/events, shaped as {source, name, message}. Messages are
fixed generic strings, never raw exception text, to avoid leaking
URLs or credential fragments. get_ha_events and get_google_events now
return (events, errors) tuples so per-calendar failures propagate to
the caller in addition to account-level failures. Frontend toast now
picks its label from err.source instead of assuming Google/err.email.
This commit is contained in:
Scarriffle
2026-07-02 18:22:11 +02:00
parent 94655ce7c5
commit 9fb350eb29
4 changed files with 54 additions and 11 deletions

View File

@@ -313,8 +313,15 @@ def _parse_ha_event(ev: dict, cal_db_id: int, cal_name: str, cal_color: str) ->
}
def get_ha_events(account: models.HomeAssistantAccount, start_dt: datetime, end_dt: datetime, db: Session) -> list:
def get_ha_events(account: models.HomeAssistantAccount, start_dt: datetime, end_dt: datetime, db: Session) -> tuple:
"""Fetch events from all enabled HA calendars for an account.
Returns (events, errors) — errors is a list of
{"source": "homeassistant", "name": ..., "message": ...} dicts for any
calendar that failed to sync. Never includes raw exception text.
"""
all_events = []
errors = []
try:
token = _get_valid_token(account, db)
except Exception as exc:
@@ -330,7 +337,12 @@ def get_ha_events(account: models.HomeAssistantAccount, start_dt: datetime, end_
all_events.append(_parse_ha_event(ev, cal.id, cal.name, color))
except Exception as exc:
logger.error("HA event fetch error %s (%s): %s", cal.entity_id, account.name, exc)
return all_events
errors.append({
"source": "homeassistant",
"name": f"{account.name} {cal.name}",
"message": "Sync fehlgeschlagen",
})
return all_events, errors
# ── Serialization ─────────────────────────────────────────