Cannie
Cannie is a gem for authorization/permissions checking on per-controller/per-action basis.
Installation
Add this line to your application's Gemfile:
gem 'cannie'
And then execute:
$ bundle
Or install it yourself as:
$ gem install cannie
Usage
Define permissions
Permissions are defined in Permissions class, which could be generated by Rails generator:
rails g cannie:
Than you can define all the permissions you want:
class Permissions
include Cannie::Permissions
# allow action on controller
allow :index, on: :posts
# or if controller is namespaced
allow :index, on: 'namespace/controller'
# few actions for controller
allow [:index, :show], on: :posts
# many actions for many controllers
allow [:index, :show], on: [:posts, :comments]
# few rules inside controller scope
controller :posts do
allow :show
allow :new
end
# namespaced controllers
namespace :admin do
controller :users do
allow [:index, :show]
end
end
end
Also its possible to pass conditions for allow
calls:
allow :index, on: :posts, if: ->{ user.admin? }
or
allow :index, on: :posts, unless: ->{ user.guest? }
or
allow :index, on: :posts, if: &:admin?
or
allow :index, on: :posts, unless: &:admin?
These conditions are executed in context of Permissions
object and its possible to use user
method to access user that was passed to Permissions::initialize
.
Checking permissions
To be sure that permissions checking is handled in each action of your controller, add check_permissions
method call to your controllers:
class PostsController < ApplicationController
#...
end
It's also possible to set a condition by specifying :if
or :unless
options for check_permissions
call:
class PostsController < ApplicationController
if: :some_method
#...
end
or
class PostsController < ApplicationController
if: ->(controller) { controller.some_method }
#...
end
or
class PostsController < ApplicationController
unless: some_method
#...
end
or
class PostsController < ApplicationController
unless: ->(controller) { controller.some_method }
#...
end
To skip checking permissions for controller, add skip_check_permissions
method call:
class PagesController < ApplicationController
#...
end
Handling of unpermitted access
If user is not permitted for appropriate action, Cannie::ActionForbidden
exception will be raised.
It can be handled globally by using rescue_from
inside ApplicationController:
class ApplicationController < ActionController::Base
rescue_from Cannie::ActionForbidden do |exception|
redirect_to root_path, alert: exception.
end
end
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request