# The LearningOnline Network # Allow visitors to create a user account with the username being either an # institutional log-in ID (institutional authentication required - localauth # or kerberos) or an e-mail address. # # $Id: createaccount.pm,v 1.40.2.5.2.11 2012/03/01 00:25:15 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # # This file is part of the LearningOnline Network with CAPA (LON-CAPA). # # LON-CAPA is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # LON-CAPA is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with LON-CAPA; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # /home/httpd/html/adm/gpl.txt # # http://www.lon-capa.org/ # # package Apache::createaccount; use strict; use Apache::Constants qw(:common); use Apache::lonacc; use Apache::lonnet; use Apache::loncommon; use Apache::lonhtmlcommon; use Apache::lonlocal; use Apache::lonauth; use Apache::resetpw; use Captcha::reCAPTCHA; use DynaLoader; # for Crypt::DES version use Crypt::DES; use LONCAPA qw(:DEFAULT :match); use HTML::Entities; sub handler { my $r = shift; &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; if ($r->header_only) { return OK; } my $domain; my $sso_username = $r->subprocess_env->get('REDIRECT_SSOUserUnknown'); my $sso_domain = $r->subprocess_env->get('REDIRECT_SSOUserDomain'); my $privkey = $r->dir_config('reCAPTCHA_PRIVATE'); my $pubkey = $r->dir_config('reCAPTCHA_PUBLIC'); &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['token','courseid']); &Apache::lonacc::get_posted_cgi($r); &Apache::lonlocal::get_language_handle($r); if ($sso_username ne '' && $sso_domain ne '') { $domain = $sso_domain; } else { $domain = &Apache::lonnet::default_login_domain(); if (defined($env{'form.courseid'})) { if (&validate_course($env{'form.courseid'})) { if ($env{'form.courseid'} =~ /^($match_domain)_($match_courseid)$/) { $domain = $1; } } } } my $domdesc = &Apache::lonnet::domain($domain,'description'); my $contact_name = &mt('LON-CAPA helpdesk'); my $origmail = $Apache::lonnet::perlvar{'lonSupportEMail'}; my $contacts = &Apache::loncommon::build_recipient_list(undef,'helpdeskmail', $domain,$origmail); my ($contact_email) = split(',',$contacts); my $lonhost = $r->dir_config('lonHostID'); my $include = $r->dir_config('lonIncludes'); my $start_page; my $handle = &Apache::lonnet::check_for_valid_session($r); if (($handle ne '') && ($handle !~ /^publicuser_\d+$/)) { $start_page = &Apache::loncommon::start_page('Already logged in'); my $end_page = &Apache::loncommon::end_page(); $r->print($start_page."\n".'

'.&mt('You are already logged in').'

'. '

'.&mt('Please either [_1]continue the current session[_2] or [_3]log out[_4].','','','',''). '

'.&mt('Login problems?').'

'.$end_page); return OK; } my ($js,$courseid,$title); if (defined($env{'form.courseid'})) { $courseid = &validate_course($env{'form.courseid'}); } if ($courseid ne '') { $js = &catreturn_js(); $title = 'Self-enroll in a LON-CAPA course'; } else { $title = 'Create a user account in LON-CAPA'; } if ($env{'form.phase'} eq 'selfenroll_login') { $title = 'Self-enroll in a LON-CAPA course'; if ($env{'form.udom'} ne '') { $domain = $env{'form.udom'}; } my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$domain); my ($cancreate,$statustocreate) = &get_creation_controls($domain,$domconfig{'usercreation'}); my ($result,$output) = &username_validation($r,$env{'form.uname'},$domain,$domdesc, $contact_name,$contact_email,$courseid, $lonhost,$statustocreate); if ($result eq 'existingaccount') { $r->print($output); &print_footer($r); return OK; } else { $start_page = &Apache::loncommon::start_page($title,$js, {'no_inline_link' => 1,}); &print_header($r,$start_page,$courseid); $r->print($output); &print_footer($r); return OK; } } $start_page = &Apache::loncommon::start_page($title,$js, {'no_inline_link' => 1,}); my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$domain); my ($cancreate,$statustocreate) = &get_creation_controls($domain,$domconfig{'usercreation'}); if (@{$cancreate} == 0) { &print_header($r,$start_page,$courseid); my $output = '

'.&mt('Account creation unavailable').'

'. ''. &mt('Creation of a new user account using an e-mail address or an institutional log-in ID as username is not permitted for [_1].',$domdesc).'

'; $r->print($output); &print_footer($r); return OK; } if ($sso_username ne '') { &print_header($r,$start_page,$courseid); my ($msg,$sso_logout); $sso_logout = &sso_logout_frag($r,$domain); if (grep(/^sso$/,@{$cancreate})) { $msg = '

'.&mt('Account creation').'

'. &mt("Although your username and password were authenticated by your institution's Single Sign On system, you do not currently have a LON-CAPA account at this institution.").'
'; $msg .= &username_check($sso_username,$domain,$domdesc,$courseid, $lonhost,$contact_email,$contact_name, $sso_logout,$statustocreate); } else { $msg = '

'.&mt('Account creation unavailable').'

'. ''.&mt("Although your username and password were authenticated by your institution's Single Sign On system, you do not currently have a LON-CAPA account at this institution, and you are not permitted to create one.").'

