Using CanCan with roles and permissions in YAML

With one rails application I need to implement an authorization system, I opted the CanCan gem because the requirements are pretty simple. But the idea to edit the ability class each time I want to add a new role or permission just seem too much for me. I want something simpler (and also i’m not feeling like to store the roles and permissions in database), so I choose to store the roles and permissions in YAML file. The idea for this approach is from railscasts and CanCan wiki page.

This is the YAML file I ended up with

# file config/roles.yml

roles:
  - admin
  - manager
  - operator

public_permissions: &public
  # public permissions goes here

permissions:
  manager:
    read: all
    create: User
    reset_password: User
    destroy: User
    <<: *public
  operator:
    <<: *public

and this is the Ability class

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new
    if user.role? :admin
      can :manage, :all
    else
      can [:edit, :update], User do |current_user|
        user.id == current_user.id
      end
      user.roles.each do |role|
        return nil if Ability.permissions[role].nil?
        Ability.permissions[role].each do |action, object|
          can action.to_sym, object == 'all'? object.to_sym : object.constantize
        end
      end
    end
  end

  def self.roles
    app_roles = Ability.load_roles
    app_roles['roles']
  end

  def self.permissions
    app_roles = Ability.load_roles
    app_roles['permissions']
  end

  def self.load_roles(file='roles.yml')
    YAML.load_file("#{RAILS_ROOT}/config/#{file}")
  end
end

I choose to load the roles.yml file each time an action need to be authorized so that when the file changed (roles or permissions added), the changes instantly applied in the app. There are some drawback in this approach though, like the order of the roles in roles.yml cannot be altered, you can only add a new roles at the end of the list, but other than that it works for me. And if you need some special permission you can always add the permissions in the ability class. Hope this usefull :)

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s