Ensure methods called on association proxies respect access control. [#1083 state:resolved] [Adam Milligan, Pratik]

This commit is contained in:
Pratik Naik 2008-10-13 19:01:37 +02:00
parent 42cbd710bb
commit 691aa20280
7 changed files with 60 additions and 2 deletions

View File

@ -140,6 +140,15 @@ module ActiveRecord
@target.inspect
end
def send(method, *args)
if proxy_respond_to?(method)
super
else
load_target
@target.send(method, *args)
end
end
protected
# Does the association have a <tt>:dependent</tt> option?
def dependent?
@ -197,6 +206,8 @@ module ActiveRecord
# Forwards any missing method call to the \target.
def method_missing(method, *args)
if load_target
raise NoMethodError unless @target.respond_to?(method)
if block_given?
@target.send(method, *args) { |*block_args| yield(*block_args) }
else

View File

@ -57,7 +57,7 @@ module ActiveRecord
protected
def owner_quoted_id
if @reflection.options[:primary_key]
quote_value(@owner.send(@reflection.options[:primary_key]))
@owner.class.quote_value(@owner.send(@reflection.options[:primary_key]))
else
@owner.quoted_id
end

View File

@ -428,4 +428,14 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
assert log.valid?
assert log.save
end
def test_belongs_to_proxy_should_not_respond_to_private_methods
assert_raises(NoMethodError) { companies(:first_firm).private_method }
assert_raises(NoMethodError) { companies(:second_client).firm.private_method }
end
def test_belongs_to_proxy_should_respond_to_private_methods_via_send
companies(:first_firm).send(:private_method)
companies(:second_client).firm.send(:private_method)
end
end

View File

@ -349,4 +349,14 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
assert companies(:first_firm).readonly_account.readonly?
end
def test_has_one_proxy_should_not_respond_to_private_methods
assert_raises(NoMethodError) { accounts(:signals37).private_method }
assert_raises(NoMethodError) { companies(:first_firm).account.private_method }
end
def test_has_one_proxy_should_respond_to_private_methods_via_send
accounts(:signals37).send(:private_method)
companies(:first_firm).account.send(:private_method)
end
end

View File

@ -110,4 +110,14 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
new_member.club = new_club = Club.create(:name => "LRUG")
assert_equal new_club, new_member.club.target
end
def test_has_one_through_proxy_should_not_respond_to_private_methods
assert_raises(NoMethodError) { clubs(:moustache_club).private_method }
assert_raises(NoMethodError) { @member.club.private_method }
end
def test_has_one_through_proxy_should_respond_to_private_methods_via_send
clubs(:moustache_club).send(:private_method)
@member.club.send(:private_method)
end
end

View File

@ -4,4 +4,10 @@ class Club < ActiveRecord::Base
has_many :current_memberships
has_one :sponsor
has_one :sponsored_member, :through => :sponsor, :source => :sponsorable, :source_type => "Member"
private
def private_method
"I'm sorry sir, this is a *private* club, not a *pirate* club"
end
end

View File

@ -13,6 +13,12 @@ class Company < AbstractCompany
def arbitrary_method
"I am Jack's profound disappointment"
end
private
def private_method
"I am Jack's innermost fears and aspirations"
end
end
module Namespaced
@ -129,9 +135,14 @@ class Account < ActiveRecord::Base
true
end
protected
def validate
errors.add_on_empty "credit_limit"
end
private
def private_method
"Sir, yes sir!"
end
end