--- loncom/interface/lonuserutils.pm 2023/10/06 02:27:26 1.184.4.10.2.5 +++ loncom/interface/lonuserutils.pm 2024/07/04 16:29:50 1.184.4.12 @@ -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.2.5 2023/10/06 02:27:26 raeburn Exp $ +# $Id: lonuserutils.pm,v 1.184.4.12 2024/07/04 16:29:50 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); } } @@ -532,7 +551,7 @@ END END } else { my ($numrules,$intargjs) = - &Apache::loncommon::passwd_validation_js('vf.elements[current.argfield].value',$domain); + &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 1 }); - $env{'course.'.$cid.'.internal.userdomains'} = $coursedesc{'internal.userdomains'}; } } my ($startdate,$enddate) = &get_dates_from_form(); @@ -4875,7 +5032,7 @@ sub upfile_drop_add { $mname,$lname,$gen,$singlesec, $env{'form.forceid'},$desiredhost, $email,$role,$enddate,$startdate, - $checkid,$inststatus); + $checkid,$inststatus,\%emptyok); } } if ($multiple) { @@ -4897,13 +5054,6 @@ 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); @@ -6133,9 +6283,8 @@ sub get_permission { } } my $allowed = 0; - foreach my $key (keys(%permission)) { - next if (($key eq 'owner') || ($key eq 'co-owner')); - if ($permission{$key}) { $allowed=1; last; } + foreach my $perm (values(%permission)) { + if ($perm) { $allowed=1; last; } } return (\%permission,$allowed); } @@ -6344,7 +6493,7 @@ sub verify_authen { $finish = "document.$formname.submit();"; } my ($numrules,$intargjs) = - &Apache::loncommon::passwd_validation_js('argpicked',$domain); + &passwd_validation_js('argpicked',$domain); my $outcome = <<"ENDSCRIPT"; function auth_check() {