condo 1.0.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.textile +19 -32
  3. data/lib/condo.rb +124 -127
  4. data/lib/condo/configuration.rb +41 -76
  5. data/lib/condo/engine.rb +32 -39
  6. data/lib/condo/errors.rb +6 -8
  7. data/lib/condo/strata/amazon_s3.rb +246 -294
  8. data/lib/condo/strata/google_cloud_storage.rb +238 -272
  9. data/lib/condo/strata/open_stack_swift.rb +251 -0
  10. data/lib/condo/version.rb +1 -1
  11. metadata +31 -96
  12. data/app/assets/javascripts/condo.js +0 -9
  13. data/app/assets/javascripts/condo/amazon.js +0 -403
  14. data/app/assets/javascripts/condo/condo.js +0 -184
  15. data/app/assets/javascripts/condo/config.js +0 -69
  16. data/app/assets/javascripts/condo/google.js +0 -338
  17. data/app/assets/javascripts/condo/md5/hash.worker.emulator.js +0 -23
  18. data/app/assets/javascripts/condo/md5/hash.worker.js +0 -11
  19. data/app/assets/javascripts/condo/md5/hasher.js +0 -119
  20. data/app/assets/javascripts/condo/md5/spark-md5.js +0 -599
  21. data/app/assets/javascripts/condo/rackspace.js +0 -326
  22. data/app/assets/javascripts/condo/services/abstract-md5.js.erb +0 -86
  23. data/app/assets/javascripts/condo/services/base64.js +0 -184
  24. data/app/assets/javascripts/condo/services/broadcaster.js +0 -26
  25. data/app/assets/javascripts/condo/services/uploader.js +0 -302
  26. data/app/assets/javascripts/core/core.js +0 -4
  27. data/app/assets/javascripts/core/services/1-safe-apply.js +0 -17
  28. data/app/assets/javascripts/core/services/2-messaging.js +0 -171
  29. data/lib/condo/strata/rackspace_cloud_files.rb +0 -245
  30. data/test/condo_test.rb +0 -27
  31. data/test/dummy/README.rdoc +0 -261
  32. data/test/dummy/Rakefile +0 -7
  33. data/test/dummy/app/assets/javascripts/application.js +0 -15
  34. data/test/dummy/app/assets/stylesheets/application.css +0 -13
  35. data/test/dummy/app/controllers/application_controller.rb +0 -3
  36. data/test/dummy/app/helpers/application_helper.rb +0 -2
  37. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  38. data/test/dummy/config.ru +0 -4
  39. data/test/dummy/config/application.rb +0 -59
  40. data/test/dummy/config/boot.rb +0 -10
  41. data/test/dummy/config/database.yml +0 -25
  42. data/test/dummy/config/environment.rb +0 -5
  43. data/test/dummy/config/environments/development.rb +0 -37
  44. data/test/dummy/config/environments/production.rb +0 -67
  45. data/test/dummy/config/environments/test.rb +0 -37
  46. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  47. data/test/dummy/config/initializers/inflections.rb +0 -15
  48. data/test/dummy/config/initializers/mime_types.rb +0 -5
  49. data/test/dummy/config/initializers/secret_token.rb +0 -7
  50. data/test/dummy/config/initializers/session_store.rb +0 -8
  51. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  52. data/test/dummy/config/locales/en.yml +0 -5
  53. data/test/dummy/config/routes.rb +0 -58
  54. data/test/dummy/public/404.html +0 -26
  55. data/test/dummy/public/422.html +0 -26
  56. data/test/dummy/public/500.html +0 -25
  57. data/test/dummy/public/favicon.ico +0 -0
  58. data/test/dummy/script/rails +0 -6
  59. data/test/integration/navigation_test.rb +0 -10
  60. data/test/test_helper.rb +0 -15
@@ -3,43 +3,40 @@ module Condo::Strata; end
3
3
 
4
4
 
5
5
  class Fog::Storage::Google::Real
6
- def condo_request(*args)
7
- request(*args)
8
- end
6
+ def condo_request(*args)
7
+ request(*args)
8
+ end
9
9
  end
10
10
 
11
11
 
12
12
  class Condo::Strata::GoogleCloudStorage
