X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fsvc_acct.pm;h=45f0a412e223c5bdcc04d4e239a95692e58bb120;hb=5657663a43689787fdc3c5da73775502daecc588;hp=53b9fd68261efb5c22ff024e5f60f13dff20adfc;hpb=65956c8ec4f5c898b1412f7f0e68495894b6c7e6;p=freeside.git diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm index 53b9fd682..45f0a412e 100644 --- a/FS/FS/svc_acct.pm +++ b/FS/FS/svc_acct.pm @@ -38,6 +38,7 @@ use FS::part_svc; use FS::svc_acct_pop; use FS::cust_main_invoice; use FS::svc_domain; +use FS::svc_pbx; use FS::raddb; use FS::queue; use FS::radius_usergroup; @@ -161,45 +162,71 @@ FS::svc_Common. The following fields are currently supported: =over 4 -=item svcnum - primary key (assigned automatcially for new accounts) +=item svcnum + +Primary key (assigned automatcially for new accounts) =item username -=item _password - generated if blank +=item _password + +generated if blank + +=item _password_encoding + +plain, crypt, ldap (or empty for autodetection) -=item _password_encoding - plain, crypt, ldap (or empty for autodetection) +=item sec_phrase -=item sec_phrase - security phrase +security phrase -=item popnum - Point of presence (see L) +=item popnum + +Point of presence (see L) =item uid =item gid -=item finger - GECOS +=item finger + +GECOS -=item dir - set automatically if blank (and uid is not) +=item dir + +set automatically if blank (and uid is not) =item shell -=item quota - (unimplementd) +=item quota + +=item slipip -=item slipip - IP address +IP address -=item seconds - +=item seconds -=item upbytes - +=item upbytes -=item downbytes - +=item downbyte -=item totalbytes - +=item totalbytes -=item domsvc - svcnum from svc_domain +=item domsvc + +svcnum from svc_domain + +=item pbxsvc + +Optional svcnum from svc_pbx -=item radius_I - I (reply) +=item radius_I -=item rc_I - I (check) +I (reply) + +=item rc_I + +I (check) =back @@ -275,6 +302,20 @@ sub table_info { disable_inventory => 1, }, + 'domsvc' => { + label => 'Domain', + type => 'select', + select_table => 'svc_domain', + select_key => 'svcnum', + select_label => 'domain', + disable_inventory => 1, + + }, + 'pbxsvc' => { label => 'PBX', + type => 'select-svc_pbx.html', + disable_inventory => 1, + disable_select => 1, #UI wonky, pry works otherwise + }, 'usergroup' => { label => 'RADIUS groups', type => 'radius_usergroup_selector', @@ -436,13 +477,7 @@ sub search_sql { $class->search_sql_field('username', $string ). ' ) '; } else { - ' ( '. - $class->search_sql_field('username', $string). - ( $string =~ /^\d+$/ - ? 'OR '. $class->search_sql_field('svcnum', $string) - : '' - ). - ' ) '; + $class->search_sql_field('username', $string); } } @@ -662,13 +697,16 @@ sub insert { } # set usage fields and thresholds if unset but set in a package def +# AND the package already has a last bill date (otherwise they get double added) sub preinsert_hook_first { my $self = shift; return '' unless $self->pkgnum; my $cust_pkg = qsearchs( 'cust_pkg', { 'pkgnum' => $self->pkgnum } ); - my $part_pkg = $cust_pkg->part_pkg if $cust_pkg; + return '' unless $cust_pkg && $cust_pkg->last_bill; + + my $part_pkg = $cust_pkg->part_pkg; return '' unless $part_pkg && $part_pkg->can('usage_valuehash'); my %values = $part_pkg->usage_valuehash; @@ -1017,7 +1055,8 @@ sub check { my $error = $self->ut_numbern('svcnum') #|| $self->ut_number('domsvc') - || $self->ut_foreign_key('domsvc', 'svc_domain', 'svcnum' ) + || $self->ut_foreign_key( 'domsvc', 'svc_domain', 'svcnum' ) + || $self->ut_foreign_keyn('pbxsvc', 'svc_pbx', 'svcnum' ) || $self->ut_textn('sec_phrase') || $self->ut_snumbern('seconds') || $self->ut_snumbern('upbytes') @@ -1184,13 +1223,14 @@ sub check { # First, if _password is blank, generate one and set default encoding. if ( ! $recref->{_password} ) { - $self->set_password(''); + $error = $self->set_password(''); } # But if there's a _password but no encoding, assume it's plaintext and # set it to default encoding. elsif ( ! $recref->{_password_encoding} ) { - $self->set_password($recref->{_password}); + $error = $self->set_password($recref->{_password}); } + return $error if $error; # Next, check _password to ensure compliance with the encoding. if ( $recref->{_password_encoding} eq 'ldap' ) { @@ -1232,11 +1272,8 @@ sub check { $recref->{_password} =~ /\!/ and return gettext('illegal_password'); } } - elsif ( $recref->{_password_encoding} eq 'legacy' ) { - # this happens when set_password fails - return gettext('illegal_password'). " $passwordmin-$passwordmax ". - FS::Msgcat::_gettext('illegal_password_characters'). - ": ". $recref->{_password}; + else { + return "invalid password encoding ('".$recref->{_password_encoding}."'"; } $self->SUPER::check; @@ -1297,73 +1334,81 @@ is >0), one will be generated randomly. =cut sub set_password { - my $self = shift; - my $pass = shift; - my ($encoding, $encryption); + my( $self, $pass ) = ( shift, shift ); + + warn "[$me] set_password (to $pass) called on $self: ". Dumper($self) + if $DEBUG; + my $failure = gettext('illegal_password'). " $passwordmin-$passwordmax ". + FS::Msgcat::_gettext('illegal_password_characters'). + ": ". $pass; - if($self->_password_encoding) { + my( $encoding, $encryption ) = ('', ''); + + if ( $self->_password_encoding ) { $encoding = $self->_password_encoding; # identify existing encryption method, try to use it. $encryption = $self->_password_encryption; - if(!$encryption) { + if (!$encryption) { # use the system default undef $encoding; } } - if(!$encoding) { + if ( !$encoding ) { # set encoding to system default - ($encoding, $encryption) = split(/-/, lc($conf->config('default-password-encoding'))); + ($encoding, $encryption) = + split(/-/, lc($conf->config('default-password-encoding'))); $encoding ||= 'legacy'; $self->_password_encoding($encoding); } - if($encoding eq 'legacy') { + if ( $encoding eq 'legacy' ) { + # The legacy behavior from check(): # If the password is blank, randomize it and set encoding to 'plain'. if(!defined($pass) or (length($pass) == 0 and $passwordmin)) { $pass = join('',map($pw_set[ int(rand $#pw_set) ], (0..7) ) ); $self->_password_encoding('plain'); - } - else { + } else { # Prefix + valid-length password if ( $pass =~ /^((\*SUSPENDED\* |!!?)?)([^\t\n]{$passwordmin,$passwordmax})$/ ) { $pass = $1.$3; $self->_password_encoding('plain'); - } # Prefix + crypt string - elsif ( $pass =~ /^((\*SUSPENDED\* |!!?)?)([\w\.\/\$\;\+]{13,64})$/ ) { + } elsif ( $pass =~ /^((\*SUSPENDED\* |!!?)?)([\w\.\/\$\;\+]{13,64})$/ ) { $pass = $1.$3; $self->_password_encoding('crypt'); - } # Various disabled crypt passwords - elsif ( $pass eq '*' or - $pass eq '!' or - $pass eq '!!' ) { + } elsif ( $pass eq '*' || $pass eq '!' || $pass eq '!!' ) { $self->_password_encoding('crypt'); + } else { + return $failure; } - else { - # do nothing; check() will recognize this as an error - } - } + } + + $self->_password($pass); + return; + } - elsif($encoding eq 'crypt') { - if($encryption eq 'md5') { + + return $failure + if $passwordmin && length($pass) < $passwordmin + or $passwordmax && length($pass) > $passwordmax; + + if ( $encoding eq 'crypt' ) { + if ($encryption eq 'md5') { $pass = unix_md5_crypt($pass); - } - elsif($encryption eq 'des') { + } elsif ($encryption eq 'des') { $pass = crypt($pass, $saltset[int(rand(64))].$saltset[int(rand(64))]); } - } - elsif($encoding eq 'ldap') { - if($encryption eq 'md5') { + + } elsif ( $encoding eq 'ldap' ) { + if ($encryption eq 'md5') { $pass = md5_base64($pass); - } - elsif($encryption eq 'sha1') { + } elsif ($encryption eq 'sha1') { $pass = sha1_base64($pass); - } - elsif($encryption eq 'crypt') { + } elsif ($encryption eq 'crypt') { $pass = crypt($pass, $saltset[int(rand(64))].$saltset[int(rand(64))]); } # else $encryption eq 'plain', do nothing @@ -1631,30 +1676,20 @@ for the password. sub radius_password { my $self = shift; - my($pw_attrib, $password); + my $pw_attrib; if ( $self->_password_encoding eq 'ldap' ) { - $pw_attrib = 'Password-With-Header'; - $password = $self->_password; - } elsif ( $self->_password_encoding eq 'crypt' ) { - $pw_attrib = 'Crypt-Password'; - $password = $self->_password; - } elsif ( $self->_password_encoding eq 'plain' ) { - - $pw_attrib = $radius_password; #Cleartext-Password? man rlm_pap - $password = $self->_password; - + $pw_attrib = $radius_password; } else { - - $pw_attrib = length($password) <= 12 ? $radius_password : 'Crypt-Password'; - $password = $self->_password; - + $pw_attrib = length($self->_password) <= 12 + ? $radius_password + : 'Crypt-Password'; } - ($pw_attrib, $password); + ($pw_attrib, $self->_password); } @@ -2014,14 +2049,14 @@ sub _op_overlimit { my $cust_pkg = $self->cust_svc->cust_pkg; - my $agent_overlimit = + my $conf_overlimit = $cust_pkg ? $conf->config('overlimit_groups', $cust_pkg->cust_main->agentnum ) - : ''; + : $conf->config('overlimit_groups'); foreach my $part_export ( $self->cust_svc->part_svc->part_export ) { - my $groups = $agent_overlimit || $part_export->option('overlimit_groups'); + my $groups = $conf_overlimit || $part_export->option('overlimit_groups'); next unless $groups; my $gref = &{ $self->_fieldhandlers->{'usergroup'} }( $self, $groups ); @@ -2117,8 +2152,8 @@ sub set_usage { #$self->snapshot; #not necessary, we retain the old values #create an object with the updated usage values my $new = qsearchs('svc_acct', { 'svcnum' => $self->svcnum }); - #call exports - my $error = $new->replace($self); + local($FS::Record::nowarn_identical) = 1; + my $error = $new->replace($self); #call exports if ( $error ) { $dbh->rollback if $oldAutoCommit; return "Error replacing: $error";