summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorJarka Kadlecova <jarka@gitlab.com>2017-05-01 15:14:35 +0200
committerJarka Kadlecova <jarka@gitlab.com>2017-05-02 15:22:24 +0200
commit43ff7386411af0f538710f3627622f71e5e34472 (patch)
tree3bb4d32c1389504d70395f36e8e223899fcbccd5 /app
parent6277bda61c511696f9d12fae4238b5214a722571 (diff)
downloadgitlab-ce-43ff7386411af0f538710f3627622f71e5e34472.tar.gz
Support uploaders for personal snippets comments12910-uploader-pers-snippet
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/dropzone_input.js10
-rw-r--r--app/controllers/concerns/uploads_actions.rb27
-rw-r--r--app/controllers/projects/uploads_controller.rb32
-rw-r--r--app/controllers/uploads_controller.rb82
-rw-r--r--app/policies/personal_snippet_policy.rb6
-rw-r--r--app/services/projects/upload_service.rb22
-rw-r--r--app/services/upload_service.rb20
-rw-r--r--app/uploaders/artifact_uploader.rb4
-rw-r--r--app/uploaders/file_uploader.rb10
-rw-r--r--app/uploaders/gitlab_uploader.rb4
-rw-r--r--app/uploaders/lfs_object_uploader.rb4
-rw-r--r--app/uploaders/personal_file_uploader.rb15
-rw-r--r--app/views/layouts/project.html.haml2
13 files changed, 140 insertions, 98 deletions
diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js
index b70d242269d..b3a76fbb43e 100644
--- a/app/assets/javascripts/dropzone_input.js
+++ b/app/assets/javascripts/dropzone_input.js
@@ -5,7 +5,7 @@ require('./preview_markdown');
window.DropzoneInput = (function() {
function DropzoneInput(form) {
- var $mdArea, alertAttr, alertClass, appendToTextArea, btnAlert, child, closeAlertMessage, closeSpinner, divAlert, divHover, divSpinner, dropzone, form_dropzone, form_textarea, getFilename, handlePaste, iconPaperclip, iconSpinner, insertToTextArea, isImage, max_file_size, pasteText, project_uploads_path, showError, showSpinner, uploadFile, uploadProgress;
+ var $mdArea, alertAttr, alertClass, appendToTextArea, btnAlert, child, closeAlertMessage, closeSpinner, divAlert, divHover, divSpinner, dropzone, form_dropzone, form_textarea, getFilename, handlePaste, iconPaperclip, iconSpinner, insertToTextArea, isImage, max_file_size, pasteText, uploads_path, showError, showSpinner, uploadFile, uploadProgress;
Dropzone.autoDiscover = false;
alertClass = "alert alert-danger alert-dismissable div-dropzone-alert";
alertAttr = "class=\"close\" data-dismiss=\"alert\"" + "aria-hidden=\"true\"";
@@ -16,7 +16,7 @@ window.DropzoneInput = (function() {
iconSpinner = "<i class=\"fa fa-spinner fa-spin div-dropzone-icon\"></i>";
uploadProgress = $("<div class=\"div-dropzone-progress\"></div>");
btnAlert = "<button type=\"button\"" + alertAttr + ">&times;</button>";
- project_uploads_path = window.project_uploads_path || null;
+ uploads_path = window.uploads_path || null;
max_file_size = gon.max_file_size || 10;
form_textarea = $(form).find(".js-gfm-input");
form_textarea.wrap("<div class=\"div-dropzone\"></div>");
@@ -39,10 +39,10 @@ window.DropzoneInput = (function() {
"display": "none"
});
- if (!project_uploads_path) return;
+ if (!uploads_path) return;
dropzone = form_dropzone.dropzone({
- url: project_uploads_path,
+ url: uploads_path,
dictDefaultMessage: "",
clickable: true,
paramName: "file",
@@ -159,7 +159,7 @@ window.DropzoneInput = (function() {
formData = new FormData();
formData.append("file", item, filename);
return $.ajax({
- url: project_uploads_path,
+ url: uploads_path,
type: "POST",
data: formData,
dataType: "json",
diff --git a/app/controllers/concerns/uploads_actions.rb b/app/controllers/concerns/uploads_actions.rb
new file mode 100644
index 00000000000..dec2e27335a
--- /dev/null
+++ b/app/controllers/concerns/uploads_actions.rb
@@ -0,0 +1,27 @@
+module UploadsActions
+ def create
+ link_to_file = UploadService.new(model, params[:file], uploader_class).execute
+
+ respond_to do |format|
+ if link_to_file
+ format.json do
+ render json: { link: link_to_file }
+ end
+ else
+ format.json do
+ render json: 'Invalid file.', status: :unprocessable_entity
+ end
+ end
+ end
+ end
+
+ def show
+ return render_404 unless uploader.exists?
+
+ disposition = uploader.image_or_video? ? 'inline' : 'attachment'
+
+ expires_in 0.seconds, must_revalidate: true, private: true
+
+ send_file uploader.file.path, disposition: disposition
+ end
+end
diff --git a/app/controllers/projects/uploads_controller.rb b/app/controllers/projects/uploads_controller.rb
index 61686499bd3..6966a7c5fee 100644
--- a/app/controllers/projects/uploads_controller.rb
+++ b/app/controllers/projects/uploads_controller.rb
@@ -1,33 +1,11 @@
class Projects::UploadsController < Projects::ApplicationController
+ include UploadsActions
+
skip_before_action :project, :repository,
if: -> { action_name == 'show' && image_or_video? }
before_action :authorize_upload_file!, only: [:create]
- def create
- link_to_file = ::Projects::UploadService.new(project, params[:file]).
- execute
-
- respond_to do |format|
- if link_to_file
- format.json do
- render json: { link: link_to_file }
- end
- else
- format.json do
- render json: 'Invalid file.', status: :unprocessable_entity
- end
- end
- end
- end
-
- def show
- return render_404 if uploader.nil? || !uploader.file.exists?
-
- disposition = uploader.image_or_video? ? 'inline' : 'attachment'
- send_file uploader.file.path, disposition: disposition
- end
-
private
def uploader
@@ -52,4 +30,10 @@ class Projects::UploadsController < Projects::ApplicationController
def image_or_video?
uploader && uploader.file.exists? && uploader.image_or_video?
end
+
+ def uploader_class
+ FileUploader
+ end
+
+ alias_method :model, :project
end
diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb
index f1bfd574f04..21a964fb391 100644
--- a/app/controllers/uploads_controller.rb
+++ b/app/controllers/uploads_controller.rb
@@ -1,50 +1,43 @@
class UploadsController < ApplicationController
- skip_before_action :authenticate_user!
- before_action :find_model, :authorize_access!
-
- def show
- uploader = @model.send(upload_mount)
-
- unless uploader.file_storage?
- return redirect_to uploader.url
- end
+ include UploadsActions
- unless uploader.file && uploader.file.exists?
- return render_404
- end
-
- disposition = uploader.image? ? 'inline' : 'attachment'
-
- expires_in 0.seconds, must_revalidate: true, private: true
- send_file uploader.file.path, disposition: disposition
- end
+ skip_before_action :authenticate_user!
+ before_action :find_model
+ before_action :authorize_access!, only: [:show]
+ before_action :authorize_create_access!, only: [:create]
private
def find_model
- unless upload_model && upload_mount
- return render_404
- end
+ return render_404 unless upload_model && upload_mount
@model = upload_model.find(params[:id])
end
def authorize_access!
authorized =
- case @model
- when Project
- can?(current_user, :read_project, @model)
- when Group
- can?(current_user, :read_group, @model)
+ case model
when Note
- can?(current_user, :read_project, @model.project)
- else
- # No authentication required for user avatars.
+ can?(current_user, :read_project, model.project)
+ when User
true
+ else
+ permission = "read_#{model.class.to_s.underscore}".to_sym
+
+ can?(current_user, permission, model)
end
- return if authorized
+ render_unauthorized unless authorized
+ end
+
+ def authorize_create_access!
+ # for now we support only personal snippets comments
+ authorized = can?(current_user, :comment_personal_snippet, model)
+ render_unauthorized unless authorized
+ end
+
+ def render_unauthorized
if current_user
render_404
else
@@ -58,17 +51,44 @@ class UploadsController < ApplicationController
"project" => Project,
"note" => Note,
"group" => Group,
- "appearance" => Appearance
+ "appearance" => Appearance,
+ "personal_snippet" => PersonalSnippet
}
upload_models[params[:model]]
end
def upload_mount
+ return true unless params[:mounted_as]
+
upload_mounts = %w(avatar attachment file logo header_logo)
if upload_mounts.include?(params[:mounted_as])
params[:mounted_as]
end
end
+
+ def uploader
+ return @uploader if defined?(@uploader)
+
+ if model.is_a?(PersonalSnippet)
+ @uploader = PersonalFileUploader.new(model, params[:secret])
+
+ @uploader.retrieve_from_store!(params[:filename])
+ else
+ @uploader = @model.send(upload_mount)
+
+ redirect_to @uploader.url unless @uploader.file_storage?
+ end
+
+ @uploader
+ end
+
+ def uploader_class
+ PersonalFileUploader
+ end
+
+ def model
+ @model ||= find_model
+ end
end
diff --git a/app/policies/personal_snippet_policy.rb b/app/policies/personal_snippet_policy.rb
index d3913986cd8..e1e5336da8c 100644
--- a/app/policies/personal_snippet_policy.rb
+++ b/app/policies/personal_snippet_policy.rb
@@ -3,11 +3,16 @@ class PersonalSnippetPolicy < BasePolicy
can! :read_personal_snippet if @subject.public?
return unless @user
+ if @subject.public?
+ can! :comment_personal_snippet
+ end
+
if @subject.author == @user
can! :read_personal_snippet
can! :update_personal_snippet
can! :destroy_personal_snippet
can! :admin_personal_snippet
+ can! :comment_personal_snippet
end
unless @user.external?
@@ -16,6 +21,7 @@ class PersonalSnippetPolicy < BasePolicy
if @subject.internal? && !@user.external?
can! :read_personal_snippet
+ can! :comment_personal_snippet
end
end
end
diff --git a/app/services/projects/upload_service.rb b/app/services/projects/upload_service.rb
deleted file mode 100644
index be34d4fa9b8..00000000000
--- a/app/services/projects/upload_service.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-module Projects
- class UploadService < BaseService
- def initialize(project, file)
- @project, @file = project, file
- end
-
- def execute
- return nil unless @file && @file.size <= max_attachment_size
-
- uploader = FileUploader.new(@project)
- uploader.store!(@file)
-
- uploader.to_h
- end
-
- private
-
- def max_attachment_size
- current_application_settings.max_attachment_size.megabytes.to_i
- end
- end
-end
diff --git a/app/services/upload_service.rb b/app/services/upload_service.rb
new file mode 100644
index 00000000000..6c5b2baff41
--- /dev/null
+++ b/app/services/upload_service.rb
@@ -0,0 +1,20 @@
+class UploadService
+ def initialize(model, file, uploader_class = FileUploader)
+ @model, @file, @uploader_class = model, file, uploader_class
+ end
+
+ def execute
+ return nil unless @file && @file.size <= max_attachment_size
+
+ uploader = @uploader_class.new(@model)
+ uploader.store!(@file)
+
+ uploader.to_h
+ end
+
+ private
+
+ def max_attachment_size
+ current_application_settings.max_attachment_size.megabytes.to_i
+ end
+end
diff --git a/app/uploaders/artifact_uploader.rb b/app/uploaders/artifact_uploader.rb
index e84944ed411..3e36ec91205 100644
--- a/app/uploaders/artifact_uploader.rb
+++ b/app/uploaders/artifact_uploader.rb
@@ -30,8 +30,4 @@ class ArtifactUploader < GitlabUploader
def filename
file.try(:filename)
end
-
- def exists?
- file.try(:exists?)
- end
end
diff --git a/app/uploaders/file_uploader.rb b/app/uploaders/file_uploader.rb
index d2783ce5b2f..7e94218c23d 100644
--- a/app/uploaders/file_uploader.rb
+++ b/app/uploaders/file_uploader.rb
@@ -26,11 +26,11 @@ class FileUploader < GitlabUploader
File.join(CarrierWave.root, base_dir, model.path_with_namespace)
end
- attr_accessor :project
+ attr_accessor :model
attr_reader :secret
- def initialize(project, secret = nil)
- @project = project
+ def initialize(model, secret = nil)
+ @model = model
@secret = secret || generate_secret
end
@@ -38,10 +38,6 @@ class FileUploader < GitlabUploader
File.join(dynamic_path_segment, @secret)
end
- def model
- project
- end
-
def relative_path
self.file.path.sub("#{dynamic_path_segment}/", '')
end
diff --git a/app/uploaders/gitlab_uploader.rb b/app/uploaders/gitlab_uploader.rb
index d662ba6820c..e0a6c9b4067 100644
--- a/app/uploaders/gitlab_uploader.rb
+++ b/app/uploaders/gitlab_uploader.rb
@@ -33,4 +33,8 @@ class GitlabUploader < CarrierWave::Uploader::Base
def relative_path
self.file.path.sub("#{root}/", '')
end
+
+ def exists?
+ file.try(:exists?)
+ end
end
diff --git a/app/uploaders/lfs_object_uploader.rb b/app/uploaders/lfs_object_uploader.rb
index faab539b8e0..95a891111e1 100644
--- a/app/uploaders/lfs_object_uploader.rb
+++ b/app/uploaders/lfs_object_uploader.rb
@@ -9,10 +9,6 @@ class LfsObjectUploader < GitlabUploader
"#{Gitlab.config.lfs.storage_path}/tmp/cache"
end
- def exists?
- file.try(:exists?)
- end
-
def filename
model.oid[4..-1]
end
diff --git a/app/uploaders/personal_file_uploader.rb b/app/uploaders/personal_file_uploader.rb
new file mode 100644
index 00000000000..969b0a20d38
--- /dev/null
+++ b/app/uploaders/personal_file_uploader.rb
@@ -0,0 +1,15 @@
+class PersonalFileUploader < FileUploader
+ def self.dynamic_path_segment(model)
+ File.join(CarrierWave.root, model_path(model))
+ end
+
+ private
+
+ def secure_url
+ File.join(self.class.model_path(model), secret, file.filename)
+ end
+
+ def self.model_path(model)
+ File.join("/#{base_dir}", model.class.to_s.underscore, model.id.to_s)
+ end
+end
diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml
index f5e7ea7710d..e9e06e5c8e3 100644
--- a/app/views/layouts/project.html.haml
+++ b/app/views/layouts/project.html.haml
@@ -11,7 +11,7 @@
- preview_markdown_path = preview_markdown_namespace_project_path(project.namespace, project)
- if current_user
:javascript
- window.project_uploads_path = "#{namespace_project_uploads_path project.namespace,project}";
+ window.uploads_path = "#{namespace_project_uploads_path project.namespace,project}";
window.preview_markdown_path = "#{preview_markdown_path}";
- content_for :header_content do