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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/lib/refile.rb +252 -27
  3. data/lib/refile/app.rb +55 -14
  4. data/lib/refile/attacher.rb +39 -40
  5. data/lib/refile/attachment.rb +28 -13
  6. data/lib/refile/attachment/active_record.rb +90 -1
  7. data/lib/refile/attachment_definition.rb +47 -0
  8. data/lib/refile/backend/s3.rb +1 -147
  9. data/lib/refile/backend_macros.rb +13 -5
  10. data/lib/refile/custom_logger.rb +3 -1
  11. data/lib/refile/file.rb +9 -0
  12. data/lib/refile/image_processing.rb +1 -143
  13. data/lib/refile/rails.rb +30 -0
  14. data/lib/refile/rails/attachment_helper.rb +27 -16
  15. data/lib/refile/signature.rb +5 -0
  16. data/lib/refile/simple_form.rb +17 -0
  17. data/lib/refile/version.rb +1 -1
  18. data/spec/refile/active_record_helper.rb +11 -0
  19. data/spec/refile/app_spec.rb +197 -20
  20. data/spec/refile/attachment/active_record_spec.rb +298 -1
  21. data/spec/refile/attachment_helper_spec.rb +39 -0
  22. data/spec/refile/attachment_spec.rb +53 -5
  23. data/spec/refile/backend_examples.rb +13 -2
  24. data/spec/refile/backend_macros_spec.rb +27 -6
  25. data/spec/refile/custom_logger_spec.rb +2 -3
  26. data/spec/refile/features/direct_upload_spec.rb +18 -0
  27. data/spec/refile/features/multiple_upload_spec.rb +122 -0
  28. data/spec/refile/features/normal_upload_spec.rb +5 -3
  29. data/spec/refile/features/presigned_upload_spec.rb +4 -0
  30. data/spec/refile/features/simple_form_spec.rb +8 -0
  31. data/spec/refile/fixtures/monkey.txt +1 -0
  32. data/spec/refile/fixtures/world.txt +1 -0
  33. data/spec/refile/spec_helper.rb +21 -11
  34. data/spec/refile_spec.rb +253 -24
  35. metadata +12 -303
  36. data/.gitignore +0 -27
  37. data/.rspec +0 -2
  38. data/.rubocop.yml +0 -68
  39. data/.travis.yml +0 -21
  40. data/.yardopts +0 -1
  41. data/CONTRIBUTING.md +0 -33
  42. data/Gemfile +0 -3
  43. data/History.md +0 -96
  44. data/LICENSE.txt +0 -22
  45. data/README.md +0 -651
  46. data/Rakefile +0 -19
  47. data/app/assets/javascripts/refile.js +0 -63
  48. data/config.ru +0 -8
  49. data/config/locales/en.yml +0 -8
  50. data/config/routes.rb +0 -5
  51. data/refile.gemspec +0 -42
  52. data/spec/refile/backend/s3_spec.rb +0 -11
  53. data/spec/refile/test_app.rb +0 -65
  54. data/spec/refile/test_app/app/assets/javascripts/application.js +0 -42
  55. data/spec/refile/test_app/app/controllers/application_controller.rb +0 -2
  56. data/spec/refile/test_app/app/controllers/direct_posts_controller.rb +0 -15
  57. data/spec/refile/test_app/app/controllers/home_controller.rb +0 -4
  58. data/spec/refile/test_app/app/controllers/normal_posts_controller.rb +0 -48
  59. data/spec/refile/test_app/app/controllers/presigned_posts_controller.rb +0 -31
  60. data/spec/refile/test_app/app/models/post.rb +0 -5
  61. data/spec/refile/test_app/app/views/direct_posts/new.html.erb +0 -20
  62. data/spec/refile/test_app/app/views/home/index.html.erb +0 -1
  63. data/spec/refile/test_app/app/views/layouts/application.html.erb +0 -14
  64. data/spec/refile/test_app/app/views/normal_posts/_form.html.erb +0 -28
  65. data/spec/refile/test_app/app/views/normal_posts/edit.html.erb +0 -1
  66. data/spec/refile/test_app/app/views/normal_posts/index.html +0 -5
  67. data/spec/refile/test_app/app/views/normal_posts/new.html.erb +0 -1
  68. data/spec/refile/test_app/app/views/normal_posts/show.html.erb +0 -19
  69. data/spec/refile/test_app/app/views/presigned_posts/new.html.erb +0 -16
  70. data/spec/refile/test_app/config/database.yml +0 -7
  71. data/spec/refile/test_app/config/routes.rb +0 -17
  72. 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: e988d5663673fd11c87f292eb3f2d31c89a454b2
4
- data.tar.gz: e6433070cb25ab59bd86f45db9b23a3fe4e69cfb
3
+ metadata.gz: 89c063ad7af052e375f5850f3dd6ab903f242015
4
+ data.tar.gz: a3d2eaedc248aea3daec5e59002cab689b593d89
5
5
  SHA512:
6
- metadata.gz: 66ef9d49c14cdd58b05f28bbdcc065e5e186b5814ef1b24a62c947b6c3570de32f37377a9780ebe0a601b6f0c2aad70b43193f1d589ed760b14e7ab9316bae7e
7
- data.tar.gz: 64ce5f77c87292698c54fafb2d791d97c264611a4787fd839d3953e3e824f67a8b7d797237ab7a4f6a3922d2a20d4b5439ecc06d37133032e89988e6517fb3c8
6
+ metadata.gz: 07df0ac320e30fdf85aad47e82fd2306b0a2d33d03039647b5e3343d0fdc127e8234fad15b6e3a6a586d9cbe5bfed4bea47aaf31f659895bf5ab7eb8a98e9217
7
+ data.tar.gz: 97a0771976c4f6ef7a5e3cb7446d2e6e7797adb635fe3a47237e7246213a2b1c693365a832dfb31c3efd3257f08263df08be1d05c319b2a09b79e8e91289f949
@@ -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. It is strongly
33
- # recommended to run Refile behind a CDN and to set this to the hostname of
34
- # the CDN distribution. A protocol relative URL is recommended for this
35
- # value.
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 :host
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 :direct_upload
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 methods.
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
- # Generate a URL to an attachment. This method receives an instance of a
205
- # class which has used the {Refile::Attachment#attachment} macro to
206
- # generate an attachment column, and the name of this column, and based on
207
- # this generates a URL to a {Refile::App}.
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.host}, which is useful for serving all
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, prefix: nil, filename: nil, format: nil, host: nil)
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
- backend_name = Refile.backends.key(file.backend)
391
+ file_url(file, *args, host: host, prefix: prefix, filename: filename, format: format)
392
+ end
245
393
 
246
- filename = Rack::Utils.escape(filename)
247
- filename << "." << format.to_s if format
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
- uri = URI(host.to_s)
250
- uri.path = ::File.join("", *prefix, backend_name, *args.map(&:to_s), file.id.to_s, filename)
251
- uri.to_s
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.direct_upload = ["cache"]
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])
@@ -32,23 +32,33 @@ module Refile
32
32
  end
33
33
  end
34
34
 
35
- get "/:backend/:id/:filename" do
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 Refile.direct_upload.include?(params[:backend])
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
- backend = Refile.backends[params[:backend]]
104
- unless backend
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
- processor = Refile.processors[params[:processor]]
122
- unless processor
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