An example how to protect user-uploaded data with a password in a Rails app. This example uses a custom password page.
require 'test_helper' | |
class UploadTest < ActiveSupport::TestCase | |
test 'password is optional' do | |
upload = Upload.create(password: nil) | |
assert(upload.persisted?) | |
end | |
test "password can't be too long" do | |
upload = Upload.new | |
upload.password = 'a' * (ActiveModel::SecurePassword::MAX_PASSWORD_LENGTH_ALLOWED + 1) | |
upload.save | |
assert_not(upload.persisted?) | |
upload.password = 'a' * ActiveModel::SecurePassword::MAX_PASSWORD_LENGTH_ALLOWED | |
upload.save | |
assert(upload.persisted?) | |
end | |
end |
class UploadsController < ApplicationController | |
def show | |
if upload.password_digest.nil? | |
redirect_to action: :download | |
else | |
# Render show.html.erb with the password prompt | |
end | |
end | |
def download | |
if upload.password_digest.nil? || upload.authenticate(params[:password]) | |
send_data upload.data | |
else | |
render :show | |
end | |
end | |
private | |
def upload | |
@upload ||= Upload.find(params[:id]) | |
end | |
end |
require 'test_helper' | |
class UploadsControllerTest < ActionDispatch::IntegrationTest | |
test '#show redirects to download if not password-protected' do | |
upload = Upload.create!(password: nil) | |
get upload_path(upload) | |
assert_redirected_to(download_upload_path(upload)) | |
end | |
test '#show asks for password if password-protected' do | |
upload = Upload.create!(password: '1234abcd') | |
get upload_path(upload) | |
assert_response(:success) | |
assert_select("form[action='#{download_upload_path(upload)}'][method=post]") do | |
assert_select('input[type=password][name=password]') | |
end | |
end | |
test '#download sends file if correct password provided' do | |
upload = Upload.create!(password: '1234abcd') | |
post download_upload_path(upload), params: { password: upload.password } | |
assert_response(:success) | |
assert_equal(upload.data, @response.body) | |
end | |
test '#download asks for password if incorrect password provided' do | |
upload = Upload.create!(password: '1234abcd') | |
post download_upload_path(upload), params: { password: "x#{upload.password}" } | |
assert_response(:success) | |
assert_select("form[action='#{download_upload_path(upload)}'][method=post]") | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment