Roadblock
A simple authorization library.
Roadblock provides a simple interface for checking if a ruby object has the authority to interact with another object. The most obvious example being if the current user in your rails controller can read/write the object they're attempting to access.
Nearly all authorization libraries require heavy weight configuration and tight integration with Rails. This library was created to provide the simplest solution to the problem without requiring any external dependencies. It doesn't require Rails or any of it's subcomponents and weighs in at less than 100 LOC for the actual implementation (less than 25 LOC if you don't care about authorizer stacks).
Installation
Add this line to your application's Gemfile:
gem 'roadblock'
And then execute:
$ bundle
Or install it yourself as:
$ gem install roadblock
Usage
require "roadblock"
class TeamAuthorizer
include Roadblock.authorizer
def can_read?(team)
scopes.include?("read") &&
auth_object.teams.include?(team)
end
def can_write?(team)
scopes.include?("write_teams") && (
auth_object.managed_teams.include?(team) ||
auth_object.owned_teams.include?(team)
)
end
end
scopes = ["read", "write_teams"] # Optional oauth scopes
auth = TeamAuthorizer.new(current_user, :scopes => scopes)
team = Team.find(params[:id])
# Scopes are optional, just don't pass any in if you don't want them.
auth.can?(:read, team) # or auth.can_read?(team)
auth.can?(:write, team) # or auth.can_write?(team)
# When using the #can? syntax, you can pass in an enumerable
# #can? will then tell you if the user is able to perform the
# action on all of the objects. `true` they can, `false` they
# cannot.
teams = Team.where(:sport => :hockey)
auth.can?(:read, teams)
auth.can?(:write, teams)
Middleware
require "roadblock"
class TeamAuthorizer
include Roadblock.authorizer
def can_read?(team)
auth_object.teams.include?(team)
end
end
class AdminAuthorizer
include Roadblock.authorizer
def can?(action, object)
if auth_object.is_admin?
true
else
yield(object)
end
end
end
stack = Roadblock::Stack.new(current_user, :scopes => scopes)
stack.add(AdminAuthorizer, TeamAuthorizer)
# Then use stack just as you would a standalone authorizer
stack.can?(:read, team) # or stack.can_read?(team)
stack.can?(:read, teams) # or stack.can_read?(teams)
Contributing
- Fork it ( http://github.com/teamsnap/roadblock/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request