bind export, editing zones, deleting unaudited domains, mmm
authorivan <ivan>
Wed, 22 May 2002 18:44:01 +0000 (18:44 +0000)
committerivan <ivan>
Wed, 22 May 2002 18:44:01 +0000 (18:44 +0000)
FS/FS/domain_record.pm
FS/FS/part_export.pm
FS/FS/svc_domain.pm
bin/bind.export
httemplate/edit/process/domain_record.cgi [new file with mode: 0755]
httemplate/misc/cancel-unaudited.cgi
httemplate/misc/delete-domain_record.cgi [new file with mode: 0755]
httemplate/misc/delete-part_export.cgi
httemplate/view/svc_domain.cgi

index 6f4dd02..44e70ad 100644 (file)
@@ -3,7 +3,7 @@ package FS::domain_record;
 use strict;
 use vars qw( @ISA );
 #use FS::Record qw( qsearch qsearchs );
-use FS::Record qw( qsearchs );
+use FS::Record qw( qsearchs dbh );
 use FS::svc_domain;
 
 @ISA = qw(FS::Record);
@@ -71,12 +71,80 @@ otherwise returns false.
 
 =cut
 
+sub insert {
+  my $self = shift;
+
+  local $SIG{HUP} = 'IGNORE';
+  local $SIG{INT} = 'IGNORE';
+  local $SIG{QUIT} = 'IGNORE';
+  local $SIG{TERM} = 'IGNORE';
+  local $SIG{TSTP} = 'IGNORE';
+  local $SIG{PIPE} = 'IGNORE';
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+  my $dbh = dbh;
+
+  my $error = $self->SUPER::insert;
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
+
+  unless ( $self->rectype =~ /^(SOA|_mstr)$/ ) {
+    my $error = $self->increment_serial;
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+  '';
+
+}
+
 =item delete
 
 Delete this record from the database.
 
 =cut
 
+sub delete {
+  my $self = shift;
+
+  local $SIG{HUP} = 'IGNORE';
+  local $SIG{INT} = 'IGNORE';
+  local $SIG{QUIT} = 'IGNORE';
+  local $SIG{TERM} = 'IGNORE';
+  local $SIG{TSTP} = 'IGNORE';
+  local $SIG{PIPE} = 'IGNORE';
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+  my $dbh = dbh;
+
+  my $error = $self->SUPER::delete;
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
+
+  unless ( $self->rectype =~ /^(SOA|_mstr)$/ ) {
+    my $error = $self->increment_serial;
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+  '';
+
+}
+
 =item replace OLD_RECORD
 
 Replaces the OLD_RECORD with this one in the database.  If there is an error,
@@ -84,6 +152,40 @@ returns the error, otherwise returns false.
 
 =cut
 
+sub replace {
+  my $self = shift;
+
+  local $SIG{HUP} = 'IGNORE';
+  local $SIG{INT} = 'IGNORE';
+  local $SIG{QUIT} = 'IGNORE';
+  local $SIG{TERM} = 'IGNORE';
+  local $SIG{TSTP} = 'IGNORE';
+  local $SIG{PIPE} = 'IGNORE';
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+  my $dbh = dbh;
+
+  my $error = $self->SUPER::replace(@_);
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
+
+  unless ( $self->rectype eq 'SOA' ) {
+    my $error = $self->increment_serial;
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+  '';
+
+}
+
 =item check
 
 Checks all fields to make sure this is a valid example.  If there is
@@ -158,11 +260,34 @@ sub check {
   ''; #no error
 }
 
+=item increment_serial
+
+=cut
+
+sub increment_serial {
+  my $self = shift;
+
+  my $soa = qsearchs('domain_record', {
+    svcnum  => $self->svcnum,
+    reczone => '@', #or full domain ?
+    recaf   => 'IN',
+    rectype => 'SOA', 
+  } ) or return "soa record not found; can't increment serial";
+
+  my $data = $soa->recdata;
+  $data =~ s/(\(\D*)(\d+)/$1.($2+1)/e; #well, it works.
+
+  my %hash = $soa->hash;
+  $hash{recdata} = $data;
+  my $new = new FS::domain_record \%hash;
+  $new->replace($soa);
+}
+
 =back
 
 =head1 VERSION
 
-$Id: domain_record.pm,v 1.7 2002-04-20 11:57:35 ivan Exp $
+$Id: domain_record.pm,v 1.8 2002-05-22 18:44:01 ivan Exp $
 
 =head1 BUGS
 
index 94b819d..8a7ac8b 100644 (file)
@@ -141,7 +141,7 @@ sub insert {
 
   '';
 
-};
+}
 
 =item delete
 
@@ -361,7 +361,8 @@ sub option {
 
 Reblesses the object into the FS::part_export::EXPORTTYPE class, where
 EXPORTTYPE is the object's I<exporttype> field.  There should be better docs
-on how to create new exports, but until then, see L</NEW EXPORT CLASSES>.
+on how to create new exports (and they should live in their own files and be
+autoloaded-on-demand), but until then, see L</NEW EXPORT CLASSES>.
 
 =cut
 
@@ -369,7 +370,7 @@ sub rebless {
   my $self = shift;
   my $exporttype = $self->exporttype;
   my $class = ref($self). "::$exporttype";
-  eval "use $class;" or die $@;
+  eval "use $class;";
   bless($self, $class);
 }
 
@@ -617,13 +618,13 @@ tie my %bind_slave_options, 'Tie::IxHash',
     'bind' => {
       'desc' =>'Batch export to BIND named',
       'options' => \%bind_options,
-      'notes' => 'bind export notes',
+      'notes' => 'bind export notes File::Rsync dependancy, run bind.export',
     },
 
     'bind_slave' => {
       'desc' =>'Batch export to slave BIND named',
       'options' => \%bind_slave_options,
-      'notes' => 'bind export notes (secondary munge)',
+      'notes' => 'bind export notes (secondary munge) File::Rsync dependancy, run bind.export',
     },
 
 
index 3dea705..a9a2fd0 100644 (file)
@@ -255,10 +255,33 @@ sub delete {
     if defined( $FS::Record::dbdef->table('svc_acct_sm') )
        && qsearch('svc_acct_sm', { 'domsvc' => $self->svcnum } );
 
-  return "Can't delete a domain with (domain_record) zone entries!"
-    if qsearch('domain_record', { 'svcnum' => $self->svcnum } );
+  #return "Can't delete a domain with (domain_record) zone entries!"
+  #  if qsearch('domain_record', { 'svcnum' => $self->svcnum } );
 
-  $self->SUPER::delete;
+  local $SIG{HUP} = 'IGNORE';
+  local $SIG{INT} = 'IGNORE';
+  local $SIG{QUIT} = 'IGNORE';
+  local $SIG{TERM} = 'IGNORE';
+  local $SIG{TSTP} = 'IGNORE';
+  local $SIG{PIPE} = 'IGNORE';
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+  my $dbh = dbh;
+
+  my $error = $self->SUPER::delete;
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
+
+  foreach my $domain_record ( reverse $self->domain_record ) {
+    my $error = $domain_record->delete;
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
 }
 
 =item replace OLD_RECORD
@@ -369,6 +392,26 @@ sub check {
 
 }
 
+=item domain_record
+
+=cut
+
+sub domain_record {
+  my $self = shift;
+
+  my %order = (
+    SOA => 1,
+    NS => 2,
+    MX => 3,
+    CNAME => 4,
+    A => 5,
+  );
+
+  sort { $order{$a->rectype} <=> $order{$b->rectype} }
+    qsearch('domain_record', { svcnum => $self->svcnum } );
+
+}
+
 =item whois
 
 Returns the Net::Whois::Domain object (see L<Net::Whois>) for this domain, or
@@ -407,7 +450,7 @@ sub submit_internic {
 
 =head1 VERSION
 
-$Id: svc_domain.pm,v 1.28 2002-05-18 09:51:30 ivan Exp $
+$Id: svc_domain.pm,v 1.29 2002-05-22 18:44:01 ivan Exp $
 
 =head1 BUGS
 
index 8d6f4e3..d49b3cf 100755 (executable)
@@ -2,6 +2,8 @@
 
 use strict;
 use File::Path;
+use File::Rsync;
+use Net::SSH qw(ssh);
 use FS::UID qw(adminsuidsetup datasrc);
 use FS::Record qw(qsearch qsearchs);
 use FS::part_export;
@@ -18,9 +20,15 @@ mkdir $spooldir unless -d $spooldir;
 my @exports = qsearch('part_export', { 'exporttype' => 'bind' } );
 my @sexports = qsearch('part_export', { 'exporttype' => 'bind_slave' } );
 
+my $rsync = File::Rsync->new({
+  rsh     => 'ssh',
+#  dry_run => 1,
+});
+
 foreach my $export ( @exports ) {
 
-  my $prefix = "$spooldir/". $export->machine;
+  my $machine = $export->machine;
+  my $prefix = "$spooldir/$machine";
 
   #prevent old domain files from piling up
   #rmtree "$prefix" or die "can't rmtree $prefix.db: $!";
@@ -96,12 +104,30 @@ END
 
   }
 
+  $rsync->exec( {
+    src       => "$prefix/",
+    recursive => 1,
+    dest      => "root\@$machine:$zonepath/",
+    exclude   => [qw( *.import named.conf.HEADER named.conf )],
+  } ) or die "rsync to $machine failed: ". join(" / ", $rsync->err);
+ # warn $rsync->out;
+
+  $rsync->exec( {
+    src     => "$prefix/named.conf",
+    dest    => "root\@$machine:". $export->option('named_conf'),
+  } ) or die "rsync to $machine failed: ". join(" / ", $rsync->err);
+#  warn $rsync->out;
+
+  ssh("root\@$machine", 'ndc reload');
+
 }
+
 close NAMED_CONF;
 
 foreach my $sexport ( @sexports ) { #false laziness with above
 
-  my $prefix = "$spooldir/". $sexport->machine;
+  my $machine = $sexport->machine;
+  my $prefix = "$spooldir/$machine";
 
   #prevent old domain files from piling up
   #rmtree "$prefix" or die "can't rmtree $prefix.db: $!";
@@ -137,6 +163,14 @@ END
 
   }
 
+  $rsync->exec( {
+    src     => "$prefix/named.conf",
+    dest    => "root\@$machine:". $sexport->option('named_conf'),
+  } ) or die "rsync to $machine failed: ". join(" / ", $rsync->err);
+#  warn $rsync->out;
+
+  ssh("root\@$machine", 'ndc reload');
+
 }
 close NAMED_CONF;
 
diff --git a/httemplate/edit/process/domain_record.cgi b/httemplate/edit/process/domain_record.cgi
new file mode 100755 (executable)
index 0000000..8fb0368
--- /dev/null
@@ -0,0 +1,31 @@
+<%
+
+my $recnum = $cgi->param('recnum');
+
+my $old = qsearchs('agent',{'recnum'=>$recnum}) if $recnum;
+
+my $new = new FS::domain_record ( {
+  map {
+    $_, scalar($cgi->param($_));
+  } fields('domain_record')
+} );
+
+my $error;
+if ( $recnum ) {
+  $error=$new->replace($old);
+} else {
+  $error=$new->insert;
+  $recnum=$new->getfield('recnum');
+}
+
+if ( $error ) {
+#  $cgi->param('error', $error);
+#  print $cgi->redirect(popurl(2). "agent.cgi?". $cgi->query_string );
+  #no edit screen to send them back to
+  eidiot($error);
+} else { 
+  my $svcnum = $new->svcnum;
+  print $cgi->redirect(popurl(3). "view/svc_domain.cgi?$svcnum");
+}
+
+%>
index ecfaef2..f1fb153 100755 (executable)
@@ -7,15 +7,18 @@ my($query) = $cgi->keywords;
 $query =~ /^(\d+)$/;
 my $svcnum = $1;
 
-my $svc_acct = qsearchs('svc_acct',{'svcnum'=>$svcnum});
-die "Unknown svcnum!" unless $svc_acct;
+#my $svc_acct = qsearchs('svc_acct',{'svcnum'=>$svcnum});
+#die "Unknown svcnum!" unless $svc_acct;
 
 my $cust_svc = qsearchs('cust_svc',{'svcnum'=>$svcnum});
+die "Unknown svcnum!" unless $cust_svc;
 &eidiot(qq!This account has already been audited.  Cancel the 
     <A HREF="!. popurl(2). qq!view/cust_pkg.cgi?! . $cust_svc->getfield('pkgnum') .
     qq!pkgnum"> package</A> instead.!) 
   if $cust_svc->pkgnum ne '' && $cust_svc->pkgnum ne '0';
 
+my $svc_x = $cust_svc->svc_x;
+
 local $SIG{HUP} = 'IGNORE';
 local $SIG{INT} = 'IGNORE';
 local $SIG{QUIT} = 'IGNORE';
@@ -24,8 +27,8 @@ local $SIG{TSTP} = 'IGNORE';
 
 local $FS::UID::AutoCommit = 0;
 
-my $error = $svc_acct->cancel;
-$error ||= $svc_acct->delete;
+my $error = $svc_x->cancel;
+$error ||= $svc_x->delete;
 $error ||= $cust_svc->delete;
 
 if ( $error ) {
diff --git a/httemplate/misc/delete-domain_record.cgi b/httemplate/misc/delete-domain_record.cgi
new file mode 100755 (executable)
index 0000000..dcc2d50
--- /dev/null
@@ -0,0 +1,15 @@
+<%
+
+#untaint recnum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal recnum";
+my $recnum = $1;
+
+my $domain_record = qsearchs('domain_record',{'recnum'=>$recnum});
+
+my $error = $domain_record->delete;
+eidiot($error) if $error;
+
+print $cgi->redirect($p. "view/svc_domain.cgi?". $domain_record->svcnum);
+
+%>
index 34ef06b..7c4ab8b 100755 (executable)
@@ -1,6 +1,6 @@
 <%
 
-#untaint paynum
+#untaint exportnum
 my($query) = $cgi->keywords;
 $query =~ /^(\d+)$/ || die "Illegal exportnum";
 my $exportnum = $1;
index 61194a2..28214f0 100755 (executable)
@@ -35,7 +35,7 @@ print header('Domain View', menubar(
     ? ( "View this package (#$pkgnum)" => "${p}view/cust_pkg.cgi?$pkgnum",
         "View this customer (#$custnum)" => "${p}view/cust_main.cgi?$custnum",
       )
-    : ( "Cancel this (unaudited) account" =>
+    : ( "Cancel this (unaudited) domain" =>
           "${p}misc/cancel-unaudited.cgi?$svcnum" )
   ),
   "Main menu" => $p,
@@ -46,17 +46,36 @@ print header('Domain View', menubar(
       qq!<BR>Catch all email <A HREF="${p}misc/catchall.cgi?$svcnum">(change)</A>:!,
       $email ? "<B>$email</B>." : "<I>(none)<I>",
       qq!<BR><BR><A HREF="http://www.geektools.com/cgi-bin/proxy.cgi?query=$domain;targetnic=auto">View whois information.</A>!,
-      '<BR><BR>', ntable("",2),
+      '<BR><BR>',
+      '<SCRIPT>function areyousure(href) {
+        if ( confirm("Remove this record?") == true )
+          window.location.href = href;
+        }
+        </SCRIPT>',
+      ntable("",2),
       '<tr><th>Zone</th><th>Type</th><th>Data</th></tr>',
 ;
 
-foreach my $domain_record ( qsearch('domain_record', { svcnum => $svcnum } ) ) {
+
+foreach my $domain_record ( $svc_domain->domain_record ) {
   print '<tr><td>'. $domain_record->reczone. '</td>'.
         '<td>'. $domain_record->recaf. ' '. $domain_record->rectype. '</td>'.
-        '<td>'. $domain_record->recdata. '</td></tr>';
+        '<td>'. $domain_record->recdata;
+  print qq! (<A HREF="javascript:areyousure('${p}misc/delete-domain_record.cgi?!
+        .$domain_record->recnum. qq!')">delete</A>)!
+    unless $domain_record->rectype eq 'SOA';
+  print '</td></tr>';
 }
-print '</table>'.
-      '<BR>'. joblisting({'svcnum'=>$svcnum}, 1).
+print '</table><BR>'.
+      qq!<FORM METHOD="POST" ACTION="${p}edit/process/domain_record.cgi">!.
+      qq!<INPUT TYPE="hidden" NAME="svcnum" VALUE="$svcnum">!.
+      '<INPUT TYPE="text" NAME="reczone"> '.
+      '<INPUT TYPE="hidden" NAME="recaf" VALUE="IN">IN '.
+      '<SELECT NAME="rectype">'.
+        join('', map qq!<OPTION VALUE="$_">$_</OPTION>!, qw(A NS CNAME MX) ).
+        '</SELECT>'.
+      ' <INPUT TYPE="text" NAME="recdata"> <INPUT TYPE="submit" VALUE="Add">'.
+      '<BR><BR>'. joblisting({'svcnum'=>$svcnum}, 1).
       '</BODY></HTML>';
 
 %>