self-service access for contacts, RT#25533
authorIvan Kohler <ivan@freeside.biz>
Mon, 30 Dec 2013 23:37:04 +0000 (15:37 -0800)
committerIvan Kohler <ivan@freeside.biz>
Mon, 30 Dec 2013 23:37:04 +0000 (15:37 -0800)
FS/FS/ClientAPI/MyAccount.pm
FS/FS/contact.pm
fs_selfservice/FS-SelfService/cgi/do_process_forgot_password.html
fs_selfservice/FS-SelfService/cgi/forgot_password.html
fs_selfservice/FS-SelfService/cgi/login.html
fs_selfservice/FS-SelfService/cgi/process_forgot_password.html
fs_selfservice/FS-SelfService/cgi/selfservice.cgi

index 37d21ea..d17131f 100644 (file)
@@ -96,6 +96,7 @@ sub skin_info {
   } elsif ( defined($p->{'agentnum'}) and $p->{'agentnum'} =~ /^(\d+)$/ ) {
     $agentnum = $1;
   }
+  $p->{'agentnum'} = $agentnum;
 
   my $conf = new FS::Conf;
 
@@ -233,7 +234,7 @@ sub login {
               && (my $contact = FS::contact->by_selfservice_email($p->{email}))
           )
   {
-    return { error => 'Incorrect password.' }
+    return { error => 'Incorrect contact password.' }
       unless $contact->authenticate_password($p->{'password'});
 
     $session->{'custnum'} = $contact->custnum;
@@ -2900,9 +2901,11 @@ sub myaccount_passwd {
 sub reset_passwd {
   my $p = shift;
 
+  my $info = skin_info($p);
+
   my $conf = new FS::Conf;
   my $verification = $conf->config('selfservice-password_reset_verification')
-    or return { 'error' => 'Password resets disabled' };
+    or return { %$info, 'error' => 'Password resets disabled' };
 
   my $contact = '';
   my $svc_acct = '';
@@ -2933,21 +2936,21 @@ sub reset_passwd {
       
     }
 
-    return { 'error' => 'Email address not found' }
+    return { %$info, 'error' => 'Email address not found' }
       unless $contact || $svc_acct;
 
   } elsif ( $p->{'username'} ) { #old style, looks in svc_acct only
 
     my $svc_domain = qsearchs('svc_domain', { 'domain' => $p->{'domain'} } )
-      or return { 'error' => 'Account not found' };
+      or return { %$info, 'error' => 'Account not found' };
 
     $svc_acct = qsearchs('svc_acct', { 'username' => $p->{'username'},
                                        'domsvc'   => $svc_domain->svcnum  }
                         )
-      or return { 'error' => 'Account not found' };
+      or return { %$info, 'error' => 'Account not found' };
 
     my $cust_pkg = $svc_acct->cust_svc->cust_pkg
-      or return { 'error' => 'Account not found' };
+      or return { %$info, 'error' => 'Account not found' };
 
     $cust_main = $cust_pkg->cust_main;
 
@@ -2981,7 +2984,7 @@ sub reset_passwd {
   foreach my $verify ( split(',', $verification) ) {
 
     &{ $verify{$verify} }( $p, $cust_main )
-      or return { 'error' => 'Account not found' };
+      or return { %$info, 'error' => 'Account not found' };
 
   }
 
@@ -2994,7 +2997,7 @@ sub reset_passwd {
                           );
 
     if ( $error ) {
-      return { 'error' => $error }; #????
+      return { %$info, 'error' => $error }; #????
     }
 
   } elsif ( $svc_acct ) {
@@ -3002,7 +3005,8 @@ sub reset_passwd {
     #create a unique session
 
     my $reset_session = {
-      'svcnum' => $svc_acct->svcnum,
+      'svcnum'   => $svc_acct->svcnum,
+      'agentnum' =>
     };
 
     my $timeout = '1 hour'; #?
@@ -3020,7 +3024,7 @@ sub reset_passwd {
     my $msgnum = $conf->config('selfservice-password_reset_msgnum',
                                $cust_main->agentnum);
     #die "selfservice-password_reset_msgnum unset" unless $msgnum;
-    return { 'error' => "selfservice-password_reset_msgnum unset" }
+    return { %$info, 'error' => "selfservice-password_reset_msgnum unset" }
       unless $msgnum;
     my $msg_template = qsearchs('msg_template', { msgnum => $msgnum } );
     my $error = $msg_template->send( 'cust_main'     => $cust_main,
@@ -3030,12 +3034,12 @@ sub reset_passwd {
                                      }
                                    );
     if ( $error ) {
-      return { 'error' => $error }; #????
+      return { %$info, 'error' => $error }; #????
     }
 
   }
 
-  return { 'error' => '' };
+  return { %$info, 'error' => '' };
 }
 
 sub check_reset_passwd {
@@ -3055,7 +3059,11 @@ sub check_reset_passwd {
     my $svc_acct = qsearchs('svc_acct', { 'svcnum' => $svcnum } )
       or return { 'error' => "Service not found" };
 
-    return { 'error'      => '',
+    $p->{'agentnum'} = $svc_acct->cust_svc->cust_pkg->cust_main->agentnum;
+    my $info = skin_info($p);
+
+    return { %$info,
+             'error'      => '',
              'session_id' => $p->{'session_id'},
              'username'   => $svc_acct->username,
            };
@@ -3070,7 +3078,11 @@ sub check_reset_passwd {
     my @contact_email = $contact->contact_email;
     return { 'error' => 'No contact email' } unless @contact_email;
 
-    return { 'error'      => '',
+    $p->{'agentnum'} = $contact->cust_main->agentnum;
+    my $info = skin_info($p);
+
+    return { %$info,
+             'error'      => '',
              'session_id' => $p->{'session_id'},
              'email'      => $contact_email[0]->email, #the first?
            };
@@ -3090,26 +3102,49 @@ sub process_reset_passwd {
   my $verification = $conf->config('selfservice-password_reset_verification')
     or return { 'error' => 'Password resets disabled' };
 
-  return { 'error' => "New passwords don't match." }
-    if $p->{'new_password'} ne $p->{'new_password2'};
-
-  return { 'error' => 'Enter new password' }
-    unless length($p->{'new_password'});
-
   my $reset_session = _cache->get('reset_passwd_'. $p->{'session_id'})
     or return { 'error' => "Can't resume session" }; #better error message
 
+  my $info = '';
+
+  my $svc_acct = '';
   if ( $reset_session->{'svcnum'} ) {
 
     my $svcnum = $reset_session->{'svcnum'};
 
-    my $svc_acct = qsearchs('svc_acct', { 'svcnum' => $svcnum } )
+    $svc_acct = qsearchs('svc_acct', { 'svcnum' => $svcnum } )
       or return { 'error' => "Service not found" };
 
+    $p->{'agentnum'} ||= $svc_acct->cust_svc->cust_pkg->cust_main->agentnum;
+    $info ||= skin_info($p);
+
+  }
+
+  my $contact = '';
+  if ( $reset_session->{'contactnum'} ) {
+
+    my $contactnum = $reset_session->{'contactnum'};
+
+    $contact = qsearchs('contact', { 'contactnum' => $contactnum } )
+      or return { 'error' => "Contact not found" };
+
+    $p->{'agentnum'} ||= $contact->cust_main->agentnum;
+    $info ||= skin_info($p);
+
+  }
+
+  return { %$info, 'error' => "New passwords don't match." }
+    if $p->{'new_password'} ne $p->{'new_password2'};
+
+  return { %$info, 'error' => 'Enter new password' }
+    unless length($p->{'new_password'});
+
+  if ( $svc_acct ) {
+
     $svc_acct->set_password($p->{'new_password'});
     my $error = $svc_acct->replace();
 
-    return { 'error' => $error } if $error;
+    return { %$info, 'error' => $error } if $error;
 
     #my($label, $value) = $svc_acct->cust_svc->label;
     #return { 'error' => $error,
@@ -3119,23 +3154,18 @@ sub process_reset_passwd {
 
   }
 
-  if ( $reset_session->{'contactnum'} ) {
-
-    my $contactnum = $reset_session->{'contactnum'};
-
-    my $contact = qsearchs('contact', { 'contactnum' => $contactnum } )
-      or return { 'error' => "Contact not found" };
+  if ( $contact ) {
 
     my $error = $contact->change_password($p->{'new_password'});
 
-    return { 'error' => $error }; # if $error;
+    return { %$info, 'error' => $error }; # if $error;
 
   }
 
   #password changed ,so remove session, don't want it reused
   _cache->remove($p->{'session_id'});
 
-  return { 'error' => '' };
+  return { %$info, 'error' => '' };
 
 }
 
index 2a73b9c..d0dd8b7 100644 (file)
@@ -471,8 +471,6 @@ sub by_selfservice_email {
                    " AND ( disabled IS NULL OR disabled = '' )",
   }) or return '';
 
-warn $contact_email;
-
   $contact_email->contact;
 
 }
index 9274f92..35728e7 100644 (file)
@@ -10,8 +10,8 @@
 <FONT SIZE="+1" COLOR="#ff0000"><%= $error %></FONT>
 
 <%= if (!$error) {
-  $self_url =~ s/\?.*//;
-  $OUT .= "Your password has been changed.  You can now <A HREF=\"$self_url\">log in</A>.";
+  $selfurl =~ s/\?.*//;
+  $OUT .= "Your password has been changed.  You can now <A HREF=\"$selfurl\">log in</A>.";
   }
 %>
 
index e14034c..6071511 100644 (file)
@@ -9,7 +9,8 @@
 <FONT SIZE=5>Forgot password</FONT><BR><BR>
 <FONT SIZE="+1" COLOR="#ff0000"><%= $error %></FONT>
 
-<FORM ACTION="<%= $self_url %>" METHOD=POST>
+<%= $selfurl =~ s/\?.*//; ''; %>
+<FORM ACTION="<%= $selfurl %>" METHOD=POST>
 <INPUT TYPE="hidden" NAME="action" VALUE="do_forgot_password">
 <INPUT TYPE="hidden" NAME="agentnum" VALUE="<%= $agentnum %>">
 
@@ -17,25 +18,26 @@ Please enter your email address.  A password reset email will be sent to that ad
 
 <TABLE BGCOLOR="<%= $box_bgcolor || '#c0c0c0' %>" BORDER=0 CELLSPACING=2 CELLPADDING=0>
 
-<TR>
-  <TH ALIGN="right">Email address </TH>
-  <TD>
-    <INPUT TYPE="text" NAME="email" VALUE="<%= $username %>"><%= $single_domain ? '@'.$single_domain : '' %>
-  </TD>
-</TR>
-
 <%=
 if ( $single_domain ) {
 
-  $OUT .= qq(<INPUT TYPE="hidden" NAME="domain" VALUE="$single_domain">);
+  $OUT .= qq(
+    <TR>
+      <TH ALIGN="right">Username </TH>
+      <TD>
+        <INPUT TYPE="text" NAME="username" VALUE="$username">\@$single_domain
+      </TD>
+    </TR>
+    <INPUT TYPE="hidden" NAME="domain" VALUE="$single_domain">
+  );
 
 } else {
 
   $OUT .= qq(
     <TR>
-      <TH ALIGN="right">Domain </TH>
+      <TH ALIGN="right">Email address </TH>
       <TD>
-        <INPUT TYPE="text" NAME="domain" VALUE="$domain">
+        <INPUT TYPE="text" NAME="email" VALUE="$email">
       </TD>
     </TR>
   );
index 65efd7b..f7af4e9 100644 (file)
@@ -9,7 +9,8 @@
 <FONT SIZE=5>Login</FONT><BR><BR>
 <FONT SIZE="+1" COLOR="#ff0000"><%= $error %></FONT>
 
-<FORM ACTION="<%= $self_url %>" METHOD=POST>
+<%= $selfurl =~ s/\?.*//; ''; %>
+<FORM ACTION="<%= $selfurl %>" METHOD=POST>
 <INPUT TYPE="hidden" NAME="action" VALUE="myaccount">
 <INPUT TYPE="hidden" NAME="agentnum" VALUE="<%= $agentnum %>">
 
@@ -65,7 +66,7 @@ if ( $phone_login ) {
 
     <B>OR</B><BR><BR>
     
-    <FORM ACTION="$self_url" METHOD=POST>
+    <FORM ACTION="$selfurl" METHOD=POST>
     <TABLE BGCOLOR="$box_bgcolor" BORDER=0 CELLSPACING=2 CELLPADDING=0>
     <TR>
       <TH ALIGN="right">Phone number </TH>
index 3d8c058..ec672c8 100644 (file)
@@ -9,7 +9,8 @@
 <FONT SIZE=5>Reset password</FONT><BR><BR>
 <FONT SIZE="+1" COLOR="#ff0000"><%= $error %></FONT>
 
-<FORM ACTION="<%= $self_url %>" METHOD=POST>
+<%= $selfurl =~ s/\?.*//; ''; %>
+<FORM ACTION="<%= $selfurl %>" METHOD=POST>
 <INPUT TYPE="hidden" NAME="action" VALUE="do_process_forgot_password">
 <INPUT TYPE="hidden" NAME="session_id" VALUE="<%= $session_id %>">
 <INPUT TYPE="hidden" NAME="agentnum" VALUE="<%= $agentnum %>">
index 8d3a23b..1372311 100755 (executable)
@@ -32,99 +32,6 @@ $DEBUG = 0;
 $form_max = 255;
 
 $cgi = new CGI;
-my %cookies = CGI::Cookie->fetch;
-
-my $login_rv;
-
-if ( exists($cookies{'session'}) ) {
-
-  $session_id = $cookies{'session'}->value;
-
-  if ( $session_id eq 'login' ) {
-    # then we've just come back from the login page
-
-    $cgi->param('password') =~ /^(.{0,$form_max})$/;
-    my $password = $1;
-
-    if ( $cgi->param('email') =~ /^\s*([a-z0-9_\-\.\@]{1,$form_max})\s*$/i ) {
-
-      my $email = $1;
-      $login_rv = login(
-        'email'    => $email,
-        'password' => $password
-      );
-      $session_id = $login_rv->{'session_id'};
-
-    } else {
-
-      $cgi->param('username') =~ /^\s*([a-z0-9_\-\.\&]{0,$form_max})\s*$/i;
-      my $username = $1;
-
-      $cgi->param('domain') =~ /^\s*([\w\-\.]{0,$form_max})\s*$/;
-      my $domain = $1;
-
-      if ( $username and $domain and $password ) {
-
-        # authenticate
-        $login_rv = login(
-          'username' => $username,
-          'domain'   => $domain,
-          'password' => $password,
-        );
-        $session_id = $login_rv->{'session_id'};
-
-      } elsif ( $username or $domain or $password ) {
-      
-        my $error = 'Illegal '; #XXX localization...
-        my $count = 0;
-        if ( !$username ) {
-          $error .= 'username';
-          $count++;
-        }
-        if ( !$domain )  {
-          $error .= ', ' if $count;
-          $error .= 'domain';
-          $count++;
-        }
-        if ( !$password ) {
-          $error .= ', ' if $count;
-          $error .= 'and ' if $count > 1;
-          $error .= 'password';
-          $count++;
-        }
-        $error .= '.';
-        $login_rv = {
-          'username'  => $username,
-          'domain'    => $domain,
-          'password'  => $password,
-          'error'     => $error,
-        };
-        $session_id = undef; # attempt login again
-
-      }
-
-    } # else there was no input, so show no error message
-
-  } # else session_id ne 'login'
-
-} else {
-  # there is no session cookie
-  $login_rv = {};
-}
-
-if ( !$session_id ) {
-  # XXX why are we getting agentnum from a CGI param? surely it should 
-  # be some kind of configuration option.
-  #
-  # show the login page
-  $session_id = 'login'; # set state
-  my $login_info = login_info( 'agentnum' => scalar($cgi->param('agentnum')) );
-
-  do_template('login', { %$login_rv, %$login_info });
-  exit;
-}
-
-# at this point $session_id is a real session
 
 #order|pw_list XXX ???
 my @actions = ( qw(
@@ -172,13 +79,18 @@ my @actions = ( qw(
   real_port_graph
   change_password
   process_change_password
+  customer_suspend_pkg
+  process_suspend_pkg
+));
+
+my @nologin_actions = (qw(
   forgot_password
   do_forgot_password
   process_forgot_password
   do_process_forgot_password
-  customer_suspend_pkg
-  process_suspend_pkg
 ));
+push @actions, @nologin_actions;
+my %nologin_actions = map { $_=>1 } @nologin_actions;
 
 my $action = 'myaccount'; # sensible default
 if ( $cgi->param('action') =~ /^(\w+)$/ ) {
@@ -189,6 +101,104 @@ if ( $cgi->param('action') =~ /^(\w+)$/ ) {
   }
 }
 
+unless ( $nologin_actions{$action} ) {
+
+  my %cookies = CGI::Cookie->fetch;
+
+  my $login_rv;
+
+  if ( exists($cookies{'session'}) ) {
+
+    $session_id = $cookies{'session'}->value;
+
+    if ( $session_id eq 'login' ) {
+      # then we've just come back from the login page
+
+      $cgi->param('password') =~ /^(.{0,$form_max})$/;
+      my $password = $1;
+
+      if ( $cgi->param('email') =~ /^\s*([a-z0-9_\-\.\@]{1,$form_max})\s*$/i ) {
+
+        my $email = $1;
+        $login_rv = login(
+          'email'    => $email,
+          'password' => $password
+        );
+        $session_id = $login_rv->{'session_id'};
+
+      } else {
+
+        $cgi->param('username') =~ /^\s*([a-z0-9_\-\.\&]{0,$form_max})\s*$/i;
+        my $username = $1;
+
+        $cgi->param('domain') =~ /^\s*([\w\-\.]{0,$form_max})\s*$/;
+        my $domain = $1;
+
+        if ( $username and $domain and $password ) {
+
+          # authenticate
+          $login_rv = login(
+            'username' => $username,
+            'domain'   => $domain,
+            'password' => $password,
+          );
+          $session_id = $login_rv->{'session_id'};
+
+        } elsif ( $username or $domain or $password ) {
+        
+          my $error = 'Illegal '; #XXX localization...
+          my $count = 0;
+          if ( !$username ) {
+            $error .= 'username';
+            $count++;
+          }
+          if ( !$domain )  {
+            $error .= ', ' if $count;
+            $error .= 'domain';
+            $count++;
+          }
+          if ( !$password ) {
+            $error .= ', ' if $count;
+            $error .= 'and ' if $count > 1;
+            $error .= 'password';
+            $count++;
+          }
+          $error .= '.';
+          $login_rv = {
+            'username'  => $username,
+            'domain'    => $domain,
+            'password'  => $password,
+            'error'     => $error,
+          };
+          $session_id = undef; # attempt login again
+
+        }
+
+      } # else there was no input, so show no error message
+
+    } # else session_id ne 'login'
+
+  } else {
+    # there is no session cookie
+    $login_rv = {};
+  }
+
+  if ( !$session_id ) {
+    # XXX why are we getting agentnum from a CGI param? surely it should 
+    # be some kind of configuration option.
+    #
+    # show the login page
+    $session_id = 'login'; # set state
+    my $login_info = login_info( 'agentnum' => scalar($cgi->param('agentnum')) );
+
+    do_template('login', { %$login_rv, %$login_info });
+    exit;
+  }
+
+  # at this point $session_id is a real session
+
+}
+
 warn "calling $action sub\n"
   if $DEBUG;
 $FS::SelfService::DEBUG = $DEBUG;
@@ -1011,13 +1021,13 @@ sub process_change_password {
 }
 
 sub forgot_password {
-  login_info( 'agentnum' => scalar($cgi->param('agentnum')) ); #skin_info
+  login_info( 'agentnum' => scalar($cgi->param('agentnum')) );
 }
 
 sub do_forgot_password {
   reset_passwd(
     map { $_ => scalar($cgi->param($_)) }
-      qw( email username domain )
+      qw( agentnum email username domain )
   );
 }