--- loncom/interface/resetpw.pm 2013/02/05 15:33:36 1.30 +++ loncom/interface/resetpw.pm 2016/09/12 16:02:16 1.38 @@ -1,7 +1,7 @@ # The LearningOnline Network # Allow access to password changing via a token sent to user's e-mail. # -# $Id: resetpw.pm,v 1.30 2013/02/05 15:33:36 raeburn Exp $ +# $Id: resetpw.pm,v 1.38 2016/09/12 16:02:16 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -57,6 +57,7 @@ use Apache::lonnet; use Apache::loncommon; use Apache::lonlocal; use LONCAPA; +use HTML::Entities; sub handler { my $r = shift; @@ -87,17 +88,26 @@ sub handler { &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['token']); my @emailtypes = ('permanentemail','critnotification','notification'); - my $uname = &unescape($env{'form.uname'}); - my $udom = $env{'form.udom'}; + my $uname = $env{'form.uname'}; + $uname =~ s/^\s+|\s+$//g; + $uname = &LONCAPA::clean_username($uname); + my $udom = &LONCAPA::clean_domain($env{'form.udom'}); + my ($domdesc,$otherinst); + if ($udom) { + $domdesc = &Apache::lonnet::domain($udom,'description'); + if ($domdesc) { + my %servers = &Apache::lonnet::internet_dom_servers($udom); + unless (exists($servers{$server})) { + $otherinst = 1; + } + } + } my $token = $env{'form.token'}; my $brcrum = []; - my $bread_crumbs_component = 'Forgotten Password'; if ($token) { push (@{$brcrum}, {href => '/adm/resetpw', text => 'Update Password'}); - - $bread_crumbs_component = 'Reset Password'; } else { push (@{$brcrum}, {href => '/adm/resetpw', @@ -108,68 +118,153 @@ sub handler { text => 'Result'}); } } - my $args = {bread_crumbs => $brcrum, - bread_crumbs_component => $bread_crumbs_component}; - $r->print(&Apache::loncommon::start_page('Reset password','',$args)); - $r->print('

'.&mt('Reset forgotten LON-CAPA password').'

'); + my $args = {bread_crumbs => $brcrum}; + my $js; + unless ($token || $otherinst || ($uname && $udom)) { + my (@intdoms,@instdoms); + my $internet_names = &Apache::lonnet::get_internet_names($server); + if (ref($internet_names) eq 'ARRAY') { + @intdoms = @{$internet_names}; + } + if (@intdoms) { + my %iphost = &Apache::lonnet::get_iphost(); + foreach my $ip (keys(%iphost)) { + if (ref($iphost{$ip}) eq 'ARRAY') { + foreach my $id (@{$iphost{$ip}}) { + my $location = &Apache::lonnet::internet_dom($id); + if ($location) { + if (grep(/^\Q$location\E$/,@intdoms)) { + my $dom = &Apache::lonnet::host_domain($id); + unless (grep(/^\Q$dom\E/,@instdoms)) { + push(@instdoms,$dom); + } + } + } + } + } + } + } + my $instdomstr; + if (@instdoms > 0) { + $instdomstr = "'".join("','",@instdoms)."'"; + } + my %js_lt = &Apache::lonlocal::texthash( + thdo => 'The domain you have selected is for another institution.', + yowi => 'You will be switched to the Forgot Password utility at that institution.', + unam => 'You must enter a username.', + mail => 'You must enter an e-mail address.' + ); + &js_escape(\%js_lt); + $js = <<"END"; + +END + } + my $header = &Apache::loncommon::start_page('Reset password',$js,$args). + '

'.&mt('Reset forgotten LON-CAPA password').'

