Dancer2-Plugin-WebService

 view release on metacpan or  search on metacpan

lib/Dancer2/Plugin/WebService.pm  view on Meta::CPAN

has pretty          => (is=>'rw', lazy=>1, default    => 1);
has route_name      => (is=>'rw', lazy=>1, default    => '');
has ClientIP        => (is=>'rw', lazy=>1, default    => '');
has reply_text      => (is=>'rw', lazy=>1, default    => '');
has auth_method     => (is=>'rw', lazy=>1, default    => '');
has auth_command    => (is=>'rw', lazy=>1, default    => '');
has data            => (is=>'rw', lazy=>1, default    => ''); # user posted data
has auth_config     => (is=>'rw', lazy=>1, default    => sub{ {} });
has Format          => (is=>'rw', lazy=>1, default    => sub{ {from => undef, to => undef} });
has Session_timeout => (is=>'ro', lazy=>0, from_config=> 'Session idle timeout',default=> sub{ 3600 }, isa => sub {unless ( $_[0]=~/^\d+$/ ) {warn "Session idle timeout \"$_[0]\" It is not a number\n"; exit 1}} );
has rules           => (is=>'ro', lazy=>0, from_config=> 'Allowed hosts',       default=> sub{ ['127.*', '192.168.*', '172.16.*'] });
has rules_compiled  => (is=>'ro', lazy=>0, default    => sub {my $array = [@{$_[0]->rules}]; for (@{$array}) { s/([^?*]+)/\Q$1\E/g; s|\?|.|g; s|\*+|.*?|g; $_ = qr/^$_$/i } $array});
has dir_session     => (is=>'ro', lazy=>0, default    => sub {my $D = exists $_[0]->config->{'Session directory'} ? $_[0]->config->{'Session directory'}."/$_[0]->{app}->{name}" : "$_[0]->{app}->{config}->{appdir}/session"; $D=~s|/+|/|g; my @MD = spli...
has OS              => (is=>'ro', lazy=>0, default    => sub {my $D = undef; foreach (qw[/usr/bin /bin /usr/sbin /sbin]) {if (-f "$_/uname") {$D="$_/uname"; last}; unless (defined $D) {warn "Could not found utility uname\n"; exit 1} } sub{-f $_[0] ? ...
has rm              => (is=>'ro', lazy=>0, default    => sub {foreach (qw[/usr/bin /bin /usr/sbin /sbin]) {return "$_/rm" if -f "$_/rm" && -x "$_/rm" } warn "Could not found utility rm\n"; exit 1});
has session_enable  => (is=>'ro', lazy=>0, default    => sub {exists $_[0]->config->{'Session enable'} ? $_[0]->config->{'Session enable'}=~/(?i)[y1t]/ ? 1:0 : 1});

# Recursive walker of complex and custon Data Structures
%Handler=(
SCALAR => sub { $Handler{WALKER}->(${$_[0]}, $_[1], @{$_[2]} )},
ARRAY  => sub { $Handler{WALKER}->($_, $_[1], @{$_[2]}) for @{$_[0]} },
HASH   => sub { $Handler{WALKER}->($_[0]->{$_}, $_[1], @{$_[2]}, $_) for sort keys %{$_[0]} },
''     => sub { $_[1]->($_[0], @{$_[2]}) },
WALKER => sub { my $data = shift; $Handler{ref $data}->($data, shift, \@_) }
);


sub BUILD
{
my $plg = shift;
my $app = $plg->app;

(my $module_dir =__FILE__) =~s|/[^/]+$||; # Module's directory
unless (-d $module_dir) { CORE::warn "Could not find the Dancer2::Plugin::WebService installation directory\n"; CORE::exit 1 }

# Built-in routes and their security
$plg->config->{Routes}->{logout}              = { Protected => 1, 'Built in' => 1, Groups=>[] }; # we should be logged in to logout
$plg->config->{Routes}->{login}               = { Protected => 0, 'Built in' => 1 };
$plg->config->{Routes}->{WebService}          = { Protected => 0, 'Built in' => 1 };
$plg->config->{Routes}->{'WebService/client'} = { Protected => 0, 'Built in' => 1 };
$plg->config->{Routes}->{'WebService/routes'} = { Protected => 0, 'Built in' => 1 };
$plg->config->{Routes}->{''}                  = { Protected => 2, 'Built in' => 1 };

# Default settings
$plg->config->{'Default format'}= 'json' if ((! exists $plg->config->{'Default format'}) || ($plg->config->{'Default format'} !~ $fmt_rgx));
$app->config->{content_type}    = $Formats{ $plg->config->{'Default format'} };
$app->config->{show_errors}   //= 0;
$app->config->{charset}       //= 'UTF-8';
$app->config->{encoding}      //= 'UTF-8';

  # Use the first active authentication method
  foreach my $method (@{$plg->config->{'Authentication methods'}}) {
  next unless ((exists $method->{Active}) && ($method->{Active}=~/(?i)[y1t]/));
  $plg->auth_method( $method->{Name} );

    # If the Authorization method is an external script
    if ($plg->auth_method ne 'INTERNAL') {
    unless (exists $method->{Command}) {warn "The active Authentication method \"".$plg->auth_method."\" does not know what to do\n"; exit 1}
    $method->{Command} =~s/^MODULE_INSTALL_DIR/$module_dir/;
    unless (-f $method->{Command}) {warn "Sorry, could not found the external authorization utility $method->{Command}\n"; exit 1}
    unless (-x $method->{Command}) {warn "Sorry, the external authorization utility $method->{Command} is not executable from user ". getpwuid($>) ."\n"; exit 1}

      if ((exists $method->{'Use sudo'}) && ($method->{'Use sudo'}=~/(?i)[y1t]/)) {
      my $sudo = undef;
      foreach (qw[/usr/bin /bin /usr/sbin /sbin]) { if ((-f "$_/sudo") && -x ("$_/sudo")) { $sudo="$_/sudo"; last } }
      unless (defined $sudo) {warn "Could not found sudo command\n"; exit 1}
      $plg->auth_command( "$sudo \Q$method->{Command}\E" )
      }
      else {
      $plg->auth_command( "\Q$method->{Command}\E" )
      }
    }

  delete @{$method}{'Name','Active','Command','Use sudo'};
  $method->{Arguments} //= [];
  $plg->auth_config($method);
  last
  }

delete $plg->config->{'Session enable'};
delete $plg->config->{'Authentication methods'};

  if (($plg->session_enable) && ($plg->auth_method eq '')) {
  warn "\nWhile the sessions are enabled there is not any active authorization method at your config.yml\n";
  CORE::exit 1
  }

  # Check if there are protected routes
  foreach (keys %{$plg->config->{Routes}}) {
  next if exists  $plg->config->{Routes}->{$_}->{'Built in'};
  $plg->config->{Routes}->{$_}->{'Built in'}=0;

    if ((exists $plg->config->{Routes}->{$_}->{Protected}) && ($plg->config->{Routes}->{$_}->{Protected}=~/(?i)[y1t]/)) {

    delete $plg->config->{Routes}->{$_}->{Protected};
           $plg->config->{Routes}->{$_}->{Protected}=1;

      if ($plg->auth_method eq '') {
      warn "\nWhile there is at least one protected route ( $_ ) there is not any active authorization method at your config.yaml\n";
      CORE::exit 1
      }
      else {

        if (exists $plg->config->{Routes}->{$_}->{Groups}) {
        $plg->config->{Routes}->{$_}->{Groups} = [ $plg->config->{Routes}->{$_}->{Groups} ] unless 'ARRAY' eq ref $plg->config->{Routes}->{$_}->{Groups}
        }
        else {
        $plg->config->{Routes}->{$_}->{Groups} = []
        }
      }
    }
    else {
    delete $plg->config->{Routes}->{$_}->{Protected};
           $plg->config->{Routes}->{$_}->{Protected}=0
    }
  }

print STDOUT "\n";
print STDOUT "Application name      : ", $plg->dsl->config->{appname}  ,"\n";
print STDOUT 'Start time            : ', scalar localtime $^T ,"\n";
print STDOUT 'Run as user           : ', (getpwuid($>))[0] ,"\n";
print STDOUT "Command               : $0\n";
print STDOUT "PID parent            : ", getppid() ,"\n";
print STDOUT "PID Main              : $$\n";
print STDOUT 'Authorization method  : ', ( $plg->auth_method ? $plg->auth_method :'UNDEFINED' ) ,"\n";
print STDOUT "Authorization scripts : $module_dir/\n";
print STDOUT 'Environment           : ', $plg->dsl->config->{environment} ,"\n";
print STDOUT 'Logging               : ', $plg->dsl->config->{log} ,"\n";
print STDOUT 'Session enable        : ', ( $plg->session_enable ? 'Yes' : 'No') ,"\n";
print STDOUT 'Session directory     : ', $plg->dir_session ,"\n";
print STDOUT 'Session idle timeout  : ', $plg->Session_timeout ," sec\n";
print STDOUT "Version application   : ", ( exists $plg->dsl->config->{appversion} ? $plg->dsl->config->{appversion} : '0.0.0' ) ,"\n";
print STDOUT "Version Perl          : $^V\n";
print STDOUT "Version Dancer2       : $Dancer2::VERSION\n";
print STDOUT "Version WebService    : $VERSION\n";
print STDOUT "Operating system      : ", $plg->OS ,"\n";

# Restore the valid sessions, and delete the expired ones
opendir DIR, $plg->dir_session or die "Could not list session directory $plg->{dir_session} because $!\n";

  foreach my $token (grep ! /^\.+$/, readdir DIR) {

    if ((-f "$plg->{dir_session}/$token/control/lastaccess") && (-f "$plg->{dir_session}/$token/control/username") && (-f "$plg->{dir_session}/$token/control/groups")) {
    my $lastaccess = ${ Storable::retrieve "$plg->{dir_session}/$token/control/lastaccess" };

      if (time - $lastaccess > $plg->Session_timeout) {
      print STDOUT "Delete expired session: $token\n";
      system $plg->rm, '-rf', "$plg->{dir_session}/$token"
      }
      else {
        $TokenDB{$token}->{data} = {};
      @{$TokenDB{$token}->{control}}{qw/lastaccess username groups/} = ($lastaccess, ${Storable::retrieve "$plg->{dir_session}/$token/control/username"}, ${Storable::retrieve "$plg->{dir_session}/$token/control/groups"});

      opendir __TOKEN, "$plg->{dir_session}/$token/data" or die "Could not read session directory $plg->{dir_session}/$token/data because $!\n";

        foreach my $record (grep ! /^\.{1,2}$/, readdir __TOKEN) {
        next unless -f "$plg->{dir_session}/$token/data/$record";
        $record = Encode::decode('utf8', $record);
        $TokenDB{$token}->{data}->{$record} = Storable::retrieve "$plg->{dir_session}/$token/data/$record";
        $TokenDB{$token}->{data}->{$record} = ${ $TokenDB{$token}->{data}->{$record} } if 'SCALAR' eq ref $TokenDB{$token}->{data}->{$record}
        }

      close __TOKEN;
      print STDOUT "Restore session       : $token (". scalar(keys %{$TokenDB{$token}->{data}}) ." records)\n"
      }
    }
    else {    
    print STDOUT "Delete corrupt session: $token\n";
    system $plg->rm,'-rf',"$plg->{dir_session}/$token"
    }
  }

closedir DIR;
print STDOUT "\n";


#print STDERR Dumper( $app ) ;exit;
#print STDERR Dumper( $plg->config->{Routes} ) ;exit;
#print STDERR Dumper( $plg->auth_config )      ;exit;
#print STDERR Dumper  \%TokenDB; exit;
#print STDERR "---------\n*".  $plg->dir_session  ."*\n---------\n";



( run in 0.549 second using v1.01-cache-2.11-cpan-39bf76dae61 )