refile 0.5.5 → 0.6.0
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 +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
|