--- loncom/interface/lonuserutils.pm 2010/08/10 04:00:16 1.109.2.4 +++ loncom/interface/lonuserutils.pm 2010/09/20 00:26:44 1.109.2.5 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Utility functions for managing LON-CAPA user accounts # -# $Id: lonuserutils.pm,v 1.109.2.4 2010/08/10 04:00:16 raeburn Exp $ +# $Id: lonuserutils.pm,v 1.109.2.5 2010/09/20 00:26:44 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -296,7 +296,8 @@ sub hidden_input { } sub print_upload_manager_header { - my ($r,$datatoken,$distotal,$krbdefdom,$context,$permission,$crstype)=@_; + my ($r,$datatoken,$distotal,$krbdefdom,$context,$permission,$crstype,$formname, + $can_assign)=@_; my $javascript; # if (! exists($env{'form.upfile_associate'})) { @@ -310,9 +311,9 @@ sub print_upload_manager_header { } } if ($env{'form.upfile_associate'} eq 'reverse') { - $javascript=&upload_manager_javascript_reverse_associate(); + $javascript=&upload_manager_javascript_reverse_associate($can_assign); } else { - $javascript=&upload_manager_javascript_forward_associate(); + $javascript=&upload_manager_javascript_forward_associate($can_assign); } # # Deal with restored settings @@ -326,9 +327,32 @@ sub print_upload_manager_header { $password_choice = 'int'; } # - my $groupslist; + my ($sectionjs,$groupslist); if ($context eq 'course') { $groupslist = &get_groupslist(); + if ($env{'form.caller'} eq 'requestcrs') { + $sectionjs = <<"ENDJS"; + +function toggleSectionsDefault() { + var usingsecs; + if (document.$formname.usesection.length > 1) { + for (var i=0; i\n"); $r->print('

'. &mt('Identify fields in uploaded list')."

\n"); - $r->print(&mt('Enter as many fields as you can.
The system will inform you and bring you back to this page,
if the data selected are insufficient to add users.')."
\n"); + $r->print(&mt('Enter as many fields as you can.').'
'. + &mt('The system will inform you and bring you back to this page,'). + '
'.&mt('if the data selected are insufficient to add users.')."
\n"); $r->print(&hidden_input('action','upload'). &hidden_input('state','got_file'). &hidden_input('associate',''). &hidden_input('datatoken',$datatoken). &hidden_input('fileupload',$env{'form.fileupload'}). &hidden_input('upfiletype',$env{'form.upfiletype'}). - &hidden_input('upfile_associate',$env{'form.upfile_associate'})); + &hidden_input('upfile_associate',$env{'form.upfile_associate'}). + &hidden_input('caller',$env{'form.caller'})); $r->print('

'); $r->print('
print("

\n". ''); } @@ -388,9 +415,13 @@ sub javascript_validations { if ($context eq 'course') { if ($env{'request.course.sec'} eq '') { $setsection_call = 'setSections(document.'.$param{'formname'}.",'$crstype'".');'; - $setsections_js = - &setsections_javascript($param{'formname'},$groupslist, - $mode,'',$crstype); + if ($env{'form.caller'} eq 'requestcrs') { + $setsections_js = &newsections_javascript($param{'formname'}); + } else { + $setsections_js = + &setsections_javascript($param{'formname'},$groupslist, + $mode,'',$crstype); + } } else { $setsection_call = "'ok'"; } @@ -518,7 +549,9 @@ END END } else { $section_checks = §ion_check_js(); - $optional_checks = (< 1) { + $auth_update = <<"END"; + // If we set the password, make the password form below correspond to + // the new value. + if (nw==9) { + changed_radio('int',document.studentform); + set_auth_radio_buttons('int',document.studentform); +END + } + if ($can_assign->{'krb'}) { + $auth_update .= " vf.krbarg.value='';\n"; + } + if ($can_assign->{'int'}) { + $auth_update .= " vf.intarg.value='';\n"; + } + if ($can_assign->{'loc'}) { + $auth_update .= " vf.locarg.value='';\n"; + } + $auth_update .= " + }\n"; + } + return(< 1) { + $auth_update = <<"END"; + // initial password specified, pick internal authentication + if (tf==8 && nw!=0) { + changed_radio('int',document.studentform); + set_auth_radio_buttons('int',document.studentform); +END + } + if ($can_assign->{'krb'}) { + $auth_update .= " vf.krbarg.value='';\n"; + } + if ($can_assign->{'int'}) { + $auth_update .= " vf.intarg.value='';\n"; + } + if ($can_assign->{'loc'}) { + $auth_update .= " vf.locarg.value='';\n"; + } + $auth_update .= " + }\n"; + } return(<=2) && (tf<=5) && (nw!=0)) { eval('vf.f1.selectedIndex=0;') } - // intial password specified, pick internal authentication - if (tf==8 && nw!=0) { - changed_radio('int',document.studentform); - set_auth_radio_buttons('int',document.studentform); - vf.krbarg.value=''; - vf.intarg.value=''; - vf.locarg.value=''; - } + $auth_update } function clearpwd(vf) { @@ -763,6 +838,9 @@ sub print_upload_manager_footer { $env{'form.ipwd_choice'} ne '') { $param{'curr_authtype'} = 'int'; } + if ($env{'form.caller'} eq 'requestcrs') { + $param{'caller'} = $env{'form.caller'}; + } my $krbform = &Apache::loncommon::authform_kerberos(%param); my $intform = &Apache::loncommon::authform_internal(%param); my $locform = &Apache::loncommon::authform_local(%param); @@ -775,8 +853,11 @@ sub print_upload_manager_footer { $Str .= '

