Rename from ActiveFile to ActiveVault since activefile gem name was taken

This commit is contained in:
David Heinemeier Hansson 2017-07-05 13:06:29 +02:00
parent e635dac88f
commit 571509ad12
29 changed files with 87 additions and 87 deletions

@ -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

@ -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:)

@ -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