13
-
14
- def initialize(options)
15
- @options = {
16
- :name => :GoogleCloudStorage,
17
- :location => :na, # US or Europe, set at bucket creation time
18
- :fog => {
19
- :provider => 'Google',
20
- :google_storage_access_key_id => options[:fog_access_id] || options[:access_id],
21
- :google_storage_secret_access_key => options[:fog_secret_key] || options[:secret_key]
22
- },
23
- :api => 1
24
- }.merge!(options)
25
-
26
-
27
- raise ArgumentError, 'Google Access ID missing' if @options[:access_id].nil?
28
- raise ArgumentError, 'Google Secret Key missing' if @options[:secret_key].nil?
29
-
30
- if @options[:api] == 2
31
- @options[:secret_key] = OpenSSL::PKey::RSA.new(@options[:secret_key])
32
- end
33
-
34
- @options[:location] = @options[:location].to_sym
35
- end
36
-
37
-
38
- #
39
- # Enable CORS on a bucket for a domain
40
- #
41
- def enable_cors(bucket, origin = '*')
42
- data =
13
+ def initialize(options)
14
+ @options = {
15
+ :name => :GoogleCloudStorage,
16
+ :location => :na, # US or Europe, set at bucket creation time
17
+ :fog => {
18
+ :provider => 'Google',
19
+ :google_storage_access_key_id => options[:fog_access_id] || options[:access_id],
20
+ :google_storage_secret_access_key => options[:fog_secret_key] || options[:secret_key]
21
+ },
22
+ :api => 1
23
+ }.merge!(options)
24
+
25
+
26
+ raise ArgumentError, 'Google Access ID missing' if @options[:access_id].nil?
27
+ raise ArgumentError, 'Google Secret Key missing' if @options[:secret_key].nil?
28
+
29
+ if @options[:api] == 2
30
+ @options[:secret_key] = OpenSSL::PKey::RSA.new(@options[:secret_key])
31
+ end
32
+
33
+ @options[:location] = @options[:location].to_sym
34
+ end
35
+
36
+
37
+ # Enable CORS on a bucket for a domain
38
+ def enable_cors(bucket, origin = '*')
39
+ data =
43
40
  <<-DATA
44
41
  <?xml version="1.0" encoding="UTF-8"?>
45
42
  <CorsConfig>
@@ -70,246 +67,215 @@ class Condo::Strata::GoogleCloudStorage
70
67
  </Cors>
71
68
  </CorsConfig>
72
69
  DATA
