test again

This commit is contained in:
Raven Scott 2024-12-01 22:14:26 -05:00
parent 73adabe2c4
commit c38f23d50e
4 changed files with 135 additions and 116 deletions

2
app.js
View File

@ -398,7 +398,7 @@ connectionItem.querySelector('.docker-terminal-btn').addEventListener('click', (
e.stopPropagation(); e.stopPropagation();
const connection = connections[topicId]; const connection = connections[topicId];
if (connection && connection.peer) { if (connection && connection.peer) {
import('./dockerTerminal.js').then(({ startDockerTerminal }) => { import('./libs/dockerTerminal.js').then(({ startDockerTerminal }) => {
startDockerTerminal(topicId, connection.peer); startDockerTerminal(topicId, connection.peer);
}); });
} else { } else {

View File

@ -516,16 +516,16 @@
</div> </div>
<!-- Docker Terminal Modal --> <!-- Docker Terminal Modal -->
<div id="docker-terminal-modal" style="display: none; flex-direction: column;"> <!-- Docker CLI Terminal Modal -->
<div class="header"> <div id="docker-terminal-modal" class="position-fixed bottom-0 start-0 w-100 max-height-90 bg-dark text-white d-flex flex-column" style="display: none; z-index: 1000;">
<span id="docker-terminal-title"></span> <div class="header d-flex justify-content-between align-items-center bg-secondary p-2">
<div> <span id="docker-terminal-title" class="fw-bold">Docker CLI Terminal</span>
<button id="docker-kill-terminal-btn" class="btn btn-sm btn-danger"> <button id="docker-kill-terminal-btn" class="btn btn-sm btn-danger">
<i class="fas fa-times-circle"></i> <i class="fas fa-times-circle"></i>
</button> </button>
</div> </div>
</div> <div id="docker-terminal-container" class="flex-grow-1 overflow-hidden" style="background-color: black;"></div>
<div id="docker-terminal-container" style="flex: 1; overflow: hidden; background-color: black;"></div> <div id="docker-terminal-resize-handle" class="bg-secondary" style="height: 10px; cursor: ns-resize;"></div>
</div> </div>
<!-- Alert Container --> <!-- Alert Container -->

View File

@ -10,7 +10,6 @@ const dockerKillTerminalBtn = document.getElementById('docker-kill-terminal-btn'
// Terminal variables // Terminal variables
let dockerTerminalSession = null; let dockerTerminalSession = null;
// Start Docker CLI terminal session
function startDockerTerminal(connectionId, peer) { function startDockerTerminal(connectionId, peer) {
if (!peer) { if (!peer) {
console.error('[ERROR] No active peer for Docker CLI terminal.'); console.error('[ERROR] No active peer for Docker CLI terminal.');
@ -18,15 +17,13 @@ function startDockerTerminal(connectionId, peer) {
} }
if (dockerTerminalSession) { if (dockerTerminalSession) {
console.log(`[INFO] Docker CLI terminal session already exists for connection: ${connectionId}`); console.log('[INFO] Docker CLI terminal session already exists.');
return; return;
} }
console.log(`[INFO] Starting Docker CLI terminal for connection: ${connectionId}`);
const xterm = new Terminal({ const xterm = new Terminal({
cursorBlink: true, cursorBlink: true,
theme: { background: '#1a1a1a', foreground: '#ffffff' }, theme: { background: '#000000', foreground: '#ffffff' },
}); });
const fitAddon = new FitAddon(); const fitAddon = new FitAddon();
xterm.loadAddon(fitAddon); xterm.loadAddon(fitAddon);
@ -37,26 +34,41 @@ function startDockerTerminal(connectionId, peer) {
dockerTerminalSession = { xterm, fitAddon, connectionId, peer }; dockerTerminalSession = { xterm, fitAddon, connectionId, peer };
let inputBuffer = ''; // Buffer for user input
xterm.onData((input) => { xterm.onData((input) => {
const sanitizedInput = sanitizeDockerCommand(input.trim()); if (input === '\r') { // User pressed Enter
const sanitizedInput = sanitizeDockerCommand(inputBuffer.trim());
if (sanitizedInput) { if (sanitizedInput) {
console.log(`[DEBUG] Sending Docker CLI command: ${sanitizedInput}`); console.log(`[DEBUG] Sending Docker CLI command: ${sanitizedInput}`);
peer.write( peer.write(
JSON.stringify({ JSON.stringify({
type: 'dockerCommand', type: 'dockerCommand',
connectionId,
data: sanitizedInput, data: sanitizedInput,
}) })
); );
xterm.write('\r\n'); // Move to the next line in the terminal
} else { } else {
xterm.write('\r\n[ERROR] Invalid command. Only Docker CLI commands are allowed.\r\n'); xterm.write('\r\n[ERROR] Invalid command. Only Docker CLI commands are allowed.\r\n');
} }
inputBuffer = ''; // Clear the buffer after processing
} else if (input === '\u007F') { // Handle backspace
if (inputBuffer.length > 0) {
inputBuffer = inputBuffer.slice(0, -1); // Remove the last character from the buffer
xterm.write('\b \b'); // Erase the character from the terminal display
}
} else {
inputBuffer += input; // Append input to the buffer
xterm.write(input); // Display input in the terminal
}
}); });
peer.on('data', (data) => { peer.on('data', (data) => {
try { try {
const response = JSON.parse(data.toString()); const response = JSON.parse(data.toString());
if (response.type === 'dockerOutput' && response.connectionId === connectionId) { if (response.type === 'dockerOutput' && response.connectionId === connectionId) {
xterm.write(response.data); xterm.write(`${response.data}\r\n`);
} }
} catch (error) { } catch (error) {
console.error(`[ERROR] Failed to parse response from peer: ${error.message}`); console.error(`[ERROR] Failed to parse response from peer: ${error.message}`);
@ -65,19 +77,17 @@ function startDockerTerminal(connectionId, peer) {
dockerTerminalTitle.textContent = `Docker CLI Terminal: ${connectionId}`; dockerTerminalTitle.textContent = `Docker CLI Terminal: ${connectionId}`;
dockerTerminalModal.style.display = 'flex'; dockerTerminalModal.style.display = 'flex';
dockerKillTerminalBtn.onclick = () => {
cleanUpDockerTerminal();
};
} }
// Sanitize input to ensure only Docker CLI commands are allowed // Sanitize input to ensure only Docker CLI commands are allowed
function sanitizeDockerCommand(command) { function sanitizeDockerCommand(command) {
const allowedCommands = ['docker', 'docker-compose']; // Allow commands starting with "docker" and disallow dangerous operators
const parts = command.split(/\s+/); const isValid = /^docker(\s+[\w.-]+)*$/i.test(command);
const baseCommand = parts[0]; return isValid ? command : null;
if (allowedCommands.includes(baseCommand)) {
return command; // Valid Docker command
}
return null; // Invalid command
} }
// Clean up Docker CLI terminal session // Clean up Docker CLI terminal session
@ -85,8 +95,9 @@ function cleanUpDockerTerminal() {
if (dockerTerminalSession) { if (dockerTerminalSession) {
dockerTerminalSession.xterm.dispose(); dockerTerminalSession.xterm.dispose();
dockerTerminalSession = null; dockerTerminalSession = null;
dockerTerminalContainer.innerHTML = ''; dockerTerminalContainer.innerHTML = ''; // Clear terminal content
dockerTerminalModal.style.display = 'none'; dockerTerminalModal.style.display = 'none'; // Hide the modal
dockerTerminalModal.classList.add('hidden');
console.log('[INFO] Docker CLI terminal session cleaned up.'); console.log('[INFO] Docker CLI terminal session cleaned up.');
} }
} }

View File

@ -110,9 +110,10 @@ swarm.on('connection', (peer) => {
case 'dockerCommand': case 'dockerCommand':
console.log(`[INFO] Executing Docker CLI command: ${parsedData.data}`); console.log(`[INFO] Executing Docker CLI command: ${parsedData.data}`);
try { try {
const exec = spawn('sh', ['-c', parsedData.data]); const exec = spawn('sh', ['-c', parsedData.data]); // Use `spawn` to execute the command
exec.stdout.on('data', (output) => { exec.stdout.on('data', (output) => {
console.log(`[DEBUG] Command output: ${output.toString()}`);
peer.write( peer.write(
JSON.stringify({ JSON.stringify({
type: 'dockerOutput', type: 'dockerOutput',
@ -123,6 +124,7 @@ swarm.on('connection', (peer) => {
}); });
exec.stderr.on('data', (error) => { exec.stderr.on('data', (error) => {
console.error(`[ERROR] Command error output: ${error.toString()}`);
peer.write( peer.write(
JSON.stringify({ JSON.stringify({
type: 'dockerOutput', type: 'dockerOutput',
@ -133,6 +135,7 @@ swarm.on('connection', (peer) => {
}); });
exec.on('close', (code) => { exec.on('close', (code) => {
console.log(`[INFO] Command exited with code: ${code}`);
peer.write( peer.write(
JSON.stringify({ JSON.stringify({
type: 'dockerOutput', type: 'dockerOutput',
@ -142,7 +145,12 @@ swarm.on('connection', (peer) => {
); );
}); });
} catch (error) { } catch (error) {
peer.write(JSON.stringify({ error: `Failed to execute command: ${error.message}` })); console.error(`[ERROR] Failed to execute command: ${error.message}`);
peer.write(
JSON.stringify({
error: `Failed to execute command: ${error.message}`
})
);
} }
break; break;
case 'startContainer': case 'startContainer':