diff --git a/app.rb b/app.rb index 8fea9a80..c0686d1a 100644 --- a/app.rb +++ b/app.rb @@ -13,6 +13,7 @@ helpers Rack::Recaptcha::Helpers before do if request.path.match(/^\/api\//i) + @api = true content_type :json else content_type :html, 'charset' => 'utf-8' @@ -34,6 +35,14 @@ error do env['sinatra.error'].backtrace.join("\n") }) + if @api + halt 500, { + result: 'error', + error_type: 'server_error', + message: 'there has been an unknown server error, please try again later' + }.to_json + end + slim :'error' end @@ -560,10 +569,12 @@ post '/api/upload' do files << {filename: k.to_s, tempfile: v[:tempfile]} end + api_error 'missing_files', 'you must provide files to upload' if files.empty? + uploaded_size = files.collect {|f| f[:tempfile].size}.inject{|sum,x| sum + x } if (uploaded_size + current_site.total_space) > Site::MAX_SPACE - api_error 'too_large', 'files are too large to fit in your space, try uploading less (or smaller) files' + api_error 'too_large', 'files are too large to fit in your space, try uploading smaller (or less) files' end files.each do |file| @@ -576,6 +587,8 @@ post '/api/upload' do current_site.store_file file[:filename], file[:tempfile] end + current_site.increment_changed_count + api_success 'your file(s) have been successfully uploaded' end @@ -636,20 +649,22 @@ def require_api_credentials begin user, pass = Base64.decode64(auth.match(/Basic (.+)/)[1]).split(':') rescue - api_error 'invalid_auth', 'could not parse your auth credentials - please check your username and password' + api_error_invalid_auth end if Site.valid_login? user, pass site = Site[username: user] if site.nil? || site.is_banned - api_error 'invalid_credentials', 'invalid credentials - please check your username and password' + api_error_invalid_auth end session[:id] = site.id else - api_error 'invalid_credentials', 'invalid credentials - please check your username and password' + api_error_invalid_auth end + else + api_error_invalid_auth end end @@ -661,6 +676,10 @@ def api_error(error_type, message) halt({result: 'error', error_type: error_type, message: message}.to_json) end +def api_error_invalid_auth + api_error 'invalid_auth', 'invalid credentials - please check your username and password' +end + def api_not_found api_error 'not_found', 'the requested api call does not exist' end \ No newline at end of file diff --git a/tests/api_tests.rb b/tests/api_tests.rb new file mode 100644 index 00000000..56c1a59b --- /dev/null +++ b/tests/api_tests.rb @@ -0,0 +1,77 @@ +require_relative './environment.rb' +require 'rack/test' + +include Rack::Test::Methods + +def app + Sinatra::Application +end + +describe 'api upload' do + def create_site + site_attr = Fabricate.attributes_for :site + @site = Site.create site_attr + @user = site_attr[:username] + @pass = site_attr[:password] + end + + it 'fails with no auth' do + post '/api/upload' + res[:result].must_equal 'error' + res[:error_type].must_equal 'invalid_auth' + end + + it 'fails for bad auth' do + basic_authorize 'username', 'password' + post '/api/upload' + res[:error_type].must_equal 'invalid_auth' + end + + it 'fails with missing files' do + create_site + basic_authorize @user, @pass + post '/api/upload' + res[:error_type].must_equal 'missing_files' + end + + it 'fails for invalid files' do + create_site + basic_authorize @user, @pass + post '/api/upload', { + 'test.jpg' => Rack::Test::UploadedFile.new('./tests/files/test.jpg', 'image/jpeg'), + 'nord.avi' => Rack::Test::UploadedFile.new('./tests/files/flowercrime.wav', 'image/jpeg') + } + res[:error_type].must_equal 'invalid_file_type' + site_file_exists?('test.jpg').must_equal false + site_file_exists?('nord.avi').must_equal false + end + + it 'succeeds with single file' do + create_site + basic_authorize @user, @pass + post '/api/upload', 'test.jpg' => Rack::Test::UploadedFile.new('./tests/files/test.jpg', 'image/jpeg') + res[:result].must_equal 'success' + site_file_exists?('test.jpg').must_equal true + end + + it 'succeeds with two files' do + create_site + basic_authorize @user, @pass + post '/api/upload', { + 'test.jpg' => Rack::Test::UploadedFile.new('./tests/files/test.jpg', 'image/jpeg'), + 'test2.jpg' => Rack::Test::UploadedFile.new('./tests/files/test.jpg', 'image/jpeg') + } + res[:result].must_equal 'success' + site_file_exists?('test.jpg').must_equal true + site_file_exists?('test2.jpg').must_equal true + end +end + +def site_file_exists?(file) + File.exist?(@site.file_path('test.jpg')) +end + +def res + JSON.parse last_response.body, symbolize_names: true +end + diff --git a/tests/files/flowercrime.wav b/tests/files/flowercrime.wav new file mode 100644 index 00000000..75347e4d Binary files /dev/null and b/tests/files/flowercrime.wav differ diff --git a/tests/files/test.jpg b/tests/files/test.jpg new file mode 100644 index 00000000..507b769b Binary files /dev/null and b/tests/files/test.jpg differ