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:
commit
79be5f3211
6 changed files with 75 additions and 19 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue