App-Netdisco

 view release on metacpan or  search on metacpan

lib/App/Netdisco/Web.pm  view on Meta::CPAN

use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use Dancer::Plugin::Swagger;

use Dancer::Error;
use Dancer::Continuation::Route::ErrorSent;

use URI ();
use Socket6 (); # to ensure dependency is met
use HTML::Entities (); # to ensure dependency is met
use URI::QueryParam (); # part of URI, to add helper methods
use MIME::Base64 'encode_base64';
use Path::Class 'dir';
use Module::Load ();
use Data::Visitor::Tiny;
use Scalar::Util 'blessed';
use Storable 'dclone';
use URI::Based;

use App::Netdisco::Util::Web qw/
  interval_to_daterange
  request_is_api
  request_is_api_report
  request_is_api_search
/;
use App::Netdisco::Util::Permission qw/acl_matches acl_matches_only/;

BEGIN {
  no warnings 'redefine';

  # https://github.com/PerlDancer/Dancer/issues/967
  *Dancer::_redirect = sub {
      my ($destination, $status) = @_;
      my $response = Dancer::SharedData->response;
      $response->status($status || 302);
      $response->headers('Location' => $destination);
  };

  # neater than using Dancer::Plugin::Res to handle JSON differently
  *Dancer::send_error = sub {
      my ($body, $status) = @_;
      if (request_is_api) {
        status $status || 400;
        $body = '' unless defined $body;
        Dancer::Continuation::Route::ErrorSent->new(
            return_value => to_json { error => $body, return_url => param('return_url') }
        )->throw;
      }
      Dancer::Continuation::Route::ErrorSent->new(
          return_value => Dancer::Error->new(
              message => $body,
              code => $status || 500)->render()
      )->throw;
  };

  # to insert /t/$tenant if set
  # which is fine for building links, but not fine for
  # comparison to request->path, because when is_forward() the
  # request->path is changed...
  *Dancer::Request::uri_for = sub {
    my ($self, $part, $params, $dont_escape) = @_;
    my $uri = $self->base;

    if (vars->{'tenant'}) {
        $part = '/t/'. vars->{'tenant'} . $part;
    }

    # Make sure there's exactly one slash between the base and the new part
    my $base = $uri->path;
    $base =~ s|/$||;
    $part =~ s|^/||;
    $uri->path("$base/$part");

    $uri->query_form($params) if $params;

    return $dont_escape ? uri_unescape($uri->canonical) : $uri->canonical;
  };

  # ...so here we are monkeypatching request->path as well
  *Dancer::Request::path = sub {
    die "path is accessor not mutator" if scalar @_ > 1;
    my $self = shift;
    $self->_build_path() unless $self->{path};

    if (vars->{'tenant'} and $self->{path} !~ m{/t/}) {
        my $path = $self->{path};
        my $base = setting('path');
        my $tenant = '/t/' . vars->{'tenant'};

        $tenant = ($base . $tenant) if $base ne '/';
        $tenant .= '/' if $base eq '/';
        $path =~ s/^$base/$tenant/;

        return $path;
    }
    return $self->{path};
  };

  # implement same_site
  # from https://github.com/PerlDancer/Dancer-Session-Cookie/issues/20
  *Dancer::Session::Cookie::_cookie_params = sub {
      my $self     = shift;
      my $name     = $self->session_name;
      my $duration = $self->_session_expires_as_duration;
      my %cookie   = (
          name      => $name,
          value     => $self->_cookie_value,
          path      => setting('session_cookie_path') || '/',
          domain    => setting('session_domain'),
          secure    => setting('session_secure'),
          http_only => setting("session_is_http_only") // 1,
          same_site => setting("session_same_site"),
      );
      if ( defined $duration ) {
          $cookie{expires} = time + $duration;
      }
      return %cookie;
  };
}

use App::Netdisco::Web::AuthN;
use App::Netdisco::Web::Static;
use App::Netdisco::Web::Search;
use App::Netdisco::Web::Device;
use App::Netdisco::Web::Report;
use App::Netdisco::Web::API::Objects;
use App::Netdisco::Web::API::Queue;
use App::Netdisco::Web::API::Statistics;
use App::Netdisco::Web::Health;
use App::Netdisco::Web::Metrics;
use App::Netdisco::Web::AdminTask;
use App::Netdisco::Web::TypeAhead;
use App::Netdisco::Web::PortControl;
use App::Netdisco::Web::Statistics;
use App::Netdisco::Web::Password;
use App::Netdisco::Web::CustomFields;



( run in 2.519 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )