Add index page with URL generator and remove passphrase from display

Created a beautiful landing page with random room/passphrase generation
and updated security model for read-only access.

New Files:
- server/php/index.html: Landing page with URL generator

Features:
- Random room name generation (e.g., "swift-phoenix-1234")
- Random passphrase generation (16 chars, URL-safe)
- Copy-to-clipboard functionality
- Responsive design with gradient header
- Step-by-step usage instructions
- FAQ section

Security Model Changes:
- WRITE (send transcriptions): Requires room + passphrase
- READ (view display): Only requires room name

Updated Files:
- server.php:
  * handleStream(): Passphrase optional (read-only)
  * handleList(): Passphrase optional (read-only)
  * Added roomExists() helper function

- display.php:
  * Removed passphrase from URL parameters
  * Removed passphrase from SSE connection
  * Removed passphrase from list endpoint

Benefits:
- Display URL is safer (no passphrase in OBS browser source)
- Simpler setup (only room name needed for viewing)
- Better security model (write-protected, read-open)
- Anyone with room name can watch, only authorized can send

Example URLs:
- Client: server.php (with room + passphrase in app settings)
- Display: display.php?room=swift-phoenix-1234&fade=10&timestamps=true

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-26 10:18:40 -08:00
parent fec44f9757
commit 2c341e8cea
3 changed files with 387 additions and 15 deletions

View File

@@ -83,18 +83,26 @@ function handleSend() {
/**
* Handle streaming transcriptions via Server-Sent Events
* Note: Passphrase is optional for streaming (read-only access)
*/
function handleStream() {
// Get parameters
$room = sanitize($_GET['room'] ?? '');
$passphrase = $_GET['passphrase'] ?? '';
if (empty($room) || empty($passphrase)) {
sendError('Missing room or passphrase', 400);
if (empty($room)) {
sendError('Missing room name', 400);
}
if (!verifyPassphrase($room, $passphrase)) {
sendError('Invalid passphrase', 401);
// Passphrase is optional for streaming (read-only)
// If room doesn't exist yet, return empty stream
if (!roomExists($room)) {
// Return empty stream - room doesn't exist yet
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('X-Accel-Buffering: no');
echo ": waiting for room to be created\n\n";
flush();
exit();
}
// Set SSE headers
@@ -136,19 +144,17 @@ function handleStream() {
/**
* Handle listing recent transcriptions
* Note: Passphrase is optional for listing (read-only access)
*/
function handleList() {
$room = sanitize($_GET['room'] ?? '');
$passphrase = $_GET['passphrase'] ?? '';
if (empty($room) || empty($passphrase)) {
sendError('Missing room or passphrase', 400);
}
if (!verifyPassphrase($room, $passphrase)) {
sendError('Invalid passphrase', 401);
if (empty($room)) {
sendError('Missing room name', 400);
}
// Passphrase is optional for read-only access
// If room doesn't exist, return empty array
$transcriptions = getTranscriptions($room);
sendJson(['transcriptions' => $transcriptions]);
}
@@ -235,6 +241,13 @@ function getRoomFile($room) {
return STORAGE_DIR . '/room_' . md5($room) . '.json';
}
/**
* Check if room exists
*/
function roomExists($room) {
return file_exists(getRoomFile($room));
}
/**
* Cleanup old sessions
*/