Shell: Add file system browser to retrieve arbitrary files

This commit is contained in:
Sebastian Serth
2022-10-04 15:21:06 +02:00
committed by Sebastian Serth
parent 60078701f5
commit 58548555a5
13 changed files with 240 additions and 38 deletions

View File

@ -2,17 +2,17 @@ $(document).on('turbolinks:load', function () {
const ENTER_KEY_CODE = 13;
const clearOutput = function () {
$('#output').html('');
log.html('');
};
const executeCommand = function (command) {
$.ajax({
data: {
command: command,
sudo: $('#sudo').is(':checked')
sudo: sudo.is(':checked')
},
method: 'POST',
url: $('#shell').data('url')
url: Routes.execute_command_execution_environment_path(id)
}).done(handleResponse);
};
@ -46,7 +46,7 @@ $(document).on('turbolinks:load', function () {
em.text(command);
const p = $('<p>');
p.append(em)
$('#output').append(p);
log.append(p);
};
const printOutput = function (output) {
@ -55,22 +55,21 @@ $(document).on('turbolinks:load', function () {
const element = $('<p>');
element.addClass('text-success');
element.text(output.stdout);
$('#output').append(element);
log.append(element);
}
if (output.stderr) {
const element = $('<p>');
element.addClass('text-warning');
element.text(output.stderr);
$('#output').append(element);
log.append(element);
}
if (!output.stdout && !output.stderr) {
const element = $('<p>');
element.addClass('text-muted');
const output = $('#output');
element.text(output.data('message-no-output'));
output.append(element);
element.text(log.data('message-no-output'));
log.append(element);
}
}
};
@ -79,26 +78,99 @@ $(document).on('turbolinks:load', function () {
const element = $('<p>');
element.addClass('text-danger');
element.text($('#shell').data('message-timeout'));
$('#output').append(element);
log.append(element);
};
const printOutOfMemory = function (output) {
const element = $('<p>');
element.addClass('text-danger');
element.text($('#shell').data('message-out-of-memory'));
$('#output').append(element);
log.append(element);
};
if ($('#shell').isPresent()) {
const command = $('#command')
command.focus();
command.on('keypress', handleKeyPress);
const retrieveFiles = function () {
let fileTree = $('#download-file-tree');
const sudo = $('#sudo');
sudo.on('change', function () {
sudo.parent().toggleClass('text-muted')
command.focus();
});
// Get current instance of the jstree if available and refresh the existing one.
// Otherwise, initialize a new one.
if (fileTree.jstree(true)) {
return fileTree.jstree('refresh');
} else {
fileTree.removeClass('my-3 justify-content-center');
fileTree.jstree({
'core': {
'data': {
'url': function (node) {
const params = {sudo: sudo.is(':checked')};
return Routes.list_files_in_execution_environment_path(id, params);
},
'data': function (node) {
return {'path': getPath(fileTree.jstree(), node)|| '/'};
}
}
}
});
fileTree.on('select_node.jstree', function (node, selected, _event) {
// We never want a node to be selected permanently, so we deselect it immediately.
selected.instance.deselect_all();
const path = getPath(selected.instance, selected.node)
const params = {sudo: sudo.is(':checked')};
const downloadPath = Routes.download_file_from_execution_environment_path(id, path, params);
// Now we download the file if allowed.
if (selected.node.original.icon.split(" ").some(function (icon) {
return ['fa-lock', 'fa-folder'].includes(icon);
})) {
$.flash.danger({
icon: ['fa-solid', 'fa-shield-halved'],
text: I18n.t('execution_environments.shell.file_tree.permission_denied')
});
} else {
window.location = downloadPath;
}
}.bind(this));
}
}
const getPath = function (jstree, node) {
if (node.id === '#') {
// Root node
return '/'
}
// We build the path to the file by concatenating the paths of all parent nodes.
let file_path = node.parents.reverse().map(function (id) {
return jstree.get_text(id);
}).filter(function (text) {
return text !== false;
}).join('/');
return `${node.parent !== '#' ? '/' : ''}${file_path}${node.original.path}`;
}
const shell = $('#shell');
if (!shell.isPresent()) {
return;
}
const command = $('#command')
command.focus();
command.on('keypress', handleKeyPress);
const id = shell.data('id');
const log = $('#output');
const sudo = $('#sudo');
sudo.on('change', function () {
sudo.parent().toggleClass('text-muted')
command.focus();
});
$('#reload-files').on('click', function () {
new bootstrap.Collapse('#collapse_files', 'show');
retrieveFiles();
});
$('#reload-now-link').on('click', retrieveFiles);
})
;