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.
- checksums.yaml +7 -0
- data/README.textile +133 -133
- data/app/assets/javascripts/condo.js +9 -6
- data/app/assets/javascripts/condo/amazon.js +403 -406
- data/app/assets/javascripts/condo/condo.js +184 -0
- data/app/assets/javascripts/condo/config.js +69 -80
- data/app/assets/javascripts/condo/google.js +338 -255
- data/app/assets/javascripts/condo/md5/hash.worker.emulator.js +23 -23
- data/app/assets/javascripts/condo/md5/hash.worker.js +11 -11
- data/app/assets/javascripts/condo/md5/hasher.js +119 -100
- data/app/assets/javascripts/condo/md5/spark-md5.js +276 -161
- data/app/assets/javascripts/condo/rackspace.js +326 -329
- data/app/assets/javascripts/condo/{abstract-md5.js.erb → services/abstract-md5.js.erb} +86 -93
- data/app/assets/javascripts/condo/{base64.js → services/base64.js} +2 -10
- data/app/assets/javascripts/condo/services/broadcaster.js +26 -0
- data/app/assets/javascripts/condo/services/uploader.js +302 -0
- data/app/assets/javascripts/core/core.js +4 -0
- data/app/assets/javascripts/core/services/1-safe-apply.js +17 -0
- data/app/assets/javascripts/core/services/2-messaging.js +171 -0
- data/lib/condo.rb +269 -269
- data/lib/condo/configuration.rb +137 -139
- data/lib/condo/errors.rb +8 -8
- data/lib/condo/strata/amazon_s3.rb +301 -301
- data/lib/condo/strata/google_cloud_storage.rb +315 -314
- data/lib/condo/strata/rackspace_cloud_files.rb +245 -223
- data/lib/condo/version.rb +1 -1
- metadata +21 -44
- data/app/assets/javascripts/condo/broadcaster.js +0 -60
- data/app/assets/javascripts/condo/controller.js +0 -194
- data/app/assets/javascripts/condo/uploader.js +0 -310
- data/test/dummy/db/test.sqlite3 +0 -0
- 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 => :
|
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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
@options[:
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
#
|
76
|
-
#
|
77
|
-
|
78
|
-
|
79
|
-
options
|
80
|
-
|
81
|
-
:
|
82
|
-
:
|
83
|
-
:
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
{
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
def
|
190
|
-
|
191
|
-
#
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
#
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
#
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
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
|
+
|