Rename from ActiveFile to ActiveVault since activefile gem name was taken
This commit is contained in:
parent
e635dac88f
commit
571509ad12
@ -1,7 +1,7 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
activefile (0.1)
|
||||
activevault (0.1)
|
||||
actionpack (>= 5.1)
|
||||
activejob (>= 5.1)
|
||||
activerecord (>= 5.1)
|
||||
@ -223,7 +223,7 @@ PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
activefile!
|
||||
activevault!
|
||||
aws-sdk
|
||||
bundler (~> 1.15)
|
||||
byebug
|
||||
|
@ -11,7 +11,7 @@ end
|
||||
|
||||
class Avatar < ApplicationRecord
|
||||
belongs_to :person
|
||||
belongs_to :image, class_name: 'ActiveFile::Blob'
|
||||
belongs_to :image, class_name: 'ActiveVault::Blob'
|
||||
|
||||
has_file :image
|
||||
end
|
||||
@ -19,9 +19,9 @@ end
|
||||
avatar.image.url(expires_in: 5.minutes)
|
||||
|
||||
|
||||
class ActiveFile::DownloadsController < ActionController::Base
|
||||
class ActiveVault::DownloadsController < ActionController::Base
|
||||
def show
|
||||
head :ok, ActiveFile::Blob.locate(params[:id]).download_headers
|
||||
head :ok, ActiveVault::Blob.locate(params[:id]).download_headers
|
||||
end
|
||||
end
|
||||
|
||||
@ -29,7 +29,7 @@ end
|
||||
class AvatarsController < ApplicationController
|
||||
def create
|
||||
# @avatar = Avatar.create \
|
||||
# image: ActiveFile::Blob.save!(file_name: params.require(:name), content_type: request.content_type, data: request.body)
|
||||
# image: ActiveVault::Blob.save!(file_name: params.require(:name), content_type: request.content_type, data: request.body)
|
||||
@avatar = Avatar.create! image: Avatar.image.extract_from(request)
|
||||
end
|
||||
end
|
||||
|
@ -1,10 +1,10 @@
|
||||
Gem::Specification.new do |s|
|
||||
s.name = "activefile"
|
||||
s.name = "activevault"
|
||||
s.version = "0.1"
|
||||
s.authors = "David Heinemeier Hansson"
|
||||
s.email = "david@basecamp.com"
|
||||
s.summary = "Store files in Rails applications"
|
||||
s.homepage = "https://github.com/rails/activefile"
|
||||
s.homepage = "https://github.com/rails/activevault"
|
||||
s.license = "MIT"
|
||||
|
||||
s.required_ruby_version = ">= 1.9.3"
|
@ -1,7 +0,0 @@
|
||||
class ActiveFile::PurgeJob < ActiveJob::Base
|
||||
retry_on ActiveFile::StorageException
|
||||
|
||||
def perform(blob)
|
||||
blob.purge
|
||||
end
|
||||
end
|
@ -1,7 +1,7 @@
|
||||
require "active_record"
|
||||
require "active_file/railtie" if defined?(Rails)
|
||||
require "active_vault/railtie" if defined?(Rails)
|
||||
|
||||
module ActiveFile
|
||||
module ActiveVault
|
||||
extend ActiveSupport::Autoload
|
||||
|
||||
autoload :Blob
|
@ -1,8 +1,8 @@
|
||||
require "active_file/site"
|
||||
require "active_file/filename"
|
||||
require "active_vault/site"
|
||||
require "active_vault/filename"
|
||||
|
||||
# Schema: id, key, filename, content_type, metadata, byte_size, checksum, created_at
|
||||
class ActiveFile::Blob < ActiveRecord::Base
|
||||
class ActiveVault::Blob < ActiveRecord::Base
|
||||
self.table_name = "rails_blobs"
|
||||
|
||||
has_secure_token :key
|
||||
@ -31,7 +31,7 @@ def key
|
||||
end
|
||||
|
||||
def filename
|
||||
ActiveFile::Filename.new(self[:filename])
|
||||
ActiveVault::Filename.new(self[:filename])
|
||||
end
|
||||
|
||||
def url(expires_in: 5.minutes, disposition: :inline)
|
||||
@ -61,6 +61,6 @@ def purge
|
||||
end
|
||||
|
||||
def purge_later
|
||||
ActiveFile::PurgeJob.perform_later(self)
|
||||
ActiveVault::PurgeJob.perform_later(self)
|
||||
end
|
||||
end
|
@ -1,13 +1,13 @@
|
||||
# Configuration should be something like this:
|
||||
#
|
||||
# config/environments/development.rb
|
||||
# config.active_file.site = :local
|
||||
# config.active_vault.site = :local
|
||||
#
|
||||
# config/environments/production.rb
|
||||
# config.active_file.site = :amazon
|
||||
# config.active_vault.site = :amazon
|
||||
local:
|
||||
site: Disk
|
||||
root: <%%= File.join(Dir.tmpdir, "active_file") %>
|
||||
root: <%%= File.join(Dir.tmpdir, "active_vault") %>
|
||||
|
||||
amazon:
|
||||
site: S3
|
@ -1,13 +1,13 @@
|
||||
require "action_controller"
|
||||
require "active_file/blob"
|
||||
require "active_file/verified_key_with_expiration"
|
||||
require "active_vault/blob"
|
||||
require "active_vault/verified_key_with_expiration"
|
||||
|
||||
require "active_support/core_ext/object/inclusion"
|
||||
|
||||
class ActiveFile::DiskController < ActionController::Base
|
||||
class ActiveVault::DiskController < ActionController::Base
|
||||
def show
|
||||
if key = decode_verified_key
|
||||
blob = ActiveFile::Blob.find_by!(key: key)
|
||||
blob = ActiveVault::Blob.find_by!(key: key)
|
||||
|
||||
if stale?(etag: blob.checksum)
|
||||
send_data blob.download, filename: blob.filename, type: blob.content_type, disposition: disposition_param
|
||||
@ -19,7 +19,7 @@ def show
|
||||
|
||||
private
|
||||
def decode_verified_key
|
||||
ActiveFile::VerifiedKeyWithExpiration.decode(params[:encoded_key])
|
||||
ActiveVault::VerifiedKeyWithExpiration.decode(params[:encoded_key])
|
||||
end
|
||||
|
||||
def disposition_param
|
@ -1,4 +1,4 @@
|
||||
class ActiveFile::Download
|
||||
class ActiveVault::Download
|
||||
# Sending .ai files as application/postscript to Safari opens them in a blank, grey screen.
|
||||
# Downloading .ai as application/postscript files in Safari appends .ps to the extension.
|
||||
# Sending HTML, SVG, XML and SWF files as binary closes XSS vulnerabilities.
|
@ -1,4 +1,4 @@
|
||||
class ActiveFile::Filename
|
||||
class ActiveVault::Filename
|
||||
include Comparable
|
||||
|
||||
def initialize(filename)
|
@ -1,4 +1,4 @@
|
||||
class ActiveFile::CreateBlobs < ActiveRecord::Migration[5.1]
|
||||
class ActiveVault::CreateBlobs < ActiveRecord::Migration[5.1]
|
||||
def change
|
||||
create_table :rails_blobs do |t|
|
||||
t.string :key
|
7
lib/active_vault/purge_job.rb
Normal file
7
lib/active_vault/purge_job.rb
Normal file
@ -0,0 +1,7 @@
|
||||
class ActiveVault::PurgeJob < ActiveJob::Base
|
||||
retry_on ActiveVault::StorageException
|
||||
|
||||
def perform(blob)
|
||||
blob.purge
|
||||
end
|
||||
end
|
@ -1,17 +1,17 @@
|
||||
require "rails/railtie"
|
||||
|
||||
module ActiveFile
|
||||
module ActiveVault
|
||||
class Railtie < Rails::Railtie # :nodoc:
|
||||
config.action_file = ActiveSupport::OrderedOptions.new
|
||||
|
||||
config.eager_load_namespaces << ActiveFile
|
||||
config.eager_load_namespaces << ActiveVault
|
||||
|
||||
initializer "action_file.routes" do
|
||||
require "active_file/disk_controller"
|
||||
require "active_vault/disk_controller"
|
||||
|
||||
config.after_initialize do |app|
|
||||
app.routes.prepend do
|
||||
get "/rails/blobs/:encoded_key" => "active_file/disk#show", as: :rails_disk_blob
|
||||
get "/rails/blobs/:encoded_key" => "active_vault/disk#show", as: :rails_disk_blob
|
||||
end
|
||||
end
|
||||
end
|
@ -1,9 +1,9 @@
|
||||
# Abstract class serving as an interface for concrete sites.
|
||||
class ActiveFile::Site
|
||||
class ActiveVault::Site
|
||||
def self.configure(site, **options)
|
||||
begin
|
||||
require "active_file/site/#{site.to_s.downcase}_site"
|
||||
ActiveFile::Site.const_get(:"#{site}Site").new(**options)
|
||||
require "active_vault/site/#{site.to_s.downcase}_site"
|
||||
ActiveVault::Site.const_get(:"#{site}Site").new(**options)
|
||||
rescue LoadError => e
|
||||
puts "Couldn't configure site: #{site} (#{e.message})"
|
||||
end
|
@ -1,7 +1,7 @@
|
||||
require "fileutils"
|
||||
require "pathname"
|
||||
|
||||
class ActiveFile::Site::DiskSite < ActiveFile::Site
|
||||
class ActiveVault::Site::DiskSite < ActiveVault::Site
|
||||
attr_reader :root
|
||||
|
||||
def initialize(root:)
|
||||
@ -38,7 +38,7 @@ def exist?(key)
|
||||
|
||||
|
||||
def url(key, expires_in:, disposition:, filename:)
|
||||
verified_key_with_expiration = ActiveFile::VerifiedKeyWithExpiration.encode(key, expires_in: expires_in)
|
||||
verified_key_with_expiration = ActiveVault::VerifiedKeyWithExpiration.encode(key, expires_in: expires_in)
|
||||
|
||||
if defined?(Rails) && defined?(Rails.application)
|
||||
Rails.application.routes.url_helpers.rails_disk_blob_path(verified_key_with_expiration, disposition: disposition)
|
@ -1,6 +1,6 @@
|
||||
require "google/cloud/storage"
|
||||
|
||||
class ActiveFile::Site::GCSSite < ActiveFile::Site
|
||||
class ActiveVault::Site::GCSSite < ActiveVault::Site
|
||||
attr_reader :client, :bucket
|
||||
|
||||
def initialize(project:, keyfile:, bucket:)
|
@ -1,4 +1,4 @@
|
||||
class ActiveFile::Site::MirrorSite < ActiveFile::Site
|
||||
class ActiveVault::Site::MirrorSite < ActiveVault::Site
|
||||
attr_reader :sites
|
||||
|
||||
def initialize(sites:)
|
@ -1,6 +1,6 @@
|
||||
require "aws-sdk"
|
||||
|
||||
class ActiveFile::Site::S3Site < ActiveFile::Site
|
||||
class ActiveVault::Site::S3Site < ActiveVault::Site
|
||||
attr_reader :client, :bucket
|
||||
|
||||
def initialize(access_key_id:, secret_access_key:, region:, bucket:)
|
4
lib/active_file/verified_key_with_expiration.rb → lib/active_vault/verified_key_with_expiration.rb
4
lib/active_file/verified_key_with_expiration.rb → lib/active_vault/verified_key_with_expiration.rb
@ -1,5 +1,5 @@
|
||||
class ActiveFile::VerifiedKeyWithExpiration
|
||||
class_attribute :verifier, default: defined?(Rails) ? Rails.application.message_verifier('ActiveFile') : nil
|
||||
class ActiveVault::VerifiedKeyWithExpiration
|
||||
class_attribute :verifier, default: defined?(Rails) ? Rails.application.message_verifier('ActiveVault') : nil
|
||||
|
||||
class << self
|
||||
def encode(key, expires_in: nil)
|
@ -1,8 +1,8 @@
|
||||
require "test_helper"
|
||||
require "database/setup"
|
||||
require "active_file/blob"
|
||||
require "active_vault/blob"
|
||||
|
||||
class ActiveFile::BlobTest < ActiveSupport::TestCase
|
||||
class ActiveVault::BlobTest < ActiveSupport::TestCase
|
||||
test "create after upload sets byte size and checksum" do
|
||||
data = "Hello world!"
|
||||
blob = create_blob data: data
|
||||
@ -23,6 +23,6 @@ class ActiveFile::BlobTest < ActiveSupport::TestCase
|
||||
|
||||
private
|
||||
def expected_url_for(blob, disposition: :inline)
|
||||
"/rails/blobs/#{ActiveFile::VerifiedKeyWithExpiration.encode(blob.key, expires_in: 5.minutes)}?disposition=#{disposition}"
|
||||
"/rails/blobs/#{ActiveVault::VerifiedKeyWithExpiration.encode(blob.key, expires_in: 5.minutes)}?disposition=#{disposition}"
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
require "active_file/migration"
|
||||
require "active_vault/migration"
|
||||
|
||||
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
|
||||
ActiveFile::CreateBlobs.migrate(:up)
|
||||
ActiveVault::CreateBlobs.migrate(:up)
|
||||
|
@ -4,30 +4,30 @@
|
||||
require "action_controller"
|
||||
require "action_controller/test_case"
|
||||
|
||||
require "active_file/disk_controller"
|
||||
require "active_file/verified_key_with_expiration"
|
||||
require "active_vault/disk_controller"
|
||||
require "active_vault/verified_key_with_expiration"
|
||||
|
||||
class ActiveFile::DiskControllerTest < ActionController::TestCase
|
||||
class ActiveVault::DiskControllerTest < ActionController::TestCase
|
||||
Routes = ActionDispatch::Routing::RouteSet.new.tap do |routes|
|
||||
routes.draw do
|
||||
get "/rails/blobs/:encoded_key" => "active_file/disk#show", as: :rails_disk_blob
|
||||
get "/rails/blobs/:encoded_key" => "active_vault/disk#show", as: :rails_disk_blob
|
||||
end
|
||||
end
|
||||
|
||||
setup do
|
||||
@blob = create_blob
|
||||
@routes = Routes
|
||||
@controller = ActiveFile::DiskController.new
|
||||
@controller = ActiveVault::DiskController.new
|
||||
end
|
||||
|
||||
test "showing blob inline" do
|
||||
get :show, params: { encoded_key: ActiveFile::VerifiedKeyWithExpiration.encode(@blob.key, expires_in: 5.minutes) }
|
||||
get :show, params: { encoded_key: ActiveVault::VerifiedKeyWithExpiration.encode(@blob.key, expires_in: 5.minutes) }
|
||||
assert_equal "inline; filename=\"#{@blob.filename}\"", @response.headers["Content-Disposition"]
|
||||
assert_equal "text/plain", @response.headers["Content-Type"]
|
||||
end
|
||||
|
||||
test "sending blob as attachment" do
|
||||
get :show, params: { encoded_key: ActiveFile::VerifiedKeyWithExpiration.encode(@blob.key, expires_in: 5.minutes), disposition: :attachment }
|
||||
get :show, params: { encoded_key: ActiveVault::VerifiedKeyWithExpiration.encode(@blob.key, expires_in: 5.minutes), disposition: :attachment }
|
||||
assert_equal "attachment; filename=\"#{@blob.filename}\"", @response.headers["Content-Disposition"]
|
||||
assert_equal "text/plain", @response.headers["Content-Type"]
|
||||
end
|
||||
|
@ -1,9 +1,9 @@
|
||||
require "test_helper"
|
||||
|
||||
class ActiveFile::FilenameTest < ActiveSupport::TestCase
|
||||
class ActiveVault::FilenameTest < ActiveSupport::TestCase
|
||||
test "sanitize" do
|
||||
"%$|:;/\t\r\n\\".each_char do |character|
|
||||
filename = ActiveFile::Filename.new("foo#{character}bar.pdf")
|
||||
filename = ActiveVault::Filename.new("foo#{character}bar.pdf")
|
||||
assert_equal 'foo-bar.pdf', filename.sanitized
|
||||
assert_equal 'foo-bar.pdf', filename.to_s
|
||||
end
|
||||
@ -16,21 +16,21 @@ class ActiveFile::FilenameTest < ActiveSupport::TestCase
|
||||
"\xCF" => "<EFBFBD>",
|
||||
"\x00" => "",
|
||||
}.each do |actual, expected|
|
||||
assert_equal expected, ActiveFile::Filename.new(actual).sanitized
|
||||
assert_equal expected, ActiveVault::Filename.new(actual).sanitized
|
||||
end
|
||||
end
|
||||
|
||||
test "strips RTL override chars used to spoof unsafe executables as docs" do
|
||||
# Would be displayed in Windows as "evilexe.pdf" due to the right-to-left
|
||||
# (RTL) override char!
|
||||
assert_equal 'evil-fdp.exe', ActiveFile::Filename.new("evil\u{202E}fdp.exe").sanitized
|
||||
assert_equal 'evil-fdp.exe', ActiveVault::Filename.new("evil\u{202E}fdp.exe").sanitized
|
||||
end
|
||||
|
||||
test "compare case-insensitively" do
|
||||
assert_operator ActiveFile::Filename.new('foobar.pdf'), :==, ActiveFile::Filename.new('FooBar.PDF')
|
||||
assert_operator ActiveVault::Filename.new('foobar.pdf'), :==, ActiveVault::Filename.new('FooBar.PDF')
|
||||
end
|
||||
|
||||
test "compare sanitized" do
|
||||
assert_operator ActiveFile::Filename.new('foo-bar.pdf'), :==, ActiveFile::Filename.new("foo\tbar.pdf")
|
||||
assert_operator ActiveVault::Filename.new('foo-bar.pdf'), :==, ActiveVault::Filename.new("foo\tbar.pdf")
|
||||
end
|
||||
end
|
||||
|
@ -1,8 +1,8 @@
|
||||
require "tmpdir"
|
||||
require "site/shared_site_tests"
|
||||
|
||||
class ActiveFile::Site::DiskSiteTest < ActiveSupport::TestCase
|
||||
SITE = ActiveFile::Site.configure(:Disk, root: File.join(Dir.tmpdir, "active_file"))
|
||||
class ActiveVault::Site::DiskSiteTest < ActiveSupport::TestCase
|
||||
SITE = ActiveVault::Site.configure(:Disk, root: File.join(Dir.tmpdir, "active_vault"))
|
||||
|
||||
include ActiveFile::Site::SharedSiteTests
|
||||
include ActiveVault::Site::SharedSiteTests
|
||||
end
|
||||
|
@ -1,10 +1,10 @@
|
||||
require "site/shared_site_tests"
|
||||
|
||||
if SITE_CONFIGURATIONS[:gcs]
|
||||
class ActiveFile::Site::GCSSiteTest < ActiveSupport::TestCase
|
||||
SITE = ActiveFile::Site.configure(:GCS, SITE_CONFIGURATIONS[:gcs])
|
||||
class ActiveVault::Site::GCSSiteTest < ActiveSupport::TestCase
|
||||
SITE = ActiveVault::Site.configure(:GCS, SITE_CONFIGURATIONS[:gcs])
|
||||
|
||||
include ActiveFile::Site::SharedSiteTests
|
||||
include ActiveVault::Site::SharedSiteTests
|
||||
end
|
||||
else
|
||||
puts "Skipping GCS Site tests because no GCS configuration was supplied"
|
||||
|
@ -1,10 +1,10 @@
|
||||
require "site/shared_site_tests"
|
||||
|
||||
if SITE_CONFIGURATIONS[:s3]
|
||||
class ActiveFile::Site::S3SiteTest < ActiveSupport::TestCase
|
||||
SITE = ActiveFile::Site.configure(:S3, SITE_CONFIGURATIONS[:s3])
|
||||
class ActiveVault::Site::S3SiteTest < ActiveSupport::TestCase
|
||||
SITE = ActiveVault::Site.configure(:S3, SITE_CONFIGURATIONS[:s3])
|
||||
|
||||
include ActiveFile::Site::SharedSiteTests
|
||||
include ActiveVault::Site::SharedSiteTests
|
||||
end
|
||||
else
|
||||
puts "Skipping S3 Site tests because no S3 configuration was supplied"
|
||||
|
@ -8,7 +8,7 @@
|
||||
puts "Missing site configuration file in test/sites/configurations.yml"
|
||||
end
|
||||
|
||||
module ActiveFile::Site::SharedSiteTests
|
||||
module ActiveVault::Site::SharedSiteTests
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
FIXTURE_KEY = SecureRandom.base58(24)
|
||||
|
@ -4,17 +4,17 @@
|
||||
require "active_support/testing/autorun"
|
||||
require "byebug"
|
||||
|
||||
require "active_file"
|
||||
require "active_vault"
|
||||
|
||||
require "active_file/site"
|
||||
ActiveFile::Blob.site = ActiveFile::Site.configure(:Disk, root: File.join(Dir.tmpdir, "active_file"))
|
||||
require "active_vault/site"
|
||||
ActiveVault::Blob.site = ActiveVault::Site.configure(:Disk, root: File.join(Dir.tmpdir, "active_vault"))
|
||||
|
||||
require "active_file/verified_key_with_expiration"
|
||||
ActiveFile::VerifiedKeyWithExpiration.verifier = ActiveSupport::MessageVerifier.new("Testing")
|
||||
require "active_vault/verified_key_with_expiration"
|
||||
ActiveVault::VerifiedKeyWithExpiration.verifier = ActiveSupport::MessageVerifier.new("Testing")
|
||||
|
||||
class ActiveSupport::TestCase
|
||||
private
|
||||
def create_blob(data: "Hello world!", filename: "hello.txt", content_type: "text/plain")
|
||||
ActiveFile::Blob.create_after_upload! io: StringIO.new(data), filename: filename, content_type: content_type
|
||||
ActiveVault::Blob.create_after_upload! io: StringIO.new(data), filename: filename, content_type: content_type
|
||||
end
|
||||
end
|
@ -1,19 +1,19 @@
|
||||
require "test_helper"
|
||||
require "active_support/core_ext/securerandom"
|
||||
|
||||
class ActiveFile::VerifiedKeyWithExpirationTest < ActiveSupport::TestCase
|
||||
class ActiveVault::VerifiedKeyWithExpirationTest < ActiveSupport::TestCase
|
||||
FIXTURE_KEY = SecureRandom.base58(24)
|
||||
|
||||
test "without expiration" do
|
||||
encoded_key = ActiveFile::VerifiedKeyWithExpiration.encode(FIXTURE_KEY)
|
||||
assert_equal FIXTURE_KEY, ActiveFile::VerifiedKeyWithExpiration.decode(encoded_key)
|
||||
encoded_key = ActiveVault::VerifiedKeyWithExpiration.encode(FIXTURE_KEY)
|
||||
assert_equal FIXTURE_KEY, ActiveVault::VerifiedKeyWithExpiration.decode(encoded_key)
|
||||
end
|
||||
|
||||
test "with expiration" do
|
||||
encoded_key = ActiveFile::VerifiedKeyWithExpiration.encode(FIXTURE_KEY, expires_in: 1.minute)
|
||||
assert_equal FIXTURE_KEY, ActiveFile::VerifiedKeyWithExpiration.decode(encoded_key)
|
||||
encoded_key = ActiveVault::VerifiedKeyWithExpiration.encode(FIXTURE_KEY, expires_in: 1.minute)
|
||||
assert_equal FIXTURE_KEY, ActiveVault::VerifiedKeyWithExpiration.decode(encoded_key)
|
||||
|
||||
travel 2.minutes
|
||||
assert_nil ActiveFile::VerifiedKeyWithExpiration.decode(encoded_key)
|
||||
assert_nil ActiveVault::VerifiedKeyWithExpiration.decode(encoded_key)
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user