--- loncom/interface/resetpw.pm 2009/09/14 14:48:20 1.11.2.1 +++ loncom/interface/resetpw.pm 2018/12/27 18:14:25 1.42 @@ -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.11.2.1 2009/09/14 14:48:20 raeburn Exp $ +# $Id: resetpw.pm,v 1.42 2018/12/27 18:14:25 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -26,6 +26,28 @@ # http://www.lon-capa.org/ # # + +=pod + +=head1 NAME + +Apache::resetpw: reset user password. + +=head1 SYNOPSIS + +Handles resetting of forgotten passwords. + +This is part of the LearningOnline Network with CAPA project +described at http://www.lon-capa.org. + +=head1 OVERVIEW + +A user with an e-mail address associated with his/her LON-CAPA username +can reset a forgotten password, using a link sent to the e-mail address +if the authentication type for the account is "internal". + +=cut + package Apache::resetpw; use strict; @@ -35,6 +57,7 @@ use Apache::lonnet; use Apache::loncommon; use Apache::lonlocal; use LONCAPA; +use HTML::Entities; sub handler { my $r = shift; @@ -44,73 +67,212 @@ sub handler { return OK; } my $contact_name = &mt('LON-CAPA helpdesk'); - my $contact_email = $r->dir_config('lonSupportEMail'); + my $origmail = $r->dir_config('lonSupportEMail'); my $server = $r->dir_config('lonHostID'); - my $defdom = $r->dir_config('lonDefDomain'); + my $defdom = &Apache::lonnet::default_login_domain(); + my $contacts = + &Apache::loncommon::build_recipient_list(undef,'helpdeskmail', + $defdom,$origmail); + my ($contact_email) = split(',',$contacts); + my $handle = &Apache::lonnet::check_for_valid_session($r); + my $lonidsdir=$r->dir_config('lonIDsDir'); + if ($handle ne '') { + if ($handle=~/^publicuser\_/) { + unlink($r->dir_config('lonIDsDir')."/$handle.id"); + } else { + &Apache::lonnet::transfer_profile_to_env($lonidsdir,$handle); + } + } &Apache::lonacc::get_posted_cgi($r); &Apache::lonlocal::get_language_handle($r); &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) { + $otherinst = 1; + my @ids=&Apache::lonnet::current_machine_ids(); + my %servers = &Apache::lonnet::internet_dom_servers($udom); + foreach my $server (keys(%servers)) { + if (grep(/^\Q$server\E$/,@ids)) { + $otherinst = 0; + last; + } + } + } + } my $token = $env{'form.token'}; - my $start_page = - &Apache::loncommon::start_page('Reset password','', - { - 'no_inline_link' => 1,}); - $r->print($start_page); - $r->print('

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

'); - my $output; + my $brcrum = []; 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 $email = ''; - my $emailtarget; - foreach my $type (@emailtypes) { - $email = $userinfo{$type}; - if ($email =~ /[^\@]+\@[^\@]+/) { - $emailtarget = $type; - last; + push (@{$brcrum}, + {href => '/adm/resetpw', + text => 'Update Password'}); + } else { + push (@{$brcrum}, + {href => '/adm/resetpw', + text => 'Account Information'}); + if ($uname && $udom) { + push (@{$brcrum}, + {href => '/adm/resetpw', + text => 'Result'}); + } + } + 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); + } + } + } } } - if ($email =~ /^[^\@]+\@[^\@]+\.[^\@\.]+$/) { - if ($useremail eq $email) { - $output = &send_token($uname,$udom,$email,$server, - $domdesc,$contact_name, - $contact_email); + } + } + 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) { + $r->print($header); + &reset_passwd($r,$token,$contact_name,$contact_email); + $r->print(&Apache::loncommon::end_page()); + return OK; + } 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); + } 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; } @@ -118,41 +280,46 @@ 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'); - my $msg = &mt('If you use the same account for other campus services besides LON-CAPA, (e.g., e-mail, course registration, etc.), a separate centrally managed mechanism likely exists to reset a password. However, if your account is used for just LON-CAPA access you will probably be able to reset a password from this page.'); - $msg .= &mt('Three conditions must be met:') - .'