Skip to content

Commit c84d170

Browse files
committed
BREAKING CHANGE: Stop authorization adapters assigning attributes on create and update, just check for permission instead
Newly created object still gets attributes assigned. Closes #3120
1 parent 70a00b0 commit c84d170

File tree

5 files changed

+50
-8
lines changed

5 files changed

+50
-8
lines changed

lib/rails_admin/config/actions/edit.rb

+1-3
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ class Edit < RailsAdmin::Config::Actions::Base
2525
sanitize_params_for!(request.xhr? ? :modal : :update)
2626

2727
@object.set_attributes(params[@abstract_model.param_key])
28-
@authorization_adapter && @authorization_adapter.attributes_for(:update, @abstract_model).each do |name, value|
29-
@object.send("#{name}=", value)
30-
end
28+
@authorization_adapter && @authorization_adapter.authorize(:update, @abstract_model, @object)
3129
changes = @object.changes
3230
if @object.save
3331
@auditing_adapter && @auditing_adapter.update_object(@object, @abstract_model, _current_user, changes)

lib/rails_admin/config/actions/new.rb

+1-3
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,7 @@ class New < RailsAdmin::Config::Actions::Base
3636
sanitize_params_for!(request.xhr? ? :modal : :create)
3737

3838
@object.set_attributes(params[@abstract_model.param_key])
39-
@authorization_adapter && @authorization_adapter.attributes_for(:create, @abstract_model).each do |name, value|
40-
@object.send("#{name}=", value)
41-
end
39+
@authorization_adapter && @authorization_adapter.authorize(:create, @abstract_model, @object)
4240

4341
if @object.save
4442
@auditing_adapter && @auditing_adapter.create_object(@object, @abstract_model, _current_user)

spec/integration/authorization/cancancan_spec.rb

+14
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,13 @@ def initialize(user)
132132
expect(@player).to be_suspended # suspended is inherited behavior based on permission
133133
end
134134

135+
it 'POST /admin/player/new with unauthorized attribute value should raise access denied' do
136+
visit new_path(model_name: 'player')
137+
fill_in 'player[name]', with: 'Jackie Robinson'
138+
uncheck 'player[suspended]'
139+
expect { click_button 'Save' }.to raise_error(CanCan::AccessDenied)
140+
end
141+
135142
it 'GET /admin/player/1/edit should raise access denied' do
136143
@player = FactoryBot.create :player
137144
expect { visit edit_path(model_name: 'player', id: @player.id) }.to raise_error(CanCan::AccessDenied)
@@ -163,6 +170,13 @@ def initialize(user)
163170
expect { visit edit_path(model_name: 'player', id: @player.id) }.to raise_error(CanCan::AccessDenied)
164171
end
165172

173+
it 'PUT /admin/player/new with unauthorized attribute value should raise access denied' do
174+
@player = FactoryBot.create :player
175+
visit edit_path(model_name: 'player', id: @player.id)
176+
check 'player[retired]'
177+
expect { click_button 'Save' }.to raise_error(CanCan::AccessDenied)
178+
end
179+
166180
it 'GET /admin/player/1/delete should raise access denied' do
167181
@player = FactoryBot.create :player
168182
expect { visit delete_path(model_name: 'player', id: @player.id) }.to raise_error(CanCan::AccessDenied)

spec/integration/authorization/pundit_spec.rb

+26
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,32 @@
9797
end
9898
end
9999

100+
describe 'with create and read player role' do
101+
before do
102+
@user.update(roles: [:admin, :read_player, :create_player])
103+
end
104+
105+
it 'POST /admin/player/new with unauthorized attribute value should raise access denied' do
106+
visit new_path(model_name: 'player')
107+
fill_in 'player[name]', with: 'Jackie Robinson'
108+
uncheck 'player[suspended]'
109+
expect { click_button 'Save' }.to raise_error(Pundit::NotAuthorizedError)
110+
end
111+
end
112+
113+
describe 'with update and read player role' do
114+
before do
115+
@user.update(roles: [:admin, :read_player, :update_player])
116+
end
117+
118+
it 'PUT /admin/player/new with unauthorized attribute value should raise access denied' do
119+
@player = FactoryBot.create :player
120+
visit edit_path(model_name: 'player', id: @player.id)
121+
check 'player[retired]'
122+
expect { click_button 'Save' }.to raise_error(Pundit::NotAuthorizedError)
123+
end
124+
end
125+
100126
context 'when ApplicationController already has pundit_user' do
101127
let(:admin) { FactoryBot.create :user, roles: [:admin] }
102128
before do

spec/policies.rb

+8-2
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ def index?
3333
def new?
3434
user.roles.include? :admin
3535
end
36+
alias create? new?
3637

3738
def edit?
3839
user.roles.include? :admin
3940
end
41+
alias update? edit?
4042

4143
def export?
4244
user.roles.include? :admin
@@ -49,12 +51,16 @@ def rails_admin_index?
4951

5052
class PlayerPolicy < ApplicationPolicy
5153
def new?
52-
(user.roles.include?(:create_player) || user.roles.include?(:admin) || user.roles.include?(:manage_player))
54+
(user.roles.include?(:manage_player) ||
55+
(user.roles.include?(:create_player) && (!record.is_a?(Player) || record.suspended)))
5356
end
57+
alias create? new?
5458

5559
def edit?
56-
(user.roles.include? :manage_player)
60+
(user.roles.include?(:manage_player) ||
61+
(user.roles.include?(:update_player) && (!record.is_a?(Player) || !record.retired)))
5762
end
63+
alias update? edit?
5864

5965
def destroy?
6066
(user.roles.include? :manage_player)

0 commit comments

Comments
 (0)