'.&mt('Please contact the [_1] ([_2]) for assistance.',$contact_name,$contact_email).'
'. $sso_logout; } $r->print($msg); &print_footer($r); return OK; } my ($output,$nostart,$noend); my $token = $env{'form.token'}; if ($token) { ($output,$nostart,$noend) = &process_mailtoken($r,$token,$contact_name,$contact_email,$domain, $domdesc,$lonhost,$include,$start_page); if ($nostart) { if ($noend) { return OK; } else { $r->print($output); &print_footer($r); return OK; } } else { &print_header($r,$start_page,$courseid); $r->print($output); &print_footer($r); return OK; } } if ($env{'form.phase'} eq 'username_activation') { (my $result,$output,$nostart) = &username_activation($r,$env{'form.uname'},$domain,$domdesc, $lonhost,$courseid); if ($result eq 'ok') { if ($nostart) { return OK; } } &print_header($r,$start_page,$courseid); $r->print($output); &print_footer($r); return OK; } elsif ($env{'form.phase'} eq 'username_validation') { (my $result,$output) = &username_validation($r,$env{'form.uname'},$domain,$domdesc, $contact_name,$contact_email,$courseid, $lonhost,$statustocreate); if ($result eq 'existingaccount') { $r->print($output); &print_footer($r); return OK; } else { &print_header($r,$start_page,$courseid); } } elsif ($env{'form.create_with_email'}) { &print_header($r,$start_page,$courseid); $output = &process_email_request($env{'form.useremail'},$domain,$domdesc, $contact_name,$contact_email,$cancreate, $lonhost,$domconfig{'usercreation'}, $courseid,$privkey); } elsif (!$token) { &print_header($r,$start_page,$courseid); my $now=time; if (grep(/^login$/,@{$cancreate})) { my $jsh=Apache::File->new($include."/londes.js"); $r->print(<$jsh>); $r->print(&javascript_setforms($now)); } if (grep(/^email$/,@{$cancreate})) { $r->print(&javascript_validmail()); } $output = &print_username_form($domain,$domdesc,$cancreate,$now,$lonhost, $courseid,$pubkey); } $r->print($output); &print_footer($r); return OK; } sub get_custom_name { my ($domain) = @_; if ($domain eq 'relate') { return 'Mechanics Online'; } else { return lc($domain); } } sub print_header { my ($r,$start_page,$courseid) = @_; $r->print($start_page); &Apache::lonhtmlcommon::clear_breadcrumbs(); if ($courseid ne '') { my %coursehash = &Apache::lonnet::coursedescription($courseid); &selfenroll_crumbs($r,$courseid,$coursehash{'description'}); } &Apache::lonhtmlcommon::add_breadcrumb ({href=>"/adm/createuser", text=>"New username"}); $r->print(&Apache::lonhtmlcommon::breadcrumbs('Create account')); return; } sub print_footer { my ($r) = @_; if ($env{'form.courseid'} ne '') { $r->print('
'. &Apache::lonhtmlcommon::echo_form_input(['backto','logtoken', 'token','serverid','uname','upass','phase','create_with_email', 'code','useremail','crypt','cfirstname','clastname', 'cmiddlename','cgeneration','cpermanentemail','cid']). '
'); } $r->print(&Apache::loncommon::end_page()); } sub selfenroll_crumbs { my ($r,$courseid,$desc) = @_; &Apache::lonhtmlcommon::add_breadcrumb ({href=>"javascript:ToCatalog('backupcrumbs','')", text=>"Course/Community Catalog"}); if ($env{'form.coursenum'} ne '') { &Apache::lonhtmlcommon::add_breadcrumb ({href=>"javascript:ToCatalog('backupcrumbs','details')", text=>"Course details"}); } my $last_crumb; if ($desc ne '') { $last_crumb = &mt('Self-enroll in [_1]',"$desc"); } else { $last_crumb = &mt('Self-enroll'); } &Apache::lonhtmlcommon::add_breadcrumb ({href=>"javascript:ToSelfenroll('backupcrumbs')", text=>$last_crumb, no_mt=>"1"}); return; } sub validate_course { my ($courseid) = @_; my ($cdom,$cnum) = ($courseid =~ /^($match_domain)_($match_courseid)$/); if (($cdom ne '') && ($cnum ne '')) { if (&Apache::lonnet::is_course($cdom,$cnum)) { return ($courseid); } } return; } sub javascript_setforms { my ($now) = @_; my $js = < function send() { this.document.server.elements.uname.value = this.document.client.elements.uname.value; this.document.server.elements.udom.value = this.document.client.elements.udom.value; uextkey=this.document.client.elements.uextkey.value; lextkey=this.document.client.elements.lextkey.value; initkeys(); this.document.server.elements.upass.value = crypted(this.document.client.elements.upass$now.value); this.document.client.elements.uname.value=''; this.document.client.elements.upass$now.value=''; this.document.server.submit(); return false; } ENDSCRIPT return $js; } sub javascript_checkpass { my ($now) = @_; my $nopass = &mt('You must enter a password.'); my $mismatchpass = &mt('The passwords you entered did not match.').'\\n'. &mt('Please try again.'); my $js = <<"ENDSCRIPT"; ENDSCRIPT return $js; } sub javascript_validmail { my %lt = &Apache::lonlocal::texthash ( email => 'The e-mail address you entered', notv => 'is not a valid e-mail address', ); my $output = "\n".''."\n"; return $output; } sub print_username_form { my ($domain,$domdesc,$cancreate,$now,$lonhost,$courseid,$pubkey) = @_; my %lt = &Apache::lonlocal::texthash ( unam => 'username', udom => 'domain', uemail => 'E-mail address in LON-CAPA', proc => 'Proceed', crea => 'Create account with a username provided by this institution', crlc => 'Create LON-CAPA account', type => 'Type in your log-in ID and password to find out.', plse => 'Please enter a valid e-mail address below.', inst => 'Instructions on how to activate your account will be sent to the e-mail address you provide.', aftr => 'After completing the activation process you will have access to a "self test" that will help you assess your readiness for the course.', thes => 'The same account will be used for access to the Mechanics Online course, once it becomes available on March 1, 2012.', ); my $output; if (ref($cancreate) eq 'ARRAY') { if (grep(/^login$/,@{$cancreate})) { my %domdefaults = &Apache::lonnet::get_domain_defaults($domain); if ((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) || ($domdefaults{'auth_def'} eq 'localauth')) { $output = '

