cloud_tempfile 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.rvmrc +2 -0
- data/.travis.yml +30 -0
- data/Appraisals +11 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile +15 -0
- data/LICENSE +20 -0
- data/README.md +232 -0
- data/Rakefile +43 -0
- data/cloud_tempfile.gemspec +38 -0
- data/gemfiles/rails_3.1.gemfile +10 -0
- data/gemfiles/rails_3.2.gemfile +10 -0
- data/gemfiles/rails_4.0.gemfile +10 -0
- data/lib/cloud_tempfile/cloud_tempfile.rb +106 -0
- data/lib/cloud_tempfile/config.rb +206 -0
- data/lib/cloud_tempfile/engine.rb +53 -0
- data/lib/cloud_tempfile/multi_mime.rb +22 -0
- data/lib/cloud_tempfile/railtie.rb +11 -0
- data/lib/cloud_tempfile/storage.rb +151 -0
- data/lib/cloud_tempfile/version.rb +9 -0
- data/lib/cloud_tempfile.rb +11 -0
- data/lib/ext/fog/aws/models/storage/file.rb +19 -0
- data/lib/generators/cloud_tempfile/install_generator.rb +71 -0
- data/lib/generators/cloud_tempfile/templates/cloud_tempfile.rb +41 -0
- data/lib/generators/cloud_tempfile/templates/cloud_tempfile.yml +52 -0
- data/lib/tasks/cloud_tempfile_tasks.rake +7 -0
- data/spec/dummy_app/Rakefile +27 -0
- data/spec/fixtures/assets/TEST.doc +0 -0
- data/spec/fixtures/assets/TEST.docx +0 -0
- data/spec/fixtures/assets/TEST.pdf +0 -0
- data/spec/fixtures/assets/TEST.rtf +1 -0
- data/spec/fixtures/aws_with_yml/config/cloud_tempfile.yml +22 -0
- data/spec/fixtures/google_with_yml/config/.gitkeep +0 -0
- data/spec/fixtures/rackspace_with_yml/config/.gitkeep +0 -0
- data/spec/fixtures/with_invalid_yml/config/cloud_tempfile.yml +22 -0
- data/spec/fixtures/without_yml/public/.gitkeep +0 -0
- data/spec/integration/.gitkeep +0 -0
- data/spec/spec_helper.rb +63 -0
- data/spec/unit/cloud_tempfile_spec.rb +208 -0
- data/spec/unit/multi_mime_spec.rb +48 -0
- data/spec/unit/railsless_spec.rb +50 -0
- data/spec/unit/storage_spec.rb +260 -0
- metadata +189 -0
@@ -0,0 +1,206 @@
|
|
1
|
+
# cloud_tempfile/config.rb
|
2
|
+
#
|
3
|
+
# Author:: Kevin Bolduc
|
4
|
+
# Date:: 14-02-24
|
5
|
+
# Time:: 3:23 PM
|
6
|
+
|
7
|
+
module CloudTempfile
|
8
|
+
class Config
|
9
|
+
include ActiveModel::Validations
|
10
|
+
|
11
|
+
# CloudTempfile
|
12
|
+
attr_accessor :enabled
|
13
|
+
|
14
|
+
attr_accessor :prefix
|
15
|
+
attr_accessor :public
|
16
|
+
attr_accessor :public_path
|
17
|
+
attr_accessor :expiry
|
18
|
+
attr_accessor :clean_up
|
19
|
+
attr_accessor :clean_up_older_than
|
20
|
+
|
21
|
+
# FOG configuration
|
22
|
+
attr_accessor :fog_host #
|
23
|
+
attr_accessor :fog_provider # Currently Supported ['AWS', 'Google', 'Rackspace', 'Local']
|
24
|
+
attr_accessor :fog_directory # e.g. 'the-bucket-name'
|
25
|
+
attr_accessor :fog_region # e.g. 'eu-west-1' or 'us-east-1' etc...
|
26
|
+
attr_accessor :fog_endpoint # e.g. '/'
|
27
|
+
|
28
|
+
# Amazon AWS
|
29
|
+
attr_accessor :aws_access_key_id, :aws_secret_access_key, :aws_reduced_redundancy, :aws_access_control_list
|
30
|
+
|
31
|
+
# Rackspace
|
32
|
+
attr_accessor :rackspace_username, :rackspace_api_key, :rackspace_auth_url
|
33
|
+
|
34
|
+
# Google Storage
|
35
|
+
attr_accessor :google_storage_secret_access_key, :google_storage_access_key_id
|
36
|
+
|
37
|
+
# Logging Options
|
38
|
+
attr_accessor :fail_silently
|
39
|
+
attr_accessor :log_silently
|
40
|
+
|
41
|
+
# Validation #######################################################################################################
|
42
|
+
validates :public, :presence => true
|
43
|
+
validates :fog_provider, :presence => true
|
44
|
+
validates :fog_directory, :presence => true
|
45
|
+
|
46
|
+
validates :aws_access_key_id, :presence => true, :if => :aws?
|
47
|
+
validates :aws_secret_access_key, :presence => true, :if => :aws?
|
48
|
+
validates :rackspace_username, :presence => true, :if => :rackspace?
|
49
|
+
validates :rackspace_api_key, :presence => true, :if => :rackspace?
|
50
|
+
validates :google_storage_secret_access_key, :presence => true, :if => :google?
|
51
|
+
validates :google_storage_access_key_id, :presence => true, :if => :google?
|
52
|
+
|
53
|
+
####################################################################################################################
|
54
|
+
def initialize
|
55
|
+
self.fog_region = nil
|
56
|
+
self.fog_endpoint = '/'
|
57
|
+
|
58
|
+
self.public = false
|
59
|
+
self.prefix = "tmp/"
|
60
|
+
|
61
|
+
self.fail_silently = false
|
62
|
+
self.log_silently = true
|
63
|
+
|
64
|
+
self.clean_up = false
|
65
|
+
self.clean_up_older_than = 600
|
66
|
+
|
67
|
+
load_yml! if defined?(Rails) && yml_exists?
|
68
|
+
end
|
69
|
+
|
70
|
+
def enabled?
|
71
|
+
enabled == true
|
72
|
+
end
|
73
|
+
|
74
|
+
def public?
|
75
|
+
public == true
|
76
|
+
end
|
77
|
+
|
78
|
+
def public_path
|
79
|
+
@public_path || Rails.public_path
|
80
|
+
end
|
81
|
+
|
82
|
+
def expiry?
|
83
|
+
!expiry.nil? && expiry.kind_of?(Fixnum)
|
84
|
+
end
|
85
|
+
|
86
|
+
def aws?
|
87
|
+
fog_provider == 'AWS'
|
88
|
+
end
|
89
|
+
|
90
|
+
def aws_rrs?
|
91
|
+
aws_reduced_redundancy == true
|
92
|
+
end
|
93
|
+
|
94
|
+
# Set file's access control list (ACL).
|
95
|
+
# Valid acls: private, public-read, public-read-write, authenticated-read, bucket-owner-read, bucket-owner-full-control
|
96
|
+
def aws_acl?
|
97
|
+
['private', 'public-read', 'public-read-write', 'authenticated-read', 'bucket-owner-read', 'bucket-owner-full-control'].include?(aws_access_control_list)
|
98
|
+
end
|
99
|
+
|
100
|
+
def rackspace?
|
101
|
+
fog_provider == 'Rackspace'
|
102
|
+
end
|
103
|
+
|
104
|
+
def google?
|
105
|
+
fog_provider == 'Google'
|
106
|
+
end
|
107
|
+
|
108
|
+
def local?
|
109
|
+
fog_provider == 'Local'
|
110
|
+
end
|
111
|
+
|
112
|
+
def clean_up?
|
113
|
+
clean_up == true
|
114
|
+
end
|
115
|
+
|
116
|
+
def fog_options
|
117
|
+
#If the CloudTempfile is disabled then revert to local file creation
|
118
|
+
@fog_provider = 'Local' if (!enabled? && !fog_provider.nil?)
|
119
|
+
|
120
|
+
options = { :provider => fog_provider }
|
121
|
+
if aws?
|
122
|
+
options.merge!({
|
123
|
+
:aws_access_key_id => aws_access_key_id,
|
124
|
+
:aws_secret_access_key => aws_secret_access_key
|
125
|
+
})
|
126
|
+
options.merge!({:host => fog_host}) if !fog_host.blank?
|
127
|
+
elsif rackspace?
|
128
|
+
options.merge!({
|
129
|
+
:rackspace_username => rackspace_username,
|
130
|
+
:rackspace_api_key => rackspace_api_key
|
131
|
+
})
|
132
|
+
options.merge!({
|
133
|
+
:rackspace_region => fog_region
|
134
|
+
}) if fog_region
|
135
|
+
options.merge!({ :rackspace_auth_url => rackspace_auth_url }) if rackspace_auth_url
|
136
|
+
elsif google?
|
137
|
+
options.merge!({
|
138
|
+
:google_storage_secret_access_key => google_storage_secret_access_key,
|
139
|
+
:google_storage_access_key_id => google_storage_access_key_id
|
140
|
+
})
|
141
|
+
elsif local?
|
142
|
+
options.merge!({
|
143
|
+
:local_root => public_path,
|
144
|
+
:endpoint => fog_endpoint
|
145
|
+
})
|
146
|
+
else
|
147
|
+
raise ArgumentError, "CloudTempfile Unknown provider: #{fog_provider} only AWS, Rackspace and Google are supported currently."
|
148
|
+
end
|
149
|
+
|
150
|
+
options.merge!({:region => fog_region}) if fog_region && !rackspace?
|
151
|
+
return options
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
def yml_exists?
|
156
|
+
defined?(Rails.root) ? File.exists?(self.yml_path) : false
|
157
|
+
end
|
158
|
+
|
159
|
+
def yml
|
160
|
+
begin
|
161
|
+
@yml ||= YAML.load(ERB.new(IO.read(yml_path)).result)[Rails.env] rescue nil || {}
|
162
|
+
rescue Psych::SyntaxError
|
163
|
+
@yml = {}
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def yml_path
|
168
|
+
Rails.root.join("config", "cloud_tempfile.yml").to_s
|
169
|
+
end
|
170
|
+
|
171
|
+
def load_yml!
|
172
|
+
self.enabled = yml["enabled"] if yml.has_key?('enabled')
|
173
|
+
|
174
|
+
self.fog_provider = yml["fog_provider"]
|
175
|
+
self.fog_directory = yml["fog_directory"]
|
176
|
+
self.fog_region = yml["fog_region"]
|
177
|
+
self.fog_host = yml["fog_host"] if yml.has_key?("fog_host")
|
178
|
+
self.aws_access_key_id = yml["aws_access_key_id"]
|
179
|
+
self.aws_secret_access_key = yml["aws_secret_access_key"]
|
180
|
+
self.aws_reduced_redundancy = yml["aws_reduced_redundancy"]
|
181
|
+
self.rackspace_username = yml["rackspace_username"]
|
182
|
+
self.rackspace_auth_url = yml["rackspace_auth_url"] if yml.has_key?("rackspace_auth_url")
|
183
|
+
self.rackspace_api_key = yml["rackspace_api_key"]
|
184
|
+
self.google_storage_secret_access_key = yml["google_storage_secret_access_key"]
|
185
|
+
self.google_storage_access_key_id = yml["google_storage_access_key_id"]
|
186
|
+
|
187
|
+
self.clean_up = yml["clean_up"] if yml.has_key?("clean_up")
|
188
|
+
self.clean_up_older_than = yml["clean_up_older_than"] if yml.has_key?("clean_up_older_than")
|
189
|
+
self.fail_silently = yml["fail_silently"] if yml.has_key?("fail_silently")
|
190
|
+
self.prefix = yml["prefix"] if yml.has_key?("prefix")
|
191
|
+
self.public_path = yml["public_path"] if yml.has_key?("public_path")
|
192
|
+
self.expiry = yml["expiry"] if yml.has_key?("expiry")
|
193
|
+
end
|
194
|
+
|
195
|
+
def fail_silently?
|
196
|
+
fail_silently || !enabled?
|
197
|
+
end
|
198
|
+
|
199
|
+
def log_silently?
|
200
|
+
self.log_silently == false
|
201
|
+
end
|
202
|
+
|
203
|
+
class Invalid < StandardError; end
|
204
|
+
private
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# cloud_tempfile/engine.rb
|
2
|
+
#
|
3
|
+
# Author:: Kevin Bolduc
|
4
|
+
# Date:: 14-02-24
|
5
|
+
# Time:: 3:23 PM
|
6
|
+
|
7
|
+
module CloudTempfile
|
8
|
+
class Engine < Rails::Engine
|
9
|
+
|
10
|
+
engine_name "cloud_tempfile"
|
11
|
+
|
12
|
+
initializer "cloud_tempfile config", :group => :all do |app|
|
13
|
+
app_initializer = Rails.root.join('config', 'initializers', 'cloud_tempfile.rb').to_s
|
14
|
+
app_yaml = Rails.root.join('config', 'cloud_tempfile.yml').to_s
|
15
|
+
|
16
|
+
if File.exists?( app_initializer )
|
17
|
+
CloudTempfile.log "CloudTempfile: using #{app_initializer}"
|
18
|
+
load app_initializer
|
19
|
+
elsif !File.exists?( app_initializer ) && !File.exists?( app_yaml )
|
20
|
+
CloudTempfile.log "CloudTempfile: using default configuration from built-in initializer"
|
21
|
+
CloudTempfile.configure do |config|
|
22
|
+
config.fog_provider = ENV['FOG_PROVIDER'] if ENV.has_key?('FOG_PROVIDER')
|
23
|
+
config.fog_directory = ENV['FOG_DIRECTORY'] if ENV.has_key?('FOG_DIRECTORY')
|
24
|
+
config.fog_region = ENV['FOG_REGION'] if ENV.has_key?('FOG_REGION')
|
25
|
+
|
26
|
+
config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID'] if ENV.has_key?('AWS_ACCESS_KEY_ID')
|
27
|
+
config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY'] if ENV.has_key?('AWS_SECRET_ACCESS_KEY')
|
28
|
+
config.aws_reduced_redundancy = ENV['AWS_REDUCED_REDUNDANCY'] == true if ENV.has_key?('AWS_REDUCED_REDUNDANCY')
|
29
|
+
|
30
|
+
config.rackspace_username = ENV['RACKSPACE_USERNAME'] if ENV.has_key?('RACKSPACE_USERNAME')
|
31
|
+
config.rackspace_api_key = ENV['RACKSPACE_API_KEY'] if ENV.has_key?('RACKSPACE_API_KEY')
|
32
|
+
|
33
|
+
config.google_storage_access_key_id = ENV['GOOGLE_STORAGE_ACCESS_KEY_ID'] if ENV.has_key?('GOOGLE_STORAGE_ACCESS_KEY_ID')
|
34
|
+
config.google_storage_secret_access_key = ENV['GOOGLE_STORAGE_SECRET_ACCESS_KEY'] if ENV.has_key?('GOOGLE_STORAGE_SECRET_ACCESS_KEY')
|
35
|
+
|
36
|
+
config.enabled = (ENV['CLOUD_TEMPFILE_ENABLED'] == 'true') if ENV.has_key?('CLOUD_TEMPFILE_ENABLED')
|
37
|
+
config.public = (ENV['CLOUD_TEMPFILE_PUBLIC'] == 'true') if ENV.has_key?('CLOUD_TEMPFILE_PUBLIC')
|
38
|
+
config.public_path = ENV['CLOUD_TEMPFILE_PUBLIC_PATH'] if ENV.has_key?('CLOUD_TEMPFILE_PUBLIC_PATH')
|
39
|
+
config.expiry = ENV['CLOUD_TEMPFILE_EXPIRY'] if ENV.has_key?('CLOUD_TEMPFILE_EXPIRY')
|
40
|
+
|
41
|
+
config.clean_up = (ENV['CLOUD_TEMPFILE_CLEAN_UP'] == 'true') if ENV.has_key?('CLOUD_TEMPFILE_CLEAN_UP')
|
42
|
+
config.clean_up_older_than = ENV['CLOUD_TEMPFILE_CLEAN_UP_OLDER_THAN'] if ENV.has_key?('CLOUD_TEMPFILE_CLEAN_UP_OLDER_THAN')
|
43
|
+
end
|
44
|
+
|
45
|
+
config.prefix = ENV['CLOUD_TEMPFILE_PREFIX'] if ENV.has_key?('CLOUD_TEMPFILE_PREFIX')
|
46
|
+
end
|
47
|
+
|
48
|
+
if File.exists?( app_yaml )
|
49
|
+
CloudTempfile.log "CloudTempfile: YAML file found #{app_yaml} settings will be merged into the configuration"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- ruby encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# cloud_tempfile/multi_mime.rb
|
4
|
+
#
|
5
|
+
# Author:: Kevin Bolduc
|
6
|
+
# Date:: 14-02-24
|
7
|
+
# Time:: 3:23 PM
|
8
|
+
|
9
|
+
module CloudTempfile
|
10
|
+
class MultiMime
|
11
|
+
def self.lookup(ext)
|
12
|
+
if defined?(Mime::Type)
|
13
|
+
Mime::Type.lookup_by_extension(ext)
|
14
|
+
elsif defined?(Rack::Mime)
|
15
|
+
ext_with_dot = ".#{ext}"
|
16
|
+
Rack::Mime.mime_type(ext_with_dot)
|
17
|
+
else
|
18
|
+
MIME::Types.type_for(ext).first
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# cloud_tempfile/storage.rb
|
2
|
+
#
|
3
|
+
# Author:: Kevin Bolduc
|
4
|
+
# Date:: 14-02-24
|
5
|
+
# Time:: 3:23 PM
|
6
|
+
|
7
|
+
module CloudTempfile
|
8
|
+
class Storage
|
9
|
+
|
10
|
+
attr_accessor :config
|
11
|
+
|
12
|
+
def initialize(cfg)
|
13
|
+
@config = cfg
|
14
|
+
end
|
15
|
+
|
16
|
+
# This "connection" is the fog connection responsible for persisting the file
|
17
|
+
# @return [Fog::Storage]
|
18
|
+
def connection
|
19
|
+
@connection ||= ::Fog::Storage.new(self.config.fog_options)
|
20
|
+
end
|
21
|
+
|
22
|
+
# This "directory" action should only be used with the cloud provider and returns a <tt>Fog::Storage::Directory</tt> class
|
23
|
+
# @return [Fog::Storage::Directory]
|
24
|
+
def directory(options={})
|
25
|
+
prefix = options.has_key?(:prefix)? options[:prefix] : self.config.prefix
|
26
|
+
@directory ||= connection.directories.get(self.config.fog_directory, :prefix => prefix)
|
27
|
+
end
|
28
|
+
|
29
|
+
# This action will upload a AWS::File to the specified directory
|
30
|
+
# @return [Fog::Storage::File]
|
31
|
+
def upload_file(f, body, options={})
|
32
|
+
file = init_fog_file(f, body, options)
|
33
|
+
if self.config.enabled?
|
34
|
+
return directory(options).files.create( file )
|
35
|
+
else
|
36
|
+
return local_file(f, body, options)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Used with the "Local" provider which will utilize the local file system with Fog.
|
41
|
+
# This is handy for development and test environments.
|
42
|
+
# @return [Fog::Storage::Local::File]
|
43
|
+
def local_file(f, body, options={})
|
44
|
+
#return !self.config.public?
|
45
|
+
file = init_fog_file(f, body, options)
|
46
|
+
# If the "file" is empty then return nil
|
47
|
+
return nil if file.nil? || file.blank? || local_root.nil?
|
48
|
+
file = local_root(options).files.create( file )
|
49
|
+
end
|
50
|
+
|
51
|
+
# This action will delete a AWS::File from the specified directory
|
52
|
+
# @param [Fog::Storage::File]
|
53
|
+
def delete_file(f)
|
54
|
+
#return false if !f.kind_of?(Fog::Storage::AWS::File) || !storage_provider.eql?(:aws)
|
55
|
+
log "Deleting: #{f.key}"
|
56
|
+
return f.destroy
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns a list of remote files for the specified directory
|
60
|
+
# @throws [BucketNotFound]
|
61
|
+
# @return [Array]
|
62
|
+
def get_remote_files
|
63
|
+
raise BucketNotFound.new("#{self.config.fog_provider} Bucket: #{self.config.fog_directory} not found.") unless directory
|
64
|
+
files = []
|
65
|
+
directory.files.each { |f| files << f.key if File.extname(f.key).present? }
|
66
|
+
return files
|
67
|
+
end
|
68
|
+
|
69
|
+
# Delete the expired file which are expired if the "config.clean_up" is true
|
70
|
+
# and "config.clean_up_older_than" is the amount of seconds it is older than.
|
71
|
+
#
|
72
|
+
# Note: This action should be used with the "bundle exec rake cloud_temp_file:clear" rake command (cronjob)
|
73
|
+
def delete_expired_tempfiles
|
74
|
+
return if !self.config.clean_up? || !self.config.enabled?
|
75
|
+
log "CloudTempfile.delete_expired_tempfiles is running..."
|
76
|
+
# Delete expired temp files
|
77
|
+
get_remote_files.each do |f|
|
78
|
+
f = directory.files.get(f)
|
79
|
+
if f.last_modified <= self.config.clean_up_older_than.ago
|
80
|
+
delete_file(f)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
log "CloudTempfile.delete_expired_tempfiles is complete!"
|
84
|
+
end
|
85
|
+
|
86
|
+
# Custom Errors (Exceptions)
|
87
|
+
class BucketNotFound < StandardError; end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
# Initialize a Hash object to be use to by <tt>Fog::Storage</tt> to persist
|
92
|
+
# @param [String] filename
|
93
|
+
# @param [Object] body
|
94
|
+
# @return [Hash]
|
95
|
+
def init_fog_file(filename, body, options={})
|
96
|
+
# If the "filename" or the "body" are empty then return nil
|
97
|
+
return nil if filename.nil? || body.nil?
|
98
|
+
# Set file's access control list (ACL).
|
99
|
+
|
100
|
+
aws_acl = (self.config.aws_acl?)? self.config.aws_access_control_list.to_s : nil
|
101
|
+
# expiry is the number of seconds the file will available publicly
|
102
|
+
expiry = (self.config.expiry?)? self.config.expiry.to_i : nil
|
103
|
+
ext = File.extname(filename)[1..-1] # The file extension
|
104
|
+
mime = MultiMime.lookup(ext) # Look up the content type based off the file extension
|
105
|
+
prefix = options.has_key?(:prefix)? options[:prefix] : self.config.prefix
|
106
|
+
full_filename = (self.config.local? || !self.config.enabled?)? filename : "#{prefix}#{filename}"
|
107
|
+
|
108
|
+
# file Hash to be used to create a Fog for upload
|
109
|
+
file = {
|
110
|
+
:key => "#{full_filename}",
|
111
|
+
:body => body,
|
112
|
+
:content_type => mime
|
113
|
+
}
|
114
|
+
|
115
|
+
file.merge!({:public => true}) if self.config.public?
|
116
|
+
|
117
|
+
if self.config.aws?
|
118
|
+
if self.config.public? && self.config.expiry?
|
119
|
+
file.merge!({:cache_control => "public, max-age=#{expiry}"})
|
120
|
+
end
|
121
|
+
# valid acls: private, public-read, public-read-write, authenticated-read, bucket-owner-read, bucket-owner-full-control
|
122
|
+
file.merge!({:acl=>self.config.aws_access_control_list.to_s}) if self.config.aws_acl?
|
123
|
+
file.merge!({:expires => Time.now.utc.to_i + expiry}) if self.config.expiry?
|
124
|
+
file.merge!({:storage_class => 'REDUCED_REDUNDANCY'}) if self.config.aws_rrs?
|
125
|
+
end
|
126
|
+
|
127
|
+
return file
|
128
|
+
end
|
129
|
+
|
130
|
+
# This "local_root" action should only be used with the "Local" provider and returns a Fog::Storage::Local::Directory class
|
131
|
+
# @return [Fog::Storage::Local::Directory]
|
132
|
+
def local_root(options={})
|
133
|
+
prefix = options.has_key?(:prefix)? options[:prefix] : self.config.prefix
|
134
|
+
|
135
|
+
begin
|
136
|
+
if !connection.directories.get(prefix).nil?
|
137
|
+
@local_root ||= connection.directories.get(prefix)
|
138
|
+
else
|
139
|
+
@local_root ||= connection.directories.create(:key => prefix)
|
140
|
+
end
|
141
|
+
rescue
|
142
|
+
@local_root ||= connection.directories.create(:key => prefix)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def log(msg)
|
147
|
+
CloudTempfile.log(msg)
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'fog'
|
2
|
+
require 'active_model'
|
3
|
+
require 'erb'
|
4
|
+
require "ext/fog/aws/models/storage/file"
|
5
|
+
require 'cloud_tempfile/cloud_tempfile'
|
6
|
+
require 'cloud_tempfile/config'
|
7
|
+
require 'cloud_tempfile/storage'
|
8
|
+
require 'cloud_tempfile/multi_mime'
|
9
|
+
|
10
|
+
require 'cloud_tempfile/railtie' if defined?(Rails)
|
11
|
+
require 'cloud_tempfile/engine' if defined?(Rails)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'fog/aws/models/storage/file'
|
2
|
+
|
3
|
+
module Fog
|
4
|
+
module Storage
|
5
|
+
class AWS
|
6
|
+
|
7
|
+
class File
|
8
|
+
fog_public_url = instance_method(:public_url)
|
9
|
+
|
10
|
+
define_method(:public_url) do
|
11
|
+
return_url = fog_public_url.bind(self).call()
|
12
|
+
return_url = url(expires) if return_url.nil? && !expires.nil?
|
13
|
+
return return_url
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
module CloudTempfile
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
desc "Install a config/cloud_tempfile.yml "
|
5
|
+
|
6
|
+
# Commandline options can be defined here using Thor-like options:
|
7
|
+
class_option :use_yml, :type => :boolean, :default => false, :desc => "Use YML file instead of Rails Initializer"
|
8
|
+
class_option :provider, :type => :string, :default => "AWS", :desc => "Generate with support for 'AWS', 'Rackspace', or 'Google'"
|
9
|
+
|
10
|
+
def self.source_root
|
11
|
+
@source_root ||= File.join(File.dirname(__FILE__), 'templates')
|
12
|
+
end
|
13
|
+
|
14
|
+
def aws?
|
15
|
+
options[:provider] == 'AWS'
|
16
|
+
end
|
17
|
+
|
18
|
+
def google?
|
19
|
+
options[:provider] == 'Google'
|
20
|
+
end
|
21
|
+
|
22
|
+
def rackspace?
|
23
|
+
options[:provider] == 'Rackspace'
|
24
|
+
end
|
25
|
+
|
26
|
+
def fog_directory
|
27
|
+
"<%= ENV['FOG_DIRECTORY'] %>"
|
28
|
+
end
|
29
|
+
|
30
|
+
def aws_access_key_id
|
31
|
+
"<%= ENV['AWS_ACCESS_KEY_ID'] %>"
|
32
|
+
end
|
33
|
+
|
34
|
+
def aws_secret_access_key
|
35
|
+
"<%= ENV['AWS_SECRET_ACCESS_KEY'] %>"
|
36
|
+
end
|
37
|
+
|
38
|
+
def google_storage_access_key_id
|
39
|
+
"<%= ENV['GOOGLE_STORAGE_ACCESS_KEY_ID'] %>"
|
40
|
+
end
|
41
|
+
|
42
|
+
def google_storage_secret_access_key
|
43
|
+
"<%= ENV['GOOGLE_STORAGE_SECRET_ACCESS_KEY'] %>"
|
44
|
+
end
|
45
|
+
|
46
|
+
def rackspace_username
|
47
|
+
"<%= ENV['RACKSPACE_USERNAME'] %>"
|
48
|
+
end
|
49
|
+
|
50
|
+
def rackspace_api_key
|
51
|
+
"<%= ENV['RACKSPACE_API_KEY'] %>"
|
52
|
+
end
|
53
|
+
|
54
|
+
def app_name
|
55
|
+
@app_name ||= Rails.application.is_a?(Rails::Application) && Rails.application.class.name.sub(/::Application$/, "").downcase
|
56
|
+
end
|
57
|
+
|
58
|
+
def generate_config
|
59
|
+
if options[:use_yml]
|
60
|
+
template "cloud_tempfile.yml", "config/cloud_tempfile.yml"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def generate_initializer
|
65
|
+
unless options[:use_yml]
|
66
|
+
template "cloud_tempfile.rb", "config/initializers/cloud_tempfile.rb"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
CloudTempfile.configure do |config|
|
2
|
+
# Enable or disable the CloudTempfile functionality (Default: true)
|
3
|
+
# config.enabled = true
|
4
|
+
<%- if aws? -%>
|
5
|
+
config.fog_provider = 'AWS'
|
6
|
+
config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
|
7
|
+
config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
|
8
|
+
# The name of Amason S3 Bucket
|
9
|
+
config.fog_directory = ENV['FOG_DIRECTORY']
|
10
|
+
# You may need to specify what region your storage bucket is in. This may increase upload performance by configuring your region
|
11
|
+
# config.fog_region = 'eu-west-1'
|
12
|
+
# To use AWS reduced redundancy storage.
|
13
|
+
# (http://aws.amazon.com/about-aws/whats-new/2010/05/19/announcing-amazon-s3-reduced-redundancy-storage/)
|
14
|
+
# config.aws_reduced_redundancy = true
|
15
|
+
<%- elsif google? -%>
|
16
|
+
config.fog_provider = 'Google'
|
17
|
+
config.fog_directory = ENV['FOG_DIRECTORY']
|
18
|
+
config.google_storage_access_key_id = ENV['GOOGLE_STORAGE_ACCESS_KEY_ID']
|
19
|
+
config.google_storage_secret_access_key = ENV['GOOGLE_STORAGE_SECRET_ACCESS_KEY']
|
20
|
+
<%- elsif rackspace? -%>
|
21
|
+
config.fog_provider = 'Rackspace'
|
22
|
+
config.fog_directory = ENV['FOG_DIRECTORY']
|
23
|
+
config.rackspace_username = ENV['RACKSPACE_USERNAME']
|
24
|
+
config.rackspace_api_key = ENV['RACKSPACE_API_KEY']
|
25
|
+
# if you need to change rackspace_auth_url (e.g. if you need to use Rackspace London)
|
26
|
+
# config.rackspace_auth_url = "lon.auth.api.rackspacecloud.com"
|
27
|
+
<%- end -%>
|
28
|
+
#
|
29
|
+
# (String) This is a string file path which will be appended to the filename
|
30
|
+
# config.prefix = "<%= ENV['RAILS_ENV'] %>/tmp/"
|
31
|
+
# (Boolean) When true, the file publicly accessible. When false (default), a authenticated url will attempt to be generated
|
32
|
+
# config.public = true
|
33
|
+
# (Integer) The number of seconds the authenticated url will be valid (600 seconds = 10 minutes)
|
34
|
+
# config.expiry = 600
|
35
|
+
# (Boolean) When true, the clean up task (CloudTempfile.clear) will be able to run. Perfect for a cron clean up! ;)
|
36
|
+
# config.clean_up = true
|
37
|
+
# (Integer) The number of seconds the authenticated url will be valid (3600 seconds = 1 hour)
|
38
|
+
# config.clean_up_older_than = 3600
|
39
|
+
# (Boolean) Useful for environments such as Heroku
|
40
|
+
# config.fail_silently = true
|
41
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
defaults: &defaults
|
2
|
+
# Enable or disable the CloudTempfile functionality (Default: true)
|
3
|
+
# enabled: true
|
4
|
+
<%- if aws? -%>
|
5
|
+
fog_provider: "AWS"
|
6
|
+
aws_access_key_id: "<%= aws_access_key_id %>"
|
7
|
+
aws_secret_access_key: "<%= aws_secret_access_key %>"
|
8
|
+
# The name of Amason S3 Bucket
|
9
|
+
fog_directory: "<%= fog_directory %>"
|
10
|
+
# You may need to specify what region your storage bucket is in. This may increase upload performance by configuring your region
|
11
|
+
# fog_region: "us-east-1"
|
12
|
+
# To use AWS reduced redundancy storage.
|
13
|
+
# (http://aws.amazon.com/about-aws/whats-new/2010/05/19/announcing-amazon-s3-reduced-redundancy-storage/)
|
14
|
+
# aws_reduced_redundancy: true
|
15
|
+
<%- elsif google? -%>
|
16
|
+
fog_provider: "Google"
|
17
|
+
fog_directory: "<%= fog_directory %>"
|
18
|
+
google_storage_access_key_id: "<%= google_storage_access_key_id %>"
|
19
|
+
google_storage_secret_access_key: "<%= google_storage_secret_access_key %>"
|
20
|
+
<%- elsif rackspace? -%>
|
21
|
+
fog_provider: "Rackspace"
|
22
|
+
fog_directory: "name_of_container"
|
23
|
+
rackspace_username: "<%= rackspace_username %>"
|
24
|
+
rackspace_api_key: "<%= rackspace_api_key %>"
|
25
|
+
# if you need to change rackspace_auth_url (e.g. if you need to use Rackspace London)
|
26
|
+
# rackspace_auth_url: "https://lon.identity.api.rackspacecloud.com/v2.0"
|
27
|
+
<%- end -%>
|
28
|
+
# (String) This is a string file path which will be appended to the filename
|
29
|
+
# prefix: "<%= ENV['RAILS_ENV'] %>/tmp/"
|
30
|
+
# (Boolean) When true, the file publicly accessible. When false (default), a authenticated url will attempt to be generated
|
31
|
+
# public: true
|
32
|
+
# (Integer) The number of seconds the authenticated url will be valid (600 seconds = 10 minutes)
|
33
|
+
# expiry: 600
|
34
|
+
# (Boolean) When true, the clean up task (CloudTempfile.clear) will be able to run. Perfect for a cron clean up! ;)
|
35
|
+
# clean_up: true
|
36
|
+
# (Integer) The number of seconds the authenticated url will be valid (3600 seconds = 1 hour)
|
37
|
+
# clean_up_older_than: 3600
|
38
|
+
# (Boolean) Useful for environments such as Heroku
|
39
|
+
# fail_silently: true
|
40
|
+
development:
|
41
|
+
<<: *defaults
|
42
|
+
enabled: false
|
43
|
+
|
44
|
+
test:
|
45
|
+
<<: *defaults
|
46
|
+
enabled: false
|
47
|
+
|
48
|
+
staging:
|
49
|
+
<<: *defaults
|
50
|
+
|
51
|
+
production:
|
52
|
+
<<: *defaults
|