diff --git a/app/controllers/account_configs_controller.rb b/app/controllers/account_configs_controller.rb index 3bc36334..0f010047 100644 --- a/app/controllers/account_configs_controller.rb +++ b/app/controllers/account_configs_controller.rb @@ -9,7 +9,8 @@ class AccountConfigsController < ApplicationController AccountConfig::FORCE_MFA, AccountConfig::ALLOW_TO_RESUBMIT, AccountConfig::ESIGNING_PREFERENCE_KEY, - AccountConfig::FORM_WITH_CONFETTI_KEY + AccountConfig::FORM_WITH_CONFETTI_KEY, + AccountConfig::DOWNLOAD_LINKS_AUTH_KEY ].freeze InvalidKey = Class.new(StandardError) diff --git a/app/controllers/api/active_storage_blobs_proxy_controller.rb b/app/controllers/api/active_storage_blobs_proxy_controller.rb index 0a9c68c1..f96d3788 100644 --- a/app/controllers/api/active_storage_blobs_proxy_controller.rb +++ b/app/controllers/api/active_storage_blobs_proxy_controller.rb @@ -20,6 +20,8 @@ module Api blob = ActiveStorage::Blob.find_by!(uuid: blob_uuid) + authorization_check!(blob) if exp.blank? + if request.headers['Range'].present? send_blob_byte_range_data blob, request.headers['Range'] else @@ -31,5 +33,20 @@ module Api end end end + + private + + def authorization_check!(blob) + is_authorized = + blob.attachments.all? do |a| + a.name.in?(%w[logo preview_images]) || + (current_user && a.record.account.id == current_user.account_id) || + !a.record.account.account_configs.find_or_initialize_by(key: AccountConfig::DOWNLOAD_LINKS_AUTH_KEY).value + end + + return if is_authorized + + raise CanCan::AccessDenied + end end end diff --git a/app/controllers/api/api_base_controller.rb b/app/controllers/api/api_base_controller.rb index c3924b53..5d7441fa 100644 --- a/app/controllers/api/api_base_controller.rb +++ b/app/controllers/api/api_base_controller.rb @@ -50,14 +50,16 @@ module Api end def authenticate_user! - @current_user ||= - if request.headers['X-Auth-Token'].present? - sha256 = Digest::SHA256.hexdigest(request.headers['X-Auth-Token']) + render json: { error: 'Not authenticated' }, status: :unauthorized unless current_user + end - User.joins(:access_token).active.find_by(access_token: { sha256: }) - end + def current_user + super || @current_user ||= + if request.headers['X-Auth-Token'].present? + sha256 = Digest::SHA256.hexdigest(request.headers['X-Auth-Token']) - render json: { error: 'Not authenticated' }, status: :unauthorized unless current_user + User.joins(:access_token).active.find_by(access_token: { sha256: }) + end end def current_account diff --git a/app/models/account_config.rb b/app/models/account_config.rb index 63b97b82..533cba19 100644 --- a/app/models/account_config.rb +++ b/app/models/account_config.rb @@ -34,6 +34,7 @@ class AccountConfig < ApplicationRecord FORM_WITH_CONFETTI_KEY = 'form_with_confetti' ESIGNING_PREFERENCE_KEY = 'esigning_preference' WEBHOOK_PREFERENCES_KEY = 'webhook_preferences' + DOWNLOAD_LINKS_AUTH_KEY = 'download_links_auth' DEFAULT_VALUES = { SUBMITTER_INVITATION_EMAIL_KEY => { diff --git a/app/views/accounts/show.html.erb b/app/views/accounts/show.html.erb index b6f8a7cb..a7563505 100644 --- a/app/views/accounts/show.html.erb +++ b/app/views/accounts/show.html.erb @@ -75,6 +75,18 @@ <% end %> <% end %> + <% account_config = AccountConfig.find_or_initialize_by(account: current_account, key: AccountConfig::DOWNLOAD_LINKS_AUTH_KEY) %> + <% if can?(:manage, account_config) %> + <%= form_for account_config, url: account_configs_path, method: :post do |f| %> + <%= f.hidden_field :key %> +
+ + Require authorization for file download links + + <%= f.check_box :value, class: 'toggle', checked: account_config.value, onchange: 'this.form.requestSubmit()' %> +
+ <% end %> + <% end %> <% end %> <% if can?(:manage, current_account) && Docuseal.multitenant? && true_user == current_user %> diff --git a/config/routes.rb b/config/routes.rb index 93aa9d17..237d6e84 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -79,6 +79,8 @@ Rails.application.routes.draw do resources :submissions_export, only: %i[index new] end resources :preview_document_page, only: %i[show], path: '/preview/:signed_uuid' + resource :blobs_proxy, only: %i[show], path: '/file/:signed_uuid/*filename', + controller: 'api/active_storage_blobs_proxy' resource :blobs_proxy, only: %i[show], path: '/blobs_proxy/:signed_uuid/*filename', controller: 'api/active_storage_blobs_proxy'