'.&mt('Options').'

' .&Apache::lonhtmlcommon::start_pick_box(); - - $Str .= &Apache::lonhtmlcommon::row_title(&mt('Login Type')); + if ($env{'form.caller'} eq 'requestcrs') { + $Str .= &Apache::lonhtmlcommon::row_title(&mt('Default password')); + } else { + $Str .= &Apache::lonhtmlcommon::row_title(&mt('Login Type')); + } if ($context eq 'domain') { $Str .= '

' .&mt('Change authentication for existing users in domain "[_1]" to these settings?' @@ -790,12 +871,17 @@ sub print_upload_manager_footer { .'

'; } else { $Str .= '

'."\n". - &mt('This will not take effect if the user already exists.'). - &Apache::loncommon::help_open_topic('Auth_Options'). - "

\n"; + &mt('This will not take effect if the user already exists.'); + my ($authnum,%can_assign) = &Apache::loncommon::get_assignable_auth($defdom); + if ($authnum > 1) { + $Str .= &Apache::loncommon::help_open_topic('Auth_Options'); + } + $Str .= "

\n"; } $Str .= &set_login($defdom,$krbform,$intform,$locform); - + if ($env{'form.caller'} eq 'requestcrs') { + $Str .= ''; + } my ($home_server_pick,$numlib) = &Apache::loncommon::home_server_form_item($defdom,'lcserver', 'default','hide'); @@ -811,14 +897,14 @@ sub print_upload_manager_footer { &Apache::lonhtmlcommon::row_closure(); } - $Str .= &Apache::lonhtmlcommon::row_title(&mt('Default domain')) - .&Apache::loncommon::select_dom_form($defdom,'defaultdomain',undef,1) - .&Apache::lonhtmlcommon::row_closure(); - - $Str .= &Apache::lonhtmlcommon::row_title(&mt('Starting and Ending Dates')) - ."

\n".$date_table."

\n" - .&Apache::lonhtmlcommon::row_closure(); - + unless ($env{'form.caller'} eq 'requestcrs') { + $Str .= &Apache::lonhtmlcommon::row_title(&mt('Default domain')) + .&Apache::loncommon::select_dom_form($defdom,'defaultdomain',undef,1) + .&Apache::lonhtmlcommon::row_closure() + .&Apache::lonhtmlcommon::row_title(&mt('Starting and Ending Dates')) + ."

\n".$date_table."

