0.0
No commit activity in last 3 years
No release in over 3 years
Aegis is a role-based permission system, where all users are given a role. It is possible to define detailed and complex permissions for each role very easily.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies
 Project Readme

Aegis - role-based permissions for your user models¶ ↑

Aegis allows you to manage fine-grained, complex permission for user accounts in a central place.

Installation¶ ↑

Add the following to your Initializer.run block in your environment.rb:

config.gem 'aegis', :source => 'http://gemcutter.org'

Then do a

sudo rake gems:install

Alternatively, use

sudo gem sources -a http://gemcutter.org
sudo gem install aegis

Example¶ ↑

First, let’s define some roles:

# app/models/permissions.rb
class Permissions < Aegis::Permissions
  role :guest
  role :registered_user
  role :moderator
  role :administrator, :default_permission => :allow
  permission :edit_post do |user, post|
    allow :registered_user do
      post.creator == user      # a registered_user can only edit his own posts
    end
    allow :moderator
  end
  permission :read_post do |post|
    allow :everyone
    deny :guest do
      post.private?             # guests may not read private posts
    end
  end
end

Now we assign roles to users. For this, the users table needs to have a string column role_name.

# app/models/user.rb
class User
  has_role
end

These permissions may be used in views and controllers:

# app/views/posts/index.html.erb
@posts.each do |post|
  <% if current_user.may_read_post? post %>
    <%= render post %>
    <% if current_user.may_edit_post? post %>
      <%= link_to 'Edit', edit_post_path(post) %>
    <% end %>
  <% end %>
<% end %>
# app/controllers/posts_controller.rb
class PostsController
  # ...
  def update
    @post = Post.find(params[:id])
    current_user.may_edit_post! @post    # raises an Aegis::PermissionError for unauthorized access
    # ...
  end
end

You might want to specifiy a default role:

class Permissions < Aegis::Permissions
  default_role 'role_name'
end

This role will be returned for objects that has nil as their role_name. This greatly reduces noise in your database (i.e. if you have 100 000 users, you don’t have to store ‘role_name’ for each row, just for your non-default roles). default_role takes the same options as role.

To explicitly make sure that a given row won’t have a permission object, set role_name to the empty string (“”).

Details¶ ↑

Roles¶ ↑

To equip a (user) model with any permissions, you simply call has_role within the model:

class User < ActiveRecord::Base
  has_role
end

Aegis assumes that the corresponding database table has a string-valued column called role_name. You may override the name with the :name_accessor => :my_role_column option.

The roles and permissions themselves are defined in a class inheriting from Aegis::Permissions. To define roles you create a model permissions.rb and use the role method:

class Permissions < Aegis::Permissions
  role 'role_name'
end

By default, users belonging to this role are not permitted anything. You may override this with :default_permission => :allow, e.g.

role 'admin', :default_permission => :allow

Permissions¶ ↑

Permissions are specified with the permission method and allow and deny

permission :do_something do
    allow :role_a, :role_b
    deny :role_c
end

Your user model just received two methods called User#may_do_something? and User#may_do_something!. The first one with the ? returns true for users with role_a and role_b, and false for users with role_c. The second one with the ! raises an Aegis::PermissionError for role_c.

Normalization¶ ↑

Aegis will perform some normalization. For example, the permissions edit_something and update_something will be the same, each granting both may_edit_something? and may_update_something?. The following normalizations are active:

  • edit = update

  • show = list = view = read

  • delete = remove = destroy

Complex permissions (with parameters)¶ ↑

allow and deny can also take a block that may return true or false indicating if this really applies. So

permission :pull_april_fools_prank do
  allow :everyone do
    Date.today.month == 4 and Date.today.day == 1
  end
end

will generate a may_pull_april_fools_prank? method that only returns true on April 1.

This becomes more useful if you pass parameters to a may_...? method, which are passed through to the permission block (together with the user object). This way you can define more complex permissions like

permission :edit_post do |current_user, post|
  allow :registered_user do
    post.owner == current_user
  end
  allow :admin
end

which will permit admins and post owners to edit posts.

For your convenience¶ ↑

As a convenience, if you create a permission ending in a plural ‘s’, this automatically includes the singular form. That is, after

permission :read_posts do
  allow :everyone
end

.may_read_post? @post will return true, as well.

If you want to grant create_something, read_something, update_something and destroy_something permissions all at once, just use

permission :crud_something do
  allow :admin
end

If several permission blocks (or several allow and denies) apply to a certain role, the later one always wins. That is

permission :do_something do
  deny :everyone
  allow :admin
end

will work as expected.

Our stance on multiple roles per user¶ ↑

We believe that you should only distinguish roles that have different ways of resolving their permissions. A typical set of roles would be

  • anonymous guest (has access to nothing with some exceptions)

  • signed up user (has access to some things depending on its attributes and associations)

  • administrator (has access to everything)

We don’t do multiple, parametrized roles like “leader for project #2” and “author of post #7”. That would be reinventing associations. Just use a single :user role and let your permission block query regular associations and attributes.

Credits¶ ↑

Henning Koch, Tobias Kraze

link www.makandra.de