Skip to content

Instantly share code, notes, and snippets.

@gregnavis gregnavis/routes.rb
Created Jan 15, 2019

Embed
What would you like to do?
An example how to protect user-uploaded data with a password in a Rails app. This example uses a custom password page.
Rails.application.routes.draw do
resources :uploads, only: :show do
member do
post :download
end
end
end
class Upload < ApplicationRecord
has_secure_password validations: false
validates_length_of :password,
maximum: ActiveModel::SecurePassword::MAX_PASSWORD_LENGTH_ALLOWED
def data
"HELLO"
end
end
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
You can’t perform that action at this time.