RADIUS exports that skip provisioning, for accounting purposes, RT#73739
[freeside.git] / FS / FS / part_export / broadband_sqlradius.pm
index 45f286f..2d6681e 100644 (file)
@@ -1,13 +1,20 @@
 package FS::part_export::broadband_sqlradius;
 
 use strict;
-use vars qw($DEBUG @ISA %options %info $conf);
+use vars qw($DEBUG @ISA @pw_set %options %info $conf);
 use Tie::IxHash;
 use FS::Conf;
 use FS::Record qw( dbh str2time_sql ); #qsearch qsearchs );
 use FS::part_export::sqlradius qw(sqlradius_connect);
+use FS::Password_Mixin;
+use NEXT;
 
-FS::UID->install_callback(sub { $conf = new FS::Conf });
+FS::UID->install_callback(
+  sub {
+    $conf = new FS::Conf;
+    @pw_set = FS::Password_Mixin->pw_set;
+  }
+);
 
 @ISA = qw(FS::part_export::sqlradius);
 
@@ -53,6 +60,7 @@ tie %options, 'Tie::IxHash',
   'svc'      => 'svc_broadband',
   'desc'     => 'Real-time export to SQL-backed RADIUS (such as FreeRadius) for broadband services',
   'options'  => \%options,
+  'no_machine' => 1,
   'nas'      => 'Y',
   'notes'    => <<END,
 Real-time export of <b>radcheck</b>, <b>radreply</b>, and <b>usergroup</b> 
@@ -76,24 +84,18 @@ END
 
 sub rebless { shift; }
 
-sub _mac_format {
-  my $self = shift;
-  my $addr = shift;
-  if ( $self->option('mac_case',1) eq 'lowercase' ) {
-    $addr = lc($addr);
-  }
-  join( ($self->option('mac_delimiter',1) || ''), $addr =~ /../g );
-}
-
 sub export_username {
   my($self, $svc_broadband) = (shift, shift);
-  my $mac_addr = $svc_broadband->mac_addr;
-  $self->_mac_format($svc_broadband->mac_addr);
+  $svc_broadband->mac_addr_formatted(
+    $self->option('mac_case'), $self->option('mac_delimiter')
+  );
 }
 
 sub radius_reply {
   my($self, $svc_broadband) = (shift, shift);
-  my %reply;
+  # start with attributes the service wants
+  my %reply = $self->NEXT::radius_reply($svc_broadband);
+  # add export-specific stuff
   if (  length($self->option('ip_addr_as',1)) 
     and length($svc_broadband->ip_addr) ) {
     $reply{$self->option('ip_addr_as')} = $svc_broadband->ip_addr;
@@ -103,10 +105,11 @@ sub radius_reply {
 
 sub radius_check {
   my($self, $svc_broadband) = (shift, shift);
+
+  my %check = $self->SUPER::radius_check($svc_broadband);
   my $password_attrib = $conf->config('radius-password') || 'Password';
-  my %check;
   if ( $self->option('mac_as_password') ) {
-    $check{$password_attrib} = $self->_mac_format($svc_broadband->mac_addr);
+    $check{$password_attrib} = $self->export_username($svc_broadband);
   }
   elsif ( length( $self->option('radius_password',1)) ) {
     $check{$password_attrib} = $self->option('radius_password');
@@ -114,8 +117,67 @@ sub radius_check {
   %check;
 }
 
-sub _export_suspend {}
-sub _export_unsuspend {}
+sub radius_check_suspended {
+  my($self, $svc_broadband) = (shift, shift);
+
+  return () unless $self->option('mac_as_password')
+                || length( $self->option('radius_password',1));
+
+  my $password_attrib = $conf->config('radius-password') || 'Password';
+  (
+    $password_attrib => join('',map($pw_set[ int(rand $#pw_set) ], (0..7) ) )
+  );
+}
+
+#false laziness w/sqlradius.pm
+sub _export_suspend {
+  my( $self, $svc_broadband ) = (shift, shift);
+
+  return '' if $self->option('skip_provisioning');
+
+  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 @newgroups = $self->suspended_usergroups($svc_broadband);
+
+  unless (@newgroups) { #don't change password if assigning to a suspended group
+
+    my $err_or_queue = $self->sqlradius_queue(
+       $svc_broadband->svcnum, 'insert',
+      'check', $self->export_username($svc_broadband),
+      $self->radius_check_suspended($svc_broadband)
+    );
+    unless ( ref($err_or_queue) ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $err_or_queue;
+    }
+
+  }
+
+  my $error =
+    $self->sqlreplace_usergroups(
+      $svc_broadband->svcnum,
+      $self->export_username($svc_broadband),
+      '',
+      [ $svc_broadband->radius_groups('hashref') ],
+      \@newgroups,
+    );
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+  '';
+}
 
 sub update_svc {} #do nothing