Skip to content

Instantly share code, notes, and snippets.

@dasch
Created December 18, 2011 11:44
Show Gist options
  • Save dasch/1493113 to your computer and use it in GitHub Desktop.
Save dasch/1493113 to your computer and use it in GitHub Desktop.
Composable Security
class TicketFinder
def initialize(account, user)
# These would be current_account and current_user from the perspective of
# the controller layer.
raise unless account.present? && user.account == account
@account = account
@user = user
end
def find(id)
Ticket.find(id).tap do |ticket
raise SecurityError unless ticket.account == account
# This is also possible:
raise AccessError unless user.can?(:view, ticket)
end
end
def find_by_something_custom
# Since we centralize snippets like these, it's easier to ensure that we
# always scope by account.
account.tickets.find_by_awesome
end
private
attr_reader :account, :user
end
describe TicketFinder do
describe "#find" do
let(:user) { Factory(:user) }
let(:account) { Factory(:account) }
let(:ticket) { Factory(:ticket, :account => account) }
let(:inaccessible_ticket) { Factory(:ticket) }
let(:finder) { TicketFinder.new(account, user) }
it "finds a ticket" do
finder.find(ticket.id).must_equal ticket
end
it "raises SecurityError if the ticket is in a different account" do
proc { finder.find(inaccessible_ticket.id) }.must_raise SecurityError
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment