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
@@ -1,26 +0,0 @@
1
- /**
2
- * CoTag Condo Amazon S3 Strategy
3
- * Direct to cloud resumable uploads for Google Cloud Storage
4
- *
5
- * Copyright (c) 2012 CoTag Media.
6
- *
7
- * @author Stephen von Takach <steve@cotag.me>
8
- * @copyright 2012 cotag.me
9
- *
10
- *
11
- * References:
12
- * *
13
- *
14
- **/
15
-
16
-
17
- (function(angular, undefined) {
18
- 'use strict';
19
-
20
- angular.module('Condo').
21
-
22
- factory('Condo.Broadcast', ['$channel', function($channel) {
23
- return $channel.openChannel('once unique');
24
- }]);
25
-
26
- })(angular);
@@ -1,302 +0,0 @@
1
- /**
2
- * CoTag Condo
3
- * Direct to cloud resumable uploads
4
- *
5
- * Copyright (c) 2012 CoTag Media.
6
- *
7
- * @author Stephen von Takach <steve@cotag.me>
8
- * @copyright 2012 cotag.me
9
- *
10
- *
11
- * References:
12
- * * http://docs.angularjs.org/api/ng.$http
13
- * * http://docs.angularjs.org/api/ng.$q
14
- *
15
- **/
16
-
17
-
18
- (function(jQuery, angular, undefined) { // jQuery required for progress event
19
- 'use strict';
20
-
21
- angular.module('Condo').
22
-
23
- //
24
- // Implements the Condo API
25
- //
26
- provider('Condo.Api', function() {
27
-
28
- var residencies = {};
29
-
30
- this.register = function(provider_name, dependency) {
31
- residencies[provider_name] = dependency;
32
- };
33
-
34
-
35
- this.$get = ['$http', '$rootScope', '$q', '$injector', function($http, $rootScope, $q, $injector) {
36
- var token = $('meta[name="csrf-token"]').attr('content'),
37
-
38
-
39
- condoConnection = function(api_endpoint, params) {
40
- this.endpoint = api_endpoint; // The API mounting point
41
- this.params = params; // Custom API parameters
42
-
43
- this.upload_id = null; // The current upload ID
44
- this.aborting = false; // Has the user has requested an abort?
45
- this.xhr = null; // Any active cloud file xhr requests
46
- };
47
-
48
-
49
- // Inject the handlers
50
- angular.forEach(residencies, function(value, key) {
51
- residencies[key] = $injector.get(value);
52
- });
53
-
54
-
55
- $http.defaults.headers = {};
56
- $http.defaults.headers['common'] = {'X-Requested-With': 'XMLHttpRequest'};
57
- $http.defaults.headers['post'] = {'X-CSRF-Token': token};
58
- $http.defaults.headers['put'] = {'X-CSRF-Token': token};
59
- $http.defaults.headers['delete'] = {'X-CSRF-Token': token};
60
-
61
- condoConnection.prototype = {
62
-
63
-
64
- //
65
- // Creates an entry in the database for the requested file and returns the upload signature
66
- // If an entry already exists it returns a parts request signature for resumable uploads
67
- //
68
- create: function(options) { // file_id: 123, options: {}
69
- var self = this;
70
- options = options || {};
71
- this.aborting = false;
72
-
73
- if(!!options['file_id'])
74
- this.params['file_id'] = options['file_id'];
75
-
76
- if(!!options['parameters'])
77
- this.params['parameters'] = options['parameters']; // We may be requesting the next set of parts
78
-
79
- return $http({
80
- method: 'POST',
81
- url: this.endpoint,
82
- params: this.params
83
- }).then(function(result){
84
- result = result.data;
85
- self.upload_id = result.upload_id; // Extract the upload id from the results
86
-
87
- if (!self.aborting)
88
- return result;
89
- else
90
- return $q.reject(undefined);
91
- }, function(reason) {
92
- return $q.reject('upload error');
93
- });
94
- },
95
-
96
-
97
- //
98
- // This requests a chunk signature
99
- // Only used for resumable uploads
100
- //
101
- edit: function(part_number, part_id) {
102
- var self = this;
103
- this.aborting = false;
104
-
105
- return $http({
106
- method: 'GET',
107
- url: this.endpoint + '/' + this.upload_id + '/edit',
108
- params: {
109
- part: part_number,
110
- file_id: part_id
111
- }
112
- }).then(function(result){
113
- if (!self.aborting)
114
- return result.data;
115
- else
116
- return $q.reject(undefined);
117
- }, function(reason) {
118
- return $q.reject('upload error');
119
- });
120
- },
121
-
122
-
123
- //
124
- // If resumable id is present the upload is updated
125
- // Otherwise the upload deemed complete
126
- //
127
- update: function(params) { // optional parameters (resumable_id, file_id and part)
128
- var self = this;
129
-
130
- this.aborting = false;
131
- params = params || {};
132
-
133
- return $http({
134
- method: 'PUT',
135
- url: this.endpoint + '/' + this.upload_id,
136
- params: params
137
- }).then(function(result){
138
- if (!self.aborting)
139
- return result.data;
140
- else
141
- return $q.reject(undefined);
142
- }, function(reason) {
143
- if (reason.status == 401 && params.resumable_id == undefined) {
144
- return ''; // User may have paused upload as put was being sent. We should let this through just to update the UI
145
- } else
146
- return $q.reject('upload error');
147
- });
148
- },
149
-
150
-
151
- //
152
- // Cancels a resumable upload
153
- // The actual destruction of the file is handled on the server side as we can't trust the client to do this
154
- // We don't care if this succeeds as the back-end will destroy the file eventually anyway.
155
- //
156
- destroy: function() {
157
- return $http({
158
- method: 'DELETE',
159
- url: this.endpoint + '/' + this.upload_id
160
- });
161
- },
162
-
163
-
164
-
165
- //
166
- // Provides a promise for any request this is what communicated with the cloud storage servers
167
- //
168
- process_request: function(signature, progress_callback) {
169
- var self = this,
170
- result = $q.defer(),
171
- params = {
172
- url: signature.signature.url,
173
- type: signature.signature.verb,
174
- headers: signature.signature.headers,
175
- processData: false,
176
- success: function(response, textStatus, jqXHR) {
177
- self.xhr = null;
178
- result.resolve([response, jqXHR]);
179
- },
180
- error: function(jqXHR, textStatus, errorThrown) {
181
- if(jqXHR.status === signature.expected) {
182
- self.xhr = null;
183
- result.resolve([errorThrown, jqXHR]);
184
- } else {
185
- self.xhr = null;
186
- if (!self.aborting)
187
- result.reject('upload error');
188
- else
189
- result.reject(undefined);
190
- }
191
- },
192
- complete: function(jqXHR, textStatus) {
193
- if(!$rootScope.$$phase) {
194
- $rootScope.$apply(); // This triggers the promise response
195
- }
196
- }
197
- };
198
-
199
- this.aborting = false;
200
-
201
- if (!!self.xhr) {
202
- result.reject('request in progress'); // This is awesome
203
- return result.promise;
204
- }
205
-
206
- if(!!signature.data){
207
- params['data'] = signature.data;
208
- }
209
-
210
- if(!!progress_callback) {
211
- params['xhr'] = function() {
212
- var xhr = jQuery.ajaxSettings.xhr();
213
- if(!!xhr.upload){
214
- xhr.upload.addEventListener('progress', function(e) {
215
- if (e.lengthComputable) {
216
- var phase = $rootScope.$$phase;
217
- if(phase == '$apply' || phase == '$digest') {
218
- progress_callback(e.loaded);
219
- } else {
220
- $rootScope.$apply(function(){
221
- progress_callback(e.loaded);
222
- });
223
- }
224
- }
225
- }, false);
226
- }
227
- return xhr;
228
- };
229
- }
230
-
231
- this.xhr = jQuery.ajax(params);
232
-
233
- return result.promise;
234
- },
235
-
236
-
237
- //
238
- // Will trigger the error call-back of the xhr object
239
- //
240
- abort: function() {
241
- this.aborting = true;
242
- if(!!this.xhr) {
243
- this.xhr.abort();
244
- }
245
- }
246
- };
247
-
248
- return {
249
- //
250
- // Used to determine what upload strategy to use (Amazon, Google, etc)
251
- //
252
- check_provider: function(api_endpoint, the_file, params) {
253
- params = params || {};
254
- params['file_size'] = the_file.size;
255
- params['file_name'] = the_file.name;
256
-
257
- if(!!the_file.dir_path)
258
- params['file_path'] = the_file.dir_path;
259
-
260
- return $http({
261
- method: 'GET',
262
- url: api_endpoint + '/new',
263
- params: params
264
- }).then(function(result){
265
- if(!!residencies[result.data.residence]) {
266
-
267
- var api = new condoConnection(api_endpoint, params);
268
-
269
- //
270
- // TODO:: Check if a file is already in the list and reject if it is
271
- //
272
- return residencies[result.data.residence].new_upload(api, the_file); // return the instantiated provider
273
-
274
- } else {
275
- return $q.reject({
276
- type: 'error',
277
- number: 0,
278
- file: the_file
279
- });
280
- }
281
- }, function(reason) {
282
- if(reason.status == 406) {
283
- return $q.reject({
284
- type: 'warn',
285
- number: 0,
286
- details: reason.data,
287
- file: the_file
288
- });
289
- } else {
290
- return $q.reject({
291
- type: 'warn',
292
- number: 1,
293
- file: the_file
294
- });
295
- }
296
- });
297
- }
298
- };
299
- }];
300
- });
301
-
302
- })(jQuery, angular);
@@ -1,4 +0,0 @@
1
- //
2
- // Defines our core module
3
- //
4
- angular.module('Core', []);
@@ -1,17 +0,0 @@
1
-
2
- (function(angular, undefined) {
3
- 'use strict';
4
-
5
- angular.module('Core').
6
- service('$safeApply', function() {
7
- this.do = function(scope, fn) {
8
- var phase = scope.$root.$$phase;
9
- if(phase == '$apply' || phase == '$digest') {
10
- fn();
11
- } else {
12
- scope.$apply(fn);
13
- }
14
- };
15
- });
16
-
17
- })(angular);
@@ -1,171 +0,0 @@
1
- /**
2
- * Core Messaging library
3
- * Provides the core wrapper for application wide messaging and signalling
4
- *
5
- * Copyright (c) 2013 CoTag Media.
6
- *
7
- * @author Stephen von Takach <steve@cotag.me>
8
- * @copyright 2013 cotag.me
9
- *
10
- *
11
- * References:
12
- * * http://www.gridlinked.info/angularJS/modules/MessagingServices.js
13
- *
14
- *
15
- **/
16
-
17
- (function(angular, undefined) {
18
- 'use strict';
19
-
20
- angular.module('Core').
21
- //
22
- //
23
- // Wrapper for jQuery Callbacks that provides a constructor for building
24
- // application specific message channels
25
- //
26
- // e.g.
27
- // factory('MyApp.Channel', ['Channel', function(Channel) {
28
- // return Channel.openChannel('once memory unique stopOnFalse'); // settings are optional
29
- // }]);
30
- //
31
- // then in a controller / directive somewhere:
32
- // controller('MyApp.Cntrl', ['$scope', 'MyApp.Channel', function($scope, channel) {
33
- // channel.subscribe(function(value) { $scope.update = value; });
34
- // }
35
- //
36
- //
37
- factory('$channel', ['$rootScope', '$safeApply', function($rootScope, safeApply) {
38
- var getChannel = function(settings) {
39
- var callback = angular.element.Callbacks(settings);
40
- return {
41
- publish: function() {
42
- var args = arguments; // Curry the arguments
43
- safeApply.do($rootScope, function() {
44
- callback.fire.apply(callback, args);
45
- });
46
- },
47
- subscribe: callback.add,
48
- unsubscribe: callback.remove,
49
- has: callback.has,
50
- empty: callback.empty
51
- };
52
- };
53
-
54
- return {
55
- openChannel: getChannel
56
- };
57
- }]).
58
-
59
-
60
- //
61
- //
62
- // Wrapper for jQuery Callbacks that provides a constructor for building
63
- // application specific messaging factories
64
- //
65
- // e.g.
66
- // factory('MyApp.Messenger', ['Spectrum', function(Spectrum) {
67
- // return Spectrum.newSpectrum('once memory unique stopOnFalse'); // settings are optional
68
- // }]);
69
- //
70
- // then in a controller / directive somewhere:
71
- // controller('MyApp.Cntrl', ['$scope', 'MyApp.Messenger', function($scope, messages) {
72
- // var channel = messages.openChannel('controllers');
73
- // channel.subscribe(function(value) { $scope.update = value; });
74
- // }
75
- //
76
- //
77
- factory('$spectrum', ['$channel', function(Channel) {
78
-
79
- var buildSpectrum = function(settings) {
80
- var channels = {},
81
-
82
- //
83
- // Creates or returns a reference to a channel in the spectrum
84
- //
85
- openChannel = function(name) {
86
- var channel = name && channels[name],
87
- callback;
88
-
89
- if (!channel) {
90
- channel = {
91
- access: Channel.openChannel(settings),
92
- count: 0
93
- };
94
-
95
- channels[name] = channel;
96
- }
97
-
98
- return channel;
99
- }, // end openChannel
100
-
101
- //
102
- // Deletes channels that are no longer in use
103
- //
104
- closeChannel = function(name) {
105
- delete channels[name];
106
- return 0;
107
- },
108
-
109
- channelList = function() {
110
- return Object.keys(channels);
111
- },
112
-
113
- subscribeTo = function(name, callback) {
114
- var channel = channels[name] || openChannel(name);
115
- if(!channel.access.has(callback)) {
116
- channel.access.subscribe(callback);
117
- channel.count += 1;
118
- }
119
- return channel.count;
120
- },
121
-
122
- subscribedTo = function(name) {
123
- return !channels[name] ? 0 : channels[name].count;
124
- },
125
-
126
- unsubscribeFrom = function(name, callback) {
127
- var channel = channels[name];
128
-
129
- if (!!channel) {
130
- if(callback === undefined) {
131
- return closeChannel(name);
132
- } else if (channel.access.has(callback)) {
133
- if (channel.count > 1) {
134
- channel.access.unsubscribe(callback);
135
- channel.count -= 1;
136
- } else {
137
- return closeChannel(name);
138
- }
139
- }
140
- return channel.count;
141
- }
142
- return 0;
143
- },
144
-
145
- publishTo = function(name) {
146
- var channel = channels[name];
147
-
148
- if (!!channel) {
149
- channel.access.publish.apply(channel.access, Array.prototype.slice.call( arguments, 1 ));
150
- } else if (settings.match(/memory/i)) {
151
- channel = openChannel(name);
152
- channel.access.publish.apply(channel.access, Array.prototype.slice.call( arguments, 1 ));
153
- }
154
- };
155
-
156
- return {
157
- channelList: channelList,
158
- subscribe: subscribeTo,
159
- subscriptions: subscribedTo,
160
- unsubscribe: unsubscribeFrom,
161
- publish: publishTo
162
- };
163
- }; // End buildSpectrum
164
-
165
- return {
166
- newSpectrum: buildSpectrum
167
- };
168
- }]);
169
-
170
-
171
- })(angular);