ActiveVault -> ActiveStorage
Yaroslav agreed to hand over the gem name ❤️
This commit is contained in:
parent
5869045f2e
commit
c624df326a
@ -1,7 +1,7 @@
|
|||||||
PATH
|
PATH
|
||||||
remote: .
|
remote: .
|
||||||
specs:
|
specs:
|
||||||
activevault (0.1)
|
activestorage (0.1)
|
||||||
actionpack (>= 5.1)
|
actionpack (>= 5.1)
|
||||||
activejob (>= 5.1)
|
activejob (>= 5.1)
|
||||||
activerecord (>= 5.1)
|
activerecord (>= 5.1)
|
||||||
@ -223,7 +223,7 @@ PLATFORMS
|
|||||||
ruby
|
ruby
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
activevault!
|
activestorage!
|
||||||
aws-sdk
|
aws-sdk
|
||||||
bundler (~> 1.15)
|
bundler (~> 1.15)
|
||||||
byebug
|
byebug
|
||||||
|
@ -19,7 +19,7 @@ user.avatar.exist? # => true
|
|||||||
user.avatar.purge
|
user.avatar.purge
|
||||||
user.avatar.exist? # => false
|
user.avatar.exist? # => false
|
||||||
|
|
||||||
user.image.url(expires_in: 5.minutes) # => /rails/blobs/<encoded-key>
|
user.avatar.url(expires_in: 5.minutes) # => /rails/blobs/<encoded-key>
|
||||||
|
|
||||||
class AvatarsController < ApplicationController
|
class AvatarsController < ApplicationController
|
||||||
def update
|
def update
|
||||||
@ -55,7 +55,7 @@ end
|
|||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Add `require "active_vault"` to config/application.rb and create a `config/initializers/active_vault_sites.rb` with the following:
|
Add `require "active_storage"` to config/application.rb and create a `config/initializers/active_storage_sites.rb` with the following:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
Gem::Specification.new do |s|
|
Gem::Specification.new do |s|
|
||||||
s.name = "activevault"
|
s.name = "activestorage"
|
||||||
s.version = "0.1"
|
s.version = "0.1"
|
||||||
s.authors = "David Heinemeier Hansson"
|
s.authors = "David Heinemeier Hansson"
|
||||||
s.email = "david@basecamp.com"
|
s.email = "david@basecamp.com"
|
||||||
s.summary = "Store files in Rails applications"
|
s.summary = "Store files in Rails applications"
|
||||||
s.homepage = "https://github.com/rails/activevault"
|
s.homepage = "https://github.com/rails/activestorage"
|
||||||
s.license = "MIT"
|
s.license = "MIT"
|
||||||
|
|
||||||
s.required_ruby_version = ">= 1.9.3"
|
s.required_ruby_version = ">= 1.9.3"
|
@ -1,7 +1,7 @@
|
|||||||
require "active_record"
|
require "active_record"
|
||||||
require "active_vault/railtie" if defined?(Rails)
|
require "active_storage/railtie" if defined?(Rails)
|
||||||
|
|
||||||
module ActiveVault
|
module ActiveStorage
|
||||||
extend ActiveSupport::Autoload
|
extend ActiveSupport::Autoload
|
||||||
|
|
||||||
autoload :Blob
|
autoload :Blob
|
@ -1,10 +1,10 @@
|
|||||||
require "active_vault/blob"
|
require "active_storage/blob"
|
||||||
require "active_vault/attachment"
|
require "active_storage/attachment"
|
||||||
|
|
||||||
require "action_dispatch/http/upload"
|
require "action_dispatch/http/upload"
|
||||||
require "active_support/core_ext/module/delegation"
|
require "active_support/core_ext/module/delegation"
|
||||||
|
|
||||||
class ActiveVault::Attached
|
class ActiveStorage::Attached
|
||||||
attr_reader :name, :record
|
attr_reader :name, :record
|
||||||
|
|
||||||
def initialize(name, record)
|
def initialize(name, record)
|
||||||
@ -14,21 +14,21 @@ def initialize(name, record)
|
|||||||
private
|
private
|
||||||
def create_blob_from(attachable)
|
def create_blob_from(attachable)
|
||||||
case attachable
|
case attachable
|
||||||
when ActiveVault::Blob
|
when ActiveStorage::Blob
|
||||||
attachable
|
attachable
|
||||||
when ActionDispatch::Http::UploadedFile
|
when ActionDispatch::Http::UploadedFile
|
||||||
ActiveVault::Blob.create_after_upload! \
|
ActiveStorage::Blob.create_after_upload! \
|
||||||
io: attachable.open,
|
io: attachable.open,
|
||||||
filename: attachable.original_filename,
|
filename: attachable.original_filename,
|
||||||
content_type: attachable.content_type
|
content_type: attachable.content_type
|
||||||
when Hash
|
when Hash
|
||||||
ActiveVault::Blob.create_after_upload!(attachable)
|
ActiveStorage::Blob.create_after_upload!(attachable)
|
||||||
else
|
else
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
require "active_vault/attached/one"
|
require "active_storage/attached/one"
|
||||||
require "active_vault/attached/many"
|
require "active_storage/attached/many"
|
||||||
require "active_vault/attached/macros"
|
require "active_storage/attached/macros"
|
23
lib/active_storage/attached/macros.rb
Normal file
23
lib/active_storage/attached/macros.rb
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
module ActiveStorage::Attached::Macros
|
||||||
|
def has_one_attached(name, dependent: :purge_later)
|
||||||
|
define_method(name) do
|
||||||
|
instance_variable_get("@active_storage_attached_#{name}") ||
|
||||||
|
instance_variable_set("@active_storage_attached_#{name}", ActiveStorage::Attached::One.new(name, self))
|
||||||
|
end
|
||||||
|
|
||||||
|
if dependent == :purge_later
|
||||||
|
before_destroy { public_send(name).purge_later }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_many_attached(name, dependent: :purge_later)
|
||||||
|
define_method(name) do
|
||||||
|
instance_variable_get("@active_storage_attached_#{name}") ||
|
||||||
|
instance_variable_set("@active_storage_attached_#{name}", ActiveStorage::Attached::Many.new(name, self))
|
||||||
|
end
|
||||||
|
|
||||||
|
if dependent == :purge_later
|
||||||
|
before_destroy { public_send(name).purge_later }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -1,13 +1,13 @@
|
|||||||
class ActiveVault::Attached::Many < ActiveVault::Attached
|
class ActiveStorage::Attached::Many < ActiveStorage::Attached
|
||||||
delegate_missing_to :attachments
|
delegate_missing_to :attachments
|
||||||
|
|
||||||
def attachments
|
def attachments
|
||||||
@attachments ||= ActiveVault::Attachment.where(record_gid: record.to_gid.to_s, name: name)
|
@attachments ||= ActiveStorage::Attachment.where(record_gid: record.to_gid.to_s, name: name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def attach(*attachables)
|
def attach(*attachables)
|
||||||
@attachments = attachments | Array(attachables).flatten.collect do |attachable|
|
@attachments = attachments | Array(attachables).flatten.collect do |attachable|
|
||||||
ActiveVault::Attachment.create!(record_gid: record.to_gid.to_s, name: name, blob: create_blob_from(attachable))
|
ActiveStorage::Attachment.create!(record_gid: record.to_gid.to_s, name: name, blob: create_blob_from(attachable))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -1,12 +1,12 @@
|
|||||||
class ActiveVault::Attached::One < ActiveVault::Attached
|
class ActiveStorage::Attached::One < ActiveStorage::Attached
|
||||||
delegate_missing_to :attachment
|
delegate_missing_to :attachment
|
||||||
|
|
||||||
def attachment
|
def attachment
|
||||||
@attachment ||= ActiveVault::Attachment.find_by(record_gid: record.to_gid.to_s, name: name)
|
@attachment ||= ActiveStorage::Attachment.find_by(record_gid: record.to_gid.to_s, name: name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def attach(attachable)
|
def attach(attachable)
|
||||||
@attachment = ActiveVault::Attachment.create!(record_gid: record.to_gid.to_s, name: name, blob: create_blob_from(attachable))
|
@attachment = ActiveStorage::Attachment.create!(record_gid: record.to_gid.to_s, name: name, blob: create_blob_from(attachable))
|
||||||
end
|
end
|
||||||
|
|
||||||
def attached?
|
def attached?
|
@ -1,12 +1,12 @@
|
|||||||
require "active_vault/blob"
|
require "active_storage/blob"
|
||||||
require "global_id"
|
require "global_id"
|
||||||
require "active_support/core_ext/module/delegation"
|
require "active_support/core_ext/module/delegation"
|
||||||
|
|
||||||
# Schema: id, record_gid, blob_id, created_at
|
# Schema: id, record_gid, blob_id, created_at
|
||||||
class ActiveVault::Attachment < ActiveRecord::Base
|
class ActiveStorage::Attachment < ActiveRecord::Base
|
||||||
self.table_name = "active_vault_attachments"
|
self.table_name = "active_storage_attachments"
|
||||||
|
|
||||||
belongs_to :blob, class_name: "ActiveVault::Blob"
|
belongs_to :blob, class_name: "ActiveStorage::Blob"
|
||||||
|
|
||||||
delegate_missing_to :blob
|
delegate_missing_to :blob
|
||||||
|
|
||||||
@ -25,6 +25,6 @@ def purge
|
|||||||
end
|
end
|
||||||
|
|
||||||
def purge_later
|
def purge_later
|
||||||
ActiveVault::PurgeJob.perform_later(self)
|
ActiveStorage::PurgeJob.perform_later(self)
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -1,10 +1,10 @@
|
|||||||
require "active_vault/site"
|
require "active_storage/site"
|
||||||
require "active_vault/filename"
|
require "active_storage/filename"
|
||||||
require "active_vault/purge_job"
|
require "active_storage/purge_job"
|
||||||
|
|
||||||
# Schema: id, key, filename, content_type, metadata, byte_size, checksum, created_at
|
# Schema: id, key, filename, content_type, metadata, byte_size, checksum, created_at
|
||||||
class ActiveVault::Blob < ActiveRecord::Base
|
class ActiveStorage::Blob < ActiveRecord::Base
|
||||||
self.table_name = "active_vault_blobs"
|
self.table_name = "active_storage_blobs"
|
||||||
|
|
||||||
has_secure_token :key
|
has_secure_token :key
|
||||||
store :metadata, coder: JSON
|
store :metadata, coder: JSON
|
||||||
@ -33,7 +33,7 @@ def key
|
|||||||
end
|
end
|
||||||
|
|
||||||
def filename
|
def filename
|
||||||
ActiveVault::Filename.new(self[:filename])
|
ActiveStorage::Filename.new(self[:filename])
|
||||||
end
|
end
|
||||||
|
|
||||||
def url(expires_in: 5.minutes, disposition: :inline)
|
def url(expires_in: 5.minutes, disposition: :inline)
|
||||||
@ -63,6 +63,6 @@ def purge
|
|||||||
end
|
end
|
||||||
|
|
||||||
def purge_later
|
def purge_later
|
||||||
ActiveVault::PurgeJob.perform_later(self)
|
ActiveStorage::PurgeJob.perform_later(self)
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -1,13 +1,13 @@
|
|||||||
# Configuration should be something like this:
|
# Configuration should be something like this:
|
||||||
#
|
#
|
||||||
# config/environments/development.rb
|
# config/environments/development.rb
|
||||||
# config.active_vault.site = :local
|
# config.active_storage.site = :local
|
||||||
#
|
#
|
||||||
# config/environments/production.rb
|
# config/environments/production.rb
|
||||||
# config.active_vault.site = :amazon
|
# config.active_storage.site = :amazon
|
||||||
local:
|
local:
|
||||||
site: Disk
|
site: Disk
|
||||||
root: <%%= File.join(Dir.tmpdir, "active_vault") %>
|
root: <%%= File.join(Dir.tmpdir, "active_storage") %>
|
||||||
|
|
||||||
amazon:
|
amazon:
|
||||||
site: S3
|
site: S3
|
@ -1,13 +1,13 @@
|
|||||||
require "action_controller"
|
require "action_controller"
|
||||||
require "active_vault/blob"
|
require "active_storage/blob"
|
||||||
require "active_vault/verified_key_with_expiration"
|
require "active_storage/verified_key_with_expiration"
|
||||||
|
|
||||||
require "active_support/core_ext/object/inclusion"
|
require "active_support/core_ext/object/inclusion"
|
||||||
|
|
||||||
class ActiveVault::DiskController < ActionController::Base
|
class ActiveStorage::DiskController < ActionController::Base
|
||||||
def show
|
def show
|
||||||
if key = decode_verified_key
|
if key = decode_verified_key
|
||||||
blob = ActiveVault::Blob.find_by!(key: key)
|
blob = ActiveStorage::Blob.find_by!(key: key)
|
||||||
|
|
||||||
if stale?(etag: blob.checksum)
|
if stale?(etag: blob.checksum)
|
||||||
send_data blob.download, filename: blob.filename, type: blob.content_type, disposition: disposition_param
|
send_data blob.download, filename: blob.filename, type: blob.content_type, disposition: disposition_param
|
||||||
@ -19,7 +19,7 @@ def show
|
|||||||
|
|
||||||
private
|
private
|
||||||
def decode_verified_key
|
def decode_verified_key
|
||||||
ActiveVault::VerifiedKeyWithExpiration.decode(params[:encoded_key])
|
ActiveStorage::VerifiedKeyWithExpiration.decode(params[:encoded_key])
|
||||||
end
|
end
|
||||||
|
|
||||||
def disposition_param
|
def disposition_param
|
@ -1,4 +1,4 @@
|
|||||||
class ActiveVault::Download
|
class ActiveStorage::Download
|
||||||
# Sending .ai files as application/postscript to Safari opens them in a blank, grey screen.
|
# 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.
|
# 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.
|
# Sending HTML, SVG, XML and SWF files as binary closes XSS vulnerabilities.
|
@ -1,4 +1,4 @@
|
|||||||
class ActiveVault::Filename
|
class ActiveStorage::Filename
|
||||||
include Comparable
|
include Comparable
|
||||||
|
|
||||||
def initialize(filename)
|
def initialize(filename)
|
@ -1,6 +1,6 @@
|
|||||||
class ActiveVault::CreateTables < ActiveRecord::Migration[5.1]
|
class ActiveStorage::CreateTables < ActiveRecord::Migration[5.1]
|
||||||
def change
|
def change
|
||||||
create_table :active_vault_blobs do |t|
|
create_table :active_storage_blobs do |t|
|
||||||
t.string :key
|
t.string :key
|
||||||
t.string :filename
|
t.string :filename
|
||||||
t.string :content_type
|
t.string :content_type
|
||||||
@ -12,7 +12,7 @@ def change
|
|||||||
t.index [ :key ], unique: true
|
t.index [ :key ], unique: true
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table :active_vault_attachments do |t|
|
create_table :active_storage_attachments do |t|
|
||||||
t.string :name
|
t.string :name
|
||||||
t.string :record_gid
|
t.string :record_gid
|
||||||
t.integer :blob_id
|
t.integer :blob_id
|
@ -1,7 +1,7 @@
|
|||||||
require "active_job"
|
require "active_job"
|
||||||
|
|
||||||
class ActiveVault::PurgeJob < ActiveJob::Base
|
class ActiveStorage::PurgeJob < ActiveJob::Base
|
||||||
# FIXME: Limit this to a custom ActiveVault error
|
# FIXME: Limit this to a custom ActiveStorage error
|
||||||
retry_on StandardError
|
retry_on StandardError
|
||||||
|
|
||||||
def perform(attachment_or_blob)
|
def perform(attachment_or_blob)
|
27
lib/active_storage/railtie.rb
Normal file
27
lib/active_storage/railtie.rb
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
require "rails/railtie"
|
||||||
|
|
||||||
|
module ActiveStorage
|
||||||
|
class Railtie < Rails::Railtie # :nodoc:
|
||||||
|
config.active_storage = ActiveSupport::OrderedOptions.new
|
||||||
|
|
||||||
|
config.eager_load_namespaces << ActiveStorage
|
||||||
|
|
||||||
|
initializer "active_storage.routes" do
|
||||||
|
require "active_storage/disk_controller"
|
||||||
|
|
||||||
|
config.after_initialize do |app|
|
||||||
|
app.routes.prepend do
|
||||||
|
get "/rails/blobs/:encoded_key" => "active_storage/disk#show", as: :rails_disk_blob
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
initializer "active_storage.attached" do
|
||||||
|
require "active_storage/attached"
|
||||||
|
|
||||||
|
ActiveSupport.on_load(:active_record) do
|
||||||
|
extend ActiveStorage::Attached::Macros
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -1,9 +1,9 @@
|
|||||||
# Abstract class serving as an interface for concrete sites.
|
# Abstract class serving as an interface for concrete sites.
|
||||||
class ActiveVault::Site
|
class ActiveStorage::Site
|
||||||
def self.configure(site, **options)
|
def self.configure(site, **options)
|
||||||
begin
|
begin
|
||||||
require "active_vault/site/#{site.to_s.downcase}_site"
|
require "active_storage/site/#{site.to_s.downcase}_site"
|
||||||
ActiveVault::Site.const_get(:"#{site}Site").new(**options)
|
ActiveStorage::Site.const_get(:"#{site}Site").new(**options)
|
||||||
rescue LoadError => e
|
rescue LoadError => e
|
||||||
puts "Couldn't configure site: #{site} (#{e.message})"
|
puts "Couldn't configure site: #{site} (#{e.message})"
|
||||||
end
|
end
|
@ -1,7 +1,7 @@
|
|||||||
require "fileutils"
|
require "fileutils"
|
||||||
require "pathname"
|
require "pathname"
|
||||||
|
|
||||||
class ActiveVault::Site::DiskSite < ActiveVault::Site
|
class ActiveStorage::Site::DiskSite < ActiveStorage::Site
|
||||||
attr_reader :root
|
attr_reader :root
|
||||||
|
|
||||||
def initialize(root:)
|
def initialize(root:)
|
||||||
@ -38,7 +38,7 @@ def exist?(key)
|
|||||||
|
|
||||||
|
|
||||||
def url(key, expires_in:, disposition:, filename:)
|
def url(key, expires_in:, disposition:, filename:)
|
||||||
verified_key_with_expiration = ActiveVault::VerifiedKeyWithExpiration.encode(key, expires_in: expires_in)
|
verified_key_with_expiration = ActiveStorage::VerifiedKeyWithExpiration.encode(key, expires_in: expires_in)
|
||||||
|
|
||||||
if defined?(Rails) && defined?(Rails.application)
|
if defined?(Rails) && defined?(Rails.application)
|
||||||
Rails.application.routes.url_helpers.rails_disk_blob_path(verified_key_with_expiration, disposition: disposition)
|
Rails.application.routes.url_helpers.rails_disk_blob_path(verified_key_with_expiration, disposition: disposition)
|
@ -1,7 +1,7 @@
|
|||||||
require "google/cloud/storage"
|
require "google/cloud/storage"
|
||||||
require "active_support/core_ext/object/to_query"
|
require "active_support/core_ext/object/to_query"
|
||||||
|
|
||||||
class ActiveVault::Site::GCSSite < ActiveVault::Site
|
class ActiveStorage::Site::GCSSite < ActiveStorage::Site
|
||||||
attr_reader :client, :bucket
|
attr_reader :client, :bucket
|
||||||
|
|
||||||
def initialize(project:, keyfile:, bucket:)
|
def initialize(project:, keyfile:, bucket:)
|
@ -1,4 +1,4 @@
|
|||||||
class ActiveVault::Site::MirrorSite < ActiveVault::Site
|
class ActiveStorage::Site::MirrorSite < ActiveStorage::Site
|
||||||
attr_reader :sites
|
attr_reader :sites
|
||||||
|
|
||||||
def initialize(sites:)
|
def initialize(sites:)
|
@ -1,6 +1,6 @@
|
|||||||
require "aws-sdk"
|
require "aws-sdk"
|
||||||
|
|
||||||
class ActiveVault::Site::S3Site < ActiveVault::Site
|
class ActiveStorage::Site::S3Site < ActiveStorage::Site
|
||||||
attr_reader :client, :bucket
|
attr_reader :client, :bucket
|
||||||
|
|
||||||
def initialize(access_key_id:, secret_access_key:, region:, bucket:)
|
def initialize(access_key_id:, secret_access_key:, region:, bucket:)
|
@ -1,5 +1,5 @@
|
|||||||
class ActiveVault::VerifiedKeyWithExpiration
|
class ActiveStorage::VerifiedKeyWithExpiration
|
||||||
class_attribute :verifier, default: defined?(Rails) ? Rails.application.message_verifier('ActiveVault') : nil
|
class_attribute :verifier, default: defined?(Rails) ? Rails.application.message_verifier('ActiveStorage') : nil
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def encode(key, expires_in: nil)
|
def encode(key, expires_in: nil)
|
@ -1,23 +0,0 @@
|
|||||||
module ActiveVault::Attached::Macros
|
|
||||||
def has_one_attached(name, dependent: :purge_later)
|
|
||||||
define_method(name) do
|
|
||||||
instance_variable_get("@active_vault_attached_#{name}") ||
|
|
||||||
instance_variable_set("@active_vault_attached_#{name}", ActiveVault::Attached::One.new(name, self))
|
|
||||||
end
|
|
||||||
|
|
||||||
if dependent == :purge_later
|
|
||||||
before_destroy { public_send(name).purge_later }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def has_many_attached(name, dependent: :purge_later)
|
|
||||||
define_method(name) do
|
|
||||||
instance_variable_get("@active_vault_attached_#{name}") ||
|
|
||||||
instance_variable_set("@active_vault_attached_#{name}", ActiveVault::Attached::Many.new(name, self))
|
|
||||||
end
|
|
||||||
|
|
||||||
if dependent == :purge_later
|
|
||||||
before_destroy { public_send(name).purge_later }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,27 +0,0 @@
|
|||||||
require "rails/railtie"
|
|
||||||
|
|
||||||
module ActiveVault
|
|
||||||
class Railtie < Rails::Railtie # :nodoc:
|
|
||||||
config.active_vault = ActiveSupport::OrderedOptions.new
|
|
||||||
|
|
||||||
config.eager_load_namespaces << ActiveVault
|
|
||||||
|
|
||||||
initializer "active_vault.routes" do
|
|
||||||
require "active_vault/disk_controller"
|
|
||||||
|
|
||||||
config.after_initialize do |app|
|
|
||||||
app.routes.prepend do
|
|
||||||
get "/rails/blobs/:encoded_key" => "active_vault/disk#show", as: :rails_disk_blob
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
initializer "active_vault.attached" do
|
|
||||||
require "active_vault/attached"
|
|
||||||
|
|
||||||
ActiveSupport.on_load(:active_record) do
|
|
||||||
extend ActiveVault::Attached::Macros
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,6 +1,6 @@
|
|||||||
require "test_helper"
|
require "test_helper"
|
||||||
require "database/setup"
|
require "database/setup"
|
||||||
require "active_vault/blob"
|
require "active_storage/blob"
|
||||||
|
|
||||||
require "active_job"
|
require "active_job"
|
||||||
ActiveJob::Base.queue_adapter = :test
|
ActiveJob::Base.queue_adapter = :test
|
||||||
@ -13,12 +13,12 @@ class User < ActiveRecord::Base
|
|||||||
has_many_attached :highlights
|
has_many_attached :highlights
|
||||||
end
|
end
|
||||||
|
|
||||||
class ActiveVault::AttachmentsTest < ActiveSupport::TestCase
|
class ActiveStorage::AttachmentsTest < ActiveSupport::TestCase
|
||||||
include ActiveJob::TestHelper
|
include ActiveJob::TestHelper
|
||||||
|
|
||||||
setup { @user = User.create!(name: "DHH") }
|
setup { @user = User.create!(name: "DHH") }
|
||||||
|
|
||||||
teardown { ActiveVault::Blob.all.each(&:purge) }
|
teardown { ActiveStorage::Blob.all.each(&:purge) }
|
||||||
|
|
||||||
test "attach existing blob" do
|
test "attach existing blob" do
|
||||||
@user.avatar.attach create_blob(filename: "funky.jpg")
|
@user.avatar.attach create_blob(filename: "funky.jpg")
|
||||||
@ -36,7 +36,7 @@ class ActiveVault::AttachmentsTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
@user.avatar.purge
|
@user.avatar.purge
|
||||||
assert_not @user.avatar.attached?
|
assert_not @user.avatar.attached?
|
||||||
assert_not ActiveVault::Blob.site.exist?(avatar_key)
|
assert_not ActiveStorage::Blob.site.exist?(avatar_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "purge attached blob later when the record is destroyed" do
|
test "purge attached blob later when the record is destroyed" do
|
||||||
@ -46,8 +46,8 @@ class ActiveVault::AttachmentsTest < ActiveSupport::TestCase
|
|||||||
perform_enqueued_jobs do
|
perform_enqueued_jobs do
|
||||||
@user.destroy
|
@user.destroy
|
||||||
|
|
||||||
assert_nil ActiveVault::Blob.find_by(key: avatar_key)
|
assert_nil ActiveStorage::Blob.find_by(key: avatar_key)
|
||||||
assert_not ActiveVault::Blob.site.exist?(avatar_key)
|
assert_not ActiveStorage::Blob.site.exist?(avatar_key)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -74,8 +74,8 @@ class ActiveVault::AttachmentsTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
@user.highlights.purge
|
@user.highlights.purge
|
||||||
assert_not @user.highlights.attached?
|
assert_not @user.highlights.attached?
|
||||||
assert_not ActiveVault::Blob.site.exist?(highlight_keys.first)
|
assert_not ActiveStorage::Blob.site.exist?(highlight_keys.first)
|
||||||
assert_not ActiveVault::Blob.site.exist?(highlight_keys.second)
|
assert_not ActiveStorage::Blob.site.exist?(highlight_keys.second)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "purge attached blobs later when the record is destroyed" do
|
test "purge attached blobs later when the record is destroyed" do
|
||||||
@ -85,11 +85,11 @@ class ActiveVault::AttachmentsTest < ActiveSupport::TestCase
|
|||||||
perform_enqueued_jobs do
|
perform_enqueued_jobs do
|
||||||
@user.destroy
|
@user.destroy
|
||||||
|
|
||||||
assert_nil ActiveVault::Blob.find_by(key: highlight_keys.first)
|
assert_nil ActiveStorage::Blob.find_by(key: highlight_keys.first)
|
||||||
assert_not ActiveVault::Blob.site.exist?(highlight_keys.first)
|
assert_not ActiveStorage::Blob.site.exist?(highlight_keys.first)
|
||||||
|
|
||||||
assert_nil ActiveVault::Blob.find_by(key: highlight_keys.second)
|
assert_nil ActiveStorage::Blob.find_by(key: highlight_keys.second)
|
||||||
assert_not ActiveVault::Blob.site.exist?(highlight_keys.second)
|
assert_not ActiveStorage::Blob.site.exist?(highlight_keys.second)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
require "test_helper"
|
require "test_helper"
|
||||||
require "database/setup"
|
require "database/setup"
|
||||||
require "active_vault/blob"
|
require "active_storage/blob"
|
||||||
|
|
||||||
class ActiveVault::BlobTest < ActiveSupport::TestCase
|
class ActiveStorage::BlobTest < ActiveSupport::TestCase
|
||||||
test "create after upload sets byte size and checksum" do
|
test "create after upload sets byte size and checksum" do
|
||||||
data = "Hello world!"
|
data = "Hello world!"
|
||||||
blob = create_blob data: data
|
blob = create_blob data: data
|
||||||
@ -23,6 +23,6 @@ class ActiveVault::BlobTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
private
|
private
|
||||||
def expected_url_for(blob, disposition: :inline)
|
def expected_url_for(blob, disposition: :inline)
|
||||||
"/rails/blobs/#{ActiveVault::VerifiedKeyWithExpiration.encode(blob.key, expires_in: 5.minutes)}?disposition=#{disposition}"
|
"/rails/blobs/#{ActiveStorage::VerifiedKeyWithExpiration.encode(blob.key, expires_in: 5.minutes)}?disposition=#{disposition}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
class ActiveVault::CreateUsers < ActiveRecord::Migration[5.1]
|
class ActiveStorage::CreateUsers < ActiveRecord::Migration[5.1]
|
||||||
def change
|
def change
|
||||||
create_table :users do |t|
|
create_table :users do |t|
|
||||||
t.string :name
|
t.string :name
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
require "active_vault/migration"
|
require "active_storage/migration"
|
||||||
require_relative "create_users_migration"
|
require_relative "create_users_migration"
|
||||||
|
|
||||||
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
|
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
|
||||||
ActiveVault::CreateTables.migrate(:up)
|
ActiveStorage::CreateTables.migrate(:up)
|
||||||
ActiveVault::CreateUsers.migrate(:up)
|
ActiveStorage::CreateUsers.migrate(:up)
|
||||||
|
@ -4,30 +4,30 @@
|
|||||||
require "action_controller"
|
require "action_controller"
|
||||||
require "action_controller/test_case"
|
require "action_controller/test_case"
|
||||||
|
|
||||||
require "active_vault/disk_controller"
|
require "active_storage/disk_controller"
|
||||||
require "active_vault/verified_key_with_expiration"
|
require "active_storage/verified_key_with_expiration"
|
||||||
|
|
||||||
class ActiveVault::DiskControllerTest < ActionController::TestCase
|
class ActiveStorage::DiskControllerTest < ActionController::TestCase
|
||||||
Routes = ActionDispatch::Routing::RouteSet.new.tap do |routes|
|
Routes = ActionDispatch::Routing::RouteSet.new.tap do |routes|
|
||||||
routes.draw do
|
routes.draw do
|
||||||
get "/rails/blobs/:encoded_key" => "active_vault/disk#show", as: :rails_disk_blob
|
get "/rails/blobs/:encoded_key" => "active_storage/disk#show", as: :rails_disk_blob
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
setup do
|
setup do
|
||||||
@blob = create_blob
|
@blob = create_blob
|
||||||
@routes = Routes
|
@routes = Routes
|
||||||
@controller = ActiveVault::DiskController.new
|
@controller = ActiveStorage::DiskController.new
|
||||||
end
|
end
|
||||||
|
|
||||||
test "showing blob inline" do
|
test "showing blob inline" do
|
||||||
get :show, params: { encoded_key: ActiveVault::VerifiedKeyWithExpiration.encode(@blob.key, expires_in: 5.minutes) }
|
get :show, params: { encoded_key: ActiveStorage::VerifiedKeyWithExpiration.encode(@blob.key, expires_in: 5.minutes) }
|
||||||
assert_equal "inline; filename=\"#{@blob.filename}\"", @response.headers["Content-Disposition"]
|
assert_equal "inline; filename=\"#{@blob.filename}\"", @response.headers["Content-Disposition"]
|
||||||
assert_equal "text/plain", @response.headers["Content-Type"]
|
assert_equal "text/plain", @response.headers["Content-Type"]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "sending blob as attachment" do
|
test "sending blob as attachment" do
|
||||||
get :show, params: { encoded_key: ActiveVault::VerifiedKeyWithExpiration.encode(@blob.key, expires_in: 5.minutes), disposition: :attachment }
|
get :show, params: { encoded_key: ActiveStorage::VerifiedKeyWithExpiration.encode(@blob.key, expires_in: 5.minutes), disposition: :attachment }
|
||||||
assert_equal "attachment; filename=\"#{@blob.filename}\"", @response.headers["Content-Disposition"]
|
assert_equal "attachment; filename=\"#{@blob.filename}\"", @response.headers["Content-Disposition"]
|
||||||
assert_equal "text/plain", @response.headers["Content-Type"]
|
assert_equal "text/plain", @response.headers["Content-Type"]
|
||||||
end
|
end
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
require "test_helper"
|
require "test_helper"
|
||||||
|
|
||||||
class ActiveVault::FilenameTest < ActiveSupport::TestCase
|
class ActiveStorage::FilenameTest < ActiveSupport::TestCase
|
||||||
test "sanitize" do
|
test "sanitize" do
|
||||||
"%$|:;/\t\r\n\\".each_char do |character|
|
"%$|:;/\t\r\n\\".each_char do |character|
|
||||||
filename = ActiveVault::Filename.new("foo#{character}bar.pdf")
|
filename = ActiveStorage::Filename.new("foo#{character}bar.pdf")
|
||||||
assert_equal 'foo-bar.pdf', filename.sanitized
|
assert_equal 'foo-bar.pdf', filename.sanitized
|
||||||
assert_equal 'foo-bar.pdf', filename.to_s
|
assert_equal 'foo-bar.pdf', filename.to_s
|
||||||
end
|
end
|
||||||
@ -16,21 +16,21 @@ class ActiveVault::FilenameTest < ActiveSupport::TestCase
|
|||||||
"\xCF" => "<EFBFBD>",
|
"\xCF" => "<EFBFBD>",
|
||||||
"\x00" => "",
|
"\x00" => "",
|
||||||
}.each do |actual, expected|
|
}.each do |actual, expected|
|
||||||
assert_equal expected, ActiveVault::Filename.new(actual).sanitized
|
assert_equal expected, ActiveStorage::Filename.new(actual).sanitized
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "strips RTL override chars used to spoof unsafe executables as docs" do
|
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
|
# Would be displayed in Windows as "evilexe.pdf" due to the right-to-left
|
||||||
# (RTL) override char!
|
# (RTL) override char!
|
||||||
assert_equal 'evil-fdp.exe', ActiveVault::Filename.new("evil\u{202E}fdp.exe").sanitized
|
assert_equal 'evil-fdp.exe', ActiveStorage::Filename.new("evil\u{202E}fdp.exe").sanitized
|
||||||
end
|
end
|
||||||
|
|
||||||
test "compare case-insensitively" do
|
test "compare case-insensitively" do
|
||||||
assert_operator ActiveVault::Filename.new('foobar.pdf'), :==, ActiveVault::Filename.new('FooBar.PDF')
|
assert_operator ActiveStorage::Filename.new('foobar.pdf'), :==, ActiveStorage::Filename.new('FooBar.PDF')
|
||||||
end
|
end
|
||||||
|
|
||||||
test "compare sanitized" do
|
test "compare sanitized" do
|
||||||
assert_operator ActiveVault::Filename.new('foo-bar.pdf'), :==, ActiveVault::Filename.new("foo\tbar.pdf")
|
assert_operator ActiveStorage::Filename.new('foo-bar.pdf'), :==, ActiveStorage::Filename.new("foo\tbar.pdf")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
require "tmpdir"
|
require "tmpdir"
|
||||||
require "site/shared_site_tests"
|
require "site/shared_site_tests"
|
||||||
|
|
||||||
class ActiveVault::Site::DiskSiteTest < ActiveSupport::TestCase
|
class ActiveStorage::Site::DiskSiteTest < ActiveSupport::TestCase
|
||||||
SITE = ActiveVault::Site.configure(:Disk, root: File.join(Dir.tmpdir, "active_vault"))
|
SITE = ActiveStorage::Site.configure(:Disk, root: File.join(Dir.tmpdir, "active_storage"))
|
||||||
|
|
||||||
include ActiveVault::Site::SharedSiteTests
|
include ActiveStorage::Site::SharedSiteTests
|
||||||
end
|
end
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
require "site/shared_site_tests"
|
require "site/shared_site_tests"
|
||||||
|
|
||||||
if SITE_CONFIGURATIONS[:gcs]
|
if SITE_CONFIGURATIONS[:gcs]
|
||||||
class ActiveVault::Site::GCSSiteTest < ActiveSupport::TestCase
|
class ActiveStorage::Site::GCSSiteTest < ActiveSupport::TestCase
|
||||||
SITE = ActiveVault::Site.configure(:GCS, SITE_CONFIGURATIONS[:gcs])
|
SITE = ActiveStorage::Site.configure(:GCS, SITE_CONFIGURATIONS[:gcs])
|
||||||
|
|
||||||
include ActiveVault::Site::SharedSiteTests
|
include ActiveStorage::Site::SharedSiteTests
|
||||||
|
|
||||||
test "signed URL generation" do
|
test "signed URL generation" do
|
||||||
travel_to Time.now do
|
travel_to Time.now do
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
require "tmpdir"
|
require "tmpdir"
|
||||||
require "site/shared_site_tests"
|
require "site/shared_site_tests"
|
||||||
|
|
||||||
class ActiveVault::Site::MirrorSiteTest < ActiveSupport::TestCase
|
class ActiveStorage::Site::MirrorSiteTest < ActiveSupport::TestCase
|
||||||
PRIMARY_DISK_SITE = ActiveVault::Site.configure(:Disk, root: File.join(Dir.tmpdir, "active_vault"))
|
PRIMARY_DISK_SITE = ActiveStorage::Site.configure(:Disk, root: File.join(Dir.tmpdir, "active_storage"))
|
||||||
SECONDARY_DISK_SITE = ActiveVault::Site.configure(:Disk, root: File.join(Dir.tmpdir, "active_vault_mirror"))
|
SECONDARY_DISK_SITE = ActiveStorage::Site.configure(:Disk, root: File.join(Dir.tmpdir, "active_storage_mirror"))
|
||||||
|
|
||||||
SITE = ActiveVault::Site.configure :Mirror, sites: [ PRIMARY_DISK_SITE, SECONDARY_DISK_SITE ]
|
SITE = ActiveStorage::Site.configure :Mirror, sites: [ PRIMARY_DISK_SITE, SECONDARY_DISK_SITE ]
|
||||||
|
|
||||||
include ActiveVault::Site::SharedSiteTests
|
include ActiveStorage::Site::SharedSiteTests
|
||||||
|
|
||||||
test "uploading to all sites" do
|
test "uploading was done to all sites" do
|
||||||
begin
|
begin
|
||||||
key = SecureRandom.base58(24)
|
key = SecureRandom.base58(24)
|
||||||
data = "Something else entirely!"
|
data = "Something else entirely!"
|
||||||
@ -27,11 +27,4 @@ class ActiveVault::Site::MirrorSiteTest < ActiveSupport::TestCase
|
|||||||
assert PRIMARY_DISK_SITE.exist?(FIXTURE_KEY)
|
assert PRIMARY_DISK_SITE.exist?(FIXTURE_KEY)
|
||||||
assert SECONDARY_DISK_SITE.exist?(FIXTURE_KEY)
|
assert SECONDARY_DISK_SITE.exist?(FIXTURE_KEY)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "URL generation for primary site" do
|
|
||||||
travel_to Time.now do
|
|
||||||
assert_equal PRIMARY_DISK_SITE.url(FIXTURE_KEY, expires_in: 5.minutes, disposition: :inline, filename: "test.txt"),
|
|
||||||
SITE.url(FIXTURE_KEY, expires_in: 5.minutes, disposition: :inline, filename: "test.txt")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
require "site/shared_site_tests"
|
require "site/shared_site_tests"
|
||||||
|
|
||||||
if SITE_CONFIGURATIONS[:s3]
|
if SITE_CONFIGURATIONS[:s3]
|
||||||
class ActiveVault::Site::S3SiteTest < ActiveSupport::TestCase
|
class ActiveStorage::Site::S3SiteTest < ActiveSupport::TestCase
|
||||||
SITE = ActiveVault::Site.configure(:S3, SITE_CONFIGURATIONS[:s3])
|
SITE = ActiveStorage::Site.configure(:S3, SITE_CONFIGURATIONS[:s3])
|
||||||
|
|
||||||
include ActiveVault::Site::SharedSiteTests
|
include ActiveStorage::Site::SharedSiteTests
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
puts "Skipping S3 Site tests because no S3 configuration was supplied"
|
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"
|
puts "Missing site configuration file in test/sites/configurations.yml"
|
||||||
end
|
end
|
||||||
|
|
||||||
module ActiveVault::Site::SharedSiteTests
|
module ActiveStorage::Site::SharedSiteTests
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
FIXTURE_KEY = SecureRandom.base58(24)
|
FIXTURE_KEY = SecureRandom.base58(24)
|
||||||
|
@ -4,25 +4,25 @@
|
|||||||
require "active_support/testing/autorun"
|
require "active_support/testing/autorun"
|
||||||
require "byebug"
|
require "byebug"
|
||||||
|
|
||||||
require "active_vault"
|
require "active_storage"
|
||||||
|
|
||||||
require "active_vault/site"
|
require "active_storage/site"
|
||||||
ActiveVault::Blob.site = ActiveVault::Site.configure(:Disk, root: File.join(Dir.tmpdir, "active_vault"))
|
ActiveStorage::Blob.site = ActiveStorage::Site.configure(:Disk, root: File.join(Dir.tmpdir, "active_storage"))
|
||||||
|
|
||||||
require "active_vault/verified_key_with_expiration"
|
require "active_storage/verified_key_with_expiration"
|
||||||
ActiveVault::VerifiedKeyWithExpiration.verifier = ActiveSupport::MessageVerifier.new("Testing")
|
ActiveStorage::VerifiedKeyWithExpiration.verifier = ActiveSupport::MessageVerifier.new("Testing")
|
||||||
|
|
||||||
class ActiveSupport::TestCase
|
class ActiveSupport::TestCase
|
||||||
private
|
private
|
||||||
def create_blob(data: "Hello world!", filename: "hello.txt", content_type: "text/plain")
|
def create_blob(data: "Hello world!", filename: "hello.txt", content_type: "text/plain")
|
||||||
ActiveVault::Blob.create_after_upload! io: StringIO.new(data), filename: filename, content_type: content_type
|
ActiveStorage::Blob.create_after_upload! io: StringIO.new(data), filename: filename, content_type: content_type
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
require "active_vault/attached"
|
require "active_storage/attached"
|
||||||
ActiveRecord::Base.send :extend, ActiveVault::Attached::Macros
|
ActiveRecord::Base.send :extend, ActiveStorage::Attached::Macros
|
||||||
|
|
||||||
require "global_id"
|
require "global_id"
|
||||||
GlobalID.app = "ActiveVaultExampleApp"
|
GlobalID.app = "ActiveStorageExampleApp"
|
||||||
ActiveRecord::Base.send :include, GlobalID::Identification
|
ActiveRecord::Base.send :include, GlobalID::Identification
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
require "test_helper"
|
require "test_helper"
|
||||||
require "active_support/core_ext/securerandom"
|
require "active_support/core_ext/securerandom"
|
||||||
|
|
||||||
class ActiveVault::VerifiedKeyWithExpirationTest < ActiveSupport::TestCase
|
class ActiveStorage::VerifiedKeyWithExpirationTest < ActiveSupport::TestCase
|
||||||
FIXTURE_KEY = SecureRandom.base58(24)
|
FIXTURE_KEY = SecureRandom.base58(24)
|
||||||
|
|
||||||
test "without expiration" do
|
test "without expiration" do
|
||||||
encoded_key = ActiveVault::VerifiedKeyWithExpiration.encode(FIXTURE_KEY)
|
encoded_key = ActiveStorage::VerifiedKeyWithExpiration.encode(FIXTURE_KEY)
|
||||||
assert_equal FIXTURE_KEY, ActiveVault::VerifiedKeyWithExpiration.decode(encoded_key)
|
assert_equal FIXTURE_KEY, ActiveStorage::VerifiedKeyWithExpiration.decode(encoded_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "with expiration" do
|
test "with expiration" do
|
||||||
encoded_key = ActiveVault::VerifiedKeyWithExpiration.encode(FIXTURE_KEY, expires_in: 1.minute)
|
encoded_key = ActiveStorage::VerifiedKeyWithExpiration.encode(FIXTURE_KEY, expires_in: 1.minute)
|
||||||
assert_equal FIXTURE_KEY, ActiveVault::VerifiedKeyWithExpiration.decode(encoded_key)
|
assert_equal FIXTURE_KEY, ActiveStorage::VerifiedKeyWithExpiration.decode(encoded_key)
|
||||||
|
|
||||||
travel 2.minutes
|
travel 2.minutes
|
||||||
assert_nil ActiveVault::VerifiedKeyWithExpiration.decode(encoded_key)
|
assert_nil ActiveStorage::VerifiedKeyWithExpiration.decode(encoded_key)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user