73
-
74
- fog_connection.condo_request(
75
- :expects => 200,
76
- :body => data,
77
- :method => 'PUT',
78
- :headers => {},
79
- :host => "#{bucket}.storage.googleapis.com",
80
- :idempotent => true,
81
- :path => '?cors' # There is an issue with Fog where this isn't included as a canonical_resource
82
- )
83
- end
84
-
85
-
86
- def name
87
- @options[:name]
88
- end
89
-
90
-
91
- def location
92
- @options[:location]
93
- end
94
-
95
-
96
- #
97
- # Create a signed URL for accessing a private file
98
- #
99
- def get_object(options)
100
- options = {}.merge!(options) # Need to deep copy here
101
- options[:object_options] = {
102
- :expires => 5.minutes.from_now,
103
- :verb => :get,
104
- :headers => {},
105
- :parameters => {},
106
- :protocol => :https
107
- }.merge!(options[:object_options] || {})
108
- options.merge!(@options)
109
-
110
- #
111
- # provide the signed request
112
- #
113
- sign_request(options)[:url]
114
- end
115
-
116
-
117
- #
118
- # Creates a new upload request (either single shot or multi-part)
119
- # => Passed: bucket_name, object_key, object_options, file_size
120
- #
121
- def new_upload(options)
122
- options = {}.merge!(options) # Need to deep copy here
123
- options[:object_options] = {
124
- :permissions => :private,
125
- :expires => 5.minutes.from_now,
126
- :verb => :put, # put for direct uploads
127
- :headers => {},
128
- :parameters => {},
129
- :protocol => :https
130
- }.merge!(options[:object_options] || {})
131
- options.merge!(@options)
132
-
133
-
134
- options[:object_options][:headers]['x-goog-api-version'] = @options[:api]
135
-
136
- if options[:object_options][:headers]['x-goog-acl'].nil?
137
- options[:object_options][:headers]['x-goog-acl'] = case options[:object_options][:permissions]
138
- when :public
139
- :'public-read'
140
- else
141
- :private
142
- end
143
- end
144
-
145
- options[:object_options][:headers]['Content-Type'] = 'binary/octet-stream' if options[:object_options][:headers]['Content-Type'].nil?
146
-
147
-
148
- #
149
- # Decide what type of request is being sent
150
- #
151
- if options[:file_size] > 1.megabytes
152
- # Resumables may not support the md5 header at this time - have to compare ETag and fail on the client side
153
- options[:object_options][:verb] = :post
154
- options[:object_options][:headers]['x-goog-resumable'] = 'start'
155
- return {
156
- :signature => sign_request(options),
157
- :type => :chunked_upload # triggers resumable
158
- }
159
- else
160
- options[:object_options][:headers]['Content-Md5'] = options[:file_id] if options[:file_id].present? && options[:object_options][:headers]['Content-Md5'].nil?
161
- return {
162
- :signature => sign_request(options),
163
- :type => :direct_upload
164
- }
165
- end
166
- end
167
-
168
-
169
- #
170
- # Creates a request for the byte we were up to
171
- #
172
- def get_parts(options, setting_parts = false)
173
- options[:object_options] = {
174
- :expires => 5.minutes.from_now,
175
- :verb => :put, # put for direct uploads
176
- :headers => {},
177
- :parameters => {},
178
- :protocol => :https
179
- }.merge!(options[:object_options] || {})
180
- options.merge!(@options)
181
-
182
- #
183
- # Set the upload and request the range of bytes we are after
184
- #
185
- if setting_parts
186
- options[:object_options][:headers]['Content-Md5'] = options[:file_id] if options[:file_id].present? && options[:object_options][:headers]['Content-Md5'].nil?
187
- options[:object_options][:headers]['Content-Range'] = "bytes #{options[:part]}-#{options[:file_size] - 1}/#{options[:file_size]}"
188
- else
189
- options[:object_options][:headers]['Content-Range'] = "bytes */#{options[:file_size]}"
190
- end
191
- options[:object_options][:headers]['x-goog-api-version'] = @options[:api]
192
- options[:object_options][:parameters]['upload_id'] = options[:resumable_id]
193
-
194
- #
195
- # provide the signed request
196
- #
197
- {
198
- :expected => 308,
199
- :type => :status,
200
- :signature => sign_request(options)
201
- }
202
- end
203
-
204
-
205
- #
206
- # Returns the requests for uploading parts and completing a resumable upload
207
- #
208
- def set_part(options)
209
- resp = get_parts(options, true)
210
- resp[:type] = :resume_upload
211
- resp[:type] = :resume_upload
212
- return resp
213
- end
214
-
215
-
216
- def fog_connection
217
- @fog = @fog || Fog::Storage.new(@options[:fog])
218
- return @fog
219
- end
220
-
221
-
222
- def destroy(upload)
223
- connection = fog_connection
224
- directory = connection.directories.get(upload.bucket_name) # it is assumed this exists - if not then the upload wouldn't have taken place
225
- file = directory.files.get(upload.object_key) # NOTE:: I only assume this works with resumables... should look into it
226
-
227
- return true if file.nil?
228
- return file.destroy
229
- end
230
-
231
-
232
-
233
- protected
234
-
235
-
236
-
237
- def sign_request(options)
238
-
239
- #
240
- # Build base URL
241
- #
242
- verb = options[:object_options][:verb].to_s.upcase.to_sym
243
- options[:object_options][:expires] = options[:object_options][:expires].utc.to_i
244
-
245
- url = "/#{options[:object_key]}"
246
-
247
-
248
- #
249
- # Add signed request params
250
- #
251
- other_params = ''
252
- signed_params = '?'
253
- (options[:object_options][:parameters] || {}).each do |key, value|
70
+
71
+ fog_connection.condo_request(
72
+ :expects => 200,
73
+ :body => data,
74
+ :method => 'PUT',
75
+ :headers => {},
76
+ :host => "#{bucket}.storage.googleapis.com",
77
+ :idempotent => true,
78
+ :path => '?cors' # There is an issue with Fog where this isn't included as a canonical_resource
79
+ )
80
+ end
81
+
82
+
83
+ def name
84
+ @options[:name]
85
+ end
86
+
87
+
88
+ def location
89
+ @options[:location]
90
+ end
91
+
92
+
93
+ # Create a signed URL for accessing a private file
94
+ def get_object(options)
95
+ options = {}.merge!(options) # Need to deep copy here
96
+ options[:object_options] = {
97
+ :expires => 5.minutes.from_now,
98
+ :verb => :get,
99
+ :headers => {},
100
+ :parameters => {},
101
+ :protocol => :https
102
+ }.merge!(options[:object_options] || {})
103
+ options.merge!(@options)
104
+
105
+ #
106
+ # provide the signed request
107
+ #
108
+ sign_request(options)[:url]
109
+ end
110
+
111
+
112
+ # Creates a new upload request (either single shot or multi-part)
113
+ # => Passed: bucket_name, object_key, object_options, file_size
114
+ def new_upload(options)
115
+ options = {}.merge!(options) # Need to deep copy here
116
+ options[:object_options] = {
117
+ :permissions => :private,
118
+ :expires => 5.minutes.from_now,
119
+ :verb => :put, # put for direct uploads
120
+ :headers => {},
121
+ :parameters => {},
122
+ :protocol => :https
123
+ }.merge!(options[:object_options] || {})
124
+ options.merge!(@options)
125
+
126
+
127
+ options[:object_options][:headers]['x-goog-api-version'] = @options[:api]
128
+
129
+ if options[:object_options][:headers]['x-goog-acl'].nil?
130
+ options[:object_options][:headers]['x-goog-acl'] = case options[:object_options][:permissions]
131
+ when :public
132
+ :'public-read'
133
+ else
134
+ :private
135
+ end
136
+ end
137
+
138
+ options[:object_options][:headers]['Content-Type'] = 'binary/octet-stream' if options[:object_options][:headers]['Content-Type'].nil?
139
+
140
+
141
+ # Decide what type of request is being sent
142
+ if options[:file_size] > 1.megabytes
143
+ # Resumables may not support the md5 header at this time - have to compare ETag and fail on the client side
144
+ options[:object_options][:verb] = :post
145
+ options[:object_options][:headers]['x-goog-resumable'] = 'start'
146
+ return {
147
+ :signature => sign_request(options),
148
+ :type => :chunked_upload # triggers resumable
149
+ }
150
+ else
151
+ options[:object_options][:headers]['Content-Md5'] = options[:file_id] if options[:file_id].present? && options[:object_options][:headers]['Content-Md5'].nil?
152
+ return {
153
+ :signature => sign_request(options),
154
+ :type => :direct_upload
155
+ }
156
+ end
157
+ end
158
+
159
+
160
+ # Creates a request for the byte we were up to
161
+ def get_parts(options, setting_parts = false)
162
+ options[:object_options] = {
163
+ :expires => 5.minutes.from_now,
164
+ :verb => :put, # put for direct uploads
165
+ :headers => {},
166
+ :parameters => {},
167
+ :protocol => :https
168
+ }.merge!(options[:object_options] || {})
169
+ options.merge!(@options)
170
+
171
+ # Set the upload and request the range of bytes we are after
172
+ if setting_parts
173
+ options[:object_options][:headers]['Content-Md5'] = options[:file_id] if options[:file_id].present? && options[:object_options][:headers]['Content-Md5'].nil?
174
+ options[:object_options][:headers]['Content-Range'] = "bytes #{options[:part]}-#{options[:file_size] - 1}/#{options[:file_size]}"
175
+ else
176
+ options[:object_options][:headers]['Content-Range'] = "bytes */#{options[:file_size]}"
177
+ end
178
+ options[:object_options][:headers]['x-goog-api-version'] = @options[:api]
179
+ options[:object_options][:parameters]['upload_id'] = options[:resumable_id]
180
+
181
+ # provide the signed request
182
+ {
183
+ :expected => 308,
184
+ :type => :status,
185
+ :signature => sign_request(options)
186
+ }
187
+ end
188
+
189
+
190
+ # Returns the requests for uploading parts and completing a resumable upload
191
+ def set_part(options)
192
+ resp = get_parts(options, true)
193
+ resp[:type] = :resume_upload
194
+ resp[:type] = :resume_upload
195
+ return resp
196
+ end
197
+
198
+
199
+ def fog_connection
200
+ @fog = @fog || Fog::Storage.new(@options[:fog])
201
+ return @fog
202
+ end
203
+
204
+
205
+ def destroy(upload)
206
+ connection = fog_connection
207
+ directory = connection.directories.get(upload.bucket_name) # it is assumed this exists - if not then the upload wouldn't have taken place
208
+ file = directory.files.get(upload.object_key) # NOTE:: I only assume this works with resumables... should look into it
209
+
210
+ return true if file.nil?
211
+ return file.destroy
212
+ end
213
+
214
+
215
+
216
+ protected
217
+
218
+
219
+
220
+ def sign_request(options)
221
+
222
+ # Build base URL
223
+ verb = options[:object_options][:verb].to_s.upcase.to_sym
224
+ options[:object_options][:expires] = options[:object_options][:expires].utc.to_i
225
+
226
+ url = "/#{options[:object_key]}"
227
+
228
+ # Add signed request params
229
+ other_params = ''
230
+ signed_params = '?'
231
+ (options[:object_options][:parameters] || {}).each do |key, value|
254
232
  if ['acl', 'cors', 'location', 'logging', 'requestPayment', 'torrent', 'versions', 'versioning'].include?(key)