'.$lt{'crea'}.'

'; my $submit_text = $lt{'crlc'}; $output .= &mt('If you already have a log-in ID at this institution,[_1] you may be able to use it for LON-CAPA.','
'). '

'.$lt{'type'}.'

'; $output .= &login_box($now,$lonhost,$courseid,$submit_text, $domain,'createaccount').'
'; } } if (grep(/^email$/,@{$cancreate})) { $output .= '

'.&mt('Create account with an e-mail address as your username').'

'. '

'. &mt('You are about to sign-up for the [_1]Mechanics Online[_2] course.','','').'
'. $lt{'plse'}.'

'; my $captchaform = &create_recaptcha($pubkey); if ($captchaform) { my $submit_text = &mt('Sign-up'); my $emailform = ''; if (grep(/^login$/,@{$cancreate})) { $output .= &mt('Provide your e-mail address to sign up for a Mechanics Online account [_1]if you do not have a log-in ID at your institution.','
').'

'; } else { $output .= '
'; } $output .= '
'. &Apache::lonhtmlcommon::start_pick_box()."\n". &Apache::lonhtmlcommon::row_title(&mt('E-mail address'), 'LC_pick_box_title')."\n". $emailform."\n". &Apache::lonhtmlcommon::row_closure(1). &Apache::lonhtmlcommon::row_title(&mt('Validation'), 'LC_pick_box_title')."\n". $captchaform."\n". &mt('If either word is hard to read, [_1] will replace them.','reCAPTCHA refresh').'

'; if ($courseid ne '') { $output .= ''."\n"; } $output .= &Apache::lonhtmlcommon::row_closure(1). &Apache::lonhtmlcommon::row_title().'
'. ''. &Apache::lonhtmlcommon::row_closure(1). &Apache::lonhtmlcommon::end_pick_box().'

'; if ($courseid ne '') { $output .= &Apache::lonhtmlcommon::echo_form_input(['courseid']); } $output .= '
'; } else { my $helpdesk = '/adm/helpdesk?origurl=%2fadm%2fcreateaccount'; if ($courseid ne '') { $helpdesk .= '&courseid='.$courseid; } $output .= ''.&mt('An error occurred generating the validation code[_1] required for an e-mail address to be used as username.','
').'


'.&mt('[_1]Contact the helpdesk[_2] or [_3]reload[_2] the page and try again.','','',''); } $output .= '
'; } } if ($output eq '') { $output = &mt('Creation of a new LON-CAPA user account using an e-mail address or an institutional log-in ID as your username is not permitted at [_1].',$domdesc); } else { $output .= ''; } return $output; } sub login_box { my ($now,$lonhost,$courseid,$submit_text,$domain,$context) = @_; my $output; my %titles = &Apache::lonlocal::texthash( createaccount => 'Log-in ID', selfenroll => 'Username', ); my ($lkey,$ukey) = &Apache::lonpreferences::des_keys(); my ($lextkey,$uextkey) = &getkeys($lkey,$ukey); my $logtoken=Apache::lonnet::reply('tmpput:'.$ukey.$lkey.'&createaccount:createaccount', $lonhost); $output = &serverform($logtoken,$lonhost,undef,$courseid,$context); my $unameform = ''; my $upassform = ''; $output .= '
'."\n". ''. &Apache::lonhtmlcommon::start_pick_box()."\n". &Apache::lonhtmlcommon::row_title($titles{$context}, 'LC_pick_box_title')."\n". $unameform."\n". &Apache::lonhtmlcommon::row_closure(1)."\n". &Apache::lonhtmlcommon::row_title(&mt('Password'), 'LC_pick_box_title')."\n". $upassform. &Apache::lonhtmlcommon::row_closure(1). &Apache::lonhtmlcommon::row_title(). '
'."\n"; if ($context eq 'selfenroll') { $output .= '

'. ''. ''.&mt('Forgot password?').''. '
'."\n"; } $output .= &Apache::lonhtmlcommon::row_closure(1)."\n". &Apache::lonhtmlcommon::end_pick_box().'
'."\n"; $output .= ''."\n". ''."\n". '
'; return $output; } sub process_email_request { my ($useremail,$domain,$domdesc,$contact_name,$contact_email,$cancreate, $server,$settings,$courseid,$privkey) = @_; $useremail = lc($env{'form.useremail'}); my $output; if (ref($cancreate) eq 'ARRAY') { if (!grep(/^email$/,@{$cancreate})) { $output = &invalid_state('noemails',$domdesc, $contact_name,$contact_email); return $output; } elsif ($useremail !~ /^[^\@]+\@[^\@]+\.[^\@\.]+$/) { $output = &invalid_state('baduseremail',$domdesc, $contact_name,$contact_email); return $output; } else { my $uhome = &Apache::lonnet::homeserver($useremail,$domain); if ($uhome ne 'no_host') { $output = &invalid_state('existinguser',$domdesc, $contact_name,$contact_email,'',$useremail); return $output; } else { my $captcha = Captcha::reCAPTCHA->new; my $captcha_result = $captcha->check_answer( $privkey, $ENV{'REMOTE_ADDR'}, $env{'form.recaptcha_challenge_field'}, $env{'form.recaptcha_response_field'}, ); # PRIVATE key from https://www.google.com/recaptcha if (!$captcha_result->{is_valid}) { $output = &invalid_state('captcha',$domdesc,$contact_name, $contact_email); return $output; } my $uhome=&Apache::lonnet::homeserver($useremail,$domain); if ($uhome eq 'no_host') { my (%rulematch,%inst_results,%curr_rules,%got_rules,%alerts); &call_rulecheck($useremail,$domain,\%alerts,\%rulematch, \%inst_results,\%curr_rules,\%got_rules,'username'); if (ref($alerts{'username'}) eq 'HASH') { if (ref($alerts{'username'}{$domain}) eq 'HASH') { if ($alerts{'username'}{$domain}{$useremail}) { $output = &invalid_state('userrules',$domdesc, $contact_name,$contact_email); return $output; } } } my $format_msg = &guest_format_check($useremail,$domain,$cancreate, $settings); if ($format_msg) { $output = &invalid_state('userformat',$domdesc,$contact_name, $contact_email,$format_msg); return $output; } } } } $output = &send_token($domain,$useremail,$server,$domdesc,$contact_name, $contact_email,$courseid); } return $output; } sub call_rulecheck { my ($uname,$udom,$alerts,$rulematch,$inst_results,$curr_rules, $got_rules,$tocheck) = @_; my ($checkhash,$checks); $checkhash->{$uname.':'.$udom} = { 'newuser' => 1, }; if ($tocheck eq 'username') { $checks = { 'username' => 1 }; } &Apache::loncommon::user_rule_check($checkhash,$checks, $alerts,$rulematch,$inst_results,$curr_rules, $got_rules); return; } sub send_token { my ($domain,$email,$server,$domdesc,$contact_name,$contact_email,$courseid) = @_; my $msg = '

