Skip to content

Latest commit

 

History

History
113 lines (78 loc) · 2.45 KB

behaviour.md

File metadata and controls

113 lines (78 loc) · 2.45 KB

Action Policy Behaviour

Action Policy provides a mixin called ActionPolicy::Behaviour which adds authorization methods to your classes.

Usage

Let's make our custom service object aware of authorization:

class PostUpdateAction
  # First, we should include the behaviour
  include ActionPolicy::Behaviour

  # Secondly, provide authorization subject (performer)
  authorize :user

  attr_reader :user

  def initialize(user)
    @user = user
  end

  def call(post, params)
    # Now we can use authorization methods
    authorize! post, to: :update?

    post.update!(params)
  end
end

ActionPolicy::Behaviour provides authorize class-level method to configure authorization context and the instance-level methods: authorize!, allowed_to? and authorized:

authorize!

This is a guard-method which raises an ActionPolicy::Unauthorized exception if authorization failed (i.e. policy rule returns false):

# `to` is a name of the policy rule to apply
authorize! post, to: :update?

allowed_to?

This is a predicate version of authorize!: it returns true if authorization succeed and false otherwise:

# the first argument is the rule to apply
# the second one is the target
if allowed_to?(:edit?, post)
  # ...
end

authorized

See scoping docs.

Policy lookup

All three instance methods (authorize!, allowed_to?, authorized) uses the same policy_for to lookup a policy class for authorization target. So, you can provide additional options to control the policy lookup process:

  • Explicitly specify policy class using with option:
allowed_to?(:edit?, post, with: SpecialPostPolicy)
# Would try to lookup Admin::PostPolicy first
authorize! post, to: :destroy?, namespace: Admin

Implicit authorization target

You can omit the authorization target for all the methods by defining an implicit authorization target:

class PostActions
  include ActionPolicy::Behaviour

  authorize :user

  attr_reader :user, :post

  def initialize(user, post)
    @user = user
    @post = post
  end

  def update(params)
    # post is used here implicitly as a target
    authorize! to: :update

    post.update!(params)
  end

  def destroy
    # post is used here implicitly as a target
    authorize! to: :destroy

    post.destroy!
  end

  def implicit_authorization_target
    post
  end
end