diff --git a/lib/rails_admin/extensions/cancancan/authorization_adapter.rb b/lib/rails_admin/extensions/cancancan/authorization_adapter.rb index 46c71f6d11..645bf1d676 100644 --- a/lib/rails_admin/extensions/cancancan/authorization_adapter.rb +++ b/lib/rails_admin/extensions/cancancan/authorization_adapter.rb @@ -5,20 +5,35 @@ module CanCanCan class AuthorizationAdapter < RailsAdmin::Extensions::CanCan::AuthorizationAdapter def authorize(action, abstract_model = nil, model_object = nil) return unless action - action, subject = resolve_action_and_subject(action, abstract_model, model_object) - @controller.current_ability.authorize!(action, subject) + subject = model_object || abstract_model && abstract_model.model + if authorized_for_dashboard_in_legacy_way?(action) + subject + else + @controller.current_ability.authorize!(*resolve_with_compatibility(action, subject)) + end end def authorized?(action, abstract_model = nil, model_object = nil) return unless action - action, subject = resolve_action_and_subject(action, abstract_model, model_object) - @controller.current_ability.can?(action, subject) + subject = model_object || abstract_model && abstract_model.model + authorized_for_dashboard_in_legacy_way?(action, true) || + @controller.current_ability.can?(*resolve_with_compatibility(action, subject)) end private - def resolve_action_and_subject(action, abstract_model, model_object) - subject = model_object || abstract_model && abstract_model.model + def authorized_for_dashboard_in_legacy_way?(action, silent = false) + return false unless action == :dashboard + legacy_ability = @controller.current_ability.permissions[:can][:dashboard] + if legacy_ability && (legacy_ability.empty? || legacy_ability.all?(&:empty?)) + ActiveSupport::Deprecation.warn('RailsAdmin CanCanCan Ability with `can :dashboard` is old and support will be removed in the next major release, use `can :read, :dashboard` instead. See https://github.com/sferik/rails_admin/issues/2901') unless silent + true + else + false + end + end + + def resolve_with_compatibility(action, subject) if subject [action, subject] else diff --git a/spec/integration/authorization/cancancan_spec.rb b/spec/integration/authorization/cancancan_spec.rb index 891b8a2a5e..6e7d4b269e 100644 --- a/spec/integration/authorization/cancancan_spec.rb +++ b/spec/integration/authorization/cancancan_spec.rb @@ -340,4 +340,27 @@ def initialize(user) end end end + + describe 'with existing dashboard ability which uses no subject' do + class LegacyDashboardAbility + include CanCan::Ability + def initialize(_) + can :access, :rails_admin + can :dashboard + end + end + + before do + RailsAdmin.config { |c| c.authorize_with :cancancan, LegacyDashboardAbility } + @user = FactoryGirl.create :user + login_as @user + end + + it 'shows dashboard with instruction on how to migrate to new ability notation' do + allow(ActiveSupport::Deprecation).to receive(:warn) + expect(ActiveSupport::Deprecation).to receive(:warn).with(/can :read, :dashboard/) + visit dashboard_path + is_expected.to have_content('Dashboard') + end + end end if defined?(CanCanCan)