8000 Support default Pundint policy class. · activeadmin/activeadmin@c93f6f4 · GitHub
[go: up one dir, main page]

Skip to content

Commit c93f6f4

Browse files
Sebastian Nowaktimoschilling
Sebastian Nowak
authored andcommitted
Support default Pundint policy class.
basic form @seban on #3323, with changes from @timoschilling
1 parent 46e923e commit c93f6f4

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

lib/active_admin/pundit_adapter.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
require 'pundit'
44

5+
# Add a setting to the application to configure the pundit default policy
6+
ActiveAdmin::Application.inheritable_setting :pundit_default_policy, nil
7+
58
module ActiveAdmin
69

710
class PunditAdapter < AuthorizationAdapter
@@ -17,6 +20,12 @@ def scope_collection(collection, action = Auth::READ)
1720
# scoping is appliable only to read/index action
1821
# which means there is no way how to scope other actions
1922
Pundit.policy_scope!(user, collection)
23+
rescue Pundit::NotDefinedError => e
24+
if default_policy_class && default_policy_class.const_defined?(:Scope)
25+
default_policy_class::Scope.new(user, collection).resolve
26+
else
27+
raise e
28+
end
2029
end
2130

2231
def retrieve_policy(subject)
@@ -25,6 +34,12 @@ def retrieve_policy(subject)
2534
when Class then Pundit.policy!(user, subject.new)
2635
else Pundit.policy!(user, subject)
2736
end
37+
rescue Pundit::NotDefinedError => e
38+
if default_policy_class
39+
default_policy(user, subject)
40+
else
41+
raise e
42+
end
2843
end
2944

3045
def format_action(action, subject)
@@ -38,6 +53,16 @@ def format_action(action, subject)
3853
end
3954
end
4055

56+
private
57+
58+
def default_policy_class
59+
ActiveAdmin.application.pundit_default_policy && ActiveAdmin.application.pundit_default_policy.constantize
60+
end
61+
62+
def default_policy(user, subject)
63+
default_policy_class.new(user, subject)
64+
end
65+
4166
end
4267

4368
end

lib/generators/active_admin/install/templates/active_admin.rb.erb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ ActiveAdmin.setup do |config|
6565
# CanCanAdapter or make your own. Please refer to documentation.
6666
# config.authorization_adapter = ActiveAdmin::CanCanAdapter
6767

68+
# In case you prefer Pundit over other solutions you can here pass
69+
# the name of default policy class. This policy will be used in every
70+
# case when Pundit is unable to find suitable policy.
71+
# config.pundit_default_policy = "MyDefaultPunditPolicy"
72+
6873
# You can customize your CanCan Ability class name here.
6974
# config.cancan_ability_class = "Ability"
7075

spec/unit/pundit_adapter_spec.rb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
require 'rails_helper'
22

3+
class DefaultPolicy < ApplicationPolicy
4+
class Scope
5+
6+
attr_reader :user, :scope
7+
8+
def initialize(user, scope)
9+
@user = user
10+
@scope = scope
11+
end
12+
13+
def resolve
14+
scope
15+
end
16+
end
17+
end
18+
319
describe ActiveAdmin::PunditAdapter do
420

521
describe "full integration" do
@@ -8,6 +24,8 @@
824
let(:namespace) { ActiveAdmin::Namespace.new(application, "Admin") }
925
let(:resource) { namespace.register(Post) }
1026
let(:auth) { namespace.authorization_adapter.new(resource, double) }
27+
let(:default_policy_klass) { DefaultPolicy }
28+
let(:default_policy_klass_name) { "DefaultPolicy" }
1129

1230
before do
1331
namespace.authorization_adapter = ActiveAdmin::PunditAdapter
@@ -31,6 +49,31 @@ def resolve
3149
auth.scope_collection(collection, :read)
3250
expect(collection).to eq collection
3351
end
52+
53+
context 'when Pundit is unable to find policy scope' do
54+
let(:collection) { double("collection", to_sym: :collection) }
55+
subject(:scope) { auth.scope_collection(collection, :read) }
56+
57+
before do
58+
allow(ActiveAdmin.application).to receive(:pundit_default_policy).and_return default_policy_klass_name
59+
allow(Pundit).to receive(:policy_scope!) { raise Pundit::NotDefinedError.new }
60+
end
61+
62+
it("should return default policy's scope if defined") { is_expected.to eq(collection) }
63+
end
64+
65+
context "when Pundit is unable to find policy" do
66+
let(:record) { double }
67+
68+
subject(:policy) { auth.retrieve_policy(record) }
69+
70+
before do
71+
allow(ActiveAdmin.application).to receive(:pundit_default_policy).and_return default_policy_klass_name
72+
allow(Pundit).to receive(:policy!) { raise Pundit::NotDefinedError.new }
73+
end
74+
75+
it("should return default policy instance") { is_expected.to be_instance_of(default_policy_klass) }
76+
end
3477
end
3578

3679
end

0 commit comments

Comments
 (0)
0