Extracts host info assembly (owner, managers, hbc version/type,
last packet timestamp, threshold configs) into a testable module-level
helper, with 10 covering tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Allows any authenticated user to update their own full_name, avatar,
notification_channels, and password via the config YAML write path.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move field-extraction inside the try/except in fetch_user so non-dict
responses from providers with empty profile_data_path (Gitea, GitHub)
raise OAuthError instead of an uncaught AttributeError. Apply
html.escape() to provider name, label, and logo URL in the login page.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace hardcoded Gitea OAuth handlers with generic {name}-parameterized
routes and update the login page to render a button for each configured
provider via oauth_mod.get_providers().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
purge_stale_alerts used _find_threshold to validate alert state keys,
but _find_threshold has no wildcard matching. A threshold configured as
"zfs_monitor.*.status" never matched the concrete alert state key
"zfs_monitor.tank.status", so every restart silently purged active ZFS
pool alert states and reset the grace period from scratch.
Also fix _check_pending_or_renotify to set last_notification after the
grace-period notification fires, so the re-notification interval is
anchored to when the alert was actually sent rather than the next PLG cycle.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add regex filter input to the Alerts dashboard that filters displayed
hosts on every keystroke; invalid regex turns the border red
- Initialise the filter from ?filter= in the URL query string
- Change _build_url() to produce /alerts?filter=<hostname> so
notification links (Pushover, email, Matrix, etc.) land on the
alerts page pre-filtered to the alerting host
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reads oauth.gitea.logo from config and, when set, renders an <img>
inside the button with flex alignment.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Older hbd clients send zfs_monitor data with a `health` string but no
`health_ok` numeric field (added in a recent plugin update). Without
health_ok in the data, the wildcard threshold check found nothing and
no CRITICAL alert was raised for DEGRADED/SUSPENDED pools.
Synthesize health_ok from the health string in the server's nested-
metric loop so alerts fire regardless of client version.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove unused `_gitea_cfg_url` module-level helper from http.py
- Add logger.warning on invalid/expired state in oauth_gitea_callback
- Add test_callback_invalid_state_rejects and test_full_oauth_flow_chain to tests/test_oauth.py (21 tests total, all passing)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Creates or updates a user from an OAuth2 provider: new users are
inserted with an empty password_hash (OAuth-only login); existing users
have their display name and avatar refreshed while all other attributes
(admin flag, password_hash, notification_channels) are preserved.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add hbd/server/oauth.py with OAuthError, _gitea_cfg(), and is_enabled()
to detect when all three required Gitea OAuth2 config keys are present.
Add "oauth": {} default to SERVER_DEFAULTS in config.py.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Store owner in data-owner attribute; updateHostHeader always prepends it
so it survives innerHTML replacement. Render it immediately on page load
before JS fetches plugin data.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- When os_info arrives with no owner field, apply default_owner from server config
- Stop applying default_owner unconditionally in get_host_access (now deferred to os_info handling)
- os_info plugin logs debug message when injecting owner from client config
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>