1
0
Fork 0
mirror of https://github.com/varvet/pundit.git synced 2022-11-09 12:30:11 -05:00

Merge pull request #529 from varvet/fix/pass-array-last-to-policy-and-scope

Pass last element in array to policy and scope and fix param_key
This commit is contained in:
Linus Marton 2018-06-17 10:26:59 +02:00 committed by GitHub
commit 79be5f3211
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 75 additions and 19 deletions

View file

@ -2,6 +2,8 @@
## Unreleased
- Fix `param_key` issue when passed an array. (#529)
- Only pass last element of "namespace array" to policy and scope. (#529)
- Allow specification of a `NilClassPolicy`. (#525)
- Make sure `policy_class` override is called when passed an array. (#475)
- Raise `InvalidConstructorError` if a policy or policy scope with an invalid constructor is called. (#462)

View file

@ -80,7 +80,7 @@ module Pundit
# @return [Scope{#resolve}, nil] instance of scope class which can resolve to a scope
def policy_scope(user, scope)
policy_scope = PolicyFinder.new(scope).scope
policy_scope.new(user, scope).resolve if policy_scope
policy_scope.new(user, pundit_model(scope)).resolve if policy_scope
rescue ArgumentError
raise InvalidConstructorError, "Invalid #<#{policy_scope}> constructor is called"
end
@ -95,7 +95,7 @@ module Pundit
# @return [Scope{#resolve}] instance of scope class which can resolve to a scope
def policy_scope!(user, scope)
policy_scope = PolicyFinder.new(scope).scope!
policy_scope.new(user, scope).resolve
policy_scope.new(user, pundit_model(scope)).resolve
rescue ArgumentError
raise InvalidConstructorError, "Invalid #<#{policy_scope}> constructor is called"
end
@ -109,7 +109,7 @@ module Pundit
# @return [Object, nil] instance of policy class with query methods
def policy(user, record)
policy = PolicyFinder.new(record).policy
policy.new(user, record) if policy
policy.new(user, pundit_model(record)) if policy
rescue ArgumentError
raise InvalidConstructorError, "Invalid #<#{policy}> constructor is called"
end
@ -124,10 +124,16 @@ module Pundit
# @return [Object] instance of policy class with query methods
def policy!(user, record)
policy = PolicyFinder.new(record).policy!
policy.new(user, record)
policy.new(user, pundit_model(record))
rescue ArgumentError
raise InvalidConstructorError, "Invalid #<#{policy}> constructor is called"
end
private
def pundit_model(record)
record.is_a?(Array) ? record.last : record
end
end
# @api private

View file

@ -55,12 +55,14 @@ module Pundit
# @return [String] the name of the key this object would have in a params hash
#
def param_key
if object.respond_to?(:model_name)
object.model_name.param_key.to_s
elsif object.is_a?(Class)
object.to_s.demodulize.underscore
model = object.is_a?(Array) ? object.last : object
if model.respond_to?(:model_name)
model.model_name.param_key.to_s
elsif model.is_a?(Class)
model.to_s.demodulize.underscore
else
object.class.to_s.demodulize.underscore
model.class.to_s.demodulize.underscore
end
end

View file

@ -106,5 +106,17 @@ describe Pundit::PolicyFinder do
expect(subject.param_key).to eq "article"
end
end
context "object is an array" do
subject { described_class.new([:project, article]) }
it "returns the param_key for the last element of the array" do
expect(subject.object).not_to respond_to(:model_name)
expect(subject.object).not_to be_a Class
expect(subject.object).to be_an_instance_of Array
expect(subject.param_key).to eq "article"
end
end
end
end

View file

@ -63,6 +63,14 @@ describe Pundit do
expect(Pundit.policy_scope(user, empty_comments_relation)).to eq CommentScope.new(empty_comments_relation)
end
it "returns an instantiated policy scope given an array of a symbol and plain model class" do
expect(Pundit.policy_scope(user, [:project, Post])).to eq :read
end
it "returns an instantiated policy scope given an array of a symbol and active model class" do
expect(Pundit.policy_scope(user, [:project, Comment])).to eq Comment
end
it "returns nil if the given policy scope can't be found" do
expect(Pundit.policy_scope(user, Article)).to be_nil
end
@ -101,6 +109,14 @@ describe Pundit do
end.to raise_error(Pundit::NotDefinedError, "Cannot scope NilClass")
end
it "returns an instantiated policy scope given an array of a symbol and plain model class" do
expect(Pundit.policy_scope!(user, [:project, Post])).to eq :read
end
it "returns an instantiated policy scope given an array of a symbol and active model class" do
expect(Pundit.policy_scope!(user, [:project, Comment])).to eq Comment
end
it "raises an error with a invalid policy scope constructor" do
expect do
Pundit.policy_scope(user, Wiki)
@ -144,35 +160,35 @@ describe Pundit do
policy = Pundit.policy(user, %i[project criteria])
expect(policy.class).to eq Project::CriteriaPolicy
expect(policy.user).to eq user
expect(policy.criteria).to eq %i[project criteria]
expect(policy.criteria).to eq :criteria
end
it "returns an instantiated policy given an array of a symbol and plain model instance" do
policy = Pundit.policy(user, [:project, post])
expect(policy.class).to eq Project::PostPolicy
expect(policy.user).to eq user
expect(policy.post).to eq [:project, post]
expect(policy.post).to eq post
end
it "returns an instantiated policy given an array of a symbol and a model instance with policy_class override" do
policy = Pundit.policy(user, [:project, customer_post])
expect(policy.class).to eq Project::PostPolicy
expect(policy.user).to eq user
expect(policy.post).to eq [:project, customer_post]
expect(policy.post).to eq customer_post
end
it "returns an instantiated policy given an array of a symbol and an active model instance" do
policy = Pundit.policy(user, [:project, comment])
expect(policy.class).to eq Project::CommentPolicy
expect(policy.user).to eq user
expect(policy.post).to eq [:project, comment]
expect(policy.comment).to eq comment
end
it "returns an instantiated policy given an array of a symbol and a plain model class" do
policy = Pundit.policy(user, [:project, Post])
expect(policy.class).to eq Project::PostPolicy
expect(policy.user).to eq user
expect(policy.post).to eq [:project, Post]
expect(policy.post).to eq Post
end
it "raises an error with a invalid policy constructor" do
@ -185,14 +201,14 @@ describe Pundit do
policy = Pundit.policy(user, [:project, Comment])
expect(policy.class).to eq Project::CommentPolicy
expect(policy.user).to eq user
expect(policy.post).to eq [:project, Comment]
expect(policy.comment).to eq Comment
end
it "returns an instantiated policy given an array of a symbol and a class with policy_class override" do
policy = Pundit.policy(user, [:project, Customer::Post])
expect(policy.class).to eq Project::PostPolicy
expect(policy.user).to eq user
expect(policy.post).to eq [:project, Customer::Post]
expect(policy.post).to eq Customer::Post
end
it "returns correct policy class for an array of a multi-word symbols" do
@ -312,7 +328,7 @@ describe Pundit do
policy = Pundit.policy!(user, %i[project criteria])
expect(policy.class).to eq Project::CriteriaPolicy
expect(policy.user).to eq user
expect(policy.criteria).to eq %i[project criteria]
expect(policy.criteria).to eq :criteria
end
it "throws an exception if the given policy can't be found" do

View file

@ -62,6 +62,10 @@ class Post < Struct.new(:user)
:published
end
def self.read
:read
end
def to_s
"Post"
end
@ -155,9 +159,23 @@ end
class CriteriaPolicy < Struct.new(:user, :criteria); end
module Project
class CommentPolicy < Struct.new(:user, :post); end
class CommentPolicy < Struct.new(:user, :comment)
class Scope < Struct.new(:user, :scope)
def resolve
scope
end
end
end
class CriteriaPolicy < Struct.new(:user, :criteria); end
class PostPolicy < Struct.new(:user, :post); end
class PostPolicy < Struct.new(:user, :post)
class Scope < Struct.new(:user, :scope)
def resolve
scope.read
end
end
end
end
class DenierPolicy < Struct.new(:user, :record)