From d2ff19c39c097aa17d16e33c8de981f43cd1ffa0 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 3 Jul 2017 20:14:28 +0200 Subject: WIP: Disk URLs --- lib/active_file/blob.rb | 3 +++ lib/active_file/disk_controller.rb | 20 ++++++++++++++++ lib/active_file/railtie.rb | 15 +++++++++++- lib/active_file/sites/disk_site.rb | 48 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 lib/active_file/disk_controller.rb (limited to 'lib') diff --git a/lib/active_file/blob.rb b/lib/active_file/blob.rb index 5a82edee65..3cb98656f2 100644 --- a/lib/active_file/blob.rb +++ b/lib/active_file/blob.rb @@ -32,6 +32,9 @@ class ActiveFile::Blob < ActiveRecord::Base def filename ActiveFile::Filename.new(self[:filename]) end + + def url(disposition: :inline, expires_in: 5.minutes) + site.url key, disposition: disposition, expires_in: expires_in end diff --git a/lib/active_file/disk_controller.rb b/lib/active_file/disk_controller.rb new file mode 100644 index 0000000000..7d94b02f5c --- /dev/null +++ b/lib/active_file/disk_controller.rb @@ -0,0 +1,20 @@ +# FIXME: To be used by DiskSite#url +class ActiveFile::DiskController < ActionController::Base + def show + if verified_key.expired? + head :gone + else + blob = ActiveFile::Blob.find_by!(key: verified_key.to_s) + send_data blob.download, filename: blob.filename, type: blob.content_type, disposition: disposition_param + end + end + + private + def verified_key + ActiveFile::Sites::DiskSite::VerifiedKeyWithExpiration.new(params[:id]) + end + + def disposition_param + params[:disposition].presence_in(%w( inline attachment )) || 'inline' + end +end diff --git a/lib/active_file/railtie.rb b/lib/active_file/railtie.rb index e1b34f56cf..4398bb6072 100644 --- a/lib/active_file/railtie.rb +++ b/lib/active_file/railtie.rb @@ -1,6 +1,19 @@ require "rails/railtie" module ActiveFile - class Engine < ::Rails::Engine + class Railtie < Rails::Railtie # :nodoc: + config.action_cable = ActiveSupport::OrderedOptions.new + + config.eager_load_namespaces << ActiveFile + + initializer "action_cable.routes" do + require "active_file/disk_controller" + + config.after_initialize do |app| + app.routes.prepend do + get "/rails/blobs/:id" => "active_file/disk#show", as: :rails_disk_blob + end + end + end end end diff --git a/lib/active_file/sites/disk_site.rb b/lib/active_file/sites/disk_site.rb index ee39b7a736..da1e69df03 100644 --- a/lib/active_file/sites/disk_site.rb +++ b/lib/active_file/sites/disk_site.rb @@ -2,6 +2,42 @@ require "fileutils" require "pathname" class ActiveFile::Sites::DiskSite < ActiveFile::Site + class_attribute :verifier, default: -> { Rails.application.message_verifier('ActiveFile::DiskSite') } + + class << self + def generate_verifiable_key(key, expires_in:) + VerifiedKeyWithExpiration + end + end + + class VerifiableKeyWithExpiration + def initialize(verifiable_key_with_expiration) + verified_key_with_expiration = ActiveFile::Sites::DiskSite.verify(verifiable_key_with_expiration) + + @key = verified_key_with_expiration[:key] + @expires_at = verified_key_with_expiration[:expires_at] + end + + def expired? + @expires_at && Time.now.utc > @expires_at + end + + def decoded + key + end + end + + class VerifiedKeyWithExpiration + def initialize(key, expires_in: nil) + @key = key + @expires_at = Time.now.utc.advance(sec: expires_in) + end + + def encoded + ActiveFile::Sites::DiskSite.verify.generate({ key: @key, expires_at: @expires_at }) + end + end + attr_reader :root def initialize(root:) @@ -38,6 +74,14 @@ class ActiveFile::Sites::DiskSite < ActiveFile::Site end + def url(key, disposition:, expires_in: nil) + if defined?(Rails) + Rails.application.routes.url_helpers.rails_disk_blob_path(key) + else + "/rails/blobs/#{key}" + end + end + def byte_size(key) File.size path_for(key) end @@ -48,6 +92,10 @@ class ActiveFile::Sites::DiskSite < ActiveFile::Site private + def verifiable_key_with_expiration(key, expires_in: nil) + verifier.generate key: key, expires_at: Time.now.utc.advance(sec: expires_in) + end + def path_for(key) File.join root, folder_for(key), key end -- cgit v1.2.3