I am making a RESTful API using Ruby on Rails. I use Active Storage to manage attachments. However, Active Storage serves attachments publicly, and I want to serve privately.
I had been thinking to serve them on a route like /assets/:name?token=TOKEN
.
So I can manage them this way on the front-end for example:
// Front-end
const flowerPhoto = new Image
const params = new URLSearchParams({ token })
image.src = `${API_URL}/assets/flower-photo?${params.toString()}`
How can I achieve this?
I found this part Serving Files of Rails Guides very confusing
All Active Storage controllers are publicly accessible by default. The generated URLs are hard to guess, but permanent by design. If your files require a higher level of protection consider implementing Authenticated Controllers.
The RedirectController redirects to the actual service endpoint. This indirection decouples the service URL from the actual one, and allows, for example, mirroring attachments in different services for high-availability. The redirection has an HTTP expiration of 5 minutes.
I had tried it this way:
# config/routes.rb
Rails.application.routes.draw do
scope 'assets/:name', as: 'asset' do
root 'assets#show', as: ''
end
end
# app/models/asset.rb
class Asset < ApplicationRecord
has_one_attached :document
end
# app/controllers/assets_controller.rb
class AssetsController < ApplicationController
include ActiveStorage::SetCurrent
before_action :set_asset
before_action :authorize
def show
redirect_to @asset.document.url
end
private
def set_asset = @asset = Asset.find_by!(name: params[:name])
def authorize = user_authentication(params[:token])
end
# config/application.rb
module App
class Application < Rails::Application
# Public attachment URLs
config.active_storage.draw_routes = false
end
end
Nonetheless, I get this error:
NoMethodError in AssetsController#show
undefined method `rails_disk_service_url' for module
redirect_to @asset.document.url
Delete the configuration you have set, and then:
redirect_to @asset.document.url(expires_in: 5.minutes, disposition: 'inline')