--- loncom/interface/lonuserutils.pm 2021/08/24 00:22:59 1.184.4.10 +++ loncom/interface/lonuserutils.pm 2024/01/05 04:09:47 1.184.4.10.2.7 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Utility functions for managing LON-CAPA user accounts # -# $Id: lonuserutils.pm,v 1.184.4.10 2021/08/24 00:22:59 raeburn Exp $ +# $Id: lonuserutils.pm,v 1.184.4.10.2.7 2024/01/05 04:09:47 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -103,7 +103,7 @@ sub modifystudent { sub modifyuserrole { my ($context,$setting,$changeauth,$cid,$udom,$uname,$uid,$umode,$upass, $first,$middle,$last,$gene,$sec,$forceid,$desiredhome,$email,$role, - $end,$start,$checkid,$inststatus) = @_; + $end,$start,$checkid,$inststatus,$emptyok) = @_; my ($scope,$userresult,$authresult,$roleresult,$idresult); if ($setting eq 'course' || $context eq 'course') { $scope = '/'.$cid; @@ -134,6 +134,25 @@ sub modifyuserrole { generation => $gene, id => $uid, ); + + # When "Update ID in user's course(s)" and "Force change of existing ID" + # checkboxes both checked, prevent replacement of name information + # in classlist.db file(s) for the user's course(s) with blank(s), + # in the case where the uploaded csv file was without column(s) for + # the particular field. Fields are: First Name, Middle Names/Initials, + # Last Name (or the composite: Last Name, First Names), and Generation. + + my %emptyallowed; + if ((ref($emptyok) eq 'HASH') && (keys(%{$emptyok}) > 0)) { + %emptyallowed = %{$emptyok}; + } + foreach my $field (keys(%userupdate)) { + if ($userupdate{$field} eq '') { + unless ($emptyallowed{$field}) { + delete($userupdate{$field}); + } + } + } $idresult = &propagate_id_change($uname,$udom,\%userupdate); } } @@ -510,7 +529,7 @@ END "; } elsif ($mode eq 'modifycourse') { $auth_checks .= " - if (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '') { + if ((current.argfield !== null) && (current.argfield !== undefined) && (current.argfield !== '') && (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '')) { "; } if ( ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) { @@ -532,7 +551,7 @@ END END } else { my ($numrules,$intargjs) = - &passwd_validation_js('vf.elements[current.argfield].value',$domain); + &Apache::loncommon::passwd_validation_js('vf.elements[current.argfield].value',$domain); $auth_checks .= (< $min) { - $min = $passwdconf{'min'}; - } - } - if ($passwdconf{'max'} =~ /^\d+$/) { - $max = $passwdconf{'max'}; - $numrules ++; - } - @chars = @{$passwdconf{'chars'}}; - if (@chars) { - $numrules ++; - } - } - if ($min > 0) { - $numrules ++; - } - if (($min > 0) || ($max ne '') || (@chars > 0)) { - my $alertmsg = &mt('Initial password did not satisfy requirement(s):').'\n\n'; - if ($min) { - $alert{'min'} = &mt('minimum [quant,_1,character]',$min).'\n'; - } - if ($max) { - $alert{'max'} = &mt('maximum [quant,_1,character]',$max).'\n'; - } - my (@charalerts,@charrules); - if (@chars) { - if (grep(/^uc$/,@chars)) { - push(@charalerts,&mt('contain at least one upper case letter')); - push(@charrules,'uc'); - } - if (grep(/^lc$/,@chars)) { - push(@charalerts,&mt('contain at least one lower case letter')); - push(@charrules,'lc'); - } - if (grep(/^num$/,@chars)) { - push(@charalerts,&mt('contain at least one number')); - push(@charrules,'num'); - } - if (grep(/^spec$/,@chars)) { - push(@charalerts,&mt('contain at least one non-alphanumeric')); - push(@charrules,'spec'); - } - } - $intargjs = qq| var rulesmsg = '';\n|. - qq| var currpwval = $currpasswdval;\n|; - if ($min) { - $intargjs .= qq| - if (currpwval.length < $min) { - rulesmsg += ' - $alert{min}'; - } -|; - } - if ($max) { - $intargjs .= qq| - if (currpwval.length > $max) { - rulesmsg += ' - $alert{max}'; - } -|; - } - if (@chars > 0) { - my $charrulestr = '"'.join('","',@charrules).'"'; - my $charalertstr = '"'.join('","',@charalerts).'"'; - $intargjs .= qq| var brokerules = new Array();\n|. - qq| var charrules = new Array($charrulestr);\n|. - qq| var charalerts = new Array($charalertstr);\n|; - my %rules; - map { $rules{$_} = 1; } @chars; - if ($rules{'uc'}) { - $intargjs .= qq| - var ucRegExp = /[A-Z]/; - if (!ucRegExp.test(currpwval)) { - brokerules.push('uc'); - } -|; - } - if ($rules{'lc'}) { - $intargjs .= qq| - var lcRegExp = /[a-z]/; - if (!lcRegExp.test(currpwval)) { - brokerules.push('lc'); - } -|; - } - if ($rules{'num'}) { - $intargjs .= qq| - var numRegExp = /[0-9]/; - if (!numRegExp.test(currpwval)) { - brokerules.push('num'); - } -|; - } - if ($rules{'spec'}) { - $intargjs .= q| - var specRegExp = /[!"#$%&'()*+,\-.\/:;<=>?@[\\^\]_`{\|}~]/; - if (!specRegExp.test(currpwval)) { - brokerules.push('spec'); - } -|; - } - $intargjs .= qq| - if (brokerules.length > 0) { - for (var i=0; i $now)) { + $env{'form.Status'} = 'Future'; + $showstart = 1; + } + if (($endaccess ne '') && ($endaccess != 0) && ($endaccess < $now)) { + $env{'form.Status'} = 'Expired'; + undef($showstart); + $showend = 1; + } + } if ($env{'form.Status'} !~ /^(Any|Expired|Active|Future)$/) { $env{'form.Status'} = 'Active'; } @@ -1786,7 +1692,7 @@ sub print_userlist { $r->print(§ion_group_filter($cnum,$cdom)); } $r->print('
'. - &column_checkboxes($context,$mode,$formname,$showcredits). + &column_checkboxes($context,$mode,$formname,$showcredits,$showstart,$showend). '
'); if ($env{'form.phase'} eq '') { $r->print('
'. @@ -2175,7 +2081,7 @@ sub get_cols_array { } sub column_checkboxes { - my ($context,$mode,$formname,$showcredits) = @_; + my ($context,$mode,$formname,$showcredits,$showstart,$showend) = @_; my @cols = &get_cols_array($context,$mode,$showcredits); my @showncols = &Apache::loncommon::get_env_multiple('form.showcol'); my (%disabledchk,%unchecked); @@ -2188,11 +2094,21 @@ sub column_checkboxes { if ($showcredits) { $unchecked{'credits'} = 1; } - } elsif ($context eq 'domain') { + my %curr_groups = &Apache::longroup::coursegroups(); + unless (keys(%curr_groups)) { + $unchecked{'groups'} = 1; + } + } elsif ($context eq 'domain') { $unchecked{'extent'} = 1; } - $unchecked{'start'} = 1; - $unchecked{'end'} = 1; + if ($showstart) { + $unchecked{'lastlogin'} = 1; + } else { + $unchecked{'start'} = 1; + } + unless ($showend) { + $unchecked{'end'} = 1; + } } else { if ($env{'form.Status'} ne 'Any') { $disabledchk{'status'} = 1; @@ -4290,17 +4206,42 @@ sub upfile_drop_add { $fieldstype{$field.'_choice'} = 'scalar'; } &Apache::loncommon::store_course_settings('enrollment_upload',\%fieldstype); - my ($cid,$crstype,$setting); + my ($cid,$crstype,$setting,$crsdom,$crsnum,$oldcrsuserdoms,%emptyok); if ($context eq 'domain') { $setting = $env{'form.roleaction'}; + if (exists($fields{'names'})) { + map { $emptyok{$_} = 1; } ('lastname','firstname','middlename'); + } else { + if (exists($fields{'lname'})) { + $emptyok{'lastname'} = 1; + } + if (exists($fields{'fname'})) { + $emptyok{'firstname'} = 1; + } + if (exists($fields{'mname'})) { + $emptyok{'middlename'} = 1; + } + } + if (exists($fields{'gen'})) { + $emptyok{'generation'} = 1; + } } if ($env{'request.course.id'} ne '') { $cid = $env{'request.course.id'}; $crstype = &Apache::loncommon::course_type(); + $crsdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + $crsnum = $env{'course.'.$env{'request.course.id'}.'.num'}; } elsif ($setting eq 'course') { if (&Apache::lonnet::is_course($env{'form.dcdomain'},$env{'form.dccourse'})) { $cid = $env{'form.dcdomain'}.'_'.$env{'form.dccourse'}; $crstype = &Apache::loncommon::course_type($cid); + $crsdom = $env{'form.dcdomain'}; + $crsnum = $env{'form.dccourse'}; + if (exists($env{'course.'.$cid.'.internal.userdomains'})) { + $oldcrsuserdoms = 1; + } + my %coursedesc = &Apache::lonnet::coursedescription($cid,{ one_time => 1 }); + $env{'course.'.$cid.'.internal.userdomains'} = $coursedesc{'internal.userdomains'}; } } my ($startdate,$enddate) = &get_dates_from_form(); @@ -4997,7 +4938,7 @@ sub upfile_drop_add { $mname,$lname,$gen,$singlesec, $env{'form.forceid'},$desiredhost, $email,$role,$enddate,$startdate, - $checkid,$inststatus); + $checkid,$inststatus,\%emptyok); } } if ($multiple) { @@ -5019,6 +4960,13 @@ sub upfile_drop_add { } # end of loop $r->print(''); &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); + if (($context eq 'domain') && ($setting eq 'course')) { + unless ($oldcrsuserdoms) { + if (exists($env{'course.'.$cid.'.internal.userdomains'})) { + delete($env{'course.'.$cid.'.internal.userdomains'}); + } + } + } } # Flush the course logs so reverse user roles immediately updated $r->register_cleanup(\&Apache::lonnet::flushcourselogs); @@ -6197,6 +6145,9 @@ sub get_permission { $permission{'selfenrolladmin'} = 1; } } + unless ($permission{'selfenrolladmin'}) { + $permission{'selfenrollview'} = 1; + } } if ($env{'request.course.id'}) { my $user; @@ -6245,8 +6196,9 @@ sub get_permission { } } my $allowed = 0; - foreach my $perm (values(%permission)) { - if ($perm) { $allowed=1; last; } + foreach my $key (keys(%permission)) { + next if (($key eq 'owner') || ($key eq 'co-owner')); + if ($permission{$key}) { $allowed=1; last; } } return (\%permission,$allowed); } @@ -6455,7 +6407,7 @@ sub verify_authen { $finish = "document.$formname.submit();"; } my ($numrules,$intargjs) = - &passwd_validation_js('argpicked',$domain); + &Apache::loncommon::passwd_validation_js('argpicked',$domain); my $outcome = <<"ENDSCRIPT"; function auth_check() { @@ -6659,7 +6611,7 @@ sub selfenrollment_administration { } } if ($settings{'internal.selfenrollmgrdc'} ne '') { - my @in_domain = split(/,/,$settings{'internal.selfenrollmgrdc'}); + @in_domain = split(/,/,$settings{'internal.selfenrollmgrdc'}); my @diffs = &Apache::loncommon::compare_arrays(\@in_domain,$possconfigs); unless (@diffs) { return (\@in_course,\@in_domain);