App-Netdisco

 view release on metacpan or  search on metacpan

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

use App::Netdisco::Util::Permission 'check_acl';

use Time::Piece;
use Time::Seconds;
use HTML::Entities ();
use URI ();
use URI::QueryParam ();

use base 'Exporter';
our @EXPORT = ();
our @EXPORT_OK = qw/
  sort_port sort_modules
  interval_to_daterange
  sql_match
  request_is_device
  request_is_api
  request_is_api_report
  request_is_api_search
  trusted_client_address
  warn_forwarded_address_ignored
  device_display_name
  page_title
  pane_chrome
  pane_history_header
  escape_for_script_context
  escape_results_token
/;
our %EXPORT_TAGS = (all => \@EXPORT_OK);

=head1 NAME

App::Netdisco::Util::Web

=head1 DESCRIPTION

A set of helper subroutines to support parts of the Netdisco application.

There are no default exports, however the C<:all> tag will export all
subroutines.

=head1 EXPORT_OK

=head2 request_is_device

Client has requested device content under C<.../device> or C<.../device/ports>.

=cut

sub request_is_device {
  return (
    index(request->path, uri_for('/device')->path) == 0
      or
    index(request->path, uri_for('/ajax/content/device/details')->path) == 0
      or
    index(request->path, uri_for('/ajax/content/device/ports')->path) == 0
  );
}

=head2 request_is_api

Client has requested JSON format data and an endpoint under C</api>.

=cut

sub request_is_api {
  # /api/ paths are always API endpoints regardless of Accept header
  return 1 if index(request->path, uri_for('/api/')->path) == 0;
  # for other paths, require Accept: json and a return_url pointing to /api/
  return ((request->accept and request->accept =~ m/(?:json|javascript)/)
    and param('return_url')
    and index(param('return_url'), uri_for('/api/')->path) == 0);
}

=head2 request_is_api_report

Same as C<request_is_api> but also requires path to start "C</api/v1/report/...>".

=cut

sub request_is_api_report {
  return (request_is_api and (
    index(request->path, uri_for('/api/v1/report/')->path) == 0
      or
    (param('return_url')
    and index(param('return_url'), uri_for('/api/v1/report/')->path) == 0)
  ));
}

=head2 request_is_api_search

Same as C<request_is_api> but also requires path to start "C</api/v1/search/...>".

=cut

sub request_is_api_search {
  return (request_is_api and (
    index(request->path, uri_for('/api/v1/search/')->path) == 0
      or
    (param('return_url')
    and index(param('return_url'), uri_for('/api/v1/search/')->path) == 0)
  ));
}

=head2 trusted_client_address

The client address to make a security decision with.

This is the peer that opened the connection, unless that peer is named in the
C<trusted_proxies> setting, in which case it is the client named in the
C<X-Forwarded-For> chain that peer forwarded. The chain is read from its
nearest hop leftwards, stepping over any address which is itself a trusted
proxy, so a deployment two proxies deep resolves to the visitor rather than to
the inner proxy.

C<trusted_proxies> takes the usual access control list forms, so a Host Group
name works as well as a literal list.

A client on a UNIX socket is treated as the loopback address.

=cut

sub trusted_client_address {
  my $peer = _socket_peer_address();

  return $peer unless _is_trusted_proxy($peer);



( run in 0.612 second using v1.01-cache-2.11-cpan-16aabcbfbcb )