Lunch and Learn

Pundit Gem

Submitted by

shalil awaley

@krazedkrish  /  krazedkrish.com
Jr. Software Engineer
Jyaasa Technologies

(... press space for next slides ...)

Authorization

Pundit Gem - Minimal authorization through OO design and pure Ruby classes.

It is a really simple Ruby Gem, that does nothing more that you could have done yourself. Here is the power!

Alternatives

  • acl9 - Acl9 is a role-based authorization system that provides a concise DSL for securing your Rails application.
  • Authority - ORM-neutral way to authorize actions in your Rails app.
  • CanCanCan - Continuation of CanCan, an authorization Gem for Ruby on Rails.
  • Declarative Authorization - An authorization Rails plugin using a declarative DSL for specifying authorization rules in one place.

Pundit Gem

 

☆ Make sure you star it

About Pundit

Pundit set some helpers to :

  • Check Policy for a given user on a given object( it is not restricted to ActiveRecord::Base instances ).
  • Describe Policy in Ruby Class
  • Enforce use of Policy in your controllers
  • Bring syntactic sugar in you Rspec tests

Installation

gem "pundit"

 

Include Pundit in your application controller:

class ApplicationController < ActionController::Base
  include Pundit
  protect_from_forgery
end

Code Example

Application Controller

              
class ApplicationController < ActionController::Base
 
# Includes Authorization mechanism
include Pundit
 
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
              
protect_from_forgery with: :exception
 
# Globally rescue Authorization Errors in controller.
# Returning 403 Forbidden if permission is denied
rescue_from Pundit::NotAuthorizedError, with: :permission_denied
 
              
 
private
 
def permission_denied
head 403
end
 
end

Policy

  • Optionally, you can run the generator, which will set up an application policy with some useful defaults for you:

    rails g pundit:install

  • Policy are placed in

    app/policies/

app/policies/application_policy.rb

class ApplicationPolicy
attr_reader :user, :record
 
def initialize(user, record)
@user = user
@record = record
end
 
def user_activities
@user.roles.select(:activities).distinct.map(&:activities).flatten
end

Scopes

                
 
def scope
Pundit.policy_scope!(user, record.class)
end
end

app/policies/post_policy.rb

                
class PostPolicy < ApplicationPolicy
attr_reader :user, :post
def initialize(user, post)
@user = user
@post = post
end
def update? user.admin? or not post.published?
end
end

Supposing that you have an instance of class Post, Pundit now lets you do this in your controller:

              
def update
@post = Post.find(params[:id])
authorize @post
if @post.update(post_params)
redirect_to @post
else
render :edit
end
end

Scopes

              
class PostPolicy < ApplicationPolicy
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
              
def resolve
if user.admin?
scope.all
else
scope.where(:published => true)
end
end
end
def update?
user.admin? or not post.published?
end
end

You can now use this class from your controller via the policy_scope method:

                
def index
@posts = policy_scope(Post)
end

THE END



There is a lot more out there

Make sure you check

[ https://github.com/elabs/pundit ]