--- loncom/interface/createaccount.pm 2008/07/10 00:18:05 1.15 +++ loncom/interface/createaccount.pm 2010/11/29 14:57:20 1.37.2.2 @@ -3,7 +3,7 @@ # institutional log-in ID (institutional authentication required - localauth # or kerberos) or an e-mail address. # -# $Id: createaccount.pm,v 1.15 2008/07/10 00:18:05 raeburn Exp $ +# $Id: createaccount.pm,v 1.37.2.2 2010/11/29 14:57:20 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -39,7 +39,7 @@ use Apache::lonhtmlcommon; use Apache::lonlocal; use Apache::lonauth; use Apache::resetpw; -use Authen::Captcha; +use Captcha::reCAPTCHA; use DynaLoader; # for Crypt::DES version use Crypt::DES; use LONCAPA qw(:DEFAULT :match); @@ -52,16 +52,27 @@ sub handler { 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'); + &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 { + } 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'); @@ -74,85 +85,92 @@ sub handler { my $include = $r->dir_config('lonIncludes'); my $start_page; - &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['token','courseid']); - &Apache::lonacc::get_posted_cgi($r); - &Apache::lonlocal::get_language_handle($r); - my $handle = &Apache::lonnet::check_for_valid_session($r); - if ($handle ne '') { + 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]logout[_4].','','','',''). + '

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

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

'.$end_page); - return OK; + return OK; } - $start_page = - &Apache::loncommon::start_page('Create a user account in LON-CAPA','', - {'no_inline_link' => 1,}); - if ($env{'form.phase'} eq 'username_activation') { + + 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 @cancreate; - my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$domain); - if (ref($domconfig{'usercreation'}) eq 'HASH') { - if (ref($domconfig{'usercreation'}{'cancreate'}) eq 'HASH') { - if (ref($domconfig{'usercreation'}{'cancreate'}{'selfcreate'}) eq 'ARRAY') { - @cancreate = @{$domconfig{'usercreation'}{'cancreate'}{'selfcreate'}}; - } elsif (($domconfig{'usercreation'}{'cancreate'}{'selfcreate'} ne 'none') && - ($domconfig{'usercreation'}{'cancreate'}{'selfcreate'} ne '')) { - @cancreate = ($domconfig{'usercreation'}{'cancreate'}{'selfcreate'}); - } + + 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,}); - if (@cancreate == 0) { - &print_header($r,$start_page); + 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 in the domain: [_1] ([_2]).',$domain,$domdesc).'

'; + &mt('Creation of a new user account using an e-mail address or an institutional log-in ID as username is not permitted for the GCI WebCenter.').'

'; $r->print($output); - $r->print(&Apache::loncommon::end_page()); + &print_footer($r); return OK; } - my $courseid; - if (defined($env{'form.courseid'})) { - $courseid = &validate_course($env{'form.courseid'}); - } - if ($sso_username ne '') { - &print_header($r,$start_page); - my ($output,$msg); - if (grep(/^sso$/,@cancreate)) { + &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 in this domain.").'

'; - ($output, my $checkfail) = &username_check($sso_username,$domain, - $domdesc,$courseid, - $lonhost,$contact_email); - 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.').''; - } elsif ($checkfail eq 'authtoken') { - $msg .= ''.&mt('Error creating token.').''; - } - $msg .= '

'. - &mt('Please contact the [_1] ([_2]) for assistance.',$contact_name,$contact_email); - } else { - $msg .= &mt('To create one, use the table below to provide information about yourself (if appropriate), then click the "Create LON-CAPA account" button.'); - } + &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 in this domain, and you are not permitted to create one.").'

