NAME

WeBWorK::PG::RestrictedClosureClass - Protect instance data and only allow calling of specified methods.

SYNPOSIS

package MyScaryClass;

sub new { return bless { @_[1..$#_] }, ref $_[0] || $_[0] }
sub get_secret { return $_[0]->{secret_data} }
sub set_secret { $_[0]->{secret_data} = $_[1] }
sub use_secret { print "Secret length is ".length($_[0]->get_secret) }
sub call_for_help { print "HELP!!" }

package main;
use WeBWorK::PG::RestrictedClosureClass;

my $unlocked = new MyScaryClass(secret_data => "pErL iS gReAt");
my $locked = new WeBWorK::PG::RestrictedClosureClass($obj, qw/use_secret call_for_help/);

$unlocked->get_secret;                # OK
$unlocked->set_secret("fOoBaR");      # OK
$unlocked->use_secret;                # OK
$unlocked->call_for_help;             # OK
print $unlocked->{secret_data};       # OK
$unlocked->{secret_data} = "WySiWyG"; # OK

$locked->get_secret;                  # NG (not in method list)
$locked->set_secret("fOoBaR");        # NG (not in method list)
$locked->use_secret;                  # OK
$locked->call_for_help;               # OK
print $locked->{secret_data};         # NG (not a hash reference)
$locked->{secret_data} = "WySiWyG";   # NG (not a hash reference)

DESCRIPTION

RestrictedClosureClass generates a wrapper object for a given object that prevents access to the objects instance data and only allows specified method calls. The wrapper object is a closure that calls methods of the underlying object, if permitted.

This is great for exposing a limited API to an untrusted environment, i.e. the PG Safe compartment.

CONSTRUCTOR

$wrapper_object = CLASS->new($object, @methods)

Generate a wrapper object for the given $object. Only calls to the methods listed in @methods will be permitted.

LIMITATIONS

You can't call SUPER methods, or methods with an explicit class given:

$locked->SUPER::call_for_help         # NG, would be superclass of RestrictedClosureClass

SEE ALSO

"Closures-as-Objects" in perltoot