Improve upload handling (server-side and UI).

This commit is contained in:
Bart Kamphorst
2018-11-07 11:06:25 +01:00
parent 6857995442
commit 64c4ee9c05
13 changed files with 65 additions and 43 deletions
+1 -1
View File
@@ -127,7 +127,7 @@ MSG
end
opts.on("--allow-uploads [MODE]", [:dir, :page], "Enable file uploads.",
"If set to 'dir', Gollum will store all uploads in the '<git-repo>/uploads/' directory.",
"If set to 'page', Gollum will store each upload at the currently edited page.") do |mode|
"If set to 'page', Gollum will store uploads per page in '<git-repo>/uploads/[pagename]'.") do |mode|
wiki_options[:allow_uploads] = true
wiki_options[:per_page_uploads] = true if mode == :page
end
+17 -12
View File
@@ -84,6 +84,7 @@ module Precious
before do
settings.wiki_options[:allow_editing] = settings.wiki_options.fetch(:allow_editing, true)
@allow_editing = settings.wiki_options[:allow_editing]
@per_page_uploads = settings.wiki_options[:per_page_uploads]
forbid unless @allow_editing || request.request_method == "GET"
Precious::App.set(:mustache, {:templates => settings.wiki_options[:template_dir]}) if settings.wiki_options[:template_dir]
@base_url = url('/', false).chomp('/')
@@ -166,7 +167,6 @@ module Precious
wikip = wiki_page(params[:splat].first)
@name = join_page_name(wikip.name, wikip.ext)
@path = wikip.path
@upload_dest = find_upload_dest(@path)
wiki = wikip.wiki
@allow_uploads = wiki.allow_uploads
@@ -182,8 +182,8 @@ module Precious
# AJAX calls only
post '/upload_file' do
wiki = wiki_new
halt 405 unless wiki.allow_uploads
if params[:file]
@@ -192,8 +192,21 @@ module Precious
end
halt 500 unless tempfile.is_a? Tempfile
# Remove page file dir prefix from upload path if necessary -- committer handles this itself
dir = wiki.per_page_uploads ? params[:upload_dest] : ::File.join([wiki.page_file_dir, 'uploads'].compact)
if wiki.per_page_uploads
# remove base_url and gollum/* subpath if necessary
dir = request.referer.
sub(request.base_url, '').
sub(/.*gollum\/\w+\//, '')
# remove file extension
dir = dir.sub(::File.extname(dir), '')
dir = ::File.join("uploads", dir)
else
# Remove page file dir prefix from upload path if necessary -- committer handles this itself
dir = ::File.join([wiki.page_file_dir, 'uploads'].compact)
end
halt 500 if dir.include?('..')
halt 500 unless Pathname(dir).relative?
ext = ::File.extname(fullname)
format = ext.split('.').last || 'txt'
filename = ::File.basename(fullname, ext)
@@ -304,7 +317,6 @@ module Precious
@ext = wikip.ext
@path = wikip.path
@allow_uploads = wikip.wiki.allow_uploads
@upload_dest = find_upload_dest(@path)
page_dir = settings.wiki_options[:page_file_dir].to_s
unless page_dir.empty?
@@ -496,7 +508,6 @@ module Precious
@page = page
@name = name
@content = page.formatted_data
@upload_dest = find_upload_dest(path)
# Extensions and layout data
@editable = true
@@ -573,11 +584,5 @@ module Precious
commit_message
end
def find_upload_dest(path)
settings.wiki_options[:allow_uploads] ?
(settings.wiki_options[:per_page_uploads] ?
"#{path}/#{@name}".sub(/^\/\//, '') : 'uploads'
) : ''
end
end
end
@@ -205,9 +205,8 @@
var file = e.dataTransfer.files[0],
formData = new FormData();
formData.append('upload_dest', uploadDest);
formData.append('file', file);
$.ajax({
url: '<%= upload_file_path %>',
data: formData,
@@ -105,8 +105,6 @@
html += '<form method=post enctype="multipart/form-data" ' +
'action="' + action + '" ' + 'id="' + id + '">';
html += '<input type="hidden" name="upload_dest" value="' +
uploadDest + '">';
html += '<input type=file name="' + name + '">';
html += '</form>';
@@ -125,9 +123,9 @@
title +'</h4></div>' +
'<div id="gollum-dialog-dialog-body">' + body + '</div>' +
'<div id="gollum-dialog-dialog-buttons">' +
'<a href="#" title="Cancel" id="gollum-dialog-action-cancel" ' +
'<button name="Cancel" id="gollum-dialog-action-cancel" ' +
'class="gollum-minibutton">Cancel</a>' +
'<a href="#" title="OK" id="gollum-dialog-action-ok" '+
'<button name="OK" id="gollum-dialog-action-ok" '+
'class="gollum-minibutton">OK</a>' +
'</div>' +
'</div>';
@@ -139,9 +137,9 @@
title +'</h4></div>' +
'<div id="gollum-dialog-dialog-body">' + body + '</div>' +
'<div id="gollum-dialog-dialog-buttons">' +
'<a href="#" title="Cancel" id="gollum-dialog-action-cancel" ' +
'class="minibutton">Cancel</a>' +
'<a href="#" title="OK" id="gollum-dialog-action-ok" '+
'<button name="Cancel" id="gollum-dialog-action-cancel" ' +
'class="minibutton">Cancel</button>' +
'<button name="OK" id="gollum-dialog-action-ok" '+
'class="minibutton">OK</a>' +
'</div>' +
'</div>' +
@@ -177,7 +177,7 @@ $(document).ready(function() {
$('#minibutton-upload-page').parent().removeClass('jaws');
$('#minibutton-upload-page').click(function(e) {
e.preventDefault();
$.GollumDialog.init({
title: 'Upload File',
fields: [
@@ -188,6 +188,7 @@ $(document).ready(function() {
}
],
OK: function( res ) {
$('#wiki-content').addClass('uploading');
var formData = new FormData($('#upload').get(0));
var endpoint = $('#upload').attr("action");
@@ -199,8 +200,10 @@ $(document).ready(function() {
contentType: false,
success: function(data) {
// File successfully uploaded
$('#wiki-content').removeClass('uploading');
},
error: function(data, textStatus, errorThrown) {
$('#wiki-content').removeClass('uploading');
if (data.status == 409) {
alert('This file already exists.');
} else {
@@ -210,6 +213,15 @@ $(document).ready(function() {
});
}
});
$('#gollum-dialog-action-ok').attr('disabled', true);
$('input:file').on('change', function() {
if ($(this).val()) {
news = 'Your uploaded file will be accessible at<br>/' + uploadDest + '/' + $('input[type=file]').val().split('\\').pop();
$(".context").html(news);
$('#gollum-dialog-action-ok').attr('disabled', false);
};
});
});
}
@@ -20,6 +20,12 @@
height: 1%;
overflow: auto;
}
&.uploading {
opacity: 0.5;
}
}
/* @section body */
@@ -29,7 +29,7 @@
display: block;
}
a.minibutton {
button.minibutton {
float: right;
margin-right: 0.5em;
width: auto;
@@ -42,6 +42,12 @@
@include button-base;
}
button.minibutton:disabled {
opacity: 0.65;
cursor: not-allowed;
}
}
#gollum-dialog-dialog-inner {
+9 -5
View File
@@ -15,11 +15,15 @@
<![endif]-->
<script>
var baseUrl = '{{base_url}}';
var uploadDest = '{{upload_dest}}';
{{#page}}
var pageFullPath = '{{url_path}}';
{{/page}}
var baseUrl = '{{base_url}}';
var uploadDest = 'uploads';
var perPageUploads = '{{per_page_uploads}}';
if (perPageUploads == 'true') {
uploadDest = uploadDest + window.location.pathname.replace(/.*gollum\/\w+\//, "/").replace(/\.[^/.]+$/, "")
}
{{#page}}
var pageFullPath = '{{url_path}}';
{{/page}}
</script>
{{#sprockets_javascript_tag}}app{{/sprockets_javascript_tag}}
{{#use_identicon}}
-4
View File
@@ -21,10 +21,6 @@ module Precious
@allow_uploads
end
def upload_dest
@upload_dest
end
def format
@format ||= find_format.to_s.downcase
end
-4
View File
@@ -64,10 +64,6 @@ module Precious
@allow_uploads
end
def upload_dest
@upload_dest
end
def format
@format = (@page.format || false) if @format.nil?
@format.to_s.downcase
+4
View File
@@ -43,6 +43,10 @@ module Precious
def js # custom js
@js
end
def per_page_uploads
@per_page_uploads
end
end
end
-4
View File
@@ -57,10 +57,6 @@ module Precious
@allow_uploads
end
def upload_dest
@upload_dest
end
def has_header
if @header
@header.formatted_data.strip.empty? ? false : true
+2 -2
View File
@@ -32,7 +32,7 @@ context "Precious::Views::Editing" do
assert_match /Delete this Page/, last_response.body, "'Delete this Page' link is blocked in page template"
assert_match /New/, last_response.body, "'New' button is blocked in page template"
assert_match /Upload/, last_response.body, "'Upload' link is blocked in page template"
assert_match /Upload\b/, last_response.body, "'Upload' link is blocked in page template"
assert_match /Rename/, last_response.body, "'Rename' link is blocked in page template"
assert_match /Edit/, last_response.body, "'Edit' link is blocked in page template"
@@ -56,7 +56,7 @@ context "Precious::Views::Editing" do
assert_no_match /Delete this Page/, last_response.body, "'Delete this Page' link not blocked in page template"
assert_no_match /New/, last_response.body, "'New' button not blocked in page template"
assert_no_match /Upload/, last_response.body, "'Upload' link not blocked in page template"
assert_no_match /Upload\b/, last_response.body, "'Upload' link not blocked in page template"
assert_no_match /Rename/, last_response.body, "'Rename' link not blocked in page template"
assert_no_match /Edit/, last_response.body, "'Edit' link not blocked in page template"