From 7b268e364a68b076e1f3bd3741159fb51759ee19 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Mon, 30 Dec 2013 15:37:04 -0800 Subject: [PATCH] self-service access for contacts, RT#25533 --- FS/FS/ClientAPI/MyAccount.pm | 90 ++++++--- FS/FS/contact.pm | 2 - .../cgi/do_process_forgot_password.html | 4 +- .../FS-SelfService/cgi/forgot_password.html | 24 +-- fs_selfservice/FS-SelfService/cgi/login.html | 5 +- .../cgi/process_forgot_password.html | 3 +- fs_selfservice/FS-SelfService/cgi/selfservice.cgi | 204 +++++++++++---------- 7 files changed, 187 insertions(+), 145 deletions(-) diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index 37d21ea7e..d17131f2d 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -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' => '' }; } diff --git a/FS/FS/contact.pm b/FS/FS/contact.pm index 2a73b9cf6..d0dd8b773 100644 --- a/FS/FS/contact.pm +++ b/FS/FS/contact.pm @@ -471,8 +471,6 @@ sub by_selfservice_email { " AND ( disabled IS NULL OR disabled = '' )", }) or return ''; -warn $contact_email; - $contact_email->contact; } diff --git a/fs_selfservice/FS-SelfService/cgi/do_process_forgot_password.html b/fs_selfservice/FS-SelfService/cgi/do_process_forgot_password.html index 9274f9294..35728e7ec 100644 --- a/fs_selfservice/FS-SelfService/cgi/do_process_forgot_password.html +++ b/fs_selfservice/FS-SelfService/cgi/do_process_forgot_password.html @@ -10,8 +10,8 @@ <%= $error %> <%= if (!$error) { - $self_url =~ s/\?.*//; - $OUT .= "Your password has been changed. You can now log in."; + $selfurl =~ s/\?.*//; + $OUT .= "Your password has been changed. You can now log in."; } %> diff --git a/fs_selfservice/FS-SelfService/cgi/forgot_password.html b/fs_selfservice/FS-SelfService/cgi/forgot_password.html index e14034c7d..607151138 100644 --- a/fs_selfservice/FS-SelfService/cgi/forgot_password.html +++ b/fs_selfservice/FS-SelfService/cgi/forgot_password.html @@ -9,7 +9,8 @@ Forgot password

<%= $error %> -
+<%= $selfurl =~ s/\?.*//; ''; %> + @@ -17,25 +18,26 @@ Please enter your email address. A password reset email will be sent to that ad - - - - - <%= if ( $single_domain ) { - $OUT .= qq(); + $OUT .= qq( + + + + + + ); } else { $OUT .= qq( - + ); diff --git a/fs_selfservice/FS-SelfService/cgi/login.html b/fs_selfservice/FS-SelfService/cgi/login.html index 65efd7bdb..f7af4e9d8 100644 --- a/fs_selfservice/FS-SelfService/cgi/login.html +++ b/fs_selfservice/FS-SelfService/cgi/login.html @@ -9,7 +9,8 @@ Login

<%= $error %> - +<%= $selfurl =~ s/\?.*//; ''; %> + @@ -65,7 +66,7 @@ if ( $phone_login ) { OR

- +
Email address - <%= $single_domain ? '@'.$single_domain : '' %> -
Username + \@$single_domain +
Domain Email address - +
diff --git a/fs_selfservice/FS-SelfService/cgi/process_forgot_password.html b/fs_selfservice/FS-SelfService/cgi/process_forgot_password.html index 3d8c0583e..ec672c8d5 100644 --- a/fs_selfservice/FS-SelfService/cgi/process_forgot_password.html +++ b/fs_selfservice/FS-SelfService/cgi/process_forgot_password.html @@ -9,7 +9,8 @@ Reset password

<%= $error %> - +<%= $selfurl =~ s/\?.*//; ''; %> + diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi index 8d3a23b03..13723118c 100755 --- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi +++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi @@ -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 ) ); } -- 2.11.0
Phone number