WeBWorK::PG::RestrictedClosureClass - Protect instance data and only allow calling of specified methods.
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)
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.
Generate a wrapper object for the given $object. Only calls to the methods listed in @methods will be permitted.
You can't call SUPER methods, or methods with an explicit class given:
$locked->SUPER::call_for_help # NG, would be superclass of RestrictedClosureClass