Security and reliability fixes: XSS, race conditions, logging
- Fix XSS in workflow list: escape name/description/created_by with escapeHtml() - Fix broadcast() race: snapshot browserClients Set before iterating - Fix waitForCommandResult: use position-based matching (worker omits command_id in result) - Fix scheduler duplicate-run race: atomic UPDATE with affectedRows check - Suppress toast alerts for automated executions (gandalf:/scheduler: prefix) - Add waiting_for_input + prompt fields to GET /executions/:id - Add GET /api/workflows/:id endpoint - Add interactive prompt UI: respondToPrompt(), WebSocket execution_prompt handler - Add workflow editor modal (admin-only) - Remove sensitive console.log calls (WS payload, command output) - Show error messages in list containers on load failure - evalCondition: log warning instead of silently swallowing errors - Worker reconnect: clean up stale entries for same dbWorkerId - Null-check execState before continuing workflow steps Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1254,6 +1254,7 @@
|
||||
document.getElementById('workerList').innerHTML = fullHtml;
|
||||
} catch (error) {
|
||||
console.error('Error loading workers:', error);
|
||||
document.getElementById('workerList').innerHTML = '<div class="empty" style="color:var(--terminal-red);">⚠ Failed to load workers</div>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1283,9 +1284,9 @@
|
||||
const def = _workflowRegistry[w.id] || {};
|
||||
return `
|
||||
<div class="workflow-item">
|
||||
<div class="workflow-name">${w.name}${paramBadge(def)}</div>
|
||||
<div class="workflow-desc">${w.description || 'No description'}</div>
|
||||
<div class="timestamp">Created by ${w.created_by || 'Unknown'} on ${safeDate(w.created_at)?.toLocaleString() ?? 'N/A'}</div>
|
||||
<div class="workflow-name">${escapeHtml(w.name)}${paramBadge(def)}</div>
|
||||
<div class="workflow-desc">${escapeHtml(w.description || 'No description')}</div>
|
||||
<div class="timestamp">Created by ${escapeHtml(w.created_by || 'Unknown')} on ${safeDate(w.created_at)?.toLocaleString() ?? 'N/A'}</div>
|
||||
<div style="margin-top: 10px;">
|
||||
<button onclick="executeWorkflow('${w.id}')">▶️ Execute</button>
|
||||
${currentUser && currentUser.isAdmin ?
|
||||
@@ -1298,6 +1299,7 @@
|
||||
document.getElementById('workflowList').innerHTML = html;
|
||||
} catch (error) {
|
||||
console.error('Error loading workflows:', error);
|
||||
document.getElementById('workflowList').innerHTML = '<div class="empty" style="color:var(--terminal-red);">⚠ Failed to load workflows</div>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1544,6 +1546,7 @@
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error loading executions:', error);
|
||||
document.getElementById('executionList').innerHTML = '<div class="empty" style="color:var(--terminal-red);">⚠ Failed to load executions</div>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2942,18 +2945,9 @@
|
||||
ws.onmessage = (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
console.log('WebSocket message:', data);
|
||||
|
||||
// Handle specific message types
|
||||
if (data.type === 'command_result') {
|
||||
// Display command result in real-time
|
||||
console.log(`Command result received for execution ${data.execution_id}`);
|
||||
console.log(`Success: ${data.success}`);
|
||||
console.log(`Output: ${data.stdout}`);
|
||||
if (data.stderr) {
|
||||
console.log(`Error: ${data.stderr}`);
|
||||
}
|
||||
|
||||
// Show terminal notification only for manual executions
|
||||
if (!data.is_automated) {
|
||||
if (data.success) {
|
||||
@@ -2978,7 +2972,6 @@
|
||||
}
|
||||
|
||||
if (data.type === 'workflow_result') {
|
||||
console.log(`Workflow ${data.status} for execution ${data.execution_id}`);
|
||||
|
||||
// Refresh execution list
|
||||
loadExecutions();
|
||||
@@ -2994,7 +2987,6 @@
|
||||
}
|
||||
|
||||
if (data.type === 'worker_update') {
|
||||
console.log(`Worker ${data.worker_id} status: ${data.status}`);
|
||||
loadWorkers();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user