'.&mt('Please contact the [_1] ([_2]) for assistance.',$contact_name,$contact_email); + $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.'
'.$output); - $r->print(&Apache::loncommon::end_page()); + $r->print($msg); + &print_footer($r); return OK; } @@ -167,13 +185,13 @@ sub handler { return OK; } else { $r->print($output); - $r->print(&Apache::loncommon::end_page()); + &print_footer($r); return OK; } } else { - &print_header($r,$start_page); + &print_header($r,$start_page,$courseid); $r->print($output); - $r->print(&Apache::loncommon::end_page()); + &print_footer($r); return OK; } } @@ -187,44 +205,55 @@ sub handler { return OK; } } - &print_header($r,$start_page); + &print_header($r,$start_page,$courseid); $r->print($output); - $r->print(&Apache::loncommon::end_page()); + &print_footer($r); return OK; - } - - &print_header($r,$start_page); - if ($env{'form.create_with_email'}) { + } 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, + $contact_name,$contact_email,$cancreate, $lonhost,$domconfig{'usercreation'}, $courseid); - } elsif ($env{'form.phase'} eq 'username_validation') { - $output = &username_validation($env{'form.uname'},$domain,$domdesc, - $contact_name,$contact_email,$courseid, - $lonhost); } elsif (!$token) { + &print_header($r,$start_page,$courseid); my $now=time; - if (grep(/^login$/,@cancreate)) { + if (grep(/^login$/,@{$cancreate})) { my $jsh=Apache::File->new($include."/londes.js"); $r->print(<$jsh>); $r->print(&javascript_setforms($now)); } - if (grep(/^email$/,@cancreate)) { + if (grep(/^email$/,@{$cancreate})) { $r->print(&javascript_validmail()); } - $output = &print_username_form($domain,$domdesc,\@cancreate,$now,$lonhost, - $courseid); + $output = &print_username_form($domain,$domdesc,$cancreate,$now,$lonhost, + $courseid); } $r->print($output); - $r->print(&Apache::loncommon::end_page()); + &print_footer($r); return OK; } sub print_header { - my ($r,$start_page) = @_; + 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"}); @@ -232,6 +261,42 @@ sub print_header { 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)$/); @@ -246,9 +311,10 @@ sub validate_course { sub javascript_setforms { my ($now) = @_; my $js = < + ENDSCRIPT @@ -308,6 +374,13 @@ function validate_email() { if (validmail(field) == false) { alert("$lt{'email'}: "+field.value+" $lt{'notv'}."); return false; + } else { + var emailaddr = field.value; + var lcemail = emailaddr.toLowerCase(); + if (emailaddr != lcemail) { + field.value = lcemail; + alert("WebCenter usernames are all lower case.\\nAccordingly your username will be "+lcemail+" once activated."); + } } return true; } @@ -321,82 +394,118 @@ sub print_username_form { my %lt = &Apache::lonlocal::texthash( unam => 'username', udom => 'domain', - uemail => 'Email address in LON-CAPA', + uemail => 'E-mail address in LON-CAPA', proc => 'Proceed'); 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 = '

'.&mt('Create account with a username provided by your institution').'

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

'.&mt('Type in your log-in ID and password to find out.').'

'; - my ($lkey,$ukey) = &Apache::lonpreferences::des_keys(); - my ($lextkey,$uextkey) = &getkeys($lkey,$ukey); - my $logtoken=Apache::lonnet::reply('tmpput:'.$ukey.$lkey.'&createaccount', - $lonhost); - $output .= &serverform($logtoken,$lonhost,undef,$courseid); - my $unameform = ''; - my $upassform = ''; + $output = '

'.&mt('Create account with a username provided by this institution').'

'; my $submit_text = &mt('Create LON-CAPA account'); - $output .= '
'."\n". - &Apache::lonhtmlcommon::start_pick_box()."\n". - &Apache::lonhtmlcommon::row_title(&mt('Log-in ID'), - '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."\n".'

'."\n". - ''."\n". - &Apache::lonhtmlcommon::row_closure(1)."\n". - &Apache::lonhtmlcommon::end_pick_box().'

'."\n". - ''."\n". - ''."\n". - '
'; + $output .= &mt('If you already have a log-in ID at this institution,[_1] you may be able to use it for LON-CAPA.','
').'

'.&mt('Type in your log-in ID and password to find out.').'

'; + $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').'

'; - if (grep(/^login$/,@{$cancreate})) { - $output .= &mt('Provide your e-mail address to request a LON-CAPA account,[_1] if you do not have a log-in ID at your institution.','
').'

