f09d36abbb0405fca6f94c05a54965061ab11e54
[freeside.git] / FS / FS / part_export / radiator.pm
1 package FS::part_export::radiator;
2
3 use vars qw(@ISA %info $radusers);
4 use Tie::IxHash;
5 use FS::part_export::sqlradius;
6
7 tie my %options, 'Tie::IxHash', %FS::part_export::sqlradius::options;
8
9 %info = (
10   'svc'      => 'svc_acct',
11   'desc'     => 'Real-time export to RADIATOR',
12   'options'  => \%options,
13   'nodomain' => '',
14   'no_machine' => 1,
15   'default_svc_class' => 'Internet',
16   'notes' => <<'END',
17 Real-time export of the <b>radusers</b> table to any SQL database in
18 <a href="http://www.open.com.au/radiator/">Radiator</a>-native format.
19 To setup accounting, see the RADIATOR documentation for hooks to update
20 a standard <b>radacct</b> table.
21 END
22 );
23
24 @ISA = qw(FS::part_export::sqlradius); #for regular sqlradius accounting
25
26 $radusers = 'RADUSERS'; #MySQL is case sensitive about table names!  huh
27
28 #sub export_username {
29 #  my($self, $svc_acct) = (shift, shift);
30 #  $svc_acct->email;
31 #}
32
33 sub _export_insert {
34   my( $self, $svc_acct ) = (shift, shift);
35
36   $self->radiator_queue(
37     $svc_acct->svcnum,
38     'insert',
39     $self->_radiator_hash($svc_acct),
40   );
41 }
42
43 sub _export_replace {
44   my( $self, $new, $old ) = (shift, shift, shift);
45
46 #  return "can't (yet) change domain with radiator export"
47 #    if $old->domain ne $new->domain;
48 #  return "can't (yet) change username with radiator export"
49 #    if $old->username ne $new->username;
50
51   $self->radiator_queue(
52     $new->svcnum,
53     'replace',
54     $self->export_username($old),
55     $self->_radiator_hash($new),
56   );
57 }
58
59 sub _export_delete {
60   my( $self, $svc_acct ) = (shift, shift);
61
62   $self->radiator_queue(
63     $svc_acct->svcnum,
64     'delete',
65     $self->export_username($svc_acct),
66   );
67 }
68
69 sub _radiator_hash {
70   my( $self, $svc_acct ) = @_;
71   my %hash = (
72     'username'  => $self->export_username($svc_acct),
73     'pass_word' => $svc_acct->crypt_password,
74     'fullname'  => $svc_acct->finger,
75     map { my $method = "radius_$_"; $_ => $svc_acct->$method(); }
76         qw( framed_filter_id framed_mtu framed_netmask framed_protocol
77             framed_routing login_host login_service login_tcp_port )
78   );
79   $hash{'timeleft'} = $svc_acct->seconds
80     if $svc_acct->seconds =~ /^\d+$/;
81   $hash{'staticaddress'} = $svc_acct->slipip
82     if $svc_acct->slipip =~ /^[\d\.]+$/; # and $self->slipip ne '0.0.0.0';
83
84   $hash{'servicename'} = ( $svc_acct->radius_groups )[0];
85
86   my $cust_pkg = $svc_acct->cust_svc->cust_pkg;
87   $hash{'validto'} = $cust_pkg->bill
88     if $cust_pkg && $cust_pkg->part_pkg->is_prepaid && $cust_pkg->bill;
89
90   #some other random stuff, should probably be attributes or virtual fields
91   #$hash{'state'} = 0; #only inserts
92   #$hash{'badlogins'} = 0; #only inserts
93   $hash{'maxlogins'} = 1;
94   $hash{'addeddate'} = $cust_pkg->setup
95     if $cust_pkg && $cust_pkg->setup;
96   $hash{'validfrom'} = $cust_pkg->last_bill || $cust_pkg->setup
97     if $cust_pkg &&  ( $cust_pkg->last_bill || $cust_pkg->setup );
98   $hash{'state'} = $cust_pkg->susp ? 1 : 0
99     if $cust_pkg;
100
101   %hash;
102 }
103
104 sub radiator_queue {
105   my( $self, $svcnum, $method ) = (shift, shift, shift);
106   my $queue = new FS::queue {
107     'svcnum' => $svcnum,
108     'job'    => "FS::part_export::radiator::radiator_$method",
109   };
110   $queue->insert(
111     $self->option('datasrc'),
112     $self->option('username'),
113     $self->option('password'),
114     @_,
115   ); # or $queue;
116 }
117
118 sub radiator_insert { #subroutine, not method
119   my $dbh = radiator_connect(shift, shift, shift);
120   my %hash = @_;
121   $hash{'state'} = 0; #see "random stuff" above
122   $hash{'badlogins'} = 0; #see "random stuff" above
123
124   my $sth = $dbh->prepare(
125     "INSERT INTO $radusers ( ". join(', ', keys %hash ). ' ) '.
126       'VALUES ( '. join(', ', map '?', keys %hash ). ' ) '
127   ) or die $dbh->errstr;
128   $sth->execute( values %hash )
129     or die $sth->errstr;
130
131   $dbh->disconnect;
132
133 }
134
135 sub radiator_replace { #subroutine, not method
136   my $dbh = radiator_connect(shift, shift, shift);
137   my ( $old_username, %hash ) = @_;
138
139   my $sth = $dbh->prepare(
140     "UPDATE $radusers SET ". join(', ', map " $_ = ?", keys %hash ).
141       ' WHERE username = ?'
142   ) or die $dbh->errstr;
143   $sth->execute( values(%hash), $old_username )
144     or die $sth->errstr;
145
146   $dbh->disconnect;
147 }
148
149 sub radiator_delete { #subroutine, not method
150   my $dbh = radiator_connect(shift, shift, shift);
151   my ( $username ) = @_;
152
153   my $sth = $dbh->prepare(
154     "DELETE FROM $radusers WHERE username = ?"
155   ) or die $dbh->errstr;
156   $sth->execute( $username )
157     or die $sth->errstr;
158
159   $dbh->disconnect;
160 }
161
162
163 sub radiator_connect {
164   #my($datasrc, $username, $password) = @_;
165   #DBI->connect($datasrc, $username, $password) or die $DBI::errstr;
166   DBI->connect(@_) or die $DBI::errstr;
167 }
168
169 1;