--- loncom/interface/lonuserutils.pm 2019/07/26 18:37:16 1.184.4.3 +++ loncom/interface/lonuserutils.pm 2019/08/22 19:31:20 1.184.4.4 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Utility functions for managing LON-CAPA user accounts # -# $Id: lonuserutils.pm,v 1.184.4.3 2019/07/26 18:37:16 raeburn Exp $ +# $Id: lonuserutils.pm,v 1.184.4.4 2019/08/22 19:31:20 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -438,7 +438,7 @@ sub javascript_validations { } elsif ($context eq 'domain') { $setsection_call = 'setCourse()'; $setsections_js = &dc_setcourse_js($param{'formname'},$mode, - $context,$showcredits); + $context,$showcredits,$domain); } $finish = " var checkSec = $setsection_call\n". " if (checkSec == 'ok') {\n". @@ -531,20 +531,24 @@ END /* regexp here to check for non \d \. in credits */ END } else { + my ($numrules,$intargjs) = + &passwd_validation_js('vf.elements[current.argfield].value',$domain); $auth_checks .= (< 0) { +$intargjs + } } END } @@ -641,6 +649,136 @@ END $section_checks.$authheader; return $result; } + +sub passwd_validation_js { + my ($currpasswdval,$domain) = @_; + my %passwdconf = &Apache::lonnet::get_passwdconf($domain); + my ($min,$max,@chars,$numrules,$intargjs,%alert); + $numrules = 0; + if (ref($passwdconf{'chars'}) eq 'ARRAY') { + if ($passwdconf{'min'} =~ /^\d+$/) { + $min = $passwdconf{'min'}; + $numrules ++; + } + if ($passwdconf{'max'} =~ /^\d+$/) { + $max = $passwdconf{'max'}; + $numrules ++; + } + @chars = @{$passwdconf{'chars'}}; + if (@chars) { + $numrules ++; + } + } else { + $min = 7; + $numrules ++; + } + if (($min ne '') || ($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'.$username.''); + map { $showpasswdrules{$_} = 1; } @brokepwdrules; + next; + } + } + } } } + unless ($passwdfromfile) { + if ($env{'form.login'} eq 'int') { + if (@genpwdfail) { + my $uhome=&Apache::lonnet::homeserver($username,$userdomain); + if (($uhome eq 'no_host') || ($changeauth)) { + $disallow{$counter} = &mt('[_1]: No specific password in file for this user; default password did not meet requirements', + ''.$username.''); + unless ($haspasswdmap) { + map { $showpasswdrules{$_} = 1; } @genpwdfail; + $haspasswdmap = 1; + } + } + next; + } + } + $password = $genpwd; + } # determine user role my $role = ''; if (defined($fields{'role'})) { @@ -4849,6 +5022,7 @@ sub upfile_drop_add { $counts{'auth'})."

\n"); } $r->print(&print_namespacing_alerts($domain,\%alerts,\%curr_rules)); + $r->print(&passwdrule_alerts($domain,\%showpasswdrules)); ##################################### # Display list of students to drop # ##################################### @@ -4918,6 +5092,38 @@ sub print_namespacing_alerts { } } +sub passwdrule_alerts { + my ($domain,$passwdrules) = @_; + my $warning; + if (ref($passwdrules) eq 'HASH') { + my %showrules = %{$passwdrules}; + if (keys(%showrules)) { + my %passwdconf = &Apache::lonnet::get_passwdconf($domain); + $warning = ''.&mt('Password requirement(s) unmet for one or more users:').''; + } + } + return $warning; +} + sub user_change_result { my ($r,$userresult,$authresult,$roleresult,$idresult,$counts,$flushc, $username,$userdomain,$userchg) = @_; @@ -5999,7 +6205,7 @@ sub get_course_identity { } sub dc_setcourse_js { - my ($formname,$mode,$context,$showcredits) = @_; + my ($formname,$mode,$context,$showcredits,$domain) = @_; my ($dc_setcourse_code,$authen_check); my $cctext = &Apache::lonnet::plaintext('cc'); my $cotext = &Apache::lonnet::plaintext('co'); @@ -6008,7 +6214,7 @@ sub dc_setcourse_js { if ($mode eq 'upload') { $role = 'courserole'; } else { - $authen_check = &verify_authen($formname,$context); + $authen_check = &verify_authen($formname,$context,$domain); } $dc_setcourse_code = (<<"SCRIPTTOP"); $authen_check @@ -6152,12 +6358,14 @@ ENDSCRIPT } sub verify_authen { - my ($formname,$context) = @_; + my ($formname,$context,$domain) = @_; my %alerts = &authcheck_alerts(); my $finish = "return 'ok';"; if ($context eq 'author') { $finish = "document.$formname.submit();"; } + my ($numrules,$intargjs) = + &passwd_validation_js('argpicked',$domain); my $outcome = <<"ENDSCRIPT"; function auth_check() { @@ -6191,6 +6399,7 @@ function auth_check() { break; case 'int': alertmsg = '$alerts{'ipass'}'; + break; case 'fsys': alertmsg = '$alerts{'ipass'}'; break; @@ -6204,6 +6413,11 @@ function auth_check() { alert(alertmsg); return; } + } else if (logintype == 'int') { + var numrules = $numrules; + if (numrules > 0) { +$intargjs + } } $finish }