Skip Menu |
 

This queue is for tickets about the Object-InsideOut CPAN distribution.

Report information
The Basics
Id: 32109
Status: resolved
Priority: 0/
Queue: Object-InsideOut

People
Owner: Nobody in particular
Requestors: perl [...] dannywarren.com
Cc:
AdminCc:

Bug Information
Severity: Unimportant
Broken in: 3.35
Fixed in: (no value)



Subject: Permissions error when calling :Restricted method in an adjacent parent class
Download (untitled) / with headers
text/plain 2.2k
First, thank you for all your work on this amazing module. Having this at my disposal makes refactoring old code and building new libraries a pleasure. Please see the attached test.pl and test.error files, as those describe the issue better than I am about to. In short, I am unable to call a :Restricted method from an adjacent parent class. For example, in the following layout... package Baz; { use Object::InsideOut; } package Bar; { use Object::InsideOut; } package Foo; { use Object::InsideOut qw| Bar Baz |; } ..all three objects would report themselves as belonging to Foo, Bar and Baz via "->isa()" or "->meta()->get_classes()". I would therefore expect to be able to call :Restricted methods in Baz from Bar, and vice- versa, since they are now in the hierarchy chain thanks to Foo. However, attempts to call a :Restricted method in Baz from Bar results in a permissions failure. Looking at the Object::InsideOut closure that performs the permission checks... # Returns a 'wrapper' closure back to initialize() that restricts a method # to being only callable from within its class hierarchy sub wrap_RESTRICTED :Sub(Private) { my ($pkg, $method, $code, $except) = @_; return sub { # Caller must be in class hierarchy, or be specified as an exception my $caller = caller(); if (! ((grep { $_ eq $caller } @$except) || $GBL{'isa'}->($caller, $pkg) || $GBL{'isa'}->($pkg, $caller))) { OIO::Method->die('message' => "Can't call restricted method '$pkg->$method' from class '$caller'"); } goto $code; }; } ...I see that it is using the original UNIVERSAL::isa directly instead of passing it through the overloaded one, which returns false in this case and prevents the call to the :Restricted method. If I make it public or add an exemption, it of course works fine. It is entirely possible that I am grossly misunderstanding the hierarchy coupling, so if this is the case please let me know. Given my ignorance of the underlying mechanisms, though, it seems to me like if I get a thumbs up from $self->isa() in my app code, I should be able to call :Restricted methods therein. Thanks in advance for looking at this!
Subject: perl.version
Download perl.version
application/octet-stream 2.9k

Message body not shown because it is not plain text.

Subject: test.pl
Download test.pl
text/x-perl 1.2k
package Derp; { use Object::InsideOut; sub say_derp { my ( $self ) = @_; print "Derp isa: " . ( join q{ }, $self->isa() ) . "\n" ; return; } } package Baz; { use Object::InsideOut; sub say_baz :Restricted { my ( $self ) = @_; print "Baz isa: " . ( join q{ }, $self->isa() ) . "\n" ; return; } } package Bar; { use Object::InsideOut; sub say_bar :Restricted { my ( $self ) = @_; print "Bar isa: " . ( join q{ }, $self->isa() ) . "\n" ; # THIS WORKS # Say hello from a public method in one of the other parents # in the hierarchy $self->say_derp(); # THIS FAILS # Say hello from a restricted method in one of the other parents # in the hierarchy $self->say_baz(); } } package Foo; { use Object::InsideOut qw| Bar Baz Derp |; sub say_foo { my ( $self ) = @_; print "Foo isa: " . ( join q{ }, $self->isa() ) . "\n" ; # Say hello from a restricted method in one of our parents, Bar $self->say_bar(); return; } } package main; my $foo = Foo->new(); $foo->say_foo();
Subject: test.error
Download test.error
application/octet-stream 354b

Message body not shown because it is not plain text.

Subject: os.version
Download os.version
application/octet-stream 36b

Message body not shown because it is not plain text.

From: jdhedden [...] cpan.org
Download (untitled) / with headers
text/plain 1.2k
Show quoted text
> package Baz; > { use Object::InsideOut; } > > package Bar; > { use Object::InsideOut; } > > package Foo; > { use Object::InsideOut qw| Bar Baz |; } > > > ..all three objects would report themselves as belonging > to Foo, Bar and Baz via "->isa()" or > "->meta()->get_classes()".
Not quite. Bar isa Bar, Baz isa Baz and Foo is all three. package Baz; { use Object::InsideOut; } package Bar; { use Object::InsideOut; } package Foo; { use Object::InsideOut qw| Bar Baz |; } package main; my $baz = Baz->new(); print('BAZ: ', $baz->isa(), "\n"); my $bar = Bar->new(); print('BAR: ', $bar->isa(), "\n"); my $foo = Foo->new(); print('FOO: ', $foo->isa(), "\n"); produces: BAZ: Baz BAR: Bar FOO: BarBazFoo It is a hierarchy, and not an agglomeration. Show quoted text
> I would therefore expect to be able to call :Restricted > methods in Baz from Bar, and vice-versa, since they are > now in the hierarchy chain thanks to Foo.
No. Foo knows about both its parents, but the other two are independent of each other. When you have a hierarchy, child classes know about parent classes higher up in the hierarchy, but parent classes don't know about each other. It's a tree, and not a 'chain'.
Download (untitled) / with headers
text/plain 451b
Show quoted text
> When you have a hierarchy, child classes know about parent > classes higher up in the hierarchy, but parent classes don't > know about each other.
On reading the docs, I see that this could be made clearer with respect to describing :Restricted methods. I'll do that for the next release. In your case, you can use the 'Exemptions' feature for methods in Bar/Baz you want to call from each other. See the docs for details. Thanks for using OIO.
From: perl [...] dannywarren.com
Download (untitled) / with headers
text/plain 803b
On Tue Jan 08 17:28:27 2008, JDHEDDEN wrote: Show quoted text
> > When you have a hierarchy, child classes know about parent > > classes higher up in the hierarchy, but parent classes don't > > know about each other.
> > On reading the docs, I see that this could be made clearer > with respect to describing :Restricted methods. I'll do > that for the next release. > > In your case, you can use the 'Exemptions' feature for > methods in Bar/Baz you want to call from each other. See > the docs for details. > > Thanks for using OIO.
...and thank *you* for taking the time to look over my ticket and answering my questions, even though the issue turned out to be a misunderstanding on my part. Looks like I have some more reading and refactoring to do! Thanks again for all your awesome work in this module.
(accidental re-open)


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

Please report any issues with rt.cpan.org to rt-cpan-admin@bestpractical.com.