Closes the v0.4.x chapter — NFS works end to end. Five additions: ## Wake-on-LAN (Hosts → Bound hosts) - New core::wol module: parse any MAC form, build the 102-byte magic packet, broadcast it. No special capability needed (ephemeral source port; SO_BROADCAST). Sends to the limited broadcast (255.255.255.255) AND the server's own subnet broadcast (computed from advertised IP + detected mask) so it reaches the right VLAN. - POST /api/hosts/:mac/wol — only fires for *bound* MACs (404 otherwise) so it's not an open packet sprayer. - Bound-hosts table grows a "Wake" button with inline Waking…/Sent ✓ state. ## Webhook notifications (Advanced tab) - core::notify: NotifyConfig + NotifyStore (notify.json), one provider at a time — Slack / Discord / Teams (incoming-webhook JSON) or SMTP. SMTP password is persisted but redacted on GET behind a __keep__ sentinel the UI round-trips so the secret never leaves the box. - http-api::notify: delivery — reqwest POST for chat (provider-shaped bodies), lettre for SMTP (rustls, STARTTLS/implicit TLS, no plaintext). 10s timeout; every send is best-effort. - GET/PUT /api/notify, POST /api/notify/test. - Fired fire-and-forget on the canonical "machine is imaging" boot event and on WoL — never blocks the boot path. ## UI: Advanced tab - New nav item. Holds the webhook config card and the API reference block (relocated from the bottom of Settings). ## UI: login/setup logo (FleetDM treatment) - /api/me now returns has_custom_logo + logo_rev (public bootstrap). The login, setup, and connection-error cards render the uploaded logo full-width with the "OpenPXE" wordmark dropped — matching the sidebar. ## About: update check + licenses - "Check for updates" button → GET /api/updates/check queries the Gitea releases API (derived from CARGO_PKG_REPOSITORY) and compares to the running version. Strictly on-demand — no background polling, keeps the air-gapped promise. - License card documents the MIT OR Apache-2.0 dual license with links, plus a note on bundled components (iPXE GPLv2/UBDL, samba, wimtools). Deps: lettre (SMTP, rustls) + reqwest gains the json feature. Both rustls so the static musl binary stays OpenSSL-free. Tests: 179 passing (+notify round-trip/redaction, webhook validation, WoL-unbound-404, WoL packet loopback, version-compare). clippy clean. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
87 lines
4.4 KiB
Rust
87 lines
4.4 KiB
Rust
use crate::uploads::UploadSessions;
|
|
use crate::auth::SessionStore;
|
|
use openpxe_core::{
|
|
AdminStore, BootLog, BrandingStore, ClientRegistry, DeploymentQueue, HostBindings, LogBus,
|
|
Metrics, NotifyStore, SettingsStore, SsoStore,
|
|
};
|
|
use openpxe_iso_store::{IsoStore, NfsShareManager, SmbManager, SmbShareManager};
|
|
use std::sync::Arc;
|
|
use time::OffsetDateTime;
|
|
|
|
#[derive(Clone)]
|
|
pub struct AppState {
|
|
pub iso_store: IsoStore,
|
|
pub clients: Arc<ClientRegistry>,
|
|
pub settings: Arc<SettingsStore>,
|
|
pub queue: Arc<DeploymentQueue>,
|
|
/// Per-MAC iPXE script overrides. When a client matching one of
|
|
/// these MACs requests `/boot.ipxe`, we chain straight to the
|
|
/// configured target instead of rendering the menu.
|
|
pub hosts: HostBindings,
|
|
/// Persistent boot-event log surfaced under the Hosts tab. Records
|
|
/// every `/boot/<entry>.ipxe` chain that goes on to serve a script
|
|
/// (i.e. an image actually starting to install on a machine).
|
|
pub boot_log: BootLog,
|
|
/// Operator-controlled UI overrides (custom logo). When the
|
|
/// operator hasn't uploaded anything, the WebUI serves the bundled
|
|
/// rainbow-horizon mark.
|
|
pub branding: BrandingStore,
|
|
/// Forms-auth admin record + first-run bootstrap state. When
|
|
/// `admin.is_configured() == false`, the auth middleware passes
|
|
/// every request through and `/api/me` reports `setup_required`.
|
|
pub admin: AdminStore,
|
|
/// In-memory session table for active operator logins. Cleared on
|
|
/// process restart (sessions are tied to UI state, not persisted —
|
|
/// matches Sonarr/Radarr behaviour).
|
|
pub sessions: SessionStore,
|
|
/// SAML SSO configuration. v0.4.5 stores it; the actual SSO login
|
|
/// flow ships in a later release.
|
|
pub sso: SsoStore,
|
|
/// v0.5.0: webhook / email notification config (Slack/Teams/Discord/
|
|
/// SMTP). Drives the fire-and-forget pings on boot events and powers
|
|
/// the Advanced tab's config + "Send test" button.
|
|
pub notify: NotifyStore,
|
|
/// Lock-free metrics counters surfaced at `/metrics` in Prometheus
|
|
/// text format. Cheap to clone (handles to atomics).
|
|
pub metrics: Metrics,
|
|
/// Optional SMB manager. Present when the binary was given a writable
|
|
/// `smb_dir` at startup; `None` in pure-Linux-only deployments where
|
|
/// Windows support is not wired in. Settings toggle drives start/stop.
|
|
pub smb: Option<Arc<SmbManager>>,
|
|
/// v0.4.65: SMB share manager — userspace consumer of remote SMB
|
|
/// shares via Samba's `smbclient` CLI. Replaces the kernel-mount
|
|
/// NFS path that v0.4.64 shipped; that path didn't work on hosts
|
|
/// (Unraid, etc.) whose kernel ships without the nfs/cifs client
|
|
/// modules, and no container-side configuration could fix it.
|
|
/// `smbclient` does the SMB protocol over a plain TCP socket in
|
|
/// userspace — works in any container, no special caps required.
|
|
pub smb_shares: SmbShareManager,
|
|
/// v0.4.67: NFSv3 share manager — pure-Rust userspace consumer
|
|
/// via the `nfs3_client` crate. Ships alongside the SMB manager
|
|
/// so operators pick whichever protocol their NAS prefers.
|
|
/// In-process (no subprocess); supports HTTP Range requests on
|
|
/// NFS-sourced ISOs because NFSv3 READ3 takes an explicit offset.
|
|
pub nfs_shares: NfsShareManager,
|
|
/// Browser chunked upload state. Multipart uploads still go straight
|
|
/// through `IsoStore`, but the UI uses sessions so large ISO transfers
|
|
/// can show deterministic progress and leave visible partial files.
|
|
pub uploads: UploadSessions,
|
|
/// Live log bus consumed by the Terminal tab via SSE. Operator-issued
|
|
/// terminal commands also push synthetic lines onto it so the tail
|
|
/// shows them inline.
|
|
pub log_bus: Arc<LogBus>,
|
|
/// Wall-clock instant the server bound — used for the uptime chip.
|
|
pub started_at: OffsetDateTime,
|
|
/// Base URL advertised to PXE clients (e.g. `http://10.0.0.5`). Used when
|
|
/// rendering iPXE scripts so every URL resolves offline.
|
|
pub public_base_url: String,
|
|
/// Name of the network interface auto-detected at startup (e.g.
|
|
/// `enp1s0`). Surfaced read-only on the Network tab. Empty if the
|
|
/// interface couldn't be identified.
|
|
pub nic_name: String,
|
|
/// Subnet mask of the public interface in dotted-quad form.
|
|
pub subnet_mask: String,
|
|
/// Default gateway IPv4 address.
|
|
pub gateway: String,
|
|
}
|