diff options
author | Hannes Rosenögger <123haynes@gmail.com> | 2015-02-14 16:04:45 +0100 |
---|---|---|
committer | Douwe Maan <douwe@gitlab.com> | 2015-02-17 22:20:44 +0100 |
commit | 9bf8480b4a0d3ea6e284c4bd8bf26243f3f3f6f5 (patch) | |
tree | 2365d68b1905ddce4d20f226f9e888c29bc0dcf4 /app | |
parent | 0da0d800f2a0db9d9c16cf5e2feb0dd80b528223 (diff) | |
download | gitlab-ce-9bf8480b4a0d3ea6e284c4bd8bf26243f3f3f6f5.tar.gz |
Generalize the image upload in markdown
This commit generalizes the image upload via drag and drop so it supports all files.
It also adds access control for these files.
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/dropzone_input.js.coffee | 21 | ||||
-rw-r--r-- | app/controllers/files_controller.rb | 29 | ||||
-rw-r--r-- | app/controllers/projects_controller.rb | 18 | ||||
-rw-r--r-- | app/services/projects/file_service.rb | 55 | ||||
-rw-r--r-- | app/services/projects/image_service.rb | 39 | ||||
-rw-r--r-- | app/uploaders/file_uploader.rb | 19 | ||||
-rw-r--r-- | app/views/projects/_issuable_form.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/issues/_form.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/merge_requests/_form.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/merge_requests/_new_submit.html.haml | 5 | ||||
-rw-r--r-- | app/views/projects/milestones/_form.html.haml | 4 | ||||
-rw-r--r-- | app/views/projects/notes/_edit_form.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/notes/_form.html.haml | 6 | ||||
-rw-r--r-- | app/views/projects/wikis/_form.html.haml | 5 |
14 files changed, 135 insertions, 74 deletions
diff --git a/app/assets/javascripts/dropzone_input.js.coffee b/app/assets/javascripts/dropzone_input.js.coffee index d98d5482937..bed8471b39a 100644 --- a/app/assets/javascripts/dropzone_input.js.coffee +++ b/app/assets/javascripts/dropzone_input.js.coffee @@ -9,7 +9,7 @@ class @DropzoneInput iconPicture = "<i class=\"fa fa-picture-o div-dropzone-icon\"></i>" iconSpinner = "<i class=\"fa fa-spinner fa-spin div-dropzone-icon\"></i>" btnAlert = "<button type=\"button\"" + alertAttr + ">×</button>" - project_image_path_upload = window.project_image_path_upload or null + project_file_path_upload = window.project_file_path_upload or null form_textarea = $(form).find("textarea.markdown-area") form_textarea.wrap "<div class=\"div-dropzone\"></div>" @@ -72,13 +72,12 @@ class @DropzoneInput form.find(".md-preview-holder").hide() dropzone = form_dropzone.dropzone( - url: project_image_path_upload + url: project_file_path_upload dictDefaultMessage: "" clickable: true - paramName: "markdown_img" + paramName: "markdown_file" maxFilesize: 10 uploadMultiple: false - acceptedFiles: "image/jpg,image/jpeg,image/gif,image/png" headers: "X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content") @@ -133,7 +132,10 @@ class @DropzoneInput child = $(dropzone[0]).children("textarea") formatLink = (str) -> - "![" + str.alt + "](" + str.url + ")" + text = "[" + str.alt + "](" + str.url + ")" + if str.is_image is true + text = "!" + text + text handlePaste = (event) -> pasteEvent = event.originalEvent @@ -177,9 +179,9 @@ class @DropzoneInput uploadFile = (item, filename) -> formData = new FormData() - formData.append "markdown_img", item, filename + formData.append "markdown_file", item, filename $.ajax - url: project_image_path_upload + url: project_file_path_upload type: "POST" data: formData dataType: "json" @@ -234,4 +236,7 @@ class @DropzoneInput return formatLink: (str) -> - "![" + str.alt + "](" + str.url + ")" + text = "[" + str.alt + "](" + str.url + ")" + if str.is_image is true + text = "!" + text + text diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb index 15523cbc2e7..a86340dd9bb 100644 --- a/app/controllers/files_controller.rb +++ b/app/controllers/files_controller.rb @@ -1,5 +1,5 @@ class FilesController < ApplicationController - def download + def download_notes note = Note.find(params[:id]) uploader = note.attachment @@ -14,7 +14,32 @@ class FilesController < ApplicationController not_found! end else - redirect_to uploader.url + not_found! end end + + def download_files + namespace_id = params[:namespace] + project_id = params[:project] + folder_id = params[:folder_id] + filename = params[:filename] + project_with_namespace="#{namespace_id}/#{project_id}" + filename_with_id="#{folder_id}/#{filename}" + + project = Project.find_with_namespace(project_with_namespace) + + uploader = FileUploader.new("#{Rails.root}/uploads","#{project_with_namespace}/#{folder_id}") + uploader.retrieve_from_store!(filename) + + if can?(current_user, :read_project, project) + download(uploader) + else + not_found! + end + end + + def download(uploader) + disposition = uploader.image? ? 'inline' : 'attachment' + send_file uploader.file.path, disposition: disposition + end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 462ab3d4749..b430278903a 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -134,12 +134,13 @@ class ProjectsController < ApplicationController end end - def upload_image - link_to_image = ::Projects::ImageService.new(repository, params, root_url).execute + def upload_file + link_to_file = ::Projects::FileService.new(repository, params, root_url). + execute respond_to do |format| - if link_to_image - format.json { render json: { link: link_to_image } } + if link_to_file + format.json { render json: { link: link_to_file } } else format.json { render json: 'Invalid file.', status: :unprocessable_entity } end @@ -158,13 +159,8 @@ class ProjectsController < ApplicationController private - def upload_path - base_dir = FileUploader.generate_dir - File.join(repository.path_with_namespace, base_dir) - end - - def accepted_images - %w(png jpg jpeg gif) + def invalid_file(error) + render json: { message: error.message }, status: :internal_server_error end def set_title diff --git a/app/services/projects/file_service.rb b/app/services/projects/file_service.rb new file mode 100644 index 00000000000..8c149bf53a1 --- /dev/null +++ b/app/services/projects/file_service.rb @@ -0,0 +1,55 @@ +module Projects + class FileService < BaseService + include Rails.application.routes.url_helpers + def initialize(repository, params, root_url) + @repository, @params, @root_url = repository, params.dup, root_url + end + + def execute + uploader = FileUploader.new("#{Rails.root}/uploads", upload_path, accepted_files) + file = @params['markdown_file'] + + if file + alt = file.original_filename + uploader.store!(file) + filename = nil + if image?(file) + filename=File.basename(alt, '.*') + else + filename=File.basename(alt) + end + link = { + 'alt' => filename, + 'url' => uploader.secure_url, + 'is_image' => image?(file) + } + else + link = nil + end + end + + protected + + def accepted_files + # insert accepted mime types here (e.g %w(jpg jpeg gif png)) + nil + end + + def accepted_images + %w(jpg jpeg gif png) + end + + def image?(file) + accepted_images.map { |format| file.content_type.include? format }.any? + end + + def upload_path + base_dir = FileUploader.generate_dir + File.join(@repository.path_with_namespace, base_dir) + end + + def correct_mime_type?(file) + accepted_files.map { |format| image.content_type.include? format }.any? + end + end +end diff --git a/app/services/projects/image_service.rb b/app/services/projects/image_service.rb deleted file mode 100644 index 7ca7e82c4a3..00000000000 --- a/app/services/projects/image_service.rb +++ /dev/null @@ -1,39 +0,0 @@ -module Projects - class ImageService < BaseService - include Rails.application.routes.url_helpers - def initialize(repository, params, root_url) - @repository, @params, @root_url = repository, params.dup, root_url - end - - def execute - uploader = FileUploader.new('uploads', upload_path, accepted_images) - image = @params['markdown_img'] - - if image && correct_mime_type?(image) - alt = image.original_filename - uploader.store!(image) - link = { - 'alt' => File.basename(alt, '.*'), - 'url' => File.join(@root_url, uploader.url) - } - else - link = nil - end - end - - protected - - def upload_path - base_dir = FileUploader.generate_dir - File.join(@repository.path_with_namespace, base_dir) - end - - def accepted_images - %w(png jpg jpeg gif) - end - - def correct_mime_type?(image) - accepted_images.map{ |format| image.content_type.include? format }.any? - end - end -end diff --git a/app/uploaders/file_uploader.rb b/app/uploaders/file_uploader.rb index 0fa987c93f6..ac7bd5b27ec 100644 --- a/app/uploaders/file_uploader.rb +++ b/app/uploaders/file_uploader.rb @@ -21,7 +21,7 @@ class FileUploader < CarrierWave::Uploader::Base end def extension_white_list - @allowed_extensions + @allowed_extensions || super end def store!(file) @@ -38,4 +38,21 @@ class FileUploader < CarrierWave::Uploader::Base def self.generate_dir SecureRandom.hex(5) end + + def secure_url + Gitlab.config.gitlab.relative_url_root + "/files/#{@path}/#{@filename}" + end + + def image? + img_ext = %w(png jpg jpeg gif bmp tiff) + if file.respond_to?(:extension) + img_ext.include?(file.extension.downcase) + else + # Not all CarrierWave storages respond to :extension + ext = file.path.split('.').last.downcase + img_ext.include?(ext) + end + rescue + false + end end diff --git a/app/views/projects/_issuable_form.html.haml b/app/views/projects/_issuable_form.html.haml index 5a57673b584..18897b055aa 100644 --- a/app/views/projects/_issuable_form.html.haml +++ b/app/views/projects/_issuable_form.html.haml @@ -23,7 +23,7 @@ Parsed with #{link_to 'GitLab Flavored Markdown', help_page_path('markdown', 'markdown'), target: '_blank'}. .pull-right - Attach images (JPG, PNG, GIF) by dragging & dropping + Attach files by dragging & dropping or #{link_to 'selecting them', '#', class: 'markdown-selector' }. .clearfix diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml index 2a7b44955cd..975980bd6bd 100644 --- a/app/views/projects/issues/_form.html.haml +++ b/app/views/projects/issues/_form.html.haml @@ -11,4 +11,4 @@ e.preventDefault(); }); - window.project_image_path_upload = "#{upload_image_project_path @project}"; + window.project_file_path_upload = "#{upload_file_project_path @project}"; diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml index d52e64666a0..28c4734e14f 100644 --- a/app/views/projects/merge_requests/_form.html.haml +++ b/app/views/projects/merge_requests/_form.html.haml @@ -9,4 +9,4 @@ e.preventDefault(); }); - window.project_image_path_upload = "#{upload_image_project_path @project}"; + window.project_file_path_upload = "#{upload_file_project_path @project}"; diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index bca3e45bf19..0653b30fcca 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -27,7 +27,7 @@ Parsed with #{link_to 'Gitlab Flavored Markdown', help_page_path('markdown', 'markdown'), target: '_blank'}. .pull-right - Attach images (JPG, PNG, GIF) by dragging & dropping + Attach files by dragging & dropping or #{link_to 'selecting them', '#', class: 'markdown-selector'}. .clearfix @@ -113,10 +113,11 @@ e.preventDefault(); }); - window.project_image_path_upload = "#{upload_image_project_path @project}"; + window.project_file_path_upload = "#{upload_file_project_path @project}"; :javascript var merge_request merge_request = new MergeRequest({ action: 'commits' }); + diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml index b3b170d7114..5fbb668570c 100644 --- a/app/views/projects/milestones/_form.html.haml +++ b/app/views/projects/milestones/_form.html.haml @@ -25,7 +25,7 @@ = render 'projects/zen', f: f, attr: :description, classes: 'description form-control' .hint .pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}. - .pull-left Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. + .pull-left Attach files by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. .clearfix .error-alert .col-md-6 @@ -51,4 +51,4 @@ onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) } }).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#milestone_due_date').val())); - window.project_image_path_upload = "#{upload_image_project_path @project}"; + window.project_file_path_upload = "#{upload_file_project_path @project}"; diff --git a/app/views/projects/notes/_edit_form.html.haml b/app/views/projects/notes/_edit_form.html.haml index cdc76f5d96f..4ba59078318 100644 --- a/app/views/projects/notes/_edit_form.html.haml +++ b/app/views/projects/notes/_edit_form.html.haml @@ -6,7 +6,7 @@ .comment-hints.clearfix .pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"),{ target: '_blank', tabindex: -1 }} - .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector', tabindex: -1 }. + .pull-right Attach files by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector', tabindex: -1 }. .note-form-actions .buttons diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml index 1a4e06289f8..fe3dab569f4 100644 --- a/app/views/projects/notes/_form.html.haml +++ b/app/views/projects/notes/_form.html.haml @@ -1,4 +1,4 @@ -= form_for [@project, @note], remote: true, html: { :'data-type' => 'json', multipart: true, id: nil, class: "new_note js-new-note-form common-note-form gfm-form" }, authenticity_token: true do |f| += form_for [@project, @note], remote: true, html: { :'data-type' => 'json', multipart: true, id: nil, class: "new_note js-new-note-form common-note-form" }, authenticity_token: true do |f| = note_target_fields = f.hidden_field :commit_id = f.hidden_field :line_code @@ -11,7 +11,7 @@ .comment-hints.clearfix .pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"),{ target: '_blank', tabindex: -1 }} - .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector', tabindex: -1 }. + .pull-right Attach files by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector', tabindex: -1 }. .note-form-actions @@ -29,4 +29,4 @@ = f.file_field :attachment, class: "js-note-attachment-input hidden" :javascript - window.project_image_path_upload = "#{upload_image_project_path @project}"; + window.project_file_path_upload = "#{upload_file_project_path @project}"; diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml index 84731e43e95..0afee138c8b 100644 --- a/app/views/projects/wikis/_form.html.haml +++ b/app/views/projects/wikis/_form.html.haml @@ -26,7 +26,7 @@ = render 'projects/zen', f: f, attr: :content, classes: 'description form-control' .col-sm-12.hint .pull-left Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'} - .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. + .pull-right Attach files by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. .clearfix .error-alert @@ -43,5 +43,6 @@ = link_to "Cancel", project_wiki_path(@project, :home), class: "btn btn-cancel" :javascript - window.project_image_path_upload = "#{upload_image_project_path @project}"; + window.project_file_path_upload = "#{upload_file_project_path @project}"; + |