ActiveStorage Authentication

In the current documentation, we have an approach for Authenticated Controllers. This requires you to essentially duplicate all of the ActiveStorage controllers so you can include your application specific modules.

Would it be better to instead have the ActiveStorage::BaseController inherit from an interim controller like ApplicationStorageController where modules could be included to provide authentication and other types of behavior?

So rather than this:

# app/controllers/logos_controller.rb
class LogosController < ApplicationController
  # Through ApplicationController:
  # include Authenticate, SetCurrentAccount

  def show
    redirect_to Current.account.logo.url
  end
end

You could instead do this:

# app/controllers/application_storage_controller.rb
class ApplicationStorageController < ApplicationController
  include Authenticate, SetCurrentAccount
end

Or maybe there is another way we could provide developers a way to mix in their modules into the existing ActiveStorage controllers?

1 Like

There was a PR to create a BaseController: https://github.com/rails/rails/pull/41505 In the comments of that PR George Claghorn mentions how they fix this in Hey.

The following is a copy of the above link;

## where does this go?
ActiveSupport.on_load :active_storage_blob do
  def accessible_to?(accessor)
    attachments.includes(:record).any? { |attachment| attachment.accessible_to?(accessor) } || attachments.none?
  end
end

ActiveSupport.on_load :active_storage_attachment do
  def accessible_to?(accessor)
    record.try(:accessible_to?, accessor)
  end
end

ActiveSupport.on_load :action_text_rich_text do
  def accessible_to?(accessor)
    record.try(:accessible_to?, accessor)
  end
end

module ActiveStorage::Authorize
  extend ActiveSupport::Concern

  included do
    before_action :require_authorization
  end

  private
    def require_authorization
      head :forbidden unless authorized?
    end

    def authorized?
      @blob.accessible_to?(Current.identity)
    end
end

## where to put this?
Rails.application.config.to_prepare do
  ActiveStorage::Blobs::RedirectController.include ActiveStorage::Authorize
  ActiveStorage::Blobs::ProxyController.include ActiveStorage::Authorize
  ActiveStorage::Representations::RedirectController.include ActiveStorage::Authorize
  ActiveStorage::Representations::ProxyController.include ActiveStorage::Authorize
end

Would anyone know where to paste this type of config?

That looks like it would go in an initializer file.

1 Like