From 8265c57cfdc47ff37c79e86def491c402623c1ff Mon Sep 17 00:00:00 2001 From: Marcel Hoppe Date: Wed, 1 Feb 2023 08:48:03 +0100 Subject: [PATCH 1/3] Add policy_class to permitted_attributes --- lib/pundit/authorization.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/pundit/authorization.rb b/lib/pundit/authorization.rb index 1231f2a7..5acb18fb 100644 --- a/lib/pundit/authorization.rb +++ b/lib/pundit/authorization.rb @@ -98,9 +98,14 @@ def policy_scope(scope, policy_scope_class: nil) # # @see https://github.com/varvet/pundit#policies # @param record [Object] the object we're retrieving the policy for + # @param policy_class [Class] the policy class we want to force use of # @return [Object, nil] instance of policy class with query methods - def policy(record) - policies[record] ||= Pundit.policy!(pundit_user, record) + def policy(record, policy_class: nil) + policies[{policy_class: policy_class, record: record}] ||= if policy_class + policy_class.new(pundit_user, record) + else + Pundit.policy!(pundit_user, record) + end end # Retrieves a set of permitted attributes from the policy by instantiating @@ -113,8 +118,9 @@ def policy(record) # @param record [Object] the object we're retrieving permitted attributes for # @param action [Symbol, String] the name of the action being performed on the record (e.g. `:update`). # If omitted then this defaults to the Rails controller action name. + # @param policy_class [Class] the policy class we want to force use of # @return [Hash{String => Object}] the permitted attributes - def permitted_attributes(record, action = action_name) + def permitted_attributes(record, action = action_name, policy_class: nil) policy = policy(record) method_name = if policy.respond_to?("permitted_attributes_for_#{action}") "permitted_attributes_for_#{action}" From 6b6c6dd9317342ab18e0b339ff7ccc689db0814c Mon Sep 17 00:00:00 2001 From: Marcel Hoppe Date: Wed, 1 Feb 2023 08:54:02 +0100 Subject: [PATCH 2/3] Use same cache structure for authorize and permitted_attributes --- lib/pundit.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pundit.rb b/lib/pundit.rb index 99b35023..1b286264 100644 --- a/lib/pundit.rb +++ b/lib/pundit.rb @@ -78,7 +78,7 @@ def authorize(user, possibly_namespaced_record, query, policy_class: nil, cache: policy = if policy_class policy_class.new(user, record) else - cache[possibly_namespaced_record] ||= policy!(user, possibly_namespaced_record) + cache[{policy_class: policy_class, record: possibly_namespaced_record}] ||= policy!(user, possibly_namespaced_record) end raise NotAuthorizedError, query: query, record: record, policy: policy unless policy.public_send(query) From 38ae9d3dac3e2758ee2a8dd6222df7804ab81ffd Mon Sep 17 00:00:00 2001 From: Marcel Hoppe Date: Wed, 1 Feb 2023 09:17:00 +0000 Subject: [PATCH 3/3] Fix linting and specs --- lib/pundit.rb | 3 ++- lib/pundit/authorization.rb | 12 ++++++------ spec/authorization_spec.rb | 6 +++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/pundit.rb b/lib/pundit.rb index 1b286264..13814269 100644 --- a/lib/pundit.rb +++ b/lib/pundit.rb @@ -78,7 +78,8 @@ def authorize(user, possibly_namespaced_record, query, policy_class: nil, cache: policy = if policy_class policy_class.new(user, record) else - cache[{policy_class: policy_class, record: possibly_namespaced_record}] ||= policy!(user, possibly_namespaced_record) + cache[{ policy_class: policy_class, + record: possibly_namespaced_record }] ||= policy!(user, possibly_namespaced_record) end raise NotAuthorizedError, query: query, record: record, policy: policy unless policy.public_send(query) diff --git a/lib/pundit/authorization.rb b/lib/pundit/authorization.rb index 5acb18fb..2c7974cc 100644 --- a/lib/pundit/authorization.rb +++ b/lib/pundit/authorization.rb @@ -101,11 +101,11 @@ def policy_scope(scope, policy_scope_class: nil) # @param policy_class [Class] the policy class we want to force use of # @return [Object, nil] instance of policy class with query methods def policy(record, policy_class: nil) - policies[{policy_class: policy_class, record: record}] ||= if policy_class - policy_class.new(pundit_user, record) - else - Pundit.policy!(pundit_user, record) - end + policies[{ policy_class: policy_class, record: record }] ||= if policy_class + policy_class.new(pundit_user, record) + else + Pundit.policy!(pundit_user, record) + end end # Retrieves a set of permitted attributes from the policy by instantiating @@ -121,7 +121,7 @@ def policy(record, policy_class: nil) # @param policy_class [Class] the policy class we want to force use of # @return [Hash{String => Object}] the permitted attributes def permitted_attributes(record, action = action_name, policy_class: nil) - policy = policy(record) + policy = policy(record, policy_class: policy_class) method_name = if policy.respond_to?("permitted_attributes_for_#{action}") "permitted_attributes_for_#{action}" else diff --git a/spec/authorization_spec.rb b/spec/authorization_spec.rb index 2995bfdb..b567cf96 100644 --- a/spec/authorization_spec.rb +++ b/spec/authorization_spec.rb @@ -104,9 +104,9 @@ end it "caches the policy" do - expect(controller.policies[post]).to be_nil + expect(controller.policies[{ policy_class: nil, record: post }]).to be_nil controller.authorize(post) - expect(controller.policies[post]).not_to be_nil + expect(controller.policies[{ policy_class: nil, record: post }]).not_to be_nil end it "raises an error when the given record is nil" do @@ -155,7 +155,7 @@ it "allows policy to be injected" do new_policy = OpenStruct.new - controller.policies[post] = new_policy + controller.policies[{ policy_class: nil, record: post }] = new_policy expect(controller.policy(post)).to eq new_policy end