Skip to content

ThreeWiseMen/cannibal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

59 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cannibal

A simple permissions system for declaring and querying permissions between Ruby objects.

Background

Cannibal is based around defining interactions between Actors and Subjects.

An Actor participates in your system as an agent that "does" things. Cannibal lets you declare what each Actor can do, and Actors are queried to determine whether or not they are permitted to perform a particular action.

You can turn any class into an Actor by including Cannibal::Actor within it.

A Subject participates in your system as something that is acted upon. You declare for each Subject the conditions under which each Actor may or may not interact with it.

You can turn any class into a Subject by including Cannibal::Actor within it.

If for example you are using Cannibal in a Rails application, an example of an Actor might be a User model. An example of a Subject might be a Task model. You may want all Users in the system to be able to view all of the available Tasks, but you may want to restrict tasks to only be editable by their creators.

Permissions can be set at various levels, starting at the Class level and getting finer grained right down to the field or method level of your models.

In addition, you can specify static permissions (no User may modify a Task) or dynamic permissions that are evaluated at query time (ie. a specific user may or may not be able to modify a specific task, based on whatever rules you put forth).

Sample Scenarios

Class-level permissions:

class User
  include Cannibal::Actor
end

class Thing
  include Cannibal::Subject
  allow User, :edit
end

@user = User.new
@thing = Thing.new

puts "Yay!" if @user.can? :edit, @thing

Actor object-level permissions:

class User
  include Cannibal::Actor
  attr_accessor :role
end

class Thing
  include Cannibal::Subject
  permission({
    :actor => User,
    :verb => :edit,
    :actor_proc => Proc.new { |user|
      user.role == 'administrator'
    }
  })
end

@user = User.new; @user.role = 'user'
@admin = User.new; @user.role = 'administrator'
@thing = Thing.new

puts "Back off!" unless @user.can? :edit, @thing
puts "Yay!" if @admin.can? :edit, @thing

Actor and subject object-to-object level permissions:

class User
  include Cannibal::Actor
  attr_accessor :role
end

class Thing
  include Cannibal::Subject
  attr_accessor :owner
  permission({
    :actor => User,
    :verb => :edit,
    :proc => Proc.new { |user, thing|
      user.role == 'administrator' or user == thing.owner
    }
  })
end

@user_a = User.new; @user.role = 'user'
@user_b = User.new; @user.role = 'user'
@admin = User.new; @user.role = 'administrator'

@thing = Thing.new; @thing.owner = @user_a

puts "Back off!" unless @user_b.can? :edit, @thing
puts "Yay!" if @user_a.can? :edit, @thing
puts "Yay!" if @admin.can? :edit, @thing

About

Permissions framework for Ruby objects

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages