Shrine - Download Endpoint with Account-based authentication

145 views Asked by At

I'm using Shrine with Rails, with the download_endpoint plugin. I have this working with route-based authentication via Devise, but I'd like to go one step further and add account-based authentication so that users can only access their own images.

Rails.application.routes.draw do
  get "/img/*rest", to: "download#confirm_response"
end

This uses the URL /img/xxx – but I'm trying to use something like /img/account_id/xxx, so this is my updated routes.rb:

Rails.application.routes.draw do
  get "/img/:account_id/*rest", to: "download#confirm_response"
end

Here is my updated Controller, I'm not sure exactly what to amend in my set_rack_response method in order to correctly pull in my account_id. I have the rack_response plugin loaded, is it possible to set this up?

class DownloadController < ApplicationController
  def confirm_response
    @account = Account.find(params[:account_id])
    set_rack_response @account.to_rack_response
  end

  private

  def set_rack_response((status, headers, body))
    self.status = status
    self.headers.merge!(headers)
    self.response_body = body
  end
end

@Janko EDIT:

I've updated my routes and controller, I have 2 models that have image files (photos and logos) that I would love to use download_endpoint for both.

I feel like I'm missing where to add :account_id to the download_url itself.

Would love for the URL to be /img/:account_id/xxx but what do you think would work best given this setup?

# Account.rb
class Account < ApplicationRecord
  has_many :photos
  has_many :logos
end

# Photo.rb
class Photo < ApplicationRecord
  belongs_to :account

  include PhotoUploader::Attachment(:photo_file)
end

# Logo.rb
class Logo < ApplicationRecord
  belongs_to :account

  include LogoUploader::Attachment(:logo_file)
end

# Updated download_controller.rb
class DownloadController < ApplicationController
  def confirm_response
    @account = Account.find(params[:account_id])
    @photo = @account.photos.find(params[:photo_id])

    set_rack_response @photo.to_rack_response
  end

  private

  def set_rack_response((status, headers, body))
    self.status = status
    self.headers.merge!(headers)
    self.response_body = body
  end
end

# Updated config/routes.rb
Rails.application.routes.draw do
  get "/img/:account_id/:photo_id/*rest", to: "download#confirm_response"
end

# Updated config/initializers/shrine.rb
Shrine.plugin :download_endpoint, prefix: "img", host: [:cloudfront]
Shrine.plugin :rack_response

# Updated views/photos/show.html.erb
<%= image_tag(@photo.photo_file.download_url) %>
0

There are 0 answers