Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Authorization Gem for Ruby on Rails with administrative interface. Semantic, Flexible, Lightweight
Ruby JavaScript
branch: master

This branch is 255 commits behind the-teacher:master

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
app
config
db/migrate
lib
.gitignore
.rvmrc.example
Bye_bye_CanCan_I_got_the_Role.png
Gemfile
MIT-LICENSE
README.md
Rakefile
pic.png
the_role.gemspec

README.md

gem 'the_role' (alpha v0.1)

Bye bye CanCan, I got The Role! Description
Bye bye CanCan, I got The Role! TheRole is an authorization library for Ruby on Rails which restricts what resources a given user is allowed to access. All permissions are defined in with 2-level-hash, and store in database with JSON.

TheRole - Semantic, lightweight role system with an administrative interface.

Role is a two-level hash, consisting of the sections and nested rules.

Section may be associated with controller name.

Rule may be associated with action name.

Section can have many rules.

Rule can have true or false value

Sections and nested Rules provide ACL (Access Control List)

Role stored in the database as JSON string.

Using of hashes, makes role system extremely easy to configure and use.

GUI

TheRole management web interface
TheRole

rubygems page

http://rubygems.org/gems/the_role

TheRole and Devise 2

Integration with Devise2

TheRole and Sorcery

Integration with Sorcery

Want to improve this gem?

Rspec for TheRole

Specs with Devise 2

Read How to start development process manual for running specs

What does it mean semantic?

Semantic - the science of meaning. Human should fast to understand what is happening in a role system.

Look at next Role hash. If you can understand access rules - this authorization system is semantically.

role = {
  'pages' => {
    'index'   => true,
    'show'    => true,
    'new'     => false,
    'edit'    => false,
    'update'  => false,
    'destroy' => false
  },
  'articles' => {
    'index'  => true,
    'show'   => true
  },
  'twitter'  => {
    'button' => true,
    'follow' => false
  }
}

Virtual sections and rules

Usually, we use real names of controllers and actions for names of sections and rules:

current_user.has_role?(:pages, :show)

But, also, you can use virtual names of sections, and virtual names of section's rules.

current_user.has_role?(:twitter, :button)
current_user.has_role?(:facebook, :like)

And you can use them as well as other access rules.

Install

  gem 'the_role'
  bundle

User Model migration

Add role_id:integer field to your User Model

def self.up
  create_table :users do |t|
    t.string :login,            :null    => false
    t.string :email,            :default => nil
    t.string :crypted_password, :default => nil
    t.string :salt,             :default => nil

    t.integer :role_id,         :default => nil

    t.timestamps
  end
end

Generate Role Model without migration

rails g model role --migration=false

Generate Role migration

rake the_role_engine:install:migrations

Create database and migrate

rake db:create && rake db:migrate

Create fake roles for test (not required)

rake db:roles:test

Change your ApplicationController

Example for Devise2

class ApplicationController < ActionController::Base
  include TheRole::Requires

  protect_from_forgery

  def access_denied
    render :text => 'access_denied: requires an role' and return
  end

  alias_method :login_required,     :authenticate_user!
  alias_method :role_access_denied, :access_denied
end

Define aliases method for correctly work TheRole's controllers

authenticate_user! or any other method from your auth system

access_denied or any other method for processing access denied situation

Using with any controller

class PagesController < ApplicationController
  # Devise2 and TheRole before_filters
  before_filter :login_required, :except => [:index, :show]
  before_filter :role_required,  :except => [:index, :show]

  before_filter :find_page,      :only   => [:edit, :update, :destroy]
  before_filter :owner_required, :only   => [:edit, :update, :destroy]

  private

  def find_page
    @page = Page.find params[:id]
    @ownership_checking_object = @page
  end
end

Ownership checking

owner_required method require @ownership_checking_object variable, with cheked object.

You should to define @ownership_checking_object before invoke of owner_required method.

Using with Views

<% if @user.has_role?(:twitter, :button) %>
  Twitter Button is Here
<% else %>
  Access Denied
<% end %>

Way to set default role for new User

class User
  after_create :set_default_role

  private

  def set_default_role
    self.role = Role.where(:name => :user).first
    self.save
  end
end

Who is Administrator?

Administrator it's a user who can access any section and the rules of your application.

Administrator is the owner of any objects in your application.

Administrator it's a user, which has virtual section system and rule administrator in the role-hash.

admin_role_fragment = {
  :system => {
    :administrator => true
  }
}

Who is Moderator?

Moderator it's a user, which has access to any actions of some section(s).

Moderator is's owner of any objects of some class.

Moderator it's a user, which has a virtual section moderator, with section name as rule name.

There is Moderator of Pages (controller) and Twitter (virtual section)

moderator_role_fragment = {
  :moderator => {
    :pages   => true,
    :blogs   => false,
    :twitter => true
  }
}

Who is Owner?

Administrator is owner of any object in system.

Moderator of pages is owner of any page.

User is owner of object, when Object#user_id == User#id.

User Model methods

Has a user an access to rule of section (action of controller)?

current_user.has_role?(:pages,    :show)  => true | false
current_user.has_role?(:blogs,    :new)   => true | false
current_user.has_role?(:articles, :edit)  => true | false

Is it Moderator?

current_user.moderator?(:pages)           => true | false
current_user.moderator?(:blogs)           => true | false
current_user.moderator?(:articles)        => true | false

Is it Administrator?

current_user.admin?                       => true | false

Is it Owner of object?

current_user.owner?(@page)                => true | false
current_user.owner?(@blog)                => true | false
current_user.owner?(@article)             => true | false

Base Role methods

# User's role
@role = current_user.role
# Find a Role by name
@role = Role.find_by_name(:user)
@role.has?(:pages, :show)       => true | false
@role.moderator?(:pages)        => true | false
@role.admin?                    => true | false

CRUD API (for console users)

CREATE

# Create a section of rules
@role.create_section(:pages)
# Create rule in section (false value by default)
@role.create_rule(:pages, :index)

READ

@role.to_hash => Hash

# JSON string
@role.to_json => String

# JSON string
@role.to_s => String

UPDATE

# Incoming hash is true-mask-hash
# All rules of Role will be reset to false
# Only rules from true-mask-hash will be set on true
new_role_hash = {
  :pages => {
    :index => true,
    :show => true
  }
}

@role.update_role(new_role_hash)
# set this rule on true
@role.rule_on(:pages, :index)
# set this rule on false
@role.rule_off(:pages, :index)

DELETE

# delete a section
@role.delete_section(:pages)

# delete rule in section
@role.delete_rule(:pages, :show)
Something went wrong with that request. Please try again.