/cancan-permits

Role specific Permits for use with CanCan permission system

Primary LanguageRubyMIT LicenseMIT

CanCan Permits

Role specific Permits for use with CanCan permission system.

Changes

See Changelog.txt

Install

gem install cancan-permits

Usage

  • Define Roles that Users can have
  • Define which Roles are available
  • Define a Permit for each Role.
  • For each Permit, define what that Role can do

To add Roles to your app, you might consider using a roles gem such as Roles Generic or any of the ORM specific variants.

Define which Roles are available

You can override the default configuration here:

  module Permits::Roles
    def self.available
      # return symbols array of Roles available to users 
    end
  end

By default it returns User.roles if such exists, otherwise it returns [:guest, :admin] by default.

Define a Permit for each Role.

Note: You might consider using the Permits generator in order to generate your permits for you (see below)

  class AdminPermit < Permit::Base
    def initialize(ability, options = {})
      super
    end

    def permit?(user, options = {})    
      super
      return if !role_match? user

      can :manage, :all    
    end  
  end

Special Permits

The Permits generator always generates the special permits Any and System.

Any permit

The Any permit, can be used to set permissions that should hold true for a user in any role. F.ex, maybe in your app, any user should be able to read comments, articles and posts:

For this to hold true, put the following permit logic in your Any permit.

  can :read, [Comment, Article, Post]

System permit

The System permit is run before any of the other permits. This gives you a chance to control the permission flow. By returning a value of :break you force a break-out from the permission flow, ensuring none of the other permits are run.

Example: The system permit can be used to allow management of all resources given the request is from localhost (which usually means "in development mode"). By default this logic is setup and ready to go.

You can be enable this simply by setting the following class instance variable:

Permits::Configuration.localhost_manager = true

Licenses

Permits also supports creation more fine-grained permits through the use of Licenses.
Licenses are a way to group logical fragments of permission statements to be reused across multiple permits. The generator will create a licenses.rb file in the permits folder where you can put your licenses. For more complex scenarios, you might want to have a separate licenses subfolder where you put your license files.

License example:

  class BloggingLicense < License::Base
    def initialize name
      super
    end

    def enforce!
      can(:read, Blog)
      can(:create, Post)
      owns(user, Post)
    end
  end  

Usage example:

  class GuestPermit < Permit::Base
    def initialize(ability, options = {})
      super
    end

    def permit?(user, options = {}) 
      super    
      return if !role_match? user

      licenses :user_admin, :blogging
    end
  end
end

By convention the permits system will try to find a license named UserAdminLicense and BloggingLicense in this example and call enforce! on each license.

ORMs

The easiest option is to directly set the orm as a class variable. An appropriate ownership strategy will be selected accordingly for the ORM.

  Permits::Ability.orm = :data_mapper

Alternatively set it for the Ability instance for more fine grained control

  ability = Permits::Ability.new(@editor, :strategy => :string)  

The ORMs currently supported (and tested) are :active_record, :data_mapper, :mongoid, :mongo_mapper

Permits Generator

Options

  • --orm : The ORM to use (active_record, data_mapper, mongoid, mongo_mapper)
  • --roles : The roles for which to generate permits ; default Guest (read all) and Admin (manage all)

Note, by default the Permits generator will attempt to discover which roles are currently defined as available to the system and generate permits for those roles (using some conventions - TODO). Any roles specified in the --roles option are merged with the roles found to be available in the app.

$ rails g permits --orm active_record --roles guest author admin

Note on Patches/Pull Requests

  • Fork the project.
  • Make your feature addition or bug fix.
  • Add tests for it. This is important so I don't break it in a future version unintentionally.
  • Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
  • Send me a pull request. Bonus points for topic branches.

Copyright

Copyright (c) 2010 Kristian Mandrup. See LICENSE for details.