condo 1.0.4 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +7 -0
  2. data/README.textile +133 -133
  3. data/app/assets/javascripts/condo.js +9 -6
  4. data/app/assets/javascripts/condo/amazon.js +403 -406
  5. data/app/assets/javascripts/condo/condo.js +184 -0
  6. data/app/assets/javascripts/condo/config.js +69 -80
  7. data/app/assets/javascripts/condo/google.js +338 -255
  8. data/app/assets/javascripts/condo/md5/hash.worker.emulator.js +23 -23
  9. data/app/assets/javascripts/condo/md5/hash.worker.js +11 -11
  10. data/app/assets/javascripts/condo/md5/hasher.js +119 -100
  11. data/app/assets/javascripts/condo/md5/spark-md5.js +276 -161
  12. data/app/assets/javascripts/condo/rackspace.js +326 -329
  13. data/app/assets/javascripts/condo/{abstract-md5.js.erb → services/abstract-md5.js.erb} +86 -93
  14. data/app/assets/javascripts/condo/{base64.js → services/base64.js} +2 -10
  15. data/app/assets/javascripts/condo/services/broadcaster.js +26 -0
  16. data/app/assets/javascripts/condo/services/uploader.js +302 -0
  17. data/app/assets/javascripts/core/core.js +4 -0
  18. data/app/assets/javascripts/core/services/1-safe-apply.js +17 -0
  19. data/app/assets/javascripts/core/services/2-messaging.js +171 -0
  20. data/lib/condo.rb +269 -269
  21. data/lib/condo/configuration.rb +137 -139
  22. data/lib/condo/errors.rb +8 -8
  23. data/lib/condo/strata/amazon_s3.rb +301 -301
  24. data/lib/condo/strata/google_cloud_storage.rb +315 -314
  25. data/lib/condo/strata/rackspace_cloud_files.rb +245 -223
  26. data/lib/condo/version.rb +1 -1
  27. metadata +21 -44
  28. data/app/assets/javascripts/condo/broadcaster.js +0 -60
  29. data/app/assets/javascripts/condo/controller.js +0 -194
  30. data/app/assets/javascripts/condo/uploader.js +0 -310
  31. data/test/dummy/db/test.sqlite3 +0 -0
  32. data/test/dummy/log/test.log +0 -25
