@ISA = qw(FS::part_export);
@EXPORT_OK = qw( sqlradius_connect );
-$DEBUG = 0;
+$DEBUG = 1;
my %groups;
tie %options, 'Tie::IxHash',
'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). '.
sub rebless { shift; }
-sub export_username {
+sub export_username { # override for other svcdb
my($self, $svc_acct) = (shift, shift);
warn "export_username called on $self with arg $svc_acct" if $DEBUG > 1;
$svc_acct->username;
}
+sub radius_reply { #override for other svcdb
+ my($self, $svc_acct) = (shift, shift);
+ $svc_acct->radius_reply;
+}
+
+sub radius_check { #override for other svcdb
+ my($self, $svc_acct) = (shift, shift);
+ $svc_acct->radius_check;
+}
+
sub _export_insert {
my($self, $svc_x) = (shift, shift);
foreach my $table (qw(reply check)) {
my $method = "radius_$table";
- my %attrib = $svc_x->$method();
+ my %attrib = $self->$method($svc_x);
next unless keys %attrib;
my $err_or_queue = $self->sqlradius_queue( $svc_x->svcnum, 'insert',
$table, $self->export_username($svc_x), %attrib );
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 ) {
$self->export_username($svc_acct),
'',
\@oldgroups,
- $svc_acct->usergroup,
+ [ $svc_acct->radius_groups ],
);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
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);
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;
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
###