RSS Git Download  Clone
Raw Blame History
package DPAE::Plugin::Admin;

# adapted from Dancer2::Plugin::Auth::Tiny
# usage: get '/foo' => needs_admin sub { ... };

our $VERSION = '0.1';

# use Carp::Always::Color; # stacktrace on warn
use Dancer2::Plugin;
use Data::Printer;
use Data::Dumper;
use Modern::Perl;

register 'needs_admin' => sub {
    my ($dsl, @args) = @_; # p $_ for ($dsl, @args); plugin_args() no longer used

	my $builder = \&_builder; # p $builder;
	return $builder->($dsl, @args);
};
register_plugin;

#==============================================================================
sub _builder {
    my ($dsl, $coderef) = @_; # p $dsl; # p$coderef;

	# original D2::Plugin assumed caller would be under D2::Plugin namespace, here
	# we will check this package is under any Plugin namespace (eg MyApp::Plugin::Foo):
	my $package = __PACKAGE__; # adapted from Dancer2::Plugin::plugin_setting():
	my ($plugin_name) = $package =~ /Plugin::(.*)/ # need 'or' here, not '||':
		or die "$package package expected to live under 'Plugin' namespace"; # p $plugin_name;

	my $conf = $dsl->app->config->{plugins}->{$plugin_name} || {}; # p $conf;
	my @users = @{ $conf->{users} }; # p @users;

	return sub {
		my $app = shift; # Dancer2::Core::App object (same as $dsl->app)

        my $session_user_var = $conf->{session_user_var};
		my $logged_in_user   = $app->session->read($session_user_var)
            or return $app->redirect(
                $app->request->uri_for('/login',
                    { return_url => $app->request->uri_for( # original request:
                        $app->request->path, $app->request->params )
                    }
                )
            ); # redirect

		if ( @users && grep $logged_in_user eq $_, @users ) {
			# ok, current user *is* in @users list:
			return &$coderef; # same functionality as original "goto $coderef";
		}
		# either no defined admin users, or logged in user not in admin list:
		elsif ( my $handler = $conf->{permission_denied_handler} ) {
			my $route_filename = $app->name; # p $route_filename; # this is NOT same as config "appname"
			my $denied = join '::', $route_filename, $handler; # p $denied;
			no strict 'refs'; # suppress inevitable warning
			return &$denied; # sub to handle 'permission_denied' requests in route file
		}
		else {
			# return $app->redirect( $app->request->uri_for('/denied') ); # redirect
			return _default_permission_denied_html(); # html from local sub
		}
	};
}

sub _default_permission_denied_html {
    return '<h1>Permission Denied</h1>'
	. '<p>Sorry, you\'re not allowed to access that page.</p>';
}

1;