@@ -1,223 +1,245 @@
1
- module Condo; end
2
- module Condo::Strata; end
3
-
4
- #
5
- # NOTE:: Set Account Metadata Key for Public Access before this will work - X-Account-Meta-Temp-Url-Key: <your key>
6
- #
7
-
8
- class Condo::Strata::RackspaceCloudFiles
9
-
10
- def initialize(options)
11
- @options = {
12
- :name => :RackspaceCloudFiles,
13
- :location => :na, # dallas or chicago - this is set at bucket creation time
14
- :fog => {
15
- :provider => 'Rackspace',
16
- :rackspace_username => options[:username],
17
- :rackspace_api_key => options[:secret_key],
18
- :rackspace_auth_url => options[:auth_url] || 'identity.api.rackspacecloud.com' # is US and UK is 'lon.auth.api.rackspacecloud.com'
19
- }
20
- }.merge!(options)
21
-
22
-
23
- raise ArgumentError, 'Rackspace Username missing' if @options[:username].nil?
24
- raise ArgumentError, 'Rackspace Secret Key missing' if @options[:secret_key].nil?
25
-
26
-
27
- @options[:location] = @options[:location].to_sym
28
- end
29
-
30
-
31
- def name
32
- @options[:name]
33
- end
34
-
35
-
36
- def location
37
- @options[:location]
38
- end
39
-
40
-
41
- #
42
- # Here for convenience
43
- #
44
- def set_metatdata_key(key)
45
- fog_connection.request(
46
- :expects => [201, 202, 204],
47
- :method => 'POST',
48
- :headers => {'X-Account-Meta-Temp-Url-Key' => key}
49
- )
50
- end
51
-
52
-
53
- #
54
- # Create a signed URL for accessing a private file
55
- #
56
- def get_object(options)
57
- options = {}.merge!(options) # Need to deep copy here
58
- options[:object_options] = {
59
- :expires => 5.minutes.from_now,
60
- :verb => :get, # Post for multi-part uploads http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadInitiate.html
61
- :headers => {},
62
- :parameters => {}
63
- }.merge!(options[:object_options] || {})
64
- options.merge!(@options)
65
-
66
- #
67
- # provide the signed request
68
- #
69
- sign_request(options)[:url]
70
- end
71
-
72
-
73
- #
74
- # Creates a new upload request (either single shot or multi-part)
75
- # => Passed: bucket_name, object_key, object_options, file_size
76
- #
77
- def new_upload(options)
78
- options = {}.merge!(options) # Need to deep copy here
79
- options[:object_options] = {
80
- :expires => 5.minutes.from_now,
81
- :verb => :put,
82
- :headers => {},
83
- :parameters => {}
84
- }.merge!(options[:object_options])
85
- options.merge!(@options)
86
-
87
- options[:object_options][:headers]['ETag'] = options[:file_id] if options[:file_id].present? && options[:object_options][:headers]['ETag'].nil?
88
- options[:object_options][:headers]['Content-Type'] = 'binary/octet-stream' if options[:object_options][:headers]['Content-Type'].nil?
89
-
90
-
91
- #
92
- # Decide what type of request is being sent
93
- #
94
- request = {}
95
- if options[:file_size] > 2097152 # 2 mb (minimum chunk size)
96
-
97
- options[:object_key] = options[:object_key] + '_p1' # Append the part number
98
- request[:type] = :chunked_upload
99
- else
100
-
101
- request[:type] = :direct_upload
102
- end
103
-
104
- #
105
- # provide the signed request
106
- #
107
- request[:signature] = sign_request(options)
108
- request
109
- end
110
-
111
-
112
- #
113
- # Returns the part we are up to
114
- #
115
- def get_parts(options)
116
- {
117
- :type => :parts,
118
- :current_part => options[:resumable_id]
119
- }
120
- end
121
-
122
-
123
- #
124
- # Returns the requests for uploading parts and completing a resumable upload
125
- #
126
- def set_part(options)
127
- options[:object_options] = {
128
- :expires => 5.minutes.from_now,
129
- :headers => {},
130
- :parameters => {},
131
- :verb => :put
132
- }.merge!(options[:object_options])
133
- options.merge!(@options)
134
-
135
-
136
- request = {}
137
- if options[:part] == 'finish'
138
- #
139
- # Send the commitment response
140
- #
141
- options[:object_options][:headers]['X-Object-Manifest'] = "#{options[:bucket_name]}/#{options[:object_key]}"
142
- request[:type] = :finish
143
- else
144
- #
145
- # Send the part upload request
146
- #
147
- options[:object_options][:headers]['Content-Md5'] = options[:file_id] if options[:file_id].present? && options[:object_options][:headers]['Content-Md5'].nil?
148
- options[:object_options][:headers]['Content-Type'] = 'binary/octet-stream' if options[:object_options][:headers]['Content-Type'].nil?
149
- options[:object_key] = options[:object_key] + '_p' + options[:part]
150
- request[:type] = :part_upload
151
- end
152
-
153
- #
154
- # provide the signed request
155
- #
156
- request[:signature] = sign_request(options)
157
- request
158
- end
159
-
160
-
161
- def fog_connection
162
- @fog = @fog || Fog::Storage.new(@options[:fog])
163
- return @fog
164
- end
165
-
166
-
167
- def destroy(upload)
168
- connection = fog_connection
169
- directory = connection.directories.get(upload.bucket_name) # it is assumed this exists - if not then the upload wouldn't have taken place
170
-
171
- if upload.resumable
172
- directory.files.all({'prefix' => upload.object_key}).each do |file|
173
- return false unless file.destroy
174
- end
175
- end
176
-
177
- file = directory.files.get(upload.object_key) # this is the manifest when resumable
178
-
179
- return true if file.nil?
180
- return file.destroy
181
- end
182
-
183
-
184
-
185
- protected
186
-
187
-
188
-
189
- def sign_request(options)
190
-
191
- #
192
- # Build base URL
193
- #
194
- options[:object_options][:expires] = options[:object_options][:expires].utc.to_i
195
- url = "/v1/#{options[:username]}/#{CGI::escape options[:bucket_name]}/#{CGI::escape options[:object_key]}"
196
-
197
-
198
-
199
- #
200
- # Build a request signature
201
- #
202
- signature = "#{options[:object_options][:verb].to_s.upcase}\n#{options[:object_options][:expires]}\n#{url}"
203
-
204
-
205
- #
206
- # Encode the request signature
207
- #
208
- signature = OpenSSL::HMAC.hexdigest('sha1', @options[:secret_key], signature)
209
-
210
-
211
- #
212
- # Finish building the request
213
- #
214
- return {
215
- :verb => options[:object_options][:verb].to_s.upcase,
216
- :url => "https://storage.clouddrive.com#{url}?temp_url_sig=#{signature}&temp_url_expires=#{options[:object_options][:expires]}",
217
- :headers => options[:object_options][:headers]
218
- }
219
- end
220
-
221
-
222
- end
223
-
1
+ module Condo; end
2
+ module Condo::Strata; end
3
+
4
+ #
5
+ # NOTE:: Set Account Metadata Key for Public Access before this will work - X-Account-Meta-Temp-Url-Key: <your key>
6
+ #
7
+
8
+ class Condo::Strata::RackspaceCloudFiles
9
+
10
+ def initialize(options)
11
+ @options = {
12
+ :name => :RackspaceCloudFiles,
13
+ :location => :dfw, # dallas or chicago - this is set at bucket creation time
14
+ :fog => {
15
+ :provider => 'Rackspace',
16
+ :rackspace_username => options[:username],
17
+ :rackspace_api_key => options[:secret_key],
18
+ :rackspace_auth_url => options[:auth_url] || 'https://identity.api.rackspacecloud.com/v2.0' # is US and UK is 'lon.auth.api.rackspacecloud.com'
19
+ }
20
+ }.merge!(options)
21
+
22
+
23
+ @options[:location] = case @options[:location]
24
+ when :dfw, :dallas, :DFW then 'storage101.dfw1.clouddrive.com'
25
+ when :ord, :chicago, :ORD then 'storage101.ord1.clouddrive.com'
26
+ end
27
+
28
+
29
+ #raise ArgumentError, 'Rackspace Username missing' if @options[:username].nil?
30
+ #raise ArgumentError, 'Rackspace Secret Key missing' if @options[:secret_key].nil?
31
+
32
+ raise ArgumentError, 'Rackspace Storage URL missing' if @options[:storage_url].nil?
33
+ raise ArgumentError, 'Rackspace Temp URL Key missing' if @options[:temp_url_key].nil?
34
+
35
+
36
+ @options[:location] = @options[:location].to_sym
37
+ end
38
+
39
+
40
+ def name
41
+ @options[:name]
42
+ end
43
+
44
+
45
+ def location
46
+ @options[:location]
47
+ end
48
+
49
+
50
+ #
51
+ # Here for convenience
52
+ #
53
+ def set_metadata_key(key)
54
+ fog_connection.request(
55
+ :expects => [201, 202, 204],
56
+ :method => 'POST',
57
+ :headers => {'X-Account-Meta-Temp-Url-Key' => key}
58
+ )
59
+ end
60
+
61
+
62
+ def allow_cors(domains = 'http://localhost:3000', options_age = 10, headers = 'etag, x-object-manifest, content-type, accept, origin, x-requested-with')
63
+ fog_connection.request(
64
+ :expects => [201, 202, 204],
65
+ :method => 'POST',
66
+ :headers => {
67
+ 'X-Container-Meta-Access-Control-Allow-Origin' => domains,
68
+ 'X-Container-Meta-Access-Control-Max-Age' => options_age,
69
+ 'X-Container-Meta-Access-Control-Allow-Headers' => headers
70
+ }
71
+ )
72
+ end
73
+
74
+
75
+ #
76
+ # Create a signed URL for accessing a private file
77
+ #
78
+ def get_object(options)
79
+ options = {}.merge!(options) # Need to deep copy here
80
+ options[:object_options] = {
81
+ :expires => 5.minutes.from_now,
82
+ :verb => :get, # Post for multi-part uploads http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadInitiate.html
83
+ :headers => {},
84
+ :parameters => {}
85
+ }.merge!(options[:object_options] || {})
86
+ options.merge!(@options)
87
+
88
+ #
89
+ # provide the signed request
90
+ #
91
+ sign_request(options)[:url]
92
+ end
93
+
94
+
95
+ #
96
+ # Creates a new upload request (either single shot or multi-part)
97
+ # => Passed: bucket_name, object_key, object_options, file_size
98
+ #
99
+ def new_upload(options)
100
+ options = {}.merge!(options) # Need to deep copy here
101
+ options[:object_options] = {
102
+ :expires => 5.minutes.from_now,
103
+ :verb => :put,
104
+ :headers => {},
105
+ :parameters => {}
106
+ }.merge!(options[:object_options])
107
+ options.merge!(@options)
108
+
109
+ options[:object_options][:headers]['ETag'] = options[:file_id] if options[:file_id].present? && options[:object_options][:headers]['ETag'].nil?
110
+ options[:object_options][:headers]['Content-Type'] = 'binary/octet-stream' if options[:object_options][:headers]['Content-Type'].nil?
111
+
112
+
113
+ #
114
+ # Decide what type of request is being sent
115
+ #
116
+ request = {}
117
+ if options[:file_size] > 2097152 # 2 mb (minimum chunk size)
118
+
119
+ options[:object_key] = options[:object_key] + '_p1' # Append the part number
120
+ request[:type] = :chunked_upload
121
+ else
122
+
123
+ request[:type] = :direct_upload
124
+ end
125
+
126
+ #
127
+ # provide the signed request
128
+ #
129
+ request[:signature] = sign_request(options)
130
+ request
131
+ end
132
+
133
+
134
+ #
135
+ # Returns the part we are up to
136
+ #
137
+ def get_parts(options)
138
+ {
139
+ :type => :parts,
140
+ :current_part => options[:resumable_id]
141
+ }
142
+ end
143
+
144
+
145
+ #
146
+ # Returns the requests for uploading parts and completing a resumable upload
147
+ #
148
+ def set_part(options)
149
+ options[:object_options] = {
150
+ :expires => 5.minutes.from_now,
151
+ :headers => {},
152
+ :parameters => {},
153
+ :verb => :put
154
+ }.merge!(options[:object_options])
155
+ options.merge!(@options)
156
+
157
+
158
+ request = {}
159
+ if options[:part] == 'finish'
160
+ #
161
+ # Send the commitment response
162
+ #
163
+ options[:object_options][:headers]['X-Object-Manifest'] = "#{options[:bucket_name]}/#{options[:object_key]}"
164
+ request[:type] = :finish
165
+ else
166
+ #
167
+ # Send the part upload request
168
+ #
169
+ options[:object_options][:headers]['ETag'] = options[:file_id] if options[:file_id].present? && options[:object_options][:headers]['ETag'].nil?
170
+ options[:object_options][:headers]['Content-Type'] = 'binary/octet-stream' if options[:object_options][:headers]['Content-Type'].nil?
171
+ options[:object_key] = options[:object_key] + '_p' + options[:part]
172
+ request[:type] = :part_upload
173
+ end
174
+
175
+ #
176
+ # provide the signed request
177
+ #
178
+ request[:signature] = sign_request(options)
179
+ request
180
+ end
181
+
182
+
183
+ def fog_connection
184
+ @fog = @fog || Fog::Storage.new(@options[:fog])
185
+ return @fog
186
+ end
187
+
188
+
189
+ def destroy(upload)
190
+ connection = fog_connection
191
+ directory = connection.directories.get(upload.bucket_name) # it is assumed this exists - if not then the upload wouldn't have taken place
192
+
193
+ if upload.resumable
194
+ directory.files.all({'prefix' => upload.object_key}).each do |file|
195
+ return false unless file.destroy
196
+ end
197
+ end
198
+
199
+ file = directory.files.get(upload.object_key) # this is the manifest when resumable
200
+
201
+ return true if file.nil?
202
+ return file.destroy
203
+ end
204
+
205
+
206
+
207
+ protected
208
+
209
+
210
+
211
+ def sign_request(options)
212
+
213
+ #
214
+ # Build base URL
215
+ #
216
+ options[:object_options][:expires] = options[:object_options][:expires].utc.to_i
217
+ url = "/v1/#{options[:storage_url]}/#{CGI::escape options[:bucket_name]}/#{CGI::escape options[:object_key]}"
218
+
219
+
220
+
221
+ #
222
+ # Build a request signature
223
+ #
224
+ signature = "#{options[:object_options][:verb].to_s.upcase}\n#{options[:object_options][:expires]}\n#{url}"
225
+
226
+
227
+ #
228
+ # Encode the request signature
229
+ #
230
+ signature = OpenSSL::HMAC.hexdigest('sha1', @options[:temp_url_key], signature)
231
+
232
+
233
+ #
234
+ # Finish building the request
235
+ #
236
+ return {
237
+ :verb => options[:object_options][:verb].to_s.upcase,
238
+ :url => "https://#{@options[:location]}#{url}?temp_url_sig=#{signature}&temp_url_expires=#{options[:object_options][:expires]}",
239
+ :headers => options[:object_options][:headers]
240
+ }
241
+ end
242
+
243
+
244
+ end
245
+