refile 0.5.5 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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