From 2c80766b5179db99f3026de06f562f35ac73f2ba Mon Sep 17 00:00:00 2001 From: Pablo Crivella Date: Mon, 19 Dec 2016 11:54:01 +0100 Subject: [PATCH] Allow overriding policy class on authorize method --- README.md | 12 ++++++++++++ lib/pundit.rb | 5 +++-- spec/pundit_spec.rb | 4 ++++ spec/spec_helper.rb | 12 ++++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6dae878..eeaf10b 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,18 @@ def publish end ``` +You can pass an argument to override the policy class if necessary. For example: + +```ruby +def create + @publication = find_publication # assume this method returns any model that behaves like a publication + # @publication.class => Post + authorize @publication, policy_class: PublicationPolicy + @publication.publish! + redirect_to @publication +end +``` + If you don't have an instance for the first argument to `authorize`, then you can pass the class. For example: diff --git a/lib/pundit.rb b/lib/pundit.rb index 7d0b088..48fe1db 100644 --- a/lib/pundit.rb +++ b/lib/pundit.rb @@ -189,14 +189,15 @@ protected # @param record [Object] the object we're checking permissions of # @param query [Symbol, String] the predicate method to check on the policy (e.g. `:show?`). # If omitted then this defaults to the Rails controller action name. + # @param policy_class [Class] the policy class we wan't to force use of # @raise [NotAuthorizedError] if the given query method returned false # @return [Object] Always returns the passed object record - def authorize(record, query = nil) + def authorize(record, query = nil, policy_class: nil) query ||= "#{action_name}?" @_pundit_policy_authorized = true - policy = policy(record) + policy = policy_class ? policy_class.new(pundit_user, record) : policy(record) raise NotAuthorizedError, query: query, record: record, policy: policy unless policy.public_send(query) diff --git a/spec/pundit_spec.rb b/spec/pundit_spec.rb index c1d01ce..db3bbbe 100644 --- a/spec/pundit_spec.rb +++ b/spec/pundit_spec.rb @@ -375,6 +375,10 @@ describe Pundit do expect { controller.authorize(post, :destroy?) }.to raise_error(Pundit::NotAuthorizedError) end + it "can be given a different policy class" do + expect(controller.authorize(post, :create?, policy_class: PublicationPolicy)).to be_truthy + end + it "works with anonymous class policies" do expect(controller.authorize(article_tag, :show?)).to be_truthy expect { controller.authorize(article_tag, :destroy?) }.to raise_error(Pundit::NotAuthorizedError) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9671bae..0d48b86 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -91,6 +91,18 @@ class CommentPolicy < Struct.new(:user, :comment) end end +class PublicationPolicy < Struct.new(:user, :publication) + class Scope < Struct.new(:user, :scope) + def resolve + scope + end + end + + def create? + true + end +end + class Comment extend ActiveModel::Naming end