refile 0.5.5 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/refile.rb +252 -27
- data/lib/refile/app.rb +55 -14
- data/lib/refile/attacher.rb +39 -40
- data/lib/refile/attachment.rb +28 -13
- data/lib/refile/attachment/active_record.rb +90 -1
- data/lib/refile/attachment_definition.rb +47 -0
- data/lib/refile/backend/s3.rb +1 -147
- data/lib/refile/backend_macros.rb +13 -5
- data/lib/refile/custom_logger.rb +3 -1
- data/lib/refile/file.rb +9 -0
- data/lib/refile/image_processing.rb +1 -143
- data/lib/refile/rails.rb +30 -0
- data/lib/refile/rails/attachment_helper.rb +27 -16
- data/lib/refile/signature.rb +5 -0
- data/lib/refile/simple_form.rb +17 -0
- data/lib/refile/version.rb +1 -1
- data/spec/refile/active_record_helper.rb +11 -0
- data/spec/refile/app_spec.rb +197 -20
- data/spec/refile/attachment/active_record_spec.rb +298 -1
- data/spec/refile/attachment_helper_spec.rb +39 -0
- data/spec/refile/attachment_spec.rb +53 -5
- data/spec/refile/backend_examples.rb +13 -2
- data/spec/refile/backend_macros_spec.rb +27 -6
- data/spec/refile/custom_logger_spec.rb +2 -3
- data/spec/refile/features/direct_upload_spec.rb +18 -0
- data/spec/refile/features/multiple_upload_spec.rb +122 -0
- data/spec/refile/features/normal_upload_spec.rb +5 -3
- data/spec/refile/features/presigned_upload_spec.rb +4 -0
- data/spec/refile/features/simple_form_spec.rb +8 -0
- data/spec/refile/fixtures/monkey.txt +1 -0
- data/spec/refile/fixtures/world.txt +1 -0
- data/spec/refile/spec_helper.rb +21 -11
- data/spec/refile_spec.rb +253 -24
- metadata +12 -303
- data/.gitignore +0 -27
- data/.rspec +0 -2
- data/.rubocop.yml +0 -68
- data/.travis.yml +0 -21
- data/.yardopts +0 -1
- data/CONTRIBUTING.md +0 -33
- data/Gemfile +0 -3
- data/History.md +0 -96
- data/LICENSE.txt +0 -22
- data/README.md +0 -651
- data/Rakefile +0 -19
- data/app/assets/javascripts/refile.js +0 -63
- data/config.ru +0 -8
- data/config/locales/en.yml +0 -8
- data/config/routes.rb +0 -5
- data/refile.gemspec +0 -42
- data/spec/refile/backend/s3_spec.rb +0 -11
- data/spec/refile/test_app.rb +0 -65
- data/spec/refile/test_app/app/assets/javascripts/application.js +0 -42
- data/spec/refile/test_app/app/controllers/application_controller.rb +0 -2
- data/spec/refile/test_app/app/controllers/direct_posts_controller.rb +0 -15
- data/spec/refile/test_app/app/controllers/home_controller.rb +0 -4
- data/spec/refile/test_app/app/controllers/normal_posts_controller.rb +0 -48
- data/spec/refile/test_app/app/controllers/presigned_posts_controller.rb +0 -31
- data/spec/refile/test_app/app/models/post.rb +0 -5
- data/spec/refile/test_app/app/views/direct_posts/new.html.erb +0 -20
- data/spec/refile/test_app/app/views/home/index.html.erb +0 -1
- data/spec/refile/test_app/app/views/layouts/application.html.erb +0 -14
- data/spec/refile/test_app/app/views/normal_posts/_form.html.erb +0 -28
- data/spec/refile/test_app/app/views/normal_posts/edit.html.erb +0 -1
- data/spec/refile/test_app/app/views/normal_posts/index.html +0 -5
- data/spec/refile/test_app/app/views/normal_posts/new.html.erb +0 -1
- data/spec/refile/test_app/app/views/normal_posts/show.html.erb +0 -19
- data/spec/refile/test_app/app/views/presigned_posts/new.html.erb +0 -16
- data/spec/refile/test_app/config/database.yml +0 -7
- data/spec/refile/test_app/config/routes.rb +0 -17
- data/spec/refile/test_app/public/favicon.ico +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89c063ad7af052e375f5850f3dd6ab903f242015
|
4
|
+
data.tar.gz: a3d2eaedc248aea3daec5e59002cab689b593d89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 07df0ac320e30fdf85aad47e82fd2306b0a2d33d03039647b5e3343d0fdc127e8234fad15b6e3a6a586d9cbe5bfed4bea47aaf31f659895bf5ab7eb8a98e9217
|
7
|
+
data.tar.gz: 97a0771976c4f6ef7a5e3cb7446d2e6e7797adb635fe3a47237e7246213a2b1c693365a832dfb31c3efd3257f08263df08be1d05c319b2a09b79e8e91289f949
|
data/lib/refile.rb
CHANGED
@@ -12,6 +12,12 @@ module Refile
|
|
12
12
|
# @api private
|
13
13
|
class InvalidID < Invalid; end
|
14
14
|
|
15
|
+
# @api private
|
16
|
+
class InvalidMaxSize < Invalid; end
|
17
|
+
|
18
|
+
# @api private
|
19
|
+
class InvalidFile < Invalid; end
|
20
|
+
|
15
21
|
# @api private
|
16
22
|
class Confirm < StandardError
|
17
23
|
def message
|
@@ -28,22 +34,65 @@ module Refile
|
|
28
34
|
# @return [Refile::App, nil]
|
29
35
|
attr_accessor :app
|
30
36
|
|
37
|
+
# The host name of a CDN distribution that the Rack application can be
|
38
|
+
# reached at. If not set, Refile will use an absolute URL without hostname.
|
39
|
+
# It is strongly recommended to run Refile behind a CDN and to set this to
|
40
|
+
# the hostname of the CDN distribution.
|
41
|
+
#
|
42
|
+
# The `cdn_host` setting is used when retrieving files, but not when
|
43
|
+
# uploading new files, since uploads should normally not go through the
|
44
|
+
# CDN.
|
45
|
+
#
|
46
|
+
# A protocol relative URL is recommended for this value.
|
47
|
+
#
|
48
|
+
# @return [String, nil]
|
49
|
+
attr_accessor :cdn_host
|
50
|
+
|
31
51
|
# The host name that the Rack application can be reached at. If not set,
|
32
|
-
# Refile will use an absolute URL without hostname.
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
52
|
+
# Refile will use an absolute URL without hostname. You should only change
|
53
|
+
# this setting if you are running the Refile app on a different domain
|
54
|
+
# than your main application.
|
55
|
+
#
|
56
|
+
# If you are simply running the Refile app behind a CDN you'll want to
|
57
|
+
# change {Refile.cdn_host} instead.
|
58
|
+
#
|
59
|
+
# The difference between {Refile.app_host} and {Refile.cdn_host} is that the
|
60
|
+
# latter only affects URLs generated by {Refile.file_url} and the
|
61
|
+
# {Refile::AttachmentHelper#attachment_url} and
|
62
|
+
# {Refile::AttachmentHelper#attachment_image_tag} helpers, whereas the
|
63
|
+
# former also affects {Refile.upload_url}, {Refile.presign_url} and the
|
64
|
+
# {Refile::AttachmentHelper#attachment_field} helper.
|
36
65
|
#
|
37
66
|
# @return [String, nil]
|
38
|
-
attr_accessor :
|
67
|
+
attr_accessor :app_host
|
68
|
+
|
69
|
+
# @deprecated use {Refile.cdn_host} instead
|
70
|
+
def host
|
71
|
+
warn "Refile.host is deprecated, please use Refile.cdn_host instead"
|
72
|
+
cdn_host
|
73
|
+
end
|
74
|
+
|
75
|
+
# @deprecated use {Refile.cdn_host} instead
|
76
|
+
def host=(host)
|
77
|
+
warn "Refile.host is deprecated, please use Refile.cdn_host instead"
|
78
|
+
self.cdn_host = host
|
79
|
+
end
|
39
80
|
|
40
81
|
# A list of names which identify backends in the global backend registry.
|
41
82
|
# The Rack application allows POST requests to only the backends specified
|
42
83
|
# in this config option. This defaults to `["cache"]`, only allowing direct
|
43
84
|
# uploads to the cache backend.
|
44
85
|
#
|
45
|
-
# @return [Array[String]]
|
46
|
-
attr_accessor :
|
86
|
+
# @return [Array[String], :all]
|
87
|
+
attr_accessor :allow_uploads_to
|
88
|
+
|
89
|
+
# A list of names which identify backends in the global backend registry.
|
90
|
+
# The Rack application allows GET requests to only the backends specified
|
91
|
+
# in this config option. This defaults to `:all`, allowing files from all
|
92
|
+
# backends to be downloaded.
|
93
|
+
#
|
94
|
+
# @return [Array[String], :all]
|
95
|
+
attr_accessor :allow_downloads_from
|
47
96
|
|
48
97
|
# Logger that should be used by rack application
|
49
98
|
#
|
@@ -75,6 +124,11 @@ module Refile
|
|
75
124
|
# @return [Boolean]
|
76
125
|
attr_accessor :automount
|
77
126
|
|
127
|
+
# Value for generating signed attachment urls to protect from DoS
|
128
|
+
#
|
129
|
+
# @return [String]
|
130
|
+
attr_accessor :secret_key
|
131
|
+
|
78
132
|
# A global registry of backends.
|
79
133
|
#
|
80
134
|
# @return [Hash{String => Backend}]
|
@@ -107,7 +161,8 @@ module Refile
|
|
107
161
|
# An IO-like object is recommended to be an instance of the `IO` class or
|
108
162
|
# one of its subclasses, like `File` or a `StringIO`, or a `Refile::File`.
|
109
163
|
# It can also be any other object which responds to `size`, `read`, `eof`?
|
110
|
-
# and `close` and mimics the behaviour of IO objects for these
|
164
|
+
# `rewind` and `close` and mimics the behaviour of IO objects for these
|
165
|
+
# methods.
|
111
166
|
#
|
112
167
|
# @example With processor class
|
113
168
|
# class Reverse
|
@@ -201,10 +256,104 @@ module Refile
|
|
201
256
|
end
|
202
257
|
end
|
203
258
|
|
204
|
-
#
|
205
|
-
#
|
206
|
-
#
|
207
|
-
#
|
259
|
+
# Generates a URL to the Refile application.
|
260
|
+
#
|
261
|
+
# The host defaults to {Refile.app_host}. You can also override the host via
|
262
|
+
# the `host` option. Normally the Refile app will not be mounted at the
|
263
|
+
# root but rather at some other path, the `prefix` option allows you to
|
264
|
+
# override this setting, and if not set it will fall back to
|
265
|
+
# {Refile.mount_point}.
|
266
|
+
#
|
267
|
+
# @example
|
268
|
+
# Refilee.app_url
|
269
|
+
#
|
270
|
+
# @example With host and prefix
|
271
|
+
# Refilee.app_url(host: "http://some.domain", prefix: "/refile")
|
272
|
+
#
|
273
|
+
# @param [String, nil] host Override the host
|
274
|
+
# @param [String, nil] prefix Adds a prefix to the URL if the application is not mounted at root
|
275
|
+
# @return [String] The generated URL
|
276
|
+
def app_url(host: nil, prefix: nil)
|
277
|
+
host ||= Refile.app_host
|
278
|
+
prefix ||= Refile.mount_point
|
279
|
+
|
280
|
+
uri = URI(host.to_s)
|
281
|
+
uri.path = prefix || "/"
|
282
|
+
uri.to_s
|
283
|
+
end
|
284
|
+
|
285
|
+
# Receives a {Refile::File} and generates a URL to it.
|
286
|
+
#
|
287
|
+
# Optionally the name of a processor and arguments to it can be appended.
|
288
|
+
#
|
289
|
+
# The `filename` option must be given.
|
290
|
+
#
|
291
|
+
# The host defaults to {Refile.cdn_host}, which is useful for serving all
|
292
|
+
# attachments from a CDN. You can also override the host via the `host`
|
293
|
+
# option.
|
294
|
+
#
|
295
|
+
# Returns `nil` if the supplied file is `nil`.
|
296
|
+
#
|
297
|
+
# @example
|
298
|
+
# Refile.file_url(Refile.store.get(id))
|
299
|
+
#
|
300
|
+
# @example With processor
|
301
|
+
# Refile.file_url(Refile.store.get(id), :image, :fill, 300, 300, format: "jpg")
|
302
|
+
#
|
303
|
+
# @param [Refile::File] file The file to generate a URL for
|
304
|
+
# @param [String] filename The filename to be appended to the URL
|
305
|
+
# @param [String, nil] format A file extension to be appended to the URL
|
306
|
+
# @param [String, nil] host Override the host
|
307
|
+
# @param [String, nil] prefix Adds a prefix to the URL if the application is not mounted at root
|
308
|
+
# @return [String, nil] The generated URL
|
309
|
+
def file_url(file, *args, host: nil, prefix: nil, filename:, format: nil)
|
310
|
+
return unless file
|
311
|
+
|
312
|
+
host ||= Refile.cdn_host
|
313
|
+
backend_name = Refile.backends.key(file.backend)
|
314
|
+
|
315
|
+
filename = Rack::Utils.escape(filename)
|
316
|
+
filename << "." << format.to_s if format
|
317
|
+
|
318
|
+
base_path = ::File.join("", backend_name, *args.map(&:to_s), file.id.to_s, filename)
|
319
|
+
|
320
|
+
::File.join(app_url(prefix: prefix, host: host), token(base_path), base_path)
|
321
|
+
end
|
322
|
+
|
323
|
+
# Receives a Refile backend and returns a URL to the Refile application
|
324
|
+
# where files can be uploaded.
|
325
|
+
#
|
326
|
+
# @example
|
327
|
+
# Refile.upload_url(Refile.store)
|
328
|
+
#
|
329
|
+
# @param [Refile::Backend] backend The backend to generate a URL for
|
330
|
+
# @param [String, nil] host Override the host
|
331
|
+
# @param [String, nil] prefix Adds a prefix to the URL if the application is not mounted at root
|
332
|
+
# @return [String] The generated URL
|
333
|
+
def upload_url(backend, host: nil, prefix: nil)
|
334
|
+
backend_name = Refile.backends.key(backend)
|
335
|
+
|
336
|
+
::File.join(app_url(host: host, prefix: prefix), backend_name)
|
337
|
+
end
|
338
|
+
|
339
|
+
# Receives a Refile backend and returns a URL to the Refile application
|
340
|
+
# where a presign object for the backend can be retrieved.
|
341
|
+
#
|
342
|
+
# @example
|
343
|
+
# Refile.upload_url(Refile.store)
|
344
|
+
#
|
345
|
+
# @param [Refile::Backend] backend The backend to generate a URL for
|
346
|
+
# @param [String, nil] host Override the host
|
347
|
+
# @param [String, nil] prefix Adds a prefix to the URL if the application is not mounted at root
|
348
|
+
# @return [String] The generated URL
|
349
|
+
def presign_url(backend, host: nil, prefix: nil)
|
350
|
+
::File.join(upload_url(backend, host: host, prefix: prefix), "presign")
|
351
|
+
end
|
352
|
+
|
353
|
+
# Generate a URL to an attachment. Receives an instance of a class which
|
354
|
+
# has used the {Refile::Attachment#attachment} macro to generate an
|
355
|
+
# attachment column, and the name of this column, and based on this
|
356
|
+
# generates a URL to a {Refile::App}.
|
208
357
|
#
|
209
358
|
# Optionally the name of a processor and arguments to it can be appended.
|
210
359
|
#
|
@@ -212,17 +361,17 @@ module Refile
|
|
212
361
|
# metadata stored in the attachment, or eventually falls back to the
|
213
362
|
# `name`.
|
214
363
|
#
|
215
|
-
# The host defaults to {Refile.
|
364
|
+
# The host defaults to {Refile.cdn_host}, which is useful for serving all
|
216
365
|
# attachments from a CDN. You can also override the host via the `host`
|
217
366
|
# option.
|
218
367
|
#
|
219
368
|
# Returns `nil` if there is no file attached.
|
220
369
|
#
|
221
370
|
# @example
|
222
|
-
# attachment_url(@post, :document)
|
371
|
+
# Refile.attachment_url(@post, :document)
|
223
372
|
#
|
224
373
|
# @example With processor
|
225
|
-
# attachment_url(@post, :image, :fill, 300, 300, format: "jpg")
|
374
|
+
# Refile.attachment_url(@post, :image, :fill, 300, 300, format: "jpg")
|
226
375
|
#
|
227
376
|
# @param [Refile::Attachment] object Instance of a class which has an attached file
|
228
377
|
# @param [Symbol] name The name of the attachment column
|
@@ -231,24 +380,98 @@ module Refile
|
|
231
380
|
# @param [String, nil] host Override the host
|
232
381
|
# @param [String, nil] prefix Adds a prefix to the URL if the application is not mounted at root
|
233
382
|
# @return [String, nil] The generated URL
|
234
|
-
def attachment_url(object, name, *args,
|
383
|
+
def attachment_url(object, name, *args, host: nil, prefix: nil, filename: nil, format: nil)
|
235
384
|
attacher = object.send(:"#{name}_attacher")
|
236
385
|
file = attacher.get
|
237
386
|
return unless file
|
238
387
|
|
239
|
-
host ||= Refile.host
|
240
|
-
prefix ||= Refile.mount_point
|
241
388
|
filename ||= attacher.basename || name.to_s
|
242
389
|
format ||= attacher.extension
|
243
390
|
|
244
|
-
|
391
|
+
file_url(file, *args, host: host, prefix: prefix, filename: filename, format: format)
|
392
|
+
end
|
245
393
|
|
246
|
-
|
247
|
-
|
394
|
+
# Receives an instance of a class which has used the
|
395
|
+
# {Refile::Attachment#attachment} macro to generate an attachment column,
|
396
|
+
# and the name of this column, and based on this generates a URL to a
|
397
|
+
# {Refile::App} where files can be uploaded.
|
398
|
+
#
|
399
|
+
# @example
|
400
|
+
# Refile.attachment_upload_url(@post, :document)
|
401
|
+
#
|
402
|
+
# @param [Refile::Attachment] object Instance of a class which has an attached file
|
403
|
+
# @param [Symbol] name The name of the attachment column
|
404
|
+
# @param [String, nil] host Override the host
|
405
|
+
# @param [String, nil] prefix Adds a prefix to the URL if the application is not mounted at root
|
406
|
+
# @return [String] The generated URL
|
407
|
+
def attachment_upload_url(object, name, host: nil, prefix: nil)
|
408
|
+
backend = object.send(:"#{name}_attachment_definition").cache
|
248
409
|
|
249
|
-
|
250
|
-
|
251
|
-
|
410
|
+
upload_url(backend, host: host, prefix: prefix)
|
411
|
+
end
|
412
|
+
|
413
|
+
# Receives an instance of a class which has used the
|
414
|
+
# {Refile::Attachment#attachment} macro to generate an attachment column,
|
415
|
+
# and the name of this column, and based on this generates a URL to a
|
416
|
+
# {Refile::App} where a presign object for the backend can be retrieved.
|
417
|
+
#
|
418
|
+
# @example
|
419
|
+
# Refile.attachment_presign_url(@post, :document)
|
420
|
+
#
|
421
|
+
# @param [Refile::Attachment] object Instance of a class which has an attached file
|
422
|
+
# @param [Symbol] name The name of the attachment column
|
423
|
+
# @param [String, nil] host Override the host
|
424
|
+
# @param [String, nil] prefix Adds a prefix to the URL if the application is not mounted at root
|
425
|
+
# @return [String] The generated URL
|
426
|
+
def attachment_presign_url(object, name, host: nil, prefix: nil)
|
427
|
+
backend = object.send(:"#{name}_attachment_definition").cache
|
428
|
+
|
429
|
+
presign_url(backend, host: host, prefix: prefix)
|
430
|
+
end
|
431
|
+
|
432
|
+
# Generate a signature for a given path concatenated with the configured secret token.
|
433
|
+
#
|
434
|
+
# Raises an error if no secret token is configured.
|
435
|
+
#
|
436
|
+
# @example
|
437
|
+
# Refile.token('/store/f5f2e4/document.pdf')
|
438
|
+
#
|
439
|
+
# @param [String] path The path to generate a token for
|
440
|
+
# @raise [RuntimeError] If {Refile.secret_key} is not set
|
441
|
+
# @return [String, nil] The generated token
|
442
|
+
def token(path)
|
443
|
+
if secret_key.nil?
|
444
|
+
error = "Refile.secret_key was not set.\n\n"
|
445
|
+
error << "Please add the following to your Refile configuration and restart your application:\n\n"
|
446
|
+
error << "```\nRefile.secret_key = '#{SecureRandom.hex(64)}'\n```\n\n"
|
447
|
+
|
448
|
+
raise error
|
449
|
+
end
|
450
|
+
|
451
|
+
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha1"), secret_key, path)
|
452
|
+
end
|
453
|
+
|
454
|
+
# Check if the given token is a valid token for the given path.
|
455
|
+
#
|
456
|
+
# @example
|
457
|
+
# Refile.valid_token?('/store/f5f2e4/document.pdf', 'abcd1234')
|
458
|
+
#
|
459
|
+
# @param [String] path The path to check validity for
|
460
|
+
# @param [String] token The token to check
|
461
|
+
# @raise [RuntimeError] If {Refile.secret_key} is not set
|
462
|
+
# @return [Boolean] Whether the token is valid
|
463
|
+
def valid_token?(path, token)
|
464
|
+
expected = Digest::SHA1.hexdigest(token(path))
|
465
|
+
actual = Digest::SHA1.hexdigest(token)
|
466
|
+
|
467
|
+
expected == actual
|
468
|
+
end
|
469
|
+
|
470
|
+
# @api private
|
471
|
+
def parse_json(data, *args)
|
472
|
+
JSON.parse(data.to_s, *args)
|
473
|
+
rescue JSON::ParserError
|
474
|
+
nil
|
252
475
|
end
|
253
476
|
end
|
254
477
|
|
@@ -256,6 +479,7 @@ module Refile
|
|
256
479
|
require "refile/signature"
|
257
480
|
require "refile/type"
|
258
481
|
require "refile/backend_macros"
|
482
|
+
require "refile/attachment_definition"
|
259
483
|
require "refile/attacher"
|
260
484
|
require "refile/attachment"
|
261
485
|
require "refile/random_hasher"
|
@@ -266,10 +490,11 @@ module Refile
|
|
266
490
|
end
|
267
491
|
|
268
492
|
Refile.configure do |config|
|
269
|
-
config.
|
493
|
+
config.allow_uploads_to = ["cache"]
|
494
|
+
config.allow_downloads_from = :all
|
270
495
|
config.allow_origin = "*"
|
271
|
-
config.logger = Logger.new(STDOUT)
|
272
|
-
config.mount_point = "attachments"
|
496
|
+
config.logger = Logger.new(STDOUT) unless ENV["RACK_ENV"] == "test"
|
497
|
+
config.mount_point = "/attachments"
|
273
498
|
config.automount = true
|
274
499
|
config.content_max_age = 60 * 60 * 24 * 365
|
275
500
|
config.types[:image] = Refile::Type.new(:image, content_type: %w[image/jpeg image/gif image/png])
|
data/lib/refile/app.rb
CHANGED
@@ -32,23 +32,33 @@ module Refile
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
|
35
|
+
# This will match all token authenticated requests
|
36
|
+
before "/:token/:backend/*" do
|
37
|
+
halt 403 unless verified?
|
38
|
+
end
|
39
|
+
|
40
|
+
get "/:token/:backend/:id/:filename" do
|
41
|
+
halt 404 unless download_allowed?
|
36
42
|
stream_file file
|
37
43
|
end
|
38
44
|
|
39
|
-
get "/:backend/:processor/:id/:file_basename.:extension" do
|
45
|
+
get "/:token/:backend/:processor/:id/:file_basename.:extension" do
|
46
|
+
halt 404 unless download_allowed?
|
40
47
|
stream_file processor.call(file, format: params[:extension])
|
41
48
|
end
|
42
49
|
|
43
|
-
get "/:backend/:processor/:id/:filename" do
|
50
|
+
get "/:token/:backend/:processor/:id/:filename" do
|
51
|
+
halt 404 unless download_allowed?
|
44
52
|
stream_file processor.call(file)
|
45
53
|
end
|
46
54
|
|
47
|
-
get "/:backend/:processor/*/:id/:file_basename.:extension" do
|
55
|
+
get "/:token/:backend/:processor/*/:id/:file_basename.:extension" do
|
56
|
+
halt 404 unless download_allowed?
|
48
57
|
stream_file processor.call(file, *params[:splat].first.split("/"), format: params[:extension])
|
49
58
|
end
|
50
59
|
|
51
|
-
get "/:backend/:processor/*/:id/:filename" do
|
60
|
+
get "/:token/:backend/:processor/*/:id/:filename" do
|
61
|
+
halt 404 unless download_allowed?
|
52
62
|
stream_file processor.call(file, *params[:splat].first.split("/"))
|
53
63
|
end
|
54
64
|
|
@@ -57,18 +67,39 @@ module Refile
|
|
57
67
|
end
|
58
68
|
|
59
69
|
post "/:backend" do
|
60
|
-
halt 404 unless
|
70
|
+
halt 404 unless upload_allowed?
|
61
71
|
tempfile = request.params.fetch("file").fetch(:tempfile)
|
62
72
|
file = backend.upload(tempfile)
|
63
73
|
content_type :json
|
64
74
|
{ id: file.id }.to_json
|
65
75
|
end
|
66
76
|
|
77
|
+
get "/:backend/presign" do
|
78
|
+
halt 404 unless upload_allowed?
|
79
|
+
content_type :json
|
80
|
+
backend.presign.to_json
|
81
|
+
end
|
82
|
+
|
67
83
|
not_found do
|
68
84
|
content_type :text
|
69
85
|
"not found"
|
70
86
|
end
|
71
87
|
|
88
|
+
error 403 do
|
89
|
+
content_type :text
|
90
|
+
"forbidden"
|
91
|
+
end
|
92
|
+
|
93
|
+
error Refile::InvalidFile do
|
94
|
+
status 400
|
95
|
+
"Upload failure error"
|
96
|
+
end
|
97
|
+
|
98
|
+
error Refile::InvalidMaxSize do
|
99
|
+
status 413
|
100
|
+
"Upload failure error"
|
101
|
+
end
|
102
|
+
|
72
103
|
error do |error_thrown|
|
73
104
|
log_error("Error -> #{error_thrown}")
|
74
105
|
error_thrown.backtrace.each do |line|
|
@@ -80,6 +111,14 @@ module Refile
|
|
80
111
|
|
81
112
|
private
|
82
113
|
|
114
|
+
def download_allowed?
|
115
|
+
Refile.allow_downloads_from == :all or Refile.allow_downloads_from.include?(params[:backend])
|
116
|
+
end
|
117
|
+
|
118
|
+
def upload_allowed?
|
119
|
+
Refile.allow_uploads_to == :all or Refile.allow_uploads_to.include?(params[:backend])
|
120
|
+
end
|
121
|
+
|
83
122
|
def logger
|
84
123
|
Refile.logger
|
85
124
|
end
|
@@ -100,12 +139,10 @@ module Refile
|
|
100
139
|
end
|
101
140
|
|
102
141
|
def backend
|
103
|
-
|
104
|
-
|
105
|
-
log_error("Could not find backend: #{params[:backend]}")
|
142
|
+
Refile.backends.fetch(params[:backend]) do |name|
|
143
|
+
log_error("Could not find backend: #{name}")
|
106
144
|
halt 404
|
107
145
|
end
|
108
|
-
backend
|
109
146
|
end
|
110
147
|
|
111
148
|
def file
|
@@ -118,16 +155,20 @@ module Refile
|
|
118
155
|
end
|
119
156
|
|
120
157
|
def processor
|
121
|
-
|
122
|
-
|
123
|
-
log_error("Could not find processor: #{params[:processor]}")
|
158
|
+
Refile.processors.fetch(params[:processor]) do |name|
|
159
|
+
log_error("Could not find processor: #{name}")
|
124
160
|
halt 404
|
125
161
|
end
|
126
|
-
processor
|
127
162
|
end
|
128
163
|
|
129
164
|
def log_error(message)
|
130
165
|
logger.error "#{self.class.name}: #{message}"
|
131
166
|
end
|
167
|
+
|
168
|
+
def verified?
|
169
|
+
base_path = request.path.gsub(::File.join(request.script_name, params[:token]), "")
|
170
|
+
|
171
|
+
Refile.valid_token?(base_path, params[:token])
|
172
|
+
end
|
132
173
|
end
|
133
174
|
end
|