[LON-CAPA-cvs] cvs: loncom(version_2_11_X) /interface domainprefs.pm
raeburn
raeburn at source.lon-capa.org
Wed Aug 21 16:31:40 EDT 2019
raeburn Wed Aug 21 20:31:40 2019 EDT
Modified files: (Branch: version_2_11_X)
/loncom/interface domainprefs.pm
Log:
- For 2.11
Backport 1.354, 1.355, 1.356, 1.358, 1.359, 1.361
(except password expiration parts).
-------------- next part --------------
Index: loncom/interface/domainprefs.pm
diff -u loncom/interface/domainprefs.pm:1.160.6.97 loncom/interface/domainprefs.pm:1.160.6.98
--- loncom/interface/domainprefs.pm:1.160.6.97 Sat Aug 17 19:24:29 2019
+++ loncom/interface/domainprefs.pm Wed Aug 21 20:31:37 2019
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
-# $Id: domainprefs.pm,v 1.160.6.97 2019/08/17 19:24:29 raeburn Exp $
+# $Id: domainprefs.pm,v 1.160.6.98 2019/08/21 20:31:37 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -216,8 +216,8 @@
'contacts','defaults','scantron','coursecategories',
'serverstatuses','requestcourses','helpsettings',
'coursedefaults','usersessions','loadbalancing',
- 'requestauthor','selfenrollment','inststatus'],$dom);
- my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',
+ 'requestauthor','selfenrollment','inststatus','passwords'],$dom);
+ my @prefs_order = ('rolecolors','login','defaults','passwords','quotas','autoenroll',
'autoupdate','autocreate','directorysrch','contacts',
'usercreation','selfcreation','usermodification','scantron',
'requestcourses','requestauthor','coursecategories',
@@ -262,13 +262,25 @@
help => 'Domain_Configuration_LangTZAuth',
header => [{col1 => 'Setting',
col2 => 'Value'},
- {col1 => 'Internal Authentication',
- col2 => 'Value'},
{col1 => 'Institutional user types',
col2 => 'Name displayed'}],
print => \&print_defaults,
modify => \&modify_defaults,
},
+ 'passwords' =>
+ { text => 'Passwords (Internal authentication)',
+ help => 'Domain_Configuration_Passwords',
+ header => [{col1 => 'Resetting Forgotten Password',
+ col2 => 'Settings'},
+ {col1 => 'Encryption of Stored Passwords (Internal Auth)',
+ col2 => 'Settings'},
+ {col1 => 'Rules for LON-CAPA Passwords',
+ col2 => 'Settings'},
+ {col1 => 'Course Owner Changing Student Passwords',
+ col2 => 'Settings'}],
+ print => \&print_passwords,
+ modify => \&modify_passwords,
+ },
'quotas' =>
{ text => 'Blogs, personal web pages, webDAV/quotas, portfolios',
help => 'Domain_Configuration_Quotas',
@@ -658,6 +670,8 @@
$output = &modify_usersessions($dom,$lastactref,%domconfig);
} elsif ($action eq 'loadbalancing') {
$output = &modify_loadbalancing($dom,%domconfig);
+ } elsif ($action eq 'passwords') {
+ $output = &modify_passwords($r,$dom,$confname,$lastactref,%domconfig);
}
return $output;
}
@@ -670,6 +684,8 @@
$output = &coursecategories_javascript($settings);
} elsif ($action eq 'defaults') {
$output = &defaults_javascript($settings);
+ } elsif ($action eq 'passwords') {
+ $output = &passwords_javascript();
} elsif ($action eq 'helpsettings') {
my (%privs,%levelscurrent);
my %full=();
@@ -724,6 +740,8 @@
($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'directorysrch') ||
($action eq 'helpsettings') || ($action eq 'contacts')) {
$output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);
+ } elsif ($action eq 'passwords') {
+ $output .= $item->{'print'}->('top',$dom,$confname,$settings,\$rowtotal);
} elsif ($action eq 'coursecategories') {
$output .= $item->{'print'}->('top',$dom,$item,$settings,\$rowtotal);
} elsif ($action eq 'scantron') {
@@ -755,10 +773,12 @@
if (($action eq 'autoupdate') || ($action eq 'usercreation') ||
($action eq 'selfcreation') || ($action eq 'selfenrollment') ||
($action eq 'usersessions') || ($action eq 'coursecategories') ||
- ($action eq 'contacts') || ($action eq 'defaults')) {
+ ($action eq 'contacts') || ($action eq 'passwords')) {
if ($action eq 'coursecategories') {
$output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);
$colspan = ' colspan="2"';
+ } elsif ($action eq 'passwords') {
+ $output .= $item->{'print'}->('middle',$dom,$confname,$settings,\$rowtotal);
} else {
$output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal);
}
@@ -775,6 +795,23 @@
</tr>'."\n";
if ($action eq 'coursecategories') {
$output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal);
+ } elsif ($action eq 'passwords') {
+ $output .= $item->{'print'}->('lower',$dom,$confname,$settings,\$rowtotal).'
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table class="LC_nested">
+ <tr class="LC_info_row">
+ <td class="LC_left_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col1'}).'</td>
+ <td class="LC_right_item"'.$colspan.'>'.&mt($item->{'header'}->[3]->{'col2'}).'</td></tr>'."\n".
+ $item->{'print'}->('bottom',$dom,$confname,$settings,\$rowtotal).'
+ </table>
+ </td>
+ </tr>
+ <tr>';
} else {
$output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal);
}
@@ -4017,6 +4054,427 @@
return $datatable;
}
+sub print_passwords {
+ my ($position,$dom,$confname,$settings,$rowtotal) = @_;
+ my ($datatable,$css_class);
+ my $itemcount = 0;
+ my %titles = &Apache::lonlocal::texthash (
+ captcha => '"Forgot Password" CAPTCHA validation',
+ link => 'Reset link expiration (hours)',
+ case => 'Case-sensitive usernames/e-mail',
+ prelink => 'Information required (form 1)',
+ postlink => 'Information required (form 2)',
+ emailsrc => 'LON-CAPA e-mail address type(s)',
+ customtext => 'Domain specific text (HTML)',
+ intauth_cost => 'Encryption cost for bcrypt (positive integer)',
+ intauth_check => 'Check bcrypt cost if authenticated',
+ intauth_switch => 'Existing crypt-based switched to bcrypt on authentication',
+ permanent => 'Permanent e-mail address',
+ critical => 'Critical notification address',
+ notify => 'Notification address',
+ min => 'Minimum password length',
+ max => 'Maximum password length',
+ chars => 'Required characters',
+ numsaved => 'Number of previous passwords to save and disallow reuse',
+ );
+ if ($position eq 'top') {
+ my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
+ my $shownlinklife = 2;
+ my $prelink = 'both';
+ my (%casesens,%postlink,%emailsrc,$nostdtext,$customurl);
+ if (ref($settings) eq 'HASH') {
+ if ($settings->{resetlink} =~ /^\d+(|\.\d*)$/) {
+ $shownlinklife = $settings->{resetlink};
+ }
+ if (ref($settings->{resetcase}) eq 'ARRAY') {
+ map { $casesens{$_} = 1; } (@{$settings->{resetcase}});
+ }
+ if ($settings->{resetprelink} =~ /^(both|either)$/) {
+ $prelink = $settings->{resetprelink};
+ }
+ if (ref($settings->{resetpostlink}) eq 'HASH') {
+ %postlink = %{$settings->{resetpostlink}};
+ }
+ if (ref($settings->{resetemail}) eq 'ARRAY') {
+ map { $emailsrc{$_} = 1; } (@{$settings->{resetemail}});
+ }
+ if ($settings->{resetremove}) {
+ $nostdtext = 1;
+ }
+ if ($settings->{resetcustom}) {
+ $customurl = $settings->{resetcustom};
+ }
+ } else {
+ if (ref($types) eq 'ARRAY') {
+ foreach my $item (@{$types}) {
+ $casesens{$item} = 1;
+ $postlink{$item} = ['username','email'];
+ }
+ }
+ }
+ $casesens{'default'} = 1;
+ $postlink{'default'} = ['username','email'];
+ $prelink = 'both';
+ %emailsrc = (
+ permanent => 1,
+ critical => 1,
+ notify => 1,
+ );
+ }
+ $datatable = &captcha_choice('passwords',$settings,$$rowtotal);
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= '<tr'.$css_class.'><td>'.$titles{'link'}.'</td>'.
+ '<td class="LC_left_item">'.
+ '<input type="textbox" value="'.$shownlinklife.'" '.
+ 'name="passwords_link" size="3" /></td></tr>';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= '<tr'.$css_class.'><td>'.$titles{'case'}.'</td>'.
+ '<td class="LC_left_item">';
+ if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
+ foreach my $item (@{$types}) {
+ my $checkedcase;
+ if ($casesens{$item}) {
+ $checkedcase = ' checked="checked"';
+ }
+ $datatable .= '<span class="LC_nobreak"><label>'.
+ '<input type="checkbox" name="passwords_case_sensitive" value="'.
+ $item.'"'.$checkedcase.' />'.$usertypes->{$item}.'</label>'.
+ '<span> ';
+ }
+ }
+ my $checkedcase;
+ if ($casesens{'default'}) {
+ $checkedcase = ' checked="checked"';
+ }
+ $datatable .= '<span class="LC_nobreak"><label><input type="checkbox" '.
+ 'name="passwords_case_sensitive" value="default"'.$checkedcase.' />'.
+ $othertitle.'</label></span></td>';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ my %checkedpre = (
+ both => ' checked="checked"',
+ either => '',
+ );
+ if ($prelink eq 'either') {
+ $checkedpre{either} = ' checked="checked"';
+ $checkedpre{both} = '';
+ }
+ $datatable .= '<tr'.$css_class.'><td>'.$titles{'prelink'}.'</td>'.
+ '<td class="LC_left_item"><span class="LC_nobreak">'.
+ '<label><input type="radio" name="passwords_prelink" value="both"'.$checkedpre{'both'}.' />'.
+ &mt('Both username and e-mail address').'</label></span> '.
+ '<span class="LC_nobreak"><label>'.
+ '<input type="radio" name="passwords_prelink" value="either"'.$checkedpre{'either'}.' />'.
+ &mt('Either username or e-mail address').'</label></span></td></tr>';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= '<tr'.$css_class.'><td>'.$titles{'postlink'}.'</td>'.
+ '<td class="LC_left_item">';
+ my %postlinked;
+ if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
+ foreach my $item (@{$types}) {
+ undef(%postlinked);
+ $datatable .= '<fieldset style="display: inline-block;">'.
+ '<legend>'.$usertypes->{$item}.'</legend>';
+ if (ref($postlink{$item}) eq 'ARRAY') {
+ map { $postlinked{$_} = 1; } (@{$postlink{$item}});
+ }
+ foreach my $field ('email','username') {
+ my $checked;
+ if ($postlinked{$field}) {
+ $checked = ' checked="checked"';
+ }
+ $datatable .= '<span class="LC_nobreak"><label>'.
+ '<input type="checkbox" name="passwords_postlink_'.$item.'" value="'.
+ $field.'"'.$checked.' />'.$field.'</label>'.
+ '<span> ';
+ }
+ $datatable .= '</fieldset>';
+ }
+ }
+ if (ref($postlink{'default'}) eq 'ARRAY') {
+ map { $postlinked{$_} = 1; } (@{$postlink{'default'}});
+ }
+ $datatable .= '<fieldset style="display: inline-block;">'.
+ '<legend>'.$othertitle.'</legend>';
+ foreach my $field ('email','username') {
+ my $checked;
+ if ($postlinked{$field}) {
+ $checked = ' checked="checked"';
+ }
+ $datatable .= '<span class="LC_nobreak"><label>'.
+ '<input type="checkbox" name="passwords_postlink_default" value="'.
+ $field.'"'.$checked.' />'.$field.'</label>'.
+ '<span> ';
+ }
+ $datatable .= '</fieldset></td></tr>';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= '<tr'.$css_class.'><td>'.$titles{'emailsrc'}.'</td>'.
+ '<td class="LC_left_item">';
+ foreach my $type ('permanent','critical','notify') {
+ my $checkedemail;
+ if ($emailsrc{$type}) {
+ $checkedemail = ' checked="checked"';
+ }
+ $datatable .= '<span class="LC_nobreak"><label>'.
+ '<input type="checkbox" name="passwords_emailsrc" value="'.
+ $type.'"'.$checkedemail.' />'.$titles{$type}.'</label>'.
+ '<span> ';
+ }
+ $datatable .= '</td></tr>';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ my $switchserver = &check_switchserver($dom,$confname);
+ my ($showstd,$noshowstd);
+ if ($nostdtext) {
+ $noshowstd = ' checked="checked"';
+ } else {
+ $showstd = ' checked="checked"';
+ }
+ $datatable .= '<tr'.$css_class.'><td>'.$titles{'customtext'}.'</td>'.
+ '<td class="LC_left_item"><span class="LC_nobreak">'.
+ &mt('Retain standard text:').
+ '<label><input type="radio" name="passwords_stdtext" value="1"'.$showstd.' />'.
+ &mt('Yes').'</label>'.' '.
+ '<label><input type="radio" name="passwords_stdtext" value="0"'.$noshowstd.' />'.
+ &mt('No').'</label></span><br />'.
+ '<span class="LC_fontsize_small">'.
+ &mt('(If you use the same account ... reset a password from this page.)').'</span><br /><br />'.
+ &mt('Include custom text:');
+ if ($customurl) {
+ my $link = &Apache::loncommon::modal_link($customurl,&mt('Custom text file'),600,500,
+ undef,undef,undef,undef,'background-color:#ffffff');
+ $datatable .= '<span class="LC_nobreak"> '.$link.
+ '<label><input type="checkbox" name="passwords_custom_del"'.
+ ' value="1" />'.&mt('Delete?').'</label></span>'.
+ ' <span class="LC_nobreak"> '.&mt('Replace:').'</span>';
+ }
+ if ($switchserver) {
+ $datatable .= '<span class="LC_nobreak"> '.&mt('Upload to library server: [_1]',$switchserver).'</span>';
+ } else {
+ $datatable .='<span class="LC_nobreak"> '.
+ '<input type="file" name="passwords_customfile" /></span>';
+ }
+ $datatable .= '</td></tr>';
+ } elsif ($position eq 'middle') {
+ my %domconf = &Apache::lonnet::get_dom('configuration',['defaults'],$dom);
+ my @items = ('intauth_cost','intauth_check','intauth_switch');
+ my %defaults;
+ if (ref($domconf{'defaults'}) eq 'HASH') {
+ %defaults = %{$domconf{'defaults'}};
+ if ($defaults{'intauth_cost'} !~ /^\d+$/) {
+ $defaults{'intauth_cost'} = 10;
+ }
+ if ($defaults{'intauth_check'} !~ /^(0|1|2)$/) {
+ $defaults{'intauth_check'} = 0;
+ }
+ if ($defaults{'intauth_switch'} !~ /^(0|1|2)$/) {
+ $defaults{'intauth_switch'} = 0;
+ }
+ } else {
+ %defaults = (
+ 'intauth_cost' => 10,
+ 'intauth_check' => 0,
+ 'intauth_switch' => 0,
+ );
+ }
+ foreach my $item (@items) {
+ if ($itemcount%2) {
+ $css_class = '';
+ } else {
+ $css_class = ' class="LC_odd_row" ';
+ }
+ $datatable .= '<tr'.$css_class.'>'.
+ '<td><span class="LC_nobreak">'.$titles{$item}.
+ '</span></td><td class="LC_left_item" colspan="3">';
+ if ($item eq 'intauth_switch') {
+ my @options = (0,1,2);
+ my %optiondesc = &Apache::lonlocal::texthash (
+ 0 => 'No',
+ 1 => 'Yes',
+ 2 => 'Yes, and copy existing passwd file to passwd.bak file',
+ );
+ $datatable .= '<table width="100%">';
+ foreach my $option (@options) {
+ my $checked = ' ';
+ if ($defaults{$item} eq $option) {
+ $checked = ' checked="checked"';
+ }
+ $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.
+ '<label><input type="radio" name="'.$item.
+ '" value="'.$option.'"'.$checked.' />'.
+ $optiondesc{$option}.'</label></span></td></tr>';
+ }
+ $datatable .= '</table>';
+ } elsif ($item eq 'intauth_check') {
+ my @options = (0,1,2);
+ my %optiondesc = &Apache::lonlocal::texthash (
+ 0 => 'No',
+ 1 => 'Yes, allow login then update passwd file using default cost (if higher)',
+ 2 => 'Yes, disallow login if stored cost is less than domain default',
+ );
+ $datatable .= '<table width="100%">';
+ foreach my $option (@options) {
+ my $checked = ' ';
+ my $onclick;
+ if ($defaults{$item} eq $option) {
+ $checked = ' checked="checked"';
+ }
+ if ($option == 2) {
+ $onclick = ' onclick="javascript:warnIntAuth(this);"';
+ }
+ $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.
+ '<label><input type="radio" name="'.$item.
+ '" value="'.$option.'"'.$checked.$onclick.' />'.
+ $optiondesc{$option}.'</label></span></td></tr>';
+ }
+ $datatable .= '</table>';
+ } else {
+ $datatable .= '<input type="text" name="'.$item.'" value="'.
+ $defaults{$item}.'" size="3" onblur="javascript:warnIntAuth(this);" />';
+ }
+ $datatable .= '</td></tr>';
+ $itemcount ++;
+ }
+ } elsif ($position eq 'lower') {
+ my ($min,$max,%chars,$numsaved);
+ if (ref($settings) eq 'HASH') {
+ if ($settings->{min}) {
+ $min = $settings->{min};
+ }
+ if ($settings->{max}) {
+ $max = $settings->{max};
+ }
+ if (ref($settings->{chars}) eq 'ARRAY') {
+ map { $chars{$_} = 1; } (@{$settings->{chars}});
+ }
+ if ($settings->{numsaved}) {
+ $numsaved = $settings->{numsaved};
+ }
+ } else {
+ $min = '7';
+ }
+ my %rulenames = &Apache::lonlocal::texthash(
+ uc => 'At least one upper case letter',
+ lc => 'At least one lower case letter',
+ num => 'At least one number',
+ spec => 'At least one non-alphanumeric',
+ );
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= '<tr'.$css_class.'><td>'.$titles{'min'}.'</td>'.
+ '<td class="LC_left_item"><span class="LC_nobreak">'.
+ '<input type="text" name="passwords_min" value="'.$min.'" size="3" />'.
+ '<span class="LC_fontsize_small"> '.&mt('(Leave blank for no minimum)').'</span>'.
+ '</span></td></tr>';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= '<tr'.$css_class.'><td>'.$titles{'max'}.'</td>'.
+ '<td class="LC_left_item"><span class="LC_nobreak">'.
+ '<input type="text" name="passwords_max" value="'.$max.'" size="3" />'.
+ '<span class="LC_fontsize_small"> '.&mt('(Leave blank for no maximum)').'</span>'.
+ '</span></td></tr>';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= '<tr'.$css_class.'><td>'.$titles{'chars'}.'<br />'.
+ '<span class="LC_nobreak LC_fontsize_small">'.&mt('(Leave unchecked if not required)').
+ '</span></td>';
+ my $numinrow = 2;
+ my @possrules = ('uc','lc','num','spec');
+ $datatable .= '<td class="LC_left_item"><table>';
+ for (my $i=0; $i<@possrules; $i++) {
+ my ($rem,$checked);
+ if ($chars{$possrules[$i]}) {
+ $checked = ' checked="checked"';
+ }
+ $rem = $i%($numinrow);
+ if ($rem == 0) {
+ if ($i > 0) {
+ $datatable .= '</tr>';
+ }
+ $datatable .= '<tr>';
+ }
+ $datatable .= '<td><span class="LC_nobreak"><label>'.
+ '<input type="checkbox" name="passwords_chars" value="'.$possrules[$i].'"'.$checked.' />'.
+ $rulenames{$possrules[$i]}.'</label></span></td>';
+ }
+ my $rem = @possrules%($numinrow);
+ my $colsleft = $numinrow - $rem;
+ if ($colsleft > 1 ) {
+ $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
+ ' </td>';
+ } elsif ($colsleft == 1) {
+ $datatable .= '<td class="LC_left_item"> </td>';
+ }
+ $datatable .='</table></td></tr>';
+ $itemcount ++;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= '<tr'.$css_class.'><td>'.$titles{'numsaved'}.'</td>'.
+ '<td class="LC_left_item"><span class="LC_nobreak">'.
+ '<input type="text" name="passwords_numsaved" value="'.$numsaved.'" size="3" />'.
+ '<span class="LC_fontsize_small"> '.&mt('(Leave blank to not save previous passwords)').'</span>'.
+ '</span></td></tr>';
+ } else {
+ my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
+ my %ownerchg = (
+ by => {},
+ for => {},
+ );
+ my %ownertitles = &Apache::lonlocal::texthash (
+ by => 'Course owner status(es) allowed',
+ for => 'Student status(es) allowed',
+ );
+ if (ref($settings) eq 'HASH') {
+ if (ref($settings->{crsownerchg}) eq 'HASH') {
+ if (ref($settings->{crsownerchg}{'by'}) eq 'ARRAY') {
+ map { $ownerchg{by}{$_} = 1; } (@{$settings->{crsownerchg}{'by'}});
+ }
+ if (ref($settings->{crsownerchg}{'for'}) eq 'ARRAY') {
+ map { $ownerchg{for}{$_} = 1; } (@{$settings->{crsownerchg}{'for'}});
+ }
+ }
+ }
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= '<tr '.$css_class.'>'.
+ '<td>'.
+ &mt('Requirements').'<ul>'.
+ '<li>'.&mt("Course 'type' is not a Community").'</li>'.
+ '<li>'.&mt('User is Course Coordinator and also course owner').'</li>'.
+ '<li>'.&mt("Student's only active roles are student role(s) in course(s) owned by this user").'</li>'.
+ '<li>'.&mt('User, course, and student share same domain').'</li>'.
+ '</ul>'.
+ '</td>'.
+ '<td class="LC_left_item">';
+ foreach my $item ('by','for') {
+ $datatable .= '<fieldset style="display: inline-block;">'.
+ '<legend>'.$ownertitles{$item}.'</legend>';
+ if ((ref($types) eq 'ARRAY') && (ref($usertypes) eq 'HASH')) {
+ foreach my $type (@{$types}) {
+ my $checked;
+ if ($ownerchg{$item}{$type}) {
+ $checked = ' checked="checked"';
+ }
+ $datatable .= '<span class="LC_nobreak"><label>'.
+ '<input type="checkbox" name="passwords_crsowner_'.$item.'" value="'.
+ $type.'"'.$checked.' />'.$usertypes->{$type}.'</label>'.
+ '<span> ';
+ }
+ }
+ my $checked;
+ if ($ownerchg{$item}{'default'}) {
+ $checked = ' checked="checked"';
+ }
+ $datatable .= '<span class="LC_nobreak"><label><input type="checkbox" '.
+ 'name="passwords_crsowner_'.$item.'" value="default"'.$checked.' />'.
+ $othertitle.'</label></span></fieldset>';
+ }
+ $datatable .= '</td></tr>';
+ }
+ return $datatable;
+}
+
sub print_usersessions {
my ($position,$dom,$settings,$rowtotal) = @_;
my ($css_class,$datatable,%checked,%choices);
@@ -5575,10 +6033,14 @@
$vertext,$currver);
my %lt = &captcha_phrases();
$keyentry = 'hidden';
+ my $colspan=2;
if ($context eq 'cancreate') {
$rowname = &mt('CAPTCHA validation');
} elsif ($context eq 'login') {
$rowname = &mt('"Contact helpdesk" CAPTCHA validation');
+ } elsif ($context eq 'passwords') {
+ $rowname = &mt('"Forgot Password" CAPTCHA validation');
+ $colspan=1;
}
if (ref($settings) eq 'HASH') {
if ($settings->{'captcha'}) {
@@ -5618,7 +6080,7 @@
$css_class .= ' style="'.$rowstyle.'"';
}
my $output = '<tr'.$css_class.'>'.
- '<td class="LC_left_item">'.$rowname.'</td><td class="LC_left_item" colspan="2">'."\n".
+ '<td class="LC_left_item">'.$rowname.'</td><td class="LC_left_item" colspan="'.$colspan.'">'."\n".
'<table><tr><td>'."\n";
foreach my $option ('original','recaptcha','notused') {
$output .= '<span class="LC_nobreak"><label><input type="radio" name="'.$context.'_captcha" value="'.
@@ -5839,97 +6301,18 @@
my $includeempty = 1;
$datatable .= &Apache::loncommon::select_timezone($item,$defaults{$item},undef,$includeempty);
} elsif ($item eq 'datelocale_def') {
- my $includeempty = 1;
- $datatable .= &Apache::loncommon::select_datelocale($item,$defaults{$item},undef,$includeempty);
- } elsif ($item eq 'lang_def') {
- my $includeempty = 1;
- $datatable .= &Apache::loncommon::select_language($item,$defaults{$item},$includeempty);
- } else {
- my $size;
- if ($item eq 'portal_def') {
- $size = ' size="25"';
- }
- $datatable .= '<input type="text" name="'.$item.'" value="'.
- $defaults{$item}.'"'.$size.' />';
- }
- $datatable .= '</td></tr>';
- $rownum ++;
- }
- } elsif ($position eq 'middle') {
- my @items = ('intauth_cost','intauth_check','intauth_switch');
- my %defaults;
- if (ref($settings) eq 'HASH') {
- %defaults = %{$settings};
- if ($defaults{'intauth_cost'} !~ /^\d+$/) {
- $defaults{'intauth_cost'} = 10;
- }
- if ($defaults{'intauth_check'} !~ /^(0|1|2)$/) {
- $defaults{'intauth_check'} = 0;
- }
- if ($defaults{'intauth_switch'} !~ /^(0|1|2)$/) {
- $defaults{'intauth_switch'} = 0;
- }
- } else {
- %defaults = (
- 'intauth_cost' => 10,
- 'intauth_check' => 0,
- 'intauth_switch' => 0,
- );
- }
- foreach my $item (@items) {
- if ($rownum%2) {
- $css_class = '';
- } else {
- $css_class = ' class="LC_odd_row" ';
- }
- $datatable .= '<tr'.$css_class.'>'.
- '<td><span class="LC_nobreak">'.$titles->{$item}.
- '</span></td><td class="LC_left_item" colspan="3">';
- if ($item eq 'intauth_switch') {
- my @options = (0,1,2);
- my %optiondesc = &Apache::lonlocal::texthash (
- 0 => 'No',
- 1 => 'Yes',
- 2 => 'Yes, and copy existing passwd file to passwd.bak file',
- );
- $datatable .= '<table width="100%">';
- foreach my $option (@options) {
- my $checked = ' ';
- if ($defaults{$item} eq $option) {
- $checked = ' checked="checked"';
- }
- $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.
- '<label><input type="radio" name="'.$item.
- '" value="'.$option.'"'.$checked.' />'.
- $optiondesc{$option}.'</label></span></td></tr>';
- }
- $datatable .= '</table>';
- } elsif ($item eq 'intauth_check') {
- my @options = (0,1,2);
- my %optiondesc = &Apache::lonlocal::texthash (
- 0 => 'No',
- 1 => 'Yes, allow login then update passwd file using default cost (if higher)',
- 2 => 'Yes, disallow login if stored cost is less than domain default',
- );
- $datatable .= '<table width="100%">';
- foreach my $option (@options) {
- my $checked = ' ';
- my $onclick;
- if ($defaults{$item} eq $option) {
- $checked = ' checked="checked"';
- }
- if ($option == 2) {
- $onclick = ' onclick="javascript:warnIntAuth(this);"';
- }
- $datatable .= '<tr><td class="LC_left_item"><span class="LC_nobreak">'.
- '<label><input type="radio" name="'.$item.
- '" value="'.$option.'"'.$checked.$onclick.' />'.
- $optiondesc{$option}.'</label></span></td></tr>';
- }
- $datatable .= '</table>';
+ my $includeempty = 1;
+ $datatable .= &Apache::loncommon::select_datelocale($item,$defaults{$item},undef,$includeempty);
+ } elsif ($item eq 'lang_def') {
+ my $includeempty = 1;
+ $datatable .= &Apache::loncommon::select_language($item,$defaults{$item},$includeempty);
} else {
+ my $size;
+ if ($item eq 'portal_def') {
+ $size = ' size="25"';
+ }
$datatable .= '<input type="text" name="'.$item.'" value="'.
- $defaults{$item}.'" size="3" onblur="javascript:warnIntAuth(this);" />';
+ $defaults{$item}.'"'.$size.' />';
}
$datatable .= '</td></tr>';
$rownum ++;
@@ -6690,35 +7073,7 @@
sub defaults_javascript {
my ($settings) = @_;
- my $intauthcheck = &mt('Warning: disallowing login for an authenticated user if the stored cost is less than the default will require a password reset by/for the user.');
- my $intauthcost = &mt('Warning: bcrypt encryption cost for internal authentication must be an integer.');
- &js_escape(\$intauthcheck);
- &js_escape(\$intauthcost);
- my $intauthjs = <<"ENDSCRIPT";
-
-function warnIntAuth(field) {
- if (field.name == 'intauth_check') {
- if (field.value == '2') {
- alert('$intauthcheck');
- }
- }
- if (field.name == 'intauth_cost') {
- field.value.replace(/\s/g,'');
- if (field.value != '') {
- var regexdigit=/^\\d+\$/;
- if (!regexdigit.test(field.value)) {
- alert('$intauthcost');
- }
- }
- }
- return;
-}
-
-ENDSCRIPT
-
- if (ref($settings) ne 'HASH') {
- return &Apache::lonhtmlcommon::scripttag($intauthjs);
- }
+ return unless (ref($settings) eq 'HASH');
if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) {
my $maxnum = scalar(@{$settings->{'inststatusorder'}});
if ($maxnum eq '') {
@@ -6772,17 +7127,42 @@
return;
}
-$intauthjs
-
// ]]>
</script>
ENDSCRIPT
- } else {
- return &Apache::lonhtmlcommon::scripttag($intauthjs);
}
}
+sub passwords_javascript {
+ my $intauthcheck = &mt('Warning: disallowing login for an authenticated user if the stored cost is less than the default will require a password reset by/for the user.');
+ my $intauthcost = &mt('Warning: bcrypt encryption cost for internal authentication must be an integer.');
+ &js_escape(\$intauthcheck);
+ &js_escape(\$intauthcost);
+ my $intauthjs = <<"ENDSCRIPT";
+
+function warnIntAuth(field) {
+ if (field.name == 'intauth_check') {
+ if (field.value == '2') {
+ alert('$intauthcheck');
+ }
+ }
+ if (field.name == 'intauth_cost') {
+ field.value.replace(/\s/g,'');
+ if (field.value != '') {
+ var regexdigit=/^\\d+\$/;
+ if (!regexdigit.test(field.value)) {
+ alert('$intauthcost');
+ }
+ }
+ }
+ return;
+}
+
+ENDSCRIPT
+ return &Apache::lonhtmlcommon::scripttag($intauthjs);
+}
+
sub coursecategories_javascript {
my ($settings) = @_;
my ($output,$jstext,$cathash);
@@ -7121,7 +7501,7 @@
my $check = ' ';
unless ($role eq 'emailusername') {
if (exists($checks{$fields[$i]})) {
- $check = $checks{$fields[$i]}
+ $check = $checks{$fields[$i]};
} else {
if ($role eq 'st') {
if (ref($settings) ne 'HASH') {
@@ -8219,7 +8599,7 @@
my ($configuserok,%currroles);
if ($uhome eq 'no_host') {
srand( time() ^ ($$ + ($$ << 15)) ); # Seed rand.
- my $configpass = &LONCAPA::Enrollment::create_password();
+ my $configpass = &LONCAPA::Enrollment::create_password($dom);
$configuserok =
&Apache::lonnet::modifyuser($dom,$confname,'','internal',
$configpass,'','','','','',undef,$servadm);
@@ -10140,6 +10520,514 @@
return $resulttext;
}
+sub modify_passwords {
+ my ($r,$dom,$confname,$lastactref,%domconfig) = @_;
+ my ($resulttext,%current,%changes,%newvalues, at oktypes,$errors,
+ $updatedefaults,$updateconf);
+ my $customfn = 'resetpw.html';
+ if (ref($domconfig{'passwords'}) eq 'HASH') {
+ %current = %{$domconfig{'passwords'}};
+ }
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
+ my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
+ if (ref($types) eq 'ARRAY') {
+ @oktypes = @{$types};
+ }
+ push(@oktypes,'default');
+
+ my %titles = &Apache::lonlocal::texthash (
+ intauth_cost => 'Encryption cost for bcrypt (positive integer)',
+ intauth_check => 'Check bcrypt cost if authenticated',
+ intauth_switch => 'Existing crypt-based switched to bcrypt on authentication',
+ permanent => 'Permanent e-mail address',
+ critical => 'Critical notification address',
+ notify => 'Notification address',
+ min => 'Minimum password length',
+ max => 'Maximum password length',
+ chars => 'Required characters',
+ numsaved => 'Number of previous passwords to save',
+ reset => 'Resetting Forgotten Password',
+ intauth => 'Encryption of Stored Passwords (Internal Auth)',
+ rules => 'Rules for LON-CAPA Passwords',
+ crsownerchg => 'Course Owner Changing Student Passwords',
+ username => 'Username',
+ email => 'E-mail address',
+ );
+
+#
+# Retrieve current domain configuration for internal authentication from $domconfig{'defaults'}.
+#
+ my (%curr_defaults,%save_defaults);
+ if (ref($domconfig{'defaults'}) eq 'HASH') {
+ foreach my $key (keys(%{$domconfig{'defaults'}})) {
+ if ($key =~ /^intauth_(cost|check|switch)$/) {
+ $curr_defaults{$key} = $domconfig{'defaults'}{$key};
+ } else {
+ $save_defaults{$key} = $domconfig{'defaults'}{$key};
+ }
+ }
+ }
+ my %staticdefaults = (
+ 'resetlink' => 2,
+ 'resetcase' => \@oktypes,
+ 'resetprelink' => 'both',
+ 'resetemail' => ['critical','notify','permanent'],
+ 'intauth_cost' => 10,
+ 'intauth_check' => 0,
+ 'intauth_switch' => 0,
+ 'min' => 7,
+ );
+ foreach my $type (@oktypes) {
+ $staticdefaults{'resetpostlink'}{$type} = ['email','username'];
+ }
+ my $linklife = $env{'form.passwords_link'};
+ $linklife =~ s/^\s+|\s+$//g;
+ if (($linklife =~ /^\d+(|\.\d*)$/) && ($linklife > 0)) {
+ $newvalues{'resetlink'} = $linklife;
+ if ($current{'resetlink'}) {
+ if ($current{'resetlink'} ne $linklife) {
+ $changes{'reset'} = 1;
+ }
+ } elsif (!exists($domconfig{passwords})) {
+ if ($staticdefaults{'resetlink'} ne $linklife) {
+ $changes{'reset'} = 1;
+ }
+ }
+ } elsif ($current{'resetlink'}) {
+ $changes{'reset'} = 1;
+ }
+ my @casesens;
+ my @posscase = &Apache::loncommon::get_env_multiple('form.passwords_case_sensitive');
+ foreach my $case (sort(@posscase)) {
+ if (grep(/^\Q$case\E$/, at oktypes)) {
+ push(@casesens,$case);
+ }
+ }
+ $newvalues{'resetcase'} = \@casesens;
+ if (ref($current{'resetcase'}) eq 'ARRAY') {
+ my @diffs = &Apache::loncommon::compare_arrays($current{'resetcase'},\@casesens);
+ if (@diffs > 0) {
+ $changes{'reset'} = 1;
+ }
+ } elsif (!exists($domconfig{passwords})) {
+ my @diffs = &Apache::loncommon::compare_arrays($staticdefaults{'resetcase'},\@casesens);
+ if (@diffs > 0) {
+ $changes{'reset'} = 1;
+ }
+ }
+ if ($env{'form.passwords_prelink'} =~ /^(both|either)$/) {
+ $newvalues{'resetprelink'} = $env{'form.passwords_prelink'};
+ if (exists($current{'resetprelink'})) {
+ if ($current{'resetprelink'} ne $newvalues{'resetprelink'}) {
+ $changes{'reset'} = 1;
+ }
+ } elsif (!exists($domconfig{passwords})) {
+ if ($staticdefaults{'resetprelink'} ne $newvalues{'resetprelink'}) {
+ $changes{'reset'} = 1;
+ }
+ }
+ } elsif ($current{'resetprelink'}) {
+ $changes{'reset'} = 1;
+ }
+ foreach my $type (@oktypes) {
+ my @possplink = &Apache::loncommon::get_env_multiple('form.passwords_postlink_'.$type);
+ my @postlink;
+ foreach my $item (sort(@possplink)) {
+ if ($item =~ /^(email|username)$/) {
+ push(@postlink,$item);
+ }
+ }
+ $newvalues{'resetpostlink'}{$type} = \@postlink;
+ unless ($changes{'reset'}) {
+ if (ref($current{'resetpostlink'}) eq 'HASH') {
+ if (ref($current{'resetpostlink'}{$type}) eq 'ARRAY') {
+ my @diffs = &Apache::loncommon::compare_arrays($current{'resetpostlink'}{$type},\@postlink);
+ if (@diffs > 0) {
+ $changes{'reset'} = 1;
+ }
+ } else {
+ $changes{'reset'} = 1;
+ }
+ } elsif (!exists($domconfig{passwords})) {
+ my @diffs = &Apache::loncommon::compare_arrays($staticdefaults{'resetpostlink'}{$type},\@postlink);
+ if (@diffs > 0) {
+ $changes{'reset'} = 1;
+ }
+ }
+ }
+ }
+ my @possemailsrc = &Apache::loncommon::get_env_multiple('form.passwords_emailsrc');
+ my @resetemail;
+ foreach my $item (sort(@possemailsrc)) {
+ if ($item =~ /^(permanent|critical|notify)$/) {
+ push(@resetemail,$item);
+ }
+ }
+ $newvalues{'resetemail'} = \@resetemail;
+ unless ($changes{'reset'}) {
+ if (ref($current{'resetemail'}) eq 'ARRAY') {
+ my @diffs = &Apache::loncommon::compare_arrays($current{'resetemail'},\@resetemail);
+ if (@diffs > 0) {
+ $changes{'reset'} = 1;
+ }
+ } elsif (!exists($domconfig{passwords})) {
+ my @diffs = &Apache::loncommon::compare_arrays($staticdefaults{'resetemail'},\@resetemail);
+ if (@diffs > 0) {
+ $changes{'reset'} = 1;
+ }
+ }
+ }
+ if ($env{'form.passwords_stdtext'} == 0) {
+ $newvalues{'resetremove'} = 1;
+ unless ($current{'resetremove'}) {
+ $changes{'reset'} = 1;
+ }
+ } elsif ($current{'resetremove'}) {
+ $changes{'reset'} = 1;
+ }
+ if ($env{'form.passwords_customfile.filename'} ne '') {
+ my $servadm = $r->dir_config('lonAdmEMail');
+ my $servadm = $r->dir_config('lonAdmEMail');
+ my ($configuserok,$author_ok,$switchserver) =
+ &config_check($dom,$confname,$servadm);
+ my $error;
+ if ($configuserok eq 'ok') {
+ if ($switchserver) {
+ $error = &mt("Upload of file containing domain-specific text is not permitted to this server: [_1]",$switchserver);
+ } else {
+ if ($author_ok eq 'ok') {
+ my ($result,$customurl) =
+ &publishlogo($r,'upload','passwords_customfile',$dom,
+ $confname,'customtext/resetpw','','',$customfn);
+ if ($result eq 'ok') {
+ $newvalues{'resetcustom'} = $customurl;
+ $changes{'reset'} = 1;
+ } else {
+ $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$customfn,$result);
+ }
+ } else {
+ $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3]. Error was: [_4].",$customfn,$confname,$dom,$author_ok);
+ }
+ }
+ } else {
+ $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$customfn,$confname,$dom,$configuserok);
+ }
+ if ($error) {
+ &Apache::lonnet::logthis($error);
+ $errors .= '<li><span class="LC_error">'.$error.'</span></li>';
+ }
+ } elsif ($current{'resetcustom'}) {
+ if ($env{'form.passwords_custom_del'}) {
+ $changes{'reset'} = 1;
+ } else {
+ $newvalues{'resetcustom'} = $current{'resetcustom'};
+ }
+ }
+ $env{'form.intauth_cost'} =~ s/^\s+|\s+$//g;
+ if (($env{'form.intauth_cost'} ne '') && ($env{'form.intauth_cost'} =~ /^\d+$/)) {
+ $save_defaults{'intauth_cost'} = $env{'form.intauth_cost'};
+ if ($save_defaults{'intauth_cost'} ne $curr_defaults{'intauth_cost'}) {
+ $changes{'intauth'} = 1;
+ }
+ } else {
+ $save_defaults{'intauth_cost'} = $curr_defaults{'intauth_cost'};
+ }
+ if ($env{'form.intauth_check'} =~ /^(0|1|2)$/) {
+ $save_defaults{'intauth_check'} = $env{'form.intauth_check'};
+ if ($save_defaults{'intauth_check'} ne $curr_defaults{'intauth_check'}) {
+ $changes{'intauth'} = 1;
+ }
+ } else {
+ $save_defaults{'intauth_check'} = $curr_defaults{'intauth_check'};
+ }
+ if ($env{'form.intauth_switch'} =~ /^(0|1|2)$/) {
+ $save_defaults{'intauth_switch'} = $env{'form.intauth_switch'};
+ if ($save_defaults{'intauth_switch'} ne $curr_defaults{'intauth_switch'}) {
+ $changes{'intauth'} = 1;
+ }
+ } else {
+ $save_defaults{'intauth_check'} = $curr_defaults{'intauth_check'};
+ }
+ foreach my $item ('cost','check','switch') {
+ if ($save_defaults{'intauth_'.$item} ne $domdefaults{'intauth_'.$item}) {
+ $domdefaults{'intauth_'.$item} = $save_defaults{'intauth_'.$item};
+ $updatedefaults = 1;
+ }
+ }
+ foreach my $rule ('min','max','numsaved') {
+ $env{'form.passwords_'.$rule} =~ s/^\s+|\s+$//g;
+ if ($env{'form.passwords_'.$rule} =~ /^\d+$/) {
+ $newvalues{$rule} = $env{'form.passwords_'.$rule};
+ if (exists($current{$rule})) {
+ if ($newvalues{$rule} ne $current{$rule}) {
+ $changes{'rules'} = 1;
+ }
+ } elsif ($rule eq 'min') {
+ if ($staticdefaults{$rule} ne $newvalues{$rule}) {
+ $changes{'rules'} = 1;
+ }
+ }
+ } elsif (exists($current{$rule})) {
+ $changes{'rules'} = 1;
+ }
+ }
+ my @posschars = &Apache::loncommon::get_env_multiple('form.passwords_chars');
+ my @chars;
+ foreach my $item (sort(@posschars)) {
+ if ($item =~ /^(uc|lc|num|spec)$/) {
+ push(@chars,$item);
+ }
+ }
+ $newvalues{'chars'} = \@chars;
+ unless ($changes{'rules'}) {
+ if (ref($current{'chars'}) eq 'ARRAY') {
+ my @diffs = &Apache::loncommon::compare_arrays($current{'chars'},\@chars);
+ if (@diffs > 0) {
+ $changes{'rules'} = 1;
+ }
+ } else {
+ if (@chars > 0) {
+ $changes{'rules'} = 1;
+ }
+ }
+ }
+ my %crsownerchg = (
+ by => [],
+ for => [],
+ );
+ foreach my $item ('by','for') {
+ my @posstypes = &Apache::loncommon::get_env_multiple('form.passwords_crsowner_'.$item);
+ foreach my $type (sort(@posstypes)) {
+ if (grep(/^\Q$type\E$/, at oktypes)) {
+ push(@{$crsownerchg{$item}},$type);
+ }
+ }
+ }
+ $newvalues{'crsownerchg'} = \%crsownerchg;
+ if (ref($current{'crsownerchg'}) eq 'HASH') {
+ foreach my $item ('by','for') {
+ if (ref($current{'crsownerchg'}{$item}) eq 'ARRAY') {
+ my @diffs = &Apache::loncommon::compare_arrays($current{'crsownerchg'}{$item},$crsownerchg{$item});
+ if (@diffs > 0) {
+ $changes{'crsownerchg'} = 1;
+ last;
+ }
+ }
+ }
+ } elsif (!exists($domconfig{passwords})) {
+ foreach my $item ('by','for') {
+ if (@{$crsownerchg{$item}} > 0) {
+ $changes{'crsownerchg'} = 1;
+ last;
+ }
+ }
+ }
+
+ my %confighash = (
+ defaults => \%save_defaults,
+ passwords => \%newvalues,
+ );
+ &process_captcha('passwords',\%changes,$confighash{'passwords'},$domconfig{'passwords'});
+
+ my $putresult = &Apache::lonnet::put_dom('configuration',\%confighash,$dom);
+ if ($putresult eq 'ok') {
+ if (keys(%changes) > 0) {
+ $resulttext = &mt('Changes made: ').'<ul>';
+ foreach my $key ('reset','intauth','rules','crsownerchg') {
+ if ($changes{$key}) {
+ unless ($key eq 'intauth') {
+ $updateconf = 1;
+ }
+ $resulttext .= '<li>'.$titles{$key}.':<ul>';
+ if ($key eq 'reset') {
+ if ($confighash{'passwords'}{'captcha'} eq 'original') {
+ $resulttext .= '<li>'.&mt('CAPTCHA validation set to use: original CAPTCHA').'</li>';
+ } elsif ($confighash{'passwords'}{'captcha'} eq 'recaptcha') {
+ $resulttext .= '<li>'.&mt('CAPTCHA validation set to use: reCAPTCHA').' '.
+ &mt('version: [_1]',$confighash{'passwords'}{'recaptchaversion'}).'<br />'.
+ &mt('Public key: [_1]',$confighash{'passwords'}{'recaptchapub'}).'</br>'.
+ &mt('Private key: [_1]',$confighash{'passwords'}{'recaptchapriv'}).'</li>';
+ } else {
+ $resulttext .= '<li>'.&mt('No CAPTCHA validation').'</li>';
+ }
+ if ($confighash{'passwords'}{'resetlink'}) {
+ $resulttext .= '<li>'.&mt('Reset link expiration set to [quant,_1,hour]',$confighash{'passwords'}{'resetlink'}).'</li>';
+ } else {
+ $resulttext .= '<li>'.&mt('No reset link expiration set.').' '.
+ &mt('Will default to 2 hours').'</li>';
+ }
+ if (ref($confighash{'passwords'}{'resetcase'}) eq 'ARRAY') {
+ if (@{$confighash{'passwords'}{'resetcase'}} == 0) {
+ $resulttext .= '<li>'.&mt('User input for username and/or e-mail address not case sensitive for "Forgot Password" web form').'</li>';
+ } else {
+ my $casesens;
+ foreach my $type (@{$confighash{'passwords'}{'resetcase'}}) {
+ if ($type eq 'default') {
+ $casesens .= $othertitle.', ';
+ } elsif ($usertypes->{$type} ne '') {
+ $casesens .= $usertypes->{$type}.', ';
+ }
+ }
+ $casesens =~ s/\Q, \E$//;
+ $resulttext .= '<li>'.&mt('"Forgot Password" web form input for username and/or e-mail address is case-sensitive for: [_1]',$casesens).'</li>';
+ }
+ } else {
+ $resulttext .= '<li>'.&mt('Case-sensitivity not set for "Forgot Password" web form').' '.&mt('Will default to case-sensitive for username and/or e-mail address for all').'</li>';
+ }
+ if ($confighash{'passwords'}{'resetprelink'} eq 'either') {
+ $resulttext .= '<li>'.&mt('Users can enter either a username or an e-mail address in "Forgot Password" web form').'</li>';
+ } else {
+ $resulttext .= '<li>'.&mt('Users can enter both a username and an e-mail address in "Forgot Password" web form').'</li>';
+ }
+ if (ref($confighash{'passwords'}{'resetpostlink'}) eq 'HASH') {
+ my $output;
+ if (ref($types) eq 'ARRAY') {
+ foreach my $type (@{$types}) {
+ if (ref($confighash{'passwords'}{'resetpostlink'}{$type}) eq 'ARRAY') {
+ if (@{$confighash{'passwords'}{'resetpostlink'}{$type}} == 0) {
+ $output .= $usertypes->{$type}.' -- '.&mt('none');
+ } else {
+ $output .= $usertypes->{$type}.' -- '.
+ join(', ',map { $titles{$_}; } (@{$confighash{'passwords'}{'resetpostlink'}{$type}})).'; ';
+ }
+ }
+ }
+ }
+ if (ref($confighash{'passwords'}{'resetpostlink'}{'default'}) eq 'ARRAY') {
+ if (@{$confighash{'passwords'}{'resetpostlink'}{'default'}} == 0) {
+ $output .= $othertitle.' -- '.&mt('none');
+ } else {
+ $output .= $othertitle.' -- '.
+ join(', ',map { $titles{$_}; } (@{$confighash{'passwords'}{'resetpostlink'}{'default'}}));
+ }
+ }
+ if ($output) {
+ $resulttext .= '<li>'.&mt('Information required for new password form (by user type) set to: [_1]',$output).'</li>';
+ } else {
+ $resulttext .= '<li>'.&mt('Information required for new password form not set.').' '.&mt('Will default to requiring both the username and an e-mail address').'</li>';
+ }
+ } else {
+ $resulttext .= '<li>'.&mt('Information required for new password form not set.').' '.&mt('Will default to requiring both the username and an e-mail address').'</li>';
+ }
+ if (ref($confighash{'passwords'}{'resetemail'}) eq 'ARRAY') {
+ if (@{$confighash{'passwords'}{'resetemail'}} > 0) {
+ $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$confighash{'passwords'}{'resetemail'}})).'</li>';
+ } else {
+ $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA used for verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).'</li>';
+ }
+ } else {
+ $resulttext .= '<li>'.&mt('E-mail address(es) in LON-CAPA usedfor verification will include: [_1]',join(', ',map { $titles{$_}; } @{$staticdefaults{'resetemail'}})).'</li>';
+ }
+ if ($confighash{'passwords'}{'resetremove'}) {
+ $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" web form not shown').'</li>';
+ } else {
+ $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" web form is shown').'</li>';
+ }
+ if ($confighash{'passwords'}{'resetcustom'}) {
+ my $customlink = &Apache::loncommon::modal_link($confighash{'passwords'}{'resetcustom'},
+ $titles{custom},600,500);
+ $resulttext .= '<li>'.&mt('Preamble to "Forgot Password" form includes [_1]',$customlink).'</li>';
+ } else {
+ $resulttext .= '<li>'.&mt('No custom text included in preamble to "Forgot Password" form').'</li>';
+ }
+ } elsif ($key eq 'intauth') {
+ foreach my $item ('cost','switch','check') {
+ my $value = $save_defaults{$key.'_'.$item};
+ if ($item eq 'switch') {
+ my %optiondesc = &Apache::lonlocal::texthash (
+ 0 => 'No',
+ 1 => 'Yes',
+ 2 => 'Yes, and copy existing passwd file to passwd.bak file',
+ );
+ if ($value =~ /^(0|1|2)$/) {
+ $value = $optiondesc{$value};
+ } else {
+ $value = &mt('none -- defaults to No');
+ }
+ } elsif ($item eq 'check') {
+ my %optiondesc = &Apache::lonlocal::texthash (
+ 0 => 'No',
+ 1 => 'Yes, allow login then update passwd file using default cost (if higher)',
+ 2 => 'Yes, disallow login if stored cost is less than domain default',
+ );
+ if ($value =~ /^(0|1|2)$/) {
+ $value = $optiondesc{$value};
+ } else {
+ $value = &mt('none -- defaults to No');
+ }
+ }
+ $resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$titles{$key.'_'.$item},$value).'</li>';
+ }
+ } elsif ($key eq 'rules') {
+ foreach my $rule ('min','max','numsaved') {
+ if ($confighash{'passwords'}{$rule} eq '') {
+ if ($rule eq 'min') {
+ $resulttext .= '<li>'.&mt('[_1] not set.',$titles{$rule});
+ ' '.&mt('Default of 7 will be used').'</li>';
+ } else {
+ $resulttext .= '<li>'.&mt('[_1] set to none',$titles{$rule}).'</li>';
+ }
+ } else {
+ $resulttext .= '<li>'.&mt('[_1] set to [_2]',$titles{$rule},$confighash{'passwords'}{$rule}).'</li>';
+ }
+ }
+ } elsif ($key eq 'crsownerchg') {
+ if (ref($confighash{'passwords'}{'crsownerchg'}) eq 'HASH') {
+ if ((@{$confighash{'passwords'}{'crsownerchg'}{'by'}} == 0) ||
+ (@{$confighash{'passwords'}{'crsownerchg'}{'for'}} == 0)) {
+ $resulttext .= '<li>'.&mt('Course owner may not change student passwords.').'</li>';
+ } else {
+ my %crsownerstr;
+ foreach my $item ('by','for') {
+ if (ref($confighash{'passwords'}{'crsownerchg'}{$item}) eq 'ARRAY') {
+ foreach my $type (@{$confighash{'passwords'}{'crsownerchg'}{$item}}) {
+ if ($type eq 'default') {
+ $crsownerstr{$item} .= $othertitle.', ';
+ } elsif ($usertypes->{$type} ne '') {
+ $crsownerstr{$item} .= $usertypes->{$type}.', ';
+ }
+ }
+ $crsownerstr{$item} =~ s/\Q, \E$//;
+ }
+ }
+ $resulttext .= '<li>'.&mt('Course owner (with status: [_1]) may change passwords for students (with status: [_2]).',
+ $crsownerstr{'by'},$crsownerstr{'for'}).'</li>';
+ }
+ } else {
+ $resulttext .= '<li>'.&mt('Course owner may not change student passwords.').'</li>';
+ }
+ }
+ $resulttext .= '</ul></li>';
+ }
+ }
+ $resulttext .= '</ul>';
+ } else {
+ $resulttext = &mt('No changes made to password settings');
+ }
+ my $cachetime = 24*60*60;
+ if ($updatedefaults) {
+ &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
+ if (ref($lastactref) eq 'HASH') {
+ $lastactref->{'domdefaults'} = 1;
+ }
+ }
+ if ($updateconf) {
+ &Apache::lonnet::do_cache_new('passwdconf',$dom,$confighash{'passwords'},$cachetime);
+ if (ref($lastactref) eq 'HASH') {
+ $lastactref->{'passwdconf'} = 1;
+ }
+ }
+ } else {
+ $resulttext = '<span class="LC_error">'.
+ &mt('An error occurred: [_1]',$putresult).'</span>';
+ }
+ if ($errors) {
+ $resulttext .= '<p>'.&mt('The following errors occurred: ').'<ul>'.
+ $errors.'</ul></p>';
+ }
+ return $resulttext;
+}
+
sub modify_usercreation {
my ($dom,%domconfig) = @_;
my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate,%save_usercreate);
@@ -11406,7 +12294,7 @@
my ($resulttext,$mailmsgtxt,%newvalues,%changes, at errors);
my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def',
- 'portal_def','intauth_cost','intauth_check','intauth_switch');
+ 'portal_def');
my @authtypes = ('internal','krb4','krb5','localauth');
foreach my $item (@items) {
$newvalues{$item} = $env{'form.'.$item};
@@ -11448,24 +12336,6 @@
push(@errors,$item);
}
}
- } elsif ($item eq 'intauth_cost') {
- if ($newvalues{$item} ne '') {
- if ($newvalues{$item} =~ /\D/) {
- push(@errors,$item);
- }
- }
- } elsif ($item eq 'intauth_check') {
- if ($newvalues{$item} ne '') {
- unless ($newvalues{$item} =~ /^(0|1|2)$/) {
- push(@errors,$item);
- }
- }
- } elsif ($item eq 'intauth_switch') {
- if ($newvalues{$item} ne '') {
- unless ($newvalues{$item} =~ /^(0|1|2)$/) {
- push(@errors,$item);
- }
- }
}
if (grep(/^\Q$item\E$/, at errors)) {
$newvalues{$item} = $domdefaults{$item};
@@ -11474,6 +12344,18 @@
}
$domdefaults{$item} = $newvalues{$item};
}
+ my %staticdefaults = (
+ 'intauth_cost' => 10,
+ 'intauth_check' => 0,
+ 'intauth_switch' => 0,
+ );
+ foreach my $item ('intauth_cost','intauth_check','intauth_switch') {
+ if (exists($domdefaults{$item})) {
+ $newvalues{$item} = $domdefaults{$item};
+ } else {
+ $newvalues{$item} = $staticdefaults{$item};
+ }
+ }
my %defaults_hash = (
defaults => \%newvalues,
);
@@ -11603,28 +12485,6 @@
localauth => 'loc',
);
$value = $authnames{$shortauth{$value}};
- } elsif ($item eq 'intauth_switch') {
- my %optiondesc = &Apache::lonlocal::texthash (
- 0 => 'No',
- 1 => 'Yes',
- 2 => 'Yes, and copy existing passwd file to passwd.bak file',
- );
- if ($value =~ /^(0|1|2)$/) {
- $value = $optiondesc{$value};
- } else {
- $value = &mt('none -- defaults to No');
- }
- } elsif ($item eq 'intauth_check') {
- my %optiondesc = &Apache::lonlocal::texthash (
- 0 => 'No',
- 1 => 'Yes, allow login then update passwd file using default cost (if higher)',
- 2 => 'Yes, disallow login if stored cost is less than domain default',
- );
- if ($value =~ /^(0|1|2)$/) {
- $value = $optiondesc{$value};
- } else {
- $value = &mt('none -- defaults to No');
- }
}
$resulttext .= '<li>'.&mt('[_1] set to "[_2]"',$title->{$item},$value).'</li>';
$mailmsgtext .= "$title->{$item} set to $value\n";
@@ -14533,7 +15393,8 @@
my %servers = &Apache::lonnet::internet_dom_servers($dom);
my %thismachine;
map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids();
- my @posscached = ('domainconfig','domdefaults','usersessions','directorysrch','cats');
+ my @posscached = ('domainconfig','domdefaults','usersessions',
+ 'directorysrch','passwdconf','cats');
if (keys(%servers)) {
foreach my $server (keys(%servers)) {
next if ($thismachine{$server});
More information about the LON-CAPA-cvs
mailing list