'.&mt('Account creation status').'

'. &mt('Thank you for your request to create a new Mechanics Online account.'). '

'; my $now = time; my %info = ('ip' => $ENV{'REMOTE_ADDR'}, 'time' => $now, 'domain' => $domain, 'username' => $email, 'courseid' => $courseid); my $token = &Apache::lonnet::tmpput(\%info,$server,'createaccount'); if ($token !~ /^error/ && $token ne 'no_such_host') { my $esc_token = &escape($token); my $mailsubj = &mt('Your Mechanics Online Course Account'); my $msgfrom = &mt('Mechanics Online Course Staff'); my $mailmsg = &mt('Greetings.')."\n\n". &mt('Thank you for your interest in our Online Mechanics Course.'). ' '. &mt('In order to complete the registration process, please open the following link in your web browser:'). "\n\n". &Apache::lonnet::absolute_url().'/adm/createaccount?token='.$esc_token. "\n\n". &mt('This link will take you to a sign-up page where you will be asked to provide some general information and finalize the registration process.'). ' '. &mt('This link will take you to a sign-up page where you will be asked to provide some general information and finalize the registration process.'). ' '. &mt('A self-test (for review) is available within the course, for you to test your level of preparation.'). "\n\n". &mt('Best Regards,'). "\n\n". &mt('RELATE Group')."\n"; my $result = &Apache::resetpw::send_mail('MIT',$email,$mailmsg, $msgfrom,$contact_email, $mailsubj); if ($result eq 'ok') { $msg .= &mt('A message has been sent to the e-mail address you provided.').'
'.&mt('The message includes the web address for the link you will use to complete the sign-up process.').'
'.&mt("The link included in the message will be valid for the next [_1]two[_2] hours.",'',''); } else { $msg .= ''. &mt('An error occurred when sending a message to the e-mail address you provided.').'
'. ' '.&mt('Please contact the [_1] ([_2]) for assistance.',$contact_name,$contact_email); } } else { $msg .= ''. &mt('An error occurred creating a token required for the account creation process.').'
'. ' '.&mt('Please contact the [_1] ([_2]) for assistance.',$contact_name,$contact_email); } return $msg; } sub process_mailtoken { my ($r,$token,$contact_name,$contact_email,$domain,$domdesc,$lonhost, $include,$start_page) = @_; my ($msg,$nostart,$noend); my %data = &Apache::lonnet::tmpget($token); my $now = time; if (keys(%data) == 0) { $msg = &mt('Sorry, the URL you provided to complete creation of a new LON-CAPA account was invalid.') .' '.&mt('Either the token included in the URL has been deleted or the URL you provided was invalid.') .' '.&mt('Please submit a [_1]new request[_2] for account creation and follow the new link page included in the e-mail that will be sent to you.','
',''); return $msg; } if (($data{'time'} =~ /^\d+$/) && ($data{'domain'} ne '') && ($data{'username'} =~ /^[^\@]+\@[^\@]+\.[^\@\.]+$/)) { if ($now - $data{'time'} < 7200) { if ($env{'form.phase'} eq 'createaccount') { my ($result,$output) = &create_account($r,$domain,$lonhost, $data{'username'},$domdesc); if ($result eq 'ok') { $msg = $output; my $shownow = &Apache::lonlocal::locallocaltime($now); my $mailmsg = &mt('A [_1] account has been created [_2] from IP address: [_3]. If you did not perform this action or authorize it, please contact the [_4] ([_5]).',$domdesc,$shownow,$ENV{'REMOTE_ADDR'},$contact_name,$contact_email)."\n"; my $mailresult = &Apache::resetpw::send_mail($domdesc,$data{'email'}, $mailmsg,$contact_name, $contact_email); if ($mailresult eq 'ok') { $msg .= &mt('An e-mail confirming creation of your new LON-CAPA account has been sent to [_1].',$data{'username'}); } else { $msg .= &mt('An error occurred when sending e-mail to [_1] confirming creation of your LON-CAPA account.',$data{'username'}); } my %form = &start_session($r,$data{'username'},$domain, $lonhost,$data{'courseid'}, $token); $nostart = 1; $noend = 1; } else { $msg .= &mt('A problem occurred when attempting to create your new LON-CAPA account.') .'
'.$output # .&mt('Please contact the [_1] ([_2]) for assistance.',$contact_name,''.$contact_email.''); .&mt('Please contact the [_1] ([_2]) for assistance.',$contact_name,$contact_email); } my $delete = &Apache::lonnet::tmpdel($token); } else { $msg .= &mt('Please provide user information and a password for your new account.').'
'.&mt('Your password, which must contain at least seven characters, will be sent to the LON-CAPA server in an encrypted form.').'
'; $msg .= &print_dataentry_form($r,$domain,$lonhost,$include,$token,$now,$data{'username'},$start_page); $nostart = 1; } } else { $msg = &mt('Sorry, the token generated when you requested creation of an account has expired.') .' '.&mt('Please submit a [_1]new request[_2] for account creation and follow the new link included in the e-mail that will be sent to you.','',''); } } else { $msg .= &mt('Sorry, the URL generated when you requested creation of an account contained incomplete information.') .' '.&mt('Please submit a [_1]new request[_2] for account creation and follow the new link included in the e-mail that will be sent to you.','',''); } return ($msg,$nostart,$noend); } sub start_session { my ($r,$username,$domain,$lonhost,$courseid,$token) = @_; my %form = ( uname => $username, udom => $domain, ); my $firsturl = '/adm/roles'; if (defined($courseid)) { $courseid = &validate_course($courseid); if ($courseid ne '') { $form{'courseid'} = $courseid; $firsturl = '/adm/selfenroll?courseid='.$courseid; } } if ($r->dir_config('lonBalancer') eq 'yes') { &Apache::lonauth::success($r,$form{'uname'},$form{'udom'}, $lonhost,'noredirect',undef,\%form); if ($token ne '') { my $delete = &Apache::lonnet::tmpdel($token); } $r->internal_redirect('/adm/switchserver'); } else { &Apache::lonauth::success($r,$form{'uname'},$form{'udom'}, $lonhost,$firsturl,undef,\%form); } return %form; } sub print_dataentry_form { my ($r,$domain,$lonhost,$include,$mailtoken,$now,$username,$start_page) = @_; my ($error,$output); &print_header($r,$start_page); if (open(my $jsh,"<$include/londes.js")) { while(my $line = <$jsh>) { $r->print($line); } close($jsh); $output .= &javascript_setforms($now)."\n".&javascript_checkpass($now); my ($lkey,$ukey) = &Apache::lonpreferences::des_keys(); my ($lextkey,$uextkey) = &getkeys($lkey,$ukey); my $logtoken=Apache::lonnet::reply('tmpput:'.$ukey.$lkey.'&createaccount:createaccount', $lonhost); my $formtag = '
'; my ($datatable,$rowcount) = &Apache::loncreateuser::personal_data_display($username,$domain, 'email','selfcreate'); if ($rowcount) { $output .= '
'.$formtag.$datatable; } else { $output .= $formtag; } $output .= <<"ENDSERVERFORM"; ENDSERVERFORM if ($rowcount) { $output .= '
'. '
'; } my $upassone = ''; my $upasstwo = ''; my $submit_text = &mt('Create LON-CAPA account'); $output .= '

