App-Netdisco

 view release on metacpan or  search on metacpan

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

package App::Netdisco::Util::Port;

use Dancer qw/:syntax :script/;
use Dancer::Plugin::DBIC 'schema';
use Dancer::Plugin::Auth::Extensible;

use App::Netdisco::Util::Device 'get_device';
use App::Netdisco::Util::Permission qw/acl_matches acl_matches_only/;

use base 'Exporter';
our @EXPORT = ();
our @EXPORT_OK = qw/
  sync_portctl_roles
  port_acl_service port_acl_pvid port_acl_name
  get_port get_iid get_powerid
  is_vlan_subinterface port_has_phone port_has_wap
  to_speed
/;
our %EXPORT_TAGS = (all => \@EXPORT_OK);

=head1 NAME

App::Netdisco::Util::Port

=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 sync_portctl_roles()

Loads Port Control Roles from the database and merges them into the
C<portctl_role> config. This should only be done lazily and near to the
time of use, to be efficient and also to get latest ACL settings.

If there exists an entry in C<portctl_role> config from C<deployment.yml>
with the same name as a database role, then the database role overwrites
it. If such a role is removed, then a backup of the original is restored.

=cut

sub sync_portctl_roles {
  my @db_roles = schema(vars->{'tenant'})
    ->resultset('PortCtlRole')->role_names;
  config->{'portctl_by_role'} = {};

  foreach my $role (sort {$a cmp $b} keys %{ setting('portctl_by_role_shadow') }) {
      config->{'portctl_by_role'}->{$role}
        = (setting('portctl_by_role_shadow')->{$role} || '!group:__ANY__');
  }

  foreach my $role (@db_roles) {
      my @rows = schema(vars->{'tenant'})->resultset('PortCtlRole')
        ->search({ role_name => $role },
                 { prefetch => [qw/device_acl port_acl/], order_by => 'me.id' })->all;

      config->{'portctl_by_role'}->{$role} = {};
      foreach my $pair (@rows) {
          # convert LHS device ACLs to named groups
          my $group = 'synthesized_group_'. $pair->device_acl->id;
          config->{'host_groups'}->{$group} = $pair->device_acl->rules;
          config->{'portctl_by_role'}->{$role}->{'group:'. $group}
            = $pair->port_acl->rules;
      }
  }
}

=head2 port_acl_by_role_check( $port, $device?, $user? )

=over 4

=item *

Permission check on C<portctl_by_role> if the device and user are provided. A
bare username will be promoted to a user instance.

=back

Will return false if these checks fail, otherwise true.

=cut

sub port_acl_by_role_check {
  my ($port, $device, $user) = @_;

  # skip user acls for netdisco-do --force jobs
  # this avoids the need to create a netdisco user in the DB and give rights
  return true if $ENV{ND2_DO_FORCE};

  # portctl_by_role check
  if ($device and ref $device and $user) {
    $user = ref $user ? $user :
      schema('netdisco')->resultset('User')
                        ->find({ username => $user });
    return false unless $user;

    # special case admin user allowed to continue, because
    # they can submit port control jobs



( run in 1.268 second using v1.01-cache-2.11-cpan-df04353d9ac )