51a828001aea7500da87f3c6eee1c0173efd6895
[freeside.git] / FS / FS / part_export / sqlradius.pm
1 package FS::part_export::sqlradius;
2
3 use vars qw(@ISA);
4 use FS::part_export;
5
6 @ISA = qw(FS::part_export);
7
8 sub rebless { shift; }
9
10 sub _export_insert {
11   my($self, $svc_acct) = (shift, shift);
12
13   foreach my $table (qw(reply check)) {
14     my $method = "radius_$table";
15     my %attrib = $svc_acct->$method;
16     next unless keys %attrib;
17     my $err_or_queue = $self->sqlradius_queue( $svc_acct->svcnum, 'insert',
18       $table, $svc_acct->username, %attrib );
19     return $err_or_queue unless ref($err_or_queue);
20   }
21   my @groups = $svc_acct->radius_groups;
22   if ( @groups ) {
23     my $err_or_queue = $self->sqlradius_queue(
24       $svc_acct->svcnum, 'usergroup_insert',
25       $svc_acct->username, @groups );
26     return $err_or_queue unless ref($err_or_queue);
27   }
28   '';
29 }
30
31 sub _export_replace {
32   my( $self, $new, $old ) = (shift, shift, shift);
33
34   #return "can't (yet) change username with sqlradius"
35   #  if $old->username ne $new->username;
36   if ( $old->username ne $new->username ) {
37     my $err_or_queue = $self->sqlradius_queue( $new->svcnum, 'rename',
38       $new->username, $old->username );
39     return $err_or_queue unless ref($err_or_queue);
40   }
41
42   foreach my $table (qw(reply check)) {
43     my $method = "radius_$table";
44     my %new = $new->$method;
45     my %old = $old->$method;
46     if ( grep { !exists $old{$_} #new attributes
47                 || $new{$_} ne $old{$_} #changed
48               } keys %new
49     ) {
50       my $err_or_queue = $self->sqlradius_queue( $new->svcnum, 'insert',
51         $table, $new->username, %new );
52       return $err_or_queue unless ref($err_or_queue);
53     }
54
55     my @del = grep { !exists $new{$_} } keys %old;
56     if ( @del ) {
57       my $err_or_queue = $self->sqlradius_queue( $new->svcnum, 'attrib_delete',
58         $table, $new->username, @del );
59       return $err_or_queue unless ref($err_or_queue);
60     }
61   }
62
63   # (sorta) false laziness with FS::svc_acct::replace
64   my @oldgroups = @{$old->usergroup}; #uuuh
65   my @newgroups = $new->radius_groups;
66   my @delgroups = ();
67   foreach my $oldgroup ( @oldgroups ) {
68     if ( grep { $oldgroup eq $_ } @newgroups ) {
69       @newgroups = grep { $oldgroup ne $_ } @newgroups;
70       next;
71     }
72     push @delgroups, $oldgroup;
73   }
74
75   if ( @delgroups ) {
76     my $err_or_queue = $self->sqlradius_queue( $new->svcnum, 'usergroup_delete',
77       $new->username, @delgroups );
78     return $err_or_queue unless ref($err_or_queue);
79   }
80
81   if ( @newgroups ) {
82     my $err_or_queue = $self->sqlradius_queue( $new->svcnum, 'usergroup_insert',
83       $new->username, @newgroups );
84     return $err_or_queue unless ref($err_or_queue);
85   }
86
87   '';
88 }
89
90 sub _export_delete {
91   my( $self, $svc_acct ) = (shift, shift);
92   my $err_or_queue = $self->sqlradius_queue( $svc_acct->svcnum, 'delete',
93     $svc_acct->username );
94   ref($err_or_queue) ? '' : $err_or_queue;
95 }
96
97 sub sqlradius_queue {
98   my( $self, $svcnum, $method ) = (shift, shift, shift);
99   my $queue = new FS::queue {
100     'svcnum' => $svcnum,
101     'job'    => "FS::part_export::sqlradius::sqlradius_$method",
102   };
103   $queue->insert(
104     $self->option('datasrc'),
105     $self->option('username'),
106     $self->option('password'),
107     @_,
108   ) or $queue;
109 }
110
111 sub sqlradius_insert { #subroutine, not method
112   my $dbh = sqlradius_connect(shift, shift, shift);
113   my( $table, $username, %attributes ) = @_;
114
115   foreach my $attribute ( keys %attributes ) {
116   
117     my $s_sth = $dbh->prepare(
118       "SELECT COUNT(*) FROM rad$table WHERE UserName = ? AND Attribute = ?"
119     ) or die $dbh->errstr;
120     $s_sth->execute( $username, $attribute ) or die $s_sth->errstr;
121
122     if ( $s_sth->fetchrow_arrayref->[0] ) {
123
124       my $u_sth = $dbh->prepare(
125         "UPDATE rad$table SET Value = ? WHERE UserName = ? AND Attribute = ?"
126       ) or die $dbh->errstr;
127       $u_sth->execute($attributes{$attribute}, $username, $attribute)
128         or die $u_sth->errstr;
129
130     } else {
131
132       my $i_sth = $dbh->prepare(
133         "INSERT INTO rad$table ( id, UserName, Attribute, Value ) ".
134           "VALUES ( ?, ?, ?, ? )"
135       ) or die $dbh->errstr;
136       $i_sth->execute( '', $username, $attribute, $attributes{$attribute} )
137         or die $i_sth->errstr;
138
139     }
140
141   }
142   $dbh->disconnect;
143 }
144
145 sub sqlradius_usergroup_insert { #subroutine, not method
146   my $dbh = sqlradius_connect(shift, shift, shift);
147   my( $username, @groups ) = @_;
148
149   my $sth = $dbh->prepare( 
150     "INSERT INTO usergroup ( id, UserName, GroupName ) VALUES ( ?, ?, ? )"
151   ) or die $dbh->errstr;
152   foreach my $group ( @groups ) {
153     $sth->execute( '', $username, $group )
154       or die "can't insert into groupname table: ". $sth->errstr;
155   }
156   $dbh->disconnect;
157 }
158
159 sub sqlradius_usergroup_delete { #subroutine, not method
160   my $dbh = sqlradius_connect(shift, shift, shift);
161   my( $username, @groups ) = @_;
162
163   my $sth = $dbh->prepare( 
164     "DELETE FROM usergroup WHERE UserName = ? AND GroupName = ?"
165   ) or die $dbh->errstr;
166   foreach my $group ( @groups ) {
167     $sth->execute( $username, $group )
168       or die "can't delete from groupname table: ". $sth->errstr;
169   }
170   $dbh->disconnect;
171 }
172
173 sub sqlradius_rename { #subroutine, not method
174   my $dbh = sqlradius_connect(shift, shift, shift);
175   my($new_username, $old_username) = @_;
176   foreach my $table (qw(radreply radcheck usergroup )) {
177     my $sth = $dbh->prepare("UPDATE $table SET Username = ? WHERE UserName = ?")
178       or die $dbh->errstr;
179     $sth->execute($new_username, $old_username)
180       or die "can't update $table: ". $sth->errstr;
181   }
182   $dbh->disconnect;
183 }
184
185 sub sqlradius_attrib_delete { #subroutine, not method
186   my $dbh = sqlradius_connect(shift, shift, shift);
187   my( $table, $username, @attrib ) = @_;
188
189   foreach my $attribute ( @attrib ) {
190     my $sth = $dbh->prepare(
191         "DELETE FROM rad$table WHERE UserName = ? AND Attribute = ?" )
192       or die $dbh->errstr;
193     $sth->execute($username,$attribute)
194       or die "can't delete from rad$table table: ". $sth->errstr;
195   }
196   $dbh->disconnect;
197 }
198
199 sub sqlradius_delete { #subroutine, not method
200   my $dbh = sqlradius_connect(shift, shift, shift);
201   my $username = shift;
202
203   foreach my $table (qw( radcheck radreply usergroup )) {
204     my $sth = $dbh->prepare( "DELETE FROM $table WHERE UserName = ?" );
205     $sth->execute($username)
206       or die "can't delete from $table table: ". $sth->errstr;
207   }
208   $dbh->disconnect;
209 }
210
211 sub sqlradius_connect {
212   #my($datasrc, $username, $password) = @_;
213   #DBI->connect($datasrc, $username, $password) or die $DBI::errstr;
214   DBI->connect(@_) or die $DBI::errstr;
215 }
216