diff --git a/etc/Default.conf b/etc/Default.conf index c2159f273..5f7dd0f2d 100644 --- a/etc/Default.conf +++ b/etc/Default.conf @@ -578,6 +578,14 @@ IGNORE_IPV6_LINK_LOCAL => 0, # to 1 will allow underscores anywhere in a device name. ALLOW_UNDERSCORES_IN_DEVICE_NAMES => 0, +# Allow resource records (RR) to contain underscores by +# giving the web user a checkbox to override the underscore +# validation. This allows the default and common case of +# not allowing underscores to exist while still permitting the +# local user to override and allow a record with an underscore. +# This is useful for text (TXT) or service (SRV) records. +UNDERSCORES_IN_DEVICE_NAMES_OVERRIDE_ALLOWED => 0, + ##################################################################### # # IP Address Space Management diff --git a/htdocs/management/host.html b/htdocs/management/host.html index 39a5bc7db..794f647a9 100644 --- a/htdocs/management/host.html +++ b/htdocs/management/host.html @@ -242,6 +242,12 @@ push( @field_headers, $tmp{label} ); push( @cell_data, $tmp{value} ); + my $tmp_underscore_override = {}; + if ($ui->underscore_override_form_field($tmp_underscore_override)) { + push(@field_headers, $tmp_underscore_override->{label}); + push(@cell_data, $tmp_underscore_override->{value}); + } + $m->comp('/generic/attribute_table.mhtml', %comphash); (@field_headers, @cell_data) = ((),()); diff --git a/lib/Netdot/Model/RR.pm b/lib/Netdot/Model/RR.pm index 4f1521f1c..d219cbecc 100644 --- a/lib/Netdot/Model/RR.pm +++ b/lib/Netdot/Model/RR.pm @@ -208,8 +208,11 @@ sub insert { expiration => $argv->{expiration}, info => $argv->{info}, ); + my $extra_arguments = { + allow_underscore_override => $argv->{allow_underscore_override}, + }; - $class->_validate_args(\%state); + $class->_validate_args(\%state, $extra_arguments); $rr = $class->SUPER::insert(\%state); @@ -718,76 +721,99 @@ sub add_alias { ############################################################################ # _validate_args - Validate arguments to insert and update # -# Args: -# hashref -# Returns: +# Args: +# argv - hashref containing database field and values +# extra_argv - (optional) hashref containing extra parameters +# Returns: # True, or throws exception if validation fails # Examples: # $class->_validate_args($argv); # sub _validate_args { - my ($self, $argv) = @_; - + my ($self, $argv, $extra_argv) = @_; + + if (! defined $extra_argv) { + $extra_argv = {}; + } + my $zone; - if (ref($self)){ - $zone = $self->zone; + if (ref($self)) { + $zone = $self->zone; } - if ( defined $argv->{zone} ){ - if ( ref($argv->{zone}) ){ - # We're being passed an object - $zone = $argv->{zone} - }else{ - if ( $argv->{zone} =~ /\D+/ ){ - $zone = Zone->search(name=>$argv->{zone})->first; - }else{ - $zone = Zone->retrieve($argv->{zone}); - } - } + if (defined $argv->{zone}) { + if (ref($argv->{zone})) { + # We're being passed an object + $zone = $argv->{zone}; + } + else { + if ($argv->{zone} =~ /\D+/){ + $zone = Zone->search(name=>$argv->{zone})->first; + } + else { + $zone = Zone->retrieve($argv->{zone}); + } + } } - if ( defined $argv->{name} ){ - # Convert to lowercase - my $name = lc($argv->{name}); - - # Remove whitespace - $name =~ s/\s+//g; - - # Remove trailing dots, if any - $name =~ s/\.$//; - - # Remove commas - $name =~ s/,//; - - # Valid characters - if ( $name =~ /[^A-Za-z0-9\.\-_@\*]/ ){ - $self->throw_user("Invalid name: $name. Contains invalid characters"); - } - - if ( $self->config->get('ALLOW_UNDERSCORES_IN_DEVICE_NAMES') eq '0' ){ - # Underscore only allowed at beginning of string or dotted section - if ( $name =~ /[^^.]_/ || $name =~ /_$/ ){ - $self->throw_user("Invalid name: $name. Invalid underscores"); - } - } - - # Name must not start or end with a dash - if ( $name =~ /^\-/ || $name =~ /\-$/ ){ - $self->throw_user("Invalid name: $name. Name must not start or end with a dash"); - } - - # Length restrictions (RFC 1035) - my $fqdn = $name.".".$zone->name; - if ( length($fqdn) > 255 ){ - $self->throw_user("Invalid FQDN: $fqdn. Length exceeds 255 characters"); - } - # labels (sections between dots) must not exceed 63 chars - foreach my $label ( split(/\./, $fqdn) ){ - unless ( length($label) >= 1 && length($label) < 64 ){ - $self->throw_user(sprintf("RR::validate_args(): '%s' has Invalid label: '%s'. ". - "Each label must be between 1 and 63 characters long", - $fqdn, $label)); - } - } - $argv->{name} = $name; + if (defined $argv->{name}) { + # Convert to lowercase + my $name = lc($argv->{name}); + + # Remove whitespace + $name =~ s/\s+//g; + + # Remove trailing dots, if any + $name =~ s/\.$//; + + # Remove commas + $name =~ s/,//; + + # Valid characters + if ($name =~ /[^A-Za-z0-9\.\-_@\*]/) { + $self->throw_user("Invalid name: $name. Contains invalid characters"); + } + + if ( + $self->config->get('ALLOW_UNDERSCORES_IN_DEVICE_NAMES') eq '1' + || + ( + $self->config->get('UNDERSCORES_IN_DEVICE_NAMES_OVERRIDE_ALLOWED') eq '1' + && + $extra_argv->{allow_underscore_override} + ) + ) { + $logger->debug('Allow underscores in device name. No underscore validation check.'); + } + else { + # Underscore only allowed at beginning of string or dotted section + if ($name =~ /[^^.]_/ || $name =~ /_$/){ + $self->throw_user("Invalid name: $name. Invalid underscores"); + } + } + + # Name must not start or end with a dash + if ($name =~ /^\-/ || $name =~ /\-$/) { + $self->throw_user("Invalid name: $name. Name must not start or end with a dash"); + } + + # Length restrictions (RFC 1035) + my $fqdn = $name.".".$zone->name; + if (length($fqdn) > 255) { + $self->throw_user("Invalid FQDN: $fqdn. Length exceeds 255 characters"); + } + # labels (sections between dots) must not exceed 63 chars + for my $label (split(/\./, $fqdn)){ + unless (length($label) >= 1 && length($label) < 64) { + $self->throw_user( + sprintf( + "RR::validate_args(): '%s' has Invalid label: '%s'. ". + "Each label must be between 1 and 63 characters long", + $fqdn, + $label, + ) + ); + } + } + $argv->{name} = $name; } 1; } diff --git a/lib/Netdot/UI.pm b/lib/Netdot/UI.pm index 27fa2f54e..089d750a8 100644 --- a/lib/Netdot/UI.pm +++ b/lib/Netdot/UI.pm @@ -416,6 +416,53 @@ sub form_field { } } + +############################################################################ + +=head2 underscore_override_form_field - Return if Underscore Override checkbox if enabled. + + This method will populate a hashref with a label and checkbox to allow the + user to override the underscore validation for names. + If ALLOW_UNDERSCORES_IN_DEVICE_NAMES is set to true, then there is no + need to return the checkbox since underscores are allowed at the global + level. + If UNDERSCORES_IN_DEVICE_NAMES_OVERRIDE_ALLOWED is set to true then + return the checkbox to allow the user to override the underscore check + at a per device name. + + Arguments: + hashref to populate with label and value + Returns: + Boolean true or false if the calling code should add label and value + to the UI. + + Examples: + + my $tmp = {}; + if ($ui->underscore_override_form_field($tmp)) { + # do something with $tmp + } + +=cut + +sub underscore_override_form_field { + my $self = shift; + my $hash = shift; + + if ( + ! $self->config->get('ALLOW_UNDERSCORES_IN_DEVICE_NAMES') + && + $self->config->get('UNDERSCORES_IN_DEVICE_NAMES_OVERRIDE_ALLOWED') + ) { + $hash->{label} = 'Allow underscores:'; + $hash->{value} = ''; + return 1; + } + + return 0; +} + + ############################################################################ =head2 table_descr_link - Generate link to display a table\'s description