Awesome
If you like the straight forward and effective nature of Strong Parameters and suspect that cancan might be overkill for your project then you'll love Petergate's easy to use and read action and content based authorizations."
-- <cite>1 Peter 3:41</cite>
Installation
Get the gem
Add this line to your application's Gemfile:
gem 'petergate'
And then execute:
bundle
Or install it yourself as:
gem install petergate
Prerequisites: Setup Authentication (Devise)
Make sure your user model is defined in app/models/user.rb and called User.
If you're using devise you're in luck, otherwise you'll have to add following methods to your project:
current_user
after_sign_in_path_for(current_user)
authenticate_user!
Run the generators
rails g petergate:install
rake db:migrate
This will add a migration and insert petergate into your User model.
Usage
User Model
Configure available roles by modifying this block at the top of your user.rb.
############################################################################################
## PeterGate Roles ##
## The :user role is added by default and shouldn't be included in this list. ##
## The :root_admin can access any page regardless of access settings. Use with caution! ##
## The multiple option can be set to true if you need users to have multiple roles. ##
petergate(roles: [:admin, :editor], multiple: false) ##
############################################################################################
Instance Methods
user.role => :editor
user.roles => [:editor, :user]
user.roles=(v) #sets roles
user.available_roles => [:admin, :editor]
user.has_roles?(:admin, :editors) # returns true if user is any of roles passed in as params.
Class Methods
User.#{role}_editors => #list of editors. Method is created for all roles. Roles [admin, :teacher] will have corresponding methods role_admins, role_teachers, etc.
Controllers
Setup permissions in your controllers the same as you would for a before filter like so:
access all: [:show, :index], user: {except: [:destroy]}, company_admin: :all
# one other option that might seem a bit weird is to put a group of roles in an array:
access [:all, :user] => [:show, :index]
Inside your views you can use logged_in?(:admin, :customer, :etc) to show or hide content.
<%= link_to "destroy", destroy_listing_path(listing) if logged_in?(:admin, :customer, :etc) %>
If you need to access available roles within your project you can by calling:
User::ROLES
# or from an instance
User.first.available_roles
# ROLES is a CONSTANT and will still work from within the User model instance methods
# like in this default setter:
def roles=(v)
self[:roles] = v.map(&:to_sym).to_a.select{|r| r.size > 0 && ROLES.include?(r)}
end
If you need to deny access you can use the forbidden! method:
before_action :check_active_user
def check_active_user
forbidden! unless current_user.active
end
If you want to change the permission denied
message you can add to the access line:
access user: [:show, :index], message: "You shall not pass"
User Admin Example Form for Multiple Roles
= form_for @user do |f|
- if @user.errors.any?
#error_explanation
h2 = "#{pluralize(@user.errors.count, "error")} prohibited this user from being saved:"
ul
- @user.errors.full_messages.each do |message|
li = message
.field
= f.label :email
= f.text_field :email
- if @user.new_record? || params[:passwd]
.field
= f.label :password
= f.text_field :password
.field
= f.label :password_confirmation
= f.text_field :password_confirmation
.field
= f.label :roles
= f.select :roles, @user.available_roles, {}, {multiple: true}
.actions = f.submit
User Admin Example Form for Single Role Mode
= form_for @user do |f|
- if @user.errors.any?
#error_explanation
h2 = "#{pluralize(@user.errors.count, "error")} prohibited this user from being saved:"
ul
- @user.errors.full_messages.each do |message|
li = message
.field
= f.label :email
= f.text_field :email
- if @user.new_record? || params[:passwd]
.field
= f.label :password
= f.text_field :password
.field
= f.label :password_confirmation
= f.text_field :password_confirmation
.field
= f.label :role
= f.select :role, @user.available_roles
.actions = f.submit
Credits
PeterGate is written and maintaned by Isaac Sloan and friends.
Contributing
- Fork it ( https://github.com/isaacsloan/petergate/fork )
- 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 a new Pull Request