fix svc_broadband / svc_acct dangling services getting left behind w/radius groups...
[freeside.git] / FS / FS / svc_Radius_Mixin.pm
1 package FS::svc_Radius_Mixin;
2 use base qw( FS::m2m_Common FS::svc_Common );
3
4 use strict;
5 use FS::Record qw( qsearch dbh );
6 use FS::radius_group;
7 use FS::radius_usergroup;
8 use Carp qw( confess );
9
10 # not really a mixin since it overrides insert/replace/delete and has svc_Common
11 #  as a base class, should probably be renamed svc_Radius_Common
12
13 =head1 NAME
14
15 FS::svc_Radius_Mixin - partial base class for services with RADIUS groups
16
17 =head1 METHODS
18
19 =over 4
20
21 =cut
22
23 sub insert {
24   my $self = shift;
25
26   local $SIG{HUP} = 'IGNORE';
27   local $SIG{INT} = 'IGNORE';
28   local $SIG{QUIT} = 'IGNORE';
29   local $SIG{TERM} = 'IGNORE';
30   local $SIG{TSTP} = 'IGNORE';
31   local $SIG{PIPE} = 'IGNORE';
32
33   my $oldAutoCommit = $FS::UID::AutoCommit;
34   local $FS::UID::AutoCommit = 0;
35   my $dbh = dbh;
36
37   my $error =  $self->SUPER::insert(@_)
38             || $self->process_m2m(
39                                    'link_table'   => 'radius_usergroup',
40                                    'target_table' => 'radius_group',
41                                    'params'       => $self->usergroup,
42                                  );
43
44   if ( $error ) {
45     $dbh->rollback if $oldAutoCommit;
46     return $error;
47   }
48
49   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
50   '';
51 }
52
53 sub replace  {
54   my $new = shift;
55   my $old = shift;
56   $old = $new->replace_old if !defined($old);
57
58   local $SIG{HUP} = 'IGNORE';
59   local $SIG{INT} = 'IGNORE';
60   local $SIG{QUIT} = 'IGNORE';
61   local $SIG{TERM} = 'IGNORE';
62   local $SIG{TSTP} = 'IGNORE';
63   local $SIG{PIPE} = 'IGNORE';
64
65   my $oldAutoCommit = $FS::UID::AutoCommit;
66   local $FS::UID::AutoCommit = 0;
67   my $dbh = dbh;
68
69   $old->usergroup; # make sure this is cached for exports
70
71   my $error =  $new->process_m2m(
72                                  'link_table'   => 'radius_usergroup',
73                                  'target_table' => 'radius_group',
74                                  'params'       => $new->usergroup,
75                                )
76             || $new->SUPER::replace($old, @_);
77
78   if ( $error ) {
79     $dbh->rollback if $oldAutoCommit;
80     return $error;
81   }
82
83   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
84   '';
85 }
86
87 sub delete {
88   my $self = shift;
89
90   local $SIG{HUP} = 'IGNORE';
91   local $SIG{INT} = 'IGNORE';
92   local $SIG{QUIT} = 'IGNORE';
93   local $SIG{TERM} = 'IGNORE';
94   local $SIG{TSTP} = 'IGNORE';
95   local $SIG{PIPE} = 'IGNORE';
96
97   my $oldAutoCommit = $FS::UID::AutoCommit;
98   local $FS::UID::AutoCommit = 0;
99   my $dbh = dbh;
100
101   my $error =  $self->SUPER::delete(@_)
102             || $self->process_m2m(
103                                    'link_table'   => 'radius_usergroup',
104                                    'target_table' => 'radius_group',
105                                    'params'       => [],
106                                  );
107
108   if ( $error ) {
109     $dbh->rollback if $oldAutoCommit;
110     return $error;
111   }
112
113   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
114   '';
115 }
116
117 sub usergroup {
118   my $self = shift;
119   my $value = shift;
120   if ( defined $value ) {
121     if ( ref $value ) {
122       return $self->set('usergroup', $value);
123     }
124     else {
125       return $self->set('usergroup', [ split(/\s*,\s*/, $value) ]);
126     }
127   }
128   $self->get('usergroup') || 
129     # if no argument is passed and usergroup is not set already, 
130     # fetch this service's group assignments
131   $self->set('usergroup', 
132     [ map { $_->groupnum } 
133         qsearch('radius_usergroup', { svcnum => $self->svcnum }) ]
134   );
135 }
136
137 sub _fieldhandlers {
138   { 
139     'usergroup' => \&usergroup
140   }
141 }
142
143 =item radius_groups METHOD
144
145 Returns a list of RADIUS groups for this service (see L<FS::radius_usergroup>).
146 METHOD is the field to return, and can be any method on L<FS::radius_group>.
147 Useful values for METHOD include 'groupnum', 'groupname', and 
148 'long_description'.  Defaults to 'groupname' for historical reasons.
149
150 =cut
151
152 sub radius_groups {
153   my $self = shift;
154   my $method = shift || 'groupname';
155   my $groups = join(',', @{$self->usergroup}) || return ();
156   my @groups = qsearch({'table' => 'radius_group',
157                         'extra_sql' => "where groupnum in ($groups)"});
158   return map {$_->$method} @groups;
159 }
160
161 =back
162
163 =cut
164
165 1;