RT#29354: Password Security in Email [v3 merge]
[freeside.git] / FS / FS / svc_acct.pm
index 40f65d6..2332505 100644 (file)
@@ -7,7 +7,11 @@ use base qw( FS::svc_Domain_Mixin
              FS::svc_Radius_Mixin
              FS::svc_Tower_Mixin
              FS::svc_IP_Mixin
-             FS::svc_Common );
+             FS::Password_Mixin
+             FS::svc_Common
+           );
+
+use strict;
 use vars qw( $DEBUG $me $conf $skip_fuzzyfiles
              $dir_prefix @shells $usernamemin
              $usernamemax $passwordmin $passwordmax
@@ -58,7 +62,6 @@ use FS::svc_www;
 use FS::cdr;
 use FS::acct_snarf;
 use FS::tower_sector;
-use FS::Misc;
 
 $DEBUG = 0;
 $me = '[FS::svc_acct]';
@@ -702,6 +705,9 @@ sub insert {
     'child_objects' => $self->child_objects,
     %options,
   );
+
+  $error ||= $self->insert_password_history;
+
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
     return $error;
@@ -730,11 +736,9 @@ sub insert {
       $cust_main->invoicing_list(\@invoicing_list);
     }
 
-    #welcome email/letter
+    #welcome email
     my @welcome_exclude_svcparts = $conf->config('svc_acct_welcome_exclude');
     unless ( grep { $_ eq $self->svcpart } @welcome_exclude_svcparts ) {
-      #indent skips a level for some reason
-        #welcome email
         my $error = '';
         my $msgnum = $conf->config('welcome_msgnum', $agentnum);
         if ( $msgnum ) {
@@ -818,21 +822,7 @@ sub insert {
 
           } # if $welcome_template
         } # if !$msgnum
-        # print welcome letter
-        if ($conf->exists('svc_acct_welcome_letter')) {
-          my $queue = new FS::queue {
-            'job'     => 'FS::svc_acct::process_print_welcome_letter',
-          };
-          $error = $queue->insert(
-            'svcnum'  => $self->svcnum,
-            'template' => 'svc_acct_welcome_letter',
-          );
-          if ($error) {
-            warn "can't send welcome letter: $error";
-          }
-        }
-      #indent skipped a level for some reason
-    } # unless in @welcome_exclude_svcparts
+    }
   } # if $cust_pkg
 
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
@@ -1002,6 +992,12 @@ sub replace {
   my $dbh = dbh;
 
   $error = $new->SUPER::replace($old, @_); # usergroup here
+
+  # don't need to record this unless the password was changed
+  if ( $old->_password ne $new->_password ) {
+    $error ||= $new->insert_password_history;
+  }
+
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
     return $error if $error;
@@ -2779,6 +2775,31 @@ sub virtual_maildir {
   $self->domain. '/maildirs/'. $self->username. '/';
 }
 
+=item password_disallowed_names
+
+Override, for L<FS::Password_Mixin>.  Not really intended for other use.
+
+=cut
+
+sub password_disallowed_names {
+  my $self = shift;
+  my $dbh = dbh;
+  my $results = {};
+  foreach my $field ( qw( username finger ) ) {
+    my $sql = 'SELECT DISTINCT '.$field.' FROM svc_acct';
+    my $sth = $dbh->prepare($sql)
+      or die "Error preparing $sql: ". $dbh->errstr;
+    $sth->execute()
+      or die "Error executing $sql: ". $sth->errstr;
+    foreach my $row (@{$sth->fetchall_arrayref}, $self->get($field)) {
+      foreach my $word (split(/\s+/,$$row[0])) {
+        $results->{lc($word)} = 1;
+      }
+    }
+  }
+  return keys %$results;
+}
+
 =back
 
 =head1 CLASS METHODS
@@ -3045,26 +3066,6 @@ sub reached_threshold {
   }
 }
 
-sub process_print_welcome_letter {
-  my %opt = @_;
-
-  my $self = qsearchs('svc_acct', { 'svcnum' => $opt{'svcnum'} } )
-    or die "invalid svc_acct: " . $opt{'svcnum'};
-  my $cust_main = $self->cust_svc->cust_pkg->cust_main;
-
-  my $ps = $cust_main->print_ps('svc_acct_welcome_letter',
-    'extra_fields' => {
-      map { $_ => $self->$_ } $self->fields, # or maybe just username & password?
-    },
-  );
-  my $error = FS::Misc::do_print(
-    [ $ps ],
-    'agentnum' => $cust_main->agentnum,
-  );
-  die $error if $error;
-
-}
-
 =back
 
 =head1 BUGS