Merge branch 'FREESIDE_3_BRANCH' of git.freeside.biz:/home/git/freeside into FREESIDE...
[freeside.git] / FS / FS / contact.pm
index e004cf8..4db3cdf 100644 (file)
@@ -1,5 +1,6 @@
 package FS::contact;
-use base qw( FS::Record );
+use base qw( FS::Password_Mixin
+             FS::Record );
 
 use strict;
 use vars qw( $skip_fuzzyfiles );
@@ -11,6 +12,7 @@ use FS::contact_class;
 use FS::cust_location;
 use FS::contact_phone;
 use FS::contact_email;
+use FS::contact::Import;
 use FS::queue;
 use FS::cust_pkg;
 use FS::phone_type; #for cgi_contact_fields
@@ -129,6 +131,8 @@ sub insert {
   my $dbh = dbh;
 
   my $error = $self->SUPER::insert;
+  $error ||= $self->insert_password_history;
+
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
     return $error;
@@ -179,7 +183,7 @@ sub insert {
     }
   }
 
-  if ( $self->selfservice_access ) {
+  if ( $self->selfservice_access && ! length($self->_password) ) {
     my $error = $self->send_reset_email( queue=>1 );
     if ( $error ) {
       $dbh->rollback if $oldAutoCommit;
@@ -230,7 +234,8 @@ sub delete {
     }
   }
 
-  my $error = $self->SUPER::delete;
+  my $error = $self->delete_password_history
+           || $self->SUPER::delete;
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
     return $error;
@@ -268,6 +273,9 @@ sub replace {
   my $dbh = dbh;
 
   my $error = $self->SUPER::replace($old);
+  if ( $old->_password ne $self->_password ) {
+    $error ||= $self->insert_password_history;
+  }
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
     return $error;
@@ -363,6 +371,15 @@ sub replace {
     }
   }
 
+  if ( $self->get('password') ) {
+    my $error = $self->is_password_allowed($self->get('password'))
+          ||  $self->change_password($self->get('password'));
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
+
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
 
   '';
@@ -449,7 +466,7 @@ and replace methods.
 sub check {
   my $self = shift;
 
-  if ( $self->selfservice_access eq 'R' ) {
+  if ( $self->selfservice_access eq 'R' || $self->selfservice_access eq 'E' || $self->selfservice_access eq 'P' ) {
     $self->selfservice_access('Y');
     $self->_resend('Y');
   }
@@ -607,9 +624,22 @@ sub authenticate_password {
 
 }
 
+=item change_password NEW_PASSWORD
+
+Changes the contact's selfservice access password to NEW_PASSWORD. This does
+not check password policy rules (see C<is_password_allowed>) and will return
+an error only if editing the record fails for some reason.
+
+If NEW_PASSWORD is the same as the existing password, this does nothing.
+
+=cut
+
 sub change_password {
   my($self, $new_password) = @_;
 
+  # do nothing if the password is unchanged
+  return if $self->authenticate_password($new_password);
+
   $self->change_password_fields( $new_password );
 
   $self->replace;
@@ -655,7 +685,10 @@ sub send_reset_email {
     'svcnum'     => $opt{'svcnum'},
   };
 
-  my $timeout = '24 hours'; #?
+  
+  my $conf = new FS::Conf;
+  my $timeout =
+    ($conf->config('selfservice-password_reset_hours') || 24 ). ' hours';
 
   my $reset_session_id;
   do {
@@ -667,8 +700,6 @@ sub send_reset_email {
 
   #email it
 
-  my $conf = new FS::Conf;
-
   my $cust_main = $self->cust_main
     or die "no customer"; #reset a password for a prospect contact?  someday
 
@@ -721,6 +752,7 @@ sub cgi_contact_fields {
 
   my @contact_fields = qw(
     classnum first last title comment emailaddress selfservice_access
+    invoice_dest password
   );
 
   push @contact_fields, 'phonetypenum'. $_->phonetypenum