Permits and Permit engine for CanTango
Switch branches/tags
Nothing to show
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


CanTango Permits

The Permit system for CanTango.

Permits are a way to partition Ability rules into logical units.

CanTango Permits includes:

  • a basic set of useful permits
  • a permit engine to execute the permits

The Permits systems comes with a few useful Permit types out-of-the-box, but you are free to develop your own to suit your needs.

Built-in permit types

The set of buit-in Permit types include:

  • User
  • UserType
  • AccountType
  • (Special)

The cantango-roles extension adds Permit types for the following:

  • Role
  • RoleGroup

Custom permit types

You can easily customize or create your own types of Permits to suit your needs! The Permit system will introspect the ability candidate and see which Permits apply and then build and execute these permits automatically, merging all the resulting rule sets into one. The simplest way to create a custom permit types is to subclass the Attribute permit as shown below. To create more complex permit types that go beyond mapping to an attribute, please look at the code of any of the built-in permits (such as Attribute Permit) to gain an insight for how to do this.

Example of a custom permit type:

class MembershipPermit < CanTango::Permit::Attribute
  class Builder < CanTango::Permit::Attribute::Builder
    attribute :membership

  def self.inherited(base_clazz)
    register base_clazz, :name => attribute_name(base_clazz)

  # optional override of inference of attribute via class name
  attribute :membership

Permit system

The permit system iterates over all the registered types of permits and executes all registered permits of each type. The result is a set of Ability rules that work with the CanCan Ability mechanism.

Defining Permits and Licenses in your app

Note: The following example uses the cantango-roles extension containing Role and RoleGroup permits.

The app/permits folder will be added to Rails autoloading. The directory layout should be the following:

- /app
  - /permits
    - /permit
      - /role
         - editor.rb
      - /role_group
         - editors.rb
      - /user_type
         - admin.rb
      -/admin (account)
         - /role
           - editor.rb

Default :editor Role permit (scope less):

module Permit::Role
  class Editor < CanTango::Permit::Role
    def permissions
      can :edit, Post

    module Cache
      def permissions
        can :edit, Post

Permit scopes

Permits can also be scoped, fx for the type of Account.

In the following example, the :editor Role permit will only be executed for the Admin scope. Typically the scope is linked to the account (but doesn't have to be).

module Permit::Admin::Role
  class Editor < CanTango::Permit::Role
	  def permissions
	    can :edit, Post if session[:edit_mode]

Another option is fx to wrap the Permit class inside the Account class namespace like this:

- /app
  - /models
    - /admin_account
      - editor_role_permit.rb
    - admin_account.rb

Also see Execution modes


Licenses can be used as Permit mixins, ie. Permit rules that are reused in multiple types of Permits.

See more on Licenses


Insert into Gemfile

gem 'cantango-permits'

Run bundler:

$ bundle


See cantango-config

Turn on/off: Enable and disable types of permits and specific permits

CanTango.config.permits do |permits|
  # which types of permits to enable
  permits.types.enable :user_type, :account_type

  permits.enable_all_for :account_type
  permits.types.disable :user_type, :account_type
  permits.disable_for :user_type, :admin, :editor

See more on Configuration

Debugging permits and abilities

You can use the CanTango class methods for debugging permits runtime anywhere in your Rails app.

puts CanTango.permits_allowed
puts CanTango.permits_denied
puts CanTango.debug_permits_registry

puts CanTango.debug_ability current_user, :edit, Project.first

See more about Debugging permits.

Design goals

This CanTango extension should have the least amount of dependencies on other extensions.

Status: Aug 2012

  • spec/cantango/ability - ok
  • config/ - 55 examples, 36 failures, 18 pending
  • executor/ - 8 examples, 1 failure
  • finder/ - 7 examples, 0 failures
  • macros/ - 4 examples, 0 failures
  • permit/ - 46 examples, 17 failures, 1 pending
  • builder/ - 11 examples, 9 failures
  • factory/ - 4 examples, 0 failures
  • license/ - 1 example, 0 failures, 1 pending
  • loader/ - 6 examples, 0 failures, 1 pending
  • parser/ - 1 examples, 0 failures
  • registry/ - 7 examples, 1 failure

Main work that needs to be done is in:

  • config
  • permit
  • builder

One of the main bugs is:

undefined methodengine' for #CanTango::Config:0x007fecdc6f7c70`

Which is fx the cause of most errors in engines_spec.rb:

29 examples, 28 failures

Please help out! Thanks :)

Contributing to Cantango Permits

  • Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
  • Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
  • Fork the project
  • Start a feature/bugfix branch
  • Commit and push until you are happy with your contribution
  • Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
  • Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.


Copyright (c) 2011 Kristian Mandrup. See LICENSE.txt for further details.