'.&mt('Login Data').'

'."\n". '
'."\n". &Apache::lonhtmlcommon::start_pick_box()."\n". &Apache::lonhtmlcommon::row_title(&mt('Username'), 'LC_pick_box_title', 'LC_oddrow_value')."\n". $username."\n". &Apache::lonhtmlcommon::row_closure(1)."\n". &Apache::lonhtmlcommon::row_title(&mt('Password'), 'LC_pick_box_title', 'LC_oddrow_value')."\n". $upassone."\n". &Apache::lonhtmlcommon::row_closure(1)."\n". &Apache::lonhtmlcommon::row_title(&mt('Confirm password'), 'LC_pick_box_title', 'LC_oddrow_value')."\n". $upasstwo. &Apache::lonhtmlcommon::row_closure(1)."\n". &Apache::lonhtmlcommon::row_title()."\n". '
'. &Apache::lonhtmlcommon::row_closure(1)."\n". &Apache::lonhtmlcommon::end_pick_box()."\n". ''."\n". ''."\n". ''."\n". ''."\n". '
'; if ($rowcount) { $output .= '
'."\n". ''."\n"; } } else { $output = &mt('Could not load javascript file [_1]','londes.js'); } return $output; } sub get_creation_controls { my ($domain,$usercreation) = @_; my (@cancreate,@statustocreate); if (ref($usercreation) eq 'HASH') { if (ref($usercreation->{'cancreate'}) eq 'HASH') { if (ref($usercreation->{'cancreate'}{'statustocreate'}) eq 'ARRAY') { @statustocreate = @{$usercreation->{'cancreate'}{'statustocreate'}}; if (@statustocreate == 0) { my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($domain); if (ref($types) eq 'ARRAY') { if (@{$types} == 0) { @statustocreate = ('default'); } } else { @statustocreate = ('default'); } } } else { @statustocreate = ('default'); my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($domain); if (ref($types) eq 'ARRAY') { push(@statustocreate,@{$types}); } } if (ref($usercreation->{'cancreate'}{'selfcreate'}) eq 'ARRAY') { @cancreate = @{$usercreation->{'cancreate'}{'selfcreate'}}; } elsif (($usercreation->{'cancreate'}{'selfcreate'} ne 'none') && ($usercreation->{'cancreate'}{'selfcreate'} ne '')) { @cancreate = ($usercreation->{'cancreate'}{'selfcreate'}); } } } return (\@cancreate,\@statustocreate); } sub create_account { my ($r,$domain,$lonhost,$username,$domdesc) = @_; my ($retrieved,$output,$upass) = &process_credentials($env{'form.logtoken'}, $env{'form.serverid'}); # Error messages my $error = ''.&mt('Error:').' '; my $end = '

