export NAS table to sqlradius, #14697
[freeside.git] / FS / FS / part_export / sqlradius.pm
index 4dea80e..07f6cf0 100644 (file)
@@ -106,6 +106,7 @@ END
   'desc'     => 'Real-time export to SQL-backed RADIUS (FreeRADIUS, ICRADIUS)',
   'options'  => \%options,
   'nodomain' => 'Y',
+  'nas'      => 'Y', # show export_nas selection in UI
   'notes'    => $notes1.
                 'This export does not export RADIUS realms (see also '.
                 'sqlradius_withdomain).  '.
@@ -251,20 +252,24 @@ sub _export_suspend {
   local $FS::UID::AutoCommit = 0;
   my $dbh = dbh;
 
-  my $err_or_queue = $self->sqlradius_queue( $new->svcnum, 'insert',
-    'check', $self->export_username($new), $new->radius_check );
-  unless ( ref($err_or_queue) ) {
-    $dbh->rollback if $oldAutoCommit;
-    return $err_or_queue;
+  my @newgroups = $self->suspended_usergroups($svc_acct);
+
+  unless (@newgroups) { #don't change password if assigning to a suspended group
+
+    my $err_or_queue = $self->sqlradius_queue( $new->svcnum, 'insert',
+      'check', $self->export_username($new), $new->radius_check );
+    unless ( ref($err_or_queue) ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $err_or_queue;
+    }
+
   }
 
-  my $error;
-  my (@newgroups) = $self->suspended_usergroups($svc_acct);
-  $error =
+  my $error =
     $self->sqlreplace_usergroups( $new->svcnum,
                                   $self->export_username($new),
                                  '',
-                                  $svc_acct->usergroup,
+                                  [ $svc_acct->radius_groups ],
                                  \@newgroups,
                                );
   if ( $error ) {
@@ -303,7 +308,7 @@ sub _export_unsuspend {
                                          $self->export_username($svc_acct),
                                          '',
                                         \@oldgroups,
-                                        $svc_acct->usergroup,
+                                        [ $svc_acct->radius_groups ],
                                       );
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
@@ -354,7 +359,7 @@ sub suspended_usergroups {
       if (!$userspec && exists($reasonmap{$r->reason}));
   }
   my $suspend_user;
-  if ($userspec =~ /^d+$/ ){
+  if ($userspec =~ /^\d+$/ ){
     $suspend_user = qsearchs( 'svc_acct', { 'svcnum' => $userspec } );
   }elsif ($userspec =~ /^\S+\@\S+$/){
     my ($username,$domain) = split(/\@/, $userspec);
@@ -757,7 +762,7 @@ sub update_svc {
            AcctInputOctets, AcctOutputOctets
       FROM radacct
       WHERE FreesideStatus IS NULL
-        AND AcctStopTime != 0
+        AND AcctStopTime IS NOT NULL
   ") or die $dbh->errstr;
   $sth->execute() or die $sth->errstr;
 
@@ -860,6 +865,72 @@ sub _try_decrement {
   return 'skipped';
 }
 
+=item export_nas_insert NAS
+
+=item export_nas_delete NAS
+
+=item export_nas_replace NEW_NAS OLD_NAS
+
+Update the NAS table (allowed RADIUS clients) on the attached RADIUS 
+server.  Currently requires the table to be named 'nas' and to follow 
+the stock schema (/etc/freeradius/nas.sql).
+
+=cut
+
+sub export_nas_insert {  shift->export_nas_action('insert', @_); }
+sub export_nas_delete {  shift->export_nas_action('delete', @_); }
+sub export_nas_replace { shift->export_nas_action('replace', @_); }
+
+sub export_nas_action {
+  my $self = shift;
+  my ($action, $new, $old) = @_;
+  # find the NAS in the target table by its name
+  my $nasname = ($action eq 'replace') ? $old->nasname : $new->nasname;
+  my $nasnum = $new->nasnum;
+
+  my $err_or_queue = $self->sqlradius_queue('', "nas_$action", 
+    nasname => $nasname,
+    nasnum => $nasnum
+  );
+  return $err_or_queue unless ref $err_or_queue;
+  '';
+}
+
+sub sqlradius_nas_insert {
+  my $dbh = sqlradius_connect(shift, shift, shift);
+  my %opt = @_;
+  my $nas = qsearchs('nas', { nasnum => $opt{'nasnum'} })
+    or die "nasnum ".$opt{'nasnum'}.' not found';
+  # insert actual NULLs where FS::Record has translated to empty strings
+  my @values = map { length($nas->$_) ? $nas->$_ : undef }
+    qw( nasname shortname type secret server community description );
+  my $sth = $dbh->prepare('INSERT INTO nas 
+(nasname, shortname, type, secret, server, community, description)
+VALUES (?, ?, ?, ?, ?, ?, ?)');
+  $sth->execute(@values) or die $dbh->errstr;
+}
+
+sub sqlradius_nas_delete {
+  my $dbh = sqlradius_connect(shift, shift, shift);
+  my %opt = @_;
+  my $sth = $dbh->prepare('DELETE FROM nas WHERE nasname = ?');
+  $sth->execute($opt{'nasname'}) or die $dbh->errstr;
+}
+
+sub sqlradius_nas_replace {
+  my $dbh = sqlradius_connect(shift, shift, shift);
+  my %opt = @_;
+  my $nas = qsearchs('nas', { nasnum => $opt{'nasnum'} })
+    or die "nasnum ".$opt{'nasnum'}.' not found';
+  my @values = map {$nas->$_} 
+    qw( nasname shortname type secret server community description );
+  my $sth = $dbh->prepare('UPDATE nas SET
+    nasname = ?, shortname = ?, type = ?, secret = ?,
+    server = ?, community = ?, description = ?
+    WHERE nasname = ?');
+  $sth->execute(@values, $opt{'nasname'}) or die $dbh->errstr;
+}
+
 ###
 #class methods
 ###