Use X-Sendfile to transmit native files and handle file uploads

This commit is contained in:
Sebastian Serth
2022-09-06 00:00:59 +02:00
parent dccc60b7ca
commit 0a16f589e9
9 changed files with 58 additions and 9 deletions

View File

@@ -10,6 +10,15 @@ module CodeOcean
end
private :authorize!
def show_protected_upload
@file = CodeOcean::File.find(params[:id])
authorize!
raise Pundit::NotAuthorizedError if @embed_options[:disable_download] || @file.name_with_extension != params[:filename]
real_location = Pathname(@file.native_file.current_path).realpath
send_file(real_location, type: @file.native_file.content_type, filename: @file.name_with_extension, disposition: 'attachment')
end
def create
@file = CodeOcean::File.new(file_params)
if @file.file_template_id

View File

@@ -56,7 +56,11 @@ class SubmissionsController < ApplicationController
def download_file
raise Pundit::NotAuthorizedError if @embed_options[:disable_download]
send_data(@file.read, filename: @file.name_with_extension)
if @file.native_file?
redirect_to protected_upload_path(id: @file.id, filename: @file.name_with_extension)
else
send_data(@file.content, filename: @file.name_with_extension)
end
end
def index

View File

@@ -58,8 +58,7 @@ module CodeOcean
def read
if native_file?
valid = Pathname(native_file.current_path).realpath.fnmatch? ::File.join(native_file.root, '**')
return nil unless valid
return nil unless native_file_location_valid?
native_file.read
else
@@ -67,6 +66,12 @@ module CodeOcean
end
end
def native_file_location_valid?
real_location = Pathname(native_file.current_path).realpath
upload_location = Pathname(::File.join(native_file.root, 'uploads')).realpath
real_location.fnmatch? ::File.join(upload_location.to_s, '**')
end
def ancestor_id
file_id || id
end

View File

@@ -7,6 +7,8 @@ module CodeOcean
end
def show?
return false if @record.native_file? && !@record.native_file_location_valid?
if @record.context.is_a?(Exercise)
admin? || author? || !@record.hidden
else
@@ -14,6 +16,16 @@ module CodeOcean
end
end
def show_protected_upload?
return false if @record.native_file? && !@record.native_file_location_valid?
if @record.context.is_a?(Exercise)
admin? || author? || (!@record.context.unpublished && !@record.hidden)
else
admin? || author?
end
end
def create?
if @record.context.is_a?(Exercise)
admin? || author?