'; my $rtnlink = ''. &mt('Return to previous page').''. &Apache::loncommon::end_page(); if ($retrieved eq 'ok') { if ($env{'form.courseid'} ne '') { my ($result,$userchkmsg) = &check_id($username,$domain,$domdesc); if ($result eq 'fail') { $output = $error.&mt('Invalid ID format').$end. $userchkmsg.$rtnlink; return ('fail',$output); } } } else { return ('fail',$error.$output.$end.$rtnlink); } # Call modifyuser my $result = &Apache::lonnet::modifyuser($domain,$username,$env{'form.cid'}, 'internal',$upass,$env{'form.cfirstname'}, $env{'form.cmiddlename'},$env{'form.clastname'}, $env{'form.cgeneration'},undef,undef,$username); $output = &mt('Generating user: [_1]',$result); my $uhome = &Apache::lonnet::homeserver($username,$domain); $output .= '
'.&mt('Home server: [_1]',$uhome).' '. &Apache::lonnet::hostname($uhome).'

'; return ('ok',$output); } sub username_validation { my ($r,$username,$domain,$domdesc,$contact_name,$contact_email,$courseid, $lonhost,$statustocreate) = @_; my ($retrieved,$output,$upass); $username= &LONCAPA::clean_username($username); $domain = &LONCAPA::clean_domain($domain); my $uhome = &Apache::lonnet::homeserver($username,$domain); ($retrieved,$output,$upass) = &process_credentials($env{'form.logtoken'}, $env{'form.serverid'}); if ($retrieved ne 'ok') { return ('fail',$output); } if ($uhome ne 'no_host') { my $result = &Apache::lonnet::authenticate($username,$upass,$domain); if ($result ne 'no_host') { my %form = &start_session($r,$username,$domain,$lonhost,$courseid); $output = '

'.&mt('A LON-CAPA account already exists for username [_1] at this institution ([_2]).',''.$username.'',$domdesc).'
'.&mt('The password entered was also correct so you have been logged in.'); return ('existingaccount',$output); } else { $output = &login_failure_msg($courseid); } } else { my $primlibserv = &Apache::lonnet::domain($domain,'primary'); my $authok; my %domdefaults = &Apache::lonnet::get_domain_defaults($domain); if ((($domdefaults{'auth_def'} =~/^krb(4|5)$/) && ($domdefaults{'auth_arg_def'} ne '')) || ($domdefaults{'auth_def'} eq 'localauth')) { my $checkdefauth = 1; $authok = &Apache::lonnet::reply("encrypt:auth:$domain:$username:$upass:$checkdefauth",$primlibserv); } else { $authok = 'non_authorized'; } if ($authok eq 'authorized') { $output = &username_check($username,$domain,$domdesc,$courseid,$lonhost, $contact_email,$contact_name,undef, $statustocreate); } else { $output = &login_failure_msg($courseid); } } return ('ok',$output); } sub login_failure_msg { my ($courseid) = @_; my $url; if ($courseid ne '') { $url = "/adm/selfenroll?courseid=".$courseid; } else { $url = "/adm/createaccount"; } my $output = '

'.&mt('Authentication failed').'

'. &mt('Username and/or password could not be authenticated.'). '
'. &mt('Please check the username and password.').'

'; ''.&mt('Try again').''; return $output; } sub username_check { my ($username,$domain,$domdesc,$courseid,$lonhost,$contact_email, $contact_name,$sso_logout,$statustocreate) = @_; my (%rulematch,%inst_results,$checkfail,$rowcount,$editable,$output,$msg, %alerts,%curr_rules,%got_rules); &call_rulecheck($username,$domain,\%alerts,\%rulematch, \%inst_results,\%curr_rules,\%got_rules,'username'); if (ref($alerts{'username'}) eq 'HASH') { if (ref($alerts{'username'}{$domain}) eq 'HASH') { if ($alerts{'username'}{$domain}{$username}) { if (ref($curr_rules{$domain}) eq 'HASH') { $output = &Apache::loncommon::instrule_disallow_msg('username',$domdesc,1, 'selfcreate'). &Apache::loncommon::user_rule_formats($domain,$domdesc, $curr_rules{$domain}{'username'},'username'); } $checkfail = 'username'; } } } if (!$checkfail) { if (ref($statustocreate) eq 'ARRAY') { $checkfail = 'inststatus'; if (ref($inst_results{$username.':'.$domain}{inststatus}) eq 'ARRAY') { foreach my $inststatus (@{$inst_results{$username.':'.$domain}{inststatus}}) { if (grep(/^\Q$inststatus\E$/,@{$statustocreate})) { undef($checkfail); last; } } } elsif (grep(/^default$/,@{$statustocreate})) { undef($checkfail); } } } if (!$checkfail) { $output = '
'; (my $datatable,$rowcount,$editable) = &Apache::loncreateuser::personal_data_display($username,$domain,1,'selfcreate', $inst_results{$username.':'.$domain}); if ($rowcount > 0) { $output .= $datatable; } $output .= '

'."\n". ''."\n". ''; my $now = time; my %info = ('ip' => $ENV{'REMOTE_ADDR'}, 'time' => $now, 'domain' => $domain, 'username' => $username); my $authtoken = &Apache::lonnet::tmpput(\%info,$lonhost,'createaccount'); if ($authtoken !~ /^error/ && $authtoken ne 'no_such_host') { $output .= ''; } else { $output = &mt('An error occurred when storing a token').'
'. &mt('You will not be able to proceed to the next stage of account creation'). &linkto_email_help($contact_email,$domdesc); $checkfail = 'authtoken'; } } if ($checkfail) { $msg = '

'.&mt('Account creation unavailable').'

'; if ($checkfail eq 'username') { $msg .= ''. &mt('A LON-CAPA account may not be created with the username you use.'). '

'.$output; } elsif ($checkfail eq 'authtoken') { $msg .= ''.&mt('Error creating token.').''. '
'.$output; } elsif ($checkfail eq 'inststatus') { $msg .= ''. &mt('You are not permitted to create a LON-CAPA account.'). '