'; + my $captchaform = &create_recaptcha(); + if ($captchaform) { + my $submit_text = &mt('Request LON-CAPA account'); + my $emailform = ''; + if (grep(/^login$/,@{$cancreate})) { + $output .= &mt('Provide your e-mail address to request a LON-CAPA 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 { - $output .= '
'; - } - my $emailform = ''; - my $captchaform = &create_captcha(); - my $submit_text = &mt('Request LON-CAPA account'); - $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".'

'; - if ($courseid ne '') { - $output .= ''."\n"; + 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 .= ''. - &Apache::lonhtmlcommon::row_closure(1). - &Apache::lonhtmlcommon::end_pick_box().'

'. - '
'; + $output .= ''; } } if ($output eq '') { - $output = &mt('Creation of a new user account using an e-mail address or an institutional log-in ID as your username is not permitted in the domain: [_1] ([_2])',$domain,$domdesc); + $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', + $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; + $output .= &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) = @_; - my $useremail = $env{'form.useremail'}; + $useremail = lc($env{'form.useremail'}); my $output; if (ref($cancreate) eq 'ARRAY') { if (!grep(/^email$/,@{$cancreate})) { @@ -414,36 +523,27 @@ sub process_email_request { $contact_name,$contact_email); return $output; } else { - my $code = $env{'form.code'}; - my $md5sum = $env{'form.crypt'}; - my %captcha_params = &captcha_settings(); - my $captcha = Authen::Captcha->new( - output_folder => $captcha_params{'output_dir'}, - data_folder => $captcha_params{'db_dir'}, - ); - my $captcha_chk = $captcha->check_code($code,$md5sum); - my %captcha_hash = ( - 0 => 'Code not checked (file error)', - -1 => 'Failed: code expired', - -2 => 'Failed: invalid code (not in database)', - -3 => 'Failed: invalid code (code does not match crypt)', - ); - if ($captcha_chk != 1) { + my $captcha = Captcha::reCAPTCHA->new; + my $captcha_result = + $captcha->check_answer( + 'PRIVATEKEY', + $ENV{'REMOTE_ADDR'}, + $env{'form.recaptcha_challenge_field'}, + $env{'form.recaptcha_response_field'}, + ); + if (!$captcha_result->{is_valid}) { $output = &invalid_state('captcha',$domdesc,$contact_name, - $contact_email,$captcha_hash{$captcha_chk}); + $contact_email); + return $output; } - my (%rulematch,%inst_results,%curr_rules,%got_rules,%alerts); my $uhome=&Apache::lonnet::homeserver($useremail,$domain); if ($uhome eq 'no_host') { - my $checkhash; - my $checks = { 'username' => 1 }; - $checkhash->{$useremail.':'.$domain} = { 'newuser' => 1, }; - &Apache::loncommon::user_rule_check($checkhash,$checks, - \%alerts,\%rulematch,\%inst_results,\%curr_rules, - \%got_rules); - if (ref($alerts{'useremail'}) eq 'HASH') { - if (ref($alerts{'useremail'}{$domain}) eq 'HASH') { + 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); @@ -468,6 +568,20 @@ sub process_email_request { 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').'

'. @@ -482,10 +596,10 @@ sub send_token { my $token = &Apache::lonnet::tmpput(\%info,$server); if ($token !~ /^error/ && $token ne 'no_such_host') { my $esc_token = &escape($token); - my $mailmsg = &mt('A request was submitted on [_1] for creation of a LON-CAPA account in the [_2] domain.',localtime(time),$domdesc).' '. - &mt('To complete this process please open a web browser and enter the following' - .' URL in the address/location box: [_1]' - ,&Apache::lonnet::absolute_url().'/adm/createaccount?token='.$esc_token); + my $showtime = localtime(time); + my $mailmsg = &mt('A request was submitted on [_1] for creation of a GCI WebCenter account.',$showtime).' '. + &mt('To complete this process please open a web browser and enter the following URL in the address/location box: [_1]', + &Apache::lonnet::absolute_url().'/adm/createaccount?token='.$esc_token); my $result = &Apache::resetpw::send_mail($domdesc,$email,$mailmsg,$contact_name, $contact_email); if ($result eq 'ok') { @@ -524,8 +638,8 @@ sub process_mailtoken { $data{'username'},$domdesc); if ($result eq 'ok') { $msg = $output; - my $shownow = localtime($now); - my $mailmsg = &mt('A LON-CAPA account in the [_1] domain 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 $shownow = &Apache::lonlocal::locallocaltime($now); + my $mailmsg = &mt('A GCI WebCenter account has been created [_1] from IP address: [_2]. If you did not perform this action or authorize it, please contact the [_3] ([_4]).',$shownow,$ENV{'REMOTE_ADDR'},$contact_name,$contact_email)."\n"; my $mailresult = &Apache::resetpw::send_mail($domdesc,$data{'email'}, $mailmsg,$contact_name, $contact_email); @@ -573,13 +687,15 @@ sub start_session { $courseid = &validate_course($courseid); if ($courseid ne '') { $form{'courseid'} = $courseid; - $firsturl = '/adm/selfenroll?cid='.$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); - my $delete = &Apache::lonnet::tmpdel($token); + if ($token ne '') { + my $delete = &Apache::lonnet::tmpdel($token); + } $r->internal_redirect('/adm/switchserver'); } else { &Apache::lonauth::success($r,$form{'uname'},$form{'udom'}, @@ -603,85 +719,97 @@ sub print_dataentry_form { my ($lextkey,$uextkey) = &getkeys($lkey,$ukey); my $logtoken=Apache::lonnet::reply('tmpput:'.$ukey.$lkey.'&createaccount', $lonhost); - my @userinfo = ('firstname','middlename','lastname','generation','id', - 'permanentemail'); - my %lt=&Apache::lonlocal::texthash( - 'pd' => "Personal Data", - 'firstname' => "First Name", - 'middlename' => "Middle Name", - 'lastname' => "Last Name", - 'generation' => "Generation", - 'permanentemail' => "Permanent e-mail address", - 'id' => "ID/Student Number", - 'lg' => "Login Data" - ); - my %textboxsize = ( - firstname => '15', - middlename => '15', - lastname => '15', - generation => '5', - id => '15', - ); - my $genhelp=&Apache::loncommon::help_open_topic('Generation'); - $output .= '

'.$lt{'pd'}.'

'. - '
'. - &Apache::lonhtmlcommon::start_pick_box(); - foreach my $item (@userinfo) { - my $rowtitle = $lt{$item}; - if ($item eq 'generation') { - $rowtitle = $genhelp.$rowtitle; - } - $output .= &Apache::lonhtmlcommon::row_title($rowtitle,undef,'LC_oddrow_value')."\n"; - if ($item eq 'permanentemail') { - $output .= $username; - } else { - $output .= ''; - } - $output .= &Apache::lonhtmlcommon::row_closure(1); + my $formtag = ''; + my ($datatable,$rowcount) = + &Apache::loncreateuser::personal_data_display($username,$domain, + 'email','selfcreate'); + if ($rowcount) { + $output .= '
'.$formtag.$datatable; + } else { + $output .= $formtag; } - $output .= &Apache::lonhtmlcommon::end_pick_box(); $output .= <<"ENDSERVERFORM"; + -
+ ENDSERVERFORM + if ($rowcount) { + $output .= '
'. + '
'; + } my $upassone = ''; my $upasstwo = ''; my $submit_text = &mt('Create LON-CAPA account'); - $output .= '

'.$lt{'lg'}.'

'."\n". - '
'."\n". + $output .= '

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

'."\n". + ''."\n". &Apache::lonhtmlcommon::start_pick_box()."\n". &Apache::lonhtmlcommon::row_title(&mt('Username'), - 'LC_pick_box_title')."\n". + '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')."\n". + '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')."\n". - $upasstwo."\n". + '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". - ''; + ''."\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'}}; + } 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'}, @@ -693,7 +821,7 @@ sub create_account { &mt('Return to previous page').'
'. &Apache::loncommon::end_page(); if ($retrieved eq 'ok') { - if ($env{'form.cid'} ne '') { + if ($env{'form.courseid'} ne '') { my ($result,$userchkmsg) = &check_id($username,$domain,$domdesc); if ($result eq 'fail') { $output = $error.&mt('Invalid ID format').$end. @@ -718,21 +846,29 @@ sub create_account { } sub username_validation { - my ($username,$domain,$domdesc,$contact_name,$contact_email,$courseid,$lonhost) = @_; + 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); - if ($uhome ne 'no_host') { - $output = &invalid_state('existinguser',$domdesc, - $contact_name,$contact_email); - return $output; - } ($retrieved,$output,$upass) = &process_credentials($env{'form.logtoken'}, $env{'form.serverid'}); - if ($retrieved eq 'ok') { + 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); @@ -744,71 +880,139 @@ sub username_validation { $authok = 'non_authorized'; } if ($authok eq 'authorized') { - ($output,undef) = &username_check($username,$domain,$domdesc, - $courseid,$lonhost,$contact_email); + $output = &username_check($username,$domain,$domdesc,$courseid,$lonhost, + $contact_email,$contact_name,undef, + $statustocreate); } else { - $output = '
' - .&mt('Username and/or password could not be authenticated.') - .'
' - .&mt('Please check the username and password.'); + $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) = @_; - my (%rulematch,%inst_results,$newuser,%alerts,%curr_rules,%got_rules); - $newuser = 1; - my $checkhash; - my $checks = { 'username' => 1 }; - $checkhash->{$username.':'.$domain} = { 'newuser' => $newuser }; - &Apache::loncommon::user_rule_check($checkhash,$checks,\%alerts,\%rulematch, - \%inst_results,\%curr_rules,\%got_rules); + 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}) { - my ($userchkmsg,$checkfail); if (ref($curr_rules{$domain}) eq 'HASH') { - $userchkmsg = - &Apache::loncommon::instrule_disallow_msg('username',$domdesc,1). + $output = + &Apache::loncommon::instrule_disallow_msg('username',$domdesc,1, + 'selfcreate'). &Apache::loncommon::user_rule_formats($domain,$domdesc, $curr_rules{$domain}{'username'},'username'); - if ($userchkmsg) { - $checkfail = '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; } } - return ($userchkmsg,$checkfail); + } elsif (grep(/^default$/,@{$statustocreate})) { + undef($checkfail); } } } - my $submit_text = &mt('Create LON-CAPA account'); - my $output = '
'. - &Apache::loncreateuser::personal_data_display($username,$domain,1, - undef,$inst_results{$username.':'.$domain}). - '

'."\n". - ''."\n". - ''; - my $now = time; - my %info = ('ip' => $ENV{'REMOTE_ADDR'}, - 'time' => $now, - 'domain' => $domain, - 'username' => $username); - my $authtoken = &Apache::lonnet::tmpput(\%info,$lonhost); - if ($authtoken !~ /^error/ && $authtoken ne 'no_such_host') { - $output .= ''; + 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); + 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 { - $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); - return($output,'authtoken'); - } - if ($courseid ne '') { - $output .= ''; + 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; } - $output .= ''; - return ($output,''); + return $msg; } sub username_activation { @@ -844,7 +1048,7 @@ sub username_activation { if ((($domdefaults{'auth_def'} =~/^krb(4|5)$/) && ($domdefaults{'auth_arg_def'} ne '')) || ($domdefaults{'auth_def'} eq 'localauth')) { - if ($env{'form.cid'} ne '') { + if ($env{'form.courseid'} ne '') { my ($result,$userchkmsg) = &check_id($username,$domain,$domdesc); if ($result eq 'fail') { $output = $error.&mt('Invalid ID format').$end. @@ -853,13 +1057,32 @@ sub username_activation { } } # 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'},$env{'form.cfirstname'}, - $env{'form.cmiddlename'},$env{'form.clastname'}, - $env{'form.cgeneration'},undef,undef, - $env{'form.cpermanentemail'}); + $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); @@ -911,15 +1134,15 @@ sub invalid_state { if ($error eq 'baduseremail') { $msg = &mt('The e-mail address you provided does not appear to be a valid address.'); } elsif ($error eq 'existinguser') { - $msg = &mt('The e-mail address you provided is already in use as a username in this LON-CAPA domain.'); + $msg = &mt('The e-mail address you provided is already in use as a username in LON-CAPA at this institution.'); } elsif ($error eq 'userrules') { - $msg = &mt('Username rules for this LON-CAPA domain do not allow the e-mail address you provided to be used as a username.'); + $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 in this LON-CAPA domain.'); + $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 your entered failed.'); } elsif ($error eq 'noemails') { - $msg = &mt('Creation of a new user account using an e-mail address as username is not permitted in this LON-CAPA domain.'); + $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) { @@ -934,36 +1157,18 @@ sub linkto_email_help { my $msg; if ($contact_email ne '') { my $escuri = &HTML::Entities::encode('/adm/createaccount','&<>"'); - $msg .= '
'.&mt('You may wish to contact the [_1]LON-CAPA helpdesk[_2] for the [_3] domain.','','',$domdesc); + $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 the [_2] domain.',$Apache::lonnet::perlvar{'AdminEmail'},$domdesc); + $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_captcha { - my ($output_dir,$db_dir) = @_; - my %captcha_params = &captcha_settings(); - my $captcha = Authen::Captcha->new( - output_folder => $captcha_params{'output_dir'}, - data_folder => $captcha_params{'db_dir'}, - ); - my $md5sum = $captcha->generate_code($captcha_params{'numchars'}); - my $output = ''."\n". - &mt('Type in the letters/numbers shown below').' '. - '
'. - ''; - return $output; -} - -sub captcha_settings { - my %captcha_params = ( - output_dir => $Apache::lonnet::perlvar{'lonCaptchaDir'}, - www_output_dir => "/captchaspool", - db_dir => $Apache::lonnet::perlvar{'lonCaptchaDb'}, - numchars => '5', - ); - return %captcha_params; +sub create_recaptcha { + my $captcha = Captcha::reCAPTCHA->new; + return $captcha->get_options_setter({theme => 'white'})."\n". + $captcha->get_html('PUBLICKEY'); # generate public key for IP + # from http://recaptcha.net/ } sub getkeys { @@ -977,16 +1182,26 @@ sub getkeys { } sub serverform { - my ($logtoken,$lonhost,$mailtoken,$courseid) = @_; - my $output .= < + 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; @@ -1050,4 +1265,82 @@ sub guest_format_check { 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.