691753f25550ce0ef7f6db548b98fed36aa54fb5
[freeside.git] / FS / FS / part_export / textradius.pm
1 package FS::part_export::textradius;
2
3 use vars qw(@ISA $prefix);
4 use Fcntl qw(:flock);
5 use FS::UID qw(datasrc);
6 use FS::part_export;
7
8 @ISA = qw(FS::part_export);
9
10 $prefix = "/usr/local/etc/freeside/export.";
11
12 sub rebless { shift; }
13
14 sub _export_insert {
15   my($self, $svc_acct) = (shift, shift);
16   $err_or_queue = $self->textradius_queue( $svc_acct->svcnum, 'insert',
17     $svc_acct->username, $svc_acct->radius_check, '-', $svc_acct->radius_reply);
18   ref($err_or_queue) ? '' : $err_or_queue;
19 }
20
21 sub _export_replace {
22   my( $self, $new, $old ) = (shift, shift, shift);
23   return "can't (yet?) change username with textradius"
24     if $old->username ne $new->username;
25   #return '' unless $old->_password ne $new->_password;
26   $err_or_queue = $self->textradius_queue( $new->svcnum, 'insert',
27     $new->username, $new->radius_check, '-', $new->radius_reply);
28   ref($err_or_queue) ? '' : $err_or_queue;
29 }
30
31 sub _export_delete {
32   my( $self, $svc_acct ) = (shift, shift);
33   $err_or_queue = $self->textradius_queue( $svc_acct->svcnum, 'delete',
34     $svc_acct->username );
35   ref($err_or_queue) ? '' : $err_or_queue;
36 }
37
38 #a good idea to queue anything that could fail or take any time
39 sub textradius_queue {
40   my( $self, $svcnum, $method ) = (shift, shift, shift);
41   my $queue = new FS::queue {
42     'svcnum' => $svcnum,
43     'job'    => "FS::part_export::textradius::textradius_$method",
44   };
45   $queue->insert(
46     $self->option('user'),
47     $self->machine,
48     $self->option('users'),
49     @_,
50   ) or $queue;
51 }
52
53 sub textradius_insert { #subroutine, not method
54   my( $user, $host, $users, $username, @attributes ) = @_;
55
56   #silly arg processing
57   my($att, @check);
58   push @check, $att while ($att=shift @attributes) ne '-';
59   my %check = @check;
60   my %reply = @attributes;
61
62   my $file = textradius_download($user, $host, $users);
63
64   eval "use RADIUS::UserFile;";
65   die $@ if $@;
66
67   my $userfile = new RADIUS::UserFile(
68     File        => $file,
69     Who         => [ $username ],
70     Check_Items => [ keys %check ],
71   ) or die "error parsing $file";
72
73   $userfile->remove($username);
74   $userfile->add(
75     Who        => $username,
76     Attributes => { %check, %reply },
77     Comment    => 'user added by Freeside',
78   ) or die "error adding to $file";
79
80   $userfile->update( Who => [ $username ] )
81     or die "error updating $file";
82
83   textradius_upload($user, $host, $users);
84
85 }
86
87 sub textradius_delete { #subroutine, not method
88   my( $user, $host, $users, $username ) = @_;
89
90   my $file = textradius_download($user, $host, $users);
91
92   eval "use RADIUS::UserFile;";
93   die $@ if $@;
94
95   my $userfile = new RADIUS::UserFile(
96     File        => $file,
97     Who         => [ $username ],
98   ) or die "error parsing $file";
99
100   $userfile->remove($username);
101
102   $userfile->update( Who => [ $username ] )
103     or die "error updating $file";
104
105   textradius_upload($user, $host, $users);
106 }
107
108 sub textradius_download {
109   my( $user, $host, $users ) = @_;
110
111   my $dir = $prefix. datasrc;
112   mkdir $dir, 0700 or die $! unless -d $dir;
113   $dir .= "/$host";
114   mkdir $dir, 0700 or die $! unless -d $dir;
115
116   my $dest = "$dir/users";
117
118   eval "use File::Rsync;";
119   die $@ if $@;
120   my $rsync = File::Rsync->new({ rsh => 'ssh' });
121
122   open(LOCK, "+>>$dest.lock")
123     and flock(LOCK,LOCK_EX)
124       or die "can't open $dest.lock: $!";
125
126   $rsync->exec( {
127     src  => "$user\@$host:$users",
128     dest => $dest,
129   } );
130
131   $dest;
132 }
133
134 sub textradius_upload {
135   my( $user, $host, $users ) = @_;
136
137   my $dir = $prefix. datasrc. "/$host";
138
139   eval "use File::Rsync;";
140   die $@ if $@;
141   my $rsync = File::Rsync->new({
142     rsh => 'ssh',
143     #dry_run => 1,
144   });
145   $rsync->exec( {
146     src  => "$dir/users",
147     dest => "$user\@$host:$users",
148   } );
149
150   flock(LOCK,LOCK_UN);
151   close LOCK;
152
153 }
154