FS/FS/msa.pm
[freeside.git] / FS / bin / freeside-sqlradius-set-lastlog
1 #!/usr/bin/perl -w
2
3 use strict;
4 use Getopt::Std;
5 use FS::UID qw(adminsuidsetup);
6 use FS::Record qw(qsearch qsearchs str2time_sql);
7 use FS::Conf;
8 use FS::part_export;
9 use FS::svc_acct;
10
11 my %allowed_types = map { $_ => 1 } qw ( sqlradius sqlradius_withdomain );
12 my $conf = new FS::Conf;
13
14 my $user = shift or die &usage;
15 adminsuidsetup $user;
16
17 my $export_x = shift;
18 my @part_export;
19 if ( !defined($export_x) ) {
20   @part_export = qsearch('part_export', {} );
21 } elsif ( $export_x =~ /^(\d+)$/ ) {
22   @part_export = qsearchs('part_export', { exportnum=>$1 } )
23     or die "exportnum $export_x not found\n";
24 } else {
25   @part_export = qsearch('part_export', { exporttype=>$export_x } )
26     or die "no exports of type $export_x found\n";
27 }
28
29 # gross almost false laziness with FS::part_export::sqlradius::update_svc_acct
30 @part_export = grep { ! $_->option('ignore_accounting') }
31                grep { $allowed_types{$_->exporttype} }
32                @part_export
33   or die "No sqlradius exports specified.";
34
35
36 foreach my $part_export ( @part_export ) {
37   my $dbh = DBI->connect( map $part_export->option($_),
38                            qw ( datasrc username password ) );
39
40   my $str2time = str2time_sql( $dbh->{Driver}->{Name} );
41   my $group = "UserName";
42   $group .= ",Realm"
43     if ( ref($part_export) =~ /withdomain/ );
44
45   my $sth = $dbh->prepare("SELECT UserName, Realm,
46                           $str2time max(AcctStartTime)),
47                           $str2time max(AcctStopTime))
48                           FROM radacct
49                           WHERE AcctStartTime != 0 AND AcctStopTime != 0
50                           GROUP BY $group")
51     or die $dbh->errstr;
52   $sth->execute() or die $sth->errstr;
53
54   while (my $row = $sth->fetchrow_arrayref ) {
55     my ($username, $realm, $start, $stop) = @$row;
56
57     $username = lc($username) unless $conf->exists('username-uppercase');
58     my $extra_sql = '';
59     if ( ref($part_export) =~ /withdomain/ ) {
60       $extra_sql = " And '$realm' = ( SELECT domain FROM svc_domain
61                        WHERE svc_domain.svcnum = svc_acct.domsvc ) ";
62     }
63
64     my $svc_acct = qsearchs( 'svc_acct',
65                              { 'username' => $username },
66                              '',
67                              $extra_sql,
68                            );
69     if ($svc_acct) {
70       $svc_acct->last_login($start)
71         if $start && (!$svc_acct->last_login || $start > $svc_acct->last_login);
72       $svc_acct->last_logout($stop)
73         if $stop && (!$svc_acct->last_logout || $stop > $svc_acct->last_logout);
74     }
75   }
76 }
77
78
79 sub usage {
80   die "Usage:\n\n  freeside-sqlradius-set_lastlog user [ exportnum|exporttype ]\n";
81 }
82
83 =head1 NAME
84
85 freeside-sqlradius-set-lastlog - Command line tool to set last_login and last_logout values from radius tables
86
87 =head1 SYNOPSIS
88
89   freeside-sqlradius-set-lastlog user [ exportnum|exporttype ]
90
91 =head1 DESCRIPTION
92
93   Sets the last_login and last_logout columns of each svc_acct based on
94   data in the radacct table for the specified export (selected by exportnum
95   or exporttype) or all exports if none are specified.
96
97 =head1 SEE ALSO
98
99 L<freeside-sqlradius-radacctd>, L<FS::part_export> 
100
101 =cut
102