pundit

Post on 14-Jun-2015

814 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

Pundit Simple Rails Authorization

TRANSCRIPT

Pundit simple Rails authorization

Ruby::AZ - July 15, 2014

Bruce White Software Ops developer bruce@softwareops.com

We Build Mobile App Systems

Authorization vs Authentication

Today we’re talking about authorization

• Authentication is about who you are

• Authorization is about what you can do

• To work, authorization requires authentication (need to know who you are to determine what you can do)

Rails Authorization: A Retrospective

• 10 years ago, in the beginning of The Enlightenment, authorization was a “roll your own” thing

• 4 years ago, CanCan shook the Rails world to the core

• A year ago, Pundit arrives on the scene

Pundit The world’s foremost authority

• Written by Elabs

• Simple, uses pure Ruby classes

• Popular and well maintained

• Second most popular Rails authorization gem

Pundit Setup

• Include in Gemfile

• Optionally run generator

• Include in ApplicationControllerclass ApplicationController < ActionController::Base include Pundit protect_from_forgery after_action :verify_authorized, :except => :index after_action :verify_policy_scoped, :only => :index …

rails g pundit:install

gem "pundit"

Policies

• Authorization in Pundit is controlled by Policy classes

• Policies go in app/policies

• Policies are PORC

Policy Example

class PostPolicy < ApplicationPolicy … def update? user.admin? or not post.published? end …

Pundit In Controllers

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

Pundit In Views

<% if policy(@post).update? %> <%= link_to "Edit post", edit_post_path(@post) %> <% end %>

Pundit Scopes

class PostPolicy < ApplicationPolicy class Scope < Scope def resolve if user.admin? scope.all else scope.where(:published => true) end end end …

Pundit Scopes In Controllers

def index @posts = policy_scope(Post) end

Pundit Scopes In Views

<% policy_scope(@user.posts).each do |post| %> <p> <% link_to post.title, post_path(post) %> </p> <% end %>

Pundit Strong Parameters 1/2

class PostPolicy < ApplicationPolicy … def permitted_attributes if user.admin? || user.owner_of?(post) [:title, :body, :tag_list] else [:tag_list] end end …

Pundit Strong Parameters 2/2

class PostsController < ApplicationController … private !

def post_params params.require(:post).permit( *policy(@post || Post).permitted_attributes ) end …

Pundit with an API 1/4custom Pundit users

class APIController < ActionController::Base … !

private !

def pundit_user current_device end …

Pundit with an API 2/4custom Pundit users

class APIController < ActionController::Base … Context = Struct.new(:app, :device, :app_instance, :user) … private !

def pundit_user Context.new( current_app, current_device, current_app_instance, current_user ) end …

Pundit with an API 3/4custom Pundit users

AppInstancePolicy < ApplicationPolicy … def update? app_instance == current.app_instance end …

Pundit with an API 4/4

class DeliveriesController < APIController … def cancel @delivery = Delivery.find(params[:id]) authorize @delivery @delivery.cancel !

respond_with @delivery end …

Pundit Is PORC

You can:

• Encapsulate a set of permissions into an included module

• Use alias_method to make permissions behave the same

• Inherit from a base set of permissions

• Use metaprogramming

Questions?

top related