From 0b3180c86f5df435d3c48cece4ffa20bcb507796 Mon Sep 17 00:00:00 2001 From: Martin Brennan Date: Tue, 20 Feb 2024 11:19:22 +1000 Subject: [PATCH] DEV: Add SecureUploadEndpointHelpers for controllers (#25758) This commit moves some code out of UploadController#show_secure so it can be reused in other controllers if a secure upload needs to have permission checks run. --- app/controllers/uploads_controller.rb | 14 +++----------- lib/secure_upload_endpoint_helpers.rb | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 11 deletions(-) create mode 100644 lib/secure_upload_endpoint_helpers.rb diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb index 00628ef5121..c4c651e9429 100644 --- a/app/controllers/uploads_controller.rb +++ b/app/controllers/uploads_controller.rb @@ -4,6 +4,7 @@ require "mini_mime" class UploadsController < ApplicationController include ExternalUploadHelpers + include SecureUploadEndpointHelpers requires_login except: %i[show show_short _show_secure_deprecated show_secure] @@ -143,12 +144,8 @@ class UploadsController < ApplicationController return xhr_not_allowed if request.xhr? path_with_ext = "#{params[:path]}.#{params[:extension]}" + upload = upload_from_path_and_extension(path_with_ext) - sha1 = File.basename(path_with_ext, File.extname(path_with_ext)) - # this takes care of optimized image requests - sha1 = sha1.partition("_").first if sha1.include?("_") - - upload = Upload.find_by(sha1: sha1) return render_404 if upload.blank? return render_404 if SiteSetting.prevent_anons_from_downloading_files && current_user.nil? @@ -167,12 +164,7 @@ class UploadsController < ApplicationController end def handle_secure_upload_request(upload, path_with_ext = nil) - if upload.access_control_post_id.present? - raise Discourse::InvalidAccess if current_user.nil? && SiteSetting.login_required - raise Discourse::InvalidAccess if !guardian.can_see?(upload.access_control_post) - else - return render_404 if current_user.nil? - end + check_secure_upload_permission(upload) # defaults to public: false, so only cached by the client browser cache_seconds = diff --git a/lib/secure_upload_endpoint_helpers.rb b/lib/secure_upload_endpoint_helpers.rb new file mode 100644 index 00000000000..363b21a7872 --- /dev/null +++ b/lib/secure_upload_endpoint_helpers.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module SecureUploadEndpointHelpers + include ActiveSupport::Concern + + def upload_from_path_and_extension(path_with_ext) + sha1 = File.basename(path_with_ext, File.extname(path_with_ext)) + # this takes care of optimized image requests + sha1 = sha1.partition("_").first if sha1.include?("_") + Upload.find_by(sha1: sha1) + end + + def upload_from_full_url(url) + Upload.find_by(sha1: Upload.sha1_from_long_url(url)) + end + + def check_secure_upload_permission(upload) + if upload.access_control_post_id.present? + raise Discourse::InvalidAccess if current_user.nil? && SiteSetting.login_required + raise Discourse::InvalidAccess if !guardian.can_see?(upload.access_control_post) + else + raise Discourse::NotFound if current_user.nil? + end + end +end