'.$output; } $msg .= &mt('Please contact the [_1] ([_2]) for assistance.', $contact_name,$contact_email).'

'. $sso_logout; &Apache::lonnet::logthis("ERROR: failure type of '$checkfail' when performing username check to create account for authenticated user: $username, in domain $domain"); } else { if ($courseid ne '') { $output .= ''; } $output .= '
'; if ($rowcount) { if ($editable) { if ($courseid ne '') { $msg = '

'.&mt('User information').'

'; } $msg .= &mt('To create one, use the table below to provide information about yourself, then click the [_1]Create LON-CAPA account[_2] button.','','').'
'; } else { if ($courseid ne '') { $msg = '

'.&mt('Review user information').'

'; } $msg .= &mt('A user account will be created with information displayed in the table below, when you click the [_1]Create LON-CAPA account[_2] button.','','').'
'; } } else { if ($courseid ne '') { $msg = '

'.&mt('Confirmation').'

'; } $msg .= &mt('Confirm that you wish to create an account.'); } $msg .= $output; } return $msg; } sub username_activation { my ($r,$username,$domain,$domdesc,$lonhost,$courseid) = @_; my $output; my $error = ''.&mt('Error:').' '; my $end = '

'; my $rtnlink = ''. &mt('Return to previous page').''. &Apache::loncommon::end_page(); my %domdefaults = &Apache::lonnet::get_domain_defaults($domain); my %data = &Apache::lonnet::tmpget($env{'form.authtoken'}); my $now = time; my $earlyout; my $timeout = 300; if (keys(%data) == 0) { $output = &mt('Sorry, your authentication has expired.'); $earlyout = 'fail'; } if (($data{'time'} !~ /^\d+$/) || ($data{'domain'} ne $domain) || ($data{'username'} ne $username)) { $earlyout = 'fail'; $output = &mt('The credentials you provided could not be verified.'); } elsif ($now - $data{'time'} > $timeout) { $earlyout = 'fail'; $output = &mt('Sorry, your authentication has expired.'); } if ($earlyout ne '') { $output .= '
'.&mt('Please [_1]start again[_2].','',''); return($earlyout,$output); } if ((($domdefaults{'auth_def'} =~/^krb(4|5)$/) && ($domdefaults{'auth_arg_def'} ne '')) || ($domdefaults{'auth_def'} eq 'localauth')) { if ($env{'form.courseid'} ne '') { my ($result,$userchkmsg) = &check_id($username,$domain,$domdesc); if ($result eq 'fail') { $output = $error.&mt('Invalid ID format').$end. $userchkmsg.$rtnlink; return ('fail',$output); } } # Call modifyuser my (%rulematch,%inst_results,%curr_rules,%got_rules,%alerts,%info); &call_rulecheck($username,$domain,\%alerts,\%rulematch, \%inst_results,\%curr_rules,\%got_rules); my @userinfo = ('firstname','middlename','lastname','generation', 'permanentemail','id'); my %canmodify = &Apache::loncreateuser::selfcreate_canmodify('selfcreate',$domain, \@userinfo,\%inst_results); foreach my $item (@userinfo) { if ($canmodify{$item}) { $info{$item} = $env{'form.c'.$item}; } else { $info{$item} = $inst_results{$username.':'.$domain}{$item}; } } if (ref($inst_results{$username.':'.$domain}{'inststatus'}) eq 'ARRAY') { my @inststatuses = @{$inst_results{$username.':'.$domain}{'inststatus'}}; $info{'inststatus'} = join(':',map { &escape($_); } @inststatuses); } my $result = &Apache::lonnet::modifyuser($domain,$username,$env{'form.cid'}, $domdefaults{'auth_def'}, $domdefaults{'auth_arg_def'},$info{'firstname'}, $info{'middlename'},$info{'lastname'}, $info{'generation'},undef,undef, $info{'permanentemail'},$info{'inststatus'}); if ($result eq 'ok') { my $delete = &Apache::lonnet::tmpdel($env{'form.authtoken'}); $output = &mt('A LON-CAPA account has been created for username: [_1] in domain: [_2].',$username,$domain); my %form = &start_session($r,$username,$domain,$lonhost,$courseid); my $nostart = 1; return ('ok',$output,$nostart); } else { $output = &mt('Account creation failed for username: [_1] in domain: [_2].',$username,$domain).'
'.&mt('Error: [_1]',$result).''; return ('fail',$output); } } else { $output = &mt('User account creation is not available for the current default authentication type.')."\n"; return('fail',$output); } } sub check_id { my ($username,$domain,$domdesc) = @_; # Check ID format my (%alerts,%rulematch,%inst_results,%curr_rules,%checkhash); my %checks = ('id' => 1); %{$checkhash{$username.':'.$domain}} = ( 'newuser' => 1, 'id' => $env{'form.cid'}, ); &Apache::loncommon::user_rule_check(\%checkhash,\%checks,\%alerts, \%rulematch,\%inst_results,\%curr_rules); if (ref($alerts{'id'}) eq 'HASH') { if (ref($alerts{'id'}{$domain}) eq 'HASH') { if ($alerts{'id'}{$domain}{$env{'form.cid'}}) { my $userchkmsg; if (ref($curr_rules{$domain}) eq 'HASH') { $userchkmsg = &Apache::loncommon::instrule_disallow_msg('id', $domdesc,1). &Apache::loncommon::user_rule_formats($domain, $domdesc,$curr_rules{$domain}{'id'},'id'); } return ('fail',$userchkmsg); } } } return; } sub invalid_state { my ($error,$domdesc,$contact_name,$contact_email,$msgtext,$useremail) = @_; my $msg = '

'.&mt('Account creation unavailable').'

