Skip to content

Latest commit

 

History

History
112 lines (82 loc) · 3.26 KB

quick_start.md

File metadata and controls

112 lines (82 loc) · 3.26 KB

Quick Start

Installation

Install Action Policy with RubyGems:

gem install action_policy

Or add action_policy to your application's Gemfile:

gem "action_policy"

And then execute:

$ bundle

Basic usage

The core component of Action Policy is a policy class. Policy class describes how you control access to resources.

We suggest having a separate policy class for each resource and encourage you to follow these conventions:

  • put policies into the app/policies folder (when using with Rails);
  • name policies using the corresponding singular resource name (model name) with a Policy suffix, e.g. Post -> PostPolicy;
  • name rules using a predicate form of the corresponding activity (typically, a controller's action), e.g. PostsController#update -> PostPolicy#update?.

We also recommend to use an application-specific ApplicationPolicy with a global configuration to inherit from:

class ApplicationPolicy < ActionPolicy::Base
end

NOTE: it is not necessary to inherit from ActionPolicy::Base; instead, you can construct basic policy choosing only the components you need.

Rules must be public methods on the class. Using private methods as rules will raise an error.

Consider a simple example:

class PostPolicy < ApplicationPolicy
  # everyone can see any post
  def show?
    true
  end

  def update?
    # `user` is a performing subject,
    # `record` is a target object (post we want to update)
    user.admin? || (user.id == record.user_id)
  end
end

Now you can easily add authorization to your Rails* controller:

class PostsController < ApplicationController
  def update
    @post = Post.find(params[:id])
    authorize! @post

    if @post.update(post_params)
      redirect_to @post
    else
      render :edit
    end
  end
end

* See Non-Rails Usage on how to add authorize! to any Ruby project.

In the above case, Action Policy automatically infers a policy class and a rule to verify access: @post -> Post -> PostPolicy, rule is inferred from the action name (update -> update?), and current_user is used as user within the policy by default (read more about authorization context).

When authorization is successful (i.e., the corresponding rule returns true), nothing happens, but in case of an authorization failure ActionPolicy::Unauthorized error is raised:

rescue_from ActionPolicy::Unauthorized do |ex|
  # Exception object contains the following information
  ex.policy #=> policy class, e.g. UserPolicy
  ex.rule #=> applied rule, e.g. :show?
end

There is also an allowed_to? method which returns true or false and could be used, for example, in views:

<% @posts.each do |post| %>
  <li><%= post.title %>
    <% if allowed_to?(:edit?, post) %>
      = link_to "Edit", post
    <% end %>
  </li>
<% end %>

Although Action Policy tries to infer the corresponding policy class and rule itself, there could be a situation when you want to specify those values explicitly:

# specify the rule to verify access
authorize! @post, to: :update?

# specify policy class
authorize! @post, with: CustomPostPolicy

# or
allowed_to? :edit?, @post, with: CustomPostPolicy