'; my $output; if ($token) { $output = &reset_passwd($r,$token,$contact_name,$contact_email); - } elsif ($uname && $udom) { - my $domdesc = &Apache::lonnet::domain($udom,'description'); - my $authtype = &Apache::lonnet::queryauthenticate($uname,$udom); - if ($authtype =~ /^internal/) { - my $useremail = $env{'form.useremail'}; - if ($useremail !~ /^[^\@]+\@[^\@]+\.[^\@\.]+$/) { - $output = &invalid_state('baduseremail',$domdesc, - $contact_name,$contact_email); - } else { - my %userinfo = - &Apache::lonnet::get('environment',\@emailtypes, - $udom,$uname); - my @allemails; - foreach my $type (@emailtypes) { - my $email = $userinfo{$type}; - my @items; - if ($email =~ /,/) { - @items = split(',',$userinfo{$type}); - } else { - @items = ($email); - } - foreach my $item (@items) { - if ($item =~ /^[^\@]+\@[^\@]+\.[^\@\.]+$/) { - unless(grep(/^\Q$item\E$/,@allemails)) { - push(@allemails,$item); + } elsif ($udom) { + if (!$domdesc) { + $output = &invalid_state('baddomain',$domdesc, + $contact_name,$contact_email); + } elsif ($otherinst) { + ($header,$output) = &homeserver_redirect($uname,$udom,$domdesc,$brcrum); + } elsif ($uname) { + my $authtype = &Apache::lonnet::queryauthenticate($uname,$udom); + if ($authtype =~ /^internal/) { + my $useremail = $env{'form.useremail'}; + my ($blocked,$blocktext) = + &Apache::loncommon::blocking_status('passwd',$uname,$udom); + if ($blocked) { + $output = '

'.$blocktext.'

