Compare commits
2
Commits
271f2d1fb5
...
dcf2a1200c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dcf2a1200c | ||
|
|
364b4db200 |
No files matched your search
@@ -8,6 +8,7 @@ DISPLAY_NUM="${VNC_DISPLAY_NUM:-99}"
|
|||||||
VNC_PORT="${VNC_PORT:-5900}"
|
VNC_PORT="${VNC_PORT:-5900}"
|
||||||
NOVNC_PORT="${NOVNC_PORT:-6080}"
|
NOVNC_PORT="${NOVNC_PORT:-6080}"
|
||||||
GEOMETRY="${SCREEN_GEOMETRY:-1280x800x24}"
|
GEOMETRY="${SCREEN_GEOMETRY:-1280x800x24}"
|
||||||
|
BROWSER_SESSION_DIR="${BROWSER_SESSION_DIR:-/app/data/browser-session}"
|
||||||
export DISPLAY=":${DISPLAY_NUM}"
|
export DISPLAY=":${DISPLAY_NUM}"
|
||||||
|
|
||||||
# noVNC ships under different paths depending on the distro; find the web root once.
|
# noVNC ships under different paths depending on the distro; find the web root once.
|
||||||
@@ -29,6 +30,15 @@ fi
|
|||||||
# to bind to the display and the bot starts up with no X server.
|
# to bind to the display and the bot starts up with no X server.
|
||||||
rm -f "/tmp/.X${DISPLAY_NUM}-lock" "/tmp/.X11-unix/X${DISPLAY_NUM}" 2>/dev/null || true
|
rm -f "/tmp/.X${DISPLAY_NUM}-lock" "/tmp/.X11-unix/X${DISPLAY_NUM}" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Persistent profiles retain Chromium's singleton artifacts when a container
|
||||||
|
# is replaced before Chromium exits cleanly. Remove only those locks; cookies,
|
||||||
|
# local storage, and the rest of the authenticated profile remain untouched.
|
||||||
|
rm -f \
|
||||||
|
"${BROWSER_SESSION_DIR}/SingletonLock" \
|
||||||
|
"${BROWSER_SESSION_DIR}/SingletonSocket" \
|
||||||
|
"${BROWSER_SESSION_DIR}/SingletonCookie" \
|
||||||
|
2>/dev/null || true
|
||||||
|
|
||||||
echo "[entrypoint] starting Xvfb on ${DISPLAY} (${GEOMETRY})"
|
echo "[entrypoint] starting Xvfb on ${DISPLAY} (${GEOMETRY})"
|
||||||
Xvfb "${DISPLAY}" -screen 0 "${GEOMETRY}" -ac +extension RANDR &
|
Xvfb "${DISPLAY}" -screen 0 "${GEOMETRY}" -ac +extension RANDR &
|
||||||
XVFB_PID=$!
|
XVFB_PID=$!
|
||||||
|
|||||||
+31
-12
@@ -27,15 +27,22 @@ The RedditBot web dashboard exposes a REST API for monitoring and controlling th
|
|||||||
|
|
||||||
**Content-Type**: `application/json` (except SSE)
|
**Content-Type**: `application/json` (except SSE)
|
||||||
**Response Format**: JSON
|
**Response Format**: JSON
|
||||||
**Authentication**: None (local network only)
|
**Authentication**: Dashboard session cookie or bearer token
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Authentication
|
## Authentication
|
||||||
|
|
||||||
No authentication is required. The dashboard is intended for local network access only.
|
The dashboard, API, SSE streams, and private media require the token configured
|
||||||
|
through `WEB_DASHBOARD_TOKEN` (preferred) or `web.authToken`. Interactive users
|
||||||
|
exchange the token for an HttpOnly, SameSite=Strict session cookie at
|
||||||
|
`POST /auth/session`. API clients may instead send
|
||||||
|
`Authorization: Bearer <token>`.
|
||||||
|
|
||||||
> **Security Note**: If exposing the dashboard externally, add authentication (e.g., basic auth, reverse proxy with auth).
|
`GET /auth/login` and `POST /auth/session` are the only unauthenticated
|
||||||
|
dashboard routes. A rejected API request returns HTTP 401 with
|
||||||
|
`{"error":"Dashboard authentication required"}`. Debug endpoints are absent
|
||||||
|
unless `web.debugEnabled` is explicitly enabled.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -976,22 +983,34 @@ All error responses follow this format:
|
|||||||
|
|
||||||
## SSE Events
|
## SSE Events
|
||||||
|
|
||||||
The SSE log stream (`/api/logs/stream`) emits the following events:
|
`GET /api/events/stream` is the typed resumable event stream used by the React
|
||||||
|
dashboard. Each SSE frame contains `id`, `event`, and `data` fields. The data is
|
||||||
### `log` Event
|
the complete validated event envelope:
|
||||||
|
|
||||||
Emitted for every log entry.
|
|
||||||
|
|
||||||
**Data Format**:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
"id": "1786201200000-000000",
|
||||||
|
"occurredAt": "2026-08-08T15:00:00.000Z",
|
||||||
|
"type": "log.created",
|
||||||
|
"payload": {
|
||||||
"level": "info",
|
"level": "info",
|
||||||
"message": "Processed post abc123 from r/gonewild",
|
"message": "Dashboard started"
|
||||||
"timestamp": "2024-01-15T10:30:00.000Z"
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Clients may reconnect with `Last-Event-ID`; the server replays retained events
|
||||||
|
after that ID in order. The stream sends heartbeats, bounds buffered events and
|
||||||
|
slow-client queues, and requires the same dashboard authentication as the API.
|
||||||
|
|
||||||
|
Current event families include bot status, message sent or failed,
|
||||||
|
conversation updated, reply received, sync lifecycle and progress, rate-limit
|
||||||
|
state, Reddit session state, and logs.
|
||||||
|
|
||||||
|
`GET /api/logs/stream` remains temporarily available for the legacy dashboard.
|
||||||
|
Its untyped `connected`, `log`, and `sync-progress` frames should not be used by
|
||||||
|
new clients.
|
||||||
|
|
||||||
**Log Levels**:
|
**Log Levels**:
|
||||||
|
|
||||||
| Level | Description |
|
| Level | Description |
|
||||||
|
|||||||
@@ -13,4 +13,13 @@ describe('VNC container entrypoint', () => {
|
|||||||
script.indexOf('starting noVNC'),
|
script.indexOf('starting noVNC'),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('removes only stale Chromium singleton artifacts before launching the bot', () => {
|
||||||
|
const script = fs.readFileSync(path.resolve('docker/entrypoint.sh'), 'utf8');
|
||||||
|
|
||||||
|
expect(script).toContain('"${BROWSER_SESSION_DIR}/SingletonLock"');
|
||||||
|
expect(script).toContain('"${BROWSER_SESSION_DIR}/SingletonSocket"');
|
||||||
|
expect(script).toContain('"${BROWSER_SESSION_DIR}/SingletonCookie"');
|
||||||
|
expect(script.indexOf('SingletonLock')).toBeLessThan(script.indexOf('launching bot'));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
Reference in new issue
Block a user