'; if ($error eq 'baduseremail') { $msg .= &mt('The e-mail address you provided does not appear to be a valid address.'); } elsif ($error eq 'existinguser') { my $uname = &HTML::Entities::encode($useremail); $msg .= &mt('The e-mail address you provided is already in use as a username in LON-CAPA at this institution.').'

'.&mt('You can either:').''; } elsif ($error eq 'userrules') { $msg .= &mt('Username rules at this institution do not allow the e-mail address you provided to be used as a username.'); } elsif ($error eq 'userformat') { $msg .= &mt('The e-mail address you provided may not be used as a username at this LON-CAPA institution.'); } elsif ($error eq 'captcha') { $msg .= &mt('Validation of the code you entered failed.'); } elsif ($error eq 'noemails') { $msg .= &mt('Creation of a new user account using an e-mail address as username is not permitted at this LON-CAPA institution.'); } $msg .= ''; if ($msgtext) { $msg .= '
'.$msgtext; } $msg .= &linkto_email_help($contact_email,$domdesc,$error); return $msg; } sub linkto_email_help { my ($contact_email,$domdesc,$error) = @_; my $msg; my $href = '/adm/helpdesk'; if ($contact_email ne '') { my $escuri = &HTML::Entities::encode('/adm/createaccount','&<>"'); $href .= '?origurl='.$escuri; if ($error eq 'existinguser') { my $escemail = &HTML::Entities::encode($env{'form.useremail'}); $href .= '&useremail='.$escemail.'&useraccount='.$escemail; } $msg .= '
'.&mt('You may wish to contact the [_1]LON-CAPA helpdesk[_2] for [_3].','','',$domdesc).'
'; } else { $msg .= '
'.&mt('You may wish to send an e-mail to the server administrator: [_1] for [_2].',$Apache::lonnet::perlvar{'AdminEmail'},$domdesc).'
'; } return $msg; } sub create_recaptcha { my ($pubkey) = @_; my $captcha = Captcha::reCAPTCHA->new; # generate PUBLICKEY from https://www.google.com/recaptcha return $captcha->get_options_setter({theme => 'white'})."\n". $captcha->get_html($pubkey); } sub getkeys { my ($lkey,$ukey) = @_; my $lextkey=hex($lkey); if ($lextkey>2147483647) { $lextkey-=4294967296; } my $uextkey=hex($ukey); if ($uextkey>2147483647) { $uextkey-=4294967296; } return ($lextkey,$uextkey); } sub serverform { my ($logtoken,$lonhost,$mailtoken,$courseid,$context) = @_; my $phase = 'username_validation'; my $catalog_elements; if ($context eq 'selfenroll') { $phase = 'selfenroll_login'; } if ($courseid ne '') { $catalog_elements = &Apache::lonhtmlcommon::echo_form_input(['courseid','phase']); } my $output = < $catalog_elements ENDSERVERFORM return $output; } sub process_credentials { my ($logtoken,$lonhost) = @_; my $tmpinfo=Apache::lonnet::reply('tmpget:'.$logtoken,$lonhost); my ($retrieved,$output,$upass); if (($tmpinfo=~/^error/) || ($tmpinfo eq 'con_lost')) { $output = &mt('Information needed to verify your login information is missing, inaccessible or expired.') .'
'.&mt('You may need to reload the previous page to obtain a new token.'); return ($retrieved,$output,$upass); } else { my $reply = &Apache::lonnet::reply('tmpdel:'.$logtoken,$lonhost); if ($reply eq 'ok') { $retrieved = 'ok'; } else { $output = &mt('Session could not be opened.'); } } my ($key,$caller)=split(/&/,$tmpinfo); if ($caller eq 'createaccount') { $upass = &Apache::lonpreferences::des_decrypt($key,$env{'form.upass'}); } else { $output = &mt('Unable to retrieve your log-in information - unexpected context'); } return ($retrieved,$output,$upass); } sub guest_format_check { my ($useremail,$domain,$cancreate,$settings) = @_; my ($login,$format_match,$format_msg,@user_rules); if (ref($settings) eq 'HASH') { if (ref($settings->{'email_rule'}) eq 'ARRAY') { push(@user_rules,@{$settings->{'email_rule'}}); } } if (@user_rules > 0) { my %rule_check = &Apache::lonnet::inst_rulecheck($domain,$useremail,undef, 'selfcreate',\@user_rules); if (keys(%rule_check) > 0) { foreach my $item (keys(%rule_check)) { if ($rule_check{$item}) { $format_match = 1; last; } } } } if ($format_match) { ($login) = ($useremail =~ /^([^\@]+)\@/); $format_msg = '
'.&mt("Your e-mail address uses the same internet domain as your institution's LON-CAPA service.").'
'.&mt('Creation of a LON-CAPA account with this type of e-mail address as username is not permitted.').'
'; if (ref($cancreate) eq 'ARRAY') { if (grep(/^login$/,@{$cancreate})) { $format_msg .= &mt('You should request creation of a LON-CAPA account for a log-in ID of "[_1]" at your institution instead.',$login).'
'; } } } return $format_msg; } sub sso_logout_frag { my ($r,$domain) = @_; my $endsessionmsg; if (defined($r->dir_config('lonSSOUserLogoutMessageFile_'.$domain))) { my $msgfile = $r->dir_config('lonSSOUserLogoutMessageFile_'.$domain); if (-e $msgfile) { open(my $fh,"<$msgfile"); $endsessionmsg = join('',<$fh>); close($fh); } } elsif (defined($r->dir_config('lonSSOUserLogoutMessageFile'))) { my $msgfile = $r->dir_config('lonSSOUserLogoutMessageFile'); if (-e $msgfile) { open(my $fh,"<$msgfile"); $endsessionmsg = join('',<$fh>); close($fh); } } return $endsessionmsg; } sub catreturn_js { return <<"ENDSCRIPT"; ENDSCRIPT } 1; 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.