' + .&display_actions($contact_email,$domdesc); + } elsif ($useremail !~ /^[^\@]+\@[^\@]+\.[^\@\.]+$/) { + $output = &invalid_state('baduseremail',$domdesc, + $contact_name,$contact_email); + } else { + my %userinfo = + &Apache::lonnet::get('environment',\@emailtypes, + $udom,$uname); + my @allemails; + foreach my $type (@emailtypes) { + my $email = $userinfo{$type}; + my @items; + if ($email =~ /,/) { + @items = split(',',$userinfo{$type}); + } else { + @items = ($email); + } + foreach my $item (@items) { + if ($item =~ /^[^\@]+\@[^\@]+\.[^\@\.]+$/) { + unless(grep(/^\Q$item\E$/,@allemails)) { + push(@allemails,$item); + } } } } - } - if (@allemails > 0) { - if (grep(/^\Q$useremail\E$/,@allemails)) { - $output = &send_token($uname,$udom,$useremail,$server, - $domdesc,$contact_name, - $contact_email); + if (@allemails > 0) { + if (grep(/^\Q$useremail\E$/,@allemails)) { + $output = &send_token($uname,$udom,$useremail,$server, + $domdesc,$contact_name, + $contact_email); + } else { + $output = &invalid_state('mismatch',$domdesc, + $contact_name, + $contact_email); + } } else { - $output = &invalid_state('mismatch',$domdesc, - $contact_name, - $contact_email); + $output = &invalid_state('missing',$domdesc, + $contact_name,$contact_email); } - } else { - $output = &invalid_state('missing',$domdesc, - $contact_name,$contact_email); } + } elsif ($authtype =~ /^(krb|unix|local)/) { + $output = &invalid_state('authentication',$domdesc, + $contact_name,$contact_email); + } else { + $output = &invalid_state('invalid',$domdesc, + $contact_name,$contact_email); } - } elsif ($authtype =~ /^(krb|unix|local)/) { - $output = &invalid_state('authentication',$domdesc, - $contact_name,$contact_email); } else { - $output = &invalid_state('invalid',$domdesc, - $contact_name,$contact_email); + $output = &get_uname($defdom); } } else { $output = &get_uname($defdom); } - $r->print($output); + $r->print($header.$output); $r->print(&Apache::loncommon::end_page()); return OK; } @@ -177,8 +272,8 @@ sub handler { sub get_uname { my ($defdom) = @_; my %lt = &Apache::lonlocal::texthash( - unam => 'username', - udom => 'domain', + unam => 'LON-CAPA username', + udom => 'LON-CAPA domain', uemail => 'E-mail address in LON-CAPA', proc => 'Proceed'); @@ -188,16 +283,23 @@ sub get_uname { .'
  • '.&mt('You must be able to access e-mail sent to that address.').'
  • ' .'
  • '.&mt('Your LON-CAPA account must be of a type for which LON-CAPA can reset a password.') .''; - $msg .= '
    '. + my $mobileargs; + (undef,undef,undef,undef,undef,undef,my $clientmobile) = + &Apache::loncommon::decode_user_agent(); + if ($clientmobile) { + $mobileargs = 'autocapitalize="off" autocorrect="off" '; + } + my $onchange = 'javascript:verifyDomain(this,this.form);'; + $msg .= ''. &Apache::lonhtmlcommon::start_pick_box(). - &Apache::lonhtmlcommon::row_title('LON-CAPA '.$lt{'unam'}). - ''. + &Apache::lonhtmlcommon::row_title($lt{'unam'}). + ''. &Apache::lonhtmlcommon::row_closure(1). - &Apache::lonhtmlcommon::row_title('LON-CAPA '.$lt{'udom'}). - &Apache::loncommon::select_dom_form($defdom,'udom'). + &Apache::lonhtmlcommon::row_title($lt{'udom'}). + &Apache::loncommon::select_dom_form($defdom,'udom',undef,undef,$onchange). &Apache::lonhtmlcommon::row_closure(1). &Apache::lonhtmlcommon::row_title($lt{'uemail'}). - ''. + ''. &Apache::lonhtmlcommon::end_pick_box(). '

    '; return $msg; @@ -229,7 +331,10 @@ sub send_token { my $result = &send_mail($domdesc,$email,$mailmsg,$contact_name, $contact_email); if ($result eq 'ok') { - $msg .= &mt("An e-mail sent to the e-mail address associated with your LON-CAPA account includes the web address for the link you should use to complete the reset process.

    The link included in the message will be valid for the next two hours."); + $msg .= + &mt('An e-mail sent to the e-mail address associated with your LON-CAPA account includes the web address for the link you should use to complete the reset process.') + .'

    ' + .&mt('The link included in the message will be valid for the next [_1]two[_2] hours.','',''); } else { $msg .= '

    ' @@ -237,7 +342,6 @@ sub send_token { .' associated with your LON-CAPA account.') .'

    ' .&display_actions($contact_email,$domdesc); - } } else { $msg .= @@ -289,6 +393,8 @@ sub invalid_state { $msg = &mt('A valid e-mail address was not located in the LON-CAPA system for the username and domain you provided.'); } elsif ($error eq 'authentication') { $msg = &mt('The username you provided uses an authentication type which can not be reset directly via LON-CAPA.'); + } elsif ($error eq 'baddomain') { + $msg = &mt('The domain you provided was not verified as a valid domain in the LON-CAPA system.'); } $msg = '

    '.$msg.'

    ' .&display_actions($contact_email,$domdesc); @@ -296,6 +402,25 @@ sub invalid_state { return $msg; } +sub homeserver_redirect { + my ($uname,$udom,$domdesc,$brcrum) = @_; + my $uhome = &Apache::lonnet::homeserver(); + if ($uhome eq 'no_host') { + $uhome = &Apache::lonnet::domain($udom,'primary'); + } + my $protocol = $Apache::lonnet::protocol{$uhome}; + $protocol = 'http' if ($protocol ne 'https'); + my $url = $protocol.'://'.&Apache::lonnet::hostname($uhome).'/adm/resetpw'; + # Breadcrumbs + my $start_page = &Apache::loncommon::start_page('Switching Server',undef, + {'redirect' => [0,$url], + 'bread_crumbs' => $brcrum,}); + my $output = '

    '.&mt('This LON-CAPA server belongs to a different domain.').' '. + &mt('You are being switched to your domain ([_1]), to use the "Forgot Password" tool.',$domdesc). + '

    '; + return ($start_page,$output); +} + sub reset_passwd { my ($r,$token,$contact_name,$contact_email) = @_; my $msg; @@ -312,7 +437,12 @@ sub reset_passwd { ($data{'email'} =~ /^[^\@]+\@[^\@]+\.[^\@\.]+$/) && ($data{'temppasswd'} =~/^\w+$/)) { my $reqtime = &Apache::lonlocal::locallocaltime($data{'time'}); - if ($now - $data{'time'} < 7200) { + my ($blocked,$blocktext) = + &Apache::loncommon::blocking_status('passwd',$data{'username'},$data{'domain'}); + if ($blocked) { + $msg = '

    '.$blocktext.'

    '; + return $msg; + } elsif ($now - $data{'time'} < 7200) { if ($env{'form.action'} eq 'verify_and_change_pass') { unless (($env{'form.uname'} eq $data{'username'}) && ($env{'form.udom'} eq $data{'domain'}) && ($env{'form.email'} eq $data{'email'})) { $msg = &generic_failure_msg($contact_name,$contact_email); @@ -328,23 +458,24 @@ sub reset_passwd { my $mailmsg = &mt('The password for your LON-CAPA account in the [_1] domain was changed [_2] from IP address: [_3]. If you did not perform this change or authorize it, please contact the [_4] ([_5]).',$domdesc,$now,$ENV{'REMOTE_ADDR'},$contact_name,$contact_email)."\n"; my $result = &send_mail($domdesc,$data{'email'},$mailmsg, $contact_name,$contact_email); + my $confirm_msg; if ($result eq 'ok') { - $msg .= - '

    ' - .&mt('An e-mail confirming setting of the password' - .' for your LON-CAPA account has been sent to [_1].' - ,$data{'email'}) - .'

    '; + $confirm_msg = + &Apache::lonhtmlcommon::confirm_success( + &mt('An e-mail confirming setting of the password' + .' for your LON-CAPA account has been sent to [_1].' + ,''.$data{'email'}.'')); } else { - $msg .= - '

    ' - .&mt('An error occurred when sending e-mail to [_1]' - .' confirming setting of your new password.' - ,$data{'email'}) - .'

    '; + $confirm_msg = + &Apache::lonhtmlcommon::confirm_success( + &mt('An error occurred when sending e-mail to [_1]' + .' confirming setting of your new password.' + ,''.$data{'email'}.''),1); } - $msg .= '
    ' - .''.&mt('Go to the login page').'.'; + $msg .= + &Apache::loncommon::confirmwrapper($confirm_msg) + .&Apache::lonhtmlcommon::actionbox([ + ''.&mt('Go to the login page').'']); } elsif ($change_failed eq 'invalid_client') { my $homeserver = &Apache::lonnet::homeserver($data{'username'},$data{'domain'}); if ($homeserver eq 'no_host') { @@ -398,7 +529,7 @@ sub generic_failure_msg { '

    ' .&mt('A problem occurred when attempting to reset the password for your account.') .'
    ' - .&mt('Please contact the [_1] - ([_2]) for assistance.', + .&mt('Please contact the [_1] ([_2]) for assistance.', $contact_name,''.$contact_email.'') .'

    '; } @@ -438,7 +569,7 @@ sub display_actions { '

    ' .&mt('You may wish to send an e-mail to the' .' server administrator: [_1] for the [_2] domain.', - ''.$Apache::lonnet::perlvar{'AdminEmail'}.'', + ''.$Apache::lonnet::perlvar{'AdmEMail'}.'', ''.$domdesc.'') .'

    '; }