255
- signed_params << "#{key}&"
256
- else
257
- other_params << (value.empty? ? "#{key}&" : "#{key}=#{value}&")
233
+ signed_params << "#{key}&"
234
+ else
235
+ other_params << (value.blank? ? "#{key}&" : "#{key}=#{value}&")
236
+ end
237
+ end
238
+ signed_params.chop!
239
+
240
+ url << signed_params
241
+
242
+ # Build a request signature
243
+ signature = "#{verb}\n#{options[:object_options][:headers]['Content-Md5']}\n#{options[:object_options][:headers]['Content-Type']}\n#{options[:object_options][:expires]}\n"
244
+ if verb != :GET
245
+ options[:object_options][:headers]['x-goog-date'] ||= Time.now.utc.httpdate
246
+
247
+ google_headers, canonical_google_headers = {}, '' # Copied from https://github.com/fog/fog/blob/master/lib/fog/google/storage.rb
248
+ for key, value in options[:object_options][:headers]
249
+ if key[0..6] == 'x-goog-'
250
+ google_headers[key] = value
251
+ end
258
252
  end
259
- end
260
- signed_params.chop!
261
-
262
- url << signed_params
263
-
264
-
265
- #
266
- # Build a request signature
267
- #
268
- signature = "#{verb}\n#{options[:object_options][:headers]['Content-Md5']}\n#{options[:object_options][:headers]['Content-Type']}\n#{options[:object_options][:expires]}\n"
269
- if verb != :GET
270
- options[:object_options][:headers]['x-goog-date'] ||= Time.now.utc.httpdate
271
-
272
- google_headers, canonical_google_headers = {}, '' # Copied from https://github.com/fog/fog/blob/master/lib/fog/google/storage.rb
273
- for key, value in options[:object_options][:headers]
274
- if key[0..6] == 'x-goog-'
275
- google_headers[key] = value
276
- end
277
- end
278
-
279
- google_headers = google_headers.sort {|x, y| x[0] <=> y[0]}
280
- for key, value in google_headers
281
- signature << "#{key}:#{value}\n"
282
- end
283
- end
284
-
285
- signature << "/#{options[:bucket_name]}#{url}"
286
-
287
-
288
- #
289
- # Encode the request signature
290
- #
291
- if @options[:api] == 1
292
- signature = Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha1'), @options[:secret_key], signature)).gsub("\n","")
293
- options[:object_options][:headers]['Authorization'] = "GOOG1 #{@options[:access_id]}:#{signature}"
294
- else
295
- signature = Base64.encode64(@options[:secret_key].sign(OpenSSL::Digest::SHA256.new, signature)).gsub("\n","")
296
- end
297
-
298
-
299
- url += signed_params.present? ? '&' : '?'
300
- url = "#{options[:object_options][:protocol]}://#{options[:bucket_name]}.storage.googleapis.com#{url}#{other_params}GoogleAccessId=#{@options[:access_id]}&Expires=#{options[:object_options][:expires]}&Signature=#{CGI::escape(signature)}"
301
-
302
-
303
- #
304
- # Finish building the request
305
- #
306
- return {
307
- :verb => options[:object_options][:verb].to_s.upcase,
308
- :url => url,
309
- :headers => options[:object_options][:headers]
310
- }
311
- end
312
-
313
-
253
+
254
+ google_headers = google_headers.sort {|x, y| x[0] <=> y[0]}
255
+ for key, value in google_headers
256
+ signature << "#{key}:#{value}\n"
257
+ end
258
+ end
259
+
260
+ signature << "/#{options[:bucket_name]}#{url}"
261
+
262
+ # Encode the request signature
263
+ if @options[:api] == 1
264
+ signature = Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), @options[:secret_key], signature)).gsub("\n","")
265
+ options[:object_options][:headers]['Authorization'] = "GOOG1 #{@options[:access_id]}:#{signature}"
266
+ else
267
+ signature = Base64.encode64(@options[:secret_key].sign(OpenSSL::Digest::SHA256.new, signature)).gsub("\n","")
268
+ end
269
+
270
+ url += signed_params.present? ? '&' : '?'
271
+ url = "#{options[:object_options][:protocol]}://#{options[:bucket_name]}.storage.googleapis.com#{url}#{other_params}GoogleAccessId=#{@options[:access_id]}&Expires=#{options[:object_options][:expires]}&Signature=#{CGI::escape(signature)}"
272
+
273
+ # Finish building the request
274
+ return {
275
+ :verb => options[:object_options][:verb].to_s.upcase,
276
+ :url => url,
277
+ :headers => options[:object_options][:headers]
278
+ }
279
+ end
314
280
  end
315
281