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,9 +2,10 @@
class ExecutionEnvironmentsController < ApplicationController
include CommonBehavior
include FileConversion
before_action :set_docker_images, only: %i[create edit new update]
before_action :set_execution_environment, only: MEMBER_ACTIONS + %i[execute_command shell statistics sync_to_runner_management]
before_action :set_execution_environment, only: MEMBER_ACTIONS + %i[execute_command shell list_files statistics sync_to_runner_management]
before_action :set_testing_framework_adapters, only: %i[create edit new update]
def authorize!
@@ -30,11 +31,24 @@ class ExecutionEnvironmentsController < ApplicationController
def execute_command
runner = Runner.for(current_user, @execution_environment)
sudo = ActiveModel::Type::Boolean.new.cast(params[:sudo])
output = runner.execute_command(params[:command], privileged_execution: sudo, raise_exception: false)
@privileged_execution = ActiveModel::Type::Boolean.new.cast(params[:sudo]) || @execution_environment.privileged_execution
output = runner.execute_command(params[:command], privileged_execution: @privileged_execution, raise_exception: false)
render json: output.except(:messages)
end
def list_files
runner = Runner.for(current_user, @execution_environment)
@privileged_execution = ActiveModel::Type::Boolean.new.cast(params[:sudo]) || @execution_environment.privileged_execution
begin
files = runner.retrieve_files(path: params[:path], recursive: false, privileged_execution: @privileged_execution)
downloadable_files, additional_directories = convert_files_json_to_files files
js_tree = FileTree.new(downloadable_files, additional_directories, force_closed: true).to_js_tree
render json: js_tree[:core][:data]
rescue Runner::Error::WorkspaceError
render json: []
end
end
def working_time_query
"
SELECT exercise_id, avg(working_time) as average_time, stddev_samp(extract('epoch' from working_time)) * interval '1 second' as stddev_time
@@ -225,4 +239,14 @@ class ExecutionEnvironmentsController < ApplicationController
redirect_to ExecutionEnvironment, alert: t('execution_environments.index.synchronize_all.failure')
end
end
def augment_files_for_download(files)
files.map do |file|
# Downloadable files get an indicator whether we performed a privileged execution.
# The download path is added dynamically in the frontend.
file.privileged_execution = @privileged_execution
file
end
end
private :augment_files_for_download
end

View File

@@ -21,12 +21,21 @@ class LiveStreamsController < ApplicationController
send_runner_file(runner, desired_file, fallback_location)
end
def download_arbitrary_file
@execution_environment = authorize ExecutionEnvironment.find(params[:id])
desired_file = params[:filename].to_s
runner = Runner.for(current_user, @execution_environment)
fallback_location = shell_execution_environment_path(@execution_environment)
privileged = params[:sudo] || @execution_environment.privileged_execution?
send_runner_file(runner, desired_file, fallback_location, privileged: privileged)
end
private
def send_runner_file(runner, desired_file, redirect_fallback = root_path)
def send_runner_file(runner, desired_file, redirect_fallback = root_path, privileged: false)
filename = File.basename(desired_file)
send_stream(filename: filename, disposition: 'attachment') do |stream|
runner.download_file desired_file do |chunk, overall_size, content_type|
runner.download_file desired_file, privileged_execution: privileged do |chunk, overall_size, content_type|
unless response.committed?
# Disable Rack::ETag, which would otherwise cause the response to be cached
# See https://github.com/rack/rack/issues/1619#issuecomment-848460528