mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-18 11:56:01 +02:00
fix(overlay): authenticate the OBS overlay with a token when login is enabled (#2613)
The /overlay/{id} route renders without a login, but everything it draws is
auth-gated: printer status and name (PRINTERS_READ), one setting (SETTINGS_READ),
and the camera stream (a camera-stream token). A signed-in browser rides its JWT
from local storage; OBS is a fresh browser with no session, so the overlay stayed
blank whenever authentication was enabled. Cloudflare/remote access was never the
cause -- an incognito window fails identically.
Give the overlay a self-contained kiosk-token mode, mirroring the Cam Wall:
- New `overlay` long-lived-token scope, kept separate from `camwall`: the overlay
names the printed file on screen, which a Cam Wall token is trusted never to
expose, so folding it in would silently widen every existing wall token.
- New token-authed GET /printers/{id}/overlay-status returning exactly the fields
the overlay draws and nothing else; added to the auth-middleware allowlist so it
reaches its own RequireOverlayTokenIfAuthEnabled gate.
- StreamOverlayPage reads ?token= and, in that mode, authenticates its status and
camera calls with the token and skips the WebSocket (the 2s poll is the feed).
The logged-in path is unchanged.
- Token-mint UI (Settings > API Keys) offers the scope with a ready-made
/overlay/{id}?token= URL copied once on creation.
This commit is contained in:
@@ -294,7 +294,7 @@ export interface SystemHealthResult {
|
||||
// 'camera_stream' reaches the video endpoints only. 'camwall' additionally
|
||||
// reaches the read-only Cam Wall feed, which names the printers (#2531), so it
|
||||
// is a separate scope rather than a widening of tokens already in the wild.
|
||||
export type LongLivedTokenScope = 'camera_stream' | 'camwall';
|
||||
export type LongLivedTokenScope = 'camera_stream' | 'camwall' | 'overlay';
|
||||
|
||||
export interface LongLivedCameraToken {
|
||||
id: number;
|
||||
@@ -324,6 +324,26 @@ export interface CamWallPrinter {
|
||||
hms_errors: HMSError[];
|
||||
}
|
||||
|
||||
// Streaming-overlay feed (#2613). The subset of print state the /overlay page
|
||||
// draws for one printer, served behind an `overlay`-scoped token so OBS embeds
|
||||
// with no login session can read it. Unlike CamWallPrinter this names the file
|
||||
// being printed (the overlay shows the part on screen).
|
||||
export interface OverlayStatus {
|
||||
id: number;
|
||||
name: string;
|
||||
camera_rotation: number;
|
||||
connected: boolean;
|
||||
state: string | null;
|
||||
current_print: string | null;
|
||||
gcode_file: string | null;
|
||||
progress: number | null;
|
||||
remaining_time: number | null;
|
||||
layer_num: number | null;
|
||||
total_layers: number | null;
|
||||
stg_cur_name: string | null;
|
||||
time_format: 'system' | '12h' | '24h';
|
||||
}
|
||||
|
||||
// Printer types
|
||||
export interface Printer {
|
||||
id: number;
|
||||
@@ -5748,6 +5768,15 @@ export const api = {
|
||||
request<CamWallPrinter[]>(
|
||||
token ? `/camwall/printers?token=${encodeURIComponent(token)}` : '/camwall/printers',
|
||||
),
|
||||
// Token-authenticated streaming-overlay feed (#2613). OBS (or any embed with
|
||||
// no login session) loads /overlay/{id}?token=... and this backs it. `token`
|
||||
// is omitted only when auth is disabled, where the backend gate is a no-op.
|
||||
getOverlayStatus: (printerId: number, token?: string) =>
|
||||
request<OverlayStatus>(
|
||||
token
|
||||
? `/printers/${printerId}/overlay-status?token=${encodeURIComponent(token)}`
|
||||
: `/printers/${printerId}/overlay-status`,
|
||||
),
|
||||
getCameraStreamUrl: (printerId: number, fps = 10) =>
|
||||
withStreamToken(`${API_BASE}/printers/${printerId}/camera/stream?fps=${fps}`),
|
||||
getCameraSnapshotUrl: (printerId: number) =>
|
||||
|
||||
Reference in New Issue
Block a user