condo 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+