diff --git a/lib/cancan/conditions_matcher.rb b/lib/cancan/conditions_matcher.rb index c1a97b96..b93facd0 100644 --- a/lib/cancan/conditions_matcher.rb +++ b/lib/cancan/conditions_matcher.rb @@ -7,6 +7,7 @@ def matches_conditions?(action, subject, attribute = nil, *extra_args) return call_block_with_all(action, subject, extra_args) if @match_all return matches_block_conditions(subject, attribute, *extra_args) if @block return matches_non_block_conditions(subject) unless conditions_empty? + return subject_descendant?(subject) if subject_class?(subject) true end @@ -143,5 +144,12 @@ def conditions_empty? (@conditions.is_a?(Hash) && @conditions == {}) || @conditions.nil? end + + def subject_descendant?(subject) + return true if @subjects.include?(:all) + + subject = subject.values.first if subject.is_a?(Hash) + @subjects.any? { |sub| sub.is_a?(Module) && sub >= subject } + end end end diff --git a/spec/cancan/model_adapters/active_record_adapter_spec.rb b/spec/cancan/model_adapters/active_record_adapter_spec.rb index 810af592..2fb4c2f4 100644 --- a/spec/cancan/model_adapters/active_record_adapter_spec.rb +++ b/spec/cancan/model_adapters/active_record_adapter_spec.rb @@ -1426,6 +1426,27 @@ class Suzuki < Motorbike end end + it 'cannot rules are not effecting parent class' do + u1 = User.create!(name: 'pippo') + ability = Ability.new(u1) + + ability.can :manage, Vehicle + ability.cannot :manage, Car + + expect(ability.can?(:index, Vehicle)).to eq(true) + expect(ability.can?(:index, Car)).to eq(false) + end + + it 'can rules are not effecting parent class' do + u1 = User.create!(name: 'pippo') + ability = Ability.new(u1) + + ability.can :manage, Car + + expect(ability.can?(:index, Vehicle)).to eq(false) + expect(ability.can?(:index, Car)).to eq(true) + end + it 'recognises rules applied to the base class' do u1 = User.create!(name: 'pippo')