\n" + .&Apache::lonhtmlcommon::row_closure(); + } if ($context eq 'domain') { $Str .= &Apache::lonhtmlcommon::row_title( &mt('Settings for assigning roles')) @@ -838,9 +924,22 @@ sub print_upload_manager_footer { &mt('Default role')) .&mt('Choose the role to assign to users without a value specified in the uploaded file.') } elsif ($context eq 'course') { - $Str .= &Apache::lonhtmlcommon::row_title( + if ($env{'form.caller'} eq 'requestcrs') { + $Str .= &Apache::lonhtmlcommon::row_title(&mt('Default section')). + &mt('Students can be assigned to different sections.').'
'. + &mt('Will you be using sections?').' '. + ''. + ' '.&mt('Yes').''. + '   '; + } else { + $Str .= &Apache::lonhtmlcommon::row_title( &mt('Default role and section')) - .&mt('Choose the role and/or section(s) to assign to users without values specified in the uploaded file.'); + .&mt('Choose the role and/or section(s) to assign to users without values specified in the uploaded file.'); + } } else { $Str .= &Apache::lonhtmlcommon::row_title( &mt('Default role and/or section(s)')) @@ -864,11 +963,22 @@ sub print_upload_manager_footer { } } else { my ($cnum,$cdom) = &get_course_identity(); - my $rowtitle = &mt('section'); + my ($rowtitle,$closure); + if ($env{'form.caller'} eq 'requestcrs') { + $closure = 1; + $rowtitle = &mt('default section name (letters/numbers only)'); + } else { + $rowtitle = &mt('section'); + } my $secbox = §ion_picker($cdom,$cnum,'Any',$rowtitle, - $permission,$context,'upload',$crstype); - $Str .= $secbox - .&Apache::lonhtmlcommon::row_closure(); + $permission,$context,'upload',$crstype, + $env{'form.caller'}). + &Apache::lonhtmlcommon::row_closure($closure); + if ($env{'form.caller'} eq 'requestcrs') { + $Str .= ''; + } else { + $Str .= $secbox; + } my %lt; if ($crstype eq 'Community') { %lt = &Apache::lonlocal::texthash ( @@ -881,15 +991,19 @@ sub print_upload_manager_footer { stus => 'Students selected from this list can be dropped.' ); } - $Str .= &Apache::lonhtmlcommon::row_title(&mt('Full Update')) - .'
' - .$lt{'stus'} - .&Apache::lonhtmlcommon::row_closure(); + unless ($env{'form.caller'} eq 'requestcrs') { + $Str .= &Apache::lonhtmlcommon::row_title(&mt('Full Update')) + .'
' + .$lt{'stus'} + .&Apache::lonhtmlcommon::row_closure(); + } } if ($context eq 'course' || $context eq 'domain') { - $Str .= &forceid_change($context); + unless ($env{'form.caller'} eq 'requestcrs') { + $Str .= &forceid_change($context); + } } $Str .= &Apache::lonhtmlcommon::end_pick_box(); @@ -933,7 +1047,7 @@ sub forceid_change { ############################################################### ############################################################### sub print_upload_manager_form { - my ($r,$context,$permission,$crstype) = @_; + my ($r,$context,$permission,$crstype,$formname) = @_; my $firstLine; my $datatoken; if (!$env{'form.datatoken'}) { @@ -979,13 +1093,15 @@ sub print_upload_manager_form { my ($krbdef,$krbdefdom) = &Apache::loncommon::get_kerberos_defaults($defdom); # + my ($authnum,%can_assign) = &Apache::loncommon::get_assignable_auth($defdom); &print_upload_manager_header($r,$datatoken,$distotal,$krbdefdom,$context, - $permission,$crstype); + $permission,$crstype,$formname,\%can_assign); my $i; my $keyfields; if ($total>=0) { my @field= (['username',&mt('Username'), $env{'form.username_choice'}], + ['ipwd', &mt('Initial Password'),$env{'form.ipwd_choice'}], ['names',&mt('Last Name, First Names'),$env{'form.names_choice'}], ['fname',&mt('First Name'), $env{'form.fname_choice'}], ['mname',&mt('Middle Names/Initials'),$env{'form.mname_choice'}], @@ -993,7 +1109,6 @@ sub print_upload_manager_form { ['gen', &mt('Generation'), $env{'form.gen_choice'}], ['id', &mt('Student/Employee ID'),$env{'form.id_choice'}], ['sec', &mt('Section'), $env{'form.sec_choice'}], - ['ipwd', &mt('Initial Password'),$env{'form.ipwd_choice'}], ['email',&mt('E-mail Address'), $env{'form.email_choice'}], ['role',&mt('Role'), $env{'form.role_choice'}], ['domain',&mt('Domain'), $env{'form.domain_choice'}], @@ -2744,7 +2859,7 @@ END } if ($role eq 'st') { my $numsub = $stusubmissions{$in{'username'}.':'.$in{'domain'}."\0attempts"} + - $stusubmissions{$in{'username'}.':'.$in{'domain'}."\0pilotsubs"}; + $stusubmissions{$in{'username'}.':'.$in{'domain'}."\0surveysubs"}; if (!$numsub) { $in{'submissions'} = 'not attempted'; } elsif ($numsub < $numparts) { @@ -3333,18 +3448,22 @@ ENDJS } sub section_picker { - my ($cdom,$cnum,$role,$rowtitle,$permission,$context,$mode,$crstype) = @_; + my ($cdom,$cnum,$role,$rowtitle,$permission,$context,$mode,$crstype,$caller) = @_; my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum); my $sections_select .= &course_sections(\%sections_count,$role); my $secbox = '

'.&Apache::lonhtmlcommon::start_pick_box()."\n"; - if ($mode eq 'upload') { + if ($mode eq 'upload' && $caller ne 'requestcrs') { my ($options,$cb_script,$coursepick) = &default_role_selector($context,1,$crstype); $secbox .= &Apache::lonhtmlcommon::row_title(&mt('role'),'LC_oddrow_value'). $options. &Apache::lonhtmlcommon::row_closure(1)."\n"; } $secbox .= &Apache::lonhtmlcommon::row_title($rowtitle,'LC_oddrow_value')."\n"; - if ($env{'request.course.sec'} eq '') { + if ($caller eq 'requestcrs') { + $secbox .= ''."\n". + ''."\n". + ''."\n"; + } elsif ($env{'request.course.sec'} eq '') { $secbox .= ''."\n". '
'.&mt('Existing sections')."\n". '
'.$sections_select.'
'. @@ -3761,13 +3880,15 @@ END # Print out the initial form to get the file containing a list of users # sub print_first_users_upload_form { - my ($r,$context) = @_; + my ($r,$context,$noheader,$caller) = @_; my $str; $str = ''; $str .= ''; $str .= ''; - $str .= '

'.&mt('Upload a file containing information about users').'

'."\n"; + unless ($noheader) { + $str .= '

'.&mt('Upload a file containing information about users').'

'."\n"; + } # Excel and CSV Help $str .= '
' @@ -3781,15 +3902,15 @@ sub print_first_users_upload_form { .&Apache::lonhtmlcommon::row_title(&mt('File')) .&Apache::loncommon::upfile_select_html() .&Apache::lonhtmlcommon::row_closure() - .&Apache::lonhtmlcommon::row_title( - '') - .'' + .&Apache::lonhtmlcommon::row_title(&mt('Ignore First Line, e.g., contains column titles')) + .'' + .'   ' + .'' .&Apache::lonhtmlcommon::row_closure(1) .&Apache::lonhtmlcommon::end_pick_box(); $str .= '

' + .'' .'' .'

'; @@ -3852,9 +3973,15 @@ sub upfile_drop_add { $crstype = &Apache::loncommon::course_type($cid); } } - my ($startdate,$enddate) = &get_dates_from_form(); - if ($env{'form.makedatesdefault'}) { - $r->print(&make_dates_default($startdate,$enddate,$context,$crstype)); + my ($startdate,$enddate); + if ($env{'form.caller'} eq 'requestcrs') { + $startdate = $env{'course.'.$env{'request.course.id'}.'.default_enrollment_start_date'}; + $enddate = $env{'course.'.$env{'request.course.id'}.'.default_enrollment_end_date'}; + } else { + ($startdate,$enddate) = &get_dates_from_form(); + if ($env{'form.makedatesdefault'}) { + $r->print(&make_dates_default($startdate,$enddate,$context,$crstype)); + } } # Determine domain and desired host (home server) my $defdom=$env{'request.role.domain'}; @@ -4020,10 +4147,15 @@ sub upfile_drop_add { $r->print($groupwarn.'
'); } } - my (%curr_rules,%got_rules,%alerts); + my (%curr_rules,%got_rules,%alerts,%cancreate); my %customroles = &my_custom_roles($crstype); my @permitted_roles = &roles_on_upload($context,$setting,$crstype,%customroles); + my %longtypes = &Apache::lonlocal::texthash( + official => 'Institutional', + unofficial => 'Non-institutional', + ); + map { $cancreate{$_} = &can_create_user($domain,$context,$_); } keys(%longtypes); # Get new users list foreach my $line (@userdata) { my @secs; @@ -4169,20 +4301,68 @@ sub upfile_drop_add { my (%rulematch,%inst_results,%idinst_results); my $uhome=&Apache::lonnet::homeserver($username,$userdomain); if ($uhome eq 'no_host') { - next if ($userdomain ne $domain); + if ($userdomain ne $domain) { + $r->print('
'. + &mt('[_1]: The domain specified ([_2]) is different to that of the course.', + ''.$username.'',$userdomain).'
'. + &mt('The user does not already exist, and you may not create a new user in a different domain.')); + next; + } $checkid = 1; $newuser = 1; + my $user = $username.':'.$domain; + if ($username =~/^[^\@]+\@[^\@]+$/) { + if ($email eq '') { + $email = $username; + } + if (&Apache::loncommon::needs_gci_custom()) { + my $lc_email; + if ($username eq $email) { + $lc_email = lc($email); + } + my $lc_username = lc($username); + if ($lc_username ne $username) { + if ($username eq $email) { + $email = $lc_username; + } + $username = $lc_username; + $uhome=&Apache::lonnet::homeserver($username,$userdomain); + if ($uhome ne 'no_host') { + $newuser = 0; + } + } + } + } + } + if ($newuser) { my $checkhash; my $checks = { 'username' => 1 }; - $checkhash->{$username.':'.$domain} = { 'newuser' => 1, }; + $checkhash->{$user} = { 'newuser' => 1, }; &Apache::loncommon::user_rule_check($checkhash,$checks, \%alerts,\%rulematch,\%inst_results,\%curr_rules, \%got_rules); if (ref($alerts{'username'}) eq 'HASH') { if (ref($alerts{'username'}{$domain}) eq 'HASH') { - next if ($alerts{'username'}{$domain}{$username}); + if ($alerts{'username'}{$domain}{$username}) { + $r->print('
'. + &mt('[_1]: matches the username format at your institution, but is not known to your directory service.',''.$username.'').'
'. + &mt('Consequently, the user was not created.')); + next; + } } } + } + my $usertype = 'unofficial'; + if (ref($rulematch{$user}) eq 'HASH') { + if ($rulematch{$user}{'username'}) { + $usertype = 'official'; + } + } + if (!$cancreate{$usertype}) { + r->print('
'. + &mt("[_1]: The user does not exist, and you are not permitted to create users of type: $longtypes{$usertype}.",''.$username.'')); + next; + } } else { if ($context eq 'course' || $context eq 'author') { if ($userdomain eq $domain ) { @@ -4233,7 +4413,12 @@ sub upfile_drop_add { \%got_rules); if (ref($alerts{'id'}) eq 'HASH') { if (ref($alerts{'id'}{$userdomain}) eq 'HASH') { - next if ($alerts{'id'}{$userdomain}{$id}); + if ($alerts{'id'}{$userdomain}{$id}) { + $r->print(&mt('[_1]: has a student/employee ID matching the format at your institution, but the ID is found by your directory service.', + ''.$username.'').'
'. + &mt('Consequently, the user was not created.')); + next; + } } } } @@ -4332,10 +4517,20 @@ sub upfile_drop_add { $r->print("

\n

\n".&mt('Processed [quant,_1,user].',$counts{'user'}). "

\n"); if ($counts{'role'} > 0) { - $r->print("

\n". - &mt('Roles added for [quant,_1,user].',$counts{'role'}).' '.&mt('If a user is currently logged-in to LON-CAPA, any new roles which are active will be available when the user next logs in.')."

\n"); + if (&Apache::loncommon::needs_gci_custom()) { + $r->print("

\n". + &mt('[quant,_1,student] enrolled in Concept Test.',$counts{'role'}). + "

\n"); + } else { + $r->print("

\n". + &mt('Roles added for [quant,_1,user].',$counts{'role'}).' '.&mt('If a user is currently logged-in to LON-CAPA, any new roles which are active will be available when the user next logs in.')."

\n"); + } } else { - $r->print('

'.&mt('No roles added').'

'); + if (&Apache::loncommon::needs_gci_custom()) { + $r->print('

'.&mt('No students enrolled').'

'); + } else { + $r->print('

'.&mt('No roles added').'

'); + } } if ($counts{'auth'} > 0) { $r->print("

\n". @@ -4924,7 +5119,7 @@ sub setsections_javascript { accr => 'A course coordinator role will be added with access to all sections.', acor => 'A coordinator role will be added with access to all sections', inea => 'In each course, each user may only have one student role at a time.', - inec => 'In each community, each user may only have on member role at a time.', + inco => 'In each community, each user may only have on member role at a time.', youh => 'You had selected ', secs => 'sections.', plmo => 'Please modify your selections so they include no more than one section.', @@ -5021,6 +5216,46 @@ ENDSECCODE return $setsection_js; } +sub newsections_javascript { + my %alerts = &Apache::lonlocal::texthash( + inea => 'In each course, each user may only have one student role at a time.', + youh => 'You had selected ', + secs => 'sections.', + plmo => 'Please modify your selections so they include no more than one section.', + mayn => 'may not be used as the name for a section, as it is a reserved word.', + plch => 'Please choose a different section name.', + ); + my $setsection_js = <<"ENDSECCODE"; + +function setSections(formname) { + var newsecs = formname.newsec.value; + var numsplit = 0; + var numsec = 0; + if (newsecs != null && newsecs != "") { + numsplit = newsecs.split(/,/g); + numsec = numsplit.length; + } + if (numsec > 1) { + alert("$alerts{'inea'} $alerts{'youh'} "+numsec+" $alerts{'secs'}\\n$alerts{'plmo'}"); + } else { + if (numsplit > 0) { + for (var j=0; j