diff --git a/lib/volumen/admin_routes.rb b/lib/volumen/admin_routes.rb index f849da5..5d1708e 100644 --- a/lib/volumen/admin_routes.rb +++ b/lib/volumen/admin_routes.rb @@ -88,6 +88,10 @@ module Volumen upload = params["file"] halt(400, json("error" => "no_file")) unless upload.is_a?(Hash) && upload[:tempfile] + if upload[:tempfile].size > Server::MAX_UPLOAD_BYTES + halt(413, json("error" => "file_too_large", "max_bytes" => Server::MAX_UPLOAD_BYTES)) + end + json("url" => store.store_upload(upload[:filename], upload[:tempfile])) end diff --git a/lib/volumen/server.rb b/lib/volumen/server.rb index 48db326..8d252dd 100644 --- a/lib/volumen/server.rb +++ b/lib/volumen/server.rb @@ -17,6 +17,7 @@ module Volumen class Server < Sinatra::Base MAX_LOGIN_ATTEMPTS = 10 LOGIN_WINDOW = 60 # seconds + MAX_UPLOAD_BYTES = 10 * 1024 * 1024 # 10 MB SLUG_REGEX = /\A[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?\z/ register ApiRoutes diff --git a/test/admin_test.rb b/test/admin_test.rb index 7f1531a..9fe2c2e 100644 --- a/test/admin_test.rb +++ b/test/admin_test.rb @@ -124,6 +124,19 @@ class AdminTest < Minitest::Test assert_equal 403, last_response.status end + def test_upload_rejects_file_too_large + login + get "/admin/posts/new" + token = csrf(last_response.body) + big_path = File.join(@dir, "big.png") + File.binwrite(big_path, "X" * (Volumen::Server::MAX_UPLOAD_BYTES + 1)) + post "/admin/uploads", + "_csrf" => token, + "file" => Rack::Test::UploadedFile.new(big_path, "image/png") + assert_equal 413, last_response.status + assert_equal "file_too_large", JSON.parse(last_response.body)["error"] + end + def test_image_upload_and